Android app for importing, organizing, installing, and restoring Mobile Legends skin script folders on Android 11+ devices.
The app replaces the older Python + ADB workflow with a native Kotlin/Jetpack Compose application. It uses:
- SAF (Storage Access Framework) to import folders from user-selected locations
- Shizuku to access the restricted
Android/data/com.mobile.legends/...path - Room to track imported scripts, installations, and backup metadata
- Internal app storage to safely store imported scripts and restore backups
- Import a skin script folder with the system folder picker
- Normalize several common script folder layouts during import
- Browse imported scripts in a Compose UI
- Preview an imported script's file tree
- Install files into the Mobile Legends assets directory through Shizuku
- Back up overwritten files before installation
- Restore the previous state for a completed installation
- Track script/install/restore state locally with Room
- Manage Shizuku connection and permission status from the Settings screen
The app installs files into the following Mobile Legends assets directory:
/storage/emulated/0/Android/data/com.mobile.legends/files/dragon2017/assets/
- Android 11+ (
minSdk = 30) - Shizuku installed and running
- Shizuku permission granted to this app
- A valid skin script folder to import
Because Android/data/... is restricted on modern Android versions, this app is designed around Shizuku rather than direct file access.
- Install and start Shizuku on your device using the method supported by your setup.
- Launch Skin Script Installer.
- Open Settings.
- Confirm that:
- Shizuku is running
- Permission is granted
- File Service is connected
- Go back to the script list.
- Tap + and pick a skin script folder.
- Open the imported script.
- Tap Install.
- If needed later, return to the same script and tap Restore.
The import flow mirrors the Python reference in docs/ref/skin_script.py.
During import, the app accepts a few script layouts and stores them in internal app storage under a normalized structure.
If the selected folder already contains:
Android/data/com.mobile.legends/files/dragon2017/assets
it is copied as-is.
If the selected folder does not contain the full Android/... path, the importer recursively searches for an Art folder.
When it finds one, it copies the parent of Art into the expected Mobile Legends assets path.
If neither of the above is found, the app treats the selected folder as raw asset content and wraps it inside the expected Mobile Legends assets path.
When you install a script, the app:
- Finds all files under the imported script's normalized assets directory
- Connects to the privileged Shizuku file service
- Checks whether each target file already exists on the device
- Backs up any file that would be overwritten
- Writes imported files into the Mobile Legends assets directory
- Records installation metadata in Room
When you restore a script, the app:
- deletes files that were newly added during install
- restores files that had been overwritten from the backup copy
- marks the installation as restored in the local database
- removes the backup directory for that installation
Imported data is kept in the app's internal storage.
filesDir/
├── scripts/<script-id>/
│ └── Android/data/com.mobile.legends/files/dragon2017/assets/...
└── backups/<installation-id>/
└── <relative-path-of-overwritten-files>
Room database file:
skin_script_installer.db
- Jetpack Compose UI
- Navigation between:
- Script list
- Script detail
- Settings
ImportScriptUseCaseInstallScriptUseCaseRestoreScriptUseCase
- Room entities:
SkinScriptInstallationInstalledFile
ScriptRepositoryas the main data access abstraction
ShizukuManagerhandles binder lifecycle, permission, and service bindingIFileService.aidldefines privileged file operationsFileServiceperforms read/write/delete/mkdir/exists operations under Shizuku
SkinScriptInstaller/
├── app/
│ ├── src/main/aidl/com/istarvin/skinscriptinstaller/IFileService.aidl
│ ├── src/main/java/com/istarvin/skinscriptinstaller/
│ │ ├── data/
│ │ ├── di/
│ │ ├── domain/
│ │ ├── service/
│ │ └── ui/
│ └── build.gradle.kts
├── docs/
│ ├── plan.md
│ ├── plan2.md
│ └── ref/skin_script.py
├── gradle/
├── build.gradle.kts
└── settings.gradle.kts
- Kotlin
- Jetpack Compose + Material 3
- Navigation Compose
- Hilt
- Room + KSP
- Coroutines / Flow
- Shizuku
- AndroidX DocumentFile (SAF)
- Android Studio
- Android SDK for the project's configured API levels
- JDK 21 for the Gradle daemon/toolchain in this repo
cd "/home/aj/AndroidStudioProjects/SkinScriptInstaller"
./gradlew :app:assembleDebugcd "/home/aj/AndroidStudioProjects/SkinScriptInstaller"
./gradlew tasks
./gradlew test
./gradlew :app:assembleDebug- Shows imported scripts
- Shows current status (
Not Installed,Installed,Restored) - Lets you import a new folder
- Lets you delete an imported script from local storage
- Shows import/install timestamps
- Shows install/restore state
- Shows a file tree preview
- Lets you install or restore
- Shows install/restore progress
- Shows whether Shizuku is available
- Shows whether permission is granted
- Shows whether the Shizuku file service is connected
- Lets you request permission or reconnect the file service
- The app currently targets the Mobile Legends assets path shown above.
- Shizuku is effectively required for the intended workflow on Android 11+.
- Imported scripts and backups are stored in internal app storage, so they are not meant for direct user file management.
- The importer is designed to handle common folder structures, but malformed or incomplete scripts may still fail to install correctly.
- This repository currently does not include a license file.
docs/plan.md- implementation plan and scopedocs/plan2.md- architecture summarydocs/ref/skin_script.py- original Python workflow that inspired the import logic
At the current repository state, a debug build succeeds with:
./gradlew :app:assembleDebugIf you want, the next improvement could be adding screenshots, an APK installation section, or a contributor-focused development guide.