Instance count violation in an Android Java app

2019-08-11 00:12发布

问题:

I am working on an Android application. In abstract, this application has an UI in order to interact with user and it also interacts with a remote service. The remote service adds a notification to Android launcher bar and this notification allows to redisplay the UI. The app and the service are in same package. The code of service notification function:

private void showNotification (String contentText) {
    Intent intent = new Intent (this, my_app.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
    PendingIntent pendingIntent = PendingIntent.getActivity(
            this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    mNotification = new Notification.Builder(this)
    .setContentIntent(pendingIntent)
    .setSmallIcon(ICON)
    .setWhen(System.currentTimeMillis())
    .setContentTitle(CONTENT_TITLE)
    .setContentText(contentText)
    .setAutoCancel(false)
    .setOngoing(true)
    .build();
    mNotificationManager.notify(NOTIFICATION_ID, mNotification);
}

Note: it is current version of method... previously I also tried the following FLAGS

   intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
   intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
   intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);

The manifest of application contains the following configuration:

    <application
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:allowBackup="true"
    android:launchMode="singleTop"
    android:uiOptions="splitActionBarWhenNarrow"
    android:allowTaskReparenting="true">...</application>

Note: I tried also other proprieties but these do not expected impact...

When the application is started but it is no more displayed, it is possible to redisplay its using notification of launcher bar or using the application entry in "Applications list" but when I execute the following scenario, the UI is displayed twice:

  1. start the application from list
  2. tape on home button
  3. (re)display the application using notification ==> UI is correctly redisplayed
  4. tape on home button
  5. (re)display the application using "applications list" ==> a new instance of UI is displayed

The logs of scenario:

#start from applications list
I/ActivityManager(  504): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.domain.my_app/.My_App bnds=[40,833][200,1033]} from pid 871
I/my_app( 6915): onCreate
I/my_app::Service( 6930): onCreate
I/my_app( 6915): onResume
#tape the home button
I/my_app( 6915): onPause
#restart from notification in launcher bar
I/ActivityManager(  504): START u0 {flg=0x34400000 cmp=com.domain.my_app/.My_App bnds=[0,102][720,230]} from pid -1
I/my_app( 6915): onResume
#tape the home button
I/my_app( 6915): onPause
#start from application list
I/ActivityManager(  504): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.domain.my_app/.My_App bnds=[40,833][200,1033]} from pid 871
I/my_app( 6915): onCreate
I/my_app( 6915): onResume
#tape the home button
I/my_app( 6915): onPause
#restart from notification in launcher bar
I/ActivityManager(  504): START u0 {flg=0x34400000 cmp=com.domain.my_app/.My_App bnds=[0,102][720,230]} from pid -1
I/PSI Recorder( 6915): onResume
#it is necessary to use two times the my_app quit button in order to exit the application, and then in log, I noted the following error
E/StrictMode( 6915): class com.domain.my_app; instances=2; limit=1
E/StrictMode( 6915): android.os.StrictMode$InstanceCountViolation: class com.domain.my_app; instances=2; limit=1

I read a lot of things, tips, etc. about application, remote service and notification but I am unable to understand why the UI is recreated when the application is restarted from list, and only if previously, it was redisplayed from notification... Note: if the FLAG_ACTIVITY_NEW_TASK flag is not added to intent, the following warning is logged, and it does not change the observed behaviour...

W/ActivityManager(  504): startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { flg=0x24400000 cmp=com.domain.my_app/.My_App bnds=[0,102][720,230] }

I will appreciate any help.

Thank you. Best regards,

EDIT: It is my fault, instead of "application" Manifest field, the android:launchMode="singleTop" attribute should be in "activity" element :/

I moved and it works

    <application
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:allowBackup="true">
    <activity
        android:name=".my_app"
        android:configChanges="orientation"
        android:label="@string/app_name"
        android:launchMode="singleTop"

回答1:

I think the source of the problem is your combination of intent flags. To help you debug this, try to implement the onNewIntent() method in your activity, and log every intent it receives, with something like this:

protected void onNewIntent(Intent intent){
    super.onNewIntent(intent);
    Log.i("my_app", "New intent with flags "+intent.getFlags());
}

This should allow you to see what flags are causing the second call to onCreate() in your logs.

As for the StrictMode instance count violation, I don't think it is worth investigating as explained here.

EDIT Try to use only the flag Intent.FLAG_ACTIVITY_NEW_TASK, e.g., remove the other three flags. Also, keep the android:launchMode to singleTop.