gpt4 book ai didi

Android Web Intent 问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:58:38 26 4
gpt4 key购买 nike

你好,

免责声明:我不是 Android 开发人员,我正在使用我描述的问题对 Android 应用程序进行质量检查。我用来描述这个问题的技术术语可能是错误的。

我正在测试一个 Android 应用程序,该应用程序在其 list 中描述它可以处理类型为 https://www.example.com/app/(.*) 的网络 Intent 。它应该处理这些 URL 的方式是获取第一个匹配组 $1 并向 https://api.example.com/$1 发送请求,如果响应是 HTTP200,它在应用程序内呈现响应。如果没有,它应该在用户安装在其设备上的任何浏览器应用程序中打开 URL(通过发送打开 URL 的 Intent )。如果用户没有在他们的设备上安装浏览器应用程序,我们会显示一条错误提示,说明他们没有安装可以处理此 URL 的浏览器。

现在,这工作正常,除非用户将此应用程序标记为默认处理 URL,如 https://www.example.com/app/(.*) 当它第一次尝试打开像 https://www.example.com/app/(.*) 这样的 URL。然后,即使用户在他们的系统上安装了浏览器应用程序,当他们打开需要在浏览器中打开的链接时,唯一的选择似乎是我们原来的应用程序,我们必须显示错误消息(看起来就像系统上没有安装可以处理此 URL 的其他浏览器应用程序一样)。

解决这个问题的一种方法是,当我们遇到需要在浏览器应用程序中打开的 URL 但唯一的选择是我们自己的应用程序时,显示一条消息要求用户清除此应用程序的默认设置——但这很糟糕用户体验。这个问题还有其他解决方法吗?

了解问题的示例代码:https://gist.github.com/GVRV/5879fcf0b1838b495e3a2151449e0da3

编辑 1:添加示例代码链接

最佳答案

要解决此问题并保持系统对 Intent 的默认处理,您需要 2 个额外的 Activity 和 1 个 <activity-alias> :

  1. 创建一个新的不可见的空 Activity。我将其称为 IntentFilterDelegationActivity。此 Activity 负责从 activity-alias 接收 URL Intent (在下一步中定义)。 list :

    <activity
    android:name=".intent_filter.IntentFilterDelegationActivity"
    android:excludeFromRecents="true"
    android:exported="true"
    android:launchMode="singleInstance"
    android:noHistory="true"
    android:taskAffinity=""
    android:theme="@style/Theme.Transparent"/>

代码:

public class IntentFilterDelegationActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
findAndStartMatchingActivity(getIntent());
finish();
}
}
  1. 创建 <activity-alias> . Activity 别名负责将您的 URL Intent 委托(delegate)给您的 IntentFilterDelegationActivity .只需要一个 Manifest 条目:

    <activity-alias
    android:name="${packageName}.IntentFilterDelegation"
    android:enabled="true"
    android:exported="true"
    android:targetActivity=".intent_filter.IntentFilterDelegationActivity">
    <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="www.example.com"/>
    </intent-filter>
    </activity-alias>
  2. 现在您可以使用技巧了:您可以停用 activity-alias在启动您自己的 URL Intent 之前,并在启动后激活别名。这会导致 android 您的应用程序不会被列为可以处理 URL Intent 的应用程序。要实现激活和停用,您需要一个额外的 Activity 。我叫它ForceOpenInBrowserActivity . list :

    <activity
    android:name=".activity.ForceOpenInBrowserActivity"
    android:excludeFromRecents="true"
    android:launchMode="singleInstance"
    android:noHistory="true"
    android:taskAffinity=""
    android:theme="@style/Theme.Transparent"/>

代码:

        public class ForceOpenInBrowserActivity extends Activity
{
public static final String URI = IntentUtils.getIntentExtraString(ForceOpenInBrowserActivity.class, "URI");

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

Uri uri = fetchUriFromIntent();
if (uri != null)
{
startForcedBrowserActivity(uri);
}
else
{
finish();
}
}

@Nullable
private Uri fetchUriFromIntent()
{
Uri uri = null;

Intent intent = getIntent();
if (intent != null)
{
uri = intent.getParcelableExtra(URI);
}

return uri;
}

private void startForcedBrowserActivity(Uri uri)
{
disableActivityAlias(this);

Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

// After starting another activity, this activity will be destroyed
// android:noHistory="true" android:excludeFromRecents="true"
startActivity(intent);
}

/**
* Re-enable intent filters when returning to app.
* Note: The intent filters will also be enabled when starting the app.
*/
@Override
protected void onStop()
{
super.onStop();
enableActivityAlias();
}

public void disableActivityAlias()
{
String packageName = getPackageName();
ComponentName componentName = new ComponentName(packageName, packageName + ".IntentFilterDelegation"); // Activity alias
getPackageManager().setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
}


public void enableActivityAlias()
{
String packageName = getPackageName();
ComponentName componentName = new ComponentName(packageName, packageName + ".IntentFilterDelegation");
getPackageManager().setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}
}
  1. 现在您可以将任何必须在外部浏览器中打开的 URL Intent 发送到 ForceOpenInBrowserActivity :

    @NonNull
    public static Intent createForceBrowserIntent(Context context, @NonNull Uri uri)
    {
    Intent intent = new Intent(context, ForceOpenInBrowserActivity.class);
    intent.setAction(Intent.ACTION_VIEW);
    intent.putExtra(ForceOpenInBrowserActivity.URI, uri);
    return intent;
    }

关于Android Web Intent 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37849431/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com