如果应用程序已通过深层链接打开,Android 深层链接将不起作用

Posted

技术标签:

【中文标题】如果应用程序已通过深层链接打开,Android 深层链接将不起作用【英文标题】:Android deep link does not work if the app is opened by deep link already 【发布时间】:2016-06-26 03:44:11 【问题描述】:

如果应用程序已经通过深层链接打开,则深层链接将不起作用。

但是,如果我不是通过触发深层链接来打开应用程序,例如单击应用程序图标来打开应用程序。然后触发深层链接总是有效的。


这里是细节:

所以我在 androidManifest 中设置了这样的活动,即 LaunchActivity。

<activity
    android:name="some.package.name.LaunchActivity"
    android:screenOrientation="portrait"
    android:theme="@style/Theme.SomeTheme">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="dlscheme" android:host="dlhost" />
    </intent-filter>
</activity>

在 LaunchActivity 中,我会在 onCreate() 中打印一个日志以表明它已经存在。

我用过

adb shell am start -W -a android.intent.action.VIEW -d "dlscheme://dlhost/param" some.package.name

测试深层链接。

应用程序被终止后,我使用了上述命令。它可以打开应用程序并路由到正确的活动,没问题。 并有以下日志。

adb shell am start -W -a android.intent.action.VIEW -d "dlscheme://dlhost/param" some.package.name
Starting: Intent  act=android.intent.action.VIEW dat=dlscheme://dlhost/param pkg=some.package.name 
Status: ok
Activity: some.package.name/.activity.LaunchActivity
ThisTime: 898
TotalTime: 898
WaitTime: 919
Complete

但是,如果我再次输入相同的命令,而不会终止应用程序。 它只会打开应用程序,但不会打开正确的活动,并产生以下日志。

adb shell am start -W -a android.intent.action.VIEW -d "dlscheme://dlhost/param" some.package.name
Starting: Intent  act=android.intent.action.VIEW dat=dlscheme://dlhost/param pkg=some.package.name 
Warning: Activity not started, its current task has been brought to the front
Status: ok
Activity: some.package.name/.activity.LaunchActivity
ThisTime: 0
TotalTime: 0
WaitTime: 6
Complete

加上这条额外的线

Warning: Activity not started, its current task has been brought to the front

我实际上也使用这个 chrome 意图在网站上尝试过这个:

intent://dlhost/param#Intent;scheme=dlscheme;package=some.package.name;end

它的行为是一样的。

【问题讨论】:

您是否在 logcat 中看到消息“设置上次选择的活动”?我看到了相同的行为,但该消息似乎表明此行为是有意的。 你是怎么决定的? 【参考方案1】:

在项目的清单文件中,您需要将以下内容添加到您的主要活动中。

android:launchMode="singleTask"

因此,在清单中,您将有类似于以下内容的内容:

<activity android:name="some.package.name.LaunchActivity" 
      android:launchMode="singleTask"
      android:screenOrientation="portrait"
      android:theme="@style/Theme.SomeTheme">
          <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
          <intent-filter>
              <action android:name="android.intent.action.VIEW" />
              <category android:name="android.intent.category.DEFAULT" />
              <category android:name="android.intent.category.BROWSABLE" />
              <data android:scheme="dlscheme" android:host="dlhost" />
          </intent-filter>
 </activity>

基本上,它的作用是创建一个新任务,并将一个新实例作为根实例推送到该任务。但是,如果任何任务中存在任何活动实例,系统会通过 onNewIntent() 方法调用将意图路由到该活动实例。在这种模式下,活动实例可以被推送到同一个任务。并且如果用户在当前activity中点击BACK键,系统会将用户返回到上一个activity。

另一方面,在singleTop 中,如果当前任务的顶部已经存在一个 Activity 实例并且系统将 Intent 路由到该 Activity,则不会创建新实例,因为它会触发 onNewIntent() 方法而不是创建一个新对象。

更多信息可以在here找到。

希望这会有所帮助:)

【讨论】:

嘿!谢谢这是解决这个问题的好方法,谢谢。但是你能帮我理解为什么会这样吗?为什么 android 需要 singleTask 才能使其深层链接路由活动正常运行?如果我从 deeplink 打开应用程序,我的 DeeplinkActivity 将成为该任务的根。但是,如果我从中打开另一个活动并完成 DeeplinkActivity,那不会使我的新活动成为根吗?如果是这样,为什么仍然无法重新创建 DeeplinkActivity? 如果我记得清楚的话,单任务的原因是没有同时打开同一活动的 2 个实例。所以通过这种方式,第一个活动在打开深度链接时保持活动状态。可以这么说,深层链接活动成为根活动,因为它的视图替换了您打开的前一个。 感谢您的回答(:但让我困扰的是通常可以打开多个活动,即如果您启动应用程序,然后打开深度链接,然后在您的应用程序中打开不同的屏幕,然后再次打开深层链接可以正常工作,但是如果您第一次启动的活动是深层链接活动,那么第二次将不起作用。就像 android 出于某种原因阻止了它的娱乐。 我完全同意@aleien,标准launchMode的活动应该能够打开指定的活动。值得庆幸的是,此错误仅在具有标准 launchMode 的某些设备 (Nexus 5X) 上重现,并且仅当应用最初通过深层链接启动并再次通过深层链接打开时。 感谢这个。我花了很多时间尝试在颤振应用中解决这个问题。【参考方案2】:

在您的 LaunchActivity 活动标签的清单中添加 android:launchMode="singleTop"

【讨论】:

【参考方案3】:

在你的活动清单中添加android:launchMode="singleTop"

如果您的启动模式是默认的,则此警告会出现“警告:活动未启动,其当前任务已被置于最前面”,因为每次它都在创建您的活动的新实例,而如果您使用单顶启动模式,那么 @ 987654322@方法调用而不是创建新对象

【讨论】:

【参考方案4】:

我在 NavigationUI 和 AppLink 集成方面遇到了类似的问题。我正在遵循单一活动架构,因此如果应用程序已经存在于任务堆栈中并且我想使用 AppLink 打开单独的片段,它将无法与 launchMode="singleTask" 一起使用。我什至尝试了finishOnTaskLaunch,但似乎都没有。

然后通过文档(我应该首先完成),我开始知道在上述情况下,意图是在活动类的 onNewIntent() 中收到的,并且将意图从当前片段重定向到我们需要调用的片段:

// 获取activity类的navController实例,然后

navController.handleDeepLink(intent)

这解决了我在任务中已经有其他片段时通过 AppLink/DeepLink 打开所需片段的问题。

希望我能提供帮助。

【讨论】:

【参考方案5】:

在您的项目的清单文件中,您需要将以下内容添加到您的主要活动中。

android:launchMode="singleTask"

并处理onNewIntent()里面的deeplink

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_recipe);
    onNewIntent(getIntent());


protected void onNewIntent(Intent intent) 
    String action = intent.getAction();
    String data = intent.getDataString();
    if (Intent.ACTION_VIEW.equals(action) && data != null) 
        String recipeId = data.substring(data.lastIndexOf("/") + 1);
        Uri contentUri = RecipeContentProvider.CONTENT_URI.buildUpon()
                .appendPath(recipeId).build();
        showRecipe(contentUri);
    

【讨论】:

【参考方案6】:

Mainefest 文件看起来像这个示例

<activity
                    android:name=".user.HomeActivity"
                    android:screenOrientation="portrait"
                    android:exported="true"
                    android:launchMode="singleTop"
                    android:windowSoftInputMode="stateAlwaysHidden"
                    android:theme="@style/AppTheme.NoActionBar" >
                    <intent-filter>
                        <action android:name="android.intent.action.VIEW" />
                        <category android:name="android.intent.category.DEFAULT" />
                        <category android:name="android.intent.category.BROWSABLE" />
                        <data android:scheme="example"/>
                        <data android:host="example.com"
                            android:pathPrefix="/deeplink"/>
                        <action android:name="android.intent.action.MAIN" />
                    </intent-filter>
                </activity>

家庭活动

@Override
            protected void onNewIntent(Intent intent) 
                super.onNewIntent(intent);
                Uri data = intent.getData();
                if (data != null)
                    callDeep(data);
                setIntent(intent);
                Log.d("DeepLinking", "new intent value==>" + data + "==== value===>");
            
        //or in on create 
        @Override
            protected void onCreate(Bundle savedInstanceState) 
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_home);
          Uri data = intent.getData();
                Log.d("DeepLinking", "intent value==>" + data + "==== value===>" + bundle + "===action==>" + action);
        

【讨论】:

【参考方案7】:

从日志中它说“警告:活动未启动,其当前任务已被带到前面”,因此没有创建活动的新实例。在这种情况下,新意图将重定向到活动的 onNewIntent(Intent intent)。

在您的情况下,我怀疑您没有覆盖此方法,并且将从活动的 onCreate() 方法中提取信息。

而是创建一个类似于 extractDataFromIntentAndProcess(Intent intent) 的方法,并从您的活动的 oncreate 方法 (extractDataFromIntentAndProcess(getIntent())) 和 onNewIntent 方法 (extractDataFromIntentAndProcess(intent)) 调用它。

【讨论】:

【参考方案8】:

我发现添加android:launchMode="singleTask" 有效。 singleTop 对我不起作用。

【讨论】:

以上是关于如果应用程序已通过深层链接打开,Android 深层链接将不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 应用中打开深层链接后返回浏览器

使用意图不打开应用程序的 Android 深层链接

如果应用程序通过深层链接打开,共享元素转换不起作用

为移动应用创建深层链接

使用 branch.io 来自 Play 商店的 Android 深层链接

Android 深层链接 - 不显示意图选择器弹出窗口,强制打开应用