Android App开发JNI环境配置
Posted 哟吼!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android App开发JNI环境配置相关的知识,希望对你有一定的参考价值。
因为想写一个native_crash的app做测试,所以搭建一个这样的jni环境。
jni环境配置可以自己写配置文件,也可以使用Android Studio自动生成。下面我们用Android Studio为IDE来进行JNI环境配置
参考文章:Android - JNI环境搭建和简单案例入门
概念
JNI:Java Native Interface。实现java 与本地语言(android是linex系统开发的,语言是c/c++) 的相互调用。
NDK:Native Development Kit。用来模拟另一个平台特性进行编译的工具集合,能够快速开发C(或C++)的动态库,能自动将so和java应用一起打包成apk。
在android的JNI中,要先将相应的C/C++语言打包生成.so文件(c++的函数库),然后导入到lib文件夹中供java调用。
需要的工具:
Android 原生开发工具包 (NDK)
CMake:一款外部构建工具,可与 Gradle 搭配使用来构建原生库。
AS搭建JNI环境(方法一)
在SDK 管理器安装NDK和CMake
注:如果选择23.x及以上版本的ndk,toolchains目录下就缺失了aarch64-linux-android-4.9 这个目录,导致工程编译失败报错。所以安装23以下的版本:22.1.7171670
在app的build.gradle中指定ndk版本号(这一步我直接省略了,因为我原来就有app的开发环境,sdk那些东西我早就配置好了,所以我可以直接用Android Studio来帮我编译。所以下面我介绍两种编译方法):
app项目文件
创建一个空的项目
添加一个目录,再添加两个文件
hellojni.c
#include <stdio.h>
#include <jni.h>
JNIEXPORT jstring JNICALL Java_com_lixiang_jniapptest_MainActivity_helloJNI(JNIEnv *env, jobject thiz)
char* str = "hello from c!!";
int a = 2/0; //这两行是用来创建native_crash的
str += a;
return (*env)->NewStringUTF(env,str);
CMakeLists.txt
# 设置构建native library所需的CMake最低版本。
cmake_minimum_required(VERSION 3.4.1)
#创建一个库(多次调用add_library即可创建多个库)
add_library( # 设置库的名称
hellojni
# 将库设置为共享库(即so文件)
SHARED
# 指定源文件的相对路径
hellojni.c )
在app的build.gradle中
android
...
defaultConfig
applicationId "com.lixiang.jniapptest"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
...
MainActivity.java(需要做一些修改)
package com.lixiang.jniapptest; import android.os.Bundle; import com.google.android.material.snackbar.Snackbar; import androidx.appcompat.app.AppCompatActivity; import android.view.View; import androidx.navigation.NavController; import androidx.navigation.Navigation; import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI; import com.lixiang.jniapptest.databinding.ActivityMainBinding; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; public class MainActivity extends AppCompatActivity private AppBarConfiguration appBarConfiguration; private ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); setSupportActionBar(binding.toolbar); NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build(); NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); binding.fab.setOnClickListener(new View.OnClickListener() @Override public void onClick(View view) Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); ); System.loadLibrary("hellojni"); Toast.makeText(getApplicationContext(), helloJNI(), Toast.LENGTH_SHORT).show(); public void hello(View view) //加载c代码生成的.so文件,so库的名称在描述文件中配置 System.loadLibrary("hellojni"); //调用处 //ToastUtils.showMessage(helloJNI()); public native String helloJNI(); @Override public boolean onCreateOptionsMenu(Menu menu) // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; @Override public boolean onOptionsItemSelected(MenuItem item) // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) return true; return super.onOptionsItemSelected(item); @Override public boolean onSupportNavigateUp() NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp();
编译方法一(适合没有配置过app开发环境的)
配置path环境变量
1)打开File > Project Structure > SDK Location,选择默认NDK的路径并复制。
如果此处点击apply提示“NDK does not contain any platforms”表示版本过高,需下载更低版本的NDK。
2)右击我的电脑>属性>高级系统设置>环境变量>新建,添加一个系统变量NDK_HOME,并把刚才复制的ndk-bundle的路径填上去
3)给Path系统变量(不需要创建),新建一个%NDK_HOME%
验证是否配置成功
在Terminal/cmd中直接输入 ndk-build,出现如下内容配置成功。未出现请重启电脑(踩坑2)
其他:如还未配置成功请看是否配置以下两处:
编译方法二(配置过app开发环境)
Build->Build Bundle(s)/APK(s)->Build APK(s)生成一个apk文件
生成的apk文件点击locate会打开那个文件夹(我的文件生成路径在AndroidStudioProjects/app/build/outputs/apk/debug)
AS搭建JNI环境(方法二)
因为我是有app开发环境的,所以我可以直接生成JNI环境,没有下载过nkd、sdk那些估计不可以
选择Native C++,剩下就是填一下项目名,然后一直Next->Finish。
我的Setting设置如下:
以上是关于Android App开发JNI环境配置的主要内容,如果未能解决你的问题,请参考以下文章