skylot / jadx

Dex to Java decompiler
Apache License 2.0
41.82k stars 4.89k forks source link

[core] Error not Deompile From Android Project #1908

Closed moderGamer closed 1 year ago

moderGamer commented 1 year ago

hello @skylot im using Library jadx 1.4.7 core and my code


package com.my.newproject14;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

import jadx.api.JadxDecompiler;
import jadx.api.JavaClass;
import jadx.api.JadxArgs;
import java.io.BufferedWriter;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.nio.file.StandardOpenOption;
import java.util.Collections;

public class DecompilationTask extends AsyncTask<Void, String, Boolean> {
    private Context context;
    private ProgressDialog progressDialog;
    private String inputFilePath;
    private String outputDirPath;
    private String errorMessage;
    private OnDone done;

    public DecompilationTask(Context context, String inputFilePath, String outputDirPath, OnDone done) {
        this.context = context;
        this.inputFilePath = inputFilePath;
        this.outputDirPath = outputDirPath;
        this.done = done;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = new ProgressDialog(context);
        progressDialog.setMessage("Decompiling...");
        progressDialog.setCancelable(false);
        progressDialog.show();
    }

    @Override
    protected Boolean doInBackground(Void... voids) {
        try {
            if (inputFilePath == null || outputDirPath == null) {
                errorMessage = "Input file path or output directory path is missing";
                return false;
            }

            File inputFile = new File(inputFilePath);
            if (!inputFile.exists()) {
                errorMessage = "Input file does not exist";
                return false;
            }

            File outputDir = new File(outputDirPath);
            if (!outputDir.exists()) {
                outputDir.mkdirs();
            }

            JadxArgs jadxArgs = new JadxArgs();         
            jadxArgs.setInputFile(inputFile);           
            jadxArgs.setOutDir(new File(outputDirPath + File.separator + "apkDecode"));
            JadxDecompiler decompiler = new JadxDecompiler(jadxArgs);
            decompiler.load();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            errorMessage = e.getMessage();
            return false;
        }
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        progressDialog.setMessage(values[0]);
    }

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
        progressDialog.dismiss();

        if (result) {
            Toast.makeText(context, "Decompiled successfully", Toast.LENGTH_SHORT).show();
            done.done();
        } else {
            Toast.makeText(context, "Decompilation failed: " + errorMessage, Toast.LENGTH_SHORT).show();
            done.error(errorMessage);
        }
    }

    public interface OnDone {
        void done();

        void error(String error);
    }
}

in code not decode Apk file and java and res.. plz Help me

skylot commented 1 year ago

@moderGamer as wiki page mention, you should call decompiler.save() after load.

moderGamer commented 1 year ago

@skylot Well, I did this too, but it didn't convert the dex file to Java for me. Can you show me a sample code? The codes in the wiki are very vague.

skylot commented 1 year ago

It can be some errors, so I suggest to enable slf4j compatible logger. Or you forget to include input plugin for dex support (see same wiki page).

Anyway decompiling whole apk on Android is a bad idea, because of insufficient memory.

moderGamer commented 1 year ago

I added everything, but I can't put the decoded Java files in the path of my memory dictator, and don't underestimate Android because it's very powerful.

skylot commented 1 year ago

I can't put the decoded Java files in the path of my memory dictator

Not sure what you mean, do you get any error?

moderGamer commented 1 year ago

@skylot Yes, only the R.java file is extracted

new Code

package com.my.newproject14;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

import jadx.api.JadxDecompiler;
import jadx.api.JavaClass;
import jadx.api.JadxArgs;
import jadx.api.JavaMethod;
import java.io.BufferedWriter;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.nio.file.StandardOpenOption;
import java.util.Collections;

public class DecompilationTask extends AsyncTask<Void, String, Boolean> {
    private Context context;
    private ProgressDialog progressDialog;
    private String inputFilePath;
    private String outputDirPath;
    private String errorMessage;
    private OnDone done;

    public DecompilationTask(Context context, String inputFilePath, String outputDirPath, OnDone done) {
        this.context = context;
        this.inputFilePath = inputFilePath;
        this.outputDirPath = outputDirPath;
        this.done = done;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = new ProgressDialog(context);
        progressDialog.setMessage("Decompiling...");
        progressDialog.setCancelable(false);
        progressDialog.show();
    }

    @Override
    protected Boolean doInBackground(Void... voids) {
        try {
            if (inputFilePath == null || outputDirPath == null) {
                errorMessage = "Input file path or output directory path is missing";
                return false;
            }

            File inputFile = new File(inputFilePath);
            if (!inputFile.exists()) {
                errorMessage = "Input file does not exist";
                return false;
            }

            File outputDir = new File(outputDirPath);
            if (!outputDir.exists()) {
                outputDir.mkdirs();
            }

            JadxArgs jadxArgs = new JadxArgs();
            jadxArgs.setInputFile(inputFile);
            jadxArgs.setOutDir(new File(outputDirPath + File.separator + "apkDecode"));
            JadxDecompiler decompiler = new JadxDecompiler(jadxArgs);
            decompiler.load();

            // get the list of all classes from the decompiled APK
            List<JavaClass> javaClasses = decompiler.getClasses();
            for (JavaClass cls : javaClasses) {
                // create a file for each Java class
                String className = cls.getName().replace('.', File.separatorChar);
                File javaFile = new File(outputDir, className + ".java");
                // create the file's parent directories, if they don't exist
                File parentDir = javaFile.getParentFile();
                if (!parentDir.exists()) {
                    parentDir.mkdirs();
                }
                // write the Java source code to the file
                BufferedWriter writer = new BufferedWriter(
                        new OutputStreamWriter(new FileOutputStream(javaFile), StandardCharsets.UTF_8));
                writer.write(cls.getCode());
                writer.flush();
                writer.close();
            }

            // save the decompiled APK
            decompiler.save();

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            errorMessage = e.getMessage();
            return false;
        }
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        progressDialog.setMessage(values[0]);
    }

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
        progressDialog.dismiss();

        if (result) {
            Toast.makeText(context, "Decompiled successfully", Toast.LENGTH_SHORT).show();
            done.done();
        } else {
            Toast.makeText(context, "Decompilation failed: " + errorMessage, Toast.LENGTH_SHORT).show();
            done.error(errorMessage);
        }
    }

    public interface OnDone {
        void done();

        void error(String error);
    }
}
skylot commented 1 year ago

decompiler.save(); should handle all code saving, so you don't need to do it manually.

And without errors in logs, I don't know how to help you. Sorry :cry:

moderGamer commented 1 year ago

Honestly, I don't know how to write the slf error correctly and activate it. It is suggested that you create a sample Android program.

skylot commented 1 year ago

I don't know how to write the slf error correctly and activate it

Try this https://github.com/nomis/slf4j-android

It is suggested that you create a sample Android program

As mentioned on wiki page, jadx lib not really suited for Android and have some issues. So I don't want to encourage people to use it on Android.