Context.getSystemService() 是一個很重要的 API,也是「Android 應用程式控制硬體」的起點。在一個開發項目中,如何擴展 getSystemService() 的實作成為一個重要的課題。
幾天前與客戶進行技術討論時,適巧討論到這個議題,因此在這裡做一個簡單的紀錄與大家分享。應用程式要存取手機上的 Sensor 裝置時,須取得 SensorManager 物件,程式寫法如下:
public class mokoidSensor extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); SensorManager sensor = (SensorManager)getSystemService(SENSOR_SERVICE); sensor.getSensors(); /* Do something. */ } }
如果手機上有一個「馬達」裝置,程式碼的寫法,依此邏輯來推論,設想的程式碼會是這樣:
MotorManager motor = (MotorManager)getSystemService(MOTOR_SERVICE);
只是,AOSP 上的程式碼並無 Motor Service 硬體服務,因此除了加入 MotorManager 與 MotorService 設計外,也要擴充 getSystemService() API。實際能採行的做法很多,這裡討論二種方式:
1. 土方法
2. 符合架構
土方法是一個簡單的方式,直接到 [ApplicationContext.java] 裡把程式碼改掉。這個方式簡單有效,不費勁。
符合架構的方法,是基於「Application Framework 不能修改」的前提下來進行設計。也就是,不要變動 Context 的設計、也不要修改 ApplicationContext 實作。AOSP 的 [Activity.java] 以 override 的方式,展示了這個做法:
@Override public Object getSystemService(String name) { if (getBaseContext() == null) { throw new IllegalStateException( "System services not available to Activities before onCreate()"); } if (WINDOW_SERVICE.equals(name)) { return mWindowManager; } else if (SEARCH_SERVICE.equals(name)) { ensureSearchManager(); return mSearchManager; } return super.getSystemService(name); }
因此,改用以下的設計:
public class mokoidActivity extends Activity { ... @Override public Object getSystemService(String name) { if (MOTOR_SERVICE.equals(name)) { MotorManager mMotorManager = new MotorManager(); return mMotorManager; } return super.getSystemService(name); } ... }
應用程式的部份也要做修改:
public class HelloWorld extends mokoidActivity { }
目前為止,這只是一個想法,尚未實作驗證。
Jollen's Blog 使用 Github issues 與讀者交流討論。請點擊上方的文章專屬 issue,或 open a new issue
您可透過電子郵件 jollen@jollen.org,或是 Linkedin 與我連絡。更歡迎使用微信,請搜尋 WeChat ID:jollentw