问题描述
我正在开发一个使用意图接收数据的应用(ACTION_SEND)。例如,如果内容仅是选定的文本,则我从Chrome共享内容时发现了一个奇怪的问题(仅发生在Chrome 83或更高版本中,旧版本无法重现该问题)。我的应用程序正确,但是如果共享的内容是URL,则到达我的应用程序,但是突然我的应用程序替换了应用程序切换器中的Chrome。因此,如果我打开了我的应用程序并打开了Chrome浏览器,则在数据共享之后,我有两个我的应用程序实例(即使Chrome图标出现在该窗口的顶部,如果我点击它,也会打开我的应用程序)。
关于这里发生的事情有什么想法吗?值得注意的是,我无法使用Firefox重现此内容。
我的活动代码:
class MainActivity : HybridActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Log.d("MyApp","onCreate")
super.onCreate(savedInstanceState)
val testButton = Button(this)
setContentView(testButton)
}
override fun onStart(){
super.onStart()
var bundle = intent.getExtras();
Log.d("MyApp","onStart intent tostr: " + intent.toString())
if (bundle != null) {
bundle.keySet().forEach {
Log.d("MyApp","EXTRA:" + it + "=" + bundle.get(it));
}
}
}
override fun onResume() {
super.onResume()
Log.d("MyApp","onResume")
}
}
在清单中定义的意图过滤器如下:
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
<data android:mimeType="image/*" />
<data android:mimeType="video/*" />
</intent-filter>
PS:不知道这是否相关,但我已将清单中的启动模式更改为singleInstance
,但该问题仍然可以重现...
PS2:我添加了此活动转储,其产生与问题出现的时间相同: https://gist.github.com/Leprosy/f63bf02bb1c2887f0e419799d98635ab
解决方法
更新2
所以我做了更多的研究,看来这仅在使用android共享表时发生。当共享数据的应用程序使用意图解析器时,活动将在新任务/实例中打开。例如,firefox中的共享功能确实可以正确处理它。不幸的是,我找不到与此相关的任何内容以及如何解决它。
原始答案
我认为这是您的应用的一种想要的行为,因为您的应用正在处理网址,并且未在您的应用中打开它。
更新
这是官方文档所说的关于您正在使用的隐式深层链接的信息:
隐式深层链接是指向应用程序中特定目标的URI。调用URI时(例如,当用户单击链接时),Android随后可以将您的应用打开到相应的目的地。
触发隐式深层链接时,后退堆栈的状态取决于是否使用Intent.FLAG_ACTIVITY_NEW_TASK
标志启动了隐式Intent:
- 如果设置了该标志,则将清除任务后退堆栈,并将其替换为深度链接目标。与显式深层链接一样,在嵌套图形时,还将嵌套的每个级别的起始目标(即,层次结构中每个元素的起始目标)也添加到堆栈中。这意味着,当用户从深层链接目标按下“返回”按钮时,他们将在导航堆栈中向上导航,就像从应用程序的入口点进入您的应用一样。
- 如果未设置该标志,则将保留在先前应用程序的任务堆栈上,在该堆栈上触发了隐式深层链接。在这种情况下,“后退”按钮可将您带回到上一个应用程序,而“向上”按钮可在导航图内的分层父目标上启动应用程序的任务。
根据我的理解,这意味着只有启动您的应用的应用才能更改此行为。
来源:https://developer.android.com/guide/navigation/navigation-deep-link#implicit
,您的应用实际上并没有取代chrome,而是来自您应用的共享链接意图接收器活动到达了chrome task的顶部。仍然是chrome任务,仅仅是最重要的活动来自您的应用程序。这样可以确保即使您先几次切换应用程序,按回退键也可以返回chrome。
作为一种解决方法,您可以检测到此情况,在这种情况下,请创建新的意图以启动新活动并关闭直接接收该活动的活动。
编辑:我对此进行了测试,可以通过以下方式完成:
import android.app.Activity
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Bundle
class ExternalTextReceiverActivity : Activity() {
val CUSTOM_EXTRA_NAME = "RELAUNCHED"
override fun onCreate(savedInstanceState: Bundle?) {
if (!intent.getBooleanExtra(CUSTOM_EXTRA_NAME,false)) {
this.finish()
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(CUSTOM_EXTRA_NAME,true);
startActivity(intent);
}
super.onCreate(savedInstanceState);
// The rest of your onCreate code here
}
}
如果您只希望将其用于chrome,则可以使用以下代码:
import android.app.Activity
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Bundle
class ExternalTextReceiverActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
if (intent.getIntExtra("org.chromium.chrome.extra.TASK_ID",-1) == this.taskId) {
this.finish()
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
super.onCreate(savedInstanceState);
// The rest of your onCreate code here
}
}
在两种情况下都将android:launchMode="singleInstance"
或android:launchMode="singleTask"
组合为您在Android清单中的“活动”,以确保它不会为同一活动打开多个任务。