活动重新创建意图附加内容为空

Posted

技术标签:

【中文标题】活动重新创建意图附加内容为空【英文标题】:Activity re-creation intent extras are null 【发布时间】:2014-10-20 10:25:41 【问题描述】:

我的应用包含一个 MainActivity 并使用全屏片段来显示内容。 我试图在重新创建应用程序期间实现以下目标(当应用程序长时间处于后台时,被系统杀死然后被带到前台)

    如果用户手动重新创建应用程序(通过从最近的应用程序列表中选择应用程序),主 Activity 应重新创建,然后应重新创建最后一个全屏片段。没问题,这是标准行为。

    如果由于用户触摸推送通知而重新创建应用程序,则主 Activity 应重新创建,但不应重新创建全屏的最后一个片段。 应该创建并显示一个新的 Fragment。为什么?推送通知包含有关应显示哪种 Fragment 的信息

我的方法依赖于检查我在构建启动 Main Activity 的通知时添加的意图附加内容,为简洁起见,未显示该部分代码,但 我总是在意图中添加一些附加内容,总是

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) 
    //debug
    System.out.println("MainActivity.onCreate() extras:"+getIntent().getExtras());
    if (savedInstanceState!=null && getIntent().getExtras()!=null)
        //case 2. passing null will prevent Fragment recreation
        super.onCreate(null)
    
    else
        //case 1.
        super.onCreate(savedInstanceState)
    
    ...


@Override
public void onResume()
    //debug
    System.out.println("MainActivity.onResume() extras:"+getIntent().getExtras());
    ...

现在,如果应用程序根本没有运行并且通知到达,我会得到以下输出:

MainActivity.onCreate() extras: Bundle[android:viewHierarchyState=Bundle[mParcelledData....
MainActivity.onResume() extras: Bundle[android:viewHierarchyState=Bundle[mParcelledData....

当用户手动重新创建应用程序时,我得到以下输出:

MainActivity.onCreate() extras: null
MainActivity.onResume() extras: null

当应用被通知重新创建时

MainActivity.onCreate() extras: null
MainActivity.onResume() extras: Bundle[android:viewHierarchyState=Bundle[mParcelledData....

这最后一种情况不是我所期望的,不知何故,通知意图附加功能只有在调用 super.onCreate() 后才可用

关于如何实现 1. 和 2. 的任何想法?

巨型编辑: 这是通知代码,如您所见,有一个启动屏幕 Activity 将 Intent 中继到 Main Activity

GcmIntentService.java

@Override protected void onHandleIntent(Intent intent) 
    Bundle extras = intent.getExtras();
    GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
    String messageType = gcm.getMessageType(intent);
    if (!extras.isEmpty()) 
        if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) 
            sendNotification(extras.getString(KEY_CATEGORY), extras.getString(KEY_CONTENT));
        
    
    GcmBroadcastReceiver.completeWakefulIntent(intent);


private void sendNotification(String category, String content) 
    category = evaluateCategory(category);
    mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
    Intent mIntent = new Intent(this, SplashActivity.class);
    mIntent.putExtra(KEY_CATEGORY, Integer.valueOf(category));
    mIntent.putExtra(KEY_NEW, true);
    mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent contentIntent = PendingIntent.getActivity(this, Integer.valueOf(category), mIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                                                .setSmallIcon(R.drawable.logo_actionbar)
                                                //customize notification

    mBuilder.setContentIntent(contentIntent);
    mNotificationManager.notify(Integer.valueOf(category), mBuilder.build());

SplashActivity.java

@Override protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    Intent mIntent = getIntent();
    if (mIntent.getExtras()!=null)
        category = mIntent.getExtras().getInt(GcmIntentService.KEY_CATEGORY);
        isNew = mIntent.getExtras().getBoolean(GcmIntentService.KEY_NEW);
    
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() 
        @Override
        public void run() 
            Intent mainIntent = new Intent(SplashActivity.this, MainActivity.class);
            mainIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_CLEAR_TOP);
            if (category!=null )
                mainIntent.putExtra(GcmIntentService.KEY_CATEGORY, category);
                mainIntent.putExtra(GcmIntentService.KEY_NEW, isNew);
            
            startActivity(mainIntent);
            overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
            finish();
        
    , SPLASH_DELAY);

【问题讨论】:

什么版本的安卓?如果您在 KitKat 通知上进行的测试与那里不同。您可以发布您的通知构建代码吗? 版本为 4.4.2。我添加了 de 通知代码,它就像这样 GcmIntentService > SplashActivity > MainActivity 你的问题解决了吗? 【参考方案1】:

重写Activity提供的onNewIntent(Intent intent)方法怎么样?

    Read savedInstanceState 可以为 null,getIntent() 可以在您的 GCM 中包含额外内容。

    According to Android Developers:

protected void onNewIntent(意图意图)

这对于将 launchMode 设置为“singleTop”的活动调用 他们的包,或者如果客户使用了 FLAG_ACTIVITY_SINGLE_TOP 标志 调用 startActivity(Intent) 时。无论哪种情况,当活动 在活动堆栈的顶部重新启动,而不是新的 正在启动的活动实例,将调用 onNewIntent() 在具有用于重新启动的 Intent 的现有实例上 它。

Activity 在接收到新的 Intent 之前总是会暂停,所以 你可以指望 onResume() 在这个方法之后被调用。

请注意,getIntent() 仍然返回原始 Intent。您可以使用 setIntent(Intent) 将其更新为这个新的 Intent。

【讨论】:

谢谢。你拯救了我的一天。

以上是关于活动重新创建意图附加内容为空的主要内容,如果未能解决你的问题,请参考以下文章

替换 SingleTask 活动中的片段

活动包缺少附加功能,即使它们应始终添加到 newIntance 方法中

如何重新附加片段(片段未附加到活动 Kotlin)

如何正确地将独特的附加内容传递给待处理的意图?

即使重新创建活动,也不会清除待处理的意图额外内容

将服务重新附加到活动?