using Byte Buddy Android : ref offical link, never used it before. is there any tutorial available for this?
code uses AndroidClassLoadingStrategy.Wrapping, which generates a .dex file in a writable location, typically in your app’s private directory (like /data/data/<your_app>), and attempts to execute it. Android 10 and above enforce strict security policies to prevent apps from writing .dex or .jar files and executing them at runtime.
how can we use byte buddy android for the latest android versions?
private fun runBuddyTest(context: Context) {
val strategy = AndroidClassLoadingStrategy.Wrapping(applicationContext.getDir("generated", Context.MODE_PRIVATE))
// Create a dynamic type (subclass of Object) and modify the "toString" method
val dynamicType = ByteBuddy()
.subclass(Any::class.java)
.method(ElementMatchers.named("toString"))
.intercept(FixedValue.value("Hello World!"))
.make()
.load(this.javaClass.classLoader, strategy)
.loaded
// Instantiate the dynamically created class and assert the "toString" method
val instance = dynamicType.getDeclaredConstructor().newInstance()
assert(instance.toString() == "Hello World!")
}
getting this error
FATAL EXCEPTION: main
Process: com.rnadigital.bytebuddyapplication, PID: 12815
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.rnadigital.bytebuddyapplication/com.rnadigital.bytebuddyapplication.MainActivity}: java.lang.SecurityException: Writable dex file '/data/user/0/com.rnadigital.bytebuddyapplication/app_generated/d7rUqolH.jar' is not allowed.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3782)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8177)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by: java.lang.SecurityException: Writable dex file '/data/user/0/com.rnadigital.bytebuddyapplication/app_generated/d7rUqolH.jar' is not allowed.
at dalvik.system.DexFile.openDexFileNative(Native Method)
at dalvik.system.DexFile.openDexFile(DexFile.java:406)
at dalvik.system.DexFile.<init>(DexFile.java:128)
at dalvik.system.DexFile.<init>(DexFile.java:101)
at dalvik.system.DexPathList.loadDexFile(DexPathList.java:438)
at dalvik.system.DexPathList.makeDexElements(DexPathList.java:397)
at dalvik.system.DexPathList.<init>(DexPathList.java:166)
at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:160)
at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:105)
at dalvik.system.DexClassLoader.<init>(DexClassLoader.java:55)
at net.bytebuddy.android.AndroidClassLoadingStrategy$Wrapping.doLoad(AndroidClassLoadingStrategy.java:580)
at net.bytebuddy.android.AndroidClassLoadingStrategy.load(AndroidClassLoadingStrategy.java:148)
at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:101)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6317)
at com.rnadigital.bytebuddyapplication.MainActivity.generateDynamicClassInMemory(MainActivity.kt:79)
at com.rnadigital.bytebuddyapplication.MainActivity.onCreate(MainActivity.kt:52)
at android.app.Activity.performCreate(Activity.java:8595)
at android.app.Activity.performCreate(Activity.java:8573)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3764)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8177)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
this is gradle file
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
}
android {
namespace = "com.rnadigital.bytebuddyapplication"
compileSdk = 34
defaultConfig {
applicationId = "com.rnadigital.bytebuddyapplication"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
multiDexEnabled = true
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
// implementation (libs.byte.buddy)
implementation (libs.byte.buddy.android)
}
Byte Buddy normally sets the file permissions to OWNER_READ
. Have a look at the FileProcessor
class where this is done. Is the processor not active? Possibly, you are running an older version of Byte Buddy where this is not taken into account. Android changes quite often, so only the newer versions will support more modern Android.