Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ensure Android app runs in a single process

We've recently started running into crashes in our Android app due to the app being open in multiple processes. Several different errors point towards that. For instance this error:

com.google.firebase.database.DatabaseException: Failed to gain exclusive lock to Firebase Database's offline persistence. This generally means you are using Firebase Database from multiple processes in your app. Keep in mind that multi-process Android apps execute the code in your Application class in all processes, so you may need to avoid initializing FirebaseDatabase in your Application class. If you are intentionally using Firebase Database from multiple processes, you can only enable offline persistence (i.e. call setPersistenceEnabled(true)) in one of them.

We are also seeing similar errors from SQLite and H2. This is a new issue and we have not explicitly allowed multiple processes to run. Nothing in our AndroidManifest.xml specifies a custom android:process attribute.

I suspect that some third party library is causing this. How do I identify the root cause of the multiple processes and how do I prevent it?

Another of our apps is connecting to this app via a ContentProvider. At first I thought that it having android:multiprocess="true" was the culprit but changing it to "false" did not help. I still suspect that the other app is somehow triggering the creation of a new process. This is how to the ContentProvider is defined:

  <provider
        android:name=".DegooContentProvider"
        android:authorities="${applicationId}.DegooContentProvider"
        android:exported="true"
        android:protectionLevel="signature"
        android:multiprocess="false">
    </provider>
like image 561
Yrlec Avatar asked Aug 07 '18 19:08

Yrlec


1 Answers

You can check in your applicaition class if there is foreign process. Here is an example:

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        if (!isMainProcess()) {
            // Do not call thread unsafe logic. Just return
            return;
        }
        // Thread unsafe logic.
        ...
    }

    private boolean isMainProcess() {
        int pid = android.os.Process.myPid();
        ActivityManager manager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
            String currentProcName = processInfo.processName;
            if (processInfo.pid == pid) {
                if (TextUtils.equals(currentProcName, BuildConfig.APPLICATION_ID)) {
                    return true;
                }
            }
        }
        return false;
    }
}
like image 135
Link182 Avatar answered Nov 08 '22 14:11

Link182