Android獲取系統服務getSystemService與getService區別

      android的後臺運行在很多service,它們在系統啓動時被SystemServer開啓,支持系統的正常工作,比如MountService監聽是否有SD卡安裝及移除,ClipboardService提供剪切板功能,PackageManagerService提供軟件包的安裝移除及查看等等,應用程序可以通過系統提供的Manager接口來訪問這些Service提供的數據,

       大概實現類似TelephoneManager這樣的遠程服務,但是由於TelephoneManager是已經封裝過的代理類,是被谷歌閹割過的服務對象,其中部分方法我們是獲取不到的(@hide),所以我們不需要去獲取binder,但是對於調用另一個應用的service或者是調用服務中隱藏的方法的時候,需要通過aidl來通信,首先要獲取他的Ibinder對象。下面說下獲取閹割過的系統服務對象,以Telephony爲例

<span style="white-space:pre">	</span>@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        /**
         * 返回電話狀態
         * 
         * CALL_STATE_IDLE 無任何狀態時 
         * CALL_STATE_OFFHOOK 接起電話時
         * CALL_STATE_RINGING 電話進來時 
         */
        tm.getCallState();
 }
/** @hide */
    @SystemApi
    public void dial(String number) {
        try {
            getITelephony().dial(number);
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelephony#dial", e);
        }
    }
我們發現在TelephonyManager類中的dial()方法是@hide過的(谷歌出於安全考慮,或是二次開發的原因,將這些方法隱藏掉),這就是代理服務的劣勢。

下面介紹下通過getService的方式獲取系統服務。

public void endCall() {

		//IBinder iBinder = ServiceManager.getService(TELEPHONY_SERVICE);
		try {
			//加載servicemanager的字節碼
			Class clazz = CallSmsSafeService.class.getClassLoader().loadClass("android.os.ServiceManager");
			Method method = clazz.getDeclaredMethod("getService", String.class);
			IBinder ibinder = (IBinder) method.invoke(null, TELEPHONY_SERVICE);
			ITelephony.Stub.asInterface(ibinder).endCall();</span><span style="color:#362e2b;">
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
這種通過反射的方式獲取的系統服務能夠使用我們的@hide方法。


發佈了15 篇原創文章 · 獲贊 7 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章