Skip to content

How to use Java classes in the JNI as an Android NativeActivity #68

@cnlohr

Description

@cnlohr

You can create a java class:

package org.yourorg.cnfgtest;
import android.app.NativeActivity;
public class MyOtherNativeActivity extends android.app.NativeActivity {}

Then you can compile it into your project as a dex.

javac -source 1.7 -target 1.7 -d bin/org/yourorg/cnfgtest/ -classpath /home/charlesl/android-sdk/platforms/android-30/android.jar -sourcepath src src/org/yourorg/cnfgtest/MyOtherNativeActivity.java
~/android-sdk/build-tools/30.0.2/dx --output=makecapk/ --dex ./bin

And make sure your bin is in the main project (rawdrawandroid does this by default)

You will need to create your java class, then create a Dalvak Class Loader

 	jclass DexClassLoaderClass = env->FindClass( envptr, "dalvik/system/DexClassLoader" );
 	jmethodID DexClassLoaderConstructorID =  env->GetMethodID( envptr, DexClassLoaderClass,
 		"<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V" );
	jobject activity = gapp->activity->clazz;
	jclass activityClass = env->GetObjectClass(envptr, activity);
	jmethodID classLoaderID = env->GetMethodID( envptr, activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;" );
	jclass appInfoClass = env->FindClass( envptr, "android/content/pm/ApplicationInfo" );
	jmethodID getAppInfo = env->GetMethodID( envptr, activityClass, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;" );
	jobject appInfo = env->CallObjectMethod( envptr, activity, getAppInfo );
	jfieldID sourceDirID = env->GetFieldID( envptr, appInfoClass, "sourceDir", "Ljava/lang/String;" );
	jfieldID dataDirID = env->GetFieldID( envptr, appInfoClass, "dataDir", "Ljava/lang/String;" );
	jfieldID nativeLibraryDirID = env->GetFieldID( envptr, appInfoClass, "nativeLibraryDir", "Ljava/lang/String;" );
	jobject  sourceDir = env->GetObjectField( envptr, appInfo, sourceDirID );
	jobject  dataDir = env->GetObjectField( envptr, appInfo, dataDirID );
	jobject  nativeLibraryDir = env->GetObjectField( envptr, appInfo, nativeLibraryDirID );
	jobject classLoader = env->CallObjectMethod( envptr, activity, classLoaderID );
	printf( "CL: %p\n", classLoader );
 	jobject dcl = env->NewObject( envptr, DexClassLoaderClass, DexClassLoaderConstructorID, 
 		sourceDir, dataDir, nativeLibraryDir, classLoader );
 	printf( "DCL********************* %p\n", dcl );
	jclass dclClass = env->GetObjectClass( envptr, dcl );
	jmethodID loadClassID = env->GetMethodID( envptr, dclClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;" );

From there, you can just

	//loadClass( java.lang.String ) -> java.lang.Class<?>
	jmethodID loadClassID = env->GetMethodID( envptr, dclClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;" );
// DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) 
	jstring myClassName = env->NewStringUTF( envptr,  "src/org/yourorg/cnfgtest/MyOtherNativeActivity" );
	jclass AccessoryClass = env->CallObjectMethod(envptr, dcl, loadClassID, myClassName );
//DumpObjectClassProperties( AccessoryClass );

Voila! Easy Peasy. 🙄

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions