I want to take an apk selected by the user (selection system is done), and then decode it into it’s resources using Apktool.
The decoded apk must then be reverted back to an apk, be resigned and be installable
The problem I am facing is that Apktool.jar cannot be used without root access as a terminal command (java command) is used normally to execute the decoding process. Can I use apktool.jar’s code directly within my app so that this process can be done without root.
I have seen similar apps decoding and changing apks although never seen there implementations, closest thing I can think of is Lucky patcher (the old patcher to get free purchases in games).
other Apps that preform these functionalities do exist although I am not sure if they require root…
// Just a heads up my project is not a native android project (it’s a flutter project) but I have
// sort of figured out native handling so you can give your answer as a native app (kotlin or java)
// Although if you have tips or info regarding my scenario please do mention those too
I have currently only tried running through calling commands (P.S this is kotlin code but might be kinda crptic since it’s embedded in a flutter project) also this isnt my actual code it’s a similar idea I constructed with AI since my code is too long, the exact details of the code are negligible…
import android.os.Bundle
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import java.io.File
class MainActivity: FlutterActivity() {
private val CHANNEL = "com.example.apktool"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
call, result ->
if (call.method == "decodeApk") {
val apkFilePath = call.arguments<String>()
val outputPath = decodeApk(apkFilePath)
if (outputPath != null) {
result.success(outputPath)
} else {
result.error("UNAVAILABLE", "Decoding failed", null)
}
} else {
result.notImplemented()
}
}
}
private fun decodeApk(apkFilePath: String): String? {
return try {
val apkToolCommand = "java -jar ${filesDir.absolutePath}/libs/apktool.jar d -f $apkFilePath -o ${filesDir.absolutePath}/decoded_apk"
val process = Runtime.getRuntime().exec(apkToolCommand)
process.waitFor()
val outputPath = File(filesDir, "decoded_apk")
if (outputPath.exists()) outputPath.absolutePath else null
} catch (e: Exception) {
e.printStackTrace()
null
}
}
}
2
Answers
Try the following 5 steps for help.
Step 1: Copy apktool_x.x.x.jar to your project directory (e.g. project_name/app/libs/) and add dependency in /app/build.gradle.
Step 2: Sync project with gradle files.
Step 3: Take a look at sidebar or toolbar on Android Studio, find ‘Project‘ and tap it then collapse all the items but ‘External Libraries‘.
Step 4: Find the item named like ‘Gradle: :apktool_x.x.x.jar‘ and locate the file by path /brut/apktool/Main.class. Double click to decompile this class file.
Step 5: Copy the content you like to your code, modify and enjoy!
Handle Permissions
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
your public class must be look like this…
You can call the decodeApk() method from an activity or service in your app. Ensure the APK file path and output directory are correctly
specified.
File apkFile = new File("/path/to/apkfile.apk"); File outputDir = new File(getExternalFilesDir(null), "decoded_apk");
ApkDecoder.decodeApk(apkFile, outputDir);