經過反射了截取屏android
public class EncoderFeeder {
public static Bitmap screenshot() {
String surfaceClassName;
if (VERSION.SDK_INT <= 17) {
surfaceClassName = "android.view.Surface";
} else {
surfaceClassName = "android.view.SurfaceControl";
}
Class<?> classname;
Bitmap bm = null;
try {
classname = Class.forName(surfaceClassName);
Method method = classname.getDeclaredMethod("screenshot",
new Class[] { int.class, int.class });
bm = (Bitmap) method.invoke(
null,
new Object[] { Integer.valueOf(Device.x),//分辨率
Integer.valueOf(Device.y) });
} catch (Exception e) {
e.printStackTrace();
}
return bm;
}
}
複製代碼
這是咱們反射調用SurfaceControl.screenshot()和Surface.screenshot(),他們都是系統提供的截屏方法,但是這個方法被@hide的了,沒法調用,咱們但是使用反射的方式調用,但是咱們普通用戶經過代碼反射調用,方法會返回null,緣由是SurfaceControl這個類也被Google隱藏了, 咱們知道通adb shell 命令能夠調用screencap或者screenshot來截屏adb shell具備截屏截屏的權限也就是說adb shell可以調用到Surface和SurfaceControl這個兩個類。 怎麼經過adb shell來調用到這兩個類呢,這裏的主角是app_process,app_process能夠直接運行一個普通的Java類。 小結一下:shell
1.經過adb shell 命令來啓動一個app_process程序bash
export CLASSPATH=/data/app/com.test.syscreen-1.apk", "exec app_process /system/bin com.test.syscreen.Main '@@'
複製代碼
2.使用app_process程序來啓動一個Java程序,在Java程序中可訪問到Surface和SurfaceControl這兩個類,就能夠繞過Root,反射截屏。 更進一步的分析,爲何app_precess程序會有普通用戶訪問不到的東西呢,查了一下(app_process其實就是Zygote進程,Zygote是由app_process「更名」而來),android中應用程序的進程都是由Zygote進程孵化而來的,Zygote進程啓動時會建立一個Dalvik虛機實例,每當有新的應用用進程產生,Zygote會將虛擬機實例複製到它裏面,而且Zygote啓動時會將Java運行庫加載進來,因此一個新的應用有Zygote建立出來,不只擁有從Zygote拷貝來的虛擬機,還會和Zygote共享Java運行庫。app