Mus*_*lar 8 facebook deep-linking applinks ios-universal-links deeplink
有太多深层链接(通用链接或应用链接)教程.但其中大多数都展示了如何在Android或IOS应用中启用它.此外还有付费云解决方案,但它们提供了许多功能.但是我在现实生活中面临三个主要问题:
我写了这个Q&A,这是我学习的结果(花了太多时间),以便有一个独特的,适用于所有案例的解决方案.
代码来自我的工作解决方案,但我删除了一些部分只是为了表明这个想法.如果存在一些编译问题,请按照算法编写自己的代码
这是解决方案,即使你知道一些步骤也要一步一步,因为代码中有技巧.还有一些解释在代码部分的注释行中,请阅读它们.
示例是使用最终的参数处理Android和IOS应用程序的深层链接http://example.com/v/,例如http://example.com/v/id-of-user?key=value.
1.配置Android
1.1将活动信息添加到AndroidManifest.xml文件中:
<activity
android:name=".appLinkHandlerActivity">
<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:host="example.com"
android:pathPrefix="/v/"
android:scheme="http" />
</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" />
<!—this intent is needed to handle links to myapp://share, I will explain later why we need it -->
<data
android:host="share"
android:scheme="myapp" />
</intent-filter>
Run Code Online (Sandbox Code Playgroud)
1.2创建名为appLinkHandlerActivity的活动,该活动将处理单击的链接
public class appLinkHandlerActivity extends AppCompatActivity {
/* assume that user is clicked http://example.com/v/my-user-id
actCode will be “v”, pCode will be “my-user-id” */
String actCode="", pCode="";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ATTENTION: This was auto-generated to handle app links.
Intent appLinkIntent = getIntent();
String appLinkAction = appLinkIntent.getAction();
Uri appLinkData = appLinkIntent.getData();
String code = null;
try {
code = getIntent().getData().getLastPathSegment();
} catch (Exception e) {
}
if (code == null) {
Intent i = new Intent(this, {your main activity.class});
startActivity(i);
}
List<String> params=appLinkData.getPathSegments();
if (params.size()>0)
actCode=params.get(0);
if (params.size()>=2)
pCode=params.get(1);
/* assume that user is clicked http://example.com/v/my-user-id actCode is “v”, pCode is “my-user-id” Do now whatever you need. */
}
}
Run Code Online (Sandbox Code Playgroud)
2.配置IOS
这比Android更复杂,我将在这里解释必要的要点.请参阅文档:https: //developer.apple.com/library/content/documentation/General/Conceptual/AppSearch/UniversalLinks.html#//apple_ref/doc/uid/TP40016308-CH12-SW1
https://www.raywenderlich.com/128948/universal-links-make-connection
2.1在Apple Developer Portal上创建App ID时,您必须启用Associated Domains.重要问题:您需要购买Apple开发者帐户才能启用此选项,这意味着无需购买开发者帐户,就无法在IOS项目上尝试使用AppLinks.
2.2在XCode项目中,打开"Capabilites"选项卡并将Associated Domains切换为On.如果您未在Apple Developer Portal App ID部分中启用Associated Domains,则可能无法选择通过单击Associated Domains选项下的+按钮添加权利,请写入"applinks:example.com".
2.3在您的Web服务器上创建一个名为"apple-app-site-association"的文件,该文件必须通过https://example.com/apple-app-site-association访问HTTPS是强制性的,如果它不是有效的SSL证书App Link可能无法正常工作.将以下行添加到apple-app-site-association文件中:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "6HY7TF56.com.example.app",
"paths": [ "/ios/*", "/v/*" ]
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
appID是{"团队ID"."应用程序的捆绑ID"}的格式.您可以在Developer Portal的"成员身份详细信息"部分下找到您的teamID.
我们处理链接http://example.com/v/parameters,但是在这里您可以看到"/ ios/*"的另一个路径配置.需要绕过不支持的浏览器,我稍后会解释.
2.4在AppDelegate.m文件中添加两个方法来处理用户在example.com上的点击
-(BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler{
if ([userActivity.activityType isEqualToString: NSUserActivityTypeBrowsingWeb]) {
NSURL *url = userActivity.webpageURL;
[self parseUrl:url];
}
return YES;
}
- (void) parseUrl:(NSURL * )handledUrl {
NSString *urlStr=@"";
NSString *pCode=@"";
NSString *handledUrlStr=[handledUrl parameterString];
NSString *handledUrlQueryPart;
NSArray<NSString *> *pathsArray= [handledUrl pathComponents];
//remember that we only added paths “/v/*” and “/ios/*” to handle in apple-app-site-association file. If you want to handle more subpaths you can add them into apple-app-site-association file, then below if-else conditions. Don’t touch to config and code for “/ios/*” path, it is needed to bypass unsopported browsers.
if ([pathsArray[1] isEqual: @"v"]){
//sample url= http://example.com/v/menu?aaa=bbb
pCode = pathsArray[2];
handledUrlQueryPart=[handledUrl query];
} else if ([pathsArray[1] isEqual: @"ios"]){
//sample url= http://example.com/ios/deeplink-ios.php?/v/menu?aaa=bbb
NSArray *uriArray = [[handledUrl query] componentsSeparatedByString:@"?"];
NSArray *queryPathsArray = [uriArray[0] componentsSeparatedByString:@"/"];
if ([queryPathsArray count] > 2)
pCode = queryPathsArray[2];
if ([uriArray count] > 1 ){
handledUrlQueryPart=uriArray[1];
}
}
/* here pCode is the parameter what is passed from user. If the link clicked is http://example.com/v/menu it is “menu”. If the link clicked is http://example.com/v/menu?aaa=bbb it is “menu?aaa=bbb”. So you can do now what ever you need. */
}
Run Code Online (Sandbox Code Playgroud)
3.管理令人不快的点击.
3.1好的,您的Android和IOS应用程序应该处理链接http://example.com/v/blabla上的点击,并将"blabla"参数传递给我展示的方法中使用的pCode变量.但是像Facebook应用程序这样的浏览器可能会禁用App Links.在这种情况下,用户单击将转到您的Web服务器,浏览器会尝试显示http://example.com/v/blabla的内容,该内容可能是404 Page Not Found.为了处理这些点击,我们将配置Apache Web服务器并将用户重定向到您的应用程序.如果您使用IIS或其他,我不知道如何操作,但您可以将其作为示例并使用相同的algortihm来配置您的Web服务器.
3.2在example.com根目录的.htaccess文件中写下以下行
#redirect to deeplink
<IfModule mod_rewrite.c>
#if there is a request to example.com/v/any-sub-path, redirect them to example.com/deeplink.php file. This rule is for both IOS and Android
RewriteRule ^(v)/.* /deeplink.php [L]
#if there is a request to example.com/ios/any-sub-path, redirect them to app installation page. That means your app is not installed on IOS device. This rule is for IOS devices only
RewriteRule ^(ios)/.* http://itunes.apple.com/install-of-your-app [L]
</IfModule>
Run Code Online (Sandbox Code Playgroud)
4.将用户重定向到应用程序
4.1步骤3中显示的.htaccess文件中的重定向规则将用户重定向到deeplink.php文件.以下是将用户重定向到您的应用程序的文件内容.
<?php
$request_uri=$_SERVER[REQUEST_URI];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
if(stripos($ua,'android') == true){
//if user device is android, redirect it to intent url which is handled by Android.
$redir_tag="<meta http-equiv='refresh' content='0;url=intent://share$request_uri/#Intent;scheme=myapp;S.browser_fallback_url=http%3A%2F%2Fexample.com%2Fget-app%2F;package=com.example.app;end' />";
//scheme=myapp and host named “share” is configured in AndroidManifest.xml file to be handled by the activity.
//fallback url is the url, if your app is not installed on android device, so you can redirect them to a page to install android app. In some cases users are redirected to Play Store directly for application id of com.example.app
}
else if ( (stripos($ua,'iPhone') == true) || (stripos($ua,'iPad') == true) ) {
//if user device is IOS, redirect them to a web page to see. There will be a link here to the another handled link: http://example.com/ios/blabla.
// due to my experience there is no way to redirect IOS to app directly at this stage, user must click a link on browser and that link must be different than the link which was shown and clicked at first.
// another experience taught me ther ecan be problems if we redirect users to a web page under example.com which is configured as applink, so I redirect users to a page under deep.example.com here
$redir_tag="<meta http-equiv='refresh' content='0;url=http://deep.example.com/deeplink-ios.php?$request_uri' />";
}
else {
//If the device is neither IOS nor Android, redirect users to a web page which gives information that this link is for Android and IOS only
$redir_tag="<meta http-equiv='refresh' content='0;url=http://example.com/non-mobile' />";
}
?>
<html>
<head>
<!— add tags for no-caching, this is important, the date below is my son’s birth time and date, he is now 6, so you can use it as a date in the past -->
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="-1" />
<meta http-equiv="expires" content="Tue, 31 May 2011 10:15:00 GMT+3" />
<meta http-equiv="pragma" content="no-cache" />
<?php echo $redir_tag; ?>
</head>
</html>
Run Code Online (Sandbox Code Playgroud)
5.向IOS用户显示单击链接
5.1以下是http://deep.example.com/deeplink-ios.php文件的内容.用户将看到如下页面,当他们点击链接时,该请求应由您的IOS应用程序处理.
<?php
//we create a link to http://example.com/ios/… which is configure to be handled by IOS app. IOS needs to be a user click in some cases to handle the request, that is why this page is shown to the user
$request_uri=$_SERVER[REQUEST_URI];
$link="<div class='w3-container w3-card'><h1><a href='http://example.com/ios$request_uri'>Click here to open MyApp</a></h1></div>";
?>
<html>
<head>
<!—adding no-cache tags is also important here-->
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="-1" />
<meta http-equiv="expires" content="Tue, 31 May 2011 10:15:00 GMT+3" />
<meta http-equiv="pragma" content="no-cache" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3mobile.css">
</head>
<body>
<?php echo $link ?>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
6.案例分析:
6.1 Android
6.1.1案例1 - 应用程序安装在设备上
•浏览器请求http://example.com/v/blabla•Android
捕获链接并创建清单文件中配置的活动
6.1.2案例2 - 应用程序安装在设备上
•浏览器请求http://example.com/v/blabla•Android
无法捕获链接.
•浏览器连接到Web服务器,请求/ v/blabla
•由于.htaccess文件中的配置,它被重定向到deeplink.php?/ v/blabla
•deeplink.php得知它是android,并重定向到:intent:// share/v/blabla/#Intnt; scheme = myapp; S.browser_fallback_url = http%3A%2F%2Fexample.com%2Fget-app%2F; package = com.example.app
•Android捕获for意图的请求: //,所以由于清单文件中的配置,myapp:// share/v/blabla由活动处理
6.1.3案例3 - 未安装应用程序
•浏览器请求http://example.com/v/blabla•Android
无法捕获链接.
•浏览器连接到Web服务器,请求/ v/blabla
•由于.htaccess文件中的配置,它被重定向到deeplink.php?/ v/blabla
•deeplink.php得知它是android,并重定向到:intent:// share/v/blabla/#Intnt; scheme = myapp; S.browser_fallback_url = http%3A%2F%2Fexample.com%2Fget-app%2F; package = com.example.app
•Android捕获for意图的请求: //,但没有为id:com.example.app安装应用程序.在某些情况下,它会将浏览器重定向并重定向到您的应用的http://example.com/get-app或Play商店安装页面
6.2 IOS
6.2.1案例1 - 应用程序安装在设备上
•浏览器请求http://example.com/v/blabla•IOS
捕获链接并调用AppDelegate.m中的continueUserActivity方法
6.2.2案例2 - 应用程序安装在设备上
•浏览器请求http://example.com/v/blabla•IOS
无法捕获链接.
•浏览器连接到Web服务器,请求/ v/blabla
•由于.htaccess文件中的配置,它被重定向到deeplink.php?/ v/blabla
•deeplink.php得知它是IOS,并重定向到:http:// deep.example.com/deeplink-ios.php?/v/blabla•deeplink-ioos.php
文件显示用户的URL.URL为:http://lify.me/ios/v/blabla•
用户点击URL,浏览器请求http://lify.me/ios/v/blabla•IOS
因路径配置而捕获请求/ ios/*"在apple-app-site-association文件中并调用AppDelegate.m中的continueUserActivity方法
•如果IOS因任何原因无法捕获http://lify.me/ios/v/blabla的请求,它将表现为设备上未安装应用程序.看那个案子.
6.2.3案例2 - 设备上未安装应用程序
•浏览器请求http://example.com/v/blabla•IOS
无法捕获链接.
•浏览器连接到Web服务器,请求/ v/blabla
•由于.htaccess文件中的配置,它被重定向到deeplink.php?/ v/blabla
•deeplink.php得知它是IOS,并重定向到:http:// deep.example.com/deeplink-ios.php?/v/blabla•deeplink-ioos.php
文件显示用户的URL.URL为:http://lify.me/ios/v/blabla•
用户点击URL和浏览器请求http://lify.me/ios/v/blabla•
如果IOS无法捕获http的请求://lify.me/ios/v/blabla•
浏览器连接到Web服务器,请求/ ios/v/blabla
•它被重定向到http://itunes.apple.com/install-of-your-app到期在Web服务器上的.htaccess文件中进行配置
6.3在非Android或IOS设备上单击App Link
•浏览器请求http://example.com/v/blabla•
设备操作系统无法捕获链接.
•浏览器连接到Web服务器,请求/ v/blabla
•由于.htaccess文件中的配置,它被重定向到deeplink.php?/ v/blabla
•deeplink.php得知它既不是IOS也不是IOS,并重定向到:http ://example.com/non-mobile