Android navigate back to Application from Android Settings

Viewed 7250

I am having an inconsistent user experience due to the way android navigates back from Android Settings.

In my application the user needs to give my app access to ACTION_USAGE_ACCESS_SETTINGS, which I access with the following:

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

After toggling the setting to on for my application, I need the user to return to my application. The only way to do this that I know of is for them to press the back button on the phone ( would love to know if it is possible to return automatically after the setting has been toggled!!!?!).

Now one of two things will happen:

1) The user has not used android settings recently, so it was not already open ( ie open in the open app drawer). The first press of the back button will take them to my application as desired.

2) The user had used android settings recently. Thus settings was already open in the application drawer. Now when the user presses back, Android will take them back through each setting page they had been using recently (ie the back button takes them through their history in the android settings pages). It may take 2, 3 or 4 presses of the back button to leave Android settings, and return to my application. This is obviously terrible UI/UX, and I was wondering if there is a better way?

I have noticed that when installing Google apps, after toggling the setting to ON, it automatically exits and returns to the application that called the setting. Being able to do that would be ideal, but I just cant work it out.

Thanks!

8 Answers

Extending upon Ufkoku's answer, I used a periodic check on the status of the permission. To get the user back, I used startActivityForResult and finishActivity.

Sample Code : I used this for the "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)

The solution from @Geordie Wicks was close to what I was looking for, but it seems like having the Android Settings open before launching your intent would cause the back button to take you to the previous Android Settings screen.

My solution involves two more flags, Intent.FLAG_ACTIVITY_CLEAR_TOP and Intent.FLAG_ACTIVITY_CLEAR_TASK.

You can define your intent as below:

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

From my experience, this will make it so that a back button press will take you back to your application regardless of whether or not the Android Settings were open beforehand.

You can do one thing here. you have to confirm that you only open the settings component that you require to be opened .... Do not open the main settings app. Open only a single component within settings app that you want. So in that way when ever you will press back, you will jump back to your application.

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");

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

This is also the simplest way to navigate it

Sorry if the answer was late but I left my answer here for others to overcome this problems. To me the problems might be ourself not from Android. For e.g I have a listener, which listen to the state of the switch

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

What happened with this code?

The user go to Setting and then navigate back. If you have set something that update the UI like belows here after user go back, then this will cause multiple listener listen to the change of 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

My solution

You may add this line inside the listener, this will remove the current switch listener, which can avoid go to Setting after and after when switch change.

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

I know that this is just my personal solution, but if you share similar ways, this might be help.

Related