Ссылки приложений Android с несколькими доменами, запускающими одно и то же действие

Это мой 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" />

Я хочу использовать ссылки на приложения Android для двух доменов,

  1. subdomain1.domain.ext
  2. subdomain2.subdomain1.domain.ext

Я уже разместил файл assetslinks.json на обоих

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

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

Но при установке приложения с помощью Android Studio я не вижу обращений ни к одному из файлов в журналах доступа сервера apache.

Обратите внимание, что я использую вариант сборки выпуска, в котором используется тот же файл хранилища ключей, который использовался для создания отпечатка пальца SHA256 в assetslinks.json.

Когда я тестирую такие ссылки, как

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

https://subdomain2.subdomain1.domain.ext/path2

Только нижняя запускает приложение, первая просто открывается в браузере. Таким образом, кажется, что последняя строка кода (второй хост) настроена для ссылки на приложение.

Вопрос 1. Как открыть два пути/ссылки на разных хостах с одинаковой активностью? В моем случае, как я могу сделать так, чтобы первая ссылка также открывала приложение?

Вопрос 2. Я хочу ограничить открытие некоторых ссылок в приложении, я попробовал это регулярное выражение в качестве шаблона пути, но это не сработало. Я знаю, что это глобус, можно ли как-то это сделать?

android:pathPattern="^(?!foo|bar)..*$"

чтобы исключить пути ссылок, которые начинаются с 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

Я прочитал другие сообщения stackoverflow об этом:

Но у меня нет параметров запроса. Моя ситуация очень похожа на ту, что описана в разделе Android Deep linking, опускающий определенный URL-адрес.

Вопрос 3. Является ли обязательным, чтобы действие, в котором определен фильтр намерений для таких ссылок на приложения (приложение, запускающее веб-ссылку), содержало action=MAIN и category=LAUNCHER?

<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

С нетерпением жду помощи. Со стороны команды Android кажется таким глупым не разрешать исключать пути, которые должны были узнать из файла Apple на стороне сервера, в котором используется простое предложение NOT.

Если это поможет, это код Java в методе onCreate() LaunchActivity.

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;
    }
}

person computingfreak    schedule 25.08.2017    source источник


Ответы (2)


Попробовав некоторые изменения кода, я понял, что

Для 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>

Для версии 2 исключение путей пока невозможно, Google должен учиться у Apple.

Для 3 можно связать любую активность, а не только ГЛАВНУЮ/ЗАПУСКНУЮ.

action=MAIN и category=LAUNCHER не требуются для кода связывания приложения, action=VIEW вместе с category=DEFAULT и BROWSABLE необходимы и достаточны.

Следовательно, разные домены/субдомены могут запускать разные действия, если значения по умолчанию и возможность просмотра определены вместе с action=VIEW.

person computingfreak    schedule 30.08.2017

pathPattern не поддерживает все функции регулярных выражений. Он поддерживает только "*" и ".*". Вот и все.

См. описание pathPattern в https://developer.android.com/guide/topics/manifest/data-element.html

Атрибут pathPattern указывает полный путь, который соответствует полному пути в объекте Intent, но может содержать следующие подстановочные знаки:

  • Звездочка ('*') соответствует последовательности 0 множеству вхождений непосредственно предшествующего символа.
  • Точка, за которой следует звездочка ("".*"), соответствует любой последовательности от 0 до многих символов.

См. также https://developer.android.com/reference/android/os/PatternMatcher.html#PATTERN_SIMPLE_GLOB


Вы можете иметь столько <intent-filter>, сколько хотите для данного <activity>. Поскольку вы не можете использовать регулярные выражения для описания различных URL-адресов, просто создайте отдельное <intent-filter> описание для каждого URL-адреса.

person David Wasser    schedule 25.08.2017
comment
как насчет + вместо ? я где-то читал, что мы должны использовать .. вместо .+, это правда? - person computingfreak; 27.08.2017