Android手机监控应用(二)

// 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;
    }

}
// 应用配置




    
    
    
    

    
        
            
                
                
            
        

        
            
                
                

                
            
        

        
        
            
                
            
            
        

    

// 布局文件




    

 

你可能感兴趣的:(java,android,多线程)