Opening Android Settings Programmatically

Opening Android Settings programmatically

I used the code from the most upvoted answer:

startActivityForResult(new Intent(android.provider.Settings.ACTION_SETTINGS), 0);

It opens the device settings in the same window, thus got the users of my android application (finnmglas/Launcher) for android stuck in there.

The answer for 2020 and beyond (in Kotlin):

startActivity(Intent(Settings.ACTION_SETTINGS))

It works in my app, should also be working in yours without any unwanted consequences.

Open specific Settings-page programmatically

I managed to find the correct answer in an old Stackoverflow-post from a while back. The code snippet now looks like this:

Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
startActivity(intent);

Android Programmatically open Settings- Security tab on Button Click

Try this instead:

        Intent intent = new Intent(Settings.ACTION_SECURITY_SETTINGS);

startActivity(intent);

Programmatically open 'About device' page in Settings correctly?

The main point is it seems impossible. Let's look at what is the reason.

The DeviceInfoSettingsActivity can be opened by an intent call like:

Intent intent = new Intent(android.provider.Settings.ACTION_DEVICE_INFO_SETTINGS);
startActivity(intent);

or

Intent intent = new Intent();
intent.setClassName(
"com.android.settings",
"com.android.settings.Settings$DeviceInfoSettingsActivity"
);
startActivity(intent)

As you can see here:

https://android.googlesource.com/platform/packages/apps/Settings/+/master/src/com/android/settings/Settings.java

Settings and all of its inner classes are children of SettingsActivity. By taking a look at source code of SettingsActivity, we found out it is possible to show a sub-settings, passing the fragment name as an intent extra with key ":settings:show_fragment" to the SettingsActivity:

SettingsActivity#onCreate() then SettingsActivity#launchSettingFragment()

If we dig into logs where the target screen is shown, we'd see that the target fragment name is com.samsung.android.settings.deviceinfo.SoftwareInfoSettings.

But the problem is that there is a check on fragment names at SettingsActivity#isValidFragment() which allows specific fragments to navigate to and they are SettingsGateway#ENTRY_FRAGMENTS:

protected boolean isValidFragment(String fragmentName) {
// Almost all fragments are wrapped in this,
// except for a few that have their own activities.
for (int i = 0; i < SettingsGateway.ENTRY_FRAGMENTS.length; i++) {
if (SettingsGateway.ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
}
return false;
}

The alternative for showing other fragments in settings is to open SubSettings activity which overrides the isValidFragment to accepts every fragment.

@Override
protected boolean isValidFragment(String fragmentName) {
Log.d("SubSettings", "Launching fragment " + fragmentName);
return true;
}

That is exactly what happens when the SoftwareInfoSettings is shown:

D/Settings: packageName : com.android.settings className : com.android.settings.SubSettings
D/SubSettings: Launching fragment com.samsung.android.settings.deviceinfo.SoftwareInfoSettings

Unfortunately, starting the SubSettings from uid except launcher's uid isn't possible, because it is not an exported activity to be visible from the outside:

AndroidManifest.xml:

<activity android:name=".SubSettings"
android:parentActivityName="Settings"
android:theme="@style/Theme.SubSettings"/>

If you try to run:

Intent intent = new Intent();
intent.setClassName(
"com.android.settings",
"com.android.settings.SubSettings"
);
intent.putExtra(
":settings:show_fragment",
"com.samsung.android.settings.deviceinfo.SoftwareInfoSettings"
);
startActivity(intent);

will see this error log:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.aminography.settingsapp, PID: 14566
java.lang.SecurityException: Permission Denial:
starting Intent { flg=0x10000000 cmp=com.android.settings/.SubSettings (has extras) }
from ProcessRecord{fac1d09 14566:com.aminography.settingsapp/u0a104} (pid=14566, uid=10104)
not exported from uid 1000

Unfortunately, since isValidFragment() and SettingsGateway#ENTRY_FRAGMENTS are parts of the platform, not your application's runtime, it's impossible to change them even with reflection.

How to open Settings panel in Android Q programmatically?

This is very simple and easy to implement using Settings panel API available in Android Q.

Simple we need to trigger intent with one of the new Settings.Panel actions.

To open Internet Connectivity Panel:

Sample Image

Java:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Intent panelIntent = new Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY)
startActivityForResult(panelIntent, 545)
}

Kotlin:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val panelIntent = Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY)
startActivityForResult(panelIntent, 545)
}


To open Volume control panel:

Sample Image

Java:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Intent panelIntent = new Intent(Settings.Panel.ACTION_VOLUME)
startActivityForResult(panelIntent, 545)
}

Kotlin:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val panelIntent = Intent(Settings.Panel.ACTION_VOLUME)
startActivityForResult(panelIntent, 545)
}


To open WIFI panel:

Sample Image

Java:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Intent panelIntent = new Intent(Settings.Panel.ACTION_WIFI)
startActivityForResult(panelIntent, 545)
}

Kotlin:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val panelIntent = Intent(Settings.Panel.ACTION_WIFI)
startActivityForResult(panelIntent, 545)
}


To open NFC panel:

Sample Image

Java:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Intent panelIntent = new Intent(Settings.Panel.ACTION_NFC)
startActivityForResult(panelIntent, 545)
}

Kotlin:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val panelIntent = Intent(Settings.Panel.ACTION_NFC)
startActivityForResult(panelIntent, 545)
}

Here you can check more about settings panel from Android official doc:

1) https://developer.android.com/preview/features#settings-panels

2) https://developer.android.com/reference/android/provider/Settings.Panel

Open Google backup settings page programmatically

I managed to open "Backup & Reset" screen using following function.

private void openBackUpAndReset(){
try {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.google.android.gms", "com.google.android.gms.backup.component.BackupSettingsActivity"));
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}

Which redirects to following screen.

Backup & Reset

I have Tested this on following devices:

  1. Samsung M51(Android 11)
  2. Pixel 3(Android 10)
  3. Poco C3(Android 10)
  4. Emulator(Android Lollipop)

Programmatically open a specific Android settings page without allowing the user to further navigate away from the application

The Intent mechanism is not totally fine-grained. As you can see from the question you linked, you can open Settings application easily. With the exception of the Location Settings page, Android Settings application is not designed to provide fine grained control so that you cannot step back to the main settings screen.

I have taken a look at source code, where you can find actions related to each settings page. In general, it could not be possible to isolate the user on a specific screen. For example, tablets show the entire settings navigation bar on the left.

Maybe you would like to tell us what settings page you want, and what settings you may want to edit. You might also think about using Android APIs to programmatically change some settings from your application, according to permissions.

How to open Android Settings App programmatically with Delphi?

Try something like this:

uses
Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.Provider, Androidapi.Helpers;

procedure TForm1.Button1Click(Sender: TObject);
var
LIntent: JIntent;
begin
LIntent := TJIntent.JavaClass.init(TJSettings.JavaClass.ACTION_SETTINGS);
LIntent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); // <-- this might be optional
TAndroidHelper.Context.startActivity(LIntent);
end;


Related Topics



Leave a reply



Submit