Android does not reuse main activity and starts multiple instances ( behavior only after using PendingIntent )

余生长醉 提交于 2020-02-05 03:51:09

问题


I have an application with only one activity.In the onCreate I am showing a notification, on whose click I show my activity, reusing it if necessary ( or so I thought ) The code is:

package com.example.multiplestartupifusingpendingintent;

import android.app.Activity;
import android.app.Notification;
import android.app.Notification.Builder;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {

    public static final String TAG = "hexor";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.d(TAG,
                "onCreate " + getClass().getSimpleName()
                        + Integer.toHexString(hashCode()));

        NotificationManager notifMgr = (NotificationManager) getSystemService(Service.NOTIFICATION_SERVICE);
        showReuseNotification(notifMgr);
    }

    private void showReuseNotification(NotificationManager notifMgr) {
        Intent reuseIntent = new Intent(this, MainActivity.class);
        reuseIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                | Intent.FLAG_ACTIVITY_SINGLE_TOP);

        PendingIntent reusePendingIntent = PendingIntent.getActivity(this, 2,
                reuseIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        Notification.Builder builder = new Builder(this)
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentIntent(reusePendingIntent)
                .setContentTitle("Resue from memory");

        notifMgr.notify(2, builder.build());
    }

    @Override
    protected void onDestroy() {

        Log.d(TAG,
                "onDestroy " + getClass().getSimpleName()
                        + Integer.toHexString(hashCode()));
        super.onDestroy();
    }
}

The manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.multiplestartupifusingpendingintent"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="19"
        android:targetSdkVersion="19" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.multiplestartupifusingpendingintent.MainActivity"
            android:configChanges="orientation|screenSize"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

My problem is a behavior happening, that I don't understand:

  1. If I start the application (first onCreate call ), then put it to backround, then click on its desktop icon, the same instance is reused. In logcat I can see just 1 onCreate call. It is what I want

  2. If I start the application ( first onCreate call ), put it to background, click the notification , then click the desktop icon ( second onCreate call ) , then I see 2 onCreate calls in logcat. As I press back I go twice before I can exit the app, and normally I see 2 onDestroy calls, since I have 2 identical stacked activities.

Why is the last behavior happening? Why is Android not reusing the existing activity, and creates 2 copies of them stacked? More weird, why is it doing only in case 2/why is it not doing it in case 1 also?

Thanks


回答1:


In the first case you comment, your activity is paused and has not been destroyed, so it moves from paused state to resumed state. You may check the activity lifecycle to learn more about it.

You should set

android:launchMode="singleInstance"

to your activity (in the manifest) and receive new intents inside:

  • onCreate(...) in case the activity has been destroyed
  • onNewIntent(...) in case the activity is paused/resumed

Hope it helps.




回答2:


If you only have a single Activity, you should be able to do this in showReuseNotification():

    Intent reuseIntent = new Intent(this, MainActivity.class);
    reuseIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent reusePendingIntent = PendingIntent.getActivity(this, 2,
            reuseIntent, PendingIntent.FLAG_UPDATE_CURRENT);

This will bring an existing instance of your application to the foreground (if there is one), or start a new one (if there isn't already an active one).




回答3:


In the second case, your activity is still visible, but not in the foreground, because the notification bar uses the trick of stacking its own transparent activity on top of the second activity to make it appear as if a status bar was getting pulled down on top of the Activity.

And because of this special case, Android assigns a different priority to the activity underlying that foreground activity.

Let me look for a reference to what I'm saying. I'll be back soon.



来源:https://stackoverflow.com/questions/20724054/android-does-not-reuse-main-activity-and-starts-multiple-instances-behavior-on

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!