赞
踩
Mac OS X 10.12.6
先配置 jni 环境,按照一年前写的文章 android Studio jni 编程 进行配置在build 工程的时候出现错误
Error:Execution failed for task ':app:compileDebugNdk'.
> Error: Your project contains C++ files but it is not using a supported native build system.
Consider using CMake or ndk-build integration. For more information, go to:
https://d.android.com/r/studio-ui/add-native-code.html
Alternatively, you can use the experimental plugin:
https://developer.android.com/r/tools/experimental-plugin.html
原生库构建的默认工具是 CMake, 所以决定改用 CMake.
首先是配置环境, 向您的项目添加 C 和 C++ 代码 中有就不详细介绍了,首先下载 NDK、CMake、LLDB.
然后创建一个只是 C++的项目看看与以前ndk-build的时候有啥不一样.
build.gradle 文件中,多了 两个 externalNativeBuild 参数 ,defaultConfig 下的 externalNativeBuild 里面的参数 是在创建工程的时候选择的,
-fexceptions 对应创建工程时的选项 Exceptions Support,是启用对 C++异常处理的支持
-frtti 对应创建工程时的选项 Runtime Type Information Support 选项,支持 RTTI 的
多了一个 CMakeyLists.txt 文件 里面的内容就4个函数
cmake_minimum_required,add_library,find_library,target_link_libraries
不同就这些,在现有工程上照着弄一遍就好了.下面下载 webrtc 源码.
在终端 执行命令
git clone https://android.googlesource.com/platform/external/webrtc
下载成功后
cd webrtc/common_audio/vad
然后将里面的文件(带 test 的不要)拷贝到统一个目录下(vad_src),然后打开 vad_core.c 文件,根据 #include 的文件路径去找到相应的文件并且把他们都拷贝到现在的目录(递归查找拷贝),并将 #include 的路径去掉.
将 vad_src 文件夹拷贝到 cpp 目录下 ,执行 Build -> Refresh Linked C++ Projects 刷新,然后修改 CMakeLists.txt文件.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp
src/main/cpp/vad_src/vad_core.c
.
.
. )
aux_source_directory(src/main/cpp/vad_src/ DIR_LIB_SRCS)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp
${DIR_LIB_SRCS})
现在编译会报错
Error:error: C++ requires a type specifier for all declarations
Error:(20, 2) error: "Must define either WEBRTC_WIN or WEBRTC_POSIX."
第二个错误 是没有宏定义的原因
在 CMakeLists.txt 文件中添加 add_definitions(-DWEBRTC_POSIX)
第一个错误 点击后会跳到c++0x_warning.h 文件有这一句
This file requires compiler and library support for the \
ISO C++ 2011 standard. This support is currently experimental, and must be \
enabled with the -std=c++11 or -std=gnu++11 compiler options.
需要启用 C++11,需要修改 build.gradle 文件 cppFlags 选项
cppFlags "-std=c++11 -frtti -fexceptions"
继续编译 错误
Error:(21, 10) fatal error: 'execinfo.h' file not found
execinfo.h 是属于glibc的,Android 用的是bionic
通过 CMake 和 C++ 库支持 知道ANDROID_STL CMake 默认用 gnustl_static,那就换一个试试
在 cppFlags 上一行添加
arguments = ['-DANDROID_STL=c++_static']
然后编译报错
CMakeLists.txt
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
aux_source_directory(src/main/cpp/vad_src/ DIR_LIB_SRCS)
add_definitions(-DWEBRTC_POSIX)
add_definitions(-DWEBRTC_ANDROID)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp
${DIR_LIB_SRCS})
include_directories(src/main/cpp/vad_src/)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.wolf.webrtc_vad"
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
arguments = ['-DANDROID_STL=c++_static']
cppFlags "-std=c++11 -frtti -fexceptions"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
- #include <jni.h>
- #include <string>
- #include <stdio.h>
- #include <assert.h>
- #include <android/log.h>
- #include "webrtc_vad.h"
-
- #define LOG_TAG "jnitest"
- #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
-
- static jstring jni_sayHello(JNIEnv *env, jobject)
- {
-
- int ret = 0;
- int i = 0;
- int kRates[] = { 8000, 12000, 16000, 24000, 32000, 48000 };
- int kMaxFrameLength = 16;
- int kFrameLengths[] = { 80, 120, 160, 240, 320, 480, 640, 960 };
- short zeros[160] = {0};
- short speech[160] = {0};
-
- for (i = 0; i < 160; i++) {
- speech[i] = (i * i);
- }
- VadInst* handle = WebRtcVad_Create();
- WebRtcVad_Init(handle);
- WebRtcVad_set_mode(handle,0);
-
- ret = WebRtcVad_Process(handle, kRates[2], speech, kFrameLengths[2]);
- LOGD("ret1 = %d\n",ret);
-
- ret = WebRtcVad_Process(handle, kRates[2], zeros, kFrameLengths[2]);
- LOGD("ret2 = %d\n",ret);
- WebRtcVad_Free(handle);
- std::string hello = "Hello from C++";
- return env->NewStringUTF(hello.c_str());
- }
-
- static jboolean jni_calcDecibelLevel(JNIEnv *env, jobject,jshortArray buffer,jint offseetInshort,jint readSize)
- {
- VadInst* handle = WebRtcVad_Create();
- WebRtcVad_Init(handle);
- WebRtcVad_set_mode(handle,0);
- short speech[160] = {0};
- int index = readSize/160;
- jshort *pcm_data = env->GetShortArrayElements(buffer, JNI_FALSE);
- bool b;
- for (int i = 0; i < index; ++i) {
- int vad = WebRtcVad_Process(handle, 16000, pcm_data+offseetInshort+i*160, 160);
- if(vad==1)
- b = JNI_TRUE;
- }
- env->ReleaseShortArrayElements(buffer,pcm_data,JNI_ABORT);
- WebRtcVad_Free(handle);
- return b;
- }
-
- /**
- * JNINativeMethod由三部分组成:(1)Java中的函数名;
- (2)函数签名,格式为(输入参数类型)返回值类型;
- (3)native函数名
- */
- static JNINativeMethod gMethods[] = {
- {"stringFromJNI", "()Ljava/lang/String;", (void *)jni_sayHello},
- {"calcDecibelLevelJNI", "([SII)Z", (void *)jni_calcDecibelLevel},
- };
-
-
- jint JNI_OnLoad(JavaVM *vm, void *reserved)
- {
- JNIEnv *env = NULL;
- jint result = JNI_FALSE;
-
- if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) { 从JavaVM获取JNIEnv
- LOGD("Error GetEnv\n");
- return result;
- }
- assert(env != NULL);
- //获取类引用,这里可以找到要注册的类,前提是这个类已经加载到java虚拟机中
- jclass clazz = env->FindClass("com/example/wolf/webrtc_vad/RecordAudioPcm");
- if (clazz == NULL) {
- return result;
- }
- //注册方法,把本地函数和一个java类方法关联起来
- if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
- return result;
- }
-
- return JNI_VERSION_1_4;
- }
- public class RecordAudioPcm {
- private static final String TAG = "RecordAudioPcm";
-
- static {
- System.loadLibrary("native-lib");
- }
- public native String stringFromJNI();
- public native boolean calcDecibelLevelJNI(short[] buffer,int offseetInshort, int readSize) ;}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。