安卓中的getIntent()返回第一个意图。

10

我开发了一个应用程序,可以下载视频文件并将其存储在SD卡中。在此过程中,我还使用NotificationManager更新下载进度和状态作为状态栏通知。

我的类名为DownloadTask.java,它继承了AsyncTask。所以,在这里,我使用onProgressUpdate()方法更新进度,并使用NotificationManager进行此操作。一切都很顺利,但是,在下载完成后,我希望单击通知以打开特定的视频文件。所以我做了以下工作:

mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);

int icon = android.R.drawable.stat_sys_download_done;
long when = System.currentTimeMillis();

mNotification = new Notification(icon, "", when);
mContentTitle_complete = mContext.getString(R.string.download_complete);
notificationIntent = new Intent(mContext,OpenDownloadedVideo.class);
notificationIntent.putExtra("fileName", file);
mContentIntent = PendingIntent.getActivity(mContext, 0, notificationIntent, 0);
mNotification.setLatestEventInfo(mContext, file, mContentTitle_complete, mContentIntent);
mNotification.flags = Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify(NOTIFICATION_ID, mNotification);
请注意,fileNameNOTIFICATION_ID在我的情况下是唯一的。 Activity OpenDownloadedVideo.java 通过以下方式打开文件:
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    try {  
        fileName = getIntent().getExtras().getString("fileName");
        Intent i = new Intent(Intent.ACTION_VIEW);
        File videoFileToPlay = new File(Environment.getExternalStorageDirectory()+"/MyFolder"+"/"+fileName);
        i.setDataAndType(Uri.fromFile(videoFileToPlay), "video/*");
        startActivity(i);
        finish();
    } catch(Exception e) {
        //
    }
}

当我第一次下载视频并点击通知时,将打开相应的视频文件。然而,下一次当我下载另一个视频并点击通知时,第一个下载的文件将再次被打开。

这是因为OpenDownloadedVideo中的getIntent返回的是第一个创建的Intent而不是最新的Intent。我该如何纠正这个问题呢?

此外,请注意,在我下载多个视频的情况下存在这个问题场景,例如如果我下载了五个不同的视频文件并且状态栏中有五个通知。每次点击通知时都会打开同一个文件。

6个回答

12
/**
 * Override super.onNewIntent() so that calls to getIntent() will return the
 * latest intent that was used to start this Activity rather than the first
 * intent.
 */
@Override
public void onNewIntent(Intent intent){
    super.onNewIntent(intent); // Propagate.
    setIntent(intent); // Passing the new intent to setIntent() means this new intent will be the one returned whenever getIntent() is called.
}

11

实际上,你只需要使用 PendingIntent.FLAG_UPDATE_CURRENT 标志创建 PendingIntent,就像这样:

mContentIntent = PendingIntent.getActivity(mContext, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

9

Android Activity.onNewIntent() 文档

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

所以,当您获得新的 Intent 时,您需要显式将其设置为活动意图。


此外,要检索新的意图,您必须覆盖onNewIntent()方法,调用getIntent()将返回旧的意图,即使您使用setIntent()。 - DoruChidean
这是一个很好的答案。我需要基本上使用setIntent或调用onNewIntent()的超级方法,以确保getIntent返回最新的意图。 - welshk91

5

感谢 @Alex 和 @Codinguser 的回复,非常感谢。然而我找到了一个对我起作用的不同的答案。当创建 PendingIntent 时,为 Intent 传递一个唯一的值即可。在我的情况下,我是这样做的:

mContentIntent = PendingIntent.getActivity(mContext, 0, notificationIntent, 0); 

但现在我正在使用NOTIFICATION_ID,因为它是唯一的。我已经将上面的调用更改为:

mContentIntent = PendingIntent.getActivity(mContext, NOTIFICATION_ID,
                                           notificationIntent, 0);

这就是全部内容,它有效。我在这个问题的“Pending Intent的多个实例”中找到了一些信息。

0
如果您将OpenDownloadedVideo活动设置为SINGLE_TOP并覆盖onNewIntent会怎样呢?

我该怎么做?抱歉,我很新手。 - Bopanna
我不知道这是否有帮助。在清单编辑器中,您为Activity启动模式添加SINGLE_TOP。然后,您覆盖Activity的onNewIntent()方法,并将与onCreate()中相同的代码放入其中。 - Alexander Kulyakhtin
我已将“OpenDownloadedVideo”活动设置为“SINGLE_TOP”,并在活动内重写了您建议的“onNewIntent”方法... 但是当活动启动或重新启动时,似乎并没有进入“onNewIntent”方法。 - Bopanna
@Bopanna 也许它没有重新启动,而是暂停然后恢复了? - Alexander Kulyakhtin

0
在你的活动中,意图正在启动。 添加(覆盖)以下函数:
@Override
protected void onNewIntent(final Intent intent) {
        super.onNewIntent(intent);
        this.setIntent(intent);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接