Override Context.getSystemService()

jollen 發表於 February 26, 2010 10:12 PM

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