Android Studio 3.0.1

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

然后搜索到 Android Studio 的文档 向您的项目添加 C 和 C++ 代码

原生库构建的默认工具是 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 的路径去掉.
都弄好后在现有工程上根据上面的分析配置环境, 现在 c++文件都存放在 app/src/main/cpp 路径下了.

将 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             .             .             .)


需要包含的源文件添加到 add_library 函数中,但是文件有好多,一个一个加得累死,幸好 CMake 有一个命令 aux_source_directory ,查找在某个路径下的所有源文件,将搜索到的源文件列表存储到指定的变量中.就像这样

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})

用aux_source_directory命令的一个缺点就是你添加新的源文件的时候,它不会触发 CMake 编译,你得手动重新运行CMake.


现在编译会报错 
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']
然后编译报错
Error:(44, 9) error: reinterpret_cast from 'pthread_t' (aka 'long') to 'pid_t' (aka 'int') is not allowed
出错文件为 platform_thread.cc 文件,看了源码后发现还是确实宏定义,因为现在是在给 android 编译,
所以在 CMakeLists.txt 文件中添加 add_definitions(-DWEBRTC_ANDROID)

没有报错,然后在测试 cpp 文件中引用 #include "webrtc_vad.h"

编译报错
Error:(10, 10) fatal error: 'webrtc_vad.h' file not found

解决方式是 在 CMakeLists.txt 中添加 引用头文件
include_directories(src/main/cpp/vad_src/)

编译成功.

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} )

build.gradle

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'}

测试文件 native-lib.cpp

#include #include #include #include #include #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;}

java文件

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) ;}




更多相关文章

  1. 用Socket实现PC和手机的文件传输
  2. Android声音焦点----从音乐回到Luncher调节音量显示的是Music的
  3. Please ensure that adb is correctly located at '/home/lq/and
  4. Android(安卓)选择文件并加载数据到界面
  5. Android(安卓)的一些提示框
  6. Android(安卓)widget 之RemoteView
  7. Android(安卓)编解码
  8. Android记录2013年10月20日
  9. android 设置开机不自动进入锁屏状态

随机推荐

  1. XML—DOM解析案例
  2. XML的解析
  3. xml学习(3) html显示xml
  4. XML包导入和处理XML数据格式|R包
  5. XML—XML解析之SAX
  6. xml学习(2)xml文档树结构图
  7. R语言XML格式数据导入与处理 - ShangFR
  8. xml学习(1)xml的几种文件格式
  9. XML—XML解析之DOM
  10. XML Http Request最新替代技术—— Fetch