zoukankan      html  css  js  c++  java
  • AndroidStudio 配置NDK/JNI开发环境

    AndroidStudio 配置NDK/JNI开发环境

    1、新建你的 AS 工程

    2、在 AndroidStudio 中配置 NDK 路径

      方法如下:

      (1)先下载NDK并安装(这句基本是废话);

      (2)点菜单栏的 File->ProjectStructure…-> 在打开的窗口中左侧选中 SDKLocation-> 在右侧 Android NDK Location 中填入 NDK 目录所在路径,如下图所示:

                                      

      (3)首先写好我们的 java 文件

      如果有朋友不明白这里怎么写的,可以看我 JNI 栏第一、二篇文章

      JNI 原理介绍及最简单实例代码

      JNI 最简单例程步骤详解

       

                                 

      先创建好我们的 JNITest.java 文件,内容如下:

    1 package com.clay.example;
    2 
    3 public class JNITest {
    4     public native String getJNIString();
    5 }

      (4)使用 javah 命令行生成 jni 目录及对应的头文件:

      这里我们使用 Android studio 的命令行终端就行,毕竟打开默认就是工程根目录,这里进行的 javac、javah 参数释义不再描述,前面两篇博文讲的很明白了,不清楚的同学可以去看看前面两篇博客。

                                             

      经过 javac 编译过后,我们看到了 JNITest.java 生成的 JNITest.class 文件

      我们使用 javah 生成 .h 文件

       生成的 .h 文件内容如下:com_clay_example_JNITest.h

     1 /* DO NOT EDIT THIS FILE - it is machine generated */
     2 #include <jni.h>
     3 /* Header for class com_clay_example_JNITest */
     4 
     5 #ifndef _Included_com_clay_example_JNITest
     6 #define _Included_com_clay_example_JNITest
     7 #ifdef __cplusplus
     8 extern "C" {
     9 #endif
    10 /*
    11  * Class:     com_clay_example_JNITest
    12  * Method:    getJNIString
    13  * Signature: ()Ljava/lang/String;
    14  */
    15 JNIEXPORT jstring JNICALL Java_com_clay_example_JNITest_getJNIString
    16   (JNIEnv *, jobject);
    17 
    18 #ifdef __cplusplus
    19 }
    20 #endif
    21 #endif

      创建我们所需的 C/C++ Source File

       这里我们选择 .c 文件(C跟C++也没什么区别)

     1 //
     2 // Created by zhengchuanyu on 20-12-9.
     3 //
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 #include <jni.h>
     7 
     8 JNIEXPORT jstring JNICALL Java_com_clay_example_JNITest_getJNIString
     9 (JNIEnv* env, jobject obj)
    10 {
    11     return (*env)->NewStringUTF(env, "Hello From JNITest Function(getJNIString)");
    12 }

      如果是 .cpp 文件

     1 //
     2 // Created by zhengchuanyu on 20-12-9.
     3 //
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 #include <jni.h>
     7 
     8 JNIEXPORT jstring JNICALL Java_com_clay_example_JNITest_getJNIString
     9 (JNIEnv* env, jobject obj)
    10 {
    11     return env->NewStringUTF(env, "Hello From JNITest Function(getJNIString)");
    12 }

      在 jni 目录下创建 Android.mk 文件:

    1 LOCAL_PATH := $(call my-dir)
    2 
    3 include $(CLEAR_VARS)
    4 
    5 LOCAL_MODULE := JNITest
    6 LOCAL_SRC_FILES := 
    7 JNITest.c 
    8 
    9 include $(BUILD_SHARED_LIBRARY)

      在 jni 目录下创建 Application.mk 文件(事实上这个可以不创建,但是还是讲一下吧)这一步的配置我嫌改 AndroidManifest.xml 跟 build.gradle 麻烦就没添加,如果你有兴趣可以去捣鼓一下,我自己也没有捣鼓明白,后面捣鼓明白了再补充上来。

    1 APP_STL := gnustl_static
    2 APP_CPPFLAGS := -frtti -fexceptions
    3 # APP_ABI:是将要生成哪些 cpu 类型的 so, all 代表全部
    4 APP_ABI := all
    5 #APP——PLATFORM:生成的 so 的最低 android 版本
    6 APP_PLATFORM := android-8

      在这里,我们会定义几个变量:

        LOCAL_PATH:        其值是 call my-dir,而 my-dir 是个宏函数,会返回 Android.mk 所在的路径,在这里,就是 jni 文件夹。

        include $(CLEAR_VARS),      这个命令会清除掉所有 LOCAL 开头的变量,比如 LOCAL_MODULE 之类的,但有一个例外,就是其上面的 LOCAL_PATH 。

        LOCAL_MODULE:      要生成的 so 包名,也是 Android 中 Java 代码加载时的名称。

        LOCAL_SRC_FILES:       要进行编译的源文件,如在这里,有JNITest.c。

        include $(BUILD_SHARED_LIBRARY):表明生成一个动态链接库。

        定义后这样一个Android.mk文件之后,在命令行中调用 ndk-build 命令,如下:

        ndk-build:command not found 请点击此链接  ndk-build:command not found

      命令实行之后,我们可以在项目目录下看到 libs 中多了一个 so 库,如下:

      到这里,关于Jni实现的就结束了,接下来就是如何在Android中使用这个本地方法了。

      我们创建了一个 Activity,在它里面只放置一个 TextView 控件,它的布局如下:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     xmlns:tools="http://schemas.android.com/tools"
     4     android:layout_width="match_parent"
     5     android:layout_height="match_parent"
     6     tools:context=".MainActivity">
     7 
     8     <TextView
     9         android:id="@+id/text"
    10         android:layout_width="match_parent"
    11         android:layout_height="wrap_content"
    12         android:text="test"
    13         android:textSize="20dp"/>
    14 </LinearLayout>

      然后在 Activity 中,我们要加载这个 so 库,如下:

     1 package com.clay.example;
     2 
     3 import androidx.appcompat.app.AppCompatActivity;
     4 
     5 import android.os.Bundle;
     6 import android.widget.TextView;
     7 
     8 import org.w3c.dom.Text;
     9 
    10 public class MainActivity extends AppCompatActivity {
    11 
    12     static {
    13         System.loadLibrary("JNITest");
    14     }
    15 
    16     @Override
    17     protected void onCreate(Bundle savedInstanceState) {
    18         super.onCreate(savedInstanceState);
    19         setContentView(R.layout.activity_main);
    20         TextView textView = (TextView) findViewById(R.id.text);
    21         JNITest jniTest = new JNITest();
    22         textView.setText(jniTest.getJNIString());
    23     }
    24 }

      最后还有一步要做:接下来就是使用so了,首先先与.so关联起来,有两种方法 

      (1)第一种方法,app/src/main目录下面创建一个jniLibs文件夹,将刚才生成的libs下的所有文件夹拷贝或者剪切到这里面,然后在 build.gradle中加入:

    1 android {
    2    ......
    3     sourceSets {
    4         main() {
    5             jni.srcDirs = [] //屏蔽掉默认的jni编译生成过程
    6         }
    7     }
    8 }

      (2)第二种方法,直接在 gradle 中加入

    1     sourceSets.main {
    2             jni.srcDirs = []  //屏蔽掉默认的jni编译生成过程
    3         jniLibs.srcDir 'src/main/libs' 
    4   }
    1 android {
    2    ......
    3     sourceSets {
    4         main() {
    5             jniLibs.srcDirs = ['src/main/libs']
    6             jni.srcDirs = [] //屏蔽掉默认的jni编译生成过程
    7         }
    8     }
    9 }

      1)利用 static 静态代码块,加载 so 库文件,可以看到在这里,这个名称就是 Anrdoid.mk 中定义的 LOCAL_MODULE 值。

      2)创建  JNITest 对象,调用其 getJNIString() 方法,最终显示结果如下:

      最后,我们总结一下这几个步骤:

      1)创建 Java 类文件,并定义 Native 方法,如 JNITest 类。

      2)利用 javac 生成 class 文件,利用 javah 生成 C/C++ 头文件,在这里要注意 (javah -d <path>(要生成的.h文件的目录) -classpath <path>(类所在的根目录) -jni -v(输出详细信息)) 的使用方法

      3)编写对应的C文件,如 JNITest.c,在里面实现C/C++的方法,记得要放在 jni 文件夹下面。

      4)编写 Android.mk 文件,利用 ndk-build 命令生成 so 文件。

      5)在 Android 中利用 static 静态代码块,调用 system.loadLibrary 方法来加载 so 库文件。

      6)在 build.gradle 中关联 ndk-build 编译出来的 so 库文件。

      7)在 Java 逻辑中调用之前定义的 JNITest 类的方法。

    结束。

  • 相关阅读:
    gateone DSM 8271
    手机
    epub- https://www.taoshudang.com/
    [outlook] [vba] Highlight text in body of incoming emails
    HDMI ARC功能详解及应用介绍
    蓝光播放机
    surfingkeys
    亿格瑞A5-hdmi故障了
    解决VS无法连接到已配置的开发web服务器或者部署在IIS上的web服务打不开的问题
    解决远程连接mysql很慢的方法
  • 原文地址:https://www.cnblogs.com/Reverse-xiaoyu/p/14110735.html
Copyright © 2011-2022 走看看