【问题标题】:Android deep link does not work if the app is opened by deep link already如果应用程序已通过深层链接打开,Android 深层链接将不起作用
【发布时间】: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 中看到消息“设置上次选择的活动”?我看到了相同的行为,但该消息似乎表明此行为是有意的。
  • 你是怎么决定的?

标签: android deep-linking


【解决方案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 对我不起作用。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2020-05-25
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-04-11
                • 2016-05-10
                • 2019-05-19
                • 1970-01-01
                相关资源
                最近更新 更多