the-mac / AndroidJniHelpers

Tools for writing secure Android/JNI code, based upon Spotify's Jni Helpers Library
http://on.fb.me/1MIc51o
MIT License
37 stars 5 forks source link

java native method how to generate the native? #5

Closed netstu closed 6 years ago

netstu commented 6 years ago

java file:

package com.test.b; class Ctest { native public PersistedObject createPersistedObject(); }

cpp h file:

class Ctest : : public JavaClass { static jobject createPersistedObject(JNIEnv *env, jobject javaThis); }

can call java method: Ctest::createPersistedObject();

but i not found the the jni statement like this:

jobject Java_com_test_b_createPersistedObject();

cdm2012 commented 6 years ago

The simplest way to generate the code for your class is to use the AndroidJniHelpers/bin/jni.bash script, then in your cpp file you can add the native implementation that you want. For example if you wanted to create a native version of MainIntentService:

package us.the.mac.library.demo.androidjni;
 ...
public class MainIntentService extends IntentService {
    static {
        Log.d(MainIntentService.class.getName(), "Called static {...} successfully");
        // SET AUTHORITY: us.the.mac.demo.library.androidjni.provider
    }
    public static final String PARAM_IN_MSG = "imsg";
    public static final String WELCOME_MESSAGE = AndroidJniApp.getS(0);
    ...
}

You could do the following to generate the MainIntentService.cpp file:

# PROJECT_PATH="/is/what/directory/your/project/is/in"
cd $PROJECT_PATH/AndroidJniHelpers

className="us.the.mac.library.demo.androidjni.MainIntentService" \
filePath="$PROJECT_PATH/AndroidJniHelpers/demo/src/main/java/us/the/mac/library/demo/androidjni/MainIntentService.java" \
bin/jni.bash $className $filePath \
cat bin/jni.files/generated/$className.jni

After executing the jni.bash script the result should look as follows:

Result: MainIntentService.jni has been generated and is ready to use.
Path: $PROJECT_PATH/AndroidJniHelpers/bin/jni.files/build.jni/us.the.mac.library.demo.androidjni.MainIntentService.jni

us.the.mac.library.demo.androidjni.MainIntentService

********************************************************************************

us.the.mac.library.demo.androidjni.MainIntentService.jni was generated as a helper for MainIntentService.java using the
bin/jni.bash script. The following code segments are C++ header and source code containing:

- getCanonicalName: The method that enables the relationship between C++ and Java.
- Java methods: us.the.mac.library.demo.androidjni.MainIntentService, onCreate, onHandleIntent, showToast

The source code can be copied into the respective MainIntentService.h and
MainIntentService.cpp files in a location of your choice. Finally, the last segment
contains an example of what these method calls would look like in your code.

********************************************************************************

#include "JniHelpers.h"

class MainIntentService : public JavaClass {
  public:
    /**
    * This facsimile of the Java method java.lang.Class.getCanonicalName() is used to maintain 
    * the Jni Helper\'s relationship to the MainIntentService class defined in Java.
    */
    const char *getCanonicalName() const { return CANONICAL_CLASS_NAME; }

    MainIntentService();

    MainIntentService(JNIEnv *env);

    void initialize(JNIEnv *env);

    void mapFields();

    void onCreate(JNIEnv *env);

    void onHandleIntent(JNIEnv *env, jobject jobjectValue1);

    void showToast(JNIEnv *env, jstring jstringValue1);

    static const char * const CANONICAL_CLASS_NAME;
};

********************************************************************************

const char * const MainIntentService::CANONICAL_CLASS_NAME = "us/the/mac/library/demo/androidjni/MainIntentService";

MainIntentService::MainIntentService() : JavaClass() {}

/**
* Here you can construct the MainIntentService object how ever you need to, 
* as well as load signatures for the Java instance method calls.
*/
MainIntentService::MainIntentService(JNIEnv *env) : JavaClass(env)
{
    initialize(env);

    thisObj = toJavaObject(env); // THIS IS WHERE WE INITIALIZE YOUR JAVA OBJECT

    // thisObj = env->NewObject(_clazz, getMethod("<init>"));
    // YOU MAY WANT TO ADD A FEW PARAMETERS TO THE 'NewObject' EXAMPLE INSTEAD

    if (thisObj == NULL) {
        JavaExceptionUtils::throwExceptionOfType(env, kTypeIllegalStateException,
            "MainIntentService's thisObj variable not intialized, methods of this class use the thisObj Java instance.");
    }
}

void MainIntentService::initialize(JNIEnv *env)
{
    bool debug = ENABLE_LOGGING_DEBUG;
    if(debug) LOG_INFO("Called %s.initialize", getCanonicalName());

    setClass(env);
    cacheConstructor(env);

    cacheSignature(env, "onCreate", "()V");
    cacheSignature(env, "onHandleIntent", "(Landroid/content/Intent;)V");
    cacheSignature(env, "showToast", "(Ljava/lang/String;)V");

    registerNativeMethods(env);
}

void MainIntentService::mapFields()
{
    //mapField("encodedString", kTypeString, &encodedString);
}

void MainIntentService::onCreate(JNIEnv *env)
{
    env->CallVoidMethod(thisObj, getMethod(__FUNCTION__));
    JavaExceptionUtils::checkException(env);
}

void MainIntentService::onHandleIntent(JNIEnv *env, jobject jobjectValue1)
{
    env->CallVoidMethod(thisObj, getMethod(__FUNCTION__), jobjectValue1);
    JavaExceptionUtils::checkException(env);
}

void MainIntentService::showToast(JNIEnv *env, jstring jstringValue1)
{
    env->CallVoidMethod(thisObj, getMethod(__FUNCTION__), jstringValue1);
    JavaExceptionUtils::checkException(env);
}

********************************************************************************

instance.onCreate(env);

instance.onHandleIntent(env, jobjectValue1);

instance.showToast(env, jstringValue1);

********************************************************************************
netstu commented 6 years ago

@cdm2012 very thanks

cdm2012 commented 6 years ago

No problem. Feel free to come back for more questions, or even join our community.

You can join the community conversation here: http://on.fb.me/1MIc51o