// 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"?>    

 

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. tcping测试服务器TCP端口
  3. Application 判断 是否在主进程、主线程
  4. Android在SurfaceView做动画一般方法
  5. android Bound Service使用:使用Message类绑定服务
  6. Android(安卓)Service学习之IntentService 深入分析
  7. Android-AsyncTask源码学习
  8. ApiDemo/FragmentRetainInstance 解析
  9. android 38 Abdroid客户端和服务端交互

随机推荐

  1. android Looper Message 代码分析
  2. Android学习笔记:布局
  3. Android中Activity常用功能设置小结(包括
  4. Android(安卓)Studio开发之JNI ---- 加载
  5. android webview中使用Java调用JavaScrip
  6. 网络数据请求实践一:android-async-http实
  7. Pro Android学习笔记(一二四):Telephony API
  8. Android(安卓)ListView中动态显示和隐藏H
  9. Mac系统下对Android(安卓)apk进行反编译
  10. android中隐藏ListView滚动条