专栏首页向全栈出发AndroidStudio创建JNI 工程与调用

AndroidStudio创建JNI 工程与调用

AndroidStudio 的 JNI 工程创建与调用

1.新建一个 Android 工程

写一个 JNI 工具类:JNITools.java

package com.example.jnitest;
public class JNITools {
public static native String getStringFromJNI();
}

2.Activity的xml文件里给布局 添加一个 id

<?xml version="1.0" encoding="utf-8"?> 
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".MainActivity"> 
    <TextView 
        android:id="@+id/tv_show" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="Hello World!" 
        app:layout_constraintBottom_toBottomOf="parent" 
        app:layout_constraintLeft_toLeftOf="parent" 
        app:layout_constraintRight_toRightOf="parent" 
        app:layout_constraintTop_toTopOf="parent" /> 
</androidx.constraintlayout.widget.ConstraintLayout>

3.在MainActivity调⽤写好的 JNI⽅法

package com.example.jnitest; 
import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; 
import android.widget.TextView; 
public class MainActivity extends AppCompatActivity { 
    @Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
        TextView tvShow = findViewById(R.id.tv_show); 
        tvShow.setText(JNITools.getStringFromJNI()); 
    } 
} 
此时因为没有 native实现,运行会报错: java.lang.UnsatisfiedLinkError: No implementation found for
2020-09-08 20:18:57.785 18756-18756/com.example.jnitest E/ AndroidRuntime: FATAL EXCEPTION: main 
    Process: com.example.jnitest, PID: 18756 
    java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.example.jnitest.JNITools.getStringFromJNI() (tried 
Java_com_example_jnitest_JNITools_getStringFromJNI and 
Java_com_example_jnitest_JNITools_getStringFromJNI__) 
        at com.example.jnitest.JNITools.getStringFromJNI(Native Method) 
        at com.example.jnitest.MainActivity.onCreate(MainActivity.java:16) 
        at android.app.Activity.performCreate(Activity.java:8085) 
        at android.app.Activity.performCreate(Activity.java:8073) 
        at 
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1320)         at 
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3868)         at 
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4074) 

4.Native实现——编译 JNI⽂件

MakeProject或者 RebuildProject之后,到 app下的 build⽂件夹找到 class所在⽬ 录; 进⼊到包名的上级⽬录,运⾏:javah -jni com.example.jnitest.JNITools ⽣成⼀个 com_example_jnitest_JNITools.h⽂件,com.example.jnitest.JNITools是 你 JNI⼯具类所在引⽤,可根据实际情况修改。

com_example_jnitest_JNITools.h ⽂件源代码:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> 
/* Header for class com_example_jnitest_JNITools */ #ifndef _Included_com_example_jnitest_JNITools 
#define _Included_com_example_jnitest_JNITools 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
 * Class:     com_example_jnitest_JNITools 
 * Method:    getStringFromJNI 
 * Signature: ()Ljava/lang/String; 
 */ 
JNIEXPORT jstring JNICALL 
Java_com_example_jnitest_JNITools_getStringFromJNI   (JNIEnv *, jclass); 
#ifdef __cplusplus 
} 
#endif 
#endif 
jni_tool.c源代码:
#include "com_example_jnitest_JNITools.h" 
JNIEXPORT jstring JNICALL 
Java_com_example_jnitest_JNITools_getStringFromJNI 
  (JNIEnv *env, jobject obj){ 
return (*env)->NewStringUTF(env,"Hellow World,这是我的 NDK的第⼀⾏ 代码"); 
  } 

注意:include进来是 com_example_jnitest_JNITools.h⽂件,⽅法名与 com_example_jnitest_JNITools.h⾥⽅法名保持⼀致

5.cd到 jni⽬录,运⾏ ndk-build

此时会报以下错误信息:

Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.    
Android NDK: WARNING: APP_PLATFORM android-16 is higher than 
android:minSdkVersion 1 in /Users/maolijun298/AndroidStudioProjects/JniTest/ app/src/main/AndroidManifest.xml. NDK binaries will *not* be compatible with devices older than android-16. See https://android.googlesource.com/platform/ ndk/+/master/docs/user/common_problems.md for more information.    Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: /Users/ maolijun298/AndroidStudioProjects/JniTest/app/src/main/jni/Android.mk    /Users/maolijun298/Library/Android/sdk/ndk/21.3.6528147/build/core/add- application.mk:88: *** Android NDK: Aborting...    .  Stop. 
原因是因为没有 Android.mk文件 。

6.添加Android.mk文件

新建Android.mk文件到jni目录

Android.mk文件内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := jni_tool

LOCAL_SRC_FILES := jni_tool.c

include $(BUILD_SHARED_LIBRARY)

7.引用so

添加完成后,再次 cd到 jni⽬录,运⾏ ndk-build,会⽣成 libs⽂件夹和对应的 so库。 生成了libs对应的so库之后,需要在app的build.gradle文件里引用so路径。

build.gradle

android { 
sourceSets{ 
main{ 
jniLibs.srcDirs+=['src/main/java/libs'] } 
} 
}

7.加载so

最后,在JNITools里面加载so文件

package com.example.jnitest; 
public class JNITools { 
static { 
        System.loadLibrary("jni_tool"); 
    } 
public static native String getStringFromJNI(); } 

8.运行

最后,sync一下代码,然后运行,界面就会显示出c代码里输出的文案:

Hellow World,这是我的 NDK的第⼀⾏ 代码

以上流程亲测可用,欢迎指正!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • android View事件分发实测

    主要测试dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent方法调用流程。

    用户7744319
  • 「okhttp」Gradle引用改jar包引用(一波三折)

    正常引用okhttp在build.gradle里面添加一行api 'com.squareup.okhttp3:okhttp:3.10.0'就可以了。

    用户7744319
  • Activity启动时生命周期汇总

    A—>B—>C A在onCreate时启动B; B在onCreate时启动C; 每个页面均不透明;

    用户7744319
  • Android实现BannerLayout图文轮播功能

    本文实例为大家分享了Android实现BannerLayout图文轮播功能的具体代码,供大家参考,具体内容如下

    砸漏
  • Android Studio对ndk开发调试的支持前言支持版本对ndk-build的支持对CMake的支持

    编写C/C++代码最大的痛苦就是语法提示和调试,早期Android Studio对NDK不做支持或者支持得不够好,导致NDK开发异常缓慢,最大的问题是调试,经常...

    用户2930595
  • Android实现自动播放图片功能

    本文实例为大家分享了Android实现自动播放图片功能的具体代码,供大家参考,具体内容如下

    砸漏
  • Android 使用AsyncTask实现断点续传

    之前公司里面项目的下载模块都是使用xUtils提供的,最近看了下xUtils的源码,它里面也是使用AsyncTask来执行异步任务的,它的下载也包含了断点续传的...

    砸漏
  • Android 实现可任意拖动的悬浮窗功能(类似悬浮球)

    最近开发项目中,有个在屏幕上任意拖动的悬浮窗功能,其实就是利用 WindowManager的api来完成这个需求,具体的实现的功能如下: 1.自定义view

    砸漏
  • 使用PSAD检测CVM入侵

    网络入侵检测的应用程序可以监控可疑流量并测试安全漏洞的网络接口。在本文中,我们将配置一个名为psad工具来监控我们的防火墙日志,并确定是否有问题。

    朝朝
  • android实现手机与单片机蓝牙模块通信

    本文实例为大家分享了android实现手机与单片机蓝牙模块通信的具体代码,供大家参考,具体内容如下

    砸漏

扫码关注云+社区

领取腾讯云代金券