編輯:關於Android編程
時隔多日,終於都抽出時間來寫blog了。廢話不多說,接著上一篇,這裡將介紹如何編寫HAL層(硬件抽象層)對應的JNI方法。
這裡提到的都是在ICS源碼裡編譯的。
1、定義JNI層接口
進入到android-4.0.4_r1.2/hardware/libhardware/include/hardware目錄,並創建 ttt.h 文件,內容如下:
[cpp]
#ifndef ANDROID_TTT_INTERFACE_H
#define ANDROID_TTT_INTERFACE_H
#include <hardware/hardware.h>
__BEGIN_DECLS
// 定義模塊ID
#define HELLO_HARDWARE_MODULE_ID "ttt"
// 硬件模塊結構體
struct ttt_module_t{
struct hw_module_t common;
};
// hardware interface struct
struct ttt_device_t{
struct hw_device_t common;
int fd;
int(*set_val)(struct ttt_device_t* dev, int val);
int(*get_val)(struct ttt_device_t* dev, int* val);
};
__END_DECLS
#endif
#ifndef ANDROID_TTT_INTERFACE_H
#define ANDROID_TTT_INTERFACE_H
#include <hardware/hardware.h>
__BEGIN_DECLS
// 定義模塊ID
#define HELLO_HARDWARE_MODULE_ID "ttt"
// 硬件模塊結構體
struct ttt_module_t{
struct hw_module_t common;
};
// hardware interface struct
struct ttt_device_t{
struct hw_device_t common;
int fd;
int(*set_val)(struct ttt_device_t* dev, int val);
int(*get_val)(struct ttt_device_t* dev, int* val);
};
__END_DECLS
#endif
2、實現JNI層接口功能
進入到android-4.0.4_r1.2/frameworks/base/services/jni目錄,並創建com_android_server_TTTService.cpp文件,其內容如下:
[cpp]
#define LOG_TAG "TTTService"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/ttt.h>
#include <stdio.h>
namespace android
{
struct ttt_device_t* ttt_device = NULL;
// through the HAL interface to set the register value
static void ttt_setVal(JNIEnv* env, jobject clazz, jint value){
int val = value;
LOGI("TTT JNI: set value %d to device.", val);
if(!ttt_device){
LOGI("TTT JNI: device is not open.");
return;
}
ttt_device->set_val(ttt_device, val);
}
// through the HAL interface to read the register value
static jint ttt_getVal(JNIEnv* env, jobject clazz){
int val = 0;
if(!ttt_device){
LOGI("TTT JNI: device is not open.");
return val;
}
ttt_device->get_val(ttt_device, &val);
LOGI("TTT JNI: get value %d from device.", val);
return val;
}
// through the HAL interface to open the hardware device
static inline int ttt_device_open(const hw_module_t* module, struct ttt_device_t** device){
return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
}
// throught the hardware module ID to load the HAL module and open the device
static jboolean ttt_init(JNIEnv* env, jclass clazz){
ttt_module_t* module;
LOGI("TTT JNI: initializing...");
if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0){
LOGI("TTT JNI: ttt stub found.");
if(ttt_device_open(&(module->common), &ttt_device) == 0){
LOGI("TTT JNI: ttt device is open.");
return 0;
}
LOGE("TTT JNI: failed to open ttt device.");
return -1;
}
LOGE("TTT JNI: failed to get ttt stub module.");
return -1;
}
// JNI methods table
static const JNINativeMethod method_table[] = {
{"init_native", "()Z", (void*)ttt_init},
{"setVal_native", "(I)V", (void*)ttt_setVal},
{"getVal_native", "()I", (void*)ttt_getVal},
};
// regist JNI method
int register_android_server_TTTService(JNIEnv* env){
return jniRegisterNativeMethods(env, "com/android/server/TTTService", method_table, NELEM(method_table));
}
};
#define LOG_TAG "TTTService"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/ttt.h>
#include <stdio.h>
namespace android
{
struct ttt_device_t* ttt_device = NULL;
// through the HAL interface to set the register value
static void ttt_setVal(JNIEnv* env, jobject clazz, jint value){
int val = value;
LOGI("TTT JNI: set value %d to device.", val);
if(!ttt_device){
LOGI("TTT JNI: device is not open.");
return;
}
ttt_device->set_val(ttt_device, val);
}
// through the HAL interface to read the register value
static jint ttt_getVal(JNIEnv* env, jobject clazz){
int val = 0;
if(!ttt_device){
LOGI("TTT JNI: device is not open.");
return val;
}
ttt_device->get_val(ttt_device, &val);
LOGI("TTT JNI: get value %d from device.", val);
return val;
}
// through the HAL interface to open the hardware device
static inline int ttt_device_open(const hw_module_t* module, struct ttt_device_t** device){
return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
}
// throught the hardware module ID to load the HAL module and open the device
static jboolean ttt_init(JNIEnv* env, jclass clazz){
ttt_module_t* module;
LOGI("TTT JNI: initializing...");
if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0){
LOGI("TTT JNI: ttt stub found.");
if(ttt_device_open(&(module->common), &ttt_device) == 0){
LOGI("TTT JNI: ttt device is open.");
return 0;
}
LOGE("TTT JNI: failed to open ttt device.");
return -1;
}
LOGE("TTT JNI: failed to get ttt stub module.");
return -1;
}
// JNI methods table
static const JNINativeMethod method_table[] = {
{"init_native", "()Z", (void*)ttt_init},
{"setVal_native", "(I)V", (void*)ttt_setVal},
{"getVal_native", "()I", (void*)ttt_getVal},
};
// regist JNI method
int register_android_server_TTTService(JNIEnv* env){
return jniRegisterNativeMethods(env, "com/android/server/TTTService", method_table, NELEM(method_table));
}
};
3、添加JNI初始化調用
修改android-4.0.4_r1.2/frameworks/base/services/jni目錄下的 onload.cpp 文件,在 JNI_OnLoad函數中的return之前添加下面一句:
[cpp]
register_android_server_TTTService(env);
register_android_server_TTTService(env);同時,在該文件中的namespace中添加下面一句聲明:
[cpp]
int register_android_server_TTTService(JNIEnv* env);
int register_android_server_TTTService(JNIEnv* env);
這樣,在系統初始化時,就會調用register_android_server_TTTService方法來加載JNI方法了。
4、添加編譯JNI的配置
修改android-4.0.4_r1.2/frameworks/base/services/jni目錄下的 Android.mk 文件,在 LOCAL_SRC_FILES 變量中添加下面一行:
[cpp]
com_android_server_TTTService.cpp \
com_android_server_TTTService.cpp \這裡是添加編譯配置。
5、開始編譯
[cpp]
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# . build/envsetup.sh
including device/moto/stingray/vendorsetup.sh
including device/moto/wingray/vendorsetup.sh
including device/samsung/crespo4g/vendorsetup.sh
including device/samsung/crespo/vendorsetup.sh
including device/samsung/maguro/vendorsetup.sh
including device/samsung/smdkc110/vendorsetup.sh
including device/samsung/smdkv210/vendorsetup.sh
including device/samsung/torospr/vendorsetup.sh
including device/samsung/toro/vendorsetup.sh
including device/samsung/tuna/vendorsetup.sh
including device/ti/panda/vendorsetup.sh
including sdk/bash_completion/adb.bash
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# . build/envsetup.sh
including device/moto/stingray/vendorsetup.sh
including device/moto/wingray/vendorsetup.sh
including device/samsung/crespo4g/vendorsetup.sh
including device/samsung/crespo/vendorsetup.sh
including device/samsung/maguro/vendorsetup.sh
including device/samsung/smdkc110/vendorsetup.sh
including device/samsung/smdkv210/vendorsetup.sh
including device/samsung/torospr/vendorsetup.sh
including device/samsung/toro/vendorsetup.sh
including device/samsung/tuna/vendorsetup.sh
including device/ti/panda/vendorsetup.sh
including sdk/bash_completion/adb.bash
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#[cpp] view plaincopyprint?root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# mmm frameworks/base/services/jni
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76I
============================================
make:進入目錄'/home/brantyou/workspace/android-4.0.4_r1.2'
target thumb C++: libandroid_servers <= frameworks/base/services/jni/com_android_server_HelloService.cpp
target thumb C++: libandroid_servers <= frameworks/base/services/jni/com_android_server_TTTService.cpp
target thumb C++: libandroid_servers <= frameworks/base/services/jni/onload.cpp
make: *** 沒有規則可以創建“out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so”需要的目標“out/target/product/generic/obj/lib/libsystem_server.so”。 停止。
make:離開目錄“/home/brantyou/workspace/android-4.0.4_r1.2”
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# mmm frameworks/base/services/jni
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76I
============================================
make:進入目錄'/home/brantyou/workspace/android-4.0.4_r1.2'
target thumb C++: libandroid_servers <= frameworks/base/services/jni/com_android_server_HelloService.cpp
target thumb C++: libandroid_servers <= frameworks/base/services/jni/com_android_server_TTTService.cpp
target thumb C++: libandroid_servers <= frameworks/base/services/jni/onload.cpp
make: *** 沒有規則可以創建“out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so”需要的目標“out/target/product/generic/obj/lib/libsystem_server.so”。 停止。
make:離開目錄“/home/brantyou/workspace/android-4.0.4_r1.2”
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#
矮油~~~這裡出錯了,提示沒有找到 libsystem_server.so 文件。
執行下面的命令,生成 libsystem_server.so 文件:
[cpp]
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# make libsystem_server
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# make libsystem_server生成之後的提示:
[cpp]
Install: out/target/product/generic/system/lib/libvorbisidec.so
Install: out/target/product/generic/system/lib/libstagefright_yuv.so
Install: out/target/product/generic/system/lib/libdrmframework.so
Install: out/target/product/generic/system/lib/libchromium_net.so
Install: out/target/product/generic/system/lib/libstagefright_amrnb_common.so
Install: out/target/product/generic/system/lib/libstagefright_enc_common.so
Install: out/target/product/generic/system/lib/libstagefright_avc_common.so
Install: out/target/product/generic/system/lib/libstagefright.so
Install: out/target/product/generic/system/lib/libstagefright_omx.so
Install: out/target/product/generic/system/lib/libmediaplayerservice.so
Install: out/target/product/generic/system/lib/libinput.so
Install: out/target/product/generic/system/lib/libsystem_server.so
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#
Install: out/target/product/generic/system/lib/libvorbisidec.so
Install: out/target/product/generic/system/lib/libstagefright_yuv.so
Install: out/target/product/generic/system/lib/libdrmframework.so
Install: out/target/product/generic/system/lib/libchromium_net.so
Install: out/target/product/generic/system/lib/libstagefright_amrnb_common.so
Install: out/target/product/generic/system/lib/libstagefright_enc_common.so
Install: out/target/product/generic/system/lib/libstagefright_avc_common.so
Install: out/target/product/generic/system/lib/libstagefright.so
Install: out/target/product/generic/system/lib/libstagefright_omx.so
Install: out/target/product/generic/system/lib/libmediaplayerservice.so
Install: out/target/product/generic/system/lib/libinput.so
Install: out/target/product/generic/system/lib/libsystem_server.so
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# 好了,這個問題解決了,我們繼續編譯這個JNI。
[cpp]
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# mmm frameworks/base/services/jni
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76I
============================================
make:進入目錄'/home/brantyou/workspace/android-4.0.4_r1.2'
target SharedLib: libandroid_servers (out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so)
target Symbolic: libandroid_servers (out/target/product/generic/symbols/system/lib/libandroid_servers.so)
target Strip: libandroid_servers (out/target/product/generic/obj/lib/libandroid_servers.so)
Install: out/target/product/generic/system/lib/libandroid_servers.so
make:離開目錄“/home/brantyou/workspace/android-4.0.4_r1.2”
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# mmm frameworks/base/services/jni
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76I
============================================
make:進入目錄'/home/brantyou/workspace/android-4.0.4_r1.2'
target SharedLib: libandroid_servers (out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so)
target Symbolic: libandroid_servers (out/target/product/generic/symbols/system/lib/libandroid_servers.so)
target Strip: libandroid_servers (out/target/product/generic/obj/lib/libandroid_servers.so)
Install: out/target/product/generic/system/lib/libandroid_servers.so
make:離開目錄“/home/brantyou/workspace/android-4.0.4_r1.2”
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#很好,這一次已經順利的編譯完了。
下面我們需要重新打包這個 system.img,包我們編寫的JNI方法包含進去:
[cpp]
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# make snod
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76I
============================================
make snod: ignoring dependencies
Target system fs image: out/target/product/generic/system.img
out/target/product/generic/system.img total size is 44107008
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2#
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# make snod
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76I
============================================
make snod: ignoring dependencies
Target system fs image: out/target/product/generic/system.img
out/target/product/generic/system.img total size is 44107008
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# 這樣就成功的把我們編寫的JNI打包到 system.img中了。
程序運行效果圖: 程序代碼: /** * 獲取所有軟件信息 * 1.通過異步的方式顯示系統中所有軟件 * 2.單擊打開指定軟件 * 3.將所有軟件的包名
有多少人,在糾結SDK老是更新出問題,打開Android開發者網站等半天,不能上google,facebook,youtube等國外網站而煩惱呢, 如果不巧你正好看到了這
本項目是一個比較有趣的項目源碼,可以給其他項目加鎖,程序鎖的原理是一個“看門狗”的服務定時監視頂層activity,如果activity對應的包名是之前上鎖的應用程序的,
先來點雞湯:Stay hungry,stay foolish這句話的的解讀:我們必須了解自己的渺小。如果我們不學習,科技發展的速度會讓我們五年後被清空。所以,我們必須用初