jdo*_*ell 8 android deep-linking
情况:
TL; DR - 你如何实现这个?
我的方法到目前为止:
第一直觉:只匹配某些网址并为其启动.问题:AndroidManifest intent-filter中表达式的缺乏阻止了这一点(例如http://weiyang.wordpress.ncsu.edu/2013/04/11/a-limitation-in-intent-filter-of-android-application/) .
作为问题的一个子集,假设m.somewhere.com上的服务器知道任何以数字结尾的URL都会进入网站上的某个页面,并且营销人员会不断地使用seo,所以例如,
我想推出以下应用:
http://m.somewhere.com/find/abc-12345
https://m.somewhere.com/shop/xyz-45678928492
Run Code Online (Sandbox Code Playgroud)
但不是
http://m.somewhere.com/find/abc-12345-xyz
https://m.somewhere.com/about-us
Run Code Online (Sandbox Code Playgroud)
没有path,pathPrefix或pathPattern的组合将处理此问题.
stackoverflow的最佳实践(在AndroidManifest中匹配URI与<data>一样http://example.com/something)似乎是要抓住所有内容,然后在你进入onCreate()时意识到你不应该有这种情况处理了这个特殊的网址:
Android清单:
...
<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="http"
android:host="m.somewhere.com"
android:pathPattern=".*"/>
</intent-filter>
...
Run Code Online (Sandbox Code Playgroud)
活动onCreate():
Intent i = getIntent()
String action = i.getAction();
Uri uri = i.getData();
if (Intent.ACTION_VIEW.equals(action) && cantHandleUrl(uri)) {
// TODO - fallback to browser.
}
Run Code Online (Sandbox Code Playgroud)
我已经编写了类似于上面的东西,但它会导致非常糟糕的最终用户体验:
可以做些什么?
(编辑:在应用程序的WebView中显示未处理页面的站点不是一个选项).
答案很晚,但是对将来的读者来说:如果您支持最低的API级别15,那么有一种更直接的(较少hacky)方式退回到浏览器中查找您不想处理的URL,而无需诉诸于禁用/重新启用URL捕获组件。
nbarraille的答案很有创造力,如果需要支持低于15的API,则可能是您唯一的选择,但是如果不需要,则可以利用Intent.makeMainSelectorActivity()它直接启动用户的默认浏览器,从而绕过Android的ResolverActivity应用选择对话框。
因此,与其像这样重新广播URL意向,不如使用以下典型方法:
// The URL your Activity intercepted
String data = "example.com/someurl"
Intent webIntent = new Intent(Intent.ACTION_VIEW, data);
webIntent.addCategory(Intent.CATEGORY_BROWSABLE);
startActivity(webIntent);
Run Code Online (Sandbox Code Playgroud)
您应改为广播此Intent:
Intent defaultBrowser = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, Intent.CATEGORY_APP_BROWSER);
defaultBrowser.setData(data);
startActivity(defaultBrowser);
Run Code Online (Sandbox Code Playgroud)
这将告诉Android加载浏览器应用程序和dataURL。即使安装了多个浏览器应用程序,这也应绕过选择器对话框。而且,没有选择器对话框,您不必担心应用程序陷入拦截/重新广播同一Intent的无限循环。
您必须在用户的浏览器中打开URL(您不想处理的URL)。如果您想让其他非浏览器应用程序也有机会打开链接,则此解决方案将无法使用,因为没有选择器对话框。
据我所知,使用此解决方案的唯一怪癖是,当用户单击您的深层链接之一时,他们将选择在应用程序或浏览器中打开。当他们选择您的应用程序和内部应用程序逻辑意识到这是一个不想拦截的URL,用户会立即看到浏览器。因此,他们选择了您的应用,但显示了浏览器。
注意:当我在此答案中说“广播”时,是指一般术语,而不是实际的Android系统功能。
There is a somewhat hacky way of doing this:
m.somewhere.com, to open a specific deeplink handler activity.ACTION_VIEW intent to be opened by your browser. The problem here, is that your app will also catch this intent, and this will create an infinite loop if your app is selected as the default handler for that URL. The solution is to use PackageManager.setComponentEnabledSetting() to disable your deeplink handler Activity before you send that intent, and re-enable it after.Some example code:
public class DeepLinkHandlerActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
Uri uri = intent.getData();
Intent intent = makeInternallySupportedIntent(uri);
if (intent == null) {
final PackageManager pm = getPackageManager();
final ComponentName component = new ComponentName(context, DeepLinkHandlerActivity.class);
pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
Intent webIntent = new Intent(Intent.ACTION_VIEW);
webIntent.setData(uri);
context.startActivity(webIntent);
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void[] params) {
SystemClock.sleep(2000);
pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
return null;
}
};
task.execute();
} else {
startActivity(intent);
}
finish();
}
}
Run Code Online (Sandbox Code Playgroud)
Hope that helps.
Note: It looks like you need to delay the re-enabling by a couple of seconds for this to work.
Note 2: For a better experience, using a Transparent theme for your activity will make it look like your app didn't even open.
Note 3: If for some reason your app crashes or gets killed before the component re-registers, you're loosing deep link support forever (or until next update/reinstall), so I would also do the component re-enabling in App.onCreate() just in case.
小智 1
URX 提供了一个免费工具 (urxlinks.js),如果安装了应用程序,该工具会自动将移动网络用户重定向到该应用程序。该文档可在此处获取:http://developers.urx.com/deeplinks/urx-links.html#using-urx-links-js
| 归档时间: |
|
| 查看次数: |
4234 次 |
| 最近记录: |