android_sdk icon indicating copy to clipboard operation
android_sdk copied to clipboard

Event tracking in a multiprocess app

Open mhelder opened this issue 5 years ago • 5 comments

I'm working on integrating the Adjust SDK in a multiprocess app. It's basically a radio app that runs a service in a separate (private) process. Somewhat like this:

<service
    android:name="com.example.RadioService"
    android:foregroundServiceType="mediaPlayback"
    android:process=":radio"
    android:stopWithTask="true">
    <intent-filter>
        <action android:name="android.media.browse.MediaBrowserService" />
    </intent-filter>
</service>

Throughout the app, several events are being triggered. These all show up fine when I run the network traffic through a proxy. However, the same cannot be said for events triggered from the RadioService. To me it looks like events from the app's 'main' process work fine, but not the radio process.

I haven't really done a deep-dive yet, but did track the call stack down to ActivityHandler.trackEventI. I also checked that this method doesn't return on any of the initial if statements, but that's as far as I've looked for now.

Before I go any further, I was wondering if there are any known limitations around using the Adjust SDK in a multiprocess app? I couldn't find anything in the docs related to this. Apologies if I overlooked any other sources of information.

mhelder avatar Mar 09 '20 16:03 mhelder

Hi @mhelder

And thanks for detailed explanation. Yes, this is limitation. Different processes in Android app are getting their own instance of Dalvik VM causing memory space between them not to be shared. Our SDK, once initialised, exists as singleton instance, but within memory space of the process you actually initialised it in. Which means that if you did Adjust.onCreate/Adjust.onResume sequence to initialise and start SDK in one process and are trying just to perform Adjust.trackEvent in another process, it just won't work since SDK instance isn't initialised and started in process where you're trying to perform event tracking.

In case you have some inter process communication inside of your app up and running, my advice would be to ping your process in which SDK has been initialised and started from these other processes and from there perform any action on Adjust SDK you need.

In case you have any further questions, feel free to ping.

Cheers

uerceg avatar Mar 09 '20 23:03 uerceg

Hi @uerceg,

Thanks for the prompt reply!

Our SDK, once initialised, exists as singleton instance, but within memory space of the process you actually initialised it in. (...) it just won't work since SDK instance isn't initialised and started in process where you're trying to perform event tracking.

Well, that's the thing: the SDK is initialised in both processes. As a result, at runtime each process will have its own singleton instance. As I mentioned before, I did already confirm that ActivityHandler.trackEventI is invoked and that it doesn't return from any of the initial if statements.

Anyways, I decided to dig a little deeper and noticed this at the bottom of trackEventI:

// if it is in the background and it can send, start the background timer
if (adjustConfig.sendInBackground && internalState.isInBackground()) {
    startBackgroundTimerI();
}
writeActivityStateI();

This made me realise that the process running the RadioService will always be considered to be in the background, because it has no UI (well, except for a notification) and no activities that will ever be resumed (so no calls to Adjust.onResume()). Enabling background tracking (per documentation) for the :radio process only, resulted in events from the service to also immediately be tracked.

Upon further investigation, even without background tracking enabled, it looks like events are still persisted to disk (into a file called AdjustIoPackageQueue). It also seems like these events aren't picked up and sent until next app start (triggered from sendFirstPackage()) - if you're lucky...

... because there are now two instances of the SDK reading and writing to the same files. As far as I could tell, there is no form of locking in place to deal with this, meaning the r/w's from the two instances will interfere with each other. So events/stats will be lost along the way and files may end up getting corrupted and flushed altogether.

Long story short, I'll probably go for an IPC solution for now so that the Adjust SDK is only initialised in the app's 'main' process and all event tracking is happening in one place (& process of course).

Thanks for the help 👍

mhelder avatar Mar 10 '20 09:03 mhelder

@mhelder Ah, okay, now I see the setup. So you do have it instantiated in both processes. Let us double check this and will reply to you once we run the tests in setup you're having.

uerceg avatar Mar 10 '20 10:03 uerceg

Multi process this device app

rajib-coder avatar Mar 02 '21 10:03 rajib-coder

[http//www.uber navigation.com](uber

rajib-coder avatar Mar 02 '21 10:03 rajib-coder

I just wanted to follow up on this one to conclude that for the time being, this setup is something which SDK v4 is not really capable to gracefully handle. In our upcoming SDK v5 release in 2024, we tried to address the issue with multiple instances and as of that version on, one will be able to have multiple SDK instances running in parallel (in same or different process(es), doesn't matter) which will be able to write to their own storage space. I think that multi-process apps still remain a bit of a challenge in some cases and we'll try to see if we can make v5 handle those scenarios in a more convenient ways. Thank you one more time for all the research / comments / advices. We'll keep the reference to this ticket in our v5 backlog and keep you posted on any progress about this topic.

In the meantime, I'm gonna close this ticket, but feel free to comment / ping in here if you have any further questions.

Cheers

uerceg avatar Dec 14 '23 09:12 uerceg