深入浅出安卓中的C++

150 阅读3分钟

深入浅出安卓中的C++

一、安卓为啥要用C++?

安卓就像混血儿

  • Java/Kotlin:处理UI、业务逻辑(像大脑)
  • C++:干重活(像肌肉):
    • 高性能计算(游戏/音视频)
    • 复用现有C++库(OpenCV/FFmpeg)
    • 底层硬件操作(传感器/图形渲染)

二、JNI基础(Java与C++的翻译官)

1. JNI工作原理

    Java ->> C++调用native方法
    C++调用native方法 ->> Java通过JNIEnv操作Java

2. 定义native方法

// Java层声明
public class NativeLib {
    public native int add(int a, int b); // native关键字
}

3. C++实现

// native-lib.cpp
#include <jni.h>

extern "C" JNIEXPORT jint JNICALL
Java_com_example_NativeLib_add(JNIEnv* env, jobject thiz, jint a, jint b) {
    return a + b; // 简单的加法
}

方法名规则Java_包名_类名_方法名

三、NDK开发四步走

1. 配置NDK(Android Studio)

// build.gradle
android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++17"
            }
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt" // CMake配置文件
        }
    }
}

2. 编写CMakeLists.txt

cmake_minimum_required(VERSION 3.10.2)
project("native-lib")

add_library( # 库名称
             native-lib
             # 类型:SHARED动态库
             SHARED
             # 源文件
             src/main/cpp/native-lib.cpp )

find_library( # 查找系统库
              log-lib
              log )

target_link_libraries( # 链接库
                       native-lib
                       ${log-lib} )

3. Java加载库

public class NativeLib {
    static {
        System.loadLibrary("native-lib"); // 加载so库
    }
    public native String getMessage();
}

4. C++与Java交互

// 调用Java方法示例
extern "C" JNIEXPORT void JNICALL
Java_com_example_NativeLib_callJavaMethod(JNIEnv* env, jobject thiz) {
    jclass clazz = env->GetObjectClass(thiz);
    jmethodID method = env->GetMethodID(clazz, "showToast", "(Ljava/lang/String;)V");
    jstring msg = env->NewStringUTF("来自C++的问候");
    env->CallVoidMethod(thiz, method, msg);
}

四、数据类型对照表

Java类型C++类型JNI类型
booleanbooljboolean
intint32_tjint
longint64_tjlong
Stringchar*jstring
byte[]uint8_t*jbyteArray

五、性能优化技巧

1. 减少JNI调用

错误示范

// Java循环调用native方法
for (int i = 0; i < 1000; i++) {
    nativeProcess(data[i]); // 每次都有JNI开销
}

正确做法

// 一次性传递数据
nativeBatchProcess(data); // C++内部循环

2. 直接内存访问

// 获取Java数组的直接指针
jbyte* buffer = env->GetByteArrayElements(javaArray, NULL);
// 直接操作内存...
env->ReleaseByteArrayElements(javaArray, buffer, 0); // 必须释放!

3. 线程管理

  • JNIEnv:每个线程需要独立获取
    JavaVM* gVm;
    JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
        gVm = vm; // 保存全局引用
        return JNI_VERSION_1_6;
    }
    
    void nativeThread() {
        JNIEnv* env;
        gVm->AttachCurrentThread(&env, NULL);
        // 使用env...
        gVm->DetachCurrentThread();
    }
    

六、实战案例:图像处理

1. Java层定义

public class ImageProcessor {
    public native void blurBitmap(Bitmap bitmap, int radius);
}

2. C++实现

#include <android/bitmap.h>

extern "C" JNIEXPORT void JNICALL
Java_com_example_ImageProcessor_blurBitmap(JNIEnv* env, jobject, jobject bitmap, jint radius) {
    AndroidBitmapInfo info;
    AndroidBitmap_getInfo(env, bitmap, &info);
    
    void* pixels;
    AndroidBitmap_lockPixels(env, bitmap, &pixels); // 锁定内存
    
    // 使用C++实现高斯模糊(示例伪代码)
    applyGaussianBlur((uint8_t*)pixels, info.width, info.height, radius);
    
    AndroidBitmap_unlockPixels(env, bitmap); // 解锁
}

七、常见问题

1. Crash排查

  • 错误信息java_vm_ext.cc:577] JNI DETECTED ERROR IN APPLICATION
  • 解决步骤
    1. 检查adb logcat崩溃堆栈
    2. 使用addr2line定位so库错误位置
      ndk-stack -sym ./obj/local/armeabi-v7a -dump crash.log
      

2. 内存泄漏

  • JNI引用:及时删除局部引用
    jstring jstr = env->NewStringUTF("hello");
    // 使用完后...
    env->DeleteLocalRef(jstr);
    

3. 兼容性问题

  • ABI适配:为不同CPU架构编译
    android {
        defaultConfig {
            ndk {
                abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86'
            }
        }
    }
    

八、进阶方向

1. 现代C++特性

  • 智能指针:避免内存泄漏
    std::unique_ptr<int[]> buffer(new int[100]);
    
  • 多线程std::thread + 原子操作

2. 混合调试

  • Android Studio:同时调试Java和C++代码
  • LLDB:命令行调试工具

3. 高性能库

  • NEON指令集:ARM芯片加速
  • RenderScript:Google提供的并行计算框架

九、终极口诀

"JavaC++手拉手,JNI来做翻译官
NDK配置CMake,类型转换要小心
减少跨语言调用,直接访问性能高
内存线程管理好,兼容问题早排查"

掌握安卓C++开发,你就能让App既聪明又有力气! 💪🧠