Android 从 Android 设置导航回应用程序

Android navigate back to Application from Android Settings

由于 android 从 Android 设置返回的方式,我的用户体验不一致。

在我的应用程序中,用户需要授予我的应用程序访问 ACTION_USAGE_ACCESS_SETTINGS 的权限,我通过以下方式访问它:

Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

为我的应用程序将设置切换为打开后,我需要用户return 到我的应用程序。据我所知,这样做的唯一方法是让他们按下 phone 上的后退按钮(很想知道是否可以在切换设置后自动 return!!! ?!)。

现在会发生以下两种情况之一:

1) 用户最近未使用android设置,因此尚未打开(即在打开的应用程序抽屉中打开)。第一次按下后退按钮将根据需要将它们带到我的应用程序。

2) 用户最近使用了 android 设置。因此设置已经在应用程序抽屉中打开。现在,当用户按下返回键时,Android 将带他们返回他们最近使用过的每个设置页面(即返回按钮带他们进入 android 设置页面中的历史记录)。可能需要按 2、3 或 4 次后退按钮才能保留 Android 设置,并 return 到我的应用程序。这显然很糟糕UI/UX,我想知道是否有更好的方法?

我注意到在安装 Google 应用程序时,将设置切换为 ON 后,它会自动退出并 returns 到调用该设置的应用程序。能够做到这一点是最理想的,但我就是做不出来。

谢谢!

你可以在这里做一件事。你必须确认你只打开了你需要打开的设置组件....不要打开主设置应用程序。在您想要的设置应用程序中仅打开一个组件。这样一来,只要您按下返回键,就会跳回到您的应用程序。

For example if i want to open bluetooth settings in settings application, I wont open the main Settings app instead i will open only bluetooth component of settings. In that way when i press back i will return to my own app because i haven't open the main setting app so i do not need to navigate in it.

ComponentName cn = new ComponentName("com.android.settings", 
                   "com.android.settings.bluetooth.BluetoothSettings");

您必须确认您只打开了您需要打开的应用设置。不要打开主设置应用程序。仅打开您想要的应用程序设置。这样一来,只要您按下后退键,您就会跳回到您的应用程序。

Uri uri = Uri.fromParts("package", getPackageName(), null);
Intent intent = new Intent();                            
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(uri);
startActivity(intent);

启动设置后activity您可以运行周期性任务,每隔(例如 500 毫秒)调用一次,并检查是否已授予权限。
使用标志 singleTask/singleInstance 标记您的设置 activity,并在获得许可后启动它。 activity 的现有实例将移至顶部。

我这样做是为了获得通知访问权限。

好的,在尝试了大约一百万种方法之后,我想出了 3 种不同的方法来改善我的问题。

1) 由@CommonsWare 提供,通过删除 FLAG_ACTIVITY_NEW_TASK,它防止了所需的不一致的后退次数,这意味着每次用户只需按两次后退。

2) 在进一步研究标志后,我发现使用三个组合:

Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                    intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                    startActivity(intent);

将所需的背压次数减少到 1 次背压。这样简单合理,用户友好。

3) 在触发设置意图后,使用处理程序持续检查所需的权限。这看起来有点像 hack,我不敢相信没有更好的方法来做到这一点,但它的工作原理与使用 Google 应用程序时完全一样。即,一旦您将开关切换到打开状态,它就会退出 Android 设置页面,并 returns 返回您的应用程序,即您离开的地方。我正在使用:

Handler handler = new Handler();

Runnable checkSettingOn = new Runnable() {

    @Override
    //@TargetApi(23)
    public void run() {
        Log.d(TAG, "run: 1");
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            Log.d(TAG, "run: 2");
            return;
        }
        if (isAccessGranted()) {
            Log.d(TAG, "run: 3");
            //You have the permission, re-launch MainActivity
            Intent i = new Intent(MainActivity.this, MainActivity.class);
            Log.d(TAG, "run: 4");
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            startActivity(i);
            return;
        }
        handler.postDelayed(this, 200);
    }
};

然后,当您触发进入 Android 设置页面的意图时,请务必启动处理程序:

handler.postDelayed(checkSettingOn, 1000);

希望这对遇到类似问题的其他人有所帮助。

Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent);

这也是最简单的导航方式

根据 Ufkoku 的回答,我对权限状态进行了定期检查。为了让用户回来,我使用了 startActivityForResult 和 finishActivity。

示例代码:我将其用于“USAGE_ACCESS_SETTINGS”。

var intent = Intent("android.settings.USAGE_ACCESS_SETTINGS")
intent.data = Uri.fromParts("package", "com.example.app", null)
startActivityForResult(intent,101)

var timer = Timer(true)
timer.scheduleAtFixedRate(object: TimerTask(){
    override fun run(){
        if(checkUsageAccessPermission()){ // checkUsageAccessPermission() is a helper function
            finishActivity(101)
            cancel()                    
        }
    }
}, 0, 1000)

来自@Geordie Wicks 的解决方案与我正在寻找的很接近,但似乎在启动 intent 之前打开 Android 设置会导致后退按钮将您带到上一个 Android 设置屏幕。

我的解决方案涉及另外两个标志,Intent.FLAG_ACTIVITY_CLEAR_TOPIntent.FLAG_ACTIVITY_CLEAR_TASK

您可以定义您的 intent 如下:

Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                startActivity(intent);

根据我的经验,无论 Android 设置是否事先打开,这将使按下后退按钮将带您返回您的应用程序。

抱歉,如果回答晚了,但我把我的答案留在这里供其他人解决这个问题。对我来说,问题可能出在我们自己身上,而不是来自 Android。例如我有一个监听器,它监听开关的状态

setOnCheckedChangeListener { _, _ ->
                val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                intent.data =
                    Uri.fromParts(
                        "package",
                        navigator.activeFragment?.activity?.packageName,
                        null
                    )
                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK

                navigator.activeFragment?.startActivity(intent)
            }

这段代码发生了什么?

用户转到“设置”,然后返回。如果你在用户返回后设置了一些更新 UI 的东西,那么这将导致多个监听器监听 switch

的变化
    override fun onResume() {
    super.onResume()
    if (!isFirst) {
        // Notify that user might have change the notification setting
        (binding.rvSetting2.adapter as SettingAdapter).notifyItemChanged(0)
    }
    isFirst = false

我的解决方案

你可以在listener中添加这一行,这样会移除当前的switch监听器,这样就可以避免switch变化时去setting after和after。

                setOnCheckedChangeListener { _, _ ->
                val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                intent.data =
                    Uri.fromParts(
                        "package",
                        navigator.activeFragment?.activity?.packageName,
                        null
                    )
                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK

                navigator.activeFragment?.startActivity(intent)

                // Remove the current listener in case of user went back from Setting and call on bind view holder again
                // This cause multiple listener listen to the change of this switch
                setOnCheckedChangeListener(null)
            }

我知道这只是我个人的解决方案,但如果您分享类似的方法,这可能会有所帮助。