资讯专栏INFORMATION COLUMN

NDK 高级编程(笔记)

arashicage / 1983人阅读

摘要:开发中针对的书籍很少,也是出版的比较早的一本书,有些内容可能对现在的开发并不适用。但是书中介绍的内容比较全面,难度也不是很大,对于开发有很大帮助,特别是在开发的配置和代码规范上。

Android 开发中针对 NDK 的书籍很少,《Pro Android C++ with the NDK》也是出版的比较早的一本书,有些内容可能对现在的开发并不适用。但是书中介绍的内容比较全面,难度也不是很大,对于 NDK 开发有很大帮助,特别是在 NDK 开发的配置和代码规范上。

0x02 深入了解 Android NDK

创建项目时 Android.mk 文件的构建:Android.mk配置参数

ndk-build 脚本参数

#NDK 项目位置
ndk-build -C /path/to/the/project

#强制重构所有代码
ndk-build -B

#清除生成的二进制文件和目标文件
ndk-build clean

#并行构建命令
ndk-build -j 4
0x03 用 JNI 实现与原生代码通信

jni 的开发基础知识,参考:

NDK开发 - JNI开发流程

NDK开发 - JNI数据类型与Java数据类型映射关系

NDK开发 - JNI基本数据和字符串处理

NDK开发 - JNI数组数据处理

NDK开发 - C/C++ 访问 Java 变量和方法

NDK开发-JNI 局部引用、全局引用和弱全局引用

0x05 日志、调试及故障处理 5.1 原生日志 API
//头文件
#include 

//Android.mk
LOCAL_LALIBS += -llog

_android_log_write(ANDROID_LOG_DEBUG, "hello-jni", "debug log.")

//多参数封装
static void logMessage(JNIEnv *env, jobject obj, const char *format, ...) {
    static jmethodID methodID = NULL;
    if (NULL == methodID) {
        jclass clazz = env->GetObjectClass(obj);
        methodID = env->GetMethodID(clazz, "logMessage", "(Ljava/lang/String;)V");
        env->DeleteLocalRef(clazz);
    }
    if(methodID != NULL) {
        char buffer[MAX_LOG_MSG_LENGTH];
        va_list ap;
        va_start(ap, format); //指向 format 后可变参数的地址
        vsnprintf(buffer, MAX_LOG_MSG_LENGTH, format, ap);
        va_end(ap);

        jstring message = env->NewStringUTF(buffer);
        if (message != NULL) {
            env->CallVoidMethod(obj, methodID, message);
            env->DeleteLocalRef(message);
        }
    }
}
5.2 重定向 Android 日志
adb shell stop
adb shell setprop log.redirect-stdio true
adb shell start
5.3 故障处理

1.堆栈分析

#ndk-stack
adb logcat | ndk-stack -sym obj/local/armeabi

#arm-linux-androideabi-addr2line
arm-linux-androideabi-addr2line -e obj/local/armeabi-v7a/libtongdun.so 0002197e

2.启用 CheckJNI:

adb shell setprop debug.checkjni 1
5.4 内存问题

1.打开 libc 调试模式

adb shell setprop libc.debug.malloc 1
adb shell stop
adb shell start

2.strace 工具

#获取进程
adb shell ps | grep packagename

#附加进程
adb shell strace -v -p 
0x07 原生线程

源码地址: ndk-pro/threads

1.POSIX 线程返回结果

//1.线程句柄 2.返回值指针
int pthread_join(pthread_t thread, void** ret_val);

2.POSIX 线程同步

static pthread_mutex_t mutex;

//初始化
int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexarrt_t* attr);

//锁定
int pthread_mutex_lock(pthread_mutex_t* mutex);

//解锁
int pthread_mutex_unlock(pthread_mutex_t* mutex);

//销毁
int pthread_mutex_destroy(pthread_mutex_t* mutex);

3.使用信号量同步 POSIX 线程

//头文件
#include 

//初始化
extern int sem_init(sem_t* sem, int pshared, unsigned int value);

//锁定信号
extern int sem_wait(sem_t* sem);

//解锁
extern int sem_post(sem_t* sem);

//销毁
extern int sem_destroy(sem_t* sem);
0x08/09/10 POSIX Socket API

TCP && UDP

源码地址: pro-ndk/echo

0x11 支持 C++ 11.1 支持的 C++ 运行库

C++系统运行库 不支持:C++标准库、 异常支持库、 RTTI 支持

GAbi++、 STLport、 GUN STL

11.2 指定 C++ 运行库
//Application.mk
APP_STL := system //默认
APP_STL := gabi++_static
APP_STL := gabi++_shared
APP_STL := stlport_static
APP_STL := stlport_shared
APP_STL := gunstl_static
APP_STL := gunstl_shared

//1.项目只有一个单一的原生模块时支持静态库
//2.项目中包含多个原生模块时使用动态库
//3.动态库使用时需要先加载 
System.loadLibrary(“strport_shared”)
11.4 C++支持异常
//单个模块 Android.mk
LOCAL_CPP_FEATURES += exceptions

//支持所有原生模块 Application.mk
APP_CPPFLAGS += -fexceptions
11.5 C++ RTTI 支持(Run-Time Type Information)

在运行库展示对象类型信息,只要用于执行安全类型转化。

//单个模块 Android.mk
LOCAL_CPP_FEATURES += rtti

//支持所有原生模块 Application.mk
APP_CPPFLAGS += -frtti
11.6 C++ 标准库

容器

序列

vector 支持随机访问,末尾常量插入删除 其他线性

deque 与 vector支持随机访问 选择实现队列的基础

list 双向列表

slist 单项链表

关联容器

排序关联容器 操作复杂度不超过对数阶

set 已排序,不重复

map 键值对,不重复

multiset 已排序,多重关联,允许重复

multimap 对拥有相同键值的元素数量不限制

哈希关联容器 查询时间快

hashed_set 不重复

hash_map

hash_multiset 允许重复

hash_multimap 允许重复

适配器

stack 堆栈 LIFO (Last In First Out)

queue 队列 FIFO (First In First Out)

String

迭代器

11.8 C++ 运行库调试模式
//GUN STL 调试模式
LOCAL_CFLAGS += -D_GLIBCXX_DEBUG

//STLport 调试模式
LOCAL_CFLAGS += -D_STLP_DEBUG

//日志重定向到 Android 日志 
LOCAL_CFLAGS += -D_STLP_DEBUG
LOCAL_CFLAGS += -D_STLP_DEBUG_MESSAGE
LOCAL_LDLIBS += —llog

void __stl_debug_message(const char* format_str, …){
    va_list ap;
    va_start(ap, format_str);
    __android_log_vprint(ANDROID_LOG_FATAL, “STLport”, format_str, ap);
    va_end(ap);
}
0x12 原生图形 API

源码地址: ndk-pro/abiplayer

0x14 程序概要分析和 NEON 优化

android-ndk-profiler

NEON 指令:并不是所有基于 ARM-V7a 的设备都支持 NEON 指令

原文地址:NDK 高级编程(笔记)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/13823.html

相关文章

  • Android程序员到底有多累,多辛苦?

    摘要:其实,这种时候,需要做的是马上买空气净化器,任何一款都好,哪怕是净化能力差一点的,也能解决当前的主要问题,更好的净化器带给你的净化效果的提升,不过是多一点边际收益。 前言 说到底,是自己的选择问题。 三百六十行,哪行容易? 但关键是自己的心态,如果工作成了你的负担和困扰,你得有跳出来的...

    adam1q84 评论0 收藏0
  • Android程序员完全没时间提升自己怎么办?

    摘要:昨天有个小学弟给我发来微信,说他现在有点后悔选择开发了,月月光不说,还加班特别严重,平时也没有属于自己的时间去学习,问我刚毕业的时候是不是这样。每天回到出租屋都是倒头就睡,非常累,也没有其他时间提升自己的技术。 昨天有个小学弟给我发来微信,说他现在有点后悔选择Android开发了,月月光不说...

    kohoh_ 评论0 收藏0
  • Flutter 里的语法糖解析,知其所然方能潇洒舞剑,字节Android高级

    摘要:所以当我们访问声明的对象时,如果对象还没有初始化,就会返回一个异常。所以对于编译后的代码,并不会对性能和运行结果产生影响。 如下图所示,通过提取编译后的代码,「可以看到 playerAnimation 其实被转变成了 Animation? 的可空对象」,而当 playerAnimation 被调用时,通过 ge...

    不知名网友 评论0 收藏0
  • 30 岁的安卓程序员还有出路吗,应该怎么规划?

    摘要:在舒伯的生涯阶段里有个确立阶段,岁岁。知识技术安卓程序员需要掌握编程语言应用框架开发工具等这些具体的知识和技术。技术能力与阅历对安卓程序员来讲,知识技术是一方面,是容易习得的,是较浅的层面。 大龄程序员的界定 老早网上有人说,安卓开发干不过30岁,后来又有人说干不过35岁,后来又有人说干不过...

    不知名网友 评论0 收藏0
  • android知识学习 - 收藏集 - 掘金

    摘要:从邮件内容来看,估计和权限知识学习笔记掘金最近在项目上因为运行时权限吃了亏,发现之前对运行时权限的理解不足,决定回炉重造,重新学习一下。 浅谈 Android Service - 掘金前言:本文所写的是博主的个人见解,如有错误或者不恰当之处,欢迎私信博主,加以改正!原文链接 ,demo链接 Serviec(服务)简述 什么是ServiceService 是一个可以在后台执行长时间运行操...

    WrBug 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<