如果应用程序已通过深层链接打开,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 深层链接将不起作用的主要内容,如果未能解决你的问题,请参考以下文章