我有一个持续通知的应用。我使用NotificationCompat.Builder
来创建通知。我在构建器上调用setContentIntent()
以向通知添加PendingIntent
,以便在单击通知时运行MyActivity。
当MyActivity正在运行时,我点击正在进行的通知,我希望调用MyActivity onNewIntent()
。为了实现这一点,我将MyActivity的launchMode设置为" singleTask",并将PendingIntent I传递给setContentIntent()
,如下所示:
Intent notifyIntent = new Intent( this,
MyActivity.class );
PendingIntent pendingIntent = PendingIntent.getActivity( this,
REQUEST_CODE,
notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT );
我在IntelliJ中调试我的应用程序,我看到一切都按预期工作。到目前为止没什么奇怪的。
当我尝试将PendingIntent切换为使用TaskStackBuilder
创建的PendingIntent时,会很奇怪。我知道这将不再导致调用onNewIntent()
,只是忍受我:
Intent notifyIntent = new Intent( this,
MyActivity.class );
TaskStackBuilder stackBuilder = TaskStackBuilder.create( this );
stackBuilder.addParentStack( MyActivity.class );
stackBuilder.addNextIntent( notifyIntent );
PendingIntent pendingIntent = stackBuilder.getPendingIntent( REQUEST_CODE,
PendingIntent.FLAG_UPDATE_CURRENT );
所以,让我们说我已经更新了我的PendingIntent以这种方式创建。我点击ctrl + S保存我的文件。我再次点击调试按钮,重建应用程序,替换我的设备上的旧apk等,并开始调试。当我点击正在进行的通知时,我期望看到的是现有的运行MyActivity被销毁并创建一个新的,即调用onCreate()
。但是,我不明白。相反,我仍然像以前一样看到onNewIntent()
被调用,好像我没有保存我的代码并重建它。
嗯,但我确实保存并重建它,因为同一个文件中的其他更改,例如新的Toast,正在显示。
让我重新启动设备并重试。嗯,现在onCreate()
被调用而不是onNewIntent()
。为什么它只在重启后才能工作?
我在不同的设备和模拟器上试过这个。我尝试了另一个IDE。同样的事情。
我甚至尝试过从使用TaskStackBuilder回到原来的PendingIntent,我仍然会遇到意想不到的行为。换句话说,我希望看到onNewIntent()
被调用,因为我不再使用TaskStackBuilder,但我看到onCreate()
被调用了。
因此,如果我重新启动设备,则会发生正确的预期行为。手动卸载应用程序也会产生正确的预期行为。
我错过了一些完全明显的东西吗?为什么会这样?好像Android正在记住上一个调试会话中的旧PendingIntent。
我在此处的示例代码中创建了一个玩具示例:http://developer.android.com/guide/topics/ui/notifiers/notifications.html
以下是玩具示例:
MainActivity.java
package com.blah.pendingintent.example;
import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity
{
private static final int REQUEST_CODE = 1;
private static final int NOTIFICATION_ID = 2;
private static final String TAG = "MainActivity";
private NotificationCompat.Builder m_builder;
private NotificationManager m_notificationMgr;
@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
m_builder = new NotificationCompat.Builder( this );
m_notificationMgr = (NotificationManager)getSystemService( Context.NOTIFICATION_SERVICE );
}
@Override
protected void onNewIntent( Intent intent )
{
super.onNewIntent( intent );
}
@Override
protected void onDestroy()
{
super.onDestroy();
}
public void onClick( View v )
{
Intent notifyIntent = new Intent( this,
MainActivity.class );
// comment out one of these lines and rerun
PendingIntent notifyPendingIntent = getPendingIntentWithActivity( notifyIntent );
// PendingIntent notifyPendingIntent = getPendingIntentWithBackStack( notifyIntent );
m_builder.setContentIntent( notifyPendingIntent );
m_builder.setContentTitle( "Picture Download" )
.setContentText( "Download in progress" )
.setSmallIcon( R.drawable.abc_ic_go );
new Thread( new Runnable()
{
@Override
public void run()
{
int incr;
for ( incr = 0; incr <= 100; incr += 5 )
{
m_builder.setProgress( 0,
0,
true );
m_notificationMgr.notify( NOTIFICATION_ID,
m_builder.build() );
try
{
Thread.sleep( 5 * 1000 );
}
catch ( InterruptedException e )
{
Log.d( TAG,
"sleep failure" );
}
}
m_builder.setContentText( "Download complete" )
.setProgress( 0,
0,
false );
m_notificationMgr.notify( NOTIFICATION_ID,
m_builder.build() );
}
}
).start();
}
private PendingIntent getPendingIntentWithBackStack( Intent notifyIntent )
{
Toast.makeText( this,
"Using TaskStackBuilder",
Toast.LENGTH_LONG )
.show();
TaskStackBuilder stackBuilder = TaskStackBuilder.create( this );
stackBuilder.addParentStack( MainActivity.class );
stackBuilder.addNextIntent( notifyIntent );
return stackBuilder.getPendingIntent( REQUEST_CODE,
PendingIntent.FLAG_UPDATE_CURRENT );
}
private PendingIntent getPendingIntentWithActivity( Intent notifyIntent )
{
Toast.makeText( this,
"Using PendingIntent",
Toast.LENGTH_LONG )
.show();
return PendingIntent.getActivity( this,
REQUEST_CODE,
notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT );
}
}
activity_main.xml中
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${packageName}.${activityClass}">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="pres butan"
android:onClick="onClick"/>
</RelativeLayout>
的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.blah.pendingintent.example" >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.blah.pendingintent.example.MainActivity"
android:launchMode="singleTask"
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>
build.gradle (IntelliJ向导中的默认文件)
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.9.+'
}
}
apply plugin: 'android'
repositories {
mavenCentral()
}
android {
compileSdkVersion 19
buildToolsVersion "19.1.0"
defaultConfig {
minSdkVersion 11
targetSdkVersion 18
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:19.+'
}
答案 0 :(得分:1)
因此,如果我重新启动设备,则会发生正确的预期行为。 手动卸载应用程序也会产生正确的预期 行为。
原因是,当您调试应用程序而不卸载它时,之前创建的PendingIntent
仍然是AlarmManager
。完全卸载应用程序后,之前的PendingIntent
将被销毁。重新启动手机也会破坏所有现有的PendingIntent
。
好像Android正在记住之前的旧PendingIntent 调试会话。
正是正在发生的事情。因此,当您测试使用PendingIntent
的应用程序时,您应该首先卸载应用程序并从IDE重新运行它以产生正确的预期行为。另请注意,正如您所观察到的,重新启动手机时会破坏现有的PendingIntent
。因此,您的应用必须以编程方式重新创建在重新启动时被销毁的PendingIntent
(因此,如果您的应用的用户重新启动他的手机,他们会收回他们安排的警报)。这是通过拦截BOOT_COMPLETE
事件来完成的。有关详情,请参阅here。
修改强>
要以编程方式检查先前创建的PendingIntent
是否存在,请使用以下命令:
boolean pendingIntentExists = (PendingIntent.getBroadcast(context, requestCode,
intent,
PendingIntent.FLAG_NO_CREATE) != null);
其中requestCode
和intent
必须与您之前创建此PendingIntent
时相同。
我希望能回答你的问题。
编辑2:
我相信你的情况,检查PendingIntent
是否存在的测试需要:
// check PendingIntent for Activity
boolean pendingIntentExists = (PendingIntent.getActivity( this,
REQUEST_CODE,
notifyIntent,
PendingIntent.FLAG_NO_CREATE) != null);
// check PendingIntent for backstack
TaskStackBuilder stackBuilder = TaskStackBuilder.create( this );
stackBuilder.addParentStack( MainActivity.class );
stackBuilder.addNextIntent( notifyIntent );
boolean pendingIntentExists = (stackBuilder.getPendingIntent( REQUEST_CODE,
PendingIntent.FLAG_NO_CREATE ) != null);
请试一试。