| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- package org.las2mile.scrcpy;
- import android.app.Service;
- import android.content.Intent;
- import android.os.Binder;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.Message;
- import android.os.Messenger;
- import android.os.RemoteException;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.view.Surface;
- import org.las2mile.scrcpy.decoder.VideoDecoder;
- import org.las2mile.scrcpy.model.ByteUtils;
- import org.las2mile.scrcpy.model.MediaPacket;
- import org.las2mile.scrcpy.model.VideoPacket;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.EOFException;
- import java.io.IOException;
- import java.net.Socket;
- import java.util.concurrent.atomic.AtomicBoolean;
- import org.las2mile.okio.OkIoClient;
- import org.las2mile.okio.message.BaseMsg;
- import org.las2mile.okio.OkIoClient.OnOkIoMsgListener;
- public class Scrcpy extends Service {
- private String serverAdr;
- private Surface surface;
- private int screenWidth;
- private int screenHeight;
- private byte[] event = null;
- private VideoDecoder videoDecoder;
- private AtomicBoolean updateAvailable = new AtomicBoolean(false);
- private IBinder mBinder = new MyServiceBinder();
- private boolean first_time = true;
- private AtomicBoolean LetServceRunning = new AtomicBoolean(true);
- private ServiceCallbacks serviceCallbacks;
- private int[] remote_dev_resolution = new int[2];
- private boolean socket_status = false;
- OkIoClient mOkIoClient;
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
- public void setServiceCallbacks(ServiceCallbacks callbacks) {
- serviceCallbacks = callbacks;
- }
- public void setParms(Surface NewSurface, int NewWidth, int NewHeight) {
- this.screenWidth = NewWidth;
- this.screenHeight = NewHeight;
- this.surface = NewSurface;
- videoDecoder.start();
- updateAvailable.set(true);
- }
- public void start(Surface surface, String serverAdr, int screenHeight, int screenWidth) {
- this.videoDecoder = new VideoDecoder();
- videoDecoder.start();
- this.serverAdr = serverAdr;
- this.screenHeight = screenHeight;
- this.screenWidth = screenWidth;
- this.surface = surface;
- Thread thread = new Thread(new Runnable() {
- @Override
- public void run() {
- startConnection();
- }
- });
- thread.start();
- //手机-设备交互客户端
- mOkIoClient = new OkIoClient(serverAdr);
- mOkIoClient.setOnOkIoMsgListener(new OnOkIoMsgListener() {
- @Override
- public void onOkIoMsg(BaseMsg msg) {
- if (serviceCallbacks != null) {
- serviceCallbacks.onOkIoMsg(msg);
- }
- }
- });
- mOkIoClient.start();
- }
- public void downloadLog(){
- if(mOkIoClient != null){
- mOkIoClient.requestLogFile();
- }
- }
- public void pause() {
- videoDecoder.stop();
- }
- public void resume() {
- videoDecoder.start();
- updateAvailable.set(true);
- }
- public void StopService() {
- LetServceRunning.set(false);
- stopSelf();
- }
- public boolean touchevent(MotionEvent touch_event, int displayW, int displayH) {
- int[] buf = new int[]{touch_event.getAction(), touch_event.getButtonState(), (int) touch_event.getX() * screenWidth / displayW, (int) touch_event.getY() * screenHeight / displayH};
- final byte[] array = new byte[buf.length * 4]; // https://stackoverflow.com/questions/2183240/java-integer-to-byte-array
- for (int j = 0; j < buf.length; j++) {
- final int c = buf[j];
- array[j * 4] = (byte) ((c & 0xFF000000) >> 24);
- array[j * 4 + 1] = (byte) ((c & 0xFF0000) >> 16);
- array[j * 4 + 2] = (byte) ((c & 0xFF00) >> 8);
- array[j * 4 + 3] = (byte) (c & 0xFF);
- }
- event = array;
- return true;
- }
- public int[] get_remote_device_resolution(){
- return remote_dev_resolution;
- }
- public boolean check_socket_connection(){
- return socket_status;
- }
- public void sendKeyevent(int keycode) {
- int[] buf = new int[]{keycode};
- final byte[] array = new byte[buf.length * 4]; // https://stackoverflow.com/questions/2183240/java-integer-to-byte-array
- for (int j = 0; j < buf.length; j++) {
- final int c = buf[j];
- array[j * 4] = (byte) ((c & 0xFF000000) >> 24);
- array[j * 4 + 1] = (byte) ((c & 0xFF0000) >> 16);
- array[j * 4 + 2] = (byte) ((c & 0xFF00) >> 8);
- array[j * 4 + 3] = (byte) (c & 0xFF);
- }
- event = array;
- }
- private void startConnection() {
- videoDecoder = new VideoDecoder();
- videoDecoder.start();
- DataInputStream dataInputStream;
- DataOutputStream dataOutputStream;
- Socket socket = null;
- VideoPacket.StreamSettings streamSettings = null;
- int attempts = 50;
- while (attempts != 0) {
- try {
- Log.e("Scrcpy",attempts+" Connecting to screen push server port 7007:" + serverAdr);
- socket = new Socket(serverAdr, 7007);
- dataInputStream = new DataInputStream(socket.getInputStream());
- dataOutputStream = new DataOutputStream(socket.getOutputStream());
- byte[] packetSize;
- attempts = 0;
- byte[] buf = new byte[16];
- dataInputStream.read(buf, 0,16);
- for(int i =0; i<remote_dev_resolution.length; i++) {
- remote_dev_resolution[i] = (((int) (buf[i * 4]) << 24) & 0xFF000000) |
- (((int) (buf[i * 4 + 1]) << 16) & 0xFF0000) |
- (((int) (buf[i * 4 + 2]) << 8) & 0xFF00) |
- ((int) (buf[i * 4 + 3]) & 0xFF);
- }
- if (remote_dev_resolution[0] > remote_dev_resolution[1]){first_time = false;
- int i = remote_dev_resolution[0];
- remote_dev_resolution[0] = remote_dev_resolution[1];
- remote_dev_resolution[1] = i;
- }
- socket_status = true;
- // Log.e("Remote device res", String.valueOf(remote_dev_resolution[0]+" x "+remote_dev_resolution[1]));
- while (LetServceRunning.get()) {
- try {
- if (event != null) {
- dataOutputStream.write(event, 0, event.length);
- event = null;
- }
- if (dataInputStream.available() > 0) {
- packetSize = new byte[4];
- dataInputStream.readFully(packetSize, 0, 4);
- int size = ByteUtils.bytesToInt(packetSize);
- byte[] packet = new byte[size];
- dataInputStream.readFully(packet, 0, size);
- VideoPacket videoPacket = VideoPacket.fromArray(packet);
- if (videoPacket.type == MediaPacket.Type.VIDEO) {
- byte[] data = videoPacket.data;
- if (videoPacket.flag == VideoPacket.Flag.CONFIG || updateAvailable.get()) {
- if (!updateAvailable.get()) {
- streamSettings = VideoPacket.getStreamSettings(data);
- if (!first_time) {
- if (serviceCallbacks != null) {
- serviceCallbacks.loadNewRotation();
- }
- while (!updateAvailable.get()) {
- // Waiting for new surface
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- updateAvailable.set(false);
- // first_time = false;
- videoDecoder.configure(surface, screenWidth, screenHeight, streamSettings.sps, streamSettings.pps);
- } else if (videoPacket.flag == VideoPacket.Flag.END) {
- // need close stream
- } else {
- videoDecoder.decodeSample(data, 0, data.length, 0, videoPacket.flag.getFlag());
- }
- first_time = false;
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- } catch (IOException e) {
- // e.printStackTrace();
- attempts = attempts - 1;
- if (attempts == 0){
- socket_status = false;
- return;
- }
- try {
- Thread.sleep(300);//连接比较耗时,适当延长重连时间。连接服务器7007端口,此端口用于推屏
- } catch (InterruptedException ignore) {
- }
- // Log.e("Scrcpy", e.getMessage());
- } finally {
- if (socket != null) {
- try {
- socket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
- public interface ServiceCallbacks {
- void loadNewRotation();
- void onOkIoMsg(BaseMsg msg);
- }
- public class MyServiceBinder extends Binder {
- public Scrcpy getService() {
- return Scrcpy.this;
- }
- }
-
- }
|