天天看點

Android 使用反射調用自定義AIDL **.Stub.asInterface(IBinder obj)、反射實作關機shutdown

自定義AIDL調用

有時根據項目需要會增加系統沒有的AIDL檔案,如:

新增 com.android.internal.telephony.IVideoTelephony;

不使用反射時的調用方式如下(需依賴系統編譯才能通過):

private boolean isVTCall(){
try{
IVideoTelephony vtInterface = null;
vtInterface = IVideoTelephony.Stub.asInterface(checkService("videophone"));
if(null != vtInterface){
if(vtInterface.isVtActive())
return true;o
}
}
catch(Exception e){}
return false;
}

----------------

private IBinder checkService(String name){
IBinder iBinder = null;
try{
Class<?> clz = Class.forName("android.os.ServiceManager");
Method checkService = clz.getMethod("checkService", String.class);
checkService.setAccessible(true);
iBinder = (IBinder)checkService.invoke(null, name);
}
catch(Exception e) {}
return iBinder;
}
           

使用反射調用

private boolean isVtActive(){
boolean isVtActive = false;
try{
Class<?> clz = Class.forName("com.android.internal.telephony.IVideoTelephony$Stub");
Method asInterface = clz.getDeclaredMethod("asInterface", IBinder.class);
Object IVideoTelephony = asInterface.invoke(null, checkService("videophone"));
Method isVtActiveMethod = IVideoTelephony.getClass().getDeclaredMethod("isVtActive",null);
isVtActive = (Boolean)isVtActiveMethod.invoke(IVideoTelephony, null);
}
catch(Exception e){}
return isVtActive;
}
           

代碼解析:

1. 首先通過Class 加載”com.android.internal.telephony.IVideoTelephony$Stub”内部類;

2. 接着調用”asInterface”方法生成Object IVideoTelephony執行個體;

3. 然後擷取”isVtActive”方法,通過invoke将執行個體IVideoTelephony傳入并擷取傳回值即可

通過反射實作關機

public static void shutDown(){
        try {
            Class<?> clz = Class.forName("android.os.ServiceManager");
            Method getService = clz.getMethod("getService", String.class);
            Object powerService = getService.invoke(null, Context.POWER_SERVICE);
            Class<?> cStub =  Class.forName("android.os.IPowerManager$Stub");
            Method asInterface = cStub.getMethod("asInterface", IBinder.class);
            Object IPowerManager = asInterface.invoke(null, powerService);
            Method shutDown = IPowerManager.getClass().getMethod("shutdown", boolean.class, boolean.class);
            shutDown.invoke(IPowerManager, false,true);
        } catch (Exception e) {
            Log.e("wmb", "--shutDown has an exception");
            e.printStackTrace();
        }
    }
           

關機shutdown代碼,親測有效。

注意點:

調用shutDown.invoke(IPowerManager, false,true);需要系統權限,在manifest中增加android:sharedUserId=”android.uid.system”,并将應用push到/system/priv-app目錄下,重新開機才能生效。