Android小白学jni

  1. android studio搭建JNI开发环境
  • 下载NDK并配置到工程中

https://developer.android.google.cn/ndk/downloads/index.html

File->Project Structure

②创建JNI目录:New->Folder->JNI Folder

③编写java native函数,并在jni目录下完成c侧实现

④配置编译:

Makefile,创建Android.mk 如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)



LOCAL_MODULE := my_service_jni

LOCAL_SRC_FILES := my_service_jni.c

LOCAL_LDLIBS    := -llog //注意此处不加该编译lib导致无法使用android封装的日志模块



include $(BUILD_SHARED_LIBRARY)

配置build.gradle

defaultConfig {

    applicationId "com.example.myservice"

    minSdkVersion 15

    targetSdkVersion 29

    versionCode 1

    versionName "1.0"



    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

    ndk {

        moduleName "my_service_jni"  //待编译生成的目标.so文件名称

        abiFilters "arm64-v8a"

    }

}
externalNativeBuild{

    ndkBuild{

        path "src/main/jni/Android.mk" // 指定makefile,或者使用cmake

    }

}

 

  1. java调用c,c调用java返回string类型demo

C调用java:套路:jclass->jmethodID->call

JAVA调用C:套路:实现JNI_OnLoad函数并注册方法

static const char *className = "com/example/myservice/MyServiceJni";



void GetProjVersion(void);

static void JNICALL HelloService(JNIEnv *env, jobject obj)

{

    LOGE("HELLO SERVICE JNI");

    GetProjVersion();

}



static jstring JNICALL HandlerClientMsg(JNIEnv *env, jobject obj, jstring s)

{

    // c接收java的 string类型

    const char *s1;

    s1 = (*env)->GetStringUTFChars(env, s, NULL);

    LOGE("%s-%d: %s", __func__, __LINE__, s1); //需要将jtring s转换成c侧的char *,使用完成后需要释放

    (*env)->ReleaseStringUTFChars(env, s, s1);

    // c返回java string类型

    char *retStr = "hello java i am c";

    return (*env)->NewStringUTF(env, retStr);

}



static const JNINativeMethod g_method[] = {

        { "HelloService",

          "()V",

          (void *)HelloService,

        },

        {

            "HandlerClientMsg",

            "(Ljava/lang/String;)Ljava/lang/String;",   // 不要漏掉 ‘;’,漏掉会导致加载so失败

            (jstring *)HandlerClientMsg,

        }

};

JNIEnv *env = NULL;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm,void* reserved)

{

   LOGE("in JNI_Onload");

   if((*vm)->GetEnv(vm,(void**)&env,JNI_VERSION_1_6)!=JNI_OK){

      return -1;

   }

   jclass cls = (*env)->FindClass(env, className);

   if (cls == NULL) {

       LOGE("Can not find %s", className);

       return -1;

   }

   if ((*env)->RegisterNatives(env, cls, g_method, sizeof(g_method) / sizeof(g_method[0])) != JNI_OK) {

       LOGE("Register native method fail");

       return -1;

   }

   return JNI_VERSION_1_6;

}



void GetProjVersion(void)

{

    jclass regionClass = (*env)->FindClass(env, className);

    if (regionClass != NULL) {

        jmethodID methodId = (*env)->GetStaticMethodID(env, regionClass, "getProjVersion", "()Ljava/lang/String;");

        jstring jVersion = (jstring) (*env)->CallStaticObjectMethod(env, regionClass, methodId);

        char *version = (char *) (*env)->GetStringUTFChars(env, jVersion, NULL);

        LOGE("GetVersionFromJava = %s", version);

    }

}

 

java侧代码:

package com.example.myservice;



public class MyServiceJni {

    private static final String LIB_NAME = "hello";



    private static final String VERSION = "11.0";



    public MyServiceJni() {



    }



    public void myServiceJniInit() {

        System.loadLibrary(LIB_NAME);

    }



    public static String getProjVersion() {

        return VERSION;

    }



    public native void HelloService();

    public native String HandlerClientMsg(String msg);

}

 

问题:

  • javah 找不到类文件的解决办法?对于动态注册JNI native接口时需要编辑签名字符串,比较简单的方式就是用javah根据java定义的native函数生成对应的头文件后拷贝。

set classpath=E:\..\app\src\main\java (com.xxx.xxx.test.java在E:\..\app\src\main\java\xxx\目录下)

javah –jni com.xxx.test 这样就可以在xxx目录下生成对应的头文件了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值