【问题标题】:Open intent from URL using Java Script is not working on production - DeepLink使用 Java 脚本从 URL 中打开意图不适用于生产 - DeepLink
【发布时间】:2015-11-17 12:26:37
【问题描述】:

我这里有个小秘密,我的 onCreate 方法中有这段代码:

    Intent intent = getIntent();

    if (Intent.ACTION_VIEW.equals(intent.getAction())) {
        Log.i(TAG, "ACTION_VIEW START");
        Uri uri = intent.getData();

        SharedPreferences.Editor tEditor = getSharedPreferences("UserFormPreferences", MODE_PRIVATE).edit();

        tEditor.putString("GuestRoomNumber", uri.getQueryParameter("h"));
        tEditor.putString("GuestSurname", uri.getQueryParameter("a"));
        tEditor.apply();
        //it shows an alert to the user
        GuestLogin(uri.getQueryParameter("h"), uri.getQueryParameter("a")); 
        Log.i(TAG, "ACTION_VIEW END");
    }

我的清单中有这段代码:

    <activity
        android:name="epinom.jm.smarthotel.vcMainScreen"
        android:label="@string/title_activity_home"
        android:launchMode="standard"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="epinom.jm.smarthotel.vcMainScreen" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <intent-filter>
            <data android:scheme="com.guestperience" />
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

我正在从一个网页执行这个 JS:

window.location = "com.guestperience://?h=x&a=x";

有趣的部分来了Chrome 中具有 JS 指令的页面,它会打开我的应用程序并使用我期望的 onCreate 和 onStart 方法打开意图,并将其添加到我的应用程序中的意图堆栈中,这意味着如果我有任何意图应用程序和我执行 JS,应用程序出现在前面,它创建意图并执行它应该执行的操作并向用户显示警报。

但是,如果我拔掉插头或使用我在 Beta 版 Play 商店中拥有的 .apk,则此功能不起作用,而且我不明白其中的区别,因为对我来说是相同的代码,所以这是当我没有连接到 Android Studio 时会发生什么:

  • 如果应用程序关闭,我单击链接,它会打开 Chrome 并启动应用程序,应用程序的第一个意图与我调用的相同,执行它应该执行的操作并显示警报。
  • 一旦应用打开,如果我重复这些步骤,它就永远不会显示意图,无论我是处于初始意图还是其他意图中。

我尝试将代码更改为 onStart 但它几乎是相同的行为:

  • 如果应用程序关闭,我点击链接,它会打开 Chrome 并启动应用程序,应用程序的第一个意图与我调用的相同,做它应该做的事情并显示警报。
  • 一旦应用程序打开,如果我重复这些步骤,它只会在我处于主要意图时显示警报(与我正在调用的相同),如果我处于另一个意图中,它永远不会显示意图,但是如果我导航到意图,则每次调用它时都会显示警报。 (在每个 onStart 上,都可以使用 bool 来控制)。

最后,我不明白为什么当我插入 Android Studio 时行为会有所不同。

也许是我缺少一些权限或者我必须配置的东西,但我迷路了。

任何帮助将不胜感激。

谢谢。

更新 1:

我已经检测到这个:

  • 如果我插上电话并按下播放键并保持插头,一切都会像魅力一样发挥作用。
  • 如果我插上电话并按下播放键并拔下插头,一切都会像魅力一样发挥作用。
  • 如果我插入手机并按播放并关闭应用程序(插头可以插入或不插入),如果我使用链接启动应用程序就像一个魅力,但如果应用程序启动停止任何意图的工作。

Android Studio 正在做一些事情让它工作,我认为它必须有权限,但我真的迷路了。

更新 2:

我已经尝试了此示例的所有选项,但结果仍然相同.

  <!-- Allow web apps to launch Barcode Scanner by linking to http://zxing.appspot.com/scan. -->
  <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="guestperience.com" android:path="/Main"/>
  </intent-filter>
  <!-- Support zxing://scan/?... like iPhone app -->
  <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="com.guestperience" android:host="Main" android:path="/"/>
  </intent-filter>

我已尝试将其附加到启动器意图,但似乎没有任何效果。

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

我已尝试从 href 启动应用程序,以查看是否需要用户操作并且结果仍然相同。

<a href="intent://Main/#Intent;scheme=com.guestperience;package=epinom.jm.smarthotel;end"> CLICK HERE TO LOGIN </a>

https://developer.chrome.com/multidevice/android/intents

https://github.com/zxing/zxing/blob/master/android/AndroidManifest.xml

更新 3:

我添加了这个来跟踪应用打开后调用的操作:

Log.i(TAG, intent.getAction().toString()); 

如果我第一次打开我的应用程序,则值为:

"com.guestperience://Main/"

但如果我打开另一个意图并再次通过链接打开应用程序,结果是我调用的最后一个操作,即:

"epinom.jm.smarthotel.vcMainScreen"

当然,如果我用 Android Studio 打开应用程序,我总是会得到这个值:

"com.guestperience://Main/"

因为所有应用程序都可以通过 JSON 文件进行配置,所以我的所有活动都有意图过滤器,所以我所有的调用都是这样的:

Intent tIntent = new Intent("epinom.jm.smarthotel.vcMainScreen"); //replacing this "epinom.jm.smarthotel.vcMainScreen" with the JSON string var of course
startActivity(tIntent);
finish();

我也读过这篇文章,据我所知,我没有遗漏任何东西:

http://developer.android.com/intl/es/training/app-indexing/deep-linking.html

【问题讨论】:

  • 据我所知,Android Studio 应该像启动器一样启动您的应用程序。
  • @Nanoc 我需要特殊权限才能从浏览器打开我的意图吗?
  • 不是深度链接专家,但我知道谷歌最近改变了你从 url 调用意图的方式,所以如果我没有错,你有不同的方法来做这件事,具体取决于浏览器。看看developer.chrome.com/multidevice/android/intents
  • @Nanoc 感谢您的链接,它为我打开了很多知识,并引导我解决了这个谜团

标签: java android android-studio deep-linking


【解决方案1】:

在做了很多测试和大量阅读之后,我已经完成了一个扩展 Activity 的基类,并且我的 Main Activity 从 Base Activity 扩展。

public class BaseActivity extends Activity {

}

public class vcMainScreen extends BaseActivity {

}

然后在 Base Activity 的 onStart() 上,我添加了这段代码来处理来自浏览器的调用:

@Override
protected void onStart() {
    super.onStart();
    Intent intent = getIntent();

    if (Intent.ACTION_VIEW.equals(intent.getAction())) {
        Uri uri = intent.getData();

        SharedPreferences.Editor tEditor = getSharedPreferences("UserFormPreferences", MODE_PRIVATE).edit();

        tEditor.putString("GuestRoomNumber", uri.getQueryParameter("h"));
        tEditor.putString("GuestSurname", uri.getQueryParameter("a").replace("/",""));
        tEditor.apply();

        Intent tIntent = new Intent("epinom.jm.smarthotel.vcMainScreen");
        tIntent.putExtra("Login", "true");
        startActivity(tIntent);
        finish();
    }
}

如您所见,它在 onStart() 中调用了 Main Activity,我添加了以下几行来调用我的登录方法:

@Override
protected void onStart() {
    super.onStart();

    if (getIntent().getExtras() != null && getIntent().getExtras().getString("Login") != null && getIntent().getExtras().getString("Login").equals("true")) {
        SharedPreferences tPrefs = getSharedPreferences("UserFormPreferences", MODE_PRIVATE);

        GuestLogin(tPrefs.getString("GuestRoomNumber", ""), tPrefs.getString("GuestSurname", ""));
        getIntent().putExtra("Login", "false");
    }
}

并且在清单中我添加了以下代码:

<activity
    android:name="epinom.jm.smarthotel.BaseActivity"
    android:label="@string/title_activity_home"
    android:launchMode="singleTask"
    android:screenOrientation="portrait">
    <intent-filter>
        <data android:scheme="com.guestperience" android:host="Main" android:path="/"/>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

<activity
    android:name="epinom.jm.smarthotel.vcMainScreen"
    android:label="@string/title_activity_home"
    android:launchMode="standard"
    android:screenOrientation="portrait">
    <intent-filter>
        <action android:name="epinom.jm.smarthotel.vcMainScreen" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Base Activity 有一个 launchMode="singleTask" 很重要,并且最后我必须使用这样的 URL:

<a href="intent://Main/?h=1&a=surname/#Intent;scheme=com.guestperience;package=epinom.jm.smarthotel;end"> CLICK HERE TO LOGIN </a>

我正在使用这个 GIT 来处理我的 DeepLink 并进行了一些更改:

https://github.com/hampusohlsson/browser-deeplink

我确定这不是正确的做法,但我希望这对将来的人有所帮助。

祝大家编码愉快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-18
    • 2016-11-03
    • 2019-05-28
    • 2016-11-08
    • 1970-01-01
    • 2012-05-31
    相关资源
    最近更新 更多