deeplink
Deeplinks are important aspects of the app which makes our app accessible using certain links and push notifications and are generally key to the company’s marketing strategy.It is vital in connecting our web ecosystem with that of application’s.
深层链接是应用程序的重要方面,它使我们的应用程序可以使用某些链接和推送通知进行访问,并且通常是公司营销策略的关键。对于将我们的网络生态系统与应用程序的网络生态联系起来,至关重要。
让我们解决这个问题 (Let's Address the problem)
As your app keeps on growing so does deeplinks based on your market requirements. when it comes to our java/kotlin classes we tend to follow various principles (SOLID etc) to keep code separated and to prevent our classes from becoming so-called “GOD” class but what about your manifest?
随着您的应用程序不断增长,基于您的市场需求的深层链接也会不断增长。 当涉及到我们的java / kotlin类时,我们倾向于遵循各种原理(SOLID等)以使代码分开并防止我们的类成为所谓的“ GOD”类,但是您的清单呢?
To address the Problem consider your app supports a single deeplink for that particular deep link you would have to cater to both HTTP and HTTPS schemes in order to successfully upload your apk to the play store.
要解决该问题,请考虑您的应用为该特定深层链接支持单个深层链接,您必须同时满足HTTP和HTTPS方案,才能成功将apk上传到Play商店。
<data
android:host="www.xyz.xyz"
android:pathPrefix="/home"
android:scheme="http" />
<data
android:host="www.xyz.xyz"
android:pathPrefix="/home"
android:scheme="https" />
No Problem, Not bad so far… we will put two <data>
entries for our path and we are done easy enough.
没问题,到目前为止还算不错……我们将在路径中放置两个<data>
条目,并且操作起来很容易。
But one fine day your company decides to launch globally to let's say 4 more countries and support 4 different languages (with a localized path like {locale}/home/
) now that would be a problem, Come to think of it you will have to add 2*4*4 ie, 32 <data>
entries for a single pathPrefix
and this is just an example, Paths can easily increase the number of </data>
entries depending on the structure of the path itself which can variate from case to case. 🤕
但是,有一天,您的公司决定在全球范围内推出更多的国家/地区,并支持4种不同的语言 (使用{locale}/home/
的本地化路径) 现在这将成为一个问题,想一想,您将必须为单个pathPrefix
添加2 * 4 * 4,即32个 <data>
条目,这仅是示例,Paths可以轻松增加</data>
的数量</data>
条目取决于路径本身的结构,该结构可能因情况而异。 🤕
现在怎么办? (What Now?)
As we know domains, locale or whatever that leads to new </data>
entry beforehand, So let’s try and come up with a script that takes the path and makes the </data>
entry in the manifest for us.
我们知道域,语言环境或任何会导致新</data>
条目的内容,所以让我们尝试提出一个脚本,该脚本采用路径并在清单中创建</data>
条目。
了解生成的清单文件 (Understanding generated Manifest file)
It is absolutely important to keep in mind that the generated manifest file is different for both APK and Bundle.
请务必牢记,APK和Bundle生成的清单文件是不同的。
给我看看代码! (Show me the code!!)
Create a separate Gradle file for keeping your deeplink configurations. let's say ‘
deeplink_config.gradle
’.创建一个单独的Gradle文件以保留您的Deeplink配置。 我们说“
deeplink_config.gradle
”。Add the following to your
build.gradle
file将以下内容添加到您的
build.gradle
文件中
apply from: 'deeplink_config.gradle'
3. Add a variable in the manifest file which will be replaced by </data>
tags inside your intent-filter
.
3.在清单文件中添加一个变量,该变量将由intent-filter
</data>
标签替换。
<intent-filter
android:autoVerify="true"
tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
deepLinkPlaceholder
</intent-filter>
4. Add code to deeplink_config
to generate </data>
for bothHTTP
and HTTPS
scheme.
4.将代码添加到deeplink_config
为HTTP
和HTTPS
方案生成</data>
。
ext {
listOfDeepLinkUrls = new ArrayList<String>()
listOfDeepLinkUrls.add("/home")
locales = ["en", "ar","es","hi-IN"]
}
ext.generateData = { host, listOfDeepLinkUrls, locales,listOfDomains ->
String links = ""
listOfDeepLinkUrls.each{ item ->
links += data(item,host)
locales.each{ locale ->
listOfDomains.each { domain ->
links += data("/"+locale.replace("_","-")+item,domain)
}
}
}
return links
}
static def data(String path, String host) {
return http(path,host) + https(path,host)
}
static def http(String path, String host) {
return "\n" +
" <data\n" +
" android:host=\"$host\"\n" +
" android:pathPrefix=\"$path\"\n" +
" android:scheme=\"http\"/>\n"
}
static def https(String path, String host) {
return "\n" +
" <data\n" +
" android:host=\"$host\"\n" +
" android:pathPrefix=\"$path\"\n" +
" android:scheme=\"https\"/>\n"
}
generateData method takes in your host
, listOfDeepLinkUrls
, locales
(depends on your use case) and list of domains
ex: [“www.xyz.in"].
generateData方法接收host
, listOfDeepLinkUrls
, locales
(取决于您的用例)和list of domains
例如:[ “ www.xyz.in” ]。
where listOfDeepLinkUrls
is storing all our pathsPrefixes.
So, to add a new deeplink to your application you just need to add it to the list rather than adding multiple <data>
manually inside the manifest
.
其中listOfDeepLinkUrls
存储我们所有的pathsPrefixes.
因此,要将新的深层链接添加到您的应用程序,只需要将其添加到列表中,而不是在manifest
手动添加多个<data>
。
5. Write these generated <data>
to your apk and bundle generated manifest files as discussed earlier apk and bundle both have their separate manifest files and to write to those we would need a path to these generated files.
5.将这些生成的<data>
写入您的apk,然后将这些生成的清单文件写到您的apk中,如前所述,apk和bundle都有各自的清单文件,要写入这些文件,我们需要这些生成文件的路径。
manifestOutputDirectory
can be used directly for getting the path to Apk’s manifest file but I was not able to find one for bundles so let's utilizemanifestOutputDirectory
to extract path of bundle’s manifest file.
manifestOutputDirectory
可以直接用于获取Apk清单文件的路径,但是我无法为bundle找到一个,因此让我们利用manifestOutputDirectory
提取捆绑清单文件的路径。
android.applicationVariants.all { variant ->
variant.outputs.all { output ->
output.processManifest.doLast {
def placeholders = variant.mergedFlavor.manifestPlaceholders;
if (placeholders == null || placeholders.isEmpty()) {
return
}
def manifestDirPath = manifestOutputDirectory.asFile.get()
String manifestMergerpath = "$manifestDirPath/AndroidManifest.xml"
def link = manifestDirPath.toString()
link = link.replace("merged_manifests","bundle_manifest")
def productFlavor = link.split("/bundle_manifest/").getAt(1)
def upper = productFlavor.capitalize()
productFlavor = "process$upper" +"Manifest"
link = link + "/$productFlavor/bundle-manifest/AndroidManifest.xml"
writeManifest(manifestMergerpath,placeholders)
writeManifest(link,placeholders)
}
}
}
def writeManifest(String manifestPath,HashMap placeholders){
def manifestContent = file(manifestPath).getText()
placeholders.each { key, value ->
if(key.equals("deepLinkPlaceholder")) {
Pattern pattern = Pattern.compile(Pattern.quote("deepLinkPlaceholder"), Pattern.DOTALL);
manifestContent = pattern.matcher(manifestContent).replaceAll(value);
}
}
file(manifestPath).write(manifestContent)
}
FYI: There could be a better way to extract out bundle’s manifest path. I would be happy to discuss if you have any idea. 😃
仅供参考:可能会有更好的方法来提取包的清单路径。 如果您有任何想法,我很乐意讨论。 😃
6. After making all the changes inside deeplink_config.gradle
file lets put it to use, Inside build.gradle
call generateData()
within defined productFlavors
of your app in order to pass a list of domains
as required by this method.If you need to insert variables into your AndroidManifest.xml
file that are defined in your build.gradle
file, you can do so with the manifestPlaceholders
property. This property takes a map of key-value pairs.
6.在deeplink_config.gradle
进行所有更改之后 该文件可以使用,在build.gradle
内部调用应用程序的定义productFlavors
的generateData()
,以传递此方法所需list of domains
如果需要在定义的AndroidManifest.xml
文件中插入变量在build.gradle
文件中,您可以使用manifestPlaceholders
属性来实现。 此属性获取键值对的映射。
productFlavors {
appin {
manifestPlaceholders = [hostName: "www.xyz.in", deepLinkPlaceholder: generateData("www.xyz.in", listOfDeepLinkUrls, locales, ["www.xyz.in"])]
}
appza {
manifestPlaceholders = [hostName: "www.xyz.co.za", deepLinkPlaceholder: generateData("www.xyz.co.za", listOfDeepLinkUrls, locales, ["www.xyz.co.za"])]
}
}
7. To test the generated <data>
you can put a print(links)
at the end of the generateData()
additionally, you can analyze the apk or maybe open the generated manifest file as shown above.
7.要测试生成的<data>
,可以另外在generateData()
的末尾放置一个print(links)
,可以分析apk或打开生成的清单文件,如上所示。
结论 (Conclusion)
I hope this post will help you in registering your deeplinks dynamically and will make your life a lot easier in the process. Reach out to me if you think somethings can be handled even better.
希望这篇文章能帮助您动态注册深层链接,并使您的生活变得更加轻松。 如果您认为某些事情可以做得更好,请与我联系。
“The way we know things is not the way we report we know things.”
“我们了解事物的方式不是我们报告我们了解事物的方式。”
if you want to contribute to this project you can fork it to your repo.
如果您想为这个项目做贡献,可以将其添加到您的仓库中。
翻译自: https://medium.com/swlh/generating-deeplinks-dynamically-in-android-ebe503e7241f
deeplink