Search code examples
androidandroid-servicekillkill-processandroid-thread

How to stop all services, threads, unload libraries on android app kill


I want to give user ability to choose language of application UI and content in it with different languages. I want to reload new fresh localized data from server with new language which user select.

To do application recreation with new language settings, I am planing to:

  1. Save selected language to shared preferances.
  2. Call stopService() on two of my IntentServices.
  3. Completely kill currently running application with the answer from here: How do I programmatically "restart" an Android app?
  4. On MyApplication start, firstly check shared preferances and if they contain new user language - then clear almost all records in SharedPreferances, Realm database.
  5. start all services again and now they will go to the server and fetch new data with new language preferances.

What I want to understand about application killing is next:

  1. At the moment of killing my currenltly running application - will all of my running Services, Threads, ThreadExecutors, CompositeDisposable, WorkEnqueuer, Runnables, AsyncTasks, Handlers and all that thread and (working in background) stuff will be stopped at the same moment as System.exit(0) will be called? Does it mean when I am killing my app it will also completely and immediatelly stop the work of all thread related stuff?

  2. Will all libraries that I use will be unloaded from memory and then, at second lauch be correctly re-initialized? Such libraries like: RealmDB, Firebase, Dagger, RxJava2, Retrofit? The list of libraries and services I user in my project is listed below.

  3. Will all static variables will be reinitialized?

Thanks.

Here is manifest and libraries I use:

<application
        android:allowBackup="false"
        android:hardwareAccelerated="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:name=".application.MyApplication"
        android:theme="@style/AppTheme"
        tools:replace="android:allowBackup">

    <activity
            android:name=".view.activity.SplashActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:launchMode="singleTask"
            android:theme="@style/Theme.AppCompat.Translucent">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    <service android:name=".services.MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>

        <service android:name=".services.MyFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
        </service>

    <receiver android:name="com.appsflyer.MultipleInstallBroadcastReceiver" android:exported="true">
            <intent-filter>
                <action android:name="com.android.vending.INSTALL_REFERRER" />
            </intent-filter>
        </receiver>

    <receiver android:name="io.branch.referral.InstallListener" android:exported="true">
            <intent-filter>
                <action android:name="com.android.vending.INSTALL_REFERRER" />
            </intent-filter>
        </receiver>

        <receiver
            android:name="com.google.android.gms.analytics.AnalyticsReceiver"
            android:enabled="true">
            <intent-filter>
                <action android:name="com.google.android.gms.analytics.ANALYTICS_DISPATCH" />
            </intent-filter>
        </receiver>


    <service
            android:name="com.google.android.gms.analytics.AnalyticsService"
            android:enabled="true"
            android:exported="false" />

        <receiver
            android:name="com.google.android.gms.measurement.AppMeasurementReceiver"
            android:enabled="true"
            android:exported="false"/>

        <receiver
            android:name="com.google.android.gms.measurement.AppMeasurementInstallReferrerReceiver"
            android:enabled="true"
            android:permission="android.permission.INSTALL_PACKAGES">
            <intent-filter>
                <action android:name="com.android.vending.INSTALL_REFERRER" />
            </intent-filter>
        </receiver>

    <service
            android:name="com.google.android.gms.measurement.AppMeasurementService"
            android:enabled="true"
            android:exported="false" />

    <service
            android:name=".services.MyIntentService"
            android:enabled="true"
            android:exported="false" />
        <service
            android:name=".services.MyJobIntentService"
            android:exported="false"
            android:permission="android.permission.BIND_JOB_SERVICE" />

</application>

Libraries:

com.google.dagger:dagger
com.jakewharton:butterknife
io.reactivex.rxjava2:rxjava
com.github.bumptech.glide:glide
com.google.code.gson:gson
com.squareup.retrofit2:retrofit
com.facebook.android:facebook-android-sdk
com.google.android.gms:play-services-auth
com.google.firebase:firebase-core
io.realm:realm-gradle-plugin

Solution

  • If you call system.exit(), the OS process hosting your application will die. This will be seen as an "application crash" and might show a dialog indicating that to the user. This is not a user-friendly way to shutdown an application and is not the usual way to do this on Android.

    In any case, all your code will stop running (all threads), all libraries will be unloaded, all static variables will be cleared as the OS process will die and it will all go away.