You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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 run su first in your terminal emulator. This gives the command the necessary permissions to modify global system settings.
  • Reliable Session Management: The libsuperuser library handles root session creation and maintenance better than raw Runtime.exec("su"), which can have issues with session persistence on some devices.
  • Error Handling: The OnCommandResultListener lets you check if the command succeeded (exit code 0) or failed, making debugging easier.

Additional Notes

  • Make sure your libsuperuser dependency is correctly added to your project (in build.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 output array in the listener—it will contain error messages from the root shell to help diagnose issues.

内容的提问来源于stack exchange,提问作者Malerosa

火山引擎 最新活动