Android 截屏服务
Posted 泸沽烟火
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 截屏服务相关的知识,希望对你有一定的参考价值。
package com.xxxx.xxxx.xxxx.xxxx.xxxx;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
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.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.IBinder;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import com.xxxx.xxxx.CourseApplication;
import com.xxxx.xxxx.R;
import com.xxxx.xxxx.utils.RxJavaUtil;
import java.nio.ByteBuffer;
/**
* 截屏
*/
public class ServicesScreenCapture extends Service
private static final int NOTIFICATION_ID = 1111;
public static final String ON_START = "onStartScreenCapture";
public static final String ON_FINISH = "onFinishScreenCapture";
public static final String ON_ERROR = "onErrorScreenCapture";
private int resultCode;
private Intent resultData;
private MediaProjectionManager mediaProjectionManager;
@Nullable
@Override
public IBinder onBind(Intent intent)
return null;
@Override
public void onCreate()
super.onCreate();
sendBroadcast(new Intent(ON_START));
Notification notification = createForegroundNotification();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION);
else
startForeground(NOTIFICATION_ID, notification);
@Override
public void onDestroy()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
stopForeground(STOP_FOREGROUND_REMOVE);
else
stopForeground(true);
super.onDestroy();
@SuppressLint("WrongConstant", "RestrictedApi")
@Override
public int onStartCommand(Intent intent, int flags, int startId)
mediaProjectionManager = (MediaProjectionManager) CourseApplication.CONTEXT.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
resultCode = intent.getIntExtra("code", -1);
resultData = intent.getParcelableExtra("data");
RxJavaUtil.runTimer(500, new RxJavaUtil.OnRxRunTimerListener()
@Override
public void onStart()
@Override
public void onExecute(Long l)
@Override
public void onFinish()
MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData);
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
ImageReader imageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2);
VirtualDisplay virtualDisplay = mediaProjection.createVirtualDisplay("screen-mirror",
width, height,
displayMetrics.densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
imageReader.getSurface(), null, null);
imageReader.setOnImageAvailableListener(reader ->
Image image = reader.acquireLatestImage();
final Image.Plane[] planes = image.getPlanes();
final ByteBuffer buffer = planes[0].getBuffer();
int w = image.getWidth();
int h = image.getHeight();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * w;
Bitmap bitmap = Bitmap.createBitmap(w + rowPadding / pixelStride, h, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), false);
if (bitmap != null)
MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, System.currentTimeMillis() + "", "welearn");
bitmap.recycle();
imageReader.close();
mediaProjection.stop();
virtualDisplay.release();
sendBroadcast(new Intent(ON_FINISH));
stopSelf();
, null);
@Override
public void onError(Throwable e)
sendBroadcast(new Intent(ON_ERROR));
stopSelf();
);
return super.onStartCommand(intent, flags, startId);
private Notification createForegroundNotification()
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// 唯一的通知通道的id.
String notificationChannelId = "notification_channel_id_screen_capture";
// Android8.0以上的系统,新建消息通道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
//用户可见的通道名称
String channelName = "ScreenCapture";
//通道的重要程度
int importance = NotificationManager.IMPORTANCE_NONE;
NotificationChannel notificationChannel = new NotificationChannel(notificationChannelId, channelName, importance);
notificationChannel.setDescription("截屏");
notificationChannel.enableLights(false);
notificationChannel.enableVibration(false);
if (notificationManager != null)
notificationManager.createNotificationChannel(notificationChannel);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, notificationChannelId);
//通知小图标
builder.setSmallIcon(R.drawable.icon);
//通知标题
builder.setContentTitle("截屏");
//通知内容
builder.setContentText("截屏");
//设定通知显示的时间
builder.setWhen(System.currentTimeMillis());
//设定启动的内容
// Intent activityIntent = new Intent(this, NotificationActivity.class);
// PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// builder.setContentIntent(pendingIntent);
//创建通知并返回
return builder.build();
Manifest添加
<service
android:name=".activity.classroomactivities.signin.ServicesScreenCapture"
android:enabled="true"
android:foregroundServiceType="mediaProjection" />
注册调用
一。
if (screenCaptureReceiver == null)
screenCaptureReceiver = new ScreenCaptureReceiver(activity);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ServicesScreenCapture.ON_START);
intentFilter.addAction(ServicesScreenCapture.ON_FINISH);
intentFilter.addAction(ServicesScreenCapture.ON_ERROR);
activity.registerReceiver(screenCaptureReceiver, intentFilter);
Intent intent = ((MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE)).createScreenCaptureIntent();
activity.startActivityForResult(intent, SignInActivity.REQUEST_CODE_SCREEN_CAPTURE);
二。
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
if (requestCode == SignInActivity.REQUEST_CODE_SCREEN_CAPTURE)
//开启截屏服务
Intent service = new Intent(activity, ServicesScreenCapture.class);
service.putExtra("code", resultCode);
service.putExtra("data", data);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
activity.startForegroundService(service);
else
activity.startService(service);
广播监听
private static class ScreenCaptureReceiver extends BroadcastReceiver
private final WeakReference<SignInActivity> activity;
public ScreenCaptureReceiver(SignInActivity activity)
this.activity = new WeakReference<>(activity);
@Override
public void onReceive(Context context, Intent intent)
SignInActivity activity = this.activity.get();
if (activity != null)
switch (intent.getAction())
case ServicesScreenCapture.ON_START:
break;
case ServicesScreenCapture.ON_FINISH:
Common.showShortToast(activity, "截屏完成,请在相册中查看");
break;
case ServicesScreenCapture.ON_ERROR:
Common.showShortToast(activity, "截屏失败");
break;
以上是关于Android 截屏服务的主要内容,如果未能解决你的问题,请参考以下文章