-
Notifications
You must be signed in to change notification settings - Fork 249
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
Example for declare(FieldId<?, ?> fieldId, int flags, Object staticValue) #110
Comments
I tried to my best knowledge and here is what I managed to make so far package com.kn.testcreatingaclassinruntime.CreateClassInRunTimeWrapper;
import com.android.dx.DexMaker;
import com.android.dx.FieldId;
import com.android.dx.TypeId;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
/**
* This is a DexMaker wrapper to create classes in run time
* because the existing code is way too big and confusing for me
* @author Ahmed Moussa <email>[email protected]</email>
* @version 1.0
* Created by Ahmed Moussa on 7/2/18.
*/
public final class DexMakerWrapper {
// ClassName
private String ClassName;
// dexMaker used to create the class
private DexMaker dexMaker;
// class declaration after finishing
private Class<?> createdClass;
// make and entry point to the train methodology
public static DexMakerWrapper Constructor() {
return new DexMakerWrapper();
}
// use the it to initiate an object of the dex maker class
private DexMakerWrapper() {
this.dexMaker = new DexMaker();
}
// set class name as well as start class declaration
public DexMakerWrapper setClassName(String ClassName) {
this.ClassName = ClassName;
TypeId<?> classDeclaration = TypeId.get("L" + this.ClassName + ";");
this.dexMaker.declare(classDeclaration, this.ClassName + ".generated", Modifier.PUBLIC, TypeId.OBJECT);
return this;
}
// set class fields with data type String for all of them
public DexMakerWrapper setStringFields(ArrayList<String> Fields) {
TypeId<System> systemType = TypeId.get(System.class);
TypeId<String> DataType = TypeId.get(String.class);
for (String field : Fields) {
FieldId<System, String>FieldDec = systemType.getField(DataType, field);
this.dexMaker.declare(FieldDec, Modifier.PUBLIC, null);
}
return this;
}
// creating the class itself
public Class<?> createClass() {
File outputDir = new File(".");
try {
ClassLoader loader = this.dexMaker.generateAndLoad(DexMakerWrapper.class.getClassLoader(), outputDir);
this.createdClass = loader.loadClass(this.ClassName);
return this.createdClass;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
} Here is an example of my use of previous code val fields = ArrayList<String>()
fields.add("A")
fields.add("B")
fields.add("C")
fields.add("D")
val dex: DexMakerWrapper = DexMakerWrapper.Constructor().setClassName("ModelA").setStringFields(fields)
val createdClass = dex.createClass() I'm getting a crash java.lang.RuntimeException java.lang.RuntimeException: Unable to start activity ComponentInfo{com.kn.testcreatingaclassinruntime/com.kn.testcreatingaclassinruntime.MainActivity}: java.lang.IllegalStateException: Undeclared type Ljava/lang/System; declares members: [Ljava/lang/System;.A, Ljava/lang/System;.B, Ljava/lang/System;.C, Ljava/lang/System;.D] [] The crash is happening inside your code DexMaker class inside generate function Any help would be appreciated. |
Another update. package com.kn.testcreatingaclassinruntime.CreateClassInRunTimeWrapper;
import android.content.ContextWrapper;
import com.android.dx.DexMaker;
import com.android.dx.FieldId;
import com.android.dx.TypeId;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
/**
* This is a DexMaker wrapper to create classes in run time
* because the existing code is way too big and confusing for me
* @author Ahmed Moussa <email>[email protected]</email>
* @version 1.0
* Created by Ahmed Moussa on 7/2/18.
*/
public final class DexMakerWrapper {
// ClassName
private String ClassName;
// dexMaker used to create the class
private DexMaker dexMaker;
// class declaration code
private TypeId<?> classDeclaration;
// class declaration after finishing
private Class<?> createdClass;
// make and entry point to the train methodology
public static DexMakerWrapper Constructor() {
return new DexMakerWrapper();
}
// use the it to initiate an object of the dex maker class
private DexMakerWrapper() {
this.dexMaker = new DexMaker();
}
// set class name as well as start class declaration
public DexMakerWrapper setClassName(String ClassName) {
this.ClassName = ClassName;
this.classDeclaration = TypeId.get("Lcom/kn/testcreatingaclassinruntime/CreateClassInRunTimeWrapper/" + this.ClassName + ";");
this.dexMaker.declare(classDeclaration, this.ClassName + ".generated", Modifier.PUBLIC, TypeId.OBJECT);
return this;
}
// set class fields with data type String for all of them
public DexMakerWrapper setStringFields(ArrayList<String> Fields) {
// TypeId<System> systemType = TypeId.get(System.class);
TypeId<String> DataType = TypeId.get(String.class);
for (String field : Fields) {
FieldId<System, String> FieldDec = (FieldId<System, String>) this.classDeclaration.getField(DataType, field); //systemType.getField(DataType, field);
this.dexMaker.declare(FieldDec, Modifier.PUBLIC, null);
}
return this;
}
// creating the class itself
public Class<?> createClass(File f) {
File outputDir = f;
try {
ClassLoader loader = this.dexMaker.generateAndLoad(DexMakerWrapper.class.getClassLoader(), outputDir);
this.createdClass = loader.loadClass(this.ClassName);
return this.createdClass;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
} And my usage val fields = ArrayList<String>()
fields.add("A")
fields.add("B")
fields.add("C")
fields.add("D")
var dir = this.dataDir
val createdClass = DexMakerWrapper.Constructor().setClassName("ModelA").setStringFields(fields).createClass(dir)
for (f in createdClass!!.declaredFields) {
println(f.name)
} Also had to add in the manifest file. Now I'm getting Now what did I do wrong here? |
Example code itself is not running? |
Guys, |
Managed to test a fix. // this line should include the absolute path of the class
this.createdClass = loader.loadClass("com.kn.testcreatingaclassinruntime.CreateClassInRunTimeWrapper." + this.ClassName); |
So Far I'm able to create the Class in run time as shown in the code. With the wanted structure public class ModelA {
public String value1;
public String value2;
public String value3;
} But I'm not able to create new instant out of it and therefore I'm not able to set fields value which is what I want I need to make an ArrayList of this newly generated Class and set the values inside their fields. |
I would like to create a norma modal with all its fields are public but I can't figure our how to use the provided function declare(FieldId fieldId, int flags, Object staticValue). Can someone please provide me with a working example
I want to create something like that
My issue is with FieldId value for the declare function.
The text was updated successfully, but these errors were encountered: