需要獲取simunlockstate狀態,而這個不由我們這邊控制,在免于提Mtk case的情況下,通過Telephony獲取這個值,telephony是個服務apk,不能通過android.bp引入,考慮到這個原因,我覺得通過aidl以telephony為服務器端,MtkSettings為客戶端,進行跨進程通信。下面說下步驟: 1.在服務器端新建aidl目錄和文件,這里通過AndroidStudio去生成(New -> Aidl ->AIDL File)。生成完后記得rebuild一下,但是我這個是源碼工程,rebuild后肯定會報錯,但只要生成aidl生成了相應的派生類那就沒關系。
// INetworkUnlockStatus.aidl
package com.android;// Declare any non-default types here with import statementsinterface INetworkUnlockStatus {int getNetworkUnlockStatus();
}
2.服務器端建立service
public class NetworkUnlockService extends Service {private final String TAG = "NetworkUnlockService";@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG, "getNetworkUnlockStatus has onBind");return mUnlockManager;}private final INetworkUnlockStatus.Stub mUnlockManager = new INetworkUnlockStatus.Stub() {@Overridepublic int getNetworkUnlockStatus() throws RemoteException {Log.d(TAG, "getNetworkUnlockStatus has exec");return getState();}};int getState() {MtkPhoneInterfaceManagerEx mtkPhoneInterfaceManagerEx = MtkPhoneInterfaceManagerEx.init((PhoneGlobals) getApplicationContext());int simLockStateForRSU = mtkPhoneInterfaceManagerEx.getSimLockStateForRSU(0);return simLockStateForRSU;}}
記得聲明下并且export為true:
<service android:name=".NetworkUnlockService"android:exported="true"android:enabled="true"><intent-filter><action android:name="com.unlock.state.aidl"/><category android:name="android.intent.category.DEFAULT"/></intent-filter></service>
3.移植aidl包到客戶端主目錄,和main同級即可,確保包名一致 4.客戶端合適的時機去啟動遠程service:
Intent intent = new Intent();intent.setAction("com.unlock.state.aidl");intent.setPackage("com.android.phone");mContext.bindServiceAsUser(intent, mCon, Context.BIND_AUTO_CREATE, UserHandle.CURRENT);
ServiceConnection:
private ServiceConnection mCon = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.d(TAG, "onServiceConnected");INetworkUnlockStatus asInterface = INetworkUnlockStatus.Stub.asInterface(service);if (null != asInterface) {try {networkUnlockStatus = asInterface.getNetworkUnlockStatus();Log.d(TAG, "onServiceConnected networkUnlockStatus:" + networkUnlockStatus);} catch (RemoteException e) {Log.d(TAG, "onServiceConnected RemoteException e:" + e.getMessage());e.printStackTrace();}}}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.d(TAG, "onServiceDisconnected");}};
注意,如果用的是bindService會爆錯誤無法運行Calling a method in the system process without a qualified user,根據源碼就知道需要調用bindServiceAsUser,其實bindService后面也是調用了bindServiceAsUser的。
5.由于我這是在源碼層的修改,所以需要在Android.bp進行aidl包的導入,注意在android R之前可能是Android.mk。下面代碼只要看 srcs: [“src/**/*.java”,“aidl/com/android/INetworkUnlockStatus.aidl”], 這個位置即可:
// Build the Settings APK
android_library {name: "MtkSettings-core",platform_apis: true,defaults: ["MtkSettingsLibDefaults","SettingsLibDefaults","SettingsLib-search-defaults",],srcs: ["src/**/*.java","aidl/com/android/INetworkUnlockStatus.aidl"],resource_dirs: ["res","res_ext",],static_libs: ["nfc_settings_adapter","androidx-constraintlayout_constraintlayout","androidx.slice_slice-builders","androidx.slice_slice-core","androidx.slice_slice-view","androidx.core_core","androidx.appcompat_appcompat","androidx.cardview_cardview","androidx.preference_preference","androidx.recyclerview_recyclerview","com.google.android.material_material","setupcompat","setupdesign","androidx-constraintlayout_constraintlayout-solver","androidx.lifecycle_lifecycle-runtime","androidx.lifecycle_lifecycle-extensions","guava","jsr305","com.mediatek.lbs.em2.utils","mtksettings-contextual-card-protos-lite","mtksettings-log-bridge-protos-lite","mtkcontextualcards","mtksettings-logtags","com.mediatek.settings.ext","statslog-mtksettings","zxing-core-1.7","android.hardware.dumpstate-V1.0-java","android.hardware.dumpstate-V1.1-java",],libs: ["telephony-common","ims-common","app-compat-annotations","mediatek-telephony-base","mediatek-telephony-common","mediatek-common","mediatek-framework","mediatek-ims-common",],
}
Telephony的Android.bp也是一樣,我就不重復了。 客戶端調用完整代碼:
public class NetworkUnlockPreferenceController extends BasePreferenceController implements PreferenceManager.OnActivityStopListener {private Context mContext;String packageName = "com.assurance.rsuapp";String className = "com.tmobile.rsuapp.MainActivity";private String TAG = "NetworkUnlockPreferenceController";private int networkUnlockStatus;public NetworkUnlockPreferenceController(Context context, String preferenceKey) {super(context, preferenceKey);mContext = context;}@Overridepublic int getAvailabilityStatus() {return AVAILABLE;}@Overridepublic void displayPreference(PreferenceScreen screen) {super.displayPreference(screen);}@Overridepublic boolean handlePreferenceTreeClick(Preference preference) {if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {return false;}ComponentName componentName = new ComponentName(packageName, className);startApp(componentName, null);return true;}@Overridepublic CharSequence getSummary() {startUnlockStatusService();String state = "";switch (networkUnlockStatus) {case 0:state = mContext.getResources().getString(R.string.locked_status);break;case 1:state = mContext.getResources().getString(R.string.temporarily_locked_status);break;case 2:state = mContext.getResources().getString(R.string.permanently_locked_status);break;}return state;}@TargetApi(Build.VERSION_CODES.DONUT)private void startUnlockStatusService() {Intent intent = new Intent();intent.setAction("com.unlock.state.aidl");intent.setPackage("com.android.phone");mContext.bindServiceAsUser(intent, mCon, Context.BIND_AUTO_CREATE, UserHandle.CURRENT);}private ServiceConnection mCon = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.d(TAG, "onServiceConnected");INetworkUnlockStatus asInterface = INetworkUnlockStatus.Stub.asInterface(service);if (null != asInterface) {try {networkUnlockStatus = asInterface.getNetworkUnlockStatus();Log.d(TAG, "onServiceConnected networkUnlockStatus:" + networkUnlockStatus);} catch (RemoteException e) {Log.d(TAG, "onServiceConnected RemoteException e:" + e.getMessage());e.printStackTrace();}}}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.d(TAG, "onServiceDisconnected");}};private void startApp(ComponentName com, String param) {if (com != null) {PackageInfo packageInfo;try {packageInfo = mContext.getPackageManager().getPackageInfo(com.getPackageName(), 0);} catch (PackageManager.NameNotFoundException e) {packageInfo = null;e.printStackTrace();}try {Intent intent = new Intent();intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.setComponent(com);if (param != null) {Bundle bundle = new Bundle();bundle.putString("flag", param);intent.putExtras(bundle);}mContext.startActivity(intent);} catch (Exception e) {Log.e(TAG, "Exception", e);}}}@Overridepublic void onActivityStop() {mContext.unbindService(mCon);}
}
6.需要注意的是,我在preference里綁定的service,而preference類似activity,fragment的生命周期,所以我實現PreferenceManager.OnActivityStopListener,在對應的Activity銷毀的時候進行解綁service。另外,Telephony編譯生成的apk是不能直接adb install -r安裝的,也不能直接push,需要先刪除之前的telephony即可push,然后reboot就能生效,MtkSettings的話可以直接install -r,也不要重啟。
總結
以上是生活随笔 為你收集整理的Android R版本 MtkSettings和Telephony进程通信aidl 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。