起因
在系统升级到Android10以上之后,之前的截屏方式不能用了,而且必须将MediaProjection放在forground service里面跑才行。网上搜了一圈,都是语焉不详或者没有完整的一个代码应用。只能自己写一个,记录下
代码实现
新建一个ScreenRecorder.java
public class ScreenRecorder extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private MediaProjection mMediaProjection;
private MediaProjectionManager mMediaProjectionManager;
private int SERVICE_ID = 123;
private String NOTIFICATION_CHANNEL_ID = "Screen Capture channel";
public static final String ACTION_START = "RecordService:Start";
public static final String ACTION_SNAPSHOT = "RecordService:Snapshot";
public static final String ACTION_STOP = "RecordService:Stop";
public static final String EXTRA_RESULT_DATA = "RecordService:Extra:ResultData";
@Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
startForeground(SERVICE_ID, new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID).build());
mMediaProjectionManager = (MediaProjectionManager) getApplicationContext().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
}
@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
if (intent != null) {
if (intent.getAction() != null) {
switch (intent.getAction()) {
case ACTION_START:
Log.d(TAG, "onStartCommand: start recorder");
mMediaProjection = mMediaProjectionManager.getMediaProjection(Activity.RESULT_OK,
Objects.requireNonNull(intent.getParcelableExtra(EXTRA_RESULT_DATA)));
startCapture();
return START_STICKY;
case ACTION_SNAPSHOT:
// stopSelf();
snapshot();
break;
case ACTION_STOP:
Log.d(TAG, "onStartCommand: close imagereader");
if (mImageReader != null){
try{
mImageReader.close();
}catch (Exception exception){
Log.e(TAG, "onStartCommand: "+ exception.getMessage() );
}
}
stopSelf();
return START_NOT_STICKY;
}
}
}
return super.onStartCommand(intent, flags, startId);
}
private void createNotificationChannel() {
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"ScreenRecorder",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(notificationChannel);
}
private ImageReader mImageReader;
private void startCapture() {
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
mImageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 2);
mMediaProjection.createVirtualDisplay("mediaprojection", screenWidth, screenHeight,
displayMetrics.densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader.getSurface(), null, null);
}
private void snapshot(){
if (mImageReader != null){
Image image = mImageReader.acquireLatestImage();
int width = image.getWidth();
int height = image.getHeight();
final Image.Plane[] planes = image.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);
//保存图片到本地
CommonLib.saveMyBitmap("snapshot", bitmap);
image.close();
}
}
}
AndroidManifest.xml中注册
<!-- 申请权限 />-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<service android:name=".ScreenRecorder"
android:exported="true"
android:foregroundServiceType="mediaProjection"/>
Activity中调用
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
requestCapturePermission();
}
/**
* 申请权限
*/
public void requestCapturePermission() {
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
Intent intent = new Intent(mediaProjectionManager.createScreenCaptureIntent());
startActivityForResult(intent, REQUESTRESULT);
}
// 回调里面启动服务
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
Intent intent = new Intent(this, ScreenRecorder.class);
intent.setAction(ScreenRecorder.ACTION_START);
intent.putExtra(ScreenRecorder.EXTRA_RESULT_DATA, data);
startForegroundService(intent);
EnableTakePhotos = true;
}
}
snapshot方法
private void startSnapshot(){
Intent intent = new Intent(this, ScreenRecorder.class);
intent.setAction(ScreenRecorder.ACTION_SNAPSHOT);
startService(intent);
}
可以设置一个按钮,然后在点击事件里面调用startSnapshot()
方法即可