1.使用方式
Android 5.0以上12 以下使用一下方式截图,以下是通过反射调用系统默认截图实现
前提应用需要有系统权限
转换成bitmap 后保存到本地 如果需要矩形截图的 需要在图片基础上进行矩形裁剪
package com.igrs.screencapture;
import android.accessibilityservice.AccessibilityService;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorSpace;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.os.Build;
import android.os.FileObserver;
import android.os.Handler;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import androidx.annotation.NonNull;
import com.droidlogic.app.ScreenControlManager;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author markLiu
* @title ViewUtil
* @time 2021/10/28 9:53
* @description
**/
public class ScreenCaptureService {
public static String cachePath;
public static int dp2px(Context context, float dp) {
return (int) (context.getResources().getDisplayMetrics().density * dp + 0.5f);
}
public static Bitmap screenShot(int x, int y,Context context) {
Class<?> cls = null;
Bitmap bitmap = null;
try {
cls = Class.forName("android.view.SurfaceControl");
} catch (Exception e) {
e.printStackTrace();
}
try {
if (Build.VERSION.SDK_INT <= 28) {
// android 8.0
Method method = cls.getMethod("screenshot", int.class, int.class);
Object obj = method.invoke(null, x, y);
bitmap = (Bitmap) obj;
} else if (Build.VERSION.SDK_INT <= 30) {
//android 12
Method method = cls.getMethod("screenshot", Rect.class, int.class, int.class, int.class);
Object obj = method.invoke(null, new Rect(0, 0, x, y), x, y, 0);
bitmap = (Bitmap) obj;
} else {
// andoird 12以上调用方式
bitmap = ScreenshotUtil.captureScreenshot(context,new Rect(0, 0, x, y)) ;
}
}catch (Exception e){
}
return bitmap;
}
public static void measureView(View view) {
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
}
public static boolean isAppInstalled(Context context, String packageName) {
try {
context.getPackageManager().getPackageInfo(packageName, 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
public static Bitmap savecreen(String name,Context context) {
File cacheDir = context.getCacheDir();
Log.i("liuhongliang","cacheDir" +cacheDir.toString());
cachePath = "/sdcard/" + name + ".png";
String cmd = "screencap -p /sdcard/" + name + ".png";
try {
// 权限设置
Process p = Runtime.getRuntime().exec("sh");
// 获取输出流
OutputStream outputStream = p.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(
outputStream);
// 将命令写入
dataOutputStream.writeBytes(cmd);
// 提交命令
dataOutputStream.flush();
// 关闭流操作
dataOutputStream.close();
outputStream.close();
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
/**
*
* @param path 图片路径
* @return
*/
/**
* 将本地图片转成Bitmap
* @param path 已有图片的路径
* @return
*/
public static Bitmap openImage(String path){
Bitmap bitmap = null;
File file = new File(path);
if (!file.exists()){
Log.i("liuhongliang","不存在");
}
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
bitmap = BitmapFactory.decodeStream(bis);
bis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
}
Android13 截屏适配截屏
1.需要Android 13 内部源码有改动,无法通过反射直接 screenShot调用截屏
需要将Android 13 源码jar 包fromwork 导入进来
以下代码是需要从源码中提取出来
package com.igrs.screencapture;
import static android.view.Display.DEFAULT_DISPLAY;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
import android.util.Log;
import android.view.Display;
import android.view.DisplayAddress;
import android.view.SurfaceControl;
public class ScreenshotUtil {
// 直接调用
public static Bitmap captureScreenshot(Context context, Rect crop) {
int width = crop.width();
int height = crop.height();
Bitmap screenshot = null;
final Display display = getDefaultDisplay(context);
final DisplayAddress address = display.getAddress();
if (!(address instanceof DisplayAddress.Physical)) {
Log.e("####", "Skipping Screenshot - Default display does not have a physical address: "
+ display);
} else {
final DisplayAddress.Physical physicalAddress = (DisplayAddress.Physical) address;
final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(
physicalAddress.getPhysicalDisplayId());
final SurfaceControl.DisplayCaptureArgs captureArgs =
new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
.setSourceCrop(crop)
.setSize(width, height)
.build();
final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
SurfaceControl.captureDisplay(captureArgs);
screenshot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
}
return screenshot;
}
public static Display getDefaultDisplay(Context context) {
DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
return displayManager.getDisplay(DEFAULT_DISPLAY);
}
}