Android-我的应用替换了共享其内容的应用 原始答案更新

问题描述

我正在开发一个使用意图接收数据的应用(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清单中的“活动”,以确保它不会为同一活动打开多个任务。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...