skip to Main Content

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


  1. 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.

    dependencies {
        implementation fileTree(include: ['*.jar'], dir: 'libs')
    }
    

    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!

    Login or Signup to reply.
  2. It should be possible. please try this code, I didn’t tested yet. But i hope its work

    • 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…

    package com.pinankh.android;
    
    import java.util.Arrays;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.File;
    
    public class ApkDecoder {
    public static void decodeApk(File apkFile, File outputDir) {
        try {
            // Path to Apktool.jar
            String apktoolPath = "path/to/apktool.jar";
    
            // Command to decode the APK
            String[] command = new String[]{
                    "java", "-jar", apktoolPath, "d", apkFile.getAbsolutePath(), "-o", outputDir.getAbsolutePath()
            };
    
            // Build and start the process
            ProcessBuilder processBuilder = new ProcessBuilder(Arrays.asList(command));
            processBuilder.redirectErrorStream(true);
            Process process = processBuilder.start();
    
            // Capture the output (for debugging purposes)
            InputStream in = process.getInputStream();
            OutputStream out = System.out;
            byte[] buffer = new byte[1024];
            int length;
            while ((length = in.read(buffer)) != -1) {
                out.write(buffer, 0, length);
            }
    
            process.waitFor();
            in.close();
            out.close();
    
            if (process.exitValue() == 0) {
                // Success
                System.out.println("APK decoded successfully.");
            } else {
                // Error occurred
                System.out.println("Failed to decode APK.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    }
    
    • 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);

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search