Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android navigate back to Application from Android Settings

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!

like image 278
Geordie Wicks Avatar asked Nov 23 '17 00:11

Geordie Wicks


4 Answers

Ok, so after trying about a millions things, I have come up with 3 different ways to improve my problem.

1) Was provided by @CommonsWare, by removing the FLAG_ACTIVITY_NEW_TASK, it prevented an inconsistent number of back presses needed, and means every time the user would only have to press back twice.

2) Upon further research into the flags, I found that using three combined:

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

reduced the number of back presses required to 1 single back press. This is simple and reasonable user friendly.

3) Using a handler to continuously check for the required permission after the settings intent has fired. This seems a like a bit of a hack, and I can't believe there is not a better way to do this, but it works exactly as it works when using a Google App. Ie, as soon as you switch the toggle to on, it exits the Android Settings page, and returns to your application, where you left off. I am using:

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

Then when you fire the intent to get to the Android settings page, just be sure to start the handler:

handler.postDelayed(checkSettingOn, 1000);

Hope this helps someone else with a similar issue.

like image 112
Geordie Wicks Avatar answered Nov 16 '22 10:11

Geordie Wicks


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.

like image 44
Jose Jaime Avatar answered Nov 16 '22 09:11

Jose Jaime


After you have started Settings activity you can run periodical task, that is invoked every, for example 500ms, and checks if permission is granted.
Mark your setup activity with flag singleTask/singleInstance, and start it, if permission is granted. Existing instance of activity will be moved to top.

I did this for notifications access permission.

like image 2
Ufkoku Avatar answered Nov 16 '22 10:11

Ufkoku


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)
like image 1
Daniyal Abbasi Avatar answered Nov 16 '22 11:11

Daniyal Abbasi