您的位置:首页 > 移动开发 > Android开发

android jni方式调用c++代码并在其它app中使用生成的.so文件

2016-10-18 21:46 806 查看
搞了一下午终于明白了一点机制,网上的代码太乱了,很多不经过验证就转载的,强烈谴责这种行为。以下所写都是android studio测试运行过的,欢迎交流指正。运行前提是在project structure中配置好ndk路径,并且配置好ndk环境变量。想看入门demo的童鞋不要再到处下载了,ndk文件目录下有一个samples,里面都是官方demo,例如hello-jni,不过是eclipse的项目。如果能帮到你,记得点个赞。

概括一下主要步骤:下载并配置ndk环境变量,并在studio中指明一致的ndk路径——>编写native方法名,根据生成的对应.h文件,用c或者cpp实现对应方法,并将.h和.cpp或者.c文件放到jni目录下——>在build.gradle文件中添加ndk属性,在jni目录下创建Android.mk和Application.mk文件,rebuild。

注意:.c和.cpp的格式的一模一样功能的函数有可能是不同的写法,并且.cpp一定要加extern “C” { } ,一定要注意,否则可能No implement了就。

具体可以参考这篇文章:http://blog.csdn.net/fengbingchun/article/details/11580983

一、使用android jni调用c++代码

①.在java代码中声明native方法

public class NdkJniUtils {
public static native String getCLanguageString();
}


②.打开view->tool windows->terminal,cd到app项目的java目录下,cd app/src/main/java。然后进行如下操作,也就是包名+native方法声明的class名,稍后会生成一个.h文件:

javah -jni com.lbb.hellojnitest.NdkJniUtils


.h文件内容如下,机器生成的文件不需要修改:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lbb_hellojnitest_NdkJniUtils */

#ifndef _Included_com_lbb_hellojnitest_NdkJniUtils
#define _Included_com_lbb_hellojnitest_NdkJniUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     com_lbb_hellojnitest_NdkJniUtils
* Method:    getCLanguageString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_lbb_hellojnitest_NdkJniUtils_getCLanguageString
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


③.在和app模型java目录并列创建jni文件夹,将生成的com_lbb_hellojnitest_NdkJniUtils.h文件剪切进去。然后创建main.c文件,文件名字是任意的。内容如下,主要是实现机器生成的头文件的声明的方法:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <com_lbb_hellojnitest_NdkJniUtils.h>

JNIEXPORT jstring
JNICALL Java_com_lbb_hellojnitest_NdkJniUtils_getCLanguageString(JNIEnv *env, jobject jObj){
//return env->NewStringUTF("Hello from JNI!");
return (*env)->NewStringUTF(env, "Hello From JNI!");
}


④.在app的build.gradle文件的defaultConfig下添加ndk属性,定义生成的.so文件的名称,文件名如果是以lib开头则不添加lib,否则添加lib字段,例如以下配置将在app-libs目录下生成libnativeTest.so。我的文件内容如下:

apply plugin: 'com.android.application'

android {
compileSdkVersion 24
buildToolsVersion "24.0.1"

defaultConfig {
applicationId "com.lbb.hellojnitest"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
ndk {
moduleName "nativeTest"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.2.1'
}


⑤.clean project->rebuild project,切换回project视图下在/app/build/intermediates/ndk/debug/lib目录下应该已经生成了.so文件了。此时可以在activity中调用了:

public class MainActivity extends Activity {

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//        NdkJniUtils jni = new NdkJniUtils();
Toast.makeText(this,NdkJniUtils.getCLanguageString(),Toast.LENGTH_SHORT).show();

}
static {
System.loadLibrary("nativeTest");
}

}


二、生成.so库文件供其它app调用。

完成上述步骤已经可以调用c++实现的方法了,如果想要进一步控制生成.so库文件供其它应用使用,则需要在jni目录下创建Android.mk和Application.mk,分别用于控制.so本身属性以及生成哪些cpu平台下的.so文件。关于具体介绍可以查看ndk路径下的docs->Start_Here.html官方文档。我的Android.mk和Application.mk是复制的官方demo也就是hello-jni项目下的,然后修改的。

Android.mk内容如下:

# Copyright (C) 2010 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0 #
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := nativeTest
LOCAL_SRC_FILES := main.c
include $(BUILD_SHARED_LIBRARY)


Application.mk文件内容如下:

APP_ABI := all
APP_PLATFORM := android-10


两个文件都整理好之后,在终端或者在view-Tool Windows-Terminal

终端窗口下,cd到jni目录下,执行ndk-build命令。前提是已经配置好系统ndk环境变量,如何配置请百度。执行完之后再app模型下会自动创建一个libs目录并且包含了生成的.so文件,至此.so库文件生成完毕

三、android studio其它项目中导入刚才生成的.so文件并使用

①.创建一个新的android studio 项目,将刚才生成的libs目录下的文件夹全部复制到新项目的app模型下的libs目录,然后配置app的build-cradle指定jniLibs.srcDirs目录为libs文件。我的app的build-gradle文件内容如下:

apply plugin: 'com.android.application'

android {
compileSdkVersion 24
buildToolsVersion "24.0.1"

defaultConfig {
applicationId "com.lbb.solibtest"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.2.1'
}


②.成功引入.so库文件之后要考虑调用了,我简单的认为.so文件是需要特定的包名和类名以及方法名的,所以我在此创建了和之前一样包名和类名以及方法名的类。(后来发现百度地图的.so文件也是通过引入其jar包中定义的固定包名类名的类来调用.so文件中的native方法的,所以应该是木错的)

我在此demo中我创建的是com.lbb.hellojnitest.NdkJniUtils类,类的内容如下,就是和之前项目中保持一致:

package com.lbb.hellojnitest;

/**
* 作者:李少波
* 邮箱:lishaobo@seengene.com
* 日期:16/10/18
*/
public class NdkJniUtils { public static native String getCLanguageString(); }


③.定义好之后就可以使用了,和之前的使用时一样一样的,稍微需要注意的是.so文件是以lib开头的,因为生成时系统自己添加lib,但System.loadLibrary()的时候是不用加前面的lib的。:

package com.lbb.solibtest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

import com.lbb.hellojnitest.NdkJniUtils;

public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("nativeTest");
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, NdkJniUtils.getCLanguageString(),Toast.LENGTH_SHORT).show();
}
}


我的两个demo下载链接:

http://download.csdn.net/detail/lishaobo211985/9657737
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐