Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error encountered while compiling APK #71

Open
cgapk123 opened this issue Aug 6, 2024 · 6 comments
Open

Error encountered while compiling APK #71

cgapk123 opened this issue Aug 6, 2024 · 6 comments

Comments

@cgapk123
Copy link

cgapk123 commented Aug 6, 2024

I tried to modify the APK, but most of them gave an error: Attempt to invoke virtual method 'boolean com.reandroid.arsc.chunk.xml.ResXmIStartNamespace.removelfNoReference()' on a nullobject reference

`package com.nekolaska.apk

import android.app.Activity
import com.luajava.LuaFunction
import com.reandroid.apkeditor.Util
import com.reandroid.apkeditor.compile.Builder
import com.reandroid.apkeditor.decompile.Decompiler
import java.io.File
import kotlin.concurrent.thread

class Editor(private val context: Activity) {
val cacheDir: String = File(context.cacheDir, "editor").absolutePath

fun start(
    inApkPath: String,
    outApkPath: String,
    newPackage: String,
    callback: LuaFunction<*>,
    onError: LuaFunction<*>
) {
    if (!File(inApkPath).exists()) {
        onError.call("APK file does not exist")
        return
    }
    thread {
        decompile(inApkPath, newPackage, callback, onError)
        build(outApkPath, callback, onError)
        Util.deleteDir(File(cacheDir))
        context.runOnUiThread {
            callback.call("Task completed")
        }
    }
}

// Command line equivalent:
// java -jar C:\\Users\\NekoLaska\\Downloads\\APKEditor-1.3.9.jar d -i C:\\Users\\NekoLaska\\Downloads\\example.apk -o test_json
fun decompile(
    apkPath: String,
    newPackage: String,
    callback: LuaFunction<*>,
    onError: LuaFunction<*>
) = try {
    decode(apkPath, newPackage, callback)
} catch (e: Exception) {
    context.runOnUiThread {
        callback.call("An exception occurred: " + e.message)
    }
    try {
        decode(apkPath, newPackage, callback)
    } catch (e: Exception) {
        context.runOnUiThread {
            onError.call("An exception occurred: " + e.message)
        }
    }
}

private fun decode(
    apkPath: String,
    newPackage: String,
    callback: LuaFunction<*>,
) {
    val outFile = File(cacheDir)
    Util.deleteDir(outFile)
    outFile.mkdirs()
    Decompiler.execute(callback, "-i", apkPath, "-o", cacheDir)
    modifyJson(newPackage)
    modifyManifest(newPackage)
}

// Command line equivalent:
// java -jar C:\\Users\\NekoLaska\\Downloads\\APKEditor-1.3.9.jar b -i test_json -o test_edit.apk
fun build(apkPath: String, callback: LuaFunction<*>, onError: LuaFunction<*>) =
    try {
        File(apkPath).delete()
        Builder.execute(callback, "-i", cacheDir, "-o", apkPath)
    } catch (e: Exception) {
        context.runOnUiThread {
            callback.call("An exception occurred: " + e.message)
        }
        try {
            File(apkPath).delete()
            Builder.execute(callback, "-i", cacheDir, "-o", apkPath)
        } catch (e: Exception) {
            context.runOnUiThread {
                onError.call("An exception occurred: " + e.message)
            }
        }
    }

fun modifyJson(newPackage: String) {
    val jsonPath = findJson()
    var json = readString(jsonPath)
    json = replacePackageText2(json!!, newPackage)
    writeString(json, jsonPath)
}

fun modifyManifest(newPackage: String) {
    val manifestPath = findManifest()
    var manifest = readString(manifestPath)
    manifest = replacePackageText(manifest!!, newPackage)
    writeString(manifest, manifestPath)
}

fun writeString(str: String, path: String?) {
    try {
        if (path == null) {
            return
        }
        val file = File(path)
        file.writeText(str)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

fun readString(path: String?): String? {
    try {
        if (path == null) {
            return null
        }
        val file = File(path)
        return file.readText()
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return null
}

private fun replacePackageText(inputText: String, replacementText: String): String {
    val pattern = "package=\\"([^\\"]*)\\""
    return inputText.replace(pattern.toRegex(), "package=\\"$replacementText\\"")
}

private fun replacePackageText2(inputText: String, replacementText: String): String {
    val pattern = "\\"package_name\\": \\"([^\\"]*)\\""
    return inputText.replace(pattern.toRegex(), "\\"package_name\\": \\"$replacementText\\"")
}

private fun findFile(dirPath: String, fileName: String): String? {
    val dir = File(dirPath)  // Create a File object representing the specified directory path
    if (!dir.exists()) {  // If the directory doesn't exist, return null
        return null
    }

    val files = dir.listFiles() ?: return null  // Get list of all files in the directory, return null if empty
    for (file in files) {  // Iterate through the file list
        if (file.isDirectory) {
            val result = findFile(file.absolutePath, fileName)
            if (result != null) {  // If the file is found, return its path
                return result
            }
        } else {  // If it's a file
            if (file.name.equals(fileName)) {  // If the file name matches fileName, return its absolute path
                return file.absolutePath
            }
        }
    }
    return null  // If the file is not found, return null
}

fun findJson(): String? = findFile(cacheDir, "package.json")
fun findManifest(): String? = findFile(cacheDir, "AndroidManifest.xml")

}`

@cgapk123
Copy link
Author

cgapk123 commented Aug 6, 2024

Attempt to invoke virtual method 'boolean com.reandroid.arsc.chunk.xml.ResXmlStartNamespace.removeIfNoReference()' on a null object reference
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean com.reandroid.arsc.chunk.xml.ResXmlStartNamespace.removeIfNoReference()' on a null object reference
at com.reandroid.arsc.chunk.xml.ResXmlElement.removeUnusedNamespaces(ResXmlElement.java:306)
at com.reandroid.arsc.chunk.xml.ResXmlDocument.removeUnusedNamespaces(ResXmlDocument.java:150)
at com.reandroid.arsc.chunk.xml.ResXmlDocument.refreshFull(ResXmlDocument.java:170)
at com.reandroid.arsc.chunk.xml.ResXmlDocument.parse(ResXmlDocument.java:481)
at com.reandroid.apk.xmlencoder.XMLEncodeSource.encode(XMLEncodeSource.java:77)
at com.reandroid.apk.xmlencoder.XMLEncodeSource.getArray(XMLEncodeSource.java:65)
at com.reandroid.apk.xmlencoder.XMLEncodeSource.write(XMLEncodeSource.java:41)
at com.reandroid.archive.writer.OutputSource.writeBuffer(OutputSource.java:58)
at com.reandroid.archive.writer.FileOutputSource.writeBuffer(FileOutputSource.java:46)
at com.reandroid.archive.writer.FileOutputSource.makeBuffer(FileOutputSource.java:42)
at com.reandroid.archive.writer.ApkFileWriter.writeBuffer(ApkFileWriter.java:81)
at com.reandroid.archive.writer.ApkFileWriter.prepareOutputs(ApkFileWriter.java:43)
at com.reandroid.archive.writer.ApkFileWriter.prepareOutputs(ApkFileWriter.java:27)
at com.reandroid.archive.writer.ApkWriter.write(ApkWriter.java:51)
at com.reandroid.apk.ApkModule.writeApk(ApkModule.java:481)
at com.reandroid.apkeditor.compile.Builder.buildXml(Builder.java:127)
at com.reandroid.apkeditor.compile.Builder.run(Builder.java:52)
at com.reandroid.apkeditor.compile.Builder.execute(Builder.java:191)
at com.nekolaska.apk.Editor.build-0E7RQCE(Editor.kt:79)
at com.nekolaska.apk.Editor.modify$lambda$2(Editor.kt:29)
at com.nekolaska.apk.Editor.$r8$lambda$JaMRkojg8dzJ9SyjMfogwP69MsM(Unknown Source:0)
at com.nekolaska.apk.Editor$$ExternalSyntheticLambda0.invoke(Unknown Source:12)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

@REAndroid
Copy link
Owner

Null at removeUnusedNamespaces could not happen, the base collection is BlockList so this doesn't store null items at all.

  • Kotlin stripped stack trace (most likely), change to java to confirm
  • Maybe you are running in multiple threads (ARSCLib is not thread safe)

FYI: If your end goal is to edit resources/xml, you don't have to decompile at all. There are all the methods to edit binary files directly.

@cgapk123
Copy link
Author

cgapk123 commented Aug 8, 2024

Null at removeUnusedNamespaces could not happen, the base collection is BlockList so this doesn't store null items at all.

  • Kotlin stripped stack trace (most likely), change to java to confirm
  • Maybe you are running in multiple threads (ARSCLib is not thread safe)

FYI: If your end goal is to edit resources/xml, you don't have to decompile at all. There are all the methods to edit binary files directly.

Hi, I need to modify the resource/xml code, how can I edit the binary file directly? Is there any example usage?

@cgapk123
Copy link
Author

cgapk123 commented Aug 9, 2024

Null at removeUnusedNamespaces could not happen, the base collection is BlockList so this doesn't store null items at all.

  • Kotlin stripped stack trace (most likely), change to java to confirm
  • Maybe you are running in multiple threads (ARSCLib is not thread safe)

FYI: If your end goal is to edit resources/xml, you don't have to decompile at all. There are all the methods to edit binary files directly.

Sorry, I need to change the package name, but I don't know how to directly edit binary file resources and xml. Please provide the following sample code

@REAndroid
Copy link
Owner

@cgapk123
Confirm :c8002af fixes this issue

@cgapk123
Copy link
Author

@cgapk123 Confirm :c8002af fixes this issue

Can you compile and update jar files?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants