Android 应用程序链接与启动相同活动的多个域

com*_*eak 2 android intentfilter android-manifest android-intent applinks

这是我的AndroidManifest.xml文件

<activity
    android:name=".activity.LaunchActivity"
    android:autoVerify="true"
    android:configChanges="orientation|keyboardHidden|screenSize|screenLayout"
    android:label="@string/app_name"
    android:noHistory="true">
    <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:host="subdomain1.domain.ext"
            android:path="/path1/subpath1/.*"
            android:scheme="https" />
    </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:host="subdomain1.domain.ext"
            android:pathPattern="/path2/subpath2/..*"
            android:scheme="https" />
    </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:host="subdomain2.subdomain1.domain.ext"
            android:pathPattern="^..*"
            android:scheme="https" />
    </intent-filter>
</activity>
<activity
    android:name=".activity.LoginActivity"
    android:configChanges="orientation|keyboardHidden|screenSize|screenLayout"
    android:label="@string/app_name" />
<activity
    android:name=".activity.MainActivity"
    android:configChanges="orientation|keyboardHidden|screenSize|screenLayout"
    android:label="@string/app_name" />
Run Code Online (Sandbox Code Playgroud)

我想使用 2 个域的 Android 应用程序链接,

  1. 子域名1.域名.ext
  2. 子域2.子域1.域.ext

我已经将 assetlinks.json 文件放置在两个位置

subdomain1.domain.ext/.well-known/assetlinks.json

subdomain2.subdomain1.domain.ext/.well-known/assetlinks.json
Run Code Online (Sandbox Code Playgroud)

但是在使用 Android Studio 安装应用程序时,我在 apache 服务器的访问日志中没有看到任何对这两个文件的命中

请注意,我使用的是发布构建变体,它使用与在 assetlinks.json 中生成 SHA256 指纹相同的密钥库文件。

当我使用诸如以下的链接进行测试时

https://subdomain1.domain.ext/path1/subpath1/

https://subdomain2.subdomain1.domain.ext/path2
Run Code Online (Sandbox Code Playgroud)

只有较低的一个启动应用程序,前一个只是在浏览器中打开。所以看起来最后一行代码(第二个主机)是为应用程序链接设置的。

Qn 1 . 如何在具有相同活动的不同主机上打开两个路径/链接?就我而言,如何使第一个链接也打开该应用程序?

Qn 2 . 我想限制打开应用程序中的某些链接,我尝试将此正则表达式作为路径模式,但它不起作用。我知道它是一个球体,有什么办法可以做到这一点吗?

android:pathPattern="^(?!foo|bar)..*$"
Run Code Online (Sandbox Code Playgroud)

排除以 foo 和 bar 开头但允许其他链接路径。

我想打开

example.com in web browser
example.com/test in web browser
example.com/test/temp in web browser
example.com/{anything else} in the app
Run Code Online (Sandbox Code Playgroud)

我阅读了有关此问题的其他 stackoverflow 帖子:

但我没有任何查询参数。我的情况与Android Deep linking中描述的情况非常相似,省略某些 url

Qn 3 . 对于定义此类应用程序链接(启动应用程序的 Web 链接)的意图过滤器的活动,是否强制要求包含 action=MAIN 和category=LAUNCHER?

<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Run Code Online (Sandbox Code Playgroud)

期待一些帮助。Android 团队不允许排除路径似乎很愚蠢,应该从 Apple 的服务器端文件中学习,该文件使用简单的 NOT 子句。

如果有帮助的话,这是 LaunchActivity 的 onCreate() 方法中的 java 代码

public class LaunchActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splashscreen);
        Intent intent = getIntent();
        if (intent != null) {
            Uri target = intent.getData();
            if (target != null && target.isHierarchical()) {
                String goal = intent.getDataString();
                List<String> params = target.getPathSegments();
                Log.d(TAG, "app uri : " + goal);
                Log.d(TAG, "app link : " + target.toString());
                Log.d(TAG, "path segments : " + params);
                if (target.toString().startsWith(MON_DOM)) {
                    if (searchString(AppLinksUtil.TARGET_URLS, target.toString())) {
                        Log.d(TAG, "Open TARGET Link in APP");
                    } else {
                        Log.d(TAG, "Open Excluded Link in Browser");
                        openLinkInChrome(LaunchActivity.this, goal);
                        finish();
                    }
                } else if (target.toString().startsWith(ENQ_DOM)) {
                    Log.d(TAG, "Exclude List : " + AppLinksUtil.ENQ_EXCLUDE_URLS);
                    if (searchString(AppLinksUtil.EXCLUDE_URLS, target.toString())) {
                        Log.d(TAG, "Open Excluded Link in Browser");
                        openLinkInChrome(LaunchActivity.this, goal);
                        finish();
                    } else {
                        Log.d(TAG, "Open Link in APP");
                    }
                }
            }
        } else {
            Log.d(TAG, "no intent");
        }
        appFlow();
    }
    ...
    public void openLinkInChrome(final Activity activity, String link) {
        Log.d(TAG, "Opening " + link + " in web browser");
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setPackage("com.android.chrome");
        try {
            activity.startActivity(intent);
        } catch (ActivityNotFoundException ex) {
            intent.setPackage(null);
            activity.startActivity(intent);
        }
    }
    public static boolean searchString(String[] arr, String targetValue) {
        for (String s : arr) {
            if (targetValue.startsWith(s))
                return true;
        }
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

com*_*eak 12

在尝试一些代码更改时我意识到

对于 1,同一域的子域没有通配符选项,支持多个域,用正确的路径模式将它们一个接一个地列出,解决了我面临的问题。

AndroidManifest.xml

<activity android:name="MainActivity">
<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" />
    <data android:host="subdomain1.example1.com" />
    <data android:host="subdomain2.example1.com" />
    <data android:host="subdomain3.example2.com" />
    <data android:path="/onlythis" />
    <data android:pathPrefix="/starter" />
    <data android:pathPattern="/prefix.*" />
    <data android:pathPattern="/.*suffix" />
</intent-filter>
</activity>
Run Code Online (Sandbox Code Playgroud)

对于2,排除路径目前还不可能,Google必须向Apple学习。

对于 3,可以链接任何活动,而不仅仅是 MAIN/LAUNCHER 活动。

应用程序链接代码不需要action=MAIN 和category=LAUNCHER,action=VIEW 以及category=DEFAULT 和BROWSABLE 是必需的且足够了。

因此,只要定义default和browsable以及action=VIEW,不同的域/子域就可以启动不同的活动