diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2cafe2f..a849a4d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -8,17 +8,25 @@
+
+
+
+
-
+
@@ -27,7 +35,10 @@
-
+
+
diff --git a/app/src/main/java/com/ttstd/remoteservice/activity/main/MainActivity.java b/app/src/main/java/com/ttstd/remoteservice/activity/main/MainActivity.java
index ba50e7b..e4b2611 100644
--- a/app/src/main/java/com/ttstd/remoteservice/activity/main/MainActivity.java
+++ b/app/src/main/java/com/ttstd/remoteservice/activity/main/MainActivity.java
@@ -1,10 +1,27 @@
package com.ttstd.remoteservice.activity.main;
+import android.Manifest;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.media.projection.MediaProjectionManager;
+import android.os.Build;
+import android.util.Log;
+import android.view.View;
+
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
import com.ttstd.remoteservice.R;
import com.ttstd.remoteservice.base.mvvm.BaseMvvmActivity;
import com.ttstd.remoteservice.databinding.ActivityMainBinding;
+import com.ttstd.remoteservice.service.ControlService;
+import com.ttstd.remoteservice.service.ScreenCaptureService;
public class MainActivity extends BaseMvvmActivity {
+ private static final String TAG ="MainActivity";
+
+ private static final int REQUEST_CODE_SCREEN_CAPTURE = 7897;
+ private MediaProjectionManager mMediaProjectionManager;
@Override
@@ -27,7 +44,8 @@ public class MainActivity extends BaseMvvmActivity= Build.VERSION_CODES.O) {
+ startForegroundService(screenServiceIntent);
+ }else {
+ startService(screenServiceIntent);
+ }
+
+ // 启动指令接收服务
+ Intent controlServiceIntent = new Intent(this, ControlService.class);
+ startService(controlServiceIntent);
+ } else {
+ Log.e(TAG, "屏幕采集权限申请失败");
+ }
+ }
public class BtnClick {
-
+ public void requestPermission(View view){
+ // 适配Android 13+ 通知权限
+// if (Build.VERSION.SDK_INT >= 33) {
+// if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
+// ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.POST_NOTIFICATIONS}, 1002);
+// }
+// }
+ // 申请屏幕采集权限
+ Intent captureIntent = mMediaProjectionManager.createScreenCaptureIntent();
+ startActivityForResult(captureIntent, REQUEST_CODE_SCREEN_CAPTURE);
+ }
}
diff --git a/app/src/main/java/com/ttstd/remoteservice/service/ScreenCaptureService.java b/app/src/main/java/com/ttstd/remoteservice/service/ScreenCaptureService.java
index 4da7d93..f0e1a6b 100644
--- a/app/src/main/java/com/ttstd/remoteservice/service/ScreenCaptureService.java
+++ b/app/src/main/java/com/ttstd/remoteservice/service/ScreenCaptureService.java
@@ -1,12 +1,86 @@
package com.ttstd.remoteservice.service;
+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.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.ImageFormat;
+import android.graphics.Matrix;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.YuvImage;
+import android.hardware.display.VirtualDisplay;
+import android.media.Image;
+import android.media.ImageReader;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
+import android.media.projection.MediaProjection;
+import android.media.projection.MediaProjectionManager;
+import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Surface;
+import android.view.WindowManager;
import androidx.annotation.Nullable;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+
public class ScreenCaptureService extends Service {
+ private static final String TAG = "ScreenCaptureService";
+
+ private static final int NOTIFICATION_ID = 7897; // 前台服务通知ID
+ private static final String CHANNEL_ID = "SCREEN_CAPTURE_CHANNEL"; // 通知渠道ID
+ private static final String CHANNEL_NAME = "屏幕采集服务"; // 通知渠道名称
+
+
+ // 编码参数配置
+ private static final String MIME_TYPE = "video/avc"; // H.264编码
+
+ private static final int BIT_RATE = 2 * 1024 * 1024; // 码率2Mbps
+
+ private static final int FRAME_RATE = 15; // 帧率15fps
+
+ private static final int I_FRAME_INTERVAL = 5; // 关键帧间隔5秒
+
+ private static final String CONTROL_HOST = "192.168.1.100"; // 控制端IP(需替换为实际IP)
+ private static final int CONTROL_PORT = 9999; // 控制端视频接收端口
+
+ private int mScreenWidth, mScreenHeight, mScreenDensity;
+
+ private MediaProjection mediaProjection;
+ private MediaCodec mediaCodec;
+ private Surface encodeSurface;
+ private VirtualDisplay virtualDisplay;
+ private Socket videoSocket;
+ private OutputStream outputStream;
+
+ private boolean isEncoding = false;
+
+ // 采集参数
+ private static final int IMAGE_FORMAT = ImageFormat.YUV_420_888; // 兼容大部分设备的格式
+
+ private ImageReader imageReader;
+ private Handler captureHandler; // 帧回调处理线程
+ private boolean isCapturing = false;
+ private VirtualDisplay picVirtualDisplay;
+
+ // 用于存储提取的单帧Bitmap(可根据需求改为回调/文件存储)
+ private Bitmap currentFrameBitmap;
+
+
@Nullable
@Override
public IBinder onBind(Intent intent) {
@@ -16,16 +90,450 @@ public class ScreenCaptureService extends Service {
@Override
public void onCreate() {
super.onCreate();
+ WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+ DisplayMetrics metrics = new DisplayMetrics();
+ windowManager.getDefaultDisplay().getRealMetrics(metrics); // 获取真实屏幕尺寸(包含状态栏等)
+ mScreenWidth = metrics.widthPixels;
+ mScreenHeight = metrics.heightPixels;
+ mScreenDensity = metrics.densityDpi;
+ Log.e(TAG, "onCreate: mScreenWidth = " + mScreenWidth);
+ Log.e(TAG, "onCreate: mScreenHeight = " + mScreenHeight);
+ Log.e(TAG, "onCreate: mScreenDensity = " + mScreenDensity);
+
+ Log.e(TAG, "onCreate: densityDpi = " + getResources().getDisplayMetrics().densityDpi);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- return super.onStartCommand(intent, flags, startId);
+ createForegroundNotification();
+
+ if (intent != null) {
+ int resultCode = intent.getIntExtra("RESULT_CODE", -1);
+ Intent data = intent.getParcelableExtra("DATA");
+
+ // 获取MediaProjection实例(屏幕采集核心)
+ MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
+ mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
+
+ if (mediaProjection != null) {
+ Log.d(TAG, "MediaProjection初始化成功,开始屏幕采集");
+ // 此处可扩展:添加VirtualDisplay + MediaCodec编码屏幕画面为H.264
+ // 并通过Socket将编码后的视频流发送到控制端
+ // 初始化编码器并开始采集
+// new Thread(this::initEncoderAndCapture).start();
+
+ // 初始化ImageReader并开始采集
+ initImageReaderAndCapture();
+
+ } else {
+ Log.e(TAG, "MediaProjection初始化失败");
+ stopSelf();
+ }
+ }
+ return START_STICKY;
+ }
+
+ /**
+ * 初始化MediaCodec编码器,并创建虚拟显示采集屏幕
+ */
+ private void initEncoderAndCapture() {
+ try {
+ // 1. 初始化MediaCodec编码器
+ MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mScreenWidth, mScreenHeight);
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
+ format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, I_FRAME_INTERVAL);
+ format.setInteger(MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
+ format.setInteger(MediaFormat.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.AVCLevel31);
+
+ mediaCodec = MediaCodec.createEncoderByType(MIME_TYPE);
+ mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+ encodeSurface = mediaCodec.createInputSurface(); // 获取编码输入Surface
+ mediaCodec.start();
+ isEncoding = true;
+ Log.d(TAG, "MediaCodec编码器初始化成功");
+
+ // 1. 创建ImageReader,用于读取屏幕帧
+ imageReader = ImageReader.newInstance(
+ mScreenWidth,
+ mScreenHeight,
+ IMAGE_FORMAT,
+ 2 // 缓冲区数量:2帧(避免帧丢失)
+ );
+
+ // 2. 创建虚拟显示,将屏幕画面投射到编码Surface
+ virtualDisplay = mediaProjection.createVirtualDisplay(
+ "ScreenCaptureDisplay",
+ mScreenWidth,
+ mScreenHeight,
+ mScreenDensity,
+ android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
+ encodeSurface,
+ null, // 显示回调(可选)
+ null // 回调处理线程(可选)
+ );
+ Log.d(TAG, "虚拟显示创建成功,开始屏幕采集");
+
+ // 3. 连接控制端并发送编码数据
+ connectToControlServer();
+ // 4. 循环读取编码后的数据并发送
+ readAndSendEncodedData();
+
+ } catch (Exception e) {
+ Log.e(TAG, "编码器初始化失败", e);
+ stopEncoding();
+ }
+ }
+
+ /**
+ * 连接控制端视频接收服务
+ */
+ private void connectToControlServer() {
+ try {
+ videoSocket = new Socket(CONTROL_HOST, CONTROL_PORT);
+ outputStream = videoSocket.getOutputStream();
+ Log.d(TAG, "已连接到控制端:" + CONTROL_HOST + ":" + CONTROL_PORT);
+ } catch (IOException e) {
+ Log.e(TAG, "连接控制端失败", e);
+ stopEncoding();
+ }
+ }
+
+ /**
+ * 循环读取编码后的H.264数据,并发送到控制端
+ */
+ private void readAndSendEncodedData() {
+ MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
+ while (isEncoding) {
+ // 获取编码后的数据包索引
+ int outputBufferId = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000); // 10秒超时
+ if (outputBufferId == MediaCodec.INFO_TRY_AGAIN_LATER) {
+ // 暂无数据,继续等待
+ continue;
+ } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ // 格式变更(如SPS/PPS数据),获取并发送
+ MediaFormat newFormat = mediaCodec.getOutputFormat();
+ Log.d(TAG, "编码器格式变更:" + newFormat);
+ sendSpsPps(newFormat);
+ } else if (outputBufferId >= 0) {
+ // 处理编码后的视频数据
+ ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferId);
+ if (outputBuffer != null && bufferInfo.size > 0) {
+ // 封装NALU(添加00 00 00 01起始码)
+ byte[] naluData = new byte[bufferInfo.size + 4];
+ naluData[0] = 0;
+ naluData[1] = 0;
+ naluData[2] = 0;
+ naluData[3] = 1;
+ outputBuffer.get(naluData, 4, bufferInfo.size);
+ outputBuffer.clear();
+
+ // 发送数据到控制端
+ if (outputStream != null) {
+ try {
+ outputStream.write(naluData);
+ outputStream.flush();
+ } catch (IOException e) {
+ Log.e(TAG, "发送视频数据失败", e);
+ break;
+ }
+ }
+ }
+ // 释放缓冲区
+ mediaCodec.releaseOutputBuffer(outputBufferId, false);
+
+ // 检查是否结束
+ if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ Log.d(TAG, "编码结束");
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * 发送SPS/PPS数据(H.264解码必需的配置数据)
+ */
+ private void sendSpsPps(MediaFormat format) {
+ try {
+ byte[] sps = format.getByteBuffer("csd-0").array();
+ byte[] pps = format.getByteBuffer("csd-1").array();
+
+ // 封装并发送SPS
+ byte[] spsData = new byte[sps.length + 4];
+ spsData[0] = 0;
+ spsData[1] = 0;
+ spsData[2] = 0;
+ spsData[3] = 1;
+ System.arraycopy(sps, 0, spsData, 4, sps.length);
+ outputStream.write(spsData);
+
+ // 封装并发送PPS
+ byte[] ppsData = new byte[pps.length + 4];
+ ppsData[0] = 0;
+ ppsData[1] = 0;
+ ppsData[2] = 0;
+ ppsData[3] = 1;
+ System.arraycopy(pps, 0, ppsData, 4, pps.length);
+ outputStream.write(ppsData);
+
+ Log.d(TAG, "已发送SPS/PPS配置数据");
+ } catch (Exception e) {
+ Log.e(TAG, "发送SPS/PPS失败", e);
+ }
+ }
+
+ /**
+ * 初始化ImageReader,创建虚拟显示采集屏幕帧
+ */
+ private void initImageReaderAndCapture() {
+ // 1. 创建ImageReader,用于读取屏幕帧
+ imageReader = ImageReader.newInstance(
+ mScreenWidth,
+ mScreenHeight,
+ PixelFormat.RGBA_8888,
+ 2 // 缓冲区数量:2帧(避免帧丢失)
+ );
+
+ // 2. 创建帧回调线程(避免阻塞主线程)
+ HandlerThread handlerThread = new HandlerThread("ScreenCaptureThread");
+ handlerThread.start();
+ captureHandler = new Handler(handlerThread.getLooper());
+
+ // 3. 设置帧可用回调
+ imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
+ @Override
+ public void onImageAvailable(ImageReader reader) {
+ Image image = reader.acquireLatestImage();
+ if (image != null) {
+ Bitmap bitmap = imageToBitmap2(image); // 将Image转换为Bitmap
+// saveBitmapToFile(bitmap); // 保存Bitmap
+ image.close(); // 重要:关闭Image释放资源
+ }
+ }
+ }, captureHandler);
+ isCapturing = true;
+
+ // 4. 创建虚拟显示,将屏幕画面投射到ImageReader的Surface
+ picVirtualDisplay = mediaProjection.createVirtualDisplay(
+ "ScreenCaptureDisplay",
+ mScreenWidth,
+ mScreenHeight,
+ mScreenDensity,
+ android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
+ imageReader.getSurface(),
+ null,
+ null
+ );
+ Log.d(TAG, "虚拟显示创建成功,开始屏幕帧采集");
+ }
+
+ /**
+ * 帧可用回调:每次屏幕刷新都会触发此方法
+ */
+ private void onImageAvailable(ImageReader reader) {
+ // 获取最新帧(注意:必须close(),否则缓冲区会耗尽)
+ try (Image image = reader.acquireLatestImage()) {
+ if (image == null) {
+ return;
+ }
+
+ // 提取当前帧并转换为Bitmap
+ currentFrameBitmap = imageToBitmap(image);
+ if (currentFrameBitmap != null) {
+ Log.d(TAG, "成功提取一帧,Bitmap尺寸:" + currentFrameBitmap.getWidth() + "x" + currentFrameBitmap.getHeight());
+
+ // ========== 此处可添加Bitmap的使用逻辑 ==========
+ // 示例1:保存为文件
+ // saveBitmapToFile(currentFrameBitmap, "/sdcard/screen_shot.png");
+ // 示例2:通过网络发送
+ // sendBitmapToServer(currentFrameBitmap);
+ // 示例3:仅提取一帧后停止采集
+ // stopCapture();
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "提取帧失败", e);
+ }
+ }
+
+ /**
+ * 将Image(YUV_420_888格式)转换为Bitmap
+ */
+ private Bitmap imageToBitmap(Image image) {
+ try {
+ // 获取Image的YUV数据
+ Image.Plane[] planes = image.getPlanes();
+ ByteBuffer yBuffer = planes[0].getBuffer();
+ ByteBuffer uBuffer = planes[1].getBuffer();
+ ByteBuffer vBuffer = planes[2].getBuffer();
+
+ int ySize = yBuffer.remaining();
+ int uSize = uBuffer.remaining();
+ int vSize = vBuffer.remaining();
+
+ // 将YUV数据合并为字节数组
+ byte[] yuvData = new byte[ySize + uSize + vSize];
+ yBuffer.get(yuvData, 0, ySize);
+ vBuffer.get(yuvData, ySize, vSize); // 注意:部分设备UV顺序是VU
+ uBuffer.get(yuvData, ySize + vSize, uSize);
+
+ // YUV转JPEG,再转Bitmap(兼容所有设备)
+ YuvImage yuvImage = new YuvImage(
+ yuvData,
+ ImageFormat.NV21, // 转换为NV21格式
+ image.getWidth(),
+ image.getHeight(),
+ new int[]{planes[0].getRowStride(), 0, 0} // 行步长
+ );
+
+ // 压缩为JPEG字节数组
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ yuvImage.compressToJpeg(new Rect(0, 0, image.getWidth(), image.getHeight()), 100, outputStream);
+ byte[] jpegData = outputStream.toByteArray();
+
+ // JPEG字节数组转Bitmap
+ Bitmap bitmap = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length);
+
+ // 修正旋转(部分设备采集的帧会旋转90度)
+ Matrix matrix = new Matrix();
+ matrix.postRotate(90); // 根据实际情况调整旋转角度(0/90/180/270)
+ return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
+
+ } catch (Exception e) {
+ Log.e(TAG, "YUV转Bitmap失败", e);
+ return null;
+ }
+ }
+
+ private Bitmap imageToBitmap2(Image image) {
+ Image.Plane[] planes = image.getPlanes();
+ ByteBuffer buffer = planes[0].getBuffer();
+ int pixelStride = planes[0].getPixelStride();
+ int rowStride = planes[0].getRowStride();
+ int rowPadding = rowStride - pixelStride * image.getWidth(); // 计算行填充
+
+ // 创建Bitmap,注意处理行跨度可能大于图像宽度的情况
+ Bitmap bitmap = Bitmap.createBitmap(
+ image.getWidth() + rowPadding / pixelStride,
+ image.getHeight(),
+ Bitmap.Config.ARGB_8888
+ );
+ bitmap.copyPixelsFromBuffer(buffer);
+
+ // 如果存在填充,则裁剪出原始图像区域
+ if (rowPadding > 0) {
+ bitmap = Bitmap.createBitmap(bitmap, 0, 0, image.getWidth(), image.getHeight());
+ }
+ return bitmap;
+ }
+
+// private void saveBitmapToFile(Bitmap bitmap) {
+// // 生成唯一的文件名
+// String fileName = "Screenshot_" + System.currentTimeMillis() + ".png";
+// // 保存到公共图片目录
+// File saveFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), fileName);
+//
+// try (FileOutputStream out = new FileOutputStream(saveFile)) {
+// bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); // PNG无损压缩
+// Toast.makeText(this, "截图已保存: " + saveFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
+// } catch (IOException e) {
+// e.printStackTrace();
+// }
+// }
+
+
+ /**
+ * 停止编码和采集
+ */
+ private void stopEncoding() {
+ isEncoding = false;
+
+ // 停止编码器
+ if (mediaCodec != null) {
+ try {
+ mediaCodec.stop();
+ mediaCodec.release();
+ } catch (Exception e) {
+ Log.e(TAG, "停止编码器失败", e);
+ }
+ mediaCodec = null;
+ }
+
+ // 释放虚拟显示
+ if (virtualDisplay != null) {
+ virtualDisplay.release();
+ virtualDisplay = null;
+ }
+
+ if (picVirtualDisplay != null) {
+ picVirtualDisplay.release();
+ picVirtualDisplay = null;
+ }
+
+ // 释放MediaProjection
+ if (mediaProjection != null) {
+ mediaProjection.stop();
+ mediaProjection = null;
+ }
+
+ // 关闭网络连接
+ try {
+ if (outputStream != null) outputStream.close();
+ if (videoSocket != null) videoSocket.close();
+ } catch (IOException e) {
+ Log.e(TAG, "关闭网络连接失败", e);
+ }
+
+ Log.d(TAG, "屏幕采集已停止");
+ }
+
+ /**
+ * 创建前台服务通知,并将Service设为前台服务(核心修复点)
+ */
+ private void createForegroundNotification() {
+ // 第一步:创建通知渠道(Android O及以上必需)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ NotificationChannel channel = new NotificationChannel(
+ CHANNEL_ID,
+ CHANNEL_NAME,
+ NotificationManager.IMPORTANCE_LOW // 低优先级,避免打扰用户
+ );
+ NotificationManager notificationManager = getSystemService(NotificationManager.class);
+ notificationManager.createNotificationChannel(channel);
+ }
+
+ // 第二步:构建基础通知
+ Notification.Builder builder = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+ ? new Notification.Builder(this, CHANNEL_ID)
+ : new Notification.Builder(this);
+
+ Notification notification = builder
+ .setContentTitle("远程控制服务")
+ .setContentText("屏幕采集服务正在运行")
+ .setSmallIcon(android.R.drawable.ic_media_play) // 替换为你的应用图标
+ .setOngoing(true) // 设为不可取消(前台服务特性)
+ .build();
+
+ // 第三步:启动前台服务(关键:指定MediaProjection类型)
+ if (Build.VERSION.SDK_INT >= 31) {
+ // Android 12+ 必须指定前台服务类型
+ startForeground(NOTIFICATION_ID, notification, android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION);
+ } else {
+ // 低版本直接启动
+ startForeground(NOTIFICATION_ID, notification);
+ }
+ Log.d(TAG, "前台服务启动成功");
}
@Override
public void onDestroy() {
super.onDestroy();
+ stopForeground(STOP_FOREGROUND_REMOVE);
+ if (mediaProjection != null) {
+ mediaProjection.stop();
+ Log.d(TAG, "屏幕采集服务停止");
+ }
}
@Override
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 9cc1e6a..f1467b0 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -5,6 +5,7 @@
tools:context=".activity.main.MainActivity">
+
@@ -14,16 +15,17 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
-
-
-
+
\ No newline at end of file