{"id":13482530,"url":"https://github.com/topjohnwu/libsu","last_synced_at":"2025-05-15T10:00:22.840Z","repository":{"id":37444269,"uuid":"118184739","full_name":"topjohnwu/libsu","owner":"topjohnwu","description":"A complete solution for apps using root permissions","archived":false,"fork":false,"pushed_at":"2024-06-28T04:48:17.000Z","size":24080,"stargazers_count":1850,"open_issues_count":7,"forks_count":368,"subscribers_count":88,"default_branch":"master","last_synced_at":"2025-04-11T19:56:36.711Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/topjohnwu.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-19T22:16:33.000Z","updated_at":"2025-04-11T10:17:36.000Z","dependencies_parsed_at":"2023-11-07T11:28:55.715Z","dependency_job_id":"7d3aff2d-e23a-435a-98fc-0e3b1b733978","html_url":"https://github.com/topjohnwu/libsu","commit_stats":{"total_commits":481,"total_committers":10,"mean_commits":48.1,"dds":0.07276507276507271,"last_synced_commit":"78c60dcecb9ac2047704324e161659a2ddb0f034"},"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/topjohnwu%2Flibsu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/topjohnwu%2Flibsu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/topjohnwu%2Flibsu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/topjohnwu%2Flibsu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/topjohnwu","download_url":"https://codeload.github.com/topjohnwu/libsu/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254319715,"owners_count":22051072,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T17:01:02.967Z","updated_at":"2025-05-15T10:00:21.559Z","avatar_url":"https://github.com/topjohnwu.png","language":"Java","funding_links":[],"categories":["Java","Java (504)"],"sub_categories":[],"readme":"# libsu\n\n[![](https://jitpack.io/v/topjohnwu/libsu.svg)](https://jitpack.io/#topjohnwu/libsu)\n\nAn Android library providing a complete solution for apps using root permissions.\n\n`libsu` comes with 2 main components: the `core` module handles the creation of the Unix (root) shell process and wraps it with high level, robust Java APIs; the `service` module handles the launching, binding, and management of root services over IPC, allowing you to run Java/Kotlin and C/C++ code (via JNI) with root permissions.\n\n## [Changelog](./CHANGELOG.md)\n\n## [Javadoc](https://topjohnwu.github.io/libsu/)\n\n## Download\n\n```groovy\nandroid {\n    compileOptions {\n        // The library uses Java 8 features\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n}\nrepositories {\n    maven { url 'https://jitpack.io' }\n}\ndependencies {\n    def libsuVersion = '6.0.0'\n\n    // The core module that provides APIs to a shell\n    implementation \"com.github.topjohnwu.libsu:core:${libsuVersion}\"\n\n    // Optional: APIs for creating root services. Depends on \":core\"\n    implementation \"com.github.topjohnwu.libsu:service:${libsuVersion}\"\n\n    // Optional: Provides remote file system support\n    implementation \"com.github.topjohnwu.libsu:nio:${libsuVersion}\"\n}\n```\n\n## Quick Tutorial\n\nPlease note that this is a quick demo going through the key features of `libsu`. Please read the full Javadoc and check out the example app (`:example`) in this project for more details.\n\n### Configuration\n\nSimilar to threads where there is a special \"main thread\", `libsu` also has the concept of the \"main shell\". For each process, there is a single globally shared \"main shell\" that is constructed on-demand and cached. Set default configurations before the main `Shell` instance is created:\n\n```java\npublic class SplashActivity extends Activity {\n\n    static {\n        // Set settings before the main shell can be created\n        Shell.enableVerboseLogging = BuildConfig.DEBUG;\n        Shell.setDefaultBuilder(Shell.Builder.create()\n            .setFlags(Shell.FLAG_MOUNT_MASTER)\n            .setInitializers(ShellInit.class)\n            .setTimeout(10));\n    }\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        showSplashScreen();\n        // As an example, preload the main root shell in the splash screen\n        // so the app can use it afterwards without interrupting application\n        // flow (e.g. waiting for root permission prompt)\n        Shell.getShell(shell -\u003e {\n            // The main shell is now constructed and cached\n            exitSplashScreen();\n        });\n    }\n}\n\n```\n\n### Shell Operations\n\n`Shell` operations can be performed through static `Shell.cmd(...)` methods that directly use the main root shell:\n\n```java\nShell.Result result;\n// Execute commands synchronously\nresult = Shell.cmd(\"find /dev/block -iname boot\").exec();\n// Aside from commands, you can also load scripts from InputStream.\n// This is NOT like executing a script like \"sh script.sh\", but rather\n// more similar to sourcing the script (\". script.sh\").\nresult = Shell.cmd(getResources().openRawResource(R.raw.script)).exec();\n\nList\u003cString\u003e out = result.getOut();  // stdout\nint code = result.getCode();         // return code of the last command\nboolean ok = result.isSuccess();     // return code == 0?\n\n// Async APIs\nShell.cmd(\"setenforce 0\").submit();   // submit and don't care results\nShell.cmd(\"sleep 5\", \"echo hello\").submit(result -\u003e updateUI(result));\nFuture\u003cShell.Result\u003e futureResult = Shell.cmd(\"sleep 5\", \"echo hello\").enqueue();\n\n// Run commands and output to specific Lists\nList\u003cString\u003e mmaps = new ArrayList\u003c\u003e();\nShell.cmd(\"cat /proc/1/maps\").to(mmaps).exec();\nList\u003cString\u003e stdout = new ArrayList\u003c\u003e();\nList\u003cString\u003e stderr = new ArrayList\u003c\u003e();\nShell.cmd(\"echo hello\", \"echo hello \u003e\u00262\").to(stdout, stderr).exec();\n\n// Receive output in real-time\nList\u003cString\u003e callbackList = new CallbackList\u003cString\u003e() {\n    @Override\n    public void onAddElement(String s) { updateUI(s); }\n};\nShell.cmd(\"for i in $(seq 5); do echo $i; sleep 1; done\")\n    .to(callbackList)\n    .submit(result -\u003e updateUI(result));\n```\n\n### Initialization\n\nOptionally, a similar concept to `.bashrc`, initialize shells with custom `Shell.Initializer`:\n\n```java\npublic class ExampleInitializer extends Shell.Initializer {\n    @Override\n    public boolean onInit(Context context, Shell shell) {\n        InputStream bashrc = context.getResources().openRawResource(R.raw.bashrc);\n        // Here we use Shell instance APIs instead of Shell.cmd(...) static methods\n        shell.newJob()\n            .add(bashrc)                  /* Load a script */\n            .add(\"export ENV_VAR=VALUE\")  /* Run some commands */\n            .exec();\n        return true;  // Return false to indicate initialization failed\n    }\n}\nShell.Builder builder = /* Create a shell builder */ ;\nbuilder.setInitializers(ExampleInitializer.class);\n```\n\n### Root Services\n\nIf interacting with a root shell is too limited for your needs, you can also implement a root service to run complex code. A root service is similar to [Bound Services](https://developer.android.com/guide/components/bound-services) but running in a root process. `libsu` uses Android's native IPC mechanism, binder, for communication between your root service and the main application process. In addition to running Java/Kotlin code, loading native libraries with JNI is also supported (`android:extractNativeLibs=false` **is** allowed). For more details, please read the full Javadoc of `RootService` and check out the example app for more details. Add `com.github.topjohnwu.libsu:service` as a dependency to access `RootService`:\n\n```java\npublic class RootConnection implements ServiceConnection { ... }\npublic class ExampleService extends RootService {\n    @Override\n    public IBinder onBind(Intent intent) {\n        // return IBinder from Messenger or AIDL stub implementation\n    }\n}\nRootConnection connection = new RootConnection();\nIntent intent = new Intent(context, ExampleService.class);\nRootService.bind(intent, connection);\n```\n\n##### Debugging Root Services\n\nIf the application process creating the root service has a debugger attached, the root service will automatically enable debugging mode and wait for the debugger to attach. In Android Studio, go to **\"Run \u003e Attach Debugger to Android Process\"**, tick the **\"Show all processes\"** box, and you should be able to manually attach to the remote root process. Currently, only the **\"Java only\"** debugger is supported.\n\n### I/O\n\nAdd `com.github.topjohnwu.libsu:nio` as a dependency to access remote file system APIs:\n\n```java\n// Create the file system service in the root process\n// For example, create and send the service back to the client in a RootService\npublic class ExampleService extends RootService {\n    @Override\n    public IBinder onBind(Intent intent) {\n        return FileSystemManager.getService();\n    }\n}\n\n// In the client process\nIBinder binder = /* From the root service connection */;\nFileSystemManager remoteFS;\ntry {\n    remoteFS = FileSystemManager.getRemote(binder);\n} catch (RemoteException e) {\n    // Handle errors\n}\nExtendedFile bootBlock = remoteFS.getFile(\"/dev/block/by-name/boot\");\nif (bootBlock.exists()) {\n    ExtendedFile bootBackup = remoteFS.getFile(\"/data/boot.img\");\n    try (InputStream in = bootBlock.newInputStream();\n         OutputStream out = bootBackup.newOutputStream()) {\n        // Do I/O stuffs...\n    } catch (IOException e) {\n        // Handle errors\n    }\n}\n```\n\n## License\n\nThis project is licensed under the Apache License, Version 2.0. Please refer to `LICENSE` for the full text.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftopjohnwu%2Flibsu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftopjohnwu%2Flibsu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftopjohnwu%2Flibsu/lists"}