I am new to NDK and JNI. I have a struct which contains 2 uint64_t variables, I want to pass these as an jobject to the java class.
Java class
public class MyClass {
private long mVar1;
private long mVar2;
public MyClass() {
}
public MyClass(final long mVAR1, final long mVar2) {
this.mVar1 = mVar1;
this.mVar2 = mVar2;
}
public long getVar1() {
return this.mVar1;
}
public long getVar2() {
return this.mVar2;
}
}
Here is my JNI
JNIEXPORT jobject JNICALL Java_my_class_getMyClass(JNIEnv * env, jobject jobj) {
clazz = env->FindClass("my/package/test/MyClass");
methodID = env->GetMethodID(clazz, "<init>", "(JJ)V");
return convertMyClass(env, test.getMyClass());
}
Here is the convert
jobject convertMyClass(JNIEnv * env, MyClass myClass) {
jobject jmyclass = env->NewObject(clazz, methodID);
return jmyclass;
}
How can i add arguments to the convertMyClass.
Related
I am using Gson to convert JSON into a Java object. I have a field in the json that our wise services people coded as either an array or object depending on how many items come back in database. Question is how do model the Java object to pass into Gson converter so that I can handle both types?
json = new Gson().fromJson(reader, Order.class);
Java Classes only parses the JSON array properly
public class Order {
private Detail detail
}
public class Detail {
public String id;
public List<Type> types;
//// getters and setters
}
public class Type {
public String typeId;
public String typeName
//// getters and setters
}
JSON data array
{
"detail":{
"id":"1234565",
"types":{
"type":[
{"typeId":"1246565","typeName":"MyName1"},
{"typeId":"1444445","typeName":"MyName2"}
]
}
}
}
JSON data object
{
"detail":{
"id":"1234565",
"types":{
"type":{"typeId":"1246565","typeName":"MyName1"}
}
}
}
I figured out how to do this by using a generic object. So now I can still call using GSON and not have to do that much manual parsing only when I need when I reconstitute the Objects, and only that particular object.
json = new Gson().fromJson(reader, Order.class);
Main Object
public class Order {
private Detail detail
}
Detail Class
public class Detail {
public String id;
public Types types;
//// getters and setters
public Types getTypes() {
return types;
}
public void setTypes(Types types) {
this.types = types;
}
}
Types class that contains a generic Object called type so it can store either a List
or a LinkedTreeMap which is how JSONObject gets parsed. You have to then manually insert it into a new Type object .
public class Types {
private Object type;
//// getters and setters
public Object getType() {
return type;
}
public void setType(Object type) {
this.type = type;
}
public List<Type> getListType() {
if (type instanceof List) {
return (List<Type>) type;
} else
return null;
}
public Type getObjectType() {
if (type instanceof Type) {
return (Type) type;
} else if (type instanceof Map) {
Map<String, String> map = (Map<String, String>)type;
Type newType = new Type((String)map.get("typeId"), (String)map.get("typeName"));
return newType;
}
return null;
}
public class Type {
private String typeId;
private String typeName;
public Type() {}
public Type(String id, String name) {
this.typeId = id;
this.typeName = name;
}
//// getters and setters
public String getTypeId() {
return typeId;
}
public void setTypeId(String typeId) {
this.typeId = typeId;
}
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
}
Sigh!!
JsonArray typeArray;
JsonElement typeElement = types.get("type");
if (typeElement.isJsonObject()) {
typeArray = new JsonArray();
typeArray.add(typeElement);
}
else {
typeArray = (JsonArray)typeElement;
}
for (int i = 0; i < typeArray.size(); i++) {
JsonObject typeObject = (JsonObject)(typeArray.get(i));
typeObject.doSomethingWithThis();
}
I'm trying to obfuscate a parcelable class with Proguard:
Before adding the Parcelable part the class is:
public class Foo{
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
The obfuscated result is:
public class a
{
private String a;
public String a()
{
return this.a;
}
public void a(String paramString)
{
this.a = paramString;
}
}
After adding implementing parcelable the example class is
public class Foo implements Parcelable {
private String value;
private Foo(Parcel in) {
value = in.readString();
}
public Foo() {
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(value);
}
public static final Parcelable.Creator<Foo> CREATOR
= new Parcelable.Creator<Foo>() {
public Foo createFromParcel(Parcel in) {
return new Foo(in);
}
public Foo[] newArray(int size) {
return new Foo[size];
}
};
}
The obfuscated result is
public class Foo implements Parcelable {
public static final Parcelable.Creator CREATOR = new a();
private String a;
public Foo() {
}
private Foo(Parcel paramParcel) {
this.a = paramParcel.readString();
}
public String a() {
return this.a;
}
public void a(String paramString) {
this.a = paramString;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel paramParcel, int paramInt) {
paramParcel.writeString(this.a);
}
}
class a implements Parcelable.Creator {
public Foo a(Parcel paramParcel) {
return new Foo(paramParcel, null);
}
public Foo[] a(int paramInt) {
return new Foo[paramInt];
}
}
How can I configure proguard for obfuscate the whole class (including name, params and methods) except the parcelable part?
Thanks
Try putting this in your proguard.cfg file:
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
That should preserve Parcelable part and obfuscate everything else.
Here's my question, how can I change an object outside of it's class, so that it maintains the changes made in the outside class?
Here's an example of the code:
Main class:
public class Main {
public static void main(String[] args)
{
Variable var = new Variable(1,2,3);
Change.changeVar(var);
System.out.println("" + var.geta() + "" + var.getb() + "" + var.getc());
}
}
Variable class:
public class Variable {
private int a;
private int b;
private int c;
public Variable(int a, int b, int c)
{
this.a = a;
this.b = b;
this.c = c;
}
public int geta()
{
return this.a;
}
public int getb()
{
return this.b;
}
public int getc()
{
return this.c;
}
}
Change class:
public class Change {
public static void changeVar(Variable var)
{
Variable var2 = new Variable(4,5,6);
var = var2;
}
}
In your example, no. When changeVar() exits, the parameter var is discarded, and the var in your main() method retains its original value. Read up on pass by reference.
public class Variable {
private int a;
private int b;
private int c;
public Variable(int a, int b, int c)
{
this.a = a;
this.b = b;
this.c = c;
}
public int geta()
{
return this.a;
}
public int getb()
{
return this.b;
}
public int getc()
{
return this.c;
}
// depending on your use case, setters might be more appropriate
// it depends on how you want to control the changing of the vars
public void update(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
public class Change {
public static void changeVar(Variable var)
{
var.update(4,5,6);
}
}
You cannot do it in a way that you described, because in Java variables are passed by values. However you can achieve the desired effect in a different way:
public class Variable {
private int a;
private int b;
private int c;
public Variable(int a, int b, int c)
{
this.a = a;
this.b = b;
this.c = c;
}
public int geta()
{
return this.a;
}
public int getb()
{
return this.b;
}
public int getc()
{
return this.c;
}
public void seta(int a) { this.a = a; }
public void setb(int b) { this.a = b; }
public void setc(int c) { this.a = c; }
}
public class Change {
public static void changeVar(Variable var)
{
var.seta(4);
var.setb(5);
var.setc(6);
}
}
You need to provide setter methods and call them on the original object:
public void seta(int newa) { this.a = newa; }
Then you would say
public static void changeVar(Variable var)
{
var.seta(4);
//etc
}
You are merely repointing the local variable reference var to point to your new instance var2. It has no effect on the value of the original instance passed into the method.
Doing it that way? You can't.
You're passing a reference to the instance. However, inside the function, you use a new reference. Assigning to the new reference does not affect others.
public static void changeVar(Variable var)
{
Variable var2 = new Variable(4,5,6);
var = var2;
}
first, u can write some setter methods in Variable class, then you can call these setter methods in the above code, like var.setA(4) ... and so on.enter code here
I have a Java program that communicates to a C program. I have written JNI before but my output structure was more simplistic and the C structure just contained doubles/ints and arrays of doubles/ints.
Now my structure contains a substructure (class/subclass) and I don't know how to change the code to access the subclass data/fields.
My C code looked like this but how do I access a value like DefaultFeeAmount if you look at my Java Class below this code....how do I get to the elements within the subclass?
C straightforward....
{
jclass out_rec_cls = jenv->GetObjectClass(ptrTo_out_rec);
jfieldID fldID, fldID2;
jintArray arr;
jdoubleArray darr;
jobjectArray oarr;
jsize len;//,len2;
jint *arrElems;
jdouble *darrElems;
jobject *oarrElems;
int i;
char temp_str[100],temp_str2[10000];
fldID = jenv->GetFieldID(out_rec_cls, "ErrorCode", "I");
if(fldID != NULL)
jenv->SetIntField(ptrTo_out_rec, fldID, out_rec->error_code);
}
Java
class FeeOutput {
public double DefaultFeeAmount;
public double MaximumAmount;
public int FeeID;
public int CompType;
public int Handling;
public int CapType;
public int ProfitType;
public int EffectiveDateMonth;
public int EffectiveDateDay;
public int EffectiveDateYear;
public int VendorBasedFee;
public int DealerRequestedFee;
public int DealerFixedTranFee;
public double FeeAmount;
public int FeeCompliant;
public String FeeName = "";
public FeeOutput() {
}
}
public class VFeeOutput {
public static final int NUM_FEES = 100;
public FeeOutput[] FeeStruct = new FeeOutput[NUM_FEES];
public int ErrorCode;
public String ErrorString = "";
public String Version = "";
public VFeeOutput() {
}
}
As a wide-spread Java convention tip, please start variable names with lower case. Here how you can access "struct" fields in Java.
public class VFeeOutput {
public static final int NUM_FEES = 100;
public FeeOutput[] FeeStruct = new FeeOutput[NUM_FEES];
public int ErrorCode;
public String ErrorString = "";
public String Version = "";
public VFeeOutput() {
}
private void loopThoughtFeeOutput() {
for(FeeOutput feeOutput : FeeStruct) {
feeOutput.CompType = ...;
}
// or
for(int i = 0; i < FeeStruct.length; i++) {
FeeStruct[0].CompType = ...;
}
}
}
For bean->xml convertion in webservices we use Aegis from CXF (it is jaxb-compatible, as I understand).
This is my type:
class C{
private int a;
private int b;
private T t;
...
}
class T{
private int t1;
private int t2;
}
I need t.t1 field to be on the same level in XML as a and b in C (bean restored from xml should be like this:
class C{
private int a;
private int b;
private int t1
}
(client code is interested only in field t1 from structure T).
Thanks.
You could add getT1() and setT1(int) to C and make getT() #XmlTransient
class C {
// snip
/**
* JAXB only
*/
#SuppressWarnings("unused")
#XmlElement
private void setT1(int t1) {
if(t != null) {
t.setT1(t1);
} else {
// TODO
}
}
/**
* JAXB only
*/
#SuppressWarnings("unused")
private int getT1() {
if(t != null) {
return t.getT1(t1);
} else {
// TODO
}
}
}