MainActivity.java 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. package org.las2mile.scrcpy;
  2. import android.annotation.SuppressLint;
  3. import android.app.Activity;
  4. import android.content.ComponentName;
  5. import android.content.Context;
  6. import android.content.Intent;
  7. import android.content.ServiceConnection;
  8. import android.content.pm.ActivityInfo;
  9. import android.content.res.AssetManager;
  10. import android.hardware.Sensor;
  11. import android.hardware.SensorEvent;
  12. import android.hardware.SensorEventListener;
  13. import android.hardware.SensorManager;
  14. import android.os.Bundle;
  15. import android.os.IBinder;
  16. import android.os.SystemClock;
  17. import android.util.Base64;
  18. import android.util.DisplayMetrics;
  19. import android.util.Log;
  20. import android.view.Display;
  21. import android.view.Surface;
  22. import android.view.SurfaceView;
  23. import android.view.View;
  24. import android.view.ViewConfiguration;
  25. import android.widget.AdapterView;
  26. import android.widget.ArrayAdapter;
  27. import android.widget.Button;
  28. import android.widget.EditText;
  29. import android.widget.LinearLayout;
  30. import android.widget.Spinner;
  31. import android.widget.Switch;
  32. import android.widget.Toast;
  33. import java.io.IOException;
  34. import java.io.InputStream;
  35. import java.net.Inet4Address;
  36. import java.net.Inet6Address;
  37. import java.net.InetAddress;
  38. import java.net.NetworkInterface;
  39. import java.net.SocketException;
  40. import java.util.Enumeration;
  41. import android.app.ProgressDialog;
  42. import android.os.Handler;
  43. import android.os.Message;
  44. import org.las2mile.okio.message.BaseMsg;
  45. import org.las2mile.okio.message.resp.HartBeatMsgResp;
  46. import org.las2mile.okio.message.resp.LogFileEndMsgResp;
  47. import org.las2mile.okio.message.resp.LogFileMsgResp;
  48. import android.widget.TextView;
  49. import java.util.Set;
  50. import com.tbruyelle.rxpermissions3.RxPermissions;
  51. import androidx.fragment.app.FragmentActivity;
  52. import android.Manifest;
  53. import android.app.AlertDialog;
  54. import android.content.DialogInterface;
  55. import android.net.Uri;
  56. import android.provider.Settings;
  57. import android.graphics.Color;
  58. import org.las2mile.okio.utils.ZipUtils;
  59. public class MainActivity extends FragmentActivity implements Scrcpy.ServiceCallbacks, SensorEventListener {
  60. private static final String PREFERENCE_KEY = "default";
  61. private static final String PREFERENCE_SPINNER_RESOLUTION = "spinner_resolution";
  62. private static final String PREFERENCE_SPINNER_BITRATE = "spinner_bitrate";
  63. private static int screenWidth;
  64. private static int screenHeight;
  65. private static boolean landscape = false;
  66. private static boolean first_time = true;
  67. private static boolean result_of_Rotation = false;
  68. private static boolean serviceBound = false;
  69. private static boolean nav = false;
  70. SensorManager sensorManager;
  71. private SendCommands sendCommands;
  72. private int videoBitrate;
  73. private String local_ip;
  74. private Context context;
  75. private String serverAdr = null;
  76. private String serverPort = null;
  77. private SurfaceView surfaceView;
  78. private Surface surface;
  79. private Scrcpy scrcpy;
  80. private long timestamp = 0;
  81. private byte[] fileBase64;
  82. private static float remote_device_width;
  83. private static float remote_device_height;
  84. private LinearLayout linearLayout;
  85. private static boolean no_control = false;
  86. private RxPermissions rxPermissions;
  87. ProgressDialog mainProgressDialog = null;
  88. static final int ADB_CONNECT_START = 1;
  89. static final int ADB_CONNECT_REAL_START = 2;
  90. static final int ADB_CONNECT_SUC = 3;
  91. static final int ADB_CONNECT_FAIL = 4;
  92. static final int ADB_CONNECT_FAIL_HIDE = 5;
  93. static final int SERVER_ENV_PREPARED = 6;
  94. static final int GOT_REMOTE_VERSION = 7;
  95. static final int GOT_REMOTE_LOG_PROCEDURE = 8;
  96. static final int GOT_REMOTE_LOG_PROCEDURE_END = 9;
  97. static final int GOT_REMOTE_LOG_PROCEDURE_START = 10;
  98. Handler mainHandler = new Handler(new Handler.Callback() {
  99. @Override
  100. public boolean handleMessage(Message message) {
  101. int what = message.what;
  102. Log.e("scrcpy",mainHandler+" Asset ADB_CONNECT_SUC "+what);
  103. if(what == ADB_CONNECT_START){
  104. showProgress();
  105. mainHandler.sendEmptyMessageDelayed(ADB_CONNECT_REAL_START,500);
  106. } else if(what == ADB_CONNECT_REAL_START){
  107. sendCommands.SendAdbCommands(context, fileBase64, serverAdr, Integer.parseInt(serverPort), local_ip, videoBitrate, Math.max(screenHeight, screenWidth));
  108. } else if(what == ADB_CONNECT_SUC){
  109. setProgressMsg("与公司设备连接成功,正在初始化公司设备...");
  110. } else if(what == ADB_CONNECT_FAIL){
  111. setProgressMsg("与公司设备连接失败, 请确认IP与端口是否正确,再次点击重连。");
  112. mainHandler.sendEmptyMessageDelayed(ADB_CONNECT_FAIL_HIDE,2000);
  113. } else if(what == ADB_CONNECT_FAIL_HIDE){
  114. hideProgress();
  115. } else if(what == SERVER_ENV_PREPARED){
  116. setProgressMsg("公司设备初始化完成,即将投屏...");
  117. // hideProgress();
  118. start_screen_copy_magic();
  119. } else if(what == GOT_REMOTE_VERSION){
  120. hideProgress();
  121. HartBeatMsgResp hartBeatMsgResp = (HartBeatMsgResp)message.obj;
  122. Toast.makeText(context, hartBeatMsgResp.remoteInfo, Toast.LENGTH_SHORT).show();
  123. TextView tv_remote_device_info = findViewById(R.id.tv_remote_device_info);
  124. String remoteVer = String.format(getResources().getString(R.string.str_remote_dev_info),hartBeatMsgResp.remoteInfo);
  125. tv_remote_device_info.setText(remoteVer);
  126. } else if(what == GOT_REMOTE_LOG_PROCEDURE){
  127. String str_save_log_to_local = (String)message.obj;
  128. TextView tv_save_log_to_local = findViewById(R.id.tv_save_log_to_local);
  129. tv_save_log_to_local.setText(str_save_log_to_local);
  130. } else if (what == GOT_REMOTE_LOG_PROCEDURE_END){
  131. Boolean ok = (Boolean)message.obj;
  132. String str_remote_log_dlst = String.format(getResources().getString(R.string.str_remote_log_dlst),ok ? "成功":"失败");
  133. TextView tv_remote_log_dlst = findViewById(R.id.tv_remote_log_dlst);
  134. tv_remote_log_dlst.setTextColor(ok ? Color.BLUE : Color.RED);
  135. tv_remote_log_dlst.setText(str_remote_log_dlst);
  136. } else if (what == GOT_REMOTE_LOG_PROCEDURE_START){
  137. TextView tv_remote_log_dlst = findViewById(R.id.tv_remote_log_dlst);
  138. tv_remote_log_dlst.setTextColor(Color.GRAY);
  139. String str_remote_log_dlst = String.format(getResources().getString(R.string.str_remote_log_dlst),"下载中");
  140. tv_remote_log_dlst.setText(str_remote_log_dlst);
  141. }
  142. return false;
  143. }
  144. });
  145. private void initDownloadBtn(){
  146. final Button btn_dl_status = findViewById(R.id.btn_dl_status);
  147. btn_dl_status.setOnClickListener(v -> {
  148. Message msg = new Message();
  149. msg.what = GOT_REMOTE_LOG_PROCEDURE_START;
  150. mainHandler.sendMessage(msg);
  151. scrcpy.downloadLog();
  152. });
  153. final Button btn_dl_imgs = findViewById(R.id.btn_dl_imgs);
  154. btn_dl_imgs.setOnClickListener(v -> {
  155. Message msg = new Message();
  156. msg.what = GOT_REMOTE_LOG_PROCEDURE_START;
  157. mainHandler.sendMessage(msg);
  158. scrcpy.downloadPics();
  159. });
  160. }
  161. private final ServiceConnection serviceConnection = new ServiceConnection() {
  162. @Override
  163. public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
  164. scrcpy = ((Scrcpy.MyServiceBinder) iBinder).getService();
  165. scrcpy.setServiceCallbacks(MainActivity.this);
  166. serviceBound = true;
  167. if (first_time) {
  168. scrcpy.start(surface, serverAdr, screenHeight, screenWidth);
  169. int count = 100;
  170. while (count!=0 && !scrcpy.check_socket_connection()){
  171. count --;
  172. try {
  173. Thread.sleep(100);
  174. } catch (InterruptedException e) {
  175. e.printStackTrace();
  176. }
  177. }
  178. if (count == 0){
  179. if (serviceBound) {
  180. scrcpy.StopService();
  181. unbindService(serviceConnection);
  182. serviceBound = false;
  183. scrcpy_main();
  184. }
  185. Toast.makeText(context, "Connection Timed out", Toast.LENGTH_SHORT).show();
  186. }else{
  187. int[] rem_res = scrcpy.get_remote_device_resolution();
  188. remote_device_height = rem_res[1];
  189. remote_device_width = rem_res[0];
  190. first_time = false;
  191. }
  192. } else {
  193. scrcpy.setParms(surface, screenWidth, screenHeight);
  194. }
  195. set_display_nd_touch();
  196. }
  197. @Override
  198. public void onServiceDisconnected(ComponentName componentName) {
  199. serviceBound = false;
  200. }
  201. };
  202. public MainActivity() {
  203. }
  204. @SuppressLint("SourceLockedOrientationActivity")
  205. @Override
  206. protected void onCreate(Bundle savedInstanceState) {
  207. super.onCreate(savedInstanceState);
  208. rxPermissions = new RxPermissions(this);
  209. rxPermissions
  210. .request(Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.INTERNET,Manifest.permission.ACCESS_WIFI_STATE)
  211. .subscribe(granted -> {
  212. if (granted) {
  213. Log.e("scrcpy","所有权限都被授予");
  214. //performActionRequiringPermissions();
  215. } else {
  216. Log.e("scrcpy","至少一个权限被拒绝");
  217. showPermissionDeniedDialog();
  218. }
  219. });
  220. if (first_time) {
  221. scrcpy_main();
  222. } else {
  223. this.context = this;
  224. start_screen_copy_magic();
  225. }
  226. sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
  227. Sensor proximity;
  228. proximity = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
  229. sensorManager.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL);
  230. }
  231. @Override
  232. public void onOkIoMsg(BaseMsg baseMsg){
  233. if(baseMsg instanceof LogFileMsgResp){
  234. LogFileMsgResp logFileMsgResp = (LogFileMsgResp)baseMsg;
  235. String sizeFmt = ZipUtils.formetFileSize(logFileMsgResp.fileSize);
  236. String percentStr = logFileMsgResp.writenPercent+"%";//Math.round((logFileMsgResp.pktNo+1)*1.0f/logFileMsgResp.pktNums * 100)+"%";
  237. String str_save_log_to_local = String.format(getResources().getString(R.string.str_save_log_to_local),logFileMsgResp.zipPath,sizeFmt,percentStr);
  238. Message msg = new Message();
  239. msg.what = GOT_REMOTE_LOG_PROCEDURE;
  240. msg.obj = str_save_log_to_local;
  241. mainHandler.sendMessage(msg);
  242. } else if(baseMsg instanceof HartBeatMsgResp){
  243. Message msg = new Message();
  244. msg.what = GOT_REMOTE_VERSION;
  245. msg.obj = baseMsg;
  246. mainHandler.sendMessage(msg);
  247. } else if(baseMsg instanceof LogFileEndMsgResp){
  248. LogFileEndMsgResp logFileEndMsgResp = (LogFileEndMsgResp)baseMsg;
  249. Message msg = new Message();
  250. msg.what = GOT_REMOTE_LOG_PROCEDURE_END;
  251. msg.obj = logFileEndMsgResp.allDownloaded;
  252. mainHandler.sendMessage(msg);
  253. }
  254. }
  255. private void showProgress(){
  256. Log.e("scrcpy","Asset showProgress");
  257. mainProgressDialog = new ProgressDialog(context);
  258. mainProgressDialog.setTitle("提示");
  259. mainProgressDialog.setMessage("正在连接公司设备...");
  260. mainProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
  261. mainProgressDialog.setIndeterminate(true);
  262. mainProgressDialog.setCancelable(false);
  263. mainProgressDialog.setCanceledOnTouchOutside(false);
  264. mainProgressDialog.show();
  265. }
  266. private void setProgressMsg(String msg){
  267. mainProgressDialog.setMessage(msg);
  268. }
  269. private void hideProgress(){
  270. if(mainProgressDialog.isShowing()){
  271. mainProgressDialog.dismiss();
  272. }
  273. }
  274. @SuppressLint("SourceLockedOrientationActivity")
  275. public void scrcpy_main(){
  276. setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
  277. setContentView(R.layout.activity_main);
  278. final Button startButton = findViewById(R.id.button_start);
  279. AssetManager assetManager = getAssets();
  280. try {
  281. InputStream input_Stream = assetManager.open("scrcpy-server.jar");
  282. byte[] buffer = new byte[input_Stream.available()];
  283. input_Stream.read(buffer);
  284. fileBase64 = Base64.encode(buffer, 2);
  285. } catch (IOException e) {
  286. Log.e("Asset Manager", e.getMessage());
  287. }
  288. sendCommands = new SendCommands(mainHandler);
  289. startButton.setOnClickListener(v -> {
  290. local_ip = wifiIpAddress();
  291. getAttributes();
  292. if (!serverAdr.isEmpty()) {
  293. //原生逻辑
  294. // if (sendCommands.SendAdbCommands(context, fileBase64, serverAdr, Integer.parseInt(serverPort), local_ip, videoBitrate, Math.max(screenHeight, screenWidth)) == 0) {
  295. // start_screen_copy_magic();
  296. // } else {
  297. // Toast.makeText(context, "Network OR ADB connection failed", Toast.LENGTH_SHORT).show();
  298. // }
  299. //开始与adbd建立连接
  300. if(first_time){
  301. mainHandler.sendEmptyMessage(ADB_CONNECT_START);
  302. }
  303. } else {
  304. Toast.makeText(context, "Server Address Empty", Toast.LENGTH_SHORT).show();
  305. }
  306. });
  307. get_saved_preferences();
  308. }
  309. public void get_saved_preferences(){
  310. this.context = this;
  311. final EditText editTextServerHost = findViewById(R.id.editText_server_host);
  312. final Switch aSwitch0 = findViewById(R.id.switch0);
  313. final Switch aSwitch1 = findViewById(R.id.switch1);
  314. final EditText editTextServerPort = findViewById(R.id.editText_server_port);
  315. editTextServerHost.setText(context.getSharedPreferences(PREFERENCE_KEY, 0).getString("Server Address", ""));
  316. editTextServerPort.setText(context.getSharedPreferences(PREFERENCE_KEY, 0).getString("Server Port", ""));
  317. aSwitch0.setChecked(context.getSharedPreferences(PREFERENCE_KEY, 0).getBoolean("No Control", false));
  318. aSwitch1.setChecked(context.getSharedPreferences(PREFERENCE_KEY, 0).getBoolean("Nav Switch", false));
  319. setSpinner(R.array.options_resolution_keys, R.id.spinner_video_resolution, PREFERENCE_SPINNER_RESOLUTION);
  320. setSpinner(R.array.options_bitrate_keys, R.id.spinner_video_bitrate, PREFERENCE_SPINNER_BITRATE);
  321. if(aSwitch0.isChecked()){
  322. aSwitch1.setVisibility(View.GONE);
  323. }
  324. aSwitch0.setOnClickListener(v -> {
  325. if(aSwitch0.isChecked()){
  326. aSwitch1.setVisibility(View.GONE);
  327. }else{
  328. aSwitch1.setVisibility(View.VISIBLE);
  329. }
  330. });
  331. }
  332. @SuppressLint("ClickableViewAccessibility")
  333. public void set_display_nd_touch() {
  334. DisplayMetrics metrics = new DisplayMetrics();
  335. if (ViewConfiguration.get(context).hasPermanentMenuKey()) {
  336. getWindowManager().getDefaultDisplay().getMetrics(metrics);
  337. } else {
  338. final Display display = getWindowManager().getDefaultDisplay();
  339. display.getRealMetrics(metrics);
  340. }
  341. float this_dev_height = metrics.heightPixels;
  342. float this_dev_width = metrics.widthPixels;
  343. if (nav && !no_control){
  344. if (landscape){
  345. this_dev_width = this_dev_width - 96;
  346. }else { //100 is the height of nav bar but need multiples of 8.
  347. this_dev_height = this_dev_height - 96;
  348. }
  349. }
  350. float remote_device_aspect_ratio = remote_device_height/remote_device_width;
  351. //改变渲染的边距
  352. if (!landscape) { //Portrait
  353. float this_device_aspect_ratio = this_dev_height/this_dev_width;
  354. if (remote_device_aspect_ratio > this_device_aspect_ratio) {
  355. linearLayout.setPadding((int) (((remote_device_aspect_ratio - this_device_aspect_ratio)*this_dev_width)/2),0,(int) (((remote_device_aspect_ratio - this_device_aspect_ratio)*this_dev_width)/2),0);
  356. } else if (remote_device_aspect_ratio < this_device_aspect_ratio) {
  357. linearLayout.setPadding(0,(int) (((this_device_aspect_ratio - remote_device_aspect_ratio)*this_dev_width)),0,0);
  358. }
  359. }else{ //Landscape
  360. float this_device_aspect_ratio = this_dev_width/this_dev_height;
  361. if (remote_device_aspect_ratio > this_device_aspect_ratio) {
  362. linearLayout.setPadding(0,(int) (((remote_device_aspect_ratio - this_device_aspect_ratio)*this_dev_height)/2),0,(int) (((remote_device_aspect_ratio - this_device_aspect_ratio)*this_dev_height)/2));
  363. } else if (remote_device_aspect_ratio < this_device_aspect_ratio) {
  364. linearLayout.setPadding(((int) (((this_device_aspect_ratio - remote_device_aspect_ratio)*this_dev_height))/2),0,((int) (((this_device_aspect_ratio - remote_device_aspect_ratio)*this_dev_height))/2),0);
  365. }
  366. }
  367. if (!no_control) {
  368. surfaceView.setOnTouchListener((v, event) -> scrcpy.touchevent(event, surfaceView.getWidth(), surfaceView.getHeight()));
  369. }
  370. if (nav && !no_control) {
  371. final Button backButton = findViewById(R.id.back_button);
  372. final Button homeButton = findViewById(R.id.home_button);
  373. final Button appswitchButton = findViewById(R.id.appswitch_button);
  374. backButton.setOnClickListener(v -> scrcpy.sendKeyevent(4));
  375. homeButton.setOnClickListener(v -> scrcpy.sendKeyevent(3));
  376. appswitchButton.setOnClickListener(v -> scrcpy.sendKeyevent(187));
  377. }
  378. }
  379. private void setSpinner(final int textArrayOptionResId, final int textViewResId, final String preferenceId) {
  380. final Spinner spinner = findViewById(textViewResId);
  381. ArrayAdapter<CharSequence> arrayAdapter = ArrayAdapter.createFromResource(this, textArrayOptionResId, android.R.layout.simple_spinner_item);
  382. arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
  383. spinner.setAdapter(arrayAdapter);
  384. spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
  385. @Override
  386. public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
  387. context.getSharedPreferences(PREFERENCE_KEY, 0).edit().putInt(preferenceId, position).apply();
  388. }
  389. @Override
  390. public void onNothingSelected(AdapterView<?> parent) {
  391. context.getSharedPreferences(PREFERENCE_KEY, 0).edit().putInt(preferenceId, 0).apply();
  392. }
  393. });
  394. spinner.setSelection(context.getSharedPreferences(PREFERENCE_KEY, 0).getInt(preferenceId, 0));
  395. }
  396. private void getAttributes() {
  397. final EditText editTextServerHost = findViewById(R.id.editText_server_host);
  398. serverAdr = editTextServerHost.getText().toString();
  399. final EditText editTextServerPort = findViewById(R.id.editText_server_port);
  400. serverPort = editTextServerPort.getText().toString();
  401. context.getSharedPreferences(PREFERENCE_KEY, 0).edit().putString("Server Port", serverPort).apply();
  402. context.getSharedPreferences(PREFERENCE_KEY, 0).edit().putString("Server Address", serverAdr).apply();
  403. final Spinner videoResolutionSpinner = findViewById(R.id.spinner_video_resolution);
  404. final Spinner videoBitrateSpinner = findViewById(R.id.spinner_video_bitrate);
  405. final Switch a_Switch0 = findViewById(R.id.switch0);
  406. no_control = a_Switch0.isChecked();
  407. final Switch a_Switch1 = findViewById(R.id.switch1);
  408. nav = a_Switch1.isChecked();
  409. context.getSharedPreferences(PREFERENCE_KEY, 0).edit().putBoolean("No Control", no_control).apply();
  410. context.getSharedPreferences(PREFERENCE_KEY, 0).edit().putBoolean("Nav Switch", nav).apply();
  411. final String[] videoResolutions = getResources().getStringArray(R.array.options_resolution_values)[videoResolutionSpinner.getSelectedItemPosition()].split(",");
  412. screenHeight = Integer.parseInt(videoResolutions[0]);
  413. screenWidth = Integer.parseInt(videoResolutions[1]);
  414. videoBitrate = getResources().getIntArray(R.array.options_bitrate_values)[videoBitrateSpinner.getSelectedItemPosition()];
  415. }
  416. private void swapDimensions() {
  417. int temp = screenHeight;
  418. screenHeight = screenWidth;
  419. screenWidth = temp;
  420. }
  421. @SuppressLint("ClickableViewAccessibility")
  422. private void start_screen_copy_magic() {
  423. Log.e("Scrcpy: ","Starting scrcpy service");
  424. setContentView(R.layout.surface);//开始渲染
  425. final View decorView = getWindow().getDecorView();
  426. decorView.setSystemUiVisibility(
  427. View.SYSTEM_UI_FLAG_LAYOUT_STABLE
  428. | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
  429. | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
  430. | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
  431. | View.SYSTEM_UI_FLAG_FULLSCREEN
  432. | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
  433. surfaceView = findViewById(R.id.decoder_surface);
  434. surface = surfaceView.getHolder().getSurface();
  435. final LinearLayout nav_bar = findViewById(R.id.nav_button_bar);
  436. if(nav && !no_control) {
  437. nav_bar.setVisibility(LinearLayout.VISIBLE);
  438. }else {
  439. nav_bar.setVisibility(LinearLayout.GONE);
  440. }
  441. linearLayout = findViewById(R.id.container1);
  442. start_Scrcpy_service();
  443. initDownloadBtn();//loadNewRotation 屏幕旋转需要重新初始化
  444. }
  445. protected String wifiIpAddress() {
  446. //https://stackoverflow.com/questions/6064510/how-to-get-ip-address-of-the-device-from-code
  447. try {
  448. InetAddress ipv4 = null;
  449. InetAddress ipv6 = null;
  450. for (Enumeration<NetworkInterface> en = NetworkInterface
  451. .getNetworkInterfaces(); en.hasMoreElements(); ) {
  452. NetworkInterface int_f = en.nextElement();
  453. for (Enumeration<InetAddress> enumIpAddr = int_f
  454. .getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
  455. InetAddress inetAddress = enumIpAddr.nextElement();
  456. if (inetAddress instanceof Inet6Address) {
  457. ipv6 = inetAddress;
  458. continue;
  459. }
  460. if (inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
  461. ipv4 = inetAddress;
  462. continue;
  463. }
  464. return inetAddress.getHostAddress();
  465. }
  466. }
  467. if (ipv6 != null) {
  468. return ipv6.getHostAddress();
  469. }
  470. if (ipv4 != null) {
  471. return ipv4.getHostAddress();
  472. }
  473. return null;
  474. } catch (SocketException ex) {
  475. ex.printStackTrace();
  476. }
  477. return null;
  478. }
  479. private void start_Scrcpy_service() {
  480. Intent intent = new Intent(this, Scrcpy.class);
  481. startService(intent);
  482. bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
  483. }
  484. @SuppressLint("SourceLockedOrientationActivity")
  485. @Override
  486. public void loadNewRotation() {
  487. Log.e("Scrcpy: ","loadNewRotation "+first_time);
  488. if (first_time){
  489. int[] rem_res = scrcpy.get_remote_device_resolution();
  490. remote_device_height = rem_res[1];
  491. remote_device_width = rem_res[0];
  492. first_time = false;
  493. }
  494. unbindService(serviceConnection);
  495. serviceBound = false;
  496. result_of_Rotation = true;
  497. landscape = !landscape;
  498. swapDimensions();
  499. if (landscape) {
  500. setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
  501. } else {
  502. setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
  503. }
  504. }
  505. @Override
  506. protected void onPause() {
  507. super.onPause();
  508. if (serviceBound) {
  509. scrcpy.pause();
  510. }
  511. }
  512. @Override
  513. protected void onResume() {
  514. super.onResume();
  515. if (!first_time && !result_of_Rotation) {
  516. final View decorView = getWindow().getDecorView();
  517. decorView.setSystemUiVisibility(
  518. View.SYSTEM_UI_FLAG_LAYOUT_STABLE
  519. | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
  520. | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
  521. | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
  522. | View.SYSTEM_UI_FLAG_FULLSCREEN
  523. | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
  524. if (serviceBound) {
  525. linearLayout = findViewById(R.id.container1);
  526. scrcpy.resume();
  527. }
  528. }
  529. result_of_Rotation = false;
  530. }
  531. @Override
  532. public void onBackPressed() {
  533. if (timestamp == 0) {
  534. timestamp = SystemClock.uptimeMillis();
  535. Toast.makeText(context, "Press again to exit", Toast.LENGTH_SHORT).show();
  536. } else {
  537. long now = SystemClock.uptimeMillis();
  538. if (now < timestamp + 1000) {
  539. timestamp = 0;
  540. if (serviceBound) {
  541. scrcpy.StopService();
  542. unbindService(serviceConnection);
  543. }
  544. android.os.Process.killProcess(android.os.Process.myPid());
  545. System.exit(1);
  546. }
  547. timestamp = 0;
  548. }
  549. }
  550. @Override
  551. public void onSensorChanged(SensorEvent sensorEvent) {
  552. if (sensorEvent.sensor.getType() == Sensor.TYPE_PROXIMITY) {
  553. if (sensorEvent.values[0] == 0) {
  554. if (serviceBound) {
  555. scrcpy.sendKeyevent(28);
  556. }
  557. } else {
  558. if (serviceBound) {
  559. scrcpy.sendKeyevent(29);
  560. }
  561. }
  562. }
  563. }
  564. @Override
  565. public void onAccuracyChanged(Sensor sensor, int i) {
  566. }
  567. private void showPermissionDeniedDialog(){
  568. AlertDialog.Builder builder = new AlertDialog.Builder(this);
  569. builder.setMessage("请前往设置界面打开SD卡读写权限");
  570. builder.setPositiveButton("去设置", new DialogInterface.OnClickListener() {
  571. @Override
  572. public void onClick(DialogInterface dialogInterface, int i) {
  573. Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:"+getPackageName()));
  574. intent.addCategory(Intent.CATEGORY_DEFAULT);
  575. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  576. startActivity(intent);
  577. }
  578. });
  579. builder.setNegativeButton("取消",new DialogInterface.OnClickListener() {
  580. @Override
  581. public void onClick(DialogInterface dialogInterface, int i) {
  582. finish();
  583. }
  584. });
  585. builder.show();
  586. }
  587. }