Android 截屏实现的几种方式

这篇具有很好参考价值的文章主要介绍了Android 截屏实现的几种方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Android 截屏分为四种:View 截屏、WebView 截屏、系统截屏 和 adb 截屏

Android 截屏实现的几种方式

image.png

Android 截屏实现的几种方式

image.png

1、View 截屏

View 截图是将当前 View 界面截取下来,而对于屏幕上其他信息比如:状态栏或其他应用的界面将无法截取。

1.1 截取除了导航栏之外的屏幕

    // 开始截屏
    private static byte[] screenshotView() {

        // ⬇⬇⬇ 可直接放入点击事件中 ⬇⬇⬇
        View view = getWindow().getDecorView(); // view可以替换成你需要截图的控件,如父控件 RelativeLayout,LinearLayout
        // view.setDrawingCacheEnabled(true); // 设置缓存,可用于实时截图
        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        view.draw(canvas);
        // view.setDrawingCacheEnabled(false); // 清空缓存,可用于实时截图

        String bitmapString = getBitmapString(bitmap); // 位图转 Base64 String
        // byte[] drawByte = getBitmapByte(bitmap); // 位图转为 Byted

        Log.d("111111 合并>>", "bitmapString ====:" + bitmapString);
        matting_img02.setImageBitmap(bitmap); // ImageView控件直接图片展示截好的图片
        // ⬆⬆⬆ 可直接放入点击事件中 ⬆⬆⬆

        return drawByte;
    }

    // 位图转 Base64 String
    private static String getBitmapString(Bitmap bitmap) {
        String result = null;
        ByteArrayOutputStream out = null;
        try {
            if (bitmap != null) {
                out = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);

                out.flush();
                out.close();

                byte[] bitmapBytes = out.toByteArray();
                result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT); // Base64.DEFAULT会自动换行,传给前端会报错,所以要用Base64.NO_WRAP
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    // 位图转 Byte
    private static byte[] getBitmapByte(Bitmap bitmap) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 参数1转换类型,参数2压缩质量,参数3字节流资源
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        try {
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();
    }



1.2 截取某个控件或者区域

// 方法1
private static byte[] screenshotView1() {
  View view = title;
  view.setDrawingCacheEnabled(true);
  view.buildDrawingCache();
  Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
  byte[] drawByte = getBitmapByte(bitmap);
  return drawByte;
}

// 方法2
private static byte[] screenshotView2() {
  View view = title;
  Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
  // 使用 Canvas,调用自定义 view 控件的 onDraw 方法,绘制图片
  Canvas canvas = new Canvas(bitmap);
  dView.draw(canvas);
  byte[] drawByte = getBitmapByte(bitmap);
  return drawByte;
}

2、WebView 截屏

WebView 截屏有四种方式

2.1 使用 capturePicture() 方法(已废弃)
private static byte[] screenshotWebView() {
Picture picture = webview.capturePicture();
//创建位图
Bitmap bitmap = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// 绘制(会调用 native 方法,完成图形绘制)
picture.draw(canvas);
byte[] drawByte = getBitmapByte(bitmap);
return drawByte;
}

2.2 使用 getScale() 方法(已废弃)

private static byte[] screenshotWebView() {
float scale = webView.getScale();
int webViewHeight = (int) (webView.getContentHeight()*scale+0.5);
Bitmap bitmap = Bitmap.createBitmap(webView.getWidth(),webViewHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
webView.draw(canvas);
byte[] drawByte = getBitmapByte(bitmap);
return drawByte;
}

2.3 使用 getDrawingCache() 方法

private static byte[] screenshotWebView() {
Bitmap bitmap = webView.getDrawingCache();
byte[] drawByte = getBitmapByte(bmp);
return drawByte;
}

2.4 使用 draw() 方法

private static byte[] screenshotWebView() {
// webView.setDrawingCacheEnabled(true); // 设置缓存
Bitmap bitmap = Bitmap.createBitmap(webView.getWidth(), webView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
webView.draw(canvas);
webView.destroyDrawingCache();
byte[] drawByte = getBitmapByte(bitmap);
// webView.setDrawingCacheEnabled(false); // 清空缓存
return drawByte;
}

2.5 截长图配置

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
WebView.enableSlowWholeDocumentDraw();
}
setContentView(R.layout.activity_webview);

WebView 截图可能截取不到 cavans 元素,原因是开启了硬件加速,可在 AndroidManifest.xml 中设置属性 android:hardwareAccelerated="false"

关闭硬件加速可能导致页面出现意外情况

3、系统截屏

3.1 MediaProjection

public static final int REQUEST_MEDIA_PROJECTION = 10001;
// 申请截屏权限
private void getScreenShotPower() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
MediaProjectionManager mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (mProjectionManager != null) {
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
}
}
}

private MediaProjection mMediaProjection;
// 回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_MEDIA_PROJECTION && data != null) {
if (resultCode == RESULT_OK) {
MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
if (mediaProjection == null) {
Toast.makeText(this,"程序发生错误:MediaProjection@1",Toast.LENGTH_SHORT).show();
return;
}
// mediaProjection 就是当前屏幕流
} else if (resultCode == RESULT_CANCELED) {
Log.d(TAG, "用户取消");
}
}
}

3.2 Surface(需要 root 权限)

使用前需要:

在 AndroidMenifest.xml 中添加 android:sharedUserId="android.uid.system" 属性
需要给程序添加系统签名
或者 root 系统
使用 Java 反射机制,调用系统 API 截图:

private void screenshotSystem() {
Class<?> surfaceClass;
Method method = null;
Bitmap bitmap = null;
try {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
surfaceClass = Class.forName("android.view.SurfaceControl");
} else {
surfaceClass = Class.forName("android.view.Surface");
}
method = surfaceClass.getDeclaredMethod("screenshot", Integer.TYPE, Integer.TYPE);
method.setAccessible(true);
bitmap = (Bitmap)method.invoke((Object)null, webview.getWidth(), webview.getHeight());
byte[] drawByte = getBitmapByte(bitmap);
} catch (ClassNotFoundException e){
e.printStackTrace();
} catch (NoSuchMethodException e){
e.printStackTrace();
} catch (IllegalAccessException e){
e.printStackTrace();
} catch (InvocationTargetException e){
e.printStackTrace();
}
}

3.3 PixelCopy

private void screenshotSystem() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PixelCopy.request(getWindow(), bitmap, new PixelCopy.OnPixelCopyFinishedListener() {
@Override
public void onPixelCopyFinished(int copyResult){
if (PixelCopy.SUCCESS == copyResult) {
byte[] drawByte = getBitmapByte(bitmap);
} else {
// onErrorCallback()
}
}
}, new Handler());
}
}

3.4 framebuffer(需要 root 权限)

String DEVICE_NAME = "/dev/graphics/fb0";
File deviceFile = new File(DEVICE_NAME);
Process localProcess = Runtime.getRuntime().exec("supersu");
String str = "cat " + deviceFile.getAbsolutePath() + "\n";
localProcess.getOutputStream().write(str.getBytes());
return localProcess.getInputStream();

3.5 screencap 命令(需要 root 权限)

private static String getScreenshot(){
Process process = null;
String filePath = "mnt/sdcard/" + System.currentTimeMillis() + ".png";
try {
process = Runtime.getRuntime().exec("su");
PrintStream outputStream = null;
outputStream = new PrintStream(new BufferedOutputStream(process.getOutputStream(), 8192));
outputStream.println("screencap -p " + filePath);
outputStream.flush();
outputStream.close();
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(process != null){
process.destroy();
}
}
return filePath;
}文章来源地址https://www.toymoban.com/news/detail-456991.html

4、adb 截屏

$ adb shell
shell@ $ screencap /sdcard/screen.png
shell@ $ exit
$ adb pull /sdcard/screen.png

到了这里,关于Android 截屏实现的几种方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 实现跨域的几种方式

    前后端的分离导致了跨域的产生  跨域的三要素:协议 域名 端口 三者有一个不同即产生跨域 例如: http ://www.csdn.com https ://www.csdn.com 由于协议不同,端口不同而产生跨域 注:http的默认端口80,https的默认端口443 跨域的解决方案 前端:webpack proxy,jsonp,ngix反向代理,webpac

    2024年02月13日
    浏览(31)
  • 单例模式的几种实现方式

    在Java中,实现单例模式主要有几种方式:懒汉式、饿汉式、双重检查锁定、静态内部类和枚举。每种方式都有其特点和适用场景。 1. 饿汉式(线程安全) 饿汉式是最简单的一种实现方式,通过静态初始化实例,保证了线程安全。但它不是懒加载模式,无法在实际使用时才创

    2024年02月20日
    浏览(29)
  • 线程间实现通信的几种方式

    线程间通信的模型有两种:共享内存和消息传递,下面介绍的都是围绕这两个来实现 有两个线程A和B,B线程向一个集合里面依次添加元素“abc”字符串,一共添加10次,当添加到第五次的时候,希望线程A能够收到线程B的通知,然后B线程执行相关的业务操作 Object类提供了线程

    2024年02月15日
    浏览(35)
  • Java实现异步的几种方式

    普通线程实现异步,但频繁创建、销毁线程比较耗资源,所以一般交给线程池执行 结果: Future异步 和普通线程实现异步区别不大,只是使用Future是要获取执行后的返回值 结果: Spring的@Async异步 使用@Async注解实现异步的前提是需要在启动类上标注@EnableAsync来开启异步配置

    2024年02月04日
    浏览(42)
  • 前端实现动画的几种方式简介

    这里只是做简要介绍,属于知识的拓展。每种方案的更详细的使用方式需要各位自行了解。 大体上技术方案分为:CSS 动画、SVG 动画、CSS + SVG、JS 控制的逐帧动画、GIF 图。 CSS 实现动画有两种方式,一种是使用 trasition ;另一种是使用 animation 。 默认情况下,当 CSS 中的属性值

    2024年04月22日
    浏览(26)
  • JavaScript里实现继承的几种方式

    JavaScript 中的继承可以通过以下几种方式来实现: 1、原型链继承 :通过将子类的原型对象指向父类的实例来实现继承。这种方式的优点是实现简单,缺点是父类的私有属性和方法子类是不能访问的。   2、借用构造函数继承 :通过在子类的构造函数中调用父类的构造函数来

    2023年04月23日
    浏览(32)
  • SpringBoot实现异步调用的几种方式

    一、使用 CompletableFuture 实现异步任务 CompletableFuture 是 Java 8 新增的一个异步编程工具,它可以方便地实现异步任务。使用 CompletableFuture 需要满足以下条件: 异步任务的返回值类型必须是 CompletableFuture 类型; 在异步任务中使用 CompletableFuture.supplyAsync() 或 CompletableFuture.runAsy

    2024年02月08日
    浏览(32)
  • Qt 多线程的几种实现方式

    Qt多线程的实现方式有: 1. 继承QThread类,重写run()方法 2. 使用moveToThread将一个继承QObject的子类移至线程,内部槽函数均在线程中执行 3. 使用QThreadPool,搭配QRunnable(线程池) 4. 使用QtConcurrent(线程池) 为什么要用线程池? 创建和销毁线程需要和OS交互,少量线程影响不大,

    2024年02月15日
    浏览(27)
  • vue深拷贝的几种实现方式

    1、通过递归方式实现深拷贝 比较全面的深拷贝,缺点是较为繁琐 2、JSON.parse(JSON.stringify(obj)) 满足一般使用场景,但无法实现对象中方法(function)的深拷贝 3、jQuery的extend方法实现深拷贝 4、Object.assign(obj1, obj2) 只有一级属性为深拷贝,二级属性后就是浅拷贝 5、扩展运算符 只有

    2024年02月09日
    浏览(34)
  • 分布式 ID 的几种实现方式

    随着互联网技术的快速发展,分布式系统在各个领域得到了广泛的应用。分布式 ID 是分布式系统中的一种重要概念,用于唯一标识系统中生成的各种数据。在分布式环境下,如何高效、可靠地生成分布式 ID 是一个具有挑战性的问题。本文将介绍几种常见的分布式 ID 实现方式

    2024年01月23日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包