Android系統匿名共享記憶體Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃 (三)

broadviewbj發表於2012-10-31
有了Binder程式間通訊介面之後,接下來就是要在Server端實現一個本地服務了。這裡,Server端實現的本地服務名為MemoryService,實現在src/shy/luo/ashmem/MemoryService.java檔案中:

  1. package shy.luo.ashmem;  
  2.   
  3. import java.io.FileDescriptor;  
  4. import java.io.IOException;  
  5.   
  6. import android.os.Parcel;  
  7. import android.os.MemoryFile;  
  8. import android.os.ParcelFileDescriptor;  
  9. import android.util.Log;  
  10.   
  11. public class MemoryService extends IMemoryService.Stub {  
  12.     private final static String LOG_TAG = "shy.luo.ashmem.MemoryService";  
  13.     private MemoryFile file = null;  
  14.       
  15.     public MemoryService() {  
  16.         try {  
  17.                         file = new MemoryFile("Ashmem"4);  
  18.                         setValue(0);  
  19.                 }  
  20.                 catch(IOException ex) {  
  21.                         Log.i(LOG_TAG, "Failed to create memory file.");  
  22.                         ex.printStackTrace();  
  23.                 }  
  24.     }  
  25.   
  26.     public ParcelFileDescriptor getFileDescriptor() {  
  27.         Log.i(LOG_TAG, "Get File Descriptor.");  
  28.   
  29.         ParcelFileDescriptor pfd = null;  
  30.   
  31.         try {  
  32.             pfd = file.getParcelFileDescriptor();  
  33.         } catch(IOException ex) {  
  34.             Log.i(LOG_TAG, "Failed to get file descriptor.");  
  35.             ex.printStackTrace();  
  36.         }  
  37.   
  38.         return pfd;  
  39.     }  
  40.       
  41.     public void setValue(int val) {  
  42.         if(file == null) {  
  43.             return;  
  44.         }  
  45.   
  46.         byte[] buffer = new byte[4];     
  47.         buffer[0] = (byte)((val >>> 24) & 0xFF);  
  48.         buffer[1] = (byte)((val >>> 16) & 0xFF);  
  49.         buffer[2] = (byte)((val >>> 8) & 0xFF);   
  50.         buffer[3] = (byte)(val & 0xFF);  
  51.           
  52.         try {  
  53.             file.writeBytes(buffer, 004);  
  54.             Log.i(LOG_TAG, "Set value " + val + " to memory file. ");  
  55.         }  
  56.         catch(IOException ex) {  
  57.             Log.i(LOG_TAG, "Failed to write bytes to memory file.");  
  58.             ex.printStackTrace();  
  59.         }  
  60.     }  
  61. }  
  1. package shy.luo.ashmem;  
  2.   
  3. import java.io.FileDescriptor;  
  4. import java.io.IOException;  
  5.   
  6. import android.os.Parcel;  
  7. import android.os.MemoryFile;  
  8. import android.os.ParcelFileDescriptor;  
  9. import android.util.Log;  
  10.   
  11. public class MemoryService extends IMemoryService.Stub {  
  12.     private final static String LOG_TAG = "shy.luo.ashmem.MemoryService";  
  13.     private MemoryFile file = null;  
  14.       
  15.     public MemoryService() {  
  16.         try {  
  17.                         file = new MemoryFile("Ashmem"4);  
  18.                         setValue(0);  
  19.                 }  
  20.                 catch(IOException ex) {  
  21.                         Log.i(LOG_TAG, "Failed to create memory file.");  
  22.                         ex.printStackTrace();  
  23.                 }  
  24.     }  
  25.   
  26.     public ParcelFileDescriptor getFileDescriptor() {  
  27.         Log.i(LOG_TAG, "Get File Descriptor.");  
  28.   
  29.         ParcelFileDescriptor pfd = null;  
  30.   
  31.         try {  
  32.             pfd = file.getParcelFileDescriptor();  
  33.         } catch(IOException ex) {  
  34.             Log.i(LOG_TAG, "Failed to get file descriptor.");  
  35.             ex.printStackTrace();  
  36.         }  
  37.   
  38.         return pfd;  
  39.     }  
  40.       
  41.     public void setValue(int val) {  
  42.         if(file == null) {  
  43.             return;  
  44.         }  
  45.   
  46.         byte[] buffer = new byte[4];     
  47.         buffer[0] = (byte)((val >>> 24) & 0xFF);  
  48.         buffer[1] = (byte)((val >>> 16) & 0xFF);  
  49.         buffer[2] = (byte)((val >>> 8) & 0xFF);   
  50.         buffer[3] = (byte)(val & 0xFF);  
  51.           
  52.         try {  
  53.             file.writeBytes(buffer, 004);  
  54.             Log.i(LOG_TAG, "Set value " + val + " to memory file. ");  
  55.         }  
  56.         catch(IOException ex) {  
  57.             Log.i(LOG_TAG, "Failed to write bytes to memory file.");  
  58.             ex.printStackTrace();  
  59.         }  
  60.     }  
  61. }  
        注意,這裡的MemoryService類實現了IMemoryService.Stub類,表示這是一個Binder服務的本地實現。在建構函式中,透過指定檔名和檔案大小來建立了一個匿名共享記憶體檔案,即建立MemoryFile的一個例項,並儲存在類成員變數file中。這個匿名共享記憶體檔名為"Ashmem",大小為4個節字,剛好容納一個整數,我們這裡舉的例子就是要說明如果建立一個匿名共享記憶體來在兩個程式間實現共享一個整數了。當然,在實際應用中,可以根據需要建立合適大小的共享記憶體來共享有意義的資料。

        這裡還實現了IMemoryService.Stub的兩個介面getFileDescriptor和setVal,一個用來獲取匿名共享記憶體檔案的檔案描述符,一個來往匿名共享記憶體檔案中寫入一個整數,其中,介面getFileDescriptor的返回值是一個ParcelFileDescriptor。在Java中,是用FileDescriptor類來表示一個檔案描述符的,而ParcelFileDescriptor是用來序列化FileDescriptor的,以便在程式間呼叫時傳輸。
        定義好本地服務好,就要定義一個Server來啟動這個服務了。這裡定義的Server實現在src/shy/luo/ashmem/Server.java檔案中:

  1. package shy.luo.ashmem;  
  2.   
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.os.IBinder;  
  6. import android.util.Log;  
  7. import android.os.ServiceManager;  
  8.   
  9. public class Server extends Service {  
  10.     private final static String LOG_TAG = "shy.luo.ashmem.Server";  
  11.   
  12.     private MemoryService memoryService = null;  
  13.   
  14.     @Override  
  15.     public IBinder onBind(Intent intent) {  
  16.         return null;  
  17.     }  
  18.   
  19.     @Override  
  20.     public void onCreate() {  
  21.     Log.i(LOG_TAG, "Create Memory Service...");  
  22.   
  23.     memoryService = new MemoryService();  
  24.   
  25.         try {  
  26.             ServiceManager.addService("AnonymousSharedMemory", memoryService);  
  27.             Log.i(LOG_TAG, "Succeed to add memory service.");  
  28.         } catch (RuntimeException ex) {  
  29.             Log.i(LOG_TAG, "Failed to add Memory Service.");  
  30.             ex.printStackTrace();  
  31.         }  
  32.   
  33.     }  
  34.   
  35.     @Override  
  36.     public void onStart(Intent intent, int startId) {  
  37.         Log.i(LOG_TAG, "Start Memory Service.");  
  38.     }  
  39.   
  40.     @Override  
  41.     public void onDestroy() {  
  42.     Log.i(LOG_TAG, "Destroy Memory Service.");  
  43.     }  
  44. }  
  1. package shy.luo.ashmem;  
  2.   
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.os.IBinder;  
  6. import android.util.Log;  
  7. import android.os.ServiceManager;  
  8.   
  9. public class Server extends Service {  
  10.     private final static String LOG_TAG = "shy.luo.ashmem.Server";  
  11.   
  12.     private MemoryService memoryService = null;  
  13.   
  14.     @Override  
  15.     public IBinder onBind(Intent intent) {  
  16.         return null;  
  17.     }  
  18.   
  19.     @Override  
  20.     public void onCreate() {  
  21.     Log.i(LOG_TAG, "Create Memory Service...");  
  22.   
  23.     memoryService = new MemoryService();  
  24.   
  25.         try {  
  26.             ServiceManager.addService("AnonymousSharedMemory", memoryService);  
  27.             Log.i(LOG_TAG, "Succeed to add memory service.");  
  28.         } catch (RuntimeException ex) {  
  29.             Log.i(LOG_TAG, "Failed to add Memory Service.");  
  30.             ex.printStackTrace();  
  31.         }  
  32.   
  33.     }  
  34.   
  35.     @Override  
  36.     public void onStart(Intent intent, int startId) {  
  37.         Log.i(LOG_TAG, "Start Memory Service.");  
  38.     }  
  39.   
  40.     @Override  
  41.     public void onDestroy() {  
  42.     Log.i(LOG_TAG, "Destroy Memory Service.");  
  43.     }  
  44. }  
        這個Server繼承了Android系統應用程式框架層提供的Service類,當它被啟動時,執行在一個獨立的程式中。當這個Server被啟動時,它的onCreate函式就會被呼叫,然後它就透過ServiceManager的addService介面來新增MemoryService了:

  1. memoryService = new MemoryService();  
  2.   
  3. try {  
  4.     ServiceManager.addService("AnonymousSharedMemory", memoryService);  
  5.     Log.i(LOG_TAG, "Succeed to add memory service.");  
  6. catch (RuntimeException ex) {  
  7.     Log.i(LOG_TAG, "Failed to add Memory Service.");  
  8.     ex.printStackTrace();  
  9. }  
  1. memoryService = new MemoryService();  
  2.   
  3. try {  
  4.     ServiceManager.addService("AnonymousSharedMemory", memoryService);  
  5.     Log.i(LOG_TAG, "Succeed to add memory service.");  
  6. catch (RuntimeException ex) {  
  7.     Log.i(LOG_TAG, "Failed to add Memory Service.");  
  8.     ex.printStackTrace();  
  9. }  
       這樣,當這個Server成功啟動了,Client就可以透過ServiceManager的getService介面來獲取這個MemoryService了。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/13164110/viewspace-747973/,如需轉載,請註明出處,否則將追究法律責任。

相關文章