1.å¦ä½å¨Androidä¸ä½¿ç¨JNI
2.ç¨jniåçå®ååºç¨è½è¢«åç¼è¯å
3.音视频探索(5):JPEG格式与Libjpeg库编译移植
4.Android开发中的源译NDK到底是什么?(详细解析+案例)
å¦ä½å¨Androidä¸ä½¿ç¨JNI
ãã1.å¼è¨
ããæ们ç¥éï¼Androidç³»ç»çåºå±åºç±c/c++ç¼åï¼ä¸å±Androidåºç¨ç¨åºéè¿Javaèææºè°ç¨åºå±æ¥å£ï¼è¡æ¥åºå±c/c++åºä¸Javaåºç¨ç¨åºé´çæ¥å£æ£æ¯JNIï¼JavaNative Interface)ãæ¬ææè¿°äºå¦ä½å¨ubuntuä¸é ç½®AndroidJNIçå¼åç¯å¢ï¼ä»¥åå¦ä½ç¼åä¸ä¸ªç®åçcå½æ°åºåJNIæ¥å£ï¼å¹¶éè¿ç¼åJavaç¨åºè°ç¨è¿äºæ¥å£ï¼æç»è¿è¡å¨æ¨¡æå¨ä¸çè¿ç¨ã
ãã2.ç¯å¢é ç½®
ãã2.1.å®è£ jdk1.6
ããï¼1ï¼ä»jdkå®æ¹ç½ç«ä¸è½½jdk-6u-linux-i.binæ件ã
ããï¼2ï¼æ§è¡jdkå®è£ æ件
ãã[html] view plaincopyprint?
ãã.$chmod a+x jdk-6u-linux-i.bin
ãã.$jdk-6u-linux-i.bin
ãã$chmod a+x jdk-6u-linux-i.bin
ãã$jdk-6u-linux-i.bin
ãã(3)é ç½®jdkç¯å¢åé
ãã[html] view plaincopyprint?
ãã.$sudo vim /etc/profile
ãã.#JAVAEVIRENMENT
ãã.exportJAVA_HOME=/usr/lib/java/jdk1.6.0_
ãã.exportJRE_HOME=$JAVA_HOME/jre
ãã.exportCLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
ãã.exportPATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
ãã$sudo vim /etc/profile
ãã#JAVAEVIRENMENT
ããexportJAVA_HOME=/usr/lib/java/jdk1.6.0_
ããexportJRE_HOME=$JAVA_HOME/jre
ããexportCLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
ããexportPATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
ããä¿ååéåºç¼è¾ï¼å¹¶éå¯ç³»ç»ã
ããï¼4ï¼éªè¯å®è£
ãã[html] view plaincopyprint?
ãã.$java -version
ãã.javaversion "1.6.0_"
ãã.Java(TM)SE Runtime Environment (build 1.6.0_-b)
ãã.JavaHotSpot(TM) Server VM (build .4-b, mixed mode)
ãã.$javah
ãã.ç¨æ³ï¼javah[é项]<ç±»>
ãã.å ¶ä¸[é项]å æ¬ï¼
ãã.-helpè¾åºæ¤å¸®å©æ¶æ¯å¹¶éåº
ãã.-classpath<è·¯å¾>ç¨äºè£ å ¥ç±»çè·¯å¾
ãã.-bootclasspath<è·¯å¾>ç¨äºè£ å ¥å¼å¯¼ç±»çè·¯å¾
ãã.-d<ç®å½>è¾åºç®å½
ãã.-o<æ件>è¾åºæ件ï¼åªè½ä½¿ç¨-dæ-oä¸çä¸ä¸ªï¼
ãã.-jniçæJNIæ ·å¼ç头æ件ï¼é»è®¤ï¼
ãã.-versionè¾åºçæ¬ä¿¡æ¯
ãã.-verboseå¯ç¨è¯¦ç»è¾åº
ãã.-forceå§ç»åå ¥è¾åºæ件
ãã.使ç¨å ¨éå®å称æå®<ç±»>ï¼ä¾
ãã.å¦ï¼java.lang.Objectï¼ã
ãã$java -version
ããjavaversion "1.6.0_"
ããJava(TM)SE Runtime Environment (build 1.6.0_-b)
ããJavaHotSpot(TM) Server VM (build .4-b, mixed mode)
ãã$javah
ããç¨æ³ï¼javah[é项]<ç±»>
ããå ¶ä¸[é项]å æ¬ï¼
ãã-helpè¾åºæ¤å¸®å©æ¶æ¯å¹¶éåº
ãã-classpath<è·¯å¾>ç¨äºè£ å ¥ç±»çè·¯å¾
ãã-bootclasspath<è·¯å¾>ç¨äºè£ å ¥å¼å¯¼ç±»çè·¯å¾
ãã-d<ç®å½>è¾åºç®å½
ãã-o<æ件>è¾åºæ件ï¼åªè½ä½¿ç¨-dæ-oä¸çä¸ä¸ªï¼
ãã-jniçæJNIæ ·å¼ç头æ件ï¼é»è®¤ï¼
ãã-versionè¾åºçæ¬ä¿¡æ¯
ãã-verboseå¯ç¨è¯¦ç»è¾åº
ãã-forceå§ç»åå ¥è¾åºæ件
ãã使ç¨å ¨éå®å称æå®<ç±»>ï¼ä¾
ããå¦ï¼java.lang.Objectï¼ã2.2.å®è£ androidåºç¨ç¨åºå¼åç¯å¢
ããubuntuä¸å®è£ androidåºç¨ç¨åºå¼åç¯å¢ä¸windows类似ï¼ä¾æ¬¡å®è£ 好以ä¸è½¯ä»¶å³å¯ï¼
ããï¼1ï¼Eclipse
ããï¼2ï¼ADT
ããï¼3ï¼AndroidSDK
ããä¸windowsä¸å®è£ å¯ä¸ä¸åçä¸ç¹æ¯ï¼ä¸è½½è¿äºè½¯ä»¶çæ¶åè¦ä¸è½½Linuxçæ¬çå®è£ å ã
ããå®è£ 好以ä¸androidåºç¨ç¨åºçå¼åç¯å¢åï¼è¿å¯ä»¥éæ©æ¯å¦éè¦é ç½®emulatoråadbå·¥å ·çç¯å¢åéï¼ä»¥æ¹ä¾¿å¨è¿è¡JNIå¼åçæ¶å使ç¨ãé ç½®æ¥éª¤å¦ä¸ï¼
ããæemulatoræå¨ç®å½android-sdk-linux/tools以åadbæå¨ç®å½android-sdk-linux/platform-toolsæ·»å å°ç¯å¢åéä¸ï¼android-sdk-linuxæandroidsdkå®è£ å android-sdk_rxx-linuxç解åç®å½ã
ãã[plain] view plaincopyprint?
ãã.$sudo vim /etc/profile
ãã.exportPATH=~/software/android/android-sdk-linux/tools:$PATH
ãã. exportPATH=~/software/android/android-sdk-linux/platform-tools:$PATH
ãã$sudo vim /etc/profile
ããexportPATH=~/software/android/android-sdk-linux/tools:$PATH
ããexportPATH=~/software/android/android-sdk-linux/platform-tools:$PATH
ããç¼è¾å®æ¯åéåºï¼å¹¶éå¯çæã
ãã2.3.å®è£ NDK
ããNDKæ¯ç±androidæä¾çç¼è¯androidæ¬å°ä»£ç çä¸ä¸ªå·¥å ·ã
ããï¼1ï¼ä»androidndkå®ç½/sdk/ndk/index.htmlä¸è½½ndkï¼ç®åææ°çæ¬ä¸ºandroid-ndk-r6b-linux-x.tar.bz2.
ããï¼2ï¼è§£åndkå°å·¥ä½ç®å½ï¼
ãã[plain] view plaincopyprint?
ãã.$tar -xvf android-ndk-r6b-linux-x.tar.bz2
ãã.$sudo mv android-ndk-r6b /usr/local/ndk
ãã$tar -xvf android-ndk-r6b-linux-x.tar.bz2
ãã$sudo mv android-ndk-r6b /usr/local/ndk
ããï¼3ï¼è®¾ç½®ndkç¯å¢åé
ãã[plain] view plaincopyprint?
ãã.$sudo vim /etc/profile
ãã.exportPATH=/usr/local/ndk:$PATH
ãã$sudo vim /etc/profile
ããexportPATH=/usr/local/ndk:$PATH
ããç¼è¾å®æ¯åä¿åéåºï¼å¹¶éå¯çæ
ããï¼4ï¼éªè¯å®è£
ãã[plain] view plaincopyprint?
ãã.$ cd/usr/local/ndk/samples/hello-jni/
ãã.$ ndk-build
ãã.Gdbserver : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
ãã.Gdbsetup : libs/armeabi/gdb.setup
ãã.Install : libhello-jni.so => libs/armeabi/libhello-jni.so
ãã$ cd/usr/local/ndk/samples/hello-jni/
ãã$ ndk-build
ããGdbserver : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
ããGdbsetup : libs/armeabi/gdb.setup
ããInstall : libhello-jni.so => libs/armeabi/libhello-jni.so
ãã3.JNIå®ç°
ããæ们éè¦å®ä¹ä¸ä¸ªç¬¦åJNIæ¥å£è§èçc/c++æ¥å£ï¼è¿ä¸ªæ¥å£ä¸ç¨å¤ªå¤æï¼ä¾å¦è¾åºä¸ä¸ªå符串ãæ¥ä¸æ¥ï¼åéè¦æc/c++æ¥å£ç代ç æ件ç¼è¯æå ±äº«åºï¼å¨æåºï¼.soæ件ï¼å¹¶æ¾å°æ¨¡æå¨çç¸å ³ç®å½ä¸ãæåï¼å¯å¨Javaåºç¨ç¨åºï¼å°±å¯ä»¥çå°æç»ææäºã
ãã3.1.ç¼åJavaåºç¨ç¨åºä»£ç
ããï¼1ï¼å¯å¨Eclipseï¼æ°å»ºandroidå·¥ç¨
ããProjectï¼JNITest
ããPackageï¼org.tonny.jni
ããActivityï¼JNITest
ããï¼2ï¼ç¼è¾èµæºæ件
ããç¼è¾res/values/strings.xmlæ件å¦ä¸ï¼
ãã
ããç¼è¾res/layout/main.xmlæ件
ããæ们å¨ä¸»çé¢ä¸æ·»å äºä¸ä¸ªEditTextæ§ä»¶åä¸ä¸ªButtonæ§ä»¶ã
ããï¼3ï¼ç¼è¾JNITest.javaæ件
ã
ããstatic表示å¨ç³»ç»ç¬¬ä¸æ¬¡å 载类çæ¶åï¼å æ§è¡è¿ä¸æ®µä»£ç ï¼å¨è¿é表示å è½½å¨æåºlibJNITest.soæ件ã
ããåçè¿ä¸æ®µï¼
ãã[java] view plaincopyprint?
ãã.privatenativeString GetReply();
ããprivatenativeString GetReply();
ããnative表示è¿ä¸ªæ¹æ³ç±æ¬å°ä»£ç å®ä¹ï¼éè¦éè¿jniæ¥å£è°ç¨æ¬å°c/c++代ç ã
ãã[java] view plaincopyprint?
ãã.publicvoidonClick(View arg0) {
ãã.edtName.setText(reply);
ãã.}
ããpublicvoidonClick(View arg0) {
ããedtName.setText(reply);
ãã}
ããè¿æ®µä»£ç 表示ç¹å»æé®åï¼ænativeæ¹æ³çè¿åçå符串æ¾ç¤ºå°EditTextæ§ä»¶ã
ããï¼4ï¼ç¼è¯å·¥ç¨ï¼çæ.classæ件ã
ãã3.2.ç¨javahå·¥å ·çæ符åJNIè§èçcè¯è¨å¤´æ件
ããå¨ç»ç«¯ä¸ï¼è¿å ¥androidå·¥ç¨æå¨çbinç®å½
ãã[plain] view plaincopyprint?
ãã.$cd ~/project/Android/JNITest/bin
ãã$cd ~/project/Android/JNITest/bin
ããæ们ç¨lså½ä»¤æ¥çï¼å¯ä»¥çå°binç®å½ä¸æ个classesç®å½ï¼å ¶ç®å½ç»æ为classes/org/tonny/jniï¼å³classesçåç®å½ç»ææ¯androidå·¥ç¨çå åorg.tonny.jniã请注æï¼ä¸é¢æ们åå¤æ§è¡javahå½ä»¤çæ¶åï¼å¿ é¡»è¿å ¥å°org/tonny/jniçä¸çº§ç®å½ï¼å³classesç®å½ï¼å¦åjavahä¼æ示æ¾ä¸å°ç¸å ³çjavaç±»ã
ããä¸é¢ç»§ç»ï¼
ãã[plain] view plaincopyprint?
ãã.$cd classes
ãã.$javah org.tonny.jni.JNITest
ãã.$ls
ãã.org org_tonny_jni_JNITest.h
ãã$cd classes
ãã$javah org.tonny.jni.JNITest
ãã$ls
ããorg org_tonny_jni_JNITest.h
ããæ§è¡javahorg.tonny.jni.JNITestå½ä»¤ï¼å¨classesç®å½ä¸ä¼çæorg_tonny_jni_JNITest.h头æ件ãå¦æä¸è¿å ¥å°classesç®å½ä¸çè¯ï¼ä¹å¯ä»¥è¿æ ·ï¼
ãã[plain] view plaincopyprint?
ãã.$javah -classpath ~/project/Android/JNITest/bin/classesorg.tonny.jni.JNITest
ãã$javah -classpath ~/project/Android/JNITest/bin/classesorg.tonny.jni.JNITest
ãã-classpath åæ°è¡¨ç¤ºè£ 载类çç®å½ã
ãã3.3.ç¼åc/c++代ç
ããçæorg_tonny_jni_JNITest.h头æ件åï¼æ们就å¯ä»¥ç¼åç¸åºçå½æ°ä»£ç äºãä¸é¢å¨androidå·¥ç¨ç®å½ä¸æ°å»ºjniç®å½ï¼å³~/project/Android/JNITest/jniï¼æorg_tonny_jni_JNITest.h头æ件æ·è´å°jniç®å½ä¸ï¼å¹¶å¨jniç®å½ä¸æ°å»ºorg_tonny_jni_JNITest.cæ件ï¼ç¼è¾ä»£ç å¦ä¸ï¼
ãã[cpp] view plaincopyprint?
ãã.#include<jni.h>
ãã.#include<string.h>
ãã.#include"org_tonny_jni_JNITest.h"
ãã.
ãã.
ãã.JNIEXPORTjstring JNICALLJava_org_tonny_jni_JNITest_GetReply
ãã.(JNIEnv *env, jobject obj){
ãã.return(*env)->NewStringUTF(env,(char*)"Hello,JNITest");
ãã.}
ãã#include<jni.h>
ãã#include<string.h>
ãã#include"org_tonny_jni_JNITest.h"
ããJNIEXPORTjstring JNICALLJava_org_tonny_jni_JNITest_GetReply
ãã(JNIEnv *env, jobject obj){
ããreturn(*env)->NewStringUTF(env,(char*)"Hello,JNITest");
ãã}
ããæ们å¯ä»¥çå°ï¼è¯¥å½æ°çå®ç°ç¸å½ç®åï¼è¿åä¸ä¸ªå符串为ï¼"Hello,JNITest"
ãã3.4.ç¼åAndroid.mkæ件
ããå¨~/project/Android/JNITest/jniç®å½ä¸æ°å»ºAndroid.mkæ件ï¼androidå¯ä»¥æ ¹æ®è¿ä¸ªæ件çç¼è¯åæ°ç¼è¯æ¨¡åãç¼è¾Android.mkæ件å¦ä¸ï¼
ãã[plain] view plaincopyprint?
ãã.LOCAL_PATH:= $(call my-dir)
ãã.include$(CLEAR_VARS)
ãã.LOCAL_MODULE := libJNITest
ãã.LOCAL_SRC_FILES:= org_tonny_jni_JNITest.c
ãã.include$(BUILD_SHARED_LIBRARY)
ããLOCAL_PATH:= $(call my-dir)
ããinclude$(CLEAR_VARS)
ããLOCAL_MODULE := libJNITest
ããLOCAL_SRC_FILES:= org_tonny_jni_JNITest.c
ããinclude$(BUILD_SHARED_LIBRARY)
ããLOCAL_MODULE表示ç¼è¯çå¨æåºå称
ããLOCAL_SRC_FILES 表示æºä»£ç æ件
ãã3.5.ç¨ndkå·¥å ·ç¼è¯å¹¶çæ.soæ件
ããè¿å ¥å°JNITestçå·¥ç¨ç®å½ï¼æ§è¡ndk-buildå½ä»¤å³å¯çælibJNITest.soæ件ã
ãã[plain] view plaincopyprint?
ãã.$cd ~/project/Android/JNITest/
ãã.$ndk-build
ãã.Invalidattribute name:
ãã.package
ãã.Install : libJNITest.so => libs/armeabi/libJNITest.so
ãã$cd ~/project/Android/JNITest/
ãã$ndk-build
ããInvalidattribute name:
ããpackage
ããInstall : libJNITest.so => libs/armeabi/libJNITest.so
ããå¯ä»¥çå°ï¼å¨å·¥ç¨ç®å½çlibs/armeabiç®å½ä¸çæäºlibJNITest.soæ件ã
ãã3.6.å¨æ¨¡æå¨ä¸è¿è¡
ããï¼1ï¼é¦å ï¼æ们æandroid模æå¨å¯å¨èµ·æ¥ãè¿å ¥å°emulatoræå¨ç®å½ï¼æ§è¡emulatorå½ä»¤ï¼
ãã[plain] view plaincopyprint?
ãã.$cd ~/software/android/android-sdk-linux/tools
ãã.$./emulator @AVD-2.3.3-V -partition-size
ãã$cd ~/software/android/android-sdk-linux/tools
ãã$./emulator @AVD-2.3.3-V -partition-size
ããAVD-2.3.3-Vè¡¨ç¤ºä½ ç模æå¨å称ï¼ä¸å¨Eclipse->AVDManagerä¸çAVDName对åºï¼-partition-size表示模æå¨çåå¨è®¾å¤å®¹éã
ããï¼2ï¼æ¥ä¸æ¥ï¼æ们éè¦ælibJNITest.soæ件æ·è´å°æ¨¡æå¨ç/system/libç®å½ä¸ï¼æ§è¡ä»¥ä¸å½ä»¤ï¼
ãã[plain] view plaincopyprint?
ãã.$cd ~/project/Android/JNITest/libs/armeabi/
ãã.$adb remount
ãã.$adb push libJNITest.so /system/lib
ãã. KB/s ( bytes in 0.s)
ãã$cd ~/project/Android/JNITest/libs/armeabi/
ãã$adb remount
ãã$adb push libJNITest.so /system/lib
ãã KB/s ( bytes in 0.s)
ããå½å¨ç»ç«¯ä¸çå°æ KB/s ( bytes in 0.s)ä¼ è¾é度çä¿¡æ¯çæ¶åï¼è¯´ææ·è´æåã
ããï¼3ï¼å¨ç»ç«¯ä¸æ§è¡JNITestç¨åºï¼è¿ä¸ªæ们å¯ä»¥å¨Eclipseä¸ï¼å³é®ç¹å»JNITestå·¥ç¨ï¼RunAs->Android Applicationï¼å³å¯å¨æ¨¡æå¨ä¸å¯å¨ç¨åº
ç¨jniåçå®ååºç¨è½è¢«åç¼è¯å
åç¼è¯æ¯å¯ä»¥çï¼ä½æ¯ç±äºcè¯è¨ä»£ç çå¯è¯»æ§æ¬èº«å°±å¾å¤§ï¼åç¼è¯åä¸å¯è½åjavaä¸æ ·åå½åæ¥çæºç çï¼åç¼è¯ç代ç æ¶æ²¡ææ°æ®ç±»åçï¼ææçæ°æ®ç±»åï¼çè³æéé½åæäºintç±»åï¼cè¯è¨çåç¼è¯åºæ¬ä¸å°±å¯ä»¥å¿½ç¥çåæåºæ¬ä¸å°±å¯ä»¥å¿½ç¥å ¶åæï¼
å¦æè¿æ¯æ³ççåç¼è¯çææï¼æä¸ä¸ªå·¥å ·å«å IDAï¼èªå·±å¯ä»¥ä¸è½½ä¸æ¥è¯è¯ï¼
å¸æå¯¹ä½ æç¨ï¼ææ¯ndkå§å§ä¸»ï¼æé®é¢å¯ä»¥ndkå§çè¨è°¢è°¢ï¼
音视频探索(5):JPEG格式与Libjpeg库编译移植
libJPEG-turbo是一个强大的JPEG图像处理库,它支持JPEG格式的码编编码和解码,尤其对于Android平台,源译其底层压缩常采用libJPEG。码编然而,源译Android系统为适应低版本设备,码编github 换脸源码压缩算法非标准,源译可能导致图像质量和压缩性能的码编权衡。因此,源译本篇将介绍如何利用AS的码编Cmake工具编译libJPEG-turbo,并通过JNI/NDK技术引入哈夫曼编码以优化Android中的源译压缩质量。
哈夫曼编码是码编一种无损压缩方法,年由Huffman提出。源译它依据字符出现概率构造编码,码编概率高的源译信息编码较短。在图像压缩中,通过计算像素概率生成Huffman码表,源码底层编码后的图像数据记录每个像素的码字,与码表对应。例如,通过构建赫夫曼树,字符集中的字符对应树的路径,形成编码。
libJPEG-turbo中的JPEG编码与解码过程包括:分配压缩对象,设置输出和参数,vecctor源码逐行处理数据,以及解压时分配和初始化解压对象、读取数据等。其核心结构体如jpeg_compress_struct和jpeg_decompress_struct,分别用于压缩和解压缩操作。
为了在Android上实现优化,我们需要从libjpeg-turbo源码开始,首先在CmakeLists.txt中配置项目,apijson源码然后在Java层编写JNI方法,将C++的哈夫曼编码逻辑与Java代码连接。编译后,会生成libjpegtil.so文件,将其与libjpeg.so一同引入目标项目。
Android开发中的NDK到底是什么?(详细解析+案例)
在Android开发中,Native Development Kit (NDK)扮演着关键角色,它是GU源码一个用于快速开发C和C++动态库的工具包。NDK的主要目标是将编译后的.so文件与应用一起打包成APK,尤其适合需要JNI(Java Native Interface)技术的场景。 NDK使用步骤如下:首先,配置Android NDK环境。这包括下载并解压NDK工具包到指定路径,如:/Users/Carson_Ho/Library/Android/sdk/ndk-bundle。Android Studio会自动检测并集成,无需额外手动关联。
关联项目与NDK:在Gradle配置文件中添加必要的配置,包括local.properties、gradle.properties和build.gradle中的ndk节点,确保项目每次都能正确使用NDK。
创建本地C++代码文件,如test.cpp。注意文件命名规则,确保Java和C++接口的兼容性。
接着,编写Android.mk和Application.mk文件,分别指定源码编译配置和平台相关配置,放在jni文件夹中。
执行编译命令,生成.so库文件,一般会在src/main/jniLibs目录下找到。
在MainActivity.java和对应的布局文件中,集成并调用NDK编写的C++代码。
对于Android Studio 2.2及以上版本,NDK的集成更为方便,只需在创建工程时按照提示配置即可,无需额外安装和配置。