<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                本篇博客接上一篇的:[Freescale IMX6 Android: 基于TQIMX6 給Toolbox添加LED控制程序](http://blog.csdn.net/sy373466062/article/details/50252123),上一篇是直接將控制程序放到了Toolbox,本篇則是通過JNI調用C庫來完成LED的控制,即APP--> C --> HW。 ## APK的編寫(源碼見末尾) ### 編寫主要需要注意下面個事項與步驟 1. 更改xml在layout中添加控件 2. Checkbox與Button的添加及其click與checked事件的handler 3. Toast的使用 4. API版本問題 5. 文檔的查詢 UI的layout如下: ![](https://box.kancloud.cn/2016-05-05_572afc9aaaf32.jpg) 然后添加checkbox與button的callback。 ### 添加調用C語言native方法的java庫 直接在App下的java中添加一個package,然后添加一個class,如下圖的libledctrl中的HWLedCtrl: ![](https://box.kancloud.cn/2016-05-05_572afc9ac9c16.jpg) 圖一 其中的內容也很簡單,就是建立一個static代碼塊,同時將native函數聲明為static函數,這樣子因為static代碼塊是存在class中的,不需要new一個對象來操作,其中HWLedCtrl.java的內容如上圖: ~~~ package libledctrl; /** * Created by hexiongjun on 12/11/15. */ public class HWLedCtrl { public static native int ledctrl(int which, int status); public static native int ledopen(); public static native void ledclose(); static { try { System.loadLibrary("ledctrl"); } catch (Exception e) { e.printStackTrace(); } } } ~~~ 可以看到這里面加載了libledctrl.so這個庫,這個就是下面的內容。 有了native方法與class之后,我們就可以在APP更改checkbox與button的時候更改led狀態了: ![](https://box.kancloud.cn/2016-05-05_572afc9aeee5e.jpg) 這里面首先是Open,然后是進行亮滅狀態切換。 ### C庫的制作 在前面博客中的C語言代碼基礎上,我們去掉main函數,將其改成符合JNI接口的C源碼: ~~~ #include "jni.h" //#include "JNIHelp.h" //#include "android_runtime/AndroidRuntime.h" //#include <utils/misc.h> //#include <utils/Log.h> //#include <hardware_legacy/led.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #define ALOGI printf #define LED_NUM 3 int leds_fd[LED_NUM]; char path_buff[255]; static jint ledctrl(JNIEnv *env, jobject clazz, jint which, jint status) { int ret = -1; if(status == 1) { ret = write(leds_fd[which], "255", 3); } else { ret = write(leds_fd[which], "0", 1); } if(ret < 0){ return -1; } ALOGI("Native ctrl fd = [%d]\n", which); return 0; } static jint ledopen(JNIEnv *env, jobject clazz) { int i = 0; printf("Native Open\n"); for(i=0; i<LED_NUM; i++){ sprintf(path_buff, "/sys/class/leds/led%d/brightness", i); printf("path:%s\n",path_buff); leds_fd[i] = open(path_buff, O_RDWR); if(leds_fd[i] < 0){ ALOGI("led%d: %s, open failed\n", i, path_buff); return -1; } else { ALOGI("led%d: %s, open success\n", i, path_buff); } } return 0; } static void ledclose(JNIEnv *env, jobject clazz) { int i = 0; for(i=0; i< LED_NUM; i++){ close(leds_fd[i]); } } static JNINativeMethod method_table[] = { { "ledctrl", "(II)I", (void*)ledctrl }, { "ledclose", "()V", (void*)ledclose }, { "ledopen", "()I", (void*)ledopen } }; #if 0 int register_android_server_LedService(JNIEnv *env) { return jniRegisterNativeMethods(env, "libledctrl", method_table, NELEM(method_table)); } #endif JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { JNIEnv *env; jclass cls; printf("Enter the JNI Onload\n"); if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) { printf("Version Error in JNI OnLoad\n"); return JNI_ERR; /* JNI version not supported */ } // Package/ClassName // The package is define in the java first line cls = (*env)->FindClass(env, "libledctrl/HWLedCtrl"); if (cls == NULL) { return JNI_ERR; } /* 2. map java hello <-->c c_hello */ if ((*env)->RegisterNatives(env, cls, method_table, sizeof(method_table)/sizeof(JNINativeMethod)) < 0) return JNI_ERR; return JNI_VERSION_1_4; } ~~~ 需要注意的是: ~~~ cls = (*env)->FindClass(env, "libledctrl/HWLedCtrl"); ~~~ 這里面需要填寫正確的來調用的class,這個路徑按照Package/Class來寫。 然后進行編譯鏈接成動態庫,要使用Android提供的ToolChain需要先lunch target,免去寫長長的路徑Prefix: ~~~ source build/ensetup.sh lunch sabresd_6dq-eng ~~~ 第一步是compile,將C源碼(ledctrl_jni.c)編譯成object(ledctrl_jni.o)文件: ~~~ arm-linux-androideabi-gcc -I bionic/libc/bionic -I libnativehelper/include/nativehelper -isystem system/core/include -isystem hardware/libhardware/include -isystem hardware/libhardware_legacy/include -isystem hardware/ril/include -isystem libnativehelper/include -isystem frameworks/native/include -isystem frameworks/native/opengl/include -isystem frameworks/av/include -isystem frameworks/base/include -isystem external/skia/include -isystem out/target/product/sabresd_6dq/obj/include -isystem bionic/libc/arch-arm/include -isystem bionic/libc/include -isystem bionic/libstdc++/include -isystem bionic/libc/kernel/common -isystem bionic/libc/kernel/arch-arm -isystem bionic/libm/include -isystem bionic/libm/include/arm -isystem bionic/libthread_db/include -fno-exceptions -Wno-multichar -msoft-float -fpic -fPIE -ffunction-sections -fdata-sections -funwind-tables -fstack-protector -Wa,--noexecstack -Werror=format-security -D_FORTIFY_SOURCE=1 -fno-short-enums -march=armv7-a -mfloat-abi=softfp -mfpu=neon -include build/core/combo/include/arch/linux-arm/AndroidConfig.h -I build/core/combo/include/arch/linux-arm/ -Wno-unused-but-set-variable -fno-builtin-sin -fno-strict-volatile-bitfields -Wno-psabi -mthumb-interwork -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -DNDEBUG -g -Wstrict-aliasing=2 -fgcse-after-reload -frerun-cse-after-loop -frename-registers -DNDEBUG -UDEBUG -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -c ledctrl_jni.c -o ledctrl_jni.o ~~~ 第二步則是完成鏈接ledctrl_jni.o --> libledctrl.so: ~~~ arm-linux-androideabi-g++ -nostdlib -Bdynamic -fPIE -pie -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Lout/target/product/sabresd_6dq/obj/lib -Wl,-rpath-link=out/target/product/sabresd_6dq/obj/lib ledctrl_jni.o -Wl,--whole-archive -Wl,--no-whole-archive -lc -lstdc++ -lm -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--icf=safe -Wl,--fix-cortex-a8 -Wl,--no-undefined -shared -fPIC -o libledctrl.so ~~~ ### 鏈接時候需要的注意 需要注意的是鏈接的時候需要寫明-lc,即要鏈接libc,否則在加載的時候后出現問題,例如沒有加入的話運行的時候會出現下面的提示: ![](https://box.kancloud.cn/2016-05-05_572afc9b1ae26.jpg) 這里提示的是找不到符號__sprintf_chk,而這個符號我們可以確定其來源于libc,操作命令如下: ~~~ readelf --syms libc.so ~~~ 結果中可以看到這個函數的定義: ~~~ File: out/target/product/sabresd_6dq/system/lib/libc.so Symbol table '.dynsym' contains 1243 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000c9d8 88 FUNC GLOBAL DEFAULT 8 __init_tls 289: 000138bd 30 FUNC GLOBAL DEFAULT 8 __sprintf_chk ~~~ 這個是查找一個symbol的方法。 ### 編譯用的ToolChain的注意 另外,看到很多人直接使用了arm-linux-gnueabi-gcc來編譯鏈接,這樣子做并不合理,因為我們是需要運行在Android上面,而Android系統編譯使用的是arm-linux-androideabi-gcc來編譯的,所以最后Android系統打包的libc等各種庫都是用這個toolchain里面的。否則容易出現問題。 添加Clib庫到APK項目中 在app/libs中添加armeabi目錄,并將libledctrl.so拷貝進來,然后project的structure如下: ![](https://box.kancloud.cn/2016-05-05_572afc9b3b00d.jpg) 添加完成后build project,并generate APK,然后我們可以解壓APK看到lib庫已經打包進去了: ![](https://box.kancloud.cn/2016-05-05_572afc9b58813.jpg) 然后就可以運行查看效果了。 ## class名字的一致性 前面提到C代碼中需要查找(FindFlass)對應來調用其的java class,如果名字不對應,那么就會提示找不到對應的class,例如下面在C中要查找的是LedCtrl class,自然找不到: ![](https://box.kancloud.cn/2016-05-05_572afc9b7cb80.jpg) ## native函數名字的一致性 如果java中native的函數聲明與實際的C中的函數不一致也會報錯,而且要注意函數的返回類型與傳入的參數類型,例如下面這個就是不匹配的結果: ![](https://box.kancloud.cn/2016-05-05_572afc9b9bff7.jpg) ## APK調試方法 ### 查看so是否加載 這個可以通過adb中的log信息來查看,同時也可以查看加載器是否加載了so,例如我們可以去cat /proc/PROCESS/maps文件查看,也可以使用pmap命令來查看: ~~~ root@sabresd_6dq:/ # pmap 9196 | grep led 415a7000 16K r--s /data/app/com.hexiongjun.led-1.apk 65c6f000 16K r--s /data/app/com.hexiongjun.led-1.apk 6644b000 156K r--s /data/app/com.hexiongjun.led-1.apk 664a7000 4K r-xp /data/app-lib/com.hexiongjun.led-1/libledctrl.so 664a8000 4K r--p /data/app-lib/com.hexiongjun.led-1/libledctrl.so 664a9000 4K rw-p /data/app-lib/com.hexiongjun.led-1/libledctrl.so ~~~ 我們可以看到后面so被加載了。 ## logcat查看某個進程的log 一條命令,后面的30585就是process id: ~~~ logcat -v process | grep 30585 ~~~ ## 代碼位置 [https://github.com/tonyho/ApkJNI01](https://github.com/tonyho/ApkJNI01.git)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看