作为安卓自动跳过广告三部曲的第二部分,主要是实现系统截屏功能。继《Android Skip Ads Yolov5 Project》之后,下一步就是获取当前屏幕的截图,把截图传入分析引擎实现广告跳过按钮的识别,最后一步是按钮点击。
要在安卓系统上实现截图(截取整个屏幕,并且需要截取其他app的界面),通常有下面三个方法:
1.直接调用系统的截屏工具,需要root权限
adb shell screencap -p /sdcard/sreenshot1.png
2.通过系统私有api实现截屏:
Bitmap mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
//通过反射进行调用
public Bitmap takeScreenShot() {
Bitmap bmp = null;
mDisplay.getMetrics(mDisplayMetrics);
float[] dims = {(float) mDisplayMetrics.widthPixels, (float) heightPixels};
float degrees = getDegreesForRotation(mDisplay.getRotation());
boolean requiresRotation = degrees > 0;
if (requiresRotation) {
mDisplayMatrix.reset();
mDisplayMatrix.preRotate(-degrees);
mDisplayMatrix.mapPoints(dims);
dims[0] = Math.abs(dims[0]);
dims[1] = Math.abs(dims[1]);
}
try {
Class<?> demo = Class.forName("android.view.SurfaceControl");
Method method = demo.getMethod("screenshot", new Class[]{Integer.TYPE, Integer.TYPE});
bmp = (Bitmap) method.invoke(demo, new Object[]{Integer.valueOf((int) dims[0]), Integer.valueOf((int) dims[1])});
if (bmp == null) {
return null;
}
if (requiresRotation) {
Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels, heightPixels, Bitmap.Config.RGB_565);
Canvas c = new Canvas(ss);
c.translate((float) (ss.getWidth() / 2), (float) (ss.getHeight() / 2));
c.rotate(degrees);
c.translate((-dims[0] / 2), (-dims[1] / 2));
c.drawBitmap(bmp, 0, 0, null);
c.setBitmap(null);
bmp.recycle();
bmp = ss;
}
if (bmp == null) {
return null;
}
bmp.setHasAlpha(false);
bmp.prepareToDraw();
return bmp;
} catch (Exception e) {
e.printStackTrace();
return bmp;
}
}
参考链接:https://www.jianshu.com/p/4ae89e1fb36a
3.通过MediaProjectionManager 录屏实现截屏:参考链接:https://www.jianshu.com/p/8a428fb45098
package cn.org.obaby.adsskiper;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.media.projection.MediaProjection;
import android.os.Build;
import android.os.DeadSystemException;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
import java.nio.ByteBuffer;
/**
* Created by Ln_Jan on 2018/12/13.
* 截屏工具
* 代码来源:https://github.com/LnJan/WechatLuckyMoneyGetter/
*/
public class ScreenShotter {
private static ScreenShotter instance = null;
private MediaProjection mMediaProjection;
private ImageReader mImageReader;
private boolean mIsNormalScreen = true;
private volatile Point[] mRealSizes = new Point[2];
private int mScreenRealHeight;
private int mScreenRealWidth;
private static final int PORTRAIT = 0;
private static final int LANDSCAPE = 1;
private ScreenShotter() {
mMediaProjection = null;
mImageReader = null;
mIsNormalScreen = checkScreenSizeIsNormal();
mScreenRealHeight = mIsNormalScreen ? getScreenHeight() : getScreenRealHeight();
mScreenRealWidth = getScreenWidth();
}
public static ScreenShotter getInstance() {
if (instance == null) {
instance = new ScreenShotter();
}
return instance;
}
public boolean isNormalScreen() {
return mIsNormalScreen;
}
public void setMediaProjection(MediaProjection projection) {
mMediaProjection = projection;
}
public boolean isShotterUseful() {
return mMediaProjection != null;
}
@SuppressLint("WrongConstant")
public Bitmap getScreenShotSync() throws DeadSystemException {
if (!isShotterUseful()) {
return null;
}
if (mImageReader == null) {
mImageReader = ImageReader.newInstance(
mScreenRealWidth,
mScreenRealHeight,
PixelFormat.RGBA_8888,//此处必须和下面 buffer处理一致的格式 ,RGB_565在一些机器上出现兼容问题。
1);
}
VirtualDisplay tmpDisplay = virtualDisplay();
try {
Thread.sleep(50); //需要稍微停一下,否则截图为空
} catch (InterruptedException e) {
e.printStackTrace();
}
Image img = mImageReader.acquireLatestImage();
if (img == null) {
return null;
}
int width = img.getWidth();
int height = img.getHeight();
final Image.Plane[] planes = img.getPlanes();
final ByteBuffer buffer = planes[0].getBuffer();
//每个像素的间距
int pixelStride = planes[0].getPixelStride();
//总的间距
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * width;
Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height,
Bitmap.Config.ARGB_8888);//虽然这个色彩比较费内存但是 兼容性更好
bitmap.copyPixelsFromBuffer(buffer);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
img.close();
//mImageReader.close();
tmpDisplay.release();
return bitmap;
}
public int getScreenWidthPublic() {
return mScreenRealWidth;
}
public int getScreenHeightPublic() {
return mScreenRealHeight;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private VirtualDisplay virtualDisplay() {
return mMediaProjection.createVirtualDisplay("baby-screen-mirror",
getScreenWidth(),
getScreenHeight(),
Resources.getSystem().getDisplayMetrics().densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mImageReader.getSurface(), null, null);
}
private int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
private int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
/**
* 某些全面屏手机获取的屏幕宽度不对,需用此方法获取宽度
*
* @return
*/
private int getScreenRealHeight() {
int orientation = LuckyMoneyTinkerApplication.getContext().getResources().getConfiguration().orientation;
orientation = orientation == Configuration.ORIENTATION_PORTRAIT ? PORTRAIT : LANDSCAPE;
if (mRealSizes[orientation] == null) {
WindowManager windowManager = (WindowManager) LuckyMoneyTinkerApplication.getContext().getSystemService(Context.WINDOW_SERVICE);
if (windowManager == null) {
return getScreenHeight();
}
Display display = windowManager.getDefaultDisplay();
Point point = new Point();
display.getRealSize(point);
mRealSizes[orientation] = point;
}
return mRealSizes[orientation].y;
}
/**
* 检查屏幕尺寸是否16:9
* 某些18:9的全面屏手机会出现截屏位置偏移的问题
*
* @return
*/
private boolean checkScreenSizeIsNormal() {
DisplayMetrics dm = new DisplayMetrics();
dm = Resources.getSystem().getDisplayMetrics();
int screenWidth = dm.widthPixels;
int screenHeight = dm.heightPixels;
return screenHeight < screenWidth * 1.8;
}
}
整体项目地址:https://github.com/obaby/skip_ads_android
☆文章版权声明☆
* 网站名称:obaby@mars
* 网址:https://h4ck.org.cn/
* 本文标题: 《Android Skip Ads Android Project【截屏部分】》
* 本文链接:https://cloud.tencent.com/developer/article/2221018
* 转载文章请标明文章来源,原文标题以及原文链接。请遵从 《署名-非商业性使用-相同方式共享 2.5 中国大陆 (CC BY-NC-SA 2.5 CN) 》许可协议。
分享文章: