Search code examples
androidpluginsapkclassloaderdexclassloader

DexClassLoader works unstable after run another application


I have a working code that links with apk-plugin. This code stopped working after I run another application on the android emulator.

DexClassLoader no longer find the apk-file.

How it looks

loadClass begin dropping to exception with text:

Didn't find class "com.example.testandlib.Testt"

Please help to understand what might have broken from running another app on android emulator. Reboot of emulator has no effect. Clean project also.

Plugin code:

package com.example.testandlib

import android.util.Log

class Testt {


    fun plus(a: Int,b: Int): Int {
        return a + b - 2

    }

    fun minus(a: Int, b: Int): Int {
        return a - b - 2

    }

    fun stringBoolHello(a: String, b: Boolean): String {
        if (b)
            return "Trully Hello, " + a
        return "Hello, " + a
    }

    fun arrayHello(a: MutableList<String>): String {
        var res = ""
        var iter = a.iterator()
        iter.forEach { res += it+";" }

        return "Hello, " + res
    }

    fun originalArrayHello(a: Array<String>): String {
        var res = ""
        for ((index, value) in a.withIndex()) {
            res += value+index.toString()+";"
        }

        return "Hello, " + res
    }

}

Part of main app code:

val cont = getApplicationContext()
val apkPath = "/data/data/com.example.pozitivmobile/tmp/app-debug.apk"
val cachePath = getDir("dex",0).absolutePath


val classLoaderr = DexClassLoader(
  apkPath,
  cachePath,
  null,
  classLoader
)

try {
    val curClass = classLoaderr.loadClass("com.example.testandlib.Testt")

    val curObj = curClass.newInstance()
    val methodParams = arrayOf(Int.javaClass)
    val plusMethod =  curClass.getMethod("plus",  Int::class.java, Int::class.java)
    val minusMethod = curClass.getMethod("minus", Int::class.java, Int::class.java)
    val stringBoolHelloMethod = curClass.getMethod("stringBoolHello", String::class.java, Boolean::class.java )
    val arrayHelloMethod = curClass.getMethod("arrayHello", MutableList::class.java )
    val originalArrayHelloMethod = curClass.getMethod("originalArrayHello", Array<String>::class.java )

    val plusResult = plusMethod.invoke(curObj,25,35)
    val minusResult = minusMethod.invoke(curObj,35,45)
    val stringBoolHelloResult1 = stringBoolHelloMethod.invoke(curObj,"Dmitry",true)
    val stringBoolHelloResult2 = stringBoolHelloMethod.invoke(curObj,"Dmitry",false)

    val paramHelloArray = mutableListOf<String>()
    paramHelloArray.add("odin")
    paramHelloArray.add("dva")
    paramHelloArray.add("tri")

    val arrayHelloResult = arrayHelloMethod.invoke(curObj,paramHelloArray)

    val paramOriginalHelloArray = arrayOf("odinn","dvaa","trii")

    val OriginalArrayHelloResult =  originalArrayHelloMethod.invoke(curObj,paramOriginalHelloArray)        


    

    
} catch (e: Exception){
    Log.d("loadClass",e.message.toString() )
}

Edit:

I change line

val cachePath = getDir("dex",0).absolutePath

to

val cachePath = cont.cacheDir.absolutePath.toString()

and now my code is working.

Then I return this line back

val cachePath = getDir("dex",0).absolutePath

and my code still works! Heisenbug?


Solution

  • Error dissapeared after these actions:

    1. go to adb shell

    2. go to superuser mode (with su command)

    3. do this commands:

      • chmod 777 /data/data/com.example.pozitivmobile/plugins/app-debug.apk

      • chmod 777 /data/data/com.example.pozitivmobile/plugins

      • chmod 777 /data/data/com.example.pozitivmobile

      • chmod 777 /data/data

      • chmod 777 /data

    4. clean project

    5. run project again

    After this, application is working with plugins, but I can't change app-debug.apk file in emulator storage anymore (permission denied). To do this I need upload apk file to directory:

    /storage/emulated/0/Download/app-debug.apk
    

    and then copy it to application dir in superuser adb shell with command:

    cp /storage/emulated/0/Download/app-debug.apk /data/data/com.example.pozitivmobile/plugins/
    

    After all of this, application are working with apk-plugins, even with change apk-files during main application running.

    But if I delete app from android emulator, error returns. I don't now why.