首页
学习
活动
专区
圈层
工具
发布
清单首页Yolo文章详情

Android Skip Ads Android Project【截屏部分】

作为安卓自动跳过广告三部曲的第二部分,主要是实现系统截屏功能。继《Android Skip Ads Yolov5 Project》之后,下一步就是获取当前屏幕的截图,把截图传入分析引擎实现广告跳过按钮的识别,最后一步是按钮点击。

要在安卓系统上实现截图(截取整个屏幕,并且需要截取其他app的界面),通常有下面三个方法:

1.直接调用系统的截屏工具,需要root权限

代码语言:javascript
代码运行次数:0
复制
adb shell screencap -p /sdcard/sreenshot1.png

2.通过系统私有api实现截屏:

代码语言:javascript
代码运行次数:0
复制
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

代码语言:javascript
代码运行次数:0
复制
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) 》许可协议。


分享文章:

相关文章:

  1. Android Skip Ads Yolov5 Project
  2. IDA Android Remote Debug
  3. Android PicasaTool Ad Free
  4. Android OS and SoftWare Protection Research
  5. Yolov5 Android torchscript方式集成
  6. Android 检测坐标是否在国内
  7. Android Game Cheate Engine
  8. Yolov5 Android tf-lite方式集成
  9. Android Studio动态调试smali
  10. Android APK installer for Windows/Linux/Mac OSX
下一篇
举报
领券