Root设备上无法通过代码执行SU命令设置Immersive模式求助
Hey there! Let's break down why your immersive mode commands aren't working in the app even though they work in a terminal—the core issue is you're running those settings commands without root privileges in your Immersive class. Right now, they execute as your app's regular user account, which doesn't have permission to modify global system settings.
Since you're already using the libsuperuser library (you checked Shell.SU.available() in MainActivity), let's leverage that library to run your commands with root access properly. Here's how to fix this:
Step 1: Fix the Immersive Class to Use Root
First, update your Immersive class to use Shell.SU from libsuperuser instead of Runtime.exec(). We'll also fix the uninitialized Context (which would have caused a NullPointerException for your Toasts):
import android.content.Context; import android.widget.Toast; import eu.chainfire.libsuperuser.Shell; public class Immersive { private final Context ctx; // Pass a valid Context through the constructor public Immersive(Context context) { this.ctx = context; } public void setImmersiveFull() { String command = "settings put global policy_control immersive.full=apps,-com.google.android.googlequicksearchbox"; // Execute command with root via libsuperuser Shell.SU.run(command, new Shell.OnCommandResultListener() { @Override public void onCommandResult(int commandCode, int exitCode, String[] output) { if (exitCode == 0) { Toast.makeText(ctx, "Full Immersive Mode Set", Toast.LENGTH_SHORT).show(); } else { // Show error if command fails (check output array for debug info) Toast.makeText(ctx, "Failed to enable Full Immersive Mode", Toast.LENGTH_SHORT).show(); } } }); } public void setImmersiveNoNavBar() { String command = "settings put global policy_control immersive.navigation=apps,-com.google.android.googlequicksearchbox"; Shell.SU.run(command, new Shell.OnCommandResultListener() { @Override public void onCommandResult(int commandCode, int exitCode, String[] output) { if (exitCode == 0) { Toast.makeText(ctx, "No Navigation Bar Immersive Mode Set", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(ctx, "Failed to hide Navigation Bar", Toast.LENGTH_SHORT).show(); } } }); } public void setImmersiveNoStatusBar() { String command = "settings put global policy_control immersive.status=apps,-com.google.android.googlequicksearchbox"; Shell.SU.run(command, new Shell.OnCommandResultListener() { @Override public void onCommandResult(int commandCode, int exitCode, String[] output) { if (exitCode == 0) { Toast.makeText(ctx, "No Status Bar Immersive Mode Set", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(ctx, "Failed to hide Status Bar", Toast.LENGTH_SHORT).show(); } } }); } public void setStockMode() { String command = "settings put global policy_control immersive="; Shell.SU.run(command, new Shell.OnCommandResultListener() { @Override public void onCommandResult(int commandCode, int exitCode, String[] output) { if (exitCode == 0) { Toast.makeText(ctx, "Stock Mode Set", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(ctx, "Failed to reset to Stock Mode", Toast.LENGTH_SHORT).show(); } } }); } }
Step 2: Update setScreenActivity to Pass Context
Modify your button click listener to pass a valid Context when instantiating Immersive:
btnFull.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Pass the activity's Context to the Immersive class Immersive im = new Immersive(setScreenActivity.this); im.setImmersiveFull(); } });
Why This Works
- Root Privileges:
Shell.SU.run()executes the command in a root shell, just like when you runsufirst in your terminal emulator. This gives the command the necessary permissions to modify global system settings. - Reliable Session Management: The
libsuperuserlibrary handles root session creation and maintenance better than rawRuntime.exec("su"), which can have issues with session persistence on some devices. - Error Handling: The
OnCommandResultListenerlets you check if the command succeeded (exit code 0) or failed, making debugging easier.
Additional Notes
- Make sure your
libsuperuserdependency is correctly added to your project (inbuild.gradle):implementation 'eu.chainfire:libsuperuser:1.0.0' - Some devices may require a launcher restart or system reboot for immersive mode changes to take full effect.
- If commands still fail, check the
outputarray in the listener—it will contain error messages from the root shell to help diagnose issues.
内容的提问来源于stack exchange,提问作者Malerosa




