在上一篇文章中,我介绍了一种应用程序直接调用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