Android獲取系統服務getSystemService與getService區別
阿新 • • 發佈:2019-02-06
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方法。