前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Android Skip Ads Android Project【截屏部分】

Android Skip Ads Android Project【截屏部分】

作者头像
obaby
发布2023-02-22 11:05:11
发布2023-02-22 11:05:11
65000
代码可运行
举报
文章被收录于专栏:obaby@marsobaby@mars
运行总次数:0
代码可运行

作为安卓自动跳过广告三部曲的第二部分,主要是实现系统截屏功能。继《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
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021年9月23日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 相关文章:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档