我有一个以 Activity 开头的应用程序,用于在显示主 Activity 之前加载内容。启动应用程序通常会执行 MyApplication --> MyLoadingActivity --> MyMainActivity 。在 MyMainActivity 中有一个带有 RecyclerViews 和其他东西的 ViewPager。 MyMainActivity 中的状态在导航到应用程序中的其他 Activity 或从其他 Activity 导航时正确保存和恢复,但是当从通知启动 MyMainActivity 时,由于 Android 重新启动该 Activity ,所有状态都被清除。

通知是从检查远程服务器更新的服务中创建的。找到更新后,新数据将存储在 SQLite 数据库中,并创建有关此的通知。当我单击此通知时,MyMainActicity 已启动,但状态丢失。

official guide 之后,这是我在服务中创建通知的方法:

NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
    .setSmallIcon(R.drawable.foo)
    .setAutoCancel(true)
    .setContentTitle("title")
    .setContentText("text")
    .setStyle(new NotificationCompat.BigTextStyle().bigText("A long text will go here if we are on Lollipop or above."));

Intent notifyIntent = new Intent(context, MyMainActivity.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

PendingIntent notifyPendingIntent = PendingIntent.getActivity(context, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(notifyPendingIntent);

NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(666, builder.build());

我曾尝试以各种方式组合 Intent.FLAG_***,但一直无法使其正常工作。我无法弄清楚这一点,因此这个问题。

打开通知时我想实现的是:
  • 如果应用程序没有运行,则正常启动应用程序并转到 MyMainActivity
  • 如果应用程序正在运行并且 MyMainActivity 处于 Activity 状态,只需将其与现有状态一起放在前面并运行几行代码。
  • 如果应用程序正在运行而另一个 Activity 正在运行,请返回 MyMainActivity ,最好使用现有堆栈。大多数其他 Activity 是 MyMainActivity 的子 Activity 。

  • 使用当前代码会发生什么:
  • 使用 Intent.FLAG_ACTIVITY_NEW_TASK 创建一个新的 MyMainActivity 实例,它具有空状态,即使它的描述状态是


  • 在创建新的 Intent.FLAG_ACTIVITY_CLEAR_TASK 后,同样使用 onDestroy() 调用现有 MyMainActivity 上的 MyMainActivity。那没有多大帮助。

  • 我尝试过的其他事情:

    A. 如 here 所述,将 Intent 设置为应用程序正常启动的方式不起作用。

    B. 各种标志组合未能提供所需的行为。

    C. Stackoverflow 上的各种其他答案。

    作为引用,这是我的 list 文件:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.my.app"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="11"
            android:targetSdkVersion="22" />
    
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/my_app_name"
            android:theme="@style/MyTheme"
            android:name=".MyApplication" >
            <activity
                android:name=".activities.MyLoadingActivity"
                android:icon="@drawable/ic_launcher"
                android:screenOrientation="portrait" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity
                android:name=".activities.MyMainActivity"
                android:icon="@drawable/ic_launcher"
                android:label="@string/my_app_name"
                android:screenOrientation="portrait" >
            </activity>
            <activity
                android:name=".activities.AnotherActivity"
                android:label="@string/aa_title"
                android:icon="@drawable/ic_launcher"
                android:parentActivityName=".activities.MyMainActivity"
                android:screenOrientation="portrait">
                <meta-data
                    android:name="android.support.PARENT_ACTIVITY"
                    android:value=".activities.MyMainActivity" >
                </meta-data>
            </activity>
    
            <!-- More children activities of MyMainActivity here -->
    
            <receiver android:name=".services.ScheduleUpdateReciever">
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED" />
                    <action android:name="com.my.app.action.ScheduleUpdateReceiver"/>
                </intent-filter>
            </receiver>
            <receiver android:name=".services.StartUpdateReceiver" />
    
            <service android:enabled="true" android:name=".services.UpdateService" />
    
        </application>
    
    </manifest>
    

    更新:保存/恢复

    以下是 MyMainActivity 的保存和恢复方式。我意识到这可能需要一些清洁。可能跟问题有关。为简洁起见,省略了该类的其他部分。如上所述,在应用程序内部导航时,所有保存和恢复都可以正常工作。
    private ShoppingList mShoppingList;
    private FilteredRecipes mFilteredRecipes;
    private MainFragment mMainFragment;
    
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity_layout);
    
        // Start the Broadcast receiver that creates notifications if new data is found.
        startService(new Intent(this, ScheduleUpdateReciever.class));
        sendBroadcast(new Intent(SCHEDULE_UPDATE_RECEIVER_BROADCAST));
    
        // Setup Toolbar, NavigationView, DrawerLayout etc. here. No state restored for these widgets.
    
        if (mShoppingList == null)
        {
            mShoppingList = new ShoppingList(this);
        }
    
        if (mFilteredRecipes == null)
        {
            mFilteredRecipes = new FilteredRecipes(this);
        }
    
        if (savedInstanceState == null)
        {
            mMainFragment = new MainFragment();
        }
        else
        {
            restoreState(savedInstanceState);
        }
    
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.content_frame, mMainFragment, FragmentConstants.MAIN_FRAGMENT_TAG)
                .commit();
    
    
    }
    
    @Override
    protected void onSaveInstanceState(Bundle outState)
    {
        super.onSaveInstanceState(outState);
    
        // These calls adds stuff directly to the Bundle instance, be it basic variables, lists or Parcelable classes.
        mShoppingList.onSaveInstanceState(outState);
        mFilteredRecipes.onSaveInstanceState(outState);
        getSupportFragmentManager().putFragment(outState, SAVE_RESTORE_MAIN_FRAGMENT, mMainFragment);
    }
    
    
    private void restoreState(Bundle savedInstanceState)
    {
        // These calls restores stuff directly from the Bundle instance, be it basic variables, lists or Parcelable classes.
        mShoppingList.onRestoreInstanceState(savedInstanceState);
        mFilteredRecipes.onRestoreInstanceState(savedInstanceState);
        mMainFragment = (MainFragment) getSupportFragmentManager().getFragment(savedInstanceState, SAVE_RESTORE_MAIN_FRAGMENT);
    }
    

    最佳答案

    来自 android 文档:http://developer.android.com/reference/android/content/Intent.html

    关于 FLAG_ACTIVITY_CLEAR_TOP:



    关于 FLAG_ACTIVITY_SINGLE_TOP:



    这听起来几乎是您试图实现的目标。试试这个:

    notifyIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    

    编辑:

    您正在使用 savedInstanceState 来保存您的 Activity 中的数据,我不建议使用这种方法,因为它不可靠,从文档( http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState%28android.os.Bundle%29 )您可以推断根本无法调用 onSaveInstanceState() :



    您应该使用更持久的方式来存储您的键/值信息,例如 sharedPreferences 或数据库,并在您的 onCreate 方法中检索这些值。这里有更多关于它的信息:http://developer.android.com/training/basics/data-storage/index.html

    您还可以在此处查看我的答案:https://stackoverflow.com/a/35023304/5837758 以了解使用 sharedPreferences 的简单方法。

    10-08 17:33