Ahmed
Ahmed

Reputation: 656

Multiple Instances of Activity

We have already the check of CATEGORY_MAIN and !isTaskRoot() but even then 2 instances of activity are launched.

SplashActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Log.i("OnCreate method.");

    if(checkIfActivityIsBroughtToFront() || checkIfActivityIsRootTask()) {
        return; // Found that if we finish and don't return then it will run the code below, hence start the recovery task.
    }

    Log.i("Checking if Recovery is required ...");
    new RecoveryTask(SplashActivity.this, this).execute();
}

private boolean checkIfActivityIsBroughtToFront() {
    if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
        // Activity was brought to front and not created,
        // Thus finishing this will get us to the last viewed activity
        Log.i("Detecting a brought to front, no need for recovery.");
        finish();

        return true;
    }

    return false;
}

private boolean checkIfActivityIsRootTask() {
    if (!isTaskRoot()) {
        final Intent intent = getIntent();
        final String intentAction = intent.getAction();
        if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
            Log.i("Main Activity is not the root. " + "Finishing Main Activity instead of launching.");
            finish();

            return true;
        }
    }

    return false;
}

Logs

2015-10-22 13:42:25.581 +0300 SplashActivity INFO[main] - OnCreate method.
2015-10-22 13:42:25.587 +0300 SplashActivity INFO[main] - Checking if Recovery is required ...
2015-10-22 13:42:25.637 +0300 SplashActivity INFO[main] - OnCreate method.
2015-10-22 13:42:25.638 +0300 SplashActivity INFO[main] - Checking if Recovery is required ...
2015-10-22 13:42:25.828 +0300 GeoFenceManager INFO[pool-5-thread-1] - Removing geofences ...
2015-10-22 13:42:25.872 +0300 GeoFenceManager INFO[pool-5-thread-2] - Removing geofences ...

Manifest

<?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="x.y.z"
    android:installLocation="internalOnly" >
<application
        android:name=".global.GlobalInstance"
        android:allowBackup="true"
        android:allowClearUserData="true"
        android:hardwareAccelerated="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:persistent="true" >

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

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

        <receiver
            android:name=".receiver.BootUpReceiver"
            android:enabled="true"
            android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>

UPDATE: This is happening after restart, the BOOT_COMPLETED listener is following

public class BootUpReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Intent i = new Intent(context, SplashActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(i);
    }
}

Any idea how this can be prevented?

Upvotes: 0

Views: 2280

Answers (3)

Steven Mark Ford
Steven Mark Ford

Reputation: 3432

Add android:launchMode="SingleTask" to the splash activity element in the xml. And then on leaving the activity i.e. navigating away from the splash call finish(). The reason you should use this pattern as opposed to "SingleInstance" is that the user can never navigate back to the splash with the back-key (as this is not normal behavior).

Upvotes: 2

Henry
Henry

Reputation: 17841

You said:

We have already the check of CATEGORY_MAIN and !isTaskRoot()

But both the check failed. In your logs that you attached, when both instances are created, neither Detecting a brought to front, no need for recovery. nor Main Activity is not the root. " + "Finishing Main Activity instead of launching. is printed in the logs. This means that in both the methods the if part is never encountered and hence finish() never gets executed. Both the methods returned false.

Also, just because you call finish() and return in onCreate(), it doesn't mean that onStart() or onResume() won't be called.

Why does this happen? Launcher activity will never be called twice (considering that you don't internally start the activity). Probably a bug in the some SDK that the user has.

POSSIBLE FIX: You could try setting android:launchMode="singleTop" in your manifest for the SplashActivity. This will make sure only one instance is maintained.

Upvotes: 0

tiny sunlight
tiny sunlight

Reputation: 6251

   private boolean checkIfActivityIsRootTask() { 
    if (!isTaskRoot()) {
    final Intent intent = getIntent();
    final String intentAction = intent.getAction();
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
          Log.i("Main Activity is not the root. " + "Finishing Main Activity   instead of launching.");
        finish();

        return true; 
      } 
   } 

return false; 
} ?

if this activity is roottask,it return false; what's RecoveryTask for?

Upvotes: 0

Related Questions