Android HAL实现的三种方式(2) - 基于Service的HAL设计

来源:互联网 发布:mysql explain用法 编辑:程序博客网 时间:2024/04/28 10:24

在上一篇文章中,我介绍了一种应用程序直接调用JNI库的HAL设计方法,该方法虽然简单,但是不符合Android的框架结构,下面我们介绍一种通过Service提供接口给应用程序的设计方法,结构如下:

HAL stub <-> JNI 库 <-> JAVA Service <->JAVA 应用程序。

HAL stub的设计和上文一样,JNI库的设计中唯一需要修改的地方就是register_mokoid_server_LedService函数,在上文中该JNI库直接提供给应用程序使用,而这里,JNI库是提供接口给JAVA Service使用,修改如下:

  1. int register_mokoid_server_LedService(JNIEnv* env) { 
  2.     //static const char* const kClassName = 
  3.       //  "com/mokoid/LedClient/LedClient"; 
  4.     static const charconst kClassName = 
  5.         "com/mokoid/server/LedService"
  6.     jclass clazz; 
  7.  
  8.     /* look up the class */ 
  9.     clazz = env->FindClass(kClassName); 
  10.     if (clazz == NULL) { 
  11.         LOGE("Can't find class %s\n", kClassName); 
  12.         return -1; 
  13.     } 
  14.  
  15.     /* register all the methods */ 
  16.     if (env->RegisterNatives(clazz, gMethods, 
  17.             sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK) 
  18.     { 
  19.         LOGE("Failed registering methods for %s\n", kClassName); 
  20.         return -1; 
  21.     } 
  22.  
  23.     /* fill out the rest of the ID cache */ 
  24.     return 0; 

在这里,我们的JNI库会提供给com.mokoid.server.LedService类使用,而不是上文中的应用程序com.mokoid.LedClient.LedClient类。该JNI库最后会被编译成libmokoid_runtime.so。

下面我们再看看com.mokoid.server.LedService的实现: 

  1. public final class LedService { 
  2.  
  3.     static { 
  4.         System.load("/system/lib/libmokoid_runtime.so"); 
  5.     } 
  6.  
  7.     public LedService() { 
  8.         Log.i("LedService""Go to get LED Stub..."); 
  9.     _init(); 
  10.     } 
  11.  
  12.     /* 
  13.      * Mokoid LED native methods. 
  14.      */ 
  15.     public boolean setOn(int led) { 
  16.         Log.i("MokoidPlatform""LED On"); 
  17.     return _set_on(led); 
  18.     } 
  19.  
  20.     public boolean setOff(int led) { 
  21.         Log.i("MokoidPlatform""LED Off"); 
  22.     return _set_off(led); 
  23.     } 
  24.  
  25.     private static native boolean _init(); 
  26.     private static native boolean _set_on(int led); 
  27.     private static native boolean _set_off(int led); 

这个Service的实现和上文中的应用程序的实现比较类似,也是通过System.load装载JNI库,然后就可以在自己的方法中使用JNI接口,该Service最后会被编译成mokoid.jar,且位于/system/framework中,值得注意的是,应用程序如果要调用该Service,必须在/etc/perimissions中有一个xml文件,内容如下:

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <permissions> 
  3.     <library name="com.mokoid.server" 
  4.             file="/system/framework/mokoid.jar"/> 
  5. </permissions> 

通过这个文件,应用程序就可以使用com.mokoid.server来找到mokoid.jar文件。

我们最后再来看看应用程序的实现:

  1. package com.mokoid.LedClient; 
  2. import com.mokoid.server.LedService; 
  3.  
  4. import android.app.Activity; 
  5. import android.os.Bundle; 
  6. import android.widget.TextView; 
  7.  
  8. public class LedClient extends Activity { 
  9.     @Override 
  10.     public void onCreate(Bundle savedInstanceState) { 
  11.         super.onCreate(savedInstanceState); 
  12.  
  13.         // Call an API on the library. 
  14.         LedService ls = new LedService(); 
  15.         ls.setOn(1); 
  16.         ls.setOff(2); 
  17.          
  18.         TextView tv = new TextView(this); 
  19.         tv.setText("LED 1 is on. LED 2 is off."); 
  20.         setContentView(tv); 
  21.     } 

这里通过import com.mokoid.server.LedService来使用上面设计的LedService,然后通过new LedService()来得到Service的实例,之后就可以直接调用该Service的方法来控制Led了。

AndroidManifest.xml如下:

  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
  2.     package="com.mokoid.LedClient"> 
  3.      
  4.     <application> 
  5.      
  6.         <!-- This tells the system about the custom library used by the 
  7.              application, so that it can be properly loaded and linked 
  8.              to the app when the app is initialized. --> 
  9.         <uses-library android:name="com.mokoid.server" /> 
  10.          
  11.         <activity android:name="LedClient"> 
  12.             <intent-filter> 
  13.                 <action android:name="android.intent.action.MAIN"/> 
  14.                 <category android:name="android.intent.category.LAUNCHER"/> 
  15.             </intent-filter> 
  16.         </activity> 
  17.     </application> 
  18. </manifest> 

注意,uses-library告诉了系统该程序需要调用的非系统库,既上面我们设计的Service库。

本文出自 “Mobile and Linux Deve..” 博客,请务必保留此出处