Android手机监控应用(二)
16lz
2021-01-26
// http service 服务类package com.example.chinaso.appcrawlermaster;import android.app.Service;import android.content.Intent;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.IBinder;import android.os.Binder;import android.util.Base64;import android.view.Surface;import android.widget.Toast;import android.util.DisplayMetrics;import java.io.*;import java.net.Inet4Address;import java.net.InetAddress;import java.net.NetworkInterface;import java.net.SocketException;import java.nio.ByteBuffer;import java.util.Enumeration;import java.util.Vector;public class HttpService extends Service { // Http服务器 private HttpServer http_server; // 本机ip private String local_ip; // 当前服务是否在运行 private boolean is_running = false; // 命令接收队列 private Vector cmd_queue = new Vector<>(); // 截屏有关 private static final int REQUEST_MEDIA_PROJECTION = 1; private int mScreenDensity; private int screen_width; private int screen_height; private int mResultCode; private Intent screen_capture_intent = null; private Surface mSurface; private MediaProjectionManager mMediaProjectionManager = null; private MediaProjection mMediaProjection; private VirtualDisplay mVirtualDisplay; private ImageReader image_reader; private static final int MAX_IMAGE_NUM = 15; private boolean has_inited = false; public HttpService() { super(); } // 命令调度线程 public class CommandScheduler extends Thread { private int sleep_time; public CommandScheduler(int sleep_time) { this.sleep_time = sleep_time; } @Override public void run() { try { while (true) { Command cmd = popCommand(); if (cmd != null) { String tag = cmd.getTag(); switch (tag) { case "screen": //System.out.println("receive screen capture cmd"); capture_thread.addCaptureCommandToQueue(cmd); break; case "swipe": System.out.println("正在分发滑动命令"); callback.dispatchCommand(cmd); break; case "jquery.js": String js_data = loadFile("jquery.js"); cmd.setResponse(js_data); break; case "remote.html": String html_data = loadFile("remote.html"); cmd.setResponse(html_data); break; } } Thread.sleep(sleep_time); } } catch (InterruptedException e) { e.printStackTrace(); } } } CommandScheduler scheduler = null; // 命令执行线程基类 class CommandThread extends Thread { protected boolean is_running = true; protected int sleep_time; protected Command command = null; public CommandThread(int sleep_time) { this.sleep_time = sleep_time; } @Override public void run() { try { while (is_running) { execute(); Thread.sleep(sleep_time); } } catch (InterruptedException e) { e.printStackTrace(); } } protected void execute() { System.out.println("start to execute screen capture cmd"); } public void setCommand(Command cmd) { this.command = cmd; } protected void stopRun () { this.is_running = false; } } // 截图线程 private Vector capture_cmd_queue = new Vector<>(); class ScreenCaptureThread extends CommandThread { private String data = null; private long last_cmd_arrive_time = 0; public ScreenCaptureThread(int sleep_time) { super(sleep_time); } @Override public void execute() { //super.execute(); if (mMediaProjection != null) { //System.out.println("媒体工程对象不为空!"); if (capture_cmd_queue.size() == 0) { //System.out.println("No capture command now"); return; } Command cmd = capture_cmd_queue.firstElement(); if (cmd == null) { //System.out.println("No capture command now"); return; } //System.out.println("start to capture screen..."); //setUpVirtualDisplay(); // 获取实时屏幕图片数据 byte[] bytes = getLastestImageContent(); if (bytes == null) { return; } System.out.println("调度线程命令总数: " + cmd_queue.size()); System.out.println("截图线程命令总数: " + capture_cmd_queue.size()); //cmd.setResponse(data); ((ScreenCommand) cmd).setBytes(bytes); //capture_cmd_queue.remove(cmd); System.out.println("调度线程命令总数: " + cmd_queue.size()); System.out.println("截图线程命令总数: " + capture_cmd_queue.size()); } else { //System.out.println("媒体工程对象为空!"); //Toast.makeText(HttpService.this, "虚拟显示对象为空!", Toast.LENGTH_SHORT).show(); } } public void addCaptureCommandToQueue(Command cmd) { capture_cmd_queue.add((ScreenCommand)cmd); //System.out.println("向截图线程队列加入一条命令: " + capture_cmd_queue.size()); } } ScreenCaptureThread capture_thread = null; //创建服务 @Override public void onCreate() { Toast.makeText(HttpService.this, "Http监听服务已创建", Toast.LENGTH_SHORT).show(); super.onCreate(); if (is_running == false) { local_ip = getIP(); http_server = new HttpServer(local_ip, 8080); http_server.registerService(HttpService.this); } else { Toast.makeText(HttpService.this, "Http服务已在8080端口监听", Toast.LENGTH_SHORT).show(); } try { if (is_running == false) { // 启动调度线程 scheduler = new CommandScheduler(10); scheduler.start(); // 启动截图线程 startCommandThread(); // 启动http服务 http_server.start(); is_running = true; Toast.makeText(HttpService.this, "Http监听服务开始执行", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(HttpService.this, "Http监听服务运行中", Toast.LENGTH_SHORT).show(); } } catch (IOException e) { Toast.makeText(HttpService.this, "出现IO异常", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (has_inited == false && intent != null) { mScreenDensity = intent.getIntExtra("screen_density", 0); screen_width = intent.getIntExtra("screen_width", 0); screen_height = intent.getIntExtra("screen_height", 0); mResultCode = intent.getIntExtra("result_code", 0); System.out.println("取得屏幕宽高: " + screen_width + ", " + screen_height); has_inited = true; } return super.onStartCommand(intent, flags, startId); } public void addCommand(Command cmd) { cmd_queue.add(cmd); } public Command popCommand() { if (cmd_queue.size() > 0) { return cmd_queue.remove(0); } return null; } public boolean removeCommand(Command cmd) { if (capture_cmd_queue.size() > 0) { return capture_cmd_queue.remove(cmd); } return false; } // 获取jquery.js或remote.html的内容 public String loadFile(String file_name) { InputStream in; if (file_name.equals("jquery.js")) { in = getResources().openRawResource(R.raw.jquery); } else { in = getResources().openRawResource(R.raw.remote); } InputStreamReader inputStreamReader = null; try { inputStreamReader = new InputStreamReader(in, "UTF-8"); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } BufferedReader reader = new BufferedReader(inputStreamReader); StringBuffer sb = new StringBuffer(); String line; try { while ((line = reader.readLine()) != null) { sb.append(line); sb.append("\n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { inputStreamReader.close(); } catch(IOException e) { e.printStackTrace(); } } String s = sb.toString(); if (file_name.equals("remote.html")) { String res = s.replaceAll("\\{\\{screen_uri\\}\\}", "http://" + local_ip + ":8080"); return res; } else { return s; } } //销毁服务时调用 @Override public void onDestroy() { if (is_running) { is_running = false; stopCommandThread(); stopVirtualDisplay(); tearDownMediaProjection(); http_server.stop(); Toast.makeText(HttpService.this, "Http监听服务已销毁", Toast.LENGTH_LONG).show(); } super.onDestroy(); } // 获取虚拟显示对象 private void setUpVirtualDisplay() { mVirtualDisplay = mMediaProjection.createVirtualDisplay("ScreenCapture", screen_width, screen_height, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mSurface, null, null); try { System.out.println("睡眠开始"); Thread.sleep(5000); System.out.println("睡眠结束"); } catch (InterruptedException e) { e.printStackTrace(); } } // 从ImageReader中读取最新截屏的字符串数据 public byte[] getLastestImageContent() { System.out.println("开始获取最近的截图"); Image image = image_reader.acquireLatestImage(); if (image == null) { return null; } 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; int width_value = width + rowPadding / pixelStride; System.out.println("截图宽高: " + width_value + ", " + height); bitmap = Bitmap.createBitmap(width_value, height, Bitmap.Config.ARGB_8888); bitmap.copyPixelsFromBuffer(buffer); /* // 方案一 ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos); image.close(); //byte[] arr = baos.toByteArray(); String image_buffer = null; try { image_buffer = baos.toString("utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } //image_buffer = new String(arr); System.out.println("截图大小: " + image_buffer.length()); return image_buffer; */ // 方案二 ByteArrayOutputStream bStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 20, bStream); image.close(); byte[] bytes = null; try { bStream.flush(); bStream.close(); bytes = bStream.toByteArray(); } catch (IOException e) { e.printStackTrace(); } System.out.println("结束获取最近的截图"); return bytes; } // 长时间没有命令请求时释放VirtualDisplay private void stopVirtualDisplay() { if (mVirtualDisplay == null) { return; } mVirtualDisplay.release(); mVirtualDisplay = null; } // 释放MediaProjection对象 public void tearDownMediaProjection() { if (mMediaProjection != null) { Toast.makeText(HttpService.this, "媒体工程对象被销毁!", Toast.LENGTH_LONG).show(); System.out.println("媒体工程对象被销毁!"); mMediaProjection.stop(); mMediaProjection = null; } } // 启动命令执行线程 public void startCommandThread() { capture_thread = new ScreenCaptureThread(50); capture_thread.start(); } // 停止命令执行线程 public void stopCommandThread() { capture_thread.is_running = false; } @Override public IBinder onBind(Intent intent) { System.out.println("--onBind()--"); return new ServiceBinder(); } @Override public boolean onUnbind(Intent intent) { System.out.println("--onUnbind()--"); return super.onUnbind(intent); } public class ServiceBinder extends Binder { HttpService getService() { return HttpService.this; } // 设置ScreenCaptureIntent public void setScreenCaptureIntent(Intent intent) { screen_capture_intent = intent; image_reader = ImageReader.newInstance(screen_width, screen_height, PixelFormat.RGBA_8888, MAX_IMAGE_NUM); mSurface = image_reader.getSurface(); mMediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE); mMediaProjection = mMediaProjectionManager.getMediaProjection(mResultCode, screen_capture_intent); if (mMediaProjection == null) { System.out.println("媒体工程对象初始化失败!"); } else { System.out.println("媒体工程对象初始化成功!"); setUpVirtualDisplay(); if (mVirtualDisplay != null) { System.out.println("虚拟显示对象初始化成功!"); } else { System.out.println("虚拟显示对象初始化失败!"); } } } } Callback callback = null; public Callback getCallback() { return callback; } public void setCallback(Callback callback) { this.callback = callback; } // 通过回调机制,将Service内部的变化传递到外部 public interface Callback { void dispatchCommand(Command cmd); } // 获取本机IP地址 public String getIP(){ try { for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { InetAddress inetAddress = enumIpAddr.nextElement(); if (!inetAddress.isLoopbackAddress() && (inetAddress instanceof Inet4Address)) { return inetAddress.getHostAddress().toString(); } } } } catch (SocketException ex){ ex.printStackTrace(); } return null; }}
// 无障碍 service 服务类package com.example.chinaso.appcrawlermaster;import android.accessibilityservice.AccessibilityService;import android.accessibilityservice.GestureDescription;import android.content.Context;import android.util.DisplayMetrics;import android.view.WindowManager;import android.view.accessibility.AccessibilityEvent;import android.view.accessibility.AccessibilityNodeInfo;import android.widget.Toast;import android.graphics.Path;public class BarrierFreeService extends AccessibilityService { private static SwipeCommand current_cmd = null; @Override public void onAccessibilityEvent(AccessibilityEvent event) { int eventType = event.getEventType(); switch (eventType) { case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: if (event.getPackageName().toString().equals("com.example.chinaso.appcrawlermaster") == false || event.getClassName().toString().equals("android.app.Notification") == false) { return; } System.out.println("类名: " + event.getClassName()); System.out.println("包名: " + event.getPackageName()); if (current_cmd != null) { System.out.println("无障碍服务正在执行滑动命令: " + current_cmd.getDuration()); int x1 = current_cmd.getUpLeftX(); int y1 = current_cmd.getUpLeftY(); int x2 = current_cmd.getDownRightX(); int y2 = current_cmd.getDownRightY(); int duration = current_cmd.getDuration(); current_cmd = null; swipe(x1, y1, x2, y2, duration); } } } @Override public void onInterrupt() { Toast.makeText(BarrierFreeService.this, "无障碍服务关闭", Toast.LENGTH_LONG).show(); } @Override protected void onServiceConnected() { Toast.makeText(BarrierFreeService.this, "无障碍服务开启", Toast.LENGTH_LONG).show(); } // 重置当前命令 public static void setCurrentCommand(SwipeCommand cmd) { current_cmd = cmd; } // 滑动 public void swipe(int x1, int y1, int x2, int y2, int delay) { Path path = new Path(); path.moveTo(scaleX(x1), scaleY(y1)); path.lineTo(scaleX(x1), scaleY(y1)); path.lineTo(scaleX(x2), scaleY(y2)); GestureDescription.StrokeDescription stroke_desc = new GestureDescription.StrokeDescription(path, 0, delay); GestureDescription.Builder builder = new GestureDescription.Builder(); builder.addStroke(stroke_desc); GestureDescription gesture_desc = builder.build(); boolean res = dispatchGesture(gesture_desc, null, null); if (res) { System.out.println("姿势分发成功!"); } else { System.out.println("姿势分发失败!"); } } public int scaleX(int x) { return x / 2; } public int scaleY(int y) { return y / 2; }}
// 应用配置<?xml version="1.0" encoding="utf-8"?>
// 布局文件<?xml version="1.0" encoding="utf-8"?>
更多相关文章
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
- tcping测试服务器TCP端口
- Application 判断 是否在主进程、主线程
- Android在SurfaceView做动画一般方法
- android Bound Service使用:使用Message类绑定服务
- Android(安卓)Service学习之IntentService 深入分析
- Android-AsyncTask源码学习
- ApiDemo/FragmentRetainInstance 解析
- android 38 Abdroid客户端和服务端交互