在上一篇文章中,我介紹了一種應用程序直接調用JNI庫的HAL設計方法,該方法雖然簡單,但是不符合Android的框架結構,下面我們介紹一種通過Service提供接口給應用程序的設計方法,結構如下:
HAL stub <-> JNI 庫 <-> JAVA Service <->JAVA 應用程序。
HAL stub的設計和上文一樣,JNI庫的設計中唯一需要修改的地方就是register_mokoid_server_LedService函數,在上文中該JNI庫直接提供給應用程序使用,而這裏,JNI庫是提供接口給JAVA Service使用,修改如下:
- int register_mokoid_server_LedService(JNIEnv* env) {
- //static const char* const kClassName =
- // "com/mokoid/LedClient/LedClient";
- static const char* const kClassName =
- "com/mokoid/server/LedService";
- jclass clazz;
- /* look up the class */
- clazz = env->FindClass(kClassName);
- if (clazz == NULL) {
- LOGE("Can't find class %s\n", kClassName);
- return -1;
- }
- /* register all the methods */
- if (env->RegisterNatives(clazz, gMethods,
- sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)
- {
- LOGE("Failed registering methods for %s\n", kClassName);
- return -1;
- }
- /* fill out the rest of the ID cache */
- return 0;
- }
在這裏,我們的JNI庫會提供給com.mokoid.server.LedService類使用,而不是上文中的應用程序com.mokoid.LedClient.LedClient類。該JNI庫最後會被編譯成libmokoid_runtime.so。
下面我們再看看com.mokoid.server.LedService的實現:
- public final class LedService {
- static {
- System.load("/system/lib/libmokoid_runtime.so");
- }
- public LedService() {
- Log.i("LedService", "Go to get LED Stub...");
- _init();
- }
- /*
- * Mokoid LED native methods.
- */
- public boolean setOn(int led) {
- Log.i("MokoidPlatform", "LED On");
- return _set_on(led);
- }
- public boolean setOff(int led) {
- Log.i("MokoidPlatform", "LED Off");
- return _set_off(led);
- }
- private static native boolean _init();
- private static native boolean _set_on(int led);
- private static native boolean _set_off(int led);
- }
這個Service的實現和上文中的應用程序的實現比較類似,也是通過System.load裝載JNI庫,然後就可以在自己的方法中使用JNI接口,該Service最後會被編譯成mokoid.jar,且位於/system/framework中,值得注意的是,應用程序如果要調用該Service,必須在/etc/perimissions中有一個xml文件,內容如下:
- <?xml version="1.0" encoding="utf-8"?>
- <permissions>
- <library name="com.mokoid.server"
- file="/system/framework/mokoid.jar"/>
- </permissions>
通過這個文件,應用程序就可以使用com.mokoid.server來找到mokoid.jar文件。
我們最後再來看看應用程序的實現:
- package com.mokoid.LedClient;
- import com.mokoid.server.LedService;
- import android.app.Activity;
- import android.os.Bundle;
- import android.widget.TextView;
- public class LedClient extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // Call an API on the library.
- LedService ls = new LedService();
- ls.setOn(1);
- ls.setOff(2);
- TextView tv = new TextView(this);
- tv.setText("LED 1 is on. LED 2 is off.");
- setContentView(tv);
- }
- }
這裏通過import com.mokoid.server.LedService來使用上面設計的LedService,然後通過new LedService()來得到Service的實例,之後就可以直接調用該Service的方法來控制Led了。
AndroidManifest.xml如下:
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.mokoid.LedClient">
- <application>
- <!-- This tells the system about the custom library used by the
- application, so that it can be properly loaded and linked
- to the app when the app is initialized. -->
- <uses-library android:name="com.mokoid.server" />
- <activity android:name="LedClient">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- </application>
- </manifest>
注意,uses-library告訴了系統該程序需要調用的非系統庫,既上面我們設計的Service庫。
本文出自 “Mobile and Linux Deve..” 博客,請務必保留此出處http://buaadallas.blog.51cto.com/399160/384902