我的Android应用程序被传递信息的意图调用(状态栏中的pendingintent).
当我按下主页按钮并通过按住主页按钮重新打开我的应用程序时,它再次调用了意图,并且仍然存在相同的附加功能.
@Override public void onSaveInstanceState(Bundle savedInstanceState) { super.onSaveInstanceState(savedInstanceState); } @Override public void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); }
这是不像它应该运行的代码
String imgUrl; Bundle extras = this.getIntent().getExtras(); if(extras != null){ imgUrl = extras.getString("imgUrl"); if( !imgUrl.equals(textView01.getText().toString()) ){ imageView.setImageDrawable( getImageFromUrl( imgUrl ) ); layout1.setVisibility(0); textView01.setText(imgUrl);//textview to hold the url } }
我的意图是:
public void showNotification(String ticker, String title, String message, String imgUrl){ String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); int icon = R.drawable.icon; // icon from resources long when = System.currentTimeMillis(); // notification time CharSequence tickerText = ticker; // ticker-text //make intent Intent notificationIntent = new Intent(this, activity.class); notificationIntent.putExtra("imgUrl", imgUrl); notificationIntent.setFlags( PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT); //make notification Notification notification = new Notification(icon, tickerText, when); notification.setLatestEventInfo(this, title, message, contentIntent); //flags notification.flags = Notification.FLAG_SHOW_LIGHTS | Notification.FLAG_ONGOING_EVENT | Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL; //sounds notification.defaults |= Notification.DEFAULT_SOUND; //notify mNotificationManager.notify(1, notification); }
有没有办法清除意图或检查它是否曾被使用过?
当我5年前第一次写这篇文章时,我没有意识到这个答案会被提到这么多!
我要澄清一点,根据@ tato-rodrigo的回答,这不会帮助你在某些情况下检测已经处理过的意图.
另外我应该指出我把"明确"放在引号中是有原因的 - 你并没有真正通过这样做清除意图,你只是使用额外的删除作为一个标志,这个意图已被活动看到.
我有完全相同的问题.
以上回答让我走上正轨,我发现更简单的解决方案,使用:
getIntent().removeExtra("key");
方法调用"清除"意图.
自从一年前被问到这个问题以后,它的回答有点迟了,但希望这对未来的其他人有所帮助.
编辑:我正在编辑发布我正在使用的完整解决方案.
如果问题是"当活动从历史记录(最近的应用程序)启动时不执行某些代码",则此解决方案将起作用.
首先,boolean
在你的声明中Activity
指示是否Intent
已经消耗了:
private boolean consumedIntent;
然后,使用onSaveInstanceState
和onCreate
方法安全地存储和恢复此值,以处理配置更改以及系统Activity
在进入后台时可能会将其杀死的情况.
private final String SAVED_INSTANCE_STATE_CONSUMED_INTENT = "SAVED_INSTANCE_STATE_CONSUMED_INTENT"; @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(SAVED_INSTANCE_STATE_CONSUMED_INTENT, consumedIntent); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //set content view ... if( savedInstanceState != null ) { consumedIntent = savedInstanceState.getBoolean(SAVED_INSTANCE_STATE_CONSUMED_INTENT); } //other initializations }
现在,检查您是否可以在onResume
方法下运行代码.
@Override protected void onResume() { super.onResume(); //check if this intent should run your code //for example, check the Intent action boolean shouldThisIntentTriggerMyCode = [...]; Intent intent = getIntent(); boolean launchedFromHistory = intent != null ? (intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0 : false; if( !launchedFromHistory && shouldThisIntentTriggerMyCode && !consumedIntent ) { consumedIntent = true; //execute the code that should be executed if the activity was not launched from history } }
此外,如果您Activity
的配置为singleTop
,则应在Intent
交付新标志时重置标记.
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); consumedIntent = false; }
Maks的答案适用于清除额外的:
getIntent().removeExtra("key");
另一个有用的命令是:
getIntent().setAction("");
您还可以通过调用标记意图:
getIntent().putExtra("used", true);
然后只需检查值.
当我们从历史(最近的应用程序)启动Android应用程序时,可以使用主要三种不同的Intent标志启动应用程序.
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
这是从最小化的应用程序的历史记录启动活动时(长按主页键).
常数值:1048576(0x00100000)
FLAG_ACTIVITY_NEW_TASK
这是通过"单击应用程序图标"或通过" 意图过滤器 "启动活动的时间.这里的活动将成为此历史堆栈上新任务的开始.
常数值:268435456(0x10000000)
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY | FLAG_ACTIVITY_NEW_TASK
这是当按下后退按钮退出应用程序然后从历史记录(最近的应用程序)恢复时.
常数值:269484032(0x10100000)
可以通过检索常量值 getIntent().getFlags()
在第三种情况下,Android从其内存重新加载最后的Intent值.因此,您的应用的intent(getIntent
)将具有启动应用的最后一个意图的值.
实际上,应用应该表现得好像是一个新的发布,新的发布的意图值而不是上一次发布的意图值.如果通过单击应用程序图标启动应用程序,则可以看到此行为,它将永远不会具有旧的意图值.这是因为Android为此方案使用以下intent过滤器
但在第三种情况下(已退出的应用程序,是从最近的应用程序的历史记录启动),Android OS使用在退出之前启动应用程序的最后一个意图(通过按下后退按钮).所以你最终得到旧的意图值并且应用流程不合适.
删除意图是解决问题的一种方法,但它不能完全解决问题!随着Android OS从上次启动的应用程序重新加载Intent,而不是启动意图的最后一个实例.
避免这种情况发生的一种干净方法是通过获取Intent类型来确定启动类型来处理它.
因此,在您LaunchActivity(这在清单中定义的意图过滤器中的一个),你可以在使用下面的代码onCreate()
,onStart()
或onResume()
方法.
if(getIntent().getFlags() == (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)) { //app is launched from recent apps after it was closed normalLaunch(); } else { String intentAction = getIntent().getAction(); String scheme = getIntent().getScheme(); //app is launched via other means // URL intent scheme, Intent action etc if("https".equalsIgnoreCase(scheme)) { // URL intent for browser } else if("com.example.bb".equalsIgnoreCase(intentAction)) { // App launched via package name } else { // App was launched via Click on App Icon, or other means normalLaunch(); } }
我认为normalLaunch()
,不应该使用Intent中的参数; 否则你需要隔离并优化你的默认启动方法,不要使用Intent参数.
intent.replaceExtras(new Bundle()); intent.setAction(""); intent.setData(null); intent.setFlags(0);
简短的回答是没有办法
答案很长.没有"一次性"的意图.从实验中可以看出,现代机器人最近的活动历史只不过是"意图历史".传递给活动的最新意图只是登录到系统,这就是交易.上面的人建议使用
setAction("")
但它不起作用,因为意图已经记录,直到你在onNewIntent()或onStart()方法中获取它.
我通过避免使用意图来解决问题.我的问题与作者发布的问题相似.我尝试通过通知区域中的控件实现应用程序的全局退出.它应该停止底层服务并关闭应用程序的所有活动.您可以在Waze应用程序中找到相同的行为.
算法:
为通知控制创建PendingIntent,将"退出"操作传递给活动.但对于一个简单代理的特殊活动.
代理活动onStart()代码解析intent,检查action并将某个模型的状态设置为"Exited".
代理活动onStart()代码使用setIntent("")清除原始意图,然后通过调用startActivity(intent)将其转发到目标"Root"活动.
代理活动onStart()代码调用finish().
在目标活动的onStart()和onNewIntent()内部检查模型状态,如果它是"已退出"则调用finish()(在我的情况下也调用stopService()).
我希望这会对某人有所帮助,因为我没有在互联网上找到答案.