From 7666fb6d731078755b1e2410218441c229239443 Mon Sep 17 00:00:00 2001 From: mingzhixian123 Date: Sun, 25 Feb 2024 22:20:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0V1.3.76?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化修改分辨率算法,避免元素缩放过大过小问题 - 完善分辨率自适应功能 - UI界面优化 - 修复部分设备UI显示问题 - 局域网设备扫描功能增强 - 完善自定义动作设置 - 增加连接时自定义分辨率功能 - 分辨率自动恢复从重置改为恢复成连接前分辨率(主控端设备长按恢复分辨率仍为重置) - 支持多设备自启动 - 修复直连与隧道无法自动切换的问题 - 增加间距减少误触 --- HOW_TO_USE.md | 2 - README.md | 16 +- easycontrol/app/build.gradle | 4 +- easycontrol/app/src/main/AndroidManifest.xml | 7 +- .../easycontrol/app/ActiveActivity.java | 22 +- .../easycontrol/app/AdbKeyActivity.java | 2 +- .../easycontrol/app/DeviceDetailActivity.java | 119 +++++++ .../saymzx/easycontrol/app/IpActivity.java | 17 +- .../saymzx/easycontrol/app/MainActivity.java | 30 +- .../saymzx/easycontrol/app/SetActivity.java | 44 +-- .../easycontrol/app/SetDetailActivity.java | 96 ----- .../app/client/ClientController.java | 27 +- .../easycontrol/app/client/ClientStream.java | 21 +- .../easycontrol/app/client/ControlPacket.java | 12 +- .../app/client/decode/VideoDecode.java | 1 - .../app/client/view/FullActivity.java | 93 +++-- .../easycontrol/app/client/view/MiniView.java | 8 +- .../app/client/view/SmallView.java | 38 +- .../saymzx/easycontrol/app/entity/Device.java | 86 ++--- .../easycontrol/app/entity/Setting.java | 188 +--------- .../easycontrol/app/helper/DbHelper.java | 199 +++++++++-- .../app/helper/DeviceListAdapter.java | 57 ++- .../app/helper/MyBroadcastReceiver.java | 27 +- .../easycontrol/app/helper/PublicTools.java | 42 ++- .../easycontrol/app/helper/ViewTools.java | 74 +--- .../src/main/res/drawable/background_cron.xml | 2 +- .../res/drawable/background_cron_stroke.xml | 8 + .../main/res/drawable/background_round.xml | 5 + .../src/main/res/drawable/chevron_down.xml | 9 + .../src/main/res/drawable/chevron_right.xml | 9 + .../src/main/res/drawable/chinese_yanhua.webp | Bin 82252 -> 0 bytes .../main/res/drawable/main_chengxuyuan.webp | Bin 0 -> 37066 bytes .../app/src/main/res/drawable/scansion.xml | 12 +- .../src/main/res/layout/activity_active.xml | 45 ++- .../src/main/res/layout/activity_adb_key.xml | 46 +-- .../res/layout/activity_device_detail.xml | 329 ++++++++++++++++++ .../app/src/main/res/layout/activity_ip.xml | 35 +- .../app/src/main/res/layout/activity_main.xml | 34 +- .../app/src/main/res/layout/activity_set.xml | 24 -- .../main/res/layout/activity_set_detail.xml | 35 -- .../main/res/layout/item_device_detail.xml | 73 ---- .../src/main/res/layout/item_devices_item.xml | 93 ++--- .../res/layout/item_request_permission.xml | 5 +- .../res/layout/item_scan_address_list.xml | 7 +- .../src/main/res/layout/item_set_device.xml | 80 ++--- .../app/src/main/res/layout/item_text.xml | 30 +- .../src/main/res/layout/module_mini_view.xml | 87 ++--- .../src/main/res/layout/module_small_view.xml | 22 +- .../app/src/main/res/values-en/strings.xml | 166 ++++----- .../app/src/main/res/values-night/color.xml | 14 +- easycontrol/app/src/main/res/values/color.xml | 14 +- easycontrol/app/src/main/res/values/size.xml | 7 +- .../app/src/main/res/values/strings.xml | 168 +++++---- .../top/saymzx/easycontrol/server/Server.java | 10 +- .../easycontrol/server/entity/Device.java | 100 +++--- .../easycontrol/server/entity/Options.java | 4 + pic/other/wechat_issue.png | Bin 0 -> 68710 bytes pic/screenshot/1.jpg | Bin 0 -> 90109 bytes pic/screenshot/2.jpg | Bin 0 -> 107980 bytes pic/screenshot/3.jpg | Bin 0 -> 113930 bytes pic/screenshot/4.jpg | Bin 0 -> 76712 bytes pic/screenshot/5.jpg | Bin 0 -> 176982 bytes pic/screenshot/6.jpg | Bin 0 -> 146727 bytes pic/screenshot/7.jpg | Bin 0 -> 90918 bytes pic/screenshot/8.jpg | Bin 0 -> 170356 bytes pic/screenshot/full.webp | Bin 149866 -> 0 bytes pic/screenshot/main.webp | Bin 68556 -> 0 bytes pic/screenshot/mini.webp | Bin 70460 -> 0 bytes pic/screenshot/small.webp | Bin 97150 -> 0 bytes 69 files changed, 1398 insertions(+), 1307 deletions(-) create mode 100644 easycontrol/app/src/main/java/top/saymzx/easycontrol/app/DeviceDetailActivity.java delete mode 100644 easycontrol/app/src/main/java/top/saymzx/easycontrol/app/SetDetailActivity.java create mode 100644 easycontrol/app/src/main/res/drawable/background_cron_stroke.xml create mode 100644 easycontrol/app/src/main/res/drawable/background_round.xml create mode 100644 easycontrol/app/src/main/res/drawable/chevron_down.xml create mode 100644 easycontrol/app/src/main/res/drawable/chevron_right.xml delete mode 100644 easycontrol/app/src/main/res/drawable/chinese_yanhua.webp create mode 100644 easycontrol/app/src/main/res/drawable/main_chengxuyuan.webp create mode 100644 easycontrol/app/src/main/res/layout/activity_device_detail.xml delete mode 100644 easycontrol/app/src/main/res/layout/activity_set_detail.xml delete mode 100644 easycontrol/app/src/main/res/layout/item_device_detail.xml create mode 100644 pic/other/wechat_issue.png create mode 100644 pic/screenshot/1.jpg create mode 100644 pic/screenshot/2.jpg create mode 100644 pic/screenshot/3.jpg create mode 100644 pic/screenshot/4.jpg create mode 100644 pic/screenshot/5.jpg create mode 100644 pic/screenshot/6.jpg create mode 100644 pic/screenshot/7.jpg create mode 100644 pic/screenshot/8.jpg delete mode 100644 pic/screenshot/full.webp delete mode 100644 pic/screenshot/main.webp delete mode 100644 pic/screenshot/mini.webp delete mode 100644 pic/screenshot/small.webp diff --git a/HOW_TO_USE.md b/HOW_TO_USE.md index 26d535dc..42b80a53 100644 --- a/HOW_TO_USE.md +++ b/HOW_TO_USE.md @@ -59,8 +59,6 @@ 4. 扩展使用 易控支持在外部使用广播控制,广播地址为:"top.saymzx.easycontrol.app.CONTROL",需要向意向也就是Intent填入想要做的动作: - - 启动默认设备: - - action:startDefault - 启动目标设备: - action:start - uuid:设备ID diff --git a/README.md b/README.md index c9999493..eaec2dee 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,11 @@ 代码是开源的,但官方打包的安装包需要激活才可使用,激活的步骤请参考[此页面](https://gitee.com/mingzhixianweb/easycontrol/blob/master/DONATE.md) ## 截图 - - - - +
+ + + +
## 构建 如果您想要自己构建,请注意以下几项 @@ -42,7 +43,12 @@ - 我去除了官方打包加入的激活模块相关的代码文件,所以会有报错,请自行注释掉报错代码即可 ## 反馈 - 请在Github或Gitee提出Issue,或进入易控反馈群反馈BUG或建议。 + + +## 附加 +- ADB协议说明(官方的文档写的真烂,感谢cstyan大佬) [点击前往](https://github.com/cstyan/adbDocumentation) +- Scrcpy官方地址 [点击前往](https://github.com/Genymobile/scrcpy) +- 第三方修改本(专为车机进行了优化) [点击前往](https://github.com/eiyooooo/Easycontrol_For_Car) diff --git a/easycontrol/app/build.gradle b/easycontrol/app/build.gradle index 9cc0c21c..4b733d40 100644 --- a/easycontrol/app/build.gradle +++ b/easycontrol/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "top.saymzx.easycontrol.app" minSdk 21 targetSdk 34 - versionCode 10373 - versionName "1.3.73" + versionCode 10376 + versionName "1.3.76" ndk { abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" } diff --git a/easycontrol/app/src/main/AndroidManifest.xml b/easycontrol/app/src/main/AndroidManifest.xml index f82cc3a1..00437198 100644 --- a/easycontrol/app/src/main/AndroidManifest.xml +++ b/easycontrol/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + @@ -28,13 +27,13 @@ PublicTools.startUrl(this, "https://gitee.com/mingzhixianweb/easycontrol/blob/master/DONATE.md")).getRoot()); + activityActiveBinding.key.setText(AppData.setting.getActiveKey()); + activityActiveBinding.url.setOnClickListener(v -> PublicTools.startUrl(this, "https://gitee.com/mingzhixianweb/easycontrol/blob/master/DONATE.md")); } private void setButtonListener() { - activeActivity.active.setOnClickListener(v -> { - String activeKey = String.valueOf(activeActivity.key.getText()); + activityActiveBinding.active.setOnClickListener(v -> { + String activeKey = String.valueOf(activityActiveBinding.key.getText()); AppData.setting.setActiveKey(activeKey); Pair loading = ViewTools.createLoading(this); AppData.windowManager.addView(loading.first, loading.second); @@ -49,8 +49,8 @@ private void setButtonListener() { finish(); AppData.setting.setIsActive(true); PublicTools.startUrl(this, "https://gitee.com/mingzhixianweb/easycontrol/blob/master/HOW_TO_USE.md"); - PublicTools.logToast("active", getString(R.string.active_button_success), true); - } else PublicTools.logToast("active", getString(R.string.active_button_error), true); + PublicTools.logToast("active", getString(R.string.toast_success), true); + } else PublicTools.logToast("active", getString(R.string.toast_fail), true); }); }).start(); }); @@ -66,8 +66,8 @@ private void deactivate() { AppData.uiHandler.post(() -> { if (isOk) { AppData.setting.setIsActive(false); - PublicTools.logToast("deactivate", getString(R.string.active_deactivate_success), true); - } else PublicTools.logToast("deactivate", getString(R.string.active_deactivate_error), true); + PublicTools.logToast("deactivate", getString(R.string.toast_success), true); + } else PublicTools.logToast("deactivate", getString(R.string.toast_fail), true); }); }).start(); } diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/AdbKeyActivity.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/AdbKeyActivity.java index 442e0808..02b6c16b 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/AdbKeyActivity.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/AdbKeyActivity.java @@ -63,7 +63,7 @@ private void writeKey() { privateKeyWriter.flush(); } AppData.keyPair = AdbKeyPair.read(adbKeyFile.first, adbKeyFile.second); - Toast.makeText(this, getString(R.string.adb_key_button_code), Toast.LENGTH_SHORT).show(); + Toast.makeText(this, getString(R.string.toast_success), Toast.LENGTH_SHORT).show(); } catch (Exception ignored) { } } diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/DeviceDetailActivity.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/DeviceDetailActivity.java new file mode 100644 index 00000000..5ad88fc6 --- /dev/null +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/DeviceDetailActivity.java @@ -0,0 +1,119 @@ +package top.saymzx.easycontrol.app; + +import android.app.Activity; +import android.content.ClipData; +import android.content.ClipDescription; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Toast; + +import java.util.UUID; + +import top.saymzx.easycontrol.app.databinding.ActivityDeviceDetailBinding; +import top.saymzx.easycontrol.app.entity.AppData; +import top.saymzx.easycontrol.app.entity.Device; +import top.saymzx.easycontrol.app.helper.MyBroadcastReceiver; +import top.saymzx.easycontrol.app.helper.ViewTools; + +public class DeviceDetailActivity extends Activity { + private ActivityDeviceDetailBinding activityDeviceDetailBinding; + private boolean isNew; + private Device device; + + @Override + protected void onCreate(Bundle savedInstanceState) { + ViewTools.setStatusAndNavBar(this); + ViewTools.setLocale(this); + activityDeviceDetailBinding = ActivityDeviceDetailBinding.inflate(this.getLayoutInflater()); + setContentView(activityDeviceDetailBinding.getRoot()); + // 获取Device + String uuid = getIntent().getStringExtra("uuid"); + isNew = uuid == null; + if (isNew) device = new Device(UUID.randomUUID().toString(), Device.TYPE_NETWORK); + else device = AppData.dbHelper.getByUUID(uuid); + // 绘制UI + drawUI(); + // 设置监听 + setListener(); + super.onCreate(savedInstanceState); + } + + // 绘制UI + private static final String[] maxSizeList = new String[]{"2560", "1920", "1600", "1280", "1024", "800"}; + private static final String[] maxFpsList = new String[]{"90", "60", "40", "30", "20", "10"}; + private static final String[] maxVideoBitList = new String[]{"12", "8", "4", "2", "1"}; + + private void drawUI() { + // UUID + activityDeviceDetailBinding.uuid.setOnClickListener(v -> { + AppData.clipBoard.setPrimaryClip(ClipData.newPlainText(ClipDescription.MIMETYPE_TEXT_PLAIN, device.uuid)); + Toast.makeText(this, getString(R.string.toast_copy), Toast.LENGTH_SHORT).show(); + }); + // 预填写参数 + activityDeviceDetailBinding.name.setText(device.name); + activityDeviceDetailBinding.address.setText(device.address); + if (!device.isNetworkDevice()) activityDeviceDetailBinding.address.setEnabled(false); + activityDeviceDetailBinding.customResolution.setVisibility(device.customResolutionOnConnect ? View.VISIBLE : View.GONE); + activityDeviceDetailBinding.customResolutionWidth.setText(String.valueOf(device.customResolutionWidth)); + activityDeviceDetailBinding.customResolutionHeight.setText(String.valueOf(device.customResolutionHeight)); + // 连接时操作 + activityDeviceDetailBinding.layoutOnConnect.setOnClickListener(v -> activityDeviceDetailBinding.layoutOnConnectSub.setVisibility(activityDeviceDetailBinding.layoutOnConnectSub.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE)); + activityDeviceDetailBinding.layoutOnConnectSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_custom_resolution_on_connect), getString(R.string.device_custom_resolution_on_connect_detail), device.customResolutionOnConnect, isChecked -> activityDeviceDetailBinding.customResolution.setVisibility(isChecked ? View.VISIBLE : View.GONE)).getRoot(), 0); + activityDeviceDetailBinding.layoutOnConnectSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_wake_on_connect), getString(R.string.device_wake_on_connect_detail), device.wakeOnConnect, isChecked -> device.wakeOnConnect = isChecked).getRoot()); + activityDeviceDetailBinding.layoutOnConnectSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_light_off_on_connect), getString(R.string.device_light_off_on_connect_detail), device.lightOffOnConnect, isChecked -> device.lightOffOnConnect = isChecked).getRoot()); + activityDeviceDetailBinding.layoutOnConnectSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_show_nav_bar_on_connect), getString(R.string.device_show_nav_bar_on_connect_detail), device.showNavBarOnConnect, isChecked -> device.showNavBarOnConnect = isChecked).getRoot()); + activityDeviceDetailBinding.layoutOnConnectSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_change_to_full_on_connect), getString(R.string.device_change_to_full_on_connect_detail), device.changeToFullOnConnect, isChecked -> device.changeToFullOnConnect = isChecked).getRoot()); + // 运行时操作 + activityDeviceDetailBinding.layoutOnRunning.setOnClickListener(v -> activityDeviceDetailBinding.layoutOnRunningSub.setVisibility(activityDeviceDetailBinding.layoutOnRunningSub.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE)); + activityDeviceDetailBinding.layoutOnRunningSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_keep_wake_on_running), getString(R.string.device_keep_wake_on_running_detail), device.keepWakeOnRunning, isChecked -> device.keepWakeOnRunning = isChecked).getRoot()); + activityDeviceDetailBinding.layoutOnRunningSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_change_resolution_on_running), getString(R.string.device_change_resolution_on_running_detail), device.changeResolutionOnRunning, isChecked -> device.changeResolutionOnRunning = isChecked).getRoot()); + activityDeviceDetailBinding.layoutOnRunningSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_small_to_mini_on_running), getString(R.string.device_small_to_mini_on_running_detail), device.smallToMiniOnRunning, isChecked -> device.smallToMiniOnRunning = isChecked).getRoot()); + activityDeviceDetailBinding.layoutOnRunningSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_full_to_mini_on_running), getString(R.string.device_full_to_mini_on_running_detail), device.fullToMiniOnRunning, isChecked -> device.fullToMiniOnRunning = isChecked).getRoot()); + activityDeviceDetailBinding.layoutOnRunningSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_mini_timeout_on_running), getString(R.string.device_mini_timeout_on_running_detail), device.miniTimeoutOnRunning, isChecked -> device.miniTimeoutOnRunning = isChecked).getRoot()); + // 断开时操作 + activityDeviceDetailBinding.layoutOnClose.setOnClickListener(v -> activityDeviceDetailBinding.layoutOnCloseSub.setVisibility(activityDeviceDetailBinding.layoutOnCloseSub.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE)); + activityDeviceDetailBinding.layoutOnCloseSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_lock_on_close), getString(R.string.device_lock_on_close_detail), device.lockOnClose, isChecked -> device.lockOnClose = isChecked).getRoot()); + activityDeviceDetailBinding.layoutOnCloseSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_light_on_close), getString(R.string.device_light_on_close_detail), device.lightOnClose, isChecked -> device.lightOnClose = isChecked).getRoot()); + activityDeviceDetailBinding.layoutOnCloseSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_reconnect_on_close), getString(R.string.device_reconnect_on_close_detail), device.reconnectOnClose, isChecked -> device.reconnectOnClose = isChecked).getRoot()); + // 参数 + activityDeviceDetailBinding.layoutOption.setOnClickListener(v -> activityDeviceDetailBinding.layoutOptionSub.setVisibility(activityDeviceDetailBinding.layoutOptionSub.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE)); + ArrayAdapter maxSizeAdapter = new ArrayAdapter<>(AppData.applicationContext, R.layout.item_spinner_item, maxSizeList); + ArrayAdapter maxFpsAdapter = new ArrayAdapter<>(AppData.applicationContext, R.layout.item_spinner_item, maxFpsList); + ArrayAdapter maxVideoBitAdapter = new ArrayAdapter<>(AppData.applicationContext, R.layout.item_spinner_item, maxVideoBitList); + activityDeviceDetailBinding.layoutOptionSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_is_audio), getString(R.string.device_is_audio_detail), device.isAudio, isChecked -> device.isAudio = isChecked).getRoot()); + activityDeviceDetailBinding.layoutOptionSub.addView(ViewTools.createSpinnerCard(this, getString(R.string.device_max_size), getString(R.string.device_max_size_detail), String.valueOf(device.maxSize), maxSizeAdapter, str -> device.maxSize = Integer.parseInt(str)).getRoot()); + activityDeviceDetailBinding.layoutOptionSub.addView(ViewTools.createSpinnerCard(this, getString(R.string.device_max_fps), getString(R.string.device_max_fps_detail), String.valueOf(device.maxFps), maxFpsAdapter, str -> device.maxFps = Integer.parseInt(str)).getRoot()); + activityDeviceDetailBinding.layoutOptionSub.addView(ViewTools.createSpinnerCard(this, getString(R.string.device_max_video_bit), getString(R.string.device_max_video_bit_detail), String.valueOf(device.maxVideoBit), maxVideoBitAdapter, str -> device.maxVideoBit = Integer.parseInt(str)).getRoot()); + activityDeviceDetailBinding.layoutOptionSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_use_h265), getString(R.string.device_use_h265_detail), device.useH265, isChecked -> device.useH265 = isChecked).getRoot()); + activityDeviceDetailBinding.layoutOptionSub.addView(ViewTools.createSwitchCard(this, getString(R.string.device_connect_on_start), getString(R.string.device_connect_on_start_detail), device.connectOnStart, isChecked -> device.connectOnStart = isChecked).getRoot()); + } + + // 设置监听 + private void setListener() { + activityDeviceDetailBinding.backButton.setOnClickListener(v -> finish()); + // 设置确认按钮监听 + activityDeviceDetailBinding.ok.setOnClickListener(v -> { + if (device.isNetworkDevice() && String.valueOf(activityDeviceDetailBinding.address.getText()).equals("")) return; + device.name = String.valueOf(activityDeviceDetailBinding.name.getText()); + device.address = String.valueOf(activityDeviceDetailBinding.address.getText()); + // 自定义分辨率 + String width = String.valueOf(activityDeviceDetailBinding.customResolutionWidth.getText()); + String height = String.valueOf(activityDeviceDetailBinding.customResolutionHeight.getText()); + device.customResolutionOnConnect = false; + if (activityDeviceDetailBinding.customResolution.getVisibility() != View.GONE && !width.equals("") && !height.equals("") && Integer.parseInt(width) >= 500 && Integer.parseInt(height) >= 500) { + device.customResolutionOnConnect = true; + device.customResolutionWidth = Integer.parseInt(width); + device.customResolutionHeight = Integer.parseInt(height); + } + // 更新数据库 + if (isNew) AppData.dbHelper.insert(device); + else AppData.dbHelper.update(device); + Intent intent = new Intent(); + intent.setAction(MyBroadcastReceiver.ACTION_UPDATE_DEVICE_LIST); + sendBroadcast(intent); + finish(); + }); + } +} \ No newline at end of file diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/IpActivity.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/IpActivity.java index c29f672d..c2dc8e62 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/IpActivity.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/IpActivity.java @@ -3,7 +3,6 @@ import android.app.Activity; import android.content.ClipData; import android.content.ClipDescription; -import android.content.Context; import android.os.Bundle; import android.util.Pair; import android.widget.Toast; @@ -17,14 +16,14 @@ import top.saymzx.easycontrol.app.helper.ViewTools; public class IpActivity extends Activity { - private ActivityIpBinding ipActivity; + private ActivityIpBinding activityIpBinding; @Override public void onCreate(Bundle savedInstanceState) { ViewTools.setStatusAndNavBar(this); ViewTools.setLocale(this); - ipActivity = ActivityIpBinding.inflate(this.getLayoutInflater()); - setContentView(ipActivity.getRoot()); + activityIpBinding = ActivityIpBinding.inflate(this.getLayoutInflater()); + setContentView(activityIpBinding.getRoot()); setButtonListener(); // 绘制UI drawUi(); @@ -37,22 +36,22 @@ private void drawUi() { for (String i : listPair.first) { ItemTextBinding text = ViewTools.createTextCard(this, i, () -> { AppData.clipBoard.setPrimaryClip(ClipData.newPlainText(ClipDescription.MIMETYPE_TEXT_PLAIN, i)); - Toast.makeText(this, getString(R.string.ip_copy), Toast.LENGTH_SHORT).show(); + Toast.makeText(this, getString(R.string.toast_copy), Toast.LENGTH_SHORT).show(); }); - ipActivity.ipv4.addView(text.getRoot()); + activityIpBinding.ipv4.addView(text.getRoot()); } for (String i : listPair.second) { ItemTextBinding text = ViewTools.createTextCard(this, i, () -> { AppData.clipBoard.setPrimaryClip(ClipData.newPlainText(ClipDescription.MIMETYPE_TEXT_PLAIN, i)); - Toast.makeText(this, getString(R.string.ip_copy), Toast.LENGTH_SHORT).show(); + Toast.makeText(this, getString(R.string.toast_copy), Toast.LENGTH_SHORT).show(); }); - ipActivity.ipv6.addView(text.getRoot()); + activityIpBinding.ipv6.addView(text.getRoot()); } } // 设置返回按钮监听 private void setButtonListener() { - ipActivity.backButton.setOnClickListener(v -> finish()); + activityIpBinding.backButton.setOnClickListener(v -> finish()); } } diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/MainActivity.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/MainActivity.java index 37bf06ea..1a2a090d 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/MainActivity.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/MainActivity.java @@ -17,25 +17,20 @@ import android.widget.Toast; import java.util.ArrayList; -import java.util.UUID; import top.saymzx.easycontrol.app.databinding.ActivityMainBinding; import top.saymzx.easycontrol.app.databinding.ItemRequestPermissionBinding; import top.saymzx.easycontrol.app.databinding.ItemScanAddressListBinding; import top.saymzx.easycontrol.app.databinding.ItemTextBinding; import top.saymzx.easycontrol.app.entity.AppData; -import top.saymzx.easycontrol.app.entity.Device; import top.saymzx.easycontrol.app.helper.DeviceListAdapter; import top.saymzx.easycontrol.app.helper.MyBroadcastReceiver; import top.saymzx.easycontrol.app.helper.PublicTools; import top.saymzx.easycontrol.app.helper.ViewTools; public class MainActivity extends Activity { - // 设备列表 - private DeviceListAdapter deviceListAdapter; - // 创建界面 - private ActivityMainBinding mainActivity; + private ActivityMainBinding activityMainBinding; // 广播 private final MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver(); @@ -46,8 +41,8 @@ public void onCreate(Bundle savedInstanceState) { AppData.init(this); ViewTools.setStatusAndNavBar(this); ViewTools.setLocale(this); - mainActivity = ActivityMainBinding.inflate(this.getLayoutInflater()); - setContentView(mainActivity.getRoot()); + activityMainBinding = ActivityMainBinding.inflate(this.getLayoutInflater()); + setContentView(activityMainBinding.getRoot()); // 检测权限 if (!checkPermission()) createAlert(); else startApp(); @@ -65,8 +60,8 @@ private void startApp() { // 检测激活 checkActive(); // 设置设备列表适配器 - deviceListAdapter = new DeviceListAdapter(this); - mainActivity.devicesList.setAdapter(deviceListAdapter); + DeviceListAdapter deviceListAdapter = new DeviceListAdapter(this); + activityMainBinding.devicesList.setAdapter(deviceListAdapter); myBroadcastReceiver.setDeviceListAdapter(deviceListAdapter); // 设置按钮监听 setButtonListener(); @@ -74,10 +69,8 @@ private void startApp() { myBroadcastReceiver.register(this); // 检查已连接设备 myBroadcastReceiver.checkConnectedUsb(this); - // 启动默认设备 - AppData.uiHandler.postDelayed(() -> myBroadcastReceiver.startDefault(this), 1000); - // 开始扫描 - if (AppData.setting.getAutoScanAddressOnStart()) scanAddress(); + // 自启动设备 + AppData.uiHandler.postDelayed(deviceListAdapter::startDefaultDevice, 1000); } // 检测激活 @@ -112,6 +105,7 @@ private void createAlert() { // 定时检查 private void checkPermissionDelay(Dialog dialog) { + // 因为某些设备可能会无法进入设置或其他问题,导致不会有返回结果,为了减少不确定性,使用定时检测的方法 AppData.uiHandler.postDelayed(() -> { if (checkPermission()) { dialog.cancel(); @@ -122,9 +116,9 @@ private void checkPermissionDelay(Dialog dialog) { // 设置按钮监听 private void setButtonListener() { - mainActivity.buttonScan.setOnClickListener(v -> scanAddress()); - mainActivity.buttonAdd.setOnClickListener(v -> ViewTools.createDeviceDetailView(this, Device.getDefaultDevice(UUID.randomUUID().toString(), Device.TYPE_NORMAL), deviceListAdapter).show()); - mainActivity.buttonSet.setOnClickListener(v -> startActivity(new Intent(this, SetActivity.class))); + activityMainBinding.buttonScan.setOnClickListener(v -> scanAddress()); + activityMainBinding.buttonAdd.setOnClickListener(v -> startActivity(new Intent(this, DeviceDetailActivity.class))); + activityMainBinding.buttonSet.setOnClickListener(v -> startActivity(new Intent(this, SetActivity.class))); } // 扫描局域网地址 @@ -140,7 +134,7 @@ private void scanAddress() { for (String i : scannedAddresses) { ItemTextBinding text = ViewTools.createTextCard(this, i, () -> { AppData.clipBoard.setPrimaryClip(ClipData.newPlainText(ClipDescription.MIMETYPE_TEXT_PLAIN, i)); - Toast.makeText(this, getString(R.string.ip_copy), Toast.LENGTH_SHORT).show(); + Toast.makeText(this, getString(R.string.toast_copy), Toast.LENGTH_SHORT).show(); }); scanAddressListView.list.addView(text.getRoot()); } diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/SetActivity.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/SetActivity.java index 0878e7f8..333febb6 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/SetActivity.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/SetActivity.java @@ -7,17 +7,18 @@ import top.saymzx.easycontrol.app.databinding.ActivitySetBinding; import top.saymzx.easycontrol.app.entity.AppData; +import top.saymzx.easycontrol.app.helper.PublicTools; import top.saymzx.easycontrol.app.helper.ViewTools; public class SetActivity extends Activity { - private ActivitySetBinding setActivity; + private ActivitySetBinding activitySetBinding; @Override public void onCreate(Bundle savedInstanceState) { ViewTools.setStatusAndNavBar(this); ViewTools.setLocale(this); - setActivity = ActivitySetBinding.inflate(this.getLayoutInflater()); - setContentView(setActivity.getRoot()); + activitySetBinding = ActivitySetBinding.inflate(this.getLayoutInflater()); + setContentView(activitySetBinding.getRoot()); // 设置页面 drawUi(); setButtonListener(); @@ -26,33 +27,26 @@ public void onCreate(Bundle savedInstanceState) { // 设置默认值 private void drawUi() { - // 默认参数 - setActivity.setDefault.addView(ViewTools.createTextCard(this, getString(R.string.set_default), () -> enterDetailSet("default")).getRoot()); - // 显示 - setActivity.setAuto.addView(ViewTools.createTextCard(this, getString(R.string.set_on_start), () -> enterDetailSet("onStart")).getRoot()); - setActivity.setAuto.addView(ViewTools.createTextCard(this, getString(R.string.set_on_connect), () -> enterDetailSet("onConnect")).getRoot()); - setActivity.setAuto.addView(ViewTools.createTextCard(this, getString(R.string.set_on_close), () -> enterDetailSet("onClose")).getRoot()); - setActivity.setAuto.addView(ViewTools.createTextCard(this, getString(R.string.set_connecting), () -> enterDetailSet("connecting")).getRoot()); // 其他 - setActivity.setOther.addView(ViewTools.createTextCard(this, getString(R.string.set_about_ip), () -> startActivity(new Intent(this, IpActivity.class))).getRoot()); - setActivity.setOther.addView(ViewTools.createTextCard(this, getString(R.string.set_adb_key), () -> enterDetailSet("adbKey")).getRoot()); - // 关于 - setActivity.setAbout.addView(ViewTools.createTextCard(this, getString(R.string.set_other_locale), () -> { - AppData.setting.setDefaultLocale(AppData.setting.getDefaultLocale().equals("en") ? "zh" : "en"); - Toast.makeText(this, getString(R.string.set_other_locale_code), Toast.LENGTH_SHORT).show(); + activitySetBinding.setOther.addView(ViewTools.createTextCard(this, getString(R.string.set_other_ip), () -> startActivity(new Intent(this, IpActivity.class))).getRoot()); + activitySetBinding.setOther.addView(ViewTools.createTextCard(this, getString(R.string.set_other_custom_key), () -> startActivity(new Intent(this, AdbKeyActivity.class))).getRoot()); + activitySetBinding.setOther.addView(ViewTools.createTextCard(this, getString(R.string.set_other_reset_key), () -> { + AppData.keyPair = PublicTools.reGenerateAdbKeyPair(); + Toast.makeText(this, getString(R.string.toast_success), Toast.LENGTH_SHORT).show(); + }).getRoot()); + activitySetBinding.setOther.addView(ViewTools.createTextCard(this, getString(R.string.set_other_locale), () -> { + AppData.setting.setLocale(AppData.setting.getLocale().equals("en") ? "zh" : "en"); + Toast.makeText(this, getString(R.string.toast_change_locale), Toast.LENGTH_SHORT).show(); }).getRoot()); - setActivity.setAbout.addView(ViewTools.createTextCard(this, getString(R.string.set_about), () -> enterDetailSet("about")).getRoot()); + // 关于 + activitySetBinding.setAbout.addView(ViewTools.createTextCard(this, getString(R.string.set_about_active), () -> startActivity(new Intent(this, ActiveActivity.class))).getRoot()); + activitySetBinding.setAbout.addView(ViewTools.createTextCard(this, getString(R.string.set_about_website), () -> PublicTools.startUrl(this, "https://gitee.com/mingzhixianweb/easycontrol")).getRoot()); + activitySetBinding.setAbout.addView(ViewTools.createTextCard(this, getString(R.string.set_about_privacy), () -> PublicTools.startUrl(this, "https://gitee.com/mingzhixianweb/easycontrol/blob/master/PRIVACY.md")).getRoot()); + activitySetBinding.setAbout.addView(ViewTools.createTextCard(this, getString(R.string.set_about_version) + BuildConfig.VERSION_NAME, () -> PublicTools.startUrl(this, "https://gitee.com/mingzhixianweb/easycontrol/releases/latest")).getRoot()); } // 设置按钮监听 private void setButtonListener() { - setActivity.backButton.setOnClickListener(v -> finish()); - } - - // 进入详细设置页面 - private void enterDetailSet(String type) { - Intent tmpIntent = new Intent(this, SetDetailActivity.class); - tmpIntent.putExtra("type", type); - startActivity(tmpIntent); + activitySetBinding.backButton.setOnClickListener(v -> finish()); } } diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/SetDetailActivity.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/SetDetailActivity.java deleted file mode 100644 index c7946c69..00000000 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/SetDetailActivity.java +++ /dev/null @@ -1,96 +0,0 @@ -package top.saymzx.easycontrol.app; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.widget.Toast; - -import java.util.Objects; - -import top.saymzx.easycontrol.app.databinding.ActivitySetDetailBinding; -import top.saymzx.easycontrol.app.entity.AppData; -import top.saymzx.easycontrol.app.helper.PublicTools; -import top.saymzx.easycontrol.app.helper.ViewTools; - -public class SetDetailActivity extends Activity { - private ActivitySetDetailBinding setDetailActivity; - - @Override - protected void onCreate(Bundle savedInstanceState) { - ViewTools.setStatusAndNavBar(this); - ViewTools.setLocale(this); - setDetailActivity = ActivitySetDetailBinding.inflate(this.getLayoutInflater()); - setContentView(setDetailActivity.getRoot()); - setButtonListener(); - // 检查类型 - String type = getIntent().getStringExtra("type"); - if (Objects.equals(type, "default")) drawDefault(); - else if (Objects.equals(type, "onStart")) drawOnStart(); - else if (Objects.equals(type, "onConnect")) drawOnConnect(); - else if (Objects.equals(type, "onClose")) drawOnClose(); - else if (Objects.equals(type, "connecting")) drawConnecting(); - else if (Objects.equals(type, "adbKey")) drawAdbKey(); - else if (Objects.equals(type, "about")) drawAbout(); - super.onCreate(savedInstanceState); - } - - // 设置按钮监听 - private void setButtonListener() { - setDetailActivity.backButton.setOnClickListener(v -> finish()); - } - - // 绘制默认参数 - private void drawDefault() { - ViewTools.createDeviceOptionSet(this, setDetailActivity.setDetail, null); - } - - // 绘制启动时操作 - private void drawOnStart() { - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_back_after_start_default_on_start), getString(R.string.set_auto_back_after_start_default_on_start_detail), AppData.setting.getAutoBackOnStart(), isChecked -> AppData.setting.setAutoBackOnStart(isChecked)).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createTextCard(this, getString(R.string.set_auto_clear_default), () -> { - AppData.setting.setDefaultDevice(""); - Toast.makeText(this, getString(R.string.set_auto_clear_default_code), Toast.LENGTH_SHORT).show(); - }).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_scan_address_on_start), getString(R.string.set_auto_scan_address_on_start_detail), AppData.setting.getAutoScanAddressOnStart(), isChecked -> AppData.setting.setAutoScanAddressOnStart(isChecked)).getRoot()); - } - - // 绘制连接时操作 - private void drawOnConnect() { - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_wake_on_connect), getString(R.string.set_auto_wake_on_connect_detail), AppData.setting.getWakeOnConnect(), isChecked -> AppData.setting.setWakeOnConnect(isChecked)).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_lightoff_on_connect), getString(R.string.set_auto_lightoff_on_connect_detail), AppData.setting.getLightOffOnConnect(), isChecked -> AppData.setting.setLightOffOnConnect(isChecked)).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_show_nav_bar_on_connect), getString(R.string.set_auto_show_nav_bar_on_connect_detail), AppData.setting.getShowNavBarOnConnect(), isChecked -> AppData.setting.setShowNavBarOnConnect(isChecked)).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_change_to_full_on_connect), getString(R.string.set_auto_change_to_full_on_connect_detail), AppData.setting.getChangeToFullOnConnect(), isChecked -> AppData.setting.setChangeToFullOnConnect(isChecked)).getRoot()); - } - - // 绘制断开时操作 - private void drawOnClose() { - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_lock_on_close), getString(R.string.set_auto_lock_on_close_detail), AppData.setting.getLockOnClose(), isChecked -> AppData.setting.setLockOnClose(isChecked)).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_light_on_close), getString(R.string.set_auto_light_on_close_detail), AppData.setting.getLightOnClose(), isChecked -> AppData.setting.setLightOnClose(isChecked)).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_reconnect_on_close), getString(R.string.set_auto_reconnect_on_close_detail), AppData.setting.getReconnectOnClose(), isChecked -> AppData.setting.setReconnectOnClose(isChecked)).getRoot()); - } - - // 绘制界面显示 - private void drawConnecting() { - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_small_to_mini_on_outside), getString(R.string.set_auto_small_to_mini_on_outside_detail), AppData.setting.getSmallToMiniOnOutside(), isChecked -> AppData.setting.setSmallToMiniOnOutside(isChecked)).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_full_to_mini_on_exit), getString(R.string.set_auto_full_to_mini_on_exit_detail), AppData.setting.getFullToMiniOnExit(), isChecked -> AppData.setting.setFullToMiniOnExit(isChecked)).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createSwitchCard(this, getString(R.string.set_auto_mini_recover_on_timeout), getString(R.string.set_auto_mini_recover_on_timeout_detail), AppData.setting.getMiniRecoverOnTimeout(), isChecked -> AppData.setting.setMiniRecoverOnTimeout(isChecked)).getRoot()); - } - - // 绘制密钥相关操作 - private void drawAdbKey() { - setDetailActivity.setDetail.addView(ViewTools.createTextCard(this, getString(R.string.set_other_custom_key), () -> startActivity(new Intent(this, AdbKeyActivity.class))).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createTextCard(this, getString(R.string.set_other_clear_key), () -> { - AppData.keyPair = PublicTools.reGenerateAdbKeyPair(); - Toast.makeText(this, getString(R.string.set_other_clear_key_code), Toast.LENGTH_SHORT).show(); - }).getRoot()); - } - - // 绘制关于 - private void drawAbout() { - setDetailActivity.setDetail.addView(ViewTools.createTextCard(this, getString(R.string.set_about_active), () -> startActivity(new Intent(this, ActiveActivity.class))).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createTextCard(this, getString(R.string.set_about_website), () -> PublicTools.startUrl(this, "https://gitee.com/mingzhixianweb/easycontrol")).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createTextCard(this, getString(R.string.set_about_how_to_use), () -> PublicTools.startUrl(this, "https://gitee.com/mingzhixianweb/easycontrol/blob/master/HOW_TO_USE.md")).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createTextCard(this, getString(R.string.set_about_privacy), () -> PublicTools.startUrl(this, "https://gitee.com/mingzhixianweb/easycontrol/blob/master/PRIVACY.md")).getRoot()); - setDetailActivity.setDetail.addView(ViewTools.createTextCard(this, getString(R.string.set_about_version) + BuildConfig.VERSION_NAME, () -> PublicTools.startUrl(this, "https://gitee.com/mingzhixianweb/easycontrol/releases")).getRoot()); - } -} \ No newline at end of file diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ClientController.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ClientController.java index d8e1a2f6..782ff7d3 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ClientController.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ClientController.java @@ -65,8 +65,9 @@ public ClientController(Device device, ClientStream clientStream, MyInterface.My // 启动界面 handleControll(device.uuid, device.changeToFullOnConnect ? "changeToFull" : "changeToSmall", null); // 运行启动时操作 - if (AppData.setting.getWakeOnConnect()) handleControll(device.uuid, "buttonWake", null); - if (AppData.setting.getLightOffOnConnect()) handler.postDelayed(() -> handleControll(device.uuid, "buttonLightOff", null), 2000); + if (device.customResolutionOnConnect) handleControll(device.uuid, "writeByteBuffer", ControlPacket.createChangeResolutionEvent(device.customResolutionWidth, device.customResolutionHeight)); + if (device.wakeOnConnect) handleControll(device.uuid, "buttonWake", null); + if (device.lightOffOnConnect) handler.postDelayed(() -> handleControll(device.uuid, "buttonLightOff", null), 2000); } public static void handleControll(String uuid, String action, ByteBuffer byteBuffer) { @@ -75,12 +76,6 @@ public static void handleControll(String uuid, String action, ByteBuffer byteBuf clientController.handler.post(() -> handleAction(clientController, action, byteBuffer)); } - public static void handleControllNow(String uuid, String action, ByteBuffer byteBuffer) { - ClientController clientController = allController.get(uuid); - if (clientController == null) return; - handleAction(clientController, action, byteBuffer); - } - private static void handleAction(ClientController clientController, String action, ByteBuffer byteBuffer) { try { if (action.equals("changeToSmall")) clientController.changeToSmall(); @@ -106,7 +101,7 @@ private static void handleAction(ClientController clientController, String actio else if (action.equals("runShell")) clientController.runShell(byteBuffer); else if (action.equals("setClipBoard")) clientController.setClipBoard(byteBuffer); } catch (Exception ignored) { - clientController.close(AppData.applicationContext.getString(R.string.error_stream_closed)); + clientController.close(AppData.applicationContext.getString(R.string.toast_stream_closed)); } } @@ -136,18 +131,16 @@ public static TextureView getTextureView(String uuid) { return clientController.textureView; } - private synchronized void changeToFull() throws Exception { + private synchronized void changeToFull() { hide(); Intent intent = new Intent(AppData.mainActivity, FullActivity.class); intent.putExtra("uuid", device.uuid); AppData.mainActivity.startActivity(intent); - if (device.setResolution) clientStream.writeToMain(ControlPacket.createChangeSizeEvent(FullActivity.getResolution())); } - private synchronized void changeToSmall() throws Exception { + private synchronized void changeToSmall() { hide(); AppData.uiHandler.post(smallView::show); - if (device.setResolution) clientStream.writeToMain(ControlPacket.createChangeSizeEvent(SmallView.getResolution())); } private synchronized void changeToMini(ByteBuffer byteBuffer) { @@ -166,14 +159,14 @@ private void close(String error) { if (isClose) return; isClose = true; hide(); - handlerThread.interrupt(); // 运行断开时操作 - if (AppData.setting.getLockOnClose()) handleControllNow(device.uuid, "buttonLock", null); + if (device.lockOnClose) handleControll(device.uuid, "buttonLock", null); // 开启了自动锁定,就没必要发送打开背光了 - else if (AppData.setting.getLightOnClose()) handleControllNow(device.uuid, "buttonLight", null); - if (error != null && device.isNormalDevice() && AppData.setting.getReconnectOnClose()) new Client(device); + else if (device.lightOnClose) handleControll(device.uuid, "buttonLight", null); + if (error != null && device.isNetworkDevice() && device.reconnectOnClose) new Client(device); // 打印日志 if (error != null) PublicTools.logToast("controller", error, true); + handlerThread.interrupt(); allController.remove(device.uuid); if (surfaceTexture != null) surfaceTexture.release(); handle.run(false); diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ClientStream.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ClientStream.java index 7dc0f982..22b7ca9e 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ClientStream.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ClientStream.java @@ -6,6 +6,7 @@ import java.io.DataInputStream; import java.io.IOException; import java.io.OutputStream; +import java.net.InetSocketAddress; import java.net.Socket; import java.nio.ByteBuffer; @@ -43,7 +44,7 @@ public ClientStream(Device device, UsbDevice usbDevice, MyInterface.MyFunctionBo Thread timeOutThread = new Thread(() -> { try { Thread.sleep(10 * 1000); - PublicTools.logToast("stream", AppData.applicationContext.getString(R.string.error_timeout), true); + PublicTools.logToast("stream", AppData.applicationContext.getString(R.string.toast_timeout), true); handle.run(false); if (connectThread != null) connectThread.interrupt(); } catch (InterruptedException ignored) { @@ -86,7 +87,7 @@ private void startServer(Device device) throws Exception { + " isAudio=" + (device.isAudio ? 1 : 0) + " maxSize=" + device.maxSize + " maxFps=" + device.maxFps + " maxVideoBit=" + device.maxVideoBit - + " keepAwake=" + (AppData.setting.getKeepAwake() ? 1 : 0) + + " keepAwake=" + (device.keepWakeOnRunning ? 1 : 0) + " supportH265=" + ((device.useH265 && supportH265) ? 1 : 0) + " supportOpus=" + (supportOpus ? 1 : 0) + " \n").getBytes())); } @@ -95,18 +96,28 @@ private void startServer(Device device) throws Exception { private void connectServer(Pair address) throws Exception { Thread.sleep(50); int reTry = 60; + long startTime = System.currentTimeMillis(); if (address != null) { reTry /= 2; for (int i = 0; i < reTry; i++) { try { - if (mainSocket == null) mainSocket = new Socket(address.first, 25166); - if (videoSocket == null) videoSocket = new Socket(address.first, 25166); + if (mainSocket == null) { + mainSocket = new Socket(); + mainSocket.connect(new InetSocketAddress(address.first, 25166), 1000); + } + if (videoSocket == null) { + videoSocket = new Socket(); + videoSocket.connect(new InetSocketAddress(address.first, 25166), 1000); + } mainOutputStream = mainSocket.getOutputStream(); mainDataInputStream = new DataInputStream(mainSocket.getInputStream()); videoDataInputStream = new DataInputStream(videoSocket.getInputStream()); connectDirect = true; return; } catch (Exception ignored) { + // 此处检查是因为代码是靠连接错误约束时间的,但有些设备为了安全,在端口没有开启的情况下不会回复reset错误,而是不回复,导致无法检测错误,无法约束时间 + // 如果超时,直接跳出循环 + if (System.currentTimeMillis() - startTime >= 5000) reTry = 60; Thread.sleep(50); } } @@ -122,7 +133,7 @@ private void connectServer(Pair address) throws Exception { Thread.sleep(50); } } - throw new Exception(AppData.applicationContext.getString(R.string.error_connect_server)); + throw new Exception(AppData.applicationContext.getString(R.string.toast_connect_server)); } public void runShell(String cmd) throws Exception { diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ControlPacket.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ControlPacket.java index 6a323c79..3457a221 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ControlPacket.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/ControlPacket.java @@ -63,7 +63,7 @@ public static ByteBuffer createKeepAlive() { } // 修改分辨率事件 - public static ByteBuffer createChangeSizeEvent(float newSize) { + public static ByteBuffer createChangeResolutionEvent(float newSize) { ByteBuffer byteBuffer = ByteBuffer.allocate(5); byteBuffer.put((byte) 5); byteBuffer.putFloat(newSize); @@ -71,6 +71,16 @@ public static ByteBuffer createChangeSizeEvent(float newSize) { return byteBuffer; } + // 修改分辨率事件 + public static ByteBuffer createChangeResolutionEvent(int width, int height) { + ByteBuffer byteBuffer = ByteBuffer.allocate(9); + byteBuffer.put((byte) 9); + byteBuffer.putInt(width); + byteBuffer.putInt(height); + byteBuffer.flip(); + return byteBuffer; + } + // 旋转请求事件 public static ByteBuffer createRotateEvent() { return ByteBuffer.wrap(new byte[]{6}); diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/decode/VideoDecode.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/decode/VideoDecode.java index 39899c32..5f467e75 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/decode/VideoDecode.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/decode/VideoDecode.java @@ -4,7 +4,6 @@ import android.media.MediaFormat; import android.os.Build; import android.os.Handler; -import android.util.Log; import android.util.Pair; import android.view.Surface; diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/FullActivity.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/FullActivity.java index 08190d27..546f205b 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/FullActivity.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/FullActivity.java @@ -9,10 +9,8 @@ import android.hardware.SensorManager; import android.os.Bundle; import android.text.InputType; -import android.util.DisplayMetrics; import android.view.KeyEvent; import android.view.View; -import android.widget.Toast; import java.nio.ByteBuffer; @@ -28,29 +26,29 @@ public class FullActivity extends Activity implements SensorEventListener { private boolean isClose = false; private Device device; - private ActivityFullBinding fullActivity; + private ActivityFullBinding activityFullBinding; private boolean autoRotate; private boolean light = true; @Override protected void onCreate(Bundle savedInstanceState) { ViewTools.setFullScreen(this); - fullActivity = ActivityFullBinding.inflate(this.getLayoutInflater()); - setContentView(fullActivity.getRoot()); + activityFullBinding = ActivityFullBinding.inflate(this.getLayoutInflater()); + setContentView(activityFullBinding.getRoot()); device = ClientController.getDevice(getIntent().getStringExtra("uuid")); if (device == null) return; ClientController.setFullView(device.uuid, this); // 初始化 - fullActivity.barView.setVisibility(View.GONE); - setNavBarHide(AppData.setting.getShowNavBarOnConnect()); + activityFullBinding.barView.setVisibility(View.GONE); + setNavBarHide(device.showNavBarOnConnect); autoRotate = AppData.setting.getAutoRotate(); - fullActivity.buttonAutoRotate.setImageResource(autoRotate ? R.drawable.un_rotate : R.drawable.rotate); + activityFullBinding.buttonAutoRotate.setImageResource(autoRotate ? R.drawable.un_rotate : R.drawable.rotate); // 按键监听 setButtonListener(); setKeyEvent(); // 更新textureView - fullActivity.textureViewLayout.addView(ClientController.getTextureView(device.uuid), 0); - fullActivity.textureViewLayout.post(() -> updateMaxSize(fullActivity.textureViewLayout.getMeasuredWidth(), fullActivity.textureViewLayout.getMeasuredHeight())); + activityFullBinding.textureViewLayout.addView(ClientController.getTextureView(device.uuid), 0); + activityFullBinding.textureViewLayout.post(this::updateMaxSize); // 页面自动旋转 AppData.sensorManager.registerListener(this, AppData.sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); super.onCreate(savedInstanceState); @@ -59,91 +57,86 @@ protected void onCreate(Bundle savedInstanceState) { @Override protected void onPause() { AppData.sensorManager.unregisterListener(this); - if (isChangingConfigurations()) fullActivity.textureViewLayout.removeView(ClientController.getTextureView(device.uuid)); - else if (!isClose) ClientController.handleControll(device.uuid, AppData.setting.getFullToMiniOnExit() ? "changeToMini" : "changeToSmall", ByteBuffer.wrap("changeToFull".getBytes())); + if (isChangingConfigurations()) activityFullBinding.textureViewLayout.removeView(ClientController.getTextureView(device.uuid)); + else if (!isClose) ClientController.handleControll(device.uuid, device.fullToMiniOnRunning ? "changeToMini" : "changeToSmall", ByteBuffer.wrap("changeToFull".getBytes())); super.onPause(); } @Override public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) { - fullActivity.textureViewLayout.post(() -> updateMaxSize(fullActivity.textureViewLayout.getMeasuredWidth(), fullActivity.textureViewLayout.getMeasuredHeight())); + activityFullBinding.textureViewLayout.post(this::updateMaxSize); super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig); } @Override public void onBackPressed() { - Toast.makeText(this, getString(R.string.error_refused_back), Toast.LENGTH_SHORT).show(); } - private void updateMaxSize(int w, int h) { + private void updateMaxSize() { + int width = activityFullBinding.textureViewLayout.getMeasuredWidth(); + int height = activityFullBinding.textureViewLayout.getMeasuredHeight(); ByteBuffer byteBuffer = ByteBuffer.allocate(8); - byteBuffer.putInt(w); - byteBuffer.putInt(h); + byteBuffer.putInt(width); + byteBuffer.putInt(height); byteBuffer.flip(); ClientController.handleControll(device.uuid, "updateMaxSize", byteBuffer); + if (!device.customResolutionOnConnect && device.changeResolutionOnRunning) ClientController.handleControll(device.uuid, "writeByteBuffer", ControlPacket.createChangeResolutionEvent((float) width / height)); } public void hide() { try { isClose = true; - fullActivity.textureViewLayout.removeView(ClientController.getTextureView(device.uuid)); + activityFullBinding.textureViewLayout.removeView(ClientController.getTextureView(device.uuid)); finish(); } catch (Exception ignored) { } } - // 获取去除底部操作栏后的屏幕大小,用于修改分辨率使用 - public static float getResolution() { - DisplayMetrics screenSize = PublicTools.getScreenSize(); - int min = Math.min(screenSize.widthPixels, screenSize.heightPixels); - int max = Math.max(screenSize.widthPixels, screenSize.heightPixels); - return (float) min / (float) (max - PublicTools.dp2px(35f)); - } - // 设置按钮监听 private void setButtonListener() { - fullActivity.buttonRotate.setOnClickListener(v -> ClientController.handleControll(device.uuid, "buttonRotate", null)); - fullActivity.buttonBack.setOnClickListener(v -> ClientController.handleControll(device.uuid, "buttonBack", null)); - fullActivity.buttonHome.setOnClickListener(v -> ClientController.handleControll(device.uuid, "buttonHome", null)); - fullActivity.buttonSwitch.setOnClickListener(v -> ClientController.handleControll(device.uuid, "buttonSwitch", null)); - fullActivity.buttonNavBar.setOnClickListener(v -> { - setNavBarHide(fullActivity.navBar.getVisibility() == View.GONE); + activityFullBinding.buttonRotate.setOnClickListener(v -> ClientController.handleControll(device.uuid, "buttonRotate", null)); + activityFullBinding.buttonBack.setOnClickListener(v -> ClientController.handleControll(device.uuid, "buttonBack", null)); + activityFullBinding.buttonHome.setOnClickListener(v -> ClientController.handleControll(device.uuid, "buttonHome", null)); + activityFullBinding.buttonSwitch.setOnClickListener(v -> ClientController.handleControll(device.uuid, "buttonSwitch", null)); + activityFullBinding.buttonNavBar.setOnClickListener(v -> { + setNavBarHide(activityFullBinding.navBar.getVisibility() == View.GONE); changeBarView(); }); - fullActivity.buttonMini.setOnClickListener(v -> ClientController.handleControll(device.uuid, "changeToMini", null)); - fullActivity.buttonSmall.setOnClickListener(v -> ClientController.handleControll(device.uuid, "changeToSmall", null)); - fullActivity.buttonClose.setOnClickListener(v -> ClientController.handleControll(device.uuid, "close", null)); - fullActivity.buttonLight.setOnClickListener(v -> { + activityFullBinding.buttonMini.setOnClickListener(v -> ClientController.handleControll(device.uuid, "changeToMini", null)); + activityFullBinding.buttonSmall.setOnClickListener(v -> ClientController.handleControll(device.uuid, "changeToSmall", null)); + activityFullBinding.buttonClose.setOnClickListener(v -> ClientController.handleControll(device.uuid, "close", null)); + activityFullBinding.buttonLight.setOnClickListener(v -> { light = !light; - fullActivity.buttonLight.setImageResource(light ? R.drawable.lightbulb_off : R.drawable.lightbulb); + activityFullBinding.buttonLight.setImageResource(light ? R.drawable.lightbulb_off : R.drawable.lightbulb); ClientController.handleControll(device.uuid, light ? "buttonLight" : "buttonLightOff", null); changeBarView(); }); - fullActivity.buttonPower.setOnClickListener(v -> { + activityFullBinding.buttonPower.setOnClickListener(v -> { ClientController.handleControll(device.uuid, "buttonPower", null); changeBarView(); }); - fullActivity.buttonMore.setOnClickListener(v -> changeBarView()); - fullActivity.buttonAutoRotate.setOnClickListener(v -> { + activityFullBinding.buttonMore.setOnClickListener(v -> changeBarView()); + activityFullBinding.buttonAutoRotate.setOnClickListener(v -> { autoRotate = !autoRotate; AppData.setting.setAutoRotate(autoRotate); - fullActivity.buttonAutoRotate.setImageResource(autoRotate ? R.drawable.un_rotate : R.drawable.rotate); + activityFullBinding.buttonAutoRotate.setImageResource(autoRotate ? R.drawable.un_rotate : R.drawable.rotate); changeBarView(); }); } // 导航栏隐藏 private void setNavBarHide(boolean isShow) { - fullActivity.navBar.setVisibility(isShow ? View.VISIBLE : View.GONE); - fullActivity.buttonNavBar.setImageResource(isShow ? R.drawable.not_equal : R.drawable.equals); + activityFullBinding.navBar.setVisibility(isShow ? View.VISIBLE : View.GONE); + activityFullBinding.buttonNavBar.setImageResource(isShow ? R.drawable.not_equal : R.drawable.equals); + activityFullBinding.textureViewLayout.post(this::updateMaxSize); } private void changeBarView() { - boolean toShowView = fullActivity.barView.getVisibility() == View.GONE; + boolean toShowView = activityFullBinding.barView.getVisibility() == View.GONE; boolean isLandscape = lastOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || lastOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; - ViewTools.viewAnim(fullActivity.barView, toShowView, 0, PublicTools.dp2px(40f) * (isLandscape ? -1 : 1), (isStart -> { - if (isStart && toShowView) fullActivity.barView.setVisibility(View.VISIBLE); - else if (!isStart && !toShowView) fullActivity.barView.setVisibility(View.GONE); + ViewTools.viewAnim(activityFullBinding.barView, toShowView, 0, PublicTools.dp2px(40f) * (isLandscape ? -1 : 1), (isStart -> { + if (isStart && toShowView) activityFullBinding.barView.setVisibility(View.VISIBLE); + else if (!isStart && !toShowView) activityFullBinding.barView.setVisibility(View.GONE); })); } @@ -175,9 +168,9 @@ public void onAccuracyChanged(Sensor sensor, int i) { // 设置键盘监听 private void setKeyEvent() { - fullActivity.editText.requestFocus(); - fullActivity.editText.setInputType(InputType.TYPE_NULL); - fullActivity.editText.setOnKeyListener((v, keyCode, event) -> { + activityFullBinding.editText.requestFocus(); + activityFullBinding.editText.setInputType(InputType.TYPE_NULL); + activityFullBinding.editText.setOnKeyListener((v, keyCode, event) -> { if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_UP && keyCode != KeyEvent.KEYCODE_VOLUME_DOWN) { ClientController.handleControll(device.uuid, "writeByteBuffer", ControlPacket.createKeyEvent(event.getKeyCode(), event.getMetaState())); return true; diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/MiniView.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/MiniView.java index c15c2c29..a88048c1 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/MiniView.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/MiniView.java @@ -21,7 +21,6 @@ public class MiniView { private final Device device; - private final boolean miniRecoverOnTimeout; private Thread timeoutListenerThread; private long lastTouchTIme = 0; @@ -37,7 +36,6 @@ public class MiniView { public MiniView(Device device) { this.device = device; - miniRecoverOnTimeout = AppData.setting.getMiniRecoverOnTimeout(); miniViewParams.gravity = Gravity.START | Gravity.TOP; miniViewParams.x = 0; // 设置监听控制 @@ -46,13 +44,13 @@ public MiniView(Device device) { } public void show(ByteBuffer byteBuffer) { - miniViewParams.y = device.mini_y; + miniViewParams.y = device.miniY; // 显示 ViewTools.viewAnim(miniView.getRoot(), true, PublicTools.dp2px(-40f), 0, (isStart -> { if (isStart) AppData.windowManager.addView(miniView.getRoot(), miniViewParams); })); // 超时检测 - if (miniRecoverOnTimeout && byteBuffer != null) { + if (device.miniTimeoutOnRunning && byteBuffer != null) { lastTouchTIme = System.currentTimeMillis(); timeoutListenerThread = new Thread(() -> timeoutListener(new String(byteBuffer.array()))); timeoutListenerThread.start(); @@ -100,7 +98,7 @@ private void setBarListener() { } case MotionEvent.ACTION_MOVE: { miniViewParams.y = oldYy.get() + (int) event.getRawY() - yy.get(); - device.mini_y = miniViewParams.y; + device.miniY = miniViewParams.y; AppData.windowManager.updateViewLayout(miniView.getRoot(), miniViewParams); break; } diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/SmallView.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/SmallView.java index afd1f82c..b6cf4ac1 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/SmallView.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/client/view/SmallView.java @@ -52,7 +52,7 @@ public SmallView(Device device) { this.device = device; smallViewParams.gravity = Gravity.START | Gravity.TOP; // 设置默认导航栏状态 - setNavBarHide(AppData.setting.getShowNavBarOnConnect()); + setNavBarHide(device.showNavBarOnConnect); // 设置监听控制 setFloatVideoListener(); setReSizeListener(); @@ -67,9 +67,11 @@ public SmallView(Device device) { public void show() { // 初始化 smallView.barView.setVisibility(View.GONE); - smallViewParams.x = device.small_x; - smallViewParams.y = device.small_y; - updateMaxSize(device.small_length, device.small_length); + smallViewParams.x = device.smallX; + smallViewParams.y = device.smallY; + updateMaxSize(device.smallLength, device.smallLength); + // 自定义分辨率(2:1) + if (!device.customResolutionOnConnect && device.changeResolutionOnRunning) ClientController.handleControll(device.uuid, "writeByteBuffer", ControlPacket.createChangeResolutionEvent(0.5f)); // 显示 AppData.windowManager.addView(smallView.getRoot(), smallViewParams); smallView.textureViewLayout.addView(ClientController.getTextureView(device.uuid), 0); @@ -86,18 +88,12 @@ public void hide() { } } - // 获取默认宽高比,用于修改分辨率使用 - public static float getResolution() { - return 0.55f; - } - // 设置焦点监听 @SuppressLint("ClickableViewAccessibility") private void setFloatVideoListener() { - boolean smallToMiniOnOutside = AppData.setting.getSmallToMiniOnOutside(); smallView.getRoot().setOnTouchHandle(event -> { if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { - if (smallToMiniOnOutside) ClientController.handleControll(device.uuid, "changeToMini", ByteBuffer.wrap("changeToSmall".getBytes())); + if (device.smallToMiniOnRunning) ClientController.handleControll(device.uuid, "changeToMini", ByteBuffer.wrap("changeToSmall".getBytes())); else if (smallViewParams.flags != LayoutParamsFlagNoFocus) { smallView.editText.clearFocus(); smallViewParams.flags = LayoutParamsFlagNoFocus; @@ -196,26 +192,24 @@ private void changeBarView() { @SuppressLint("ClickableViewAccessibility") private void setReSizeListener() { smallView.reSize.setOnTouchListener((v, event) -> { - if (event.getActionMasked() == MotionEvent.ACTION_MOVE) { - int sizeX = (int) (event.getRawX() - smallViewParams.x); - int sizeY = (int) (event.getRawY() - smallViewParams.y); - int length = Math.max(sizeX, sizeY); - updateMaxSize(length, length); - } + int sizeX = (int) (event.getRawX() - smallViewParams.x); + int sizeY = (int) (event.getRawY() - smallViewParams.y); + int length = Math.max(sizeX, sizeY); + updateMaxSize(length, length); return true; }); } private void updateSite(int x, int y) { - device.small_x = x; - device.small_y = y; + device.smallX = x; + device.smallY = y; smallViewParams.x = x; smallViewParams.y = y; AppData.windowManager.updateViewLayout(smallView.getRoot(), smallViewParams); } private void updateMaxSize(int w, int h) { - device.small_length = w; + device.smallLength = w; ByteBuffer byteBuffer = ByteBuffer.allocate(8); byteBuffer.putInt(w); byteBuffer.putInt(h); @@ -252,7 +246,7 @@ public void checkSizeAndSite() { if (width > screenMaxWidth + 200 || height > screenMaxHeight + 200) { int maxLength = Math.min(screenMaxWidth, screenMaxHeight); updateMaxSize(maxLength, maxLength); - updateSite(50, statusBarHeight); + updateSite(0, statusBarHeight); return; } // 检测到位置超出过多 @@ -265,7 +259,7 @@ public void checkSizeAndSite() { @Override public void getOutline(View view, Outline outline) { - outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), AppData.applicationContext.getResources().getDimension(R.dimen.round)); + outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), AppData.applicationContext.getResources().getDimension(R.dimen.cron)); } private static int statusBarHeight = 0; diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/entity/Device.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/entity/Device.java index c547b401..7b44c661 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/entity/Device.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/entity/Device.java @@ -1,68 +1,48 @@ package top.saymzx.easycontrol.app.entity; -import top.saymzx.easycontrol.app.helper.PublicTools; - public class Device { - public static final int TYPE_NORMAL = 1; + public static final int TYPE_NETWORK = 1; public static final int TYPE_LINK = 2; public final String uuid; public final int type; public String name; - public String address; - public boolean isAudio; - public int maxSize; - public int maxFps; - public int maxVideoBit; - public boolean setResolution; - public boolean useH265; - public int small_x; - public static int SMALL_X = 200; - public int small_y; - public static int SMALL_Y = 200; - public int small_length; - public static int SMALL_LENGTH = 800; - public int mini_y; - public static int MINI_Y = 200; - public boolean changeToFullOnConnect; - - public Device(String uuid, - int type, - String name, - String address, - boolean isAudio, - int maxSize, - int maxFps, - int maxVideoBit, - boolean setResolution, - boolean useH265, - int small_x, - int small_y, - int small_length, - int mini_y) { + public String address = ""; + public boolean isAudio = true; + public int maxSize = 1600; + public int maxFps = 60; + public int maxVideoBit = 4; + public boolean useH265 = true; + public boolean connectOnStart = false; + public boolean customResolutionOnConnect = false; + public boolean wakeOnConnect = true; + public boolean lightOffOnConnect = false; + public boolean showNavBarOnConnect = true; + public boolean changeToFullOnConnect = false; + public boolean keepWakeOnRunning = true; + public boolean changeResolutionOnRunning = false; + public boolean smallToMiniOnRunning = false; + public boolean fullToMiniOnRunning = true; + public boolean miniTimeoutOnRunning = false; + public boolean lockOnClose = true; + public boolean lightOnClose = false; + public boolean reconnectOnClose = false; + + public int customResolutionWidth = 1080; + public int customResolutionHeight = 2400; + public int smallX = 200; + public int smallY = 200; + public int smallLength = 800; + public int miniY = 200; + + public Device(String uuid, int type) { this.uuid = uuid; this.type = type; - this.name = name; - this.address = address; - this.isAudio = isAudio; - this.maxSize = maxSize; - this.maxFps = maxFps; - this.maxVideoBit = maxVideoBit; - this.setResolution = setResolution; - this.useH265 = useH265; - this.small_x = small_x; - this.small_y = small_y; - this.small_length = small_length; - this.mini_y = mini_y; - } - - public static Device getDefaultDevice(String uuid, int type) { - if (SMALL_LENGTH == 0) SMALL_LENGTH = PublicTools.dp2px(500f); - return new Device(uuid, type, uuid, "", AppData.setting.getDefaultIsAudio(), AppData.setting.getDefaultMaxSize(), AppData.setting.getDefaultMaxFps(), AppData.setting.getDefaultMaxVideoBit(), AppData.setting.getDefaultSetResolution(), AppData.setting.getDefaultUseH265(), SMALL_X, SMALL_Y, SMALL_LENGTH, MINI_Y); + this.name = uuid; } - public boolean isNormalDevice() { - return type == TYPE_NORMAL; + public boolean isNetworkDevice() { + return type == TYPE_NETWORK; } public boolean isLinkDevice() { diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/entity/Setting.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/entity/Setting.java index 783c5fc5..8a9776eb 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/entity/Setting.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/entity/Setting.java @@ -27,111 +27,12 @@ public void setActiveKey(String value) { editor.apply(); } - public String getDefaultLocale() { - return sharedPreferences.getString("defaultLocale", ""); + public String getLocale() { + return sharedPreferences.getString("locale", ""); } - public void setDefaultLocale(String value) { - editor.putString("defaultLocale", value); - editor.apply(); - } - - public boolean getDefaultIsAudio() { - return sharedPreferences.getBoolean("defaultIsAudio", true); - } - - public void setDefaultIsAudio(boolean value) { - editor.putBoolean("defaultIsAudio", value); - editor.apply(); - } - - public int getDefaultMaxSize() { - return sharedPreferences.getInt("defaultMaxSize", 1600); - } - - public void setDefaultMaxSize(int value) { - editor.putInt("defaultMaxSize", value); - editor.apply(); - } - - public int getDefaultMaxFps() { - return sharedPreferences.getInt("defaultMaxFps", 60); - } - - public void setDefaultMaxFps(int value) { - editor.putInt("defaultMaxFps", value); - editor.apply(); - } - - public int getDefaultMaxVideoBit() { - return sharedPreferences.getInt("defaultMaxVideoBit", 4); - } - - public void setDefaultMaxVideoBit(int value) { - editor.putInt("defaultMaxVideoBit", value); - editor.apply(); - } - - public boolean getDefaultSetResolution() { - return sharedPreferences.getBoolean("defaultSetResolution", false); - } - - public void setDefaultSetResolution(boolean value) { - editor.putBoolean("defaultSetResolution", value); - editor.apply(); - } - - public boolean getDefaultUseH265() { - return sharedPreferences.getBoolean("defaultUseH265", true); - } - - public void setDefaultUseH265(boolean value) { - editor.putBoolean("defaultUseH265", value); - editor.apply(); - } - - public boolean getWakeOnConnect() { - return sharedPreferences.getBoolean("wakeOnConnect", true); - } - - public void setWakeOnConnect(boolean value) { - editor.putBoolean("wakeOnConnect", value); - editor.apply(); - } - - public boolean getLightOffOnConnect() { - return sharedPreferences.getBoolean("lightOffOnConnect", false); - } - - public void setLightOffOnConnect(boolean value) { - editor.putBoolean("lightOffOnConnect", value); - editor.apply(); - } - - public boolean getLockOnClose() { - return sharedPreferences.getBoolean("lockOnClose", true); - } - - public void setLockOnClose(boolean value) { - editor.putBoolean("lockOnClose", value); - editor.apply(); - } - - public boolean getLightOnClose() { - return sharedPreferences.getBoolean("lightOnClose", false); - } - - public void setLightOnClose(boolean value) { - editor.putBoolean("lightOnClose", value); - editor.apply(); - } - - public boolean getReconnectOnClose() { - return sharedPreferences.getBoolean("reconnectOnClose", false); - } - - public void setReconnectOnClose(boolean value) { - editor.putBoolean("reconnectOnClose", value); + public void setLocale(String value) { + editor.putString("locale", value); editor.apply(); } @@ -144,87 +45,6 @@ public void setAutoRotate(boolean value) { editor.apply(); } - public boolean getAutoBackOnStart() { - return sharedPreferences.getBoolean("autoBackOnStart", false); - } - - public void setAutoBackOnStart(boolean value) { - editor.putBoolean("autoBackOnStart", value); - editor.apply(); - } - - public boolean getAutoScanAddressOnStart() { - return sharedPreferences.getBoolean("autoScanAddressStart", false); - } - - public void setAutoScanAddressOnStart(boolean value) { - editor.putBoolean("autoScanAddressStart", value); - editor.apply(); - } - - public boolean getKeepAwake() { - return sharedPreferences.getBoolean("keepAwake", true); - } - - public void setKeepAwake(boolean value) { - editor.putBoolean("keepAwake", value); - editor.apply(); - } - - public boolean getShowNavBarOnConnect() { - return sharedPreferences.getBoolean("showNavBarOnConnect", true); - } - - public void setShowNavBarOnConnect(boolean value) { - editor.putBoolean("showNavBarOnConnect", value); - editor.apply(); - } - - public boolean getChangeToFullOnConnect() { - return sharedPreferences.getBoolean("changeToFullOnConnect", false); - } - - public void setChangeToFullOnConnect(boolean value) { - editor.putBoolean("changeToFullOnConnect", value); - editor.apply(); - } - - public boolean getSmallToMiniOnOutside() { - return sharedPreferences.getBoolean("smallToMiniOnOutside", false); - } - - public void setSmallToMiniOnOutside(boolean value) { - editor.putBoolean("smallToMiniOnOutside", value); - editor.apply(); - } - - public boolean getMiniRecoverOnTimeout() { - return sharedPreferences.getBoolean("miniRecoverOnTimeout", false); - } - - public void setMiniRecoverOnTimeout(boolean value) { - editor.putBoolean("miniRecoverOnTimeout", value); - editor.apply(); - } - - public boolean getFullToMiniOnExit() { - return sharedPreferences.getBoolean("fullToMiniOnExit", true); - } - - public void setFullToMiniOnExit(boolean value) { - editor.putBoolean("fullToMiniOnExit", value); - editor.apply(); - } - - public String getDefaultDevice() { - return sharedPreferences.getString("defaultDevice", ""); - } - - public void setDefaultDevice(String value) { - editor.putString("defaultDevice", value); - editor.apply(); - } - public String getLocalUUID() { if (!sharedPreferences.contains("UUID")) { editor.putString("UUID", UUID.randomUUID().toString()); diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/DbHelper.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/DbHelper.java index 5202e6ca..d73e9f13 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/DbHelper.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/DbHelper.java @@ -9,13 +9,12 @@ import java.util.ArrayList; -import top.saymzx.easycontrol.app.entity.AppData; import top.saymzx.easycontrol.app.entity.Device; public class DbHelper extends SQLiteOpenHelper { private static final String dataBaseName = "app.db"; - private static final int version = 14; + private static final int version = 16; private final String tableName = "DevicesDb"; public DbHelper(Context context) { @@ -24,7 +23,38 @@ public DbHelper(Context context) { @Override public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + tableName + " (\n" + "\t uuid text PRIMARY KEY,\n" + "\t type integer,\n" + "\t name text,\n" + "\t address text,\n" + "\t isAudio integer,\n" + "\t maxSize integer,\n" + "\t maxFps integer,\n" + "\t maxVideoBit integer," + "\t setResolution integer," + "\t useH265 integer ," + "\t small_x integer ," + "\t small_y integer ," + "\t small_length integer ," + "\t mini_y integer " + ");"); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("CREATE TABLE " + tableName + " ("); + stringBuilder.append("uuid text PRIMARY KEY,"); + stringBuilder.append("type integer,"); + stringBuilder.append("name text,"); + stringBuilder.append("address text,"); + stringBuilder.append("isAudio integer,"); + stringBuilder.append("maxSize integer,"); + stringBuilder.append("maxFps integer,"); + stringBuilder.append("maxVideoBit integer,"); + stringBuilder.append("useH265 integer,"); + stringBuilder.append("connectOnStart integer,"); + stringBuilder.append("customResolutionOnConnect integer,"); + stringBuilder.append("wakeOnConnect integer,"); + stringBuilder.append("lightOffOnConnect integer,"); + stringBuilder.append("showNavBarOnConnect integer,"); + stringBuilder.append("changeToFullOnConnect integer,"); + stringBuilder.append("keepWakeOnRunning integer,"); + stringBuilder.append("changeResolutionOnRunning integer,"); + stringBuilder.append("smallToMiniOnRunning integer,"); + stringBuilder.append("fullToMiniOnRunning integer,"); + stringBuilder.append("miniTimeoutOnRunning integer,"); + stringBuilder.append("lockOnClose integer,"); + stringBuilder.append("lightOnClose integer,"); + stringBuilder.append("reconnectOnClose integer,"); + stringBuilder.append("customResolutionWidth integer,"); + stringBuilder.append("customResolutionHeight integer,"); + stringBuilder.append("smallX integer,"); + stringBuilder.append("smallY integer,"); + stringBuilder.append("smallLength integer,"); + stringBuilder.append("miniY integer);"); + db.execSQL(stringBuilder.toString()); } @SuppressLint("Range") @@ -75,12 +105,12 @@ public void insert(Device device) { // 更新 public void update(Device device) { - getWritableDatabase().update(tableName, getValues(device), "uuid=?", new String[]{String.valueOf(device.uuid)}); + getWritableDatabase().update(tableName, getValues(device), "uuid=?", new String[]{device.uuid}); } // 删除 public void delete(Device device) { - getWritableDatabase().delete(tableName, "uuid=?", new String[]{String.valueOf(device.uuid)}); + getWritableDatabase().delete(tableName, "uuid=?", new String[]{device.uuid}); } private ContentValues getValues(Device device) { @@ -88,37 +118,150 @@ private ContentValues getValues(Device device) { values.put("uuid", device.uuid); values.put("type", device.type); values.put("name", device.name); - values.put("isAudio", device.isAudio); values.put("address", device.address); + values.put("isAudio", device.isAudio); values.put("maxSize", device.maxSize); values.put("maxFps", device.maxFps); values.put("maxVideoBit", device.maxVideoBit); - values.put("setResolution", device.setResolution); - values.put("useH265", device.useH265); - values.put("small_x", device.small_x); - values.put("small_y", device.small_y); - values.put("small_length", device.small_length); - values.put("mini_y", device.mini_y); + values.put("useH265", device.useH265 ? 1 : 0); + values.put("connectOnStart", device.connectOnStart ? 1 : 0); + values.put("customResolutionOnConnect", device.customResolutionOnConnect ? 1 : 0); + values.put("wakeOnConnect", device.wakeOnConnect ? 1 : 0); + values.put("lightOffOnConnect", device.lightOffOnConnect ? 1 : 0); + values.put("showNavBarOnConnect", device.showNavBarOnConnect ? 1 : 0); + values.put("changeToFullOnConnect", device.changeToFullOnConnect ? 1 : 0); + values.put("keepWakeOnRunning", device.keepWakeOnRunning ? 1 : 0); + values.put("changeResolutionOnRunning", device.changeResolutionOnRunning ? 1 : 0); + values.put("smallToMiniOnRunning", device.smallToMiniOnRunning ? 1 : 0); + values.put("fullToMiniOnRunning", device.fullToMiniOnRunning ? 1 : 0); + values.put("miniTimeoutOnRunning", device.miniTimeoutOnRunning ? 1 : 0); + values.put("lockOnClose", device.lockOnClose ? 1 : 0); + values.put("lightOnClose", device.lightOnClose ? 1 : 0); + values.put("reconnectOnClose", device.reconnectOnClose ? 1 : 0); + values.put("customResolutionWidth", device.customResolutionWidth); + values.put("customResolutionHeight", device.customResolutionHeight); + values.put("smallX", device.smallX); + values.put("smallY", device.smallY); + values.put("smallLength", device.smallLength); + values.put("miniY", device.miniY); return values; } @SuppressLint("Range") private Device getDeviceFormCursor(Cursor cursor) { - return new Device( - cursor.getString(cursor.getColumnIndex("uuid")), - cursor.getInt(cursor.getColumnIndex("type")), - cursor.getString(cursor.getColumnIndex("name")), - cursor.getString(cursor.getColumnIndex("address")), - cursor.getInt(cursor.getColumnIndex("isAudio")) == 1, - cursor.getInt(cursor.getColumnIndex("maxSize")), - cursor.getInt(cursor.getColumnIndex("maxFps")), - cursor.getInt(cursor.getColumnIndex("maxVideoBit")), - cursor.getInt(cursor.getColumnIndex("setResolution")) == 1, - cursor.getColumnIndex("useH265") == -1 ? AppData.setting.getDefaultUseH265() : cursor.getInt(cursor.getColumnIndex("useH265")) == 1, - cursor.getColumnIndex("small_x") == -1 ? Device.SMALL_X : cursor.getInt(cursor.getColumnIndex("small_x")), - cursor.getColumnIndex("small_y") == -1 ? Device.SMALL_Y : cursor.getInt(cursor.getColumnIndex("small_y")), - cursor.getColumnIndex("small_length") == -1 ? Device.SMALL_LENGTH : cursor.getInt(cursor.getColumnIndex("small_length")), - cursor.getColumnIndex("mini_y") == -1 ? Device.MINI_Y : cursor.getInt(cursor.getColumnIndex("mini_y")) - ); + Device device = new Device(cursor.getString(cursor.getColumnIndex("uuid")), cursor.getInt(cursor.getColumnIndex("type"))); + for (int i = 0; i < cursor.getColumnCount(); i++) { + switch (cursor.getColumnName(i)) { + case "name": { + device.name = cursor.getString(i); + break; + } + case "address": { + device.address = cursor.getString(i); + break; + } + case "isAudio": { + device.isAudio = cursor.getInt(i) == 1; + break; + } + case "maxSize": { + device.maxSize = cursor.getInt(i); + break; + } + case "maxFps": { + device.maxFps = cursor.getInt(i); + break; + } + case "maxVideoBit": { + device.maxVideoBit = cursor.getInt(i); + break; + } + case "useH265": { + device.useH265 = cursor.getInt(i) == 1; + break; + } + case "connectOnStart": { + device.connectOnStart = cursor.getInt(i) == 1; + break; + } + case "customResolutionOnConnect": { + device.customResolutionOnConnect = cursor.getInt(i) == 1; + break; + } + case "wakeOnConnect": { + device.wakeOnConnect = cursor.getInt(i) == 1; + break; + } + case "lightOffOnConnect": { + device.lightOffOnConnect = cursor.getInt(i) == 1; + break; + } + case "showNavBarOnConnect": { + device.showNavBarOnConnect = cursor.getInt(i) == 1; + break; + } + case "changeToFullOnConnect": { + device.changeToFullOnConnect = cursor.getInt(i) == 1; + break; + } + case "keepWakeOnRunning": { + device.keepWakeOnRunning = cursor.getInt(i) == 1; + break; + } + case "changeResolutionOnRunning": { + device.changeResolutionOnRunning = cursor.getInt(i) == 1; + break; + } + case "smallToMiniOnRunning": { + device.smallToMiniOnRunning = cursor.getInt(i) == 1; + break; + } + case "fullToMiniOnRunning": { + device.fullToMiniOnRunning = cursor.getInt(i) == 1; + break; + } + case "miniTimeoutOnRunning": { + device.miniTimeoutOnRunning = cursor.getInt(i) == 1; + break; + } + case "lockOnClose": { + device.lockOnClose = cursor.getInt(i) == 1; + break; + } + case "lightOnClose": { + device.lightOnClose = cursor.getInt(i) == 1; + break; + } + case "reconnectOnClose": { + device.reconnectOnClose = cursor.getInt(i) == 1; + break; + } + case "customResolutionWidth": { + device.customResolutionWidth = cursor.getInt(i); + break; + } + case "customResolutionHeight": { + device.customResolutionHeight = cursor.getInt(i); + break; + } + case "smallX": { + device.smallX = cursor.getInt(i); + break; + } + case "smallY": { + device.smallY = cursor.getInt(i); + break; + } + case "smallLength": { + device.smallLength = cursor.getInt(i); + break; + } + case "miniY": { + device.miniY = cursor.getInt(i); + break; + } + } + } + return device; } } diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/DeviceListAdapter.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/DeviceListAdapter.java index 239fa6a6..83d5603d 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/DeviceListAdapter.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/DeviceListAdapter.java @@ -1,10 +1,9 @@ package top.saymzx.easycontrol.app.helper; -import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN; - import android.app.Dialog; -import android.content.ClipData; import android.content.Context; +import android.content.Intent; +import android.content.res.ColorStateList; import android.hardware.usb.UsbDevice; import android.view.LayoutInflater; import android.view.View; @@ -15,7 +14,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Objects; +import java.util.Random; +import top.saymzx.easycontrol.app.DeviceDetailActivity; import top.saymzx.easycontrol.app.R; import top.saymzx.easycontrol.app.client.Client; import top.saymzx.easycontrol.app.client.ClientStream; @@ -29,6 +30,10 @@ public class DeviceListAdapter extends BaseAdapter { public final ArrayList devicesList = new ArrayList<>(); public final HashMap linkDevices = new HashMap<>(); private final Context context; + private static final int[] colors = {R.color.color1, R.color.color2, R.color.color3, R.color.color4, R.color.color5, R.color.color6, R.color.color7, R.color.color8}; + + // 生成随机数 + private final Random random = new Random(); public DeviceListAdapter(Context c) { queryDevices(); @@ -59,25 +64,20 @@ public View getView(int i, View view, ViewGroup viewGroup) { } // 获取设备 Device device = devicesList.get(i); - setView(view, device); - return view; - } - - // 创建View - private void setView(View view, Device device) { ItemDevicesItemBinding devicesItemBinding = (ItemDevicesItemBinding) view.getTag(); // 设置卡片值 - devicesItemBinding.deviceIcon.setImageResource(device.isLinkDevice() ? R.drawable.link : R.drawable.wifi); + devicesItemBinding.deviceIconBackground.setBackgroundTintList(ColorStateList.valueOf(context.getResources().getColor(colors[random.nextInt(8)]))); + devicesItemBinding.deviceIcon.setImageResource(device.isNetworkDevice() ? R.drawable.wifi : R.drawable.link); + devicesItemBinding.deviceType.setText(context.getString(device.isNetworkDevice() ? R.string.main_device_type_network : R.string.main_device_type_link)); devicesItemBinding.deviceName.setText(device.name); // 单击事件 - devicesItemBinding.getRoot().setOnClickListener(v -> startDevice(device, AppData.setting.getChangeToFullOnConnect())); - devicesItemBinding.buttonSmall.setOnClickListener(v -> startDevice(device, false)); - devicesItemBinding.buttonFull.setOnClickListener(v -> startDevice(device, true)); + devicesItemBinding.getRoot().setOnClickListener(v -> startDevice(device)); // 长按事件 devicesItemBinding.getRoot().setOnLongClickListener(v -> { onLongClickCard(device); return true; }); + return view; } // 卡片长按事件 @@ -91,7 +91,7 @@ private void onLongClickCard(Device device) { dialog.cancel(); UsbDevice usbDevice = linkDevices.get(device.uuid); if (usbDevice == null) return; - ClientStream.restartOnTcpip(device, usbDevice, result -> AppData.uiHandler.post(() -> Toast.makeText(context, context.getString(result ? R.string.set_device_button_start_wireless_success : R.string.set_device_button_recover_error), Toast.LENGTH_SHORT).show())); + ClientStream.restartOnTcpip(device, usbDevice, result -> AppData.uiHandler.post(() -> Toast.makeText(context, context.getString(result ? R.string.toast_success : R.string.toast_fail), Toast.LENGTH_SHORT).show())); }); } else itemSetDeviceBinding.buttonStartWireless.setVisibility(View.GONE); itemSetDeviceBinding.buttonRecover.setOnClickListener(v -> { @@ -99,22 +99,14 @@ private void onLongClickCard(Device device) { if (device.isLinkDevice()) { UsbDevice usbDevice = linkDevices.get(device.uuid); if (usbDevice == null) return; - ClientStream.runOnceCmd(device, usbDevice, "wm size reset", result -> AppData.uiHandler.post(() -> Toast.makeText(context, context.getString(result ? R.string.set_device_button_recover_success : R.string.set_device_button_recover_error), Toast.LENGTH_SHORT).show())); - } else ClientStream.runOnceCmd(device, null, "wm size reset", result -> AppData.uiHandler.post(() -> Toast.makeText(context, context.getString(result ? R.string.set_device_button_recover_success : R.string.set_device_button_recover_error), Toast.LENGTH_SHORT).show())); - }); - itemSetDeviceBinding.buttonSetDefault.setOnClickListener(v -> { - dialog.cancel(); - if (!device.isNormalDevice()) return; - AppData.setting.setDefaultDevice(device.uuid); - }); - itemSetDeviceBinding.buttonGetUuid.setOnClickListener(v -> { - dialog.cancel(); - AppData.clipBoard.setPrimaryClip(ClipData.newPlainText(MIMETYPE_TEXT_PLAIN, device.uuid)); - Toast.makeText(context, context.getString(R.string.set_device_button_get_uuid_success), Toast.LENGTH_SHORT).show(); + ClientStream.runOnceCmd(device, usbDevice, "wm size reset", result -> AppData.uiHandler.post(() -> Toast.makeText(context, context.getString(result ? R.string.toast_success : R.string.toast_fail), Toast.LENGTH_SHORT).show())); + } else ClientStream.runOnceCmd(device, null, "wm size reset", result -> AppData.uiHandler.post(() -> Toast.makeText(context, context.getString(result ? R.string.toast_success : R.string.toast_fail), Toast.LENGTH_SHORT).show())); }); itemSetDeviceBinding.buttonChange.setOnClickListener(v -> { dialog.cancel(); - ViewTools.createDeviceDetailView(context, device, this).show(); + Intent intent = new Intent(context, DeviceDetailActivity.class); + intent.putExtra("uuid", device.uuid); + context.startActivity(intent); }); itemSetDeviceBinding.buttonDelete.setOnClickListener(v -> { AppData.dbHelper.delete(device); @@ -130,7 +122,7 @@ private void queryDevices() { ArrayList tmp2 = new ArrayList<>(); for (Device device : rawDevices) { if (device.isLinkDevice() && linkDevices.containsKey(device.uuid)) tmp1.add(device); - else if (device.isNormalDevice()) tmp2.add(device); + else if (device.isNetworkDevice()) tmp2.add(device); } devicesList.clear(); devicesList.addAll(tmp1); @@ -138,11 +130,10 @@ private void queryDevices() { } public void startByUUID(String uuid) { - for (Device device : devicesList) if (Objects.equals(device.uuid, uuid)) startDevice(device, AppData.setting.getChangeToFullOnConnect()); + for (Device device : devicesList) if (Objects.equals(device.uuid, uuid)) startDevice(device); } - public void startDevice(Device device, boolean changeToFullOnConnect) { - device.changeToFullOnConnect = changeToFullOnConnect; + public void startDevice(Device device) { if (device.isLinkDevice()) { UsbDevice usbDevice = linkDevices.get(device.uuid); if (usbDevice == null) return; @@ -150,6 +141,10 @@ public void startDevice(Device device, boolean changeToFullOnConnect) { } else new Client(device); } + public void startDefaultDevice() { + for (Device device : devicesList) if (device.connectOnStart) startDevice(device); + } + public void update() { queryDevices(); notifyDataSetChanged(); diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/MyBroadcastReceiver.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/MyBroadcastReceiver.java index 714b279b..29e43cea 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/MyBroadcastReceiver.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/MyBroadcastReceiver.java @@ -11,7 +11,6 @@ import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; import android.os.Build; -import android.view.KeyEvent; import java.nio.ByteBuffer; import java.util.Map; @@ -24,6 +23,7 @@ public class MyBroadcastReceiver extends BroadcastReceiver { private static final String ACTION_USB_PERMISSION = "top.saymzx.easycontrol.app.USB_PERMISSION"; + public static final String ACTION_UPDATE_DEVICE_LIST = "top.saymzx.easycontrol.app.UPDATE_DEVICE_LIST"; private static final String ACTION_CONTROL = "top.saymzx.easycontrol.app.CONTROL"; private static final String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF"; @@ -36,6 +36,7 @@ public void register(Context context) { filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); filter.addAction(ACTION_USB_PERMISSION); + filter.addAction(ACTION_UPDATE_DEVICE_LIST); filter.addAction(ACTION_CONTROL); filter.addAction(ACTION_SCREEN_OFF); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) context.registerReceiver(this, filter, Context.RECEIVER_EXPORTED); @@ -50,6 +51,7 @@ public void unRegister(Context context) { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_SCREEN_OFF.equals(action)) handleScreenOff(); + else if (ACTION_UPDATE_DEVICE_LIST.equals(action)) deviceListAdapter.update(); else if (ACTION_CONTROL.equals(action)) handleControl(context, intent); else handleUSB(context, intent); } @@ -64,13 +66,8 @@ private void handleScreenOff() { private void handleControl(Context context, Intent intent) { String action = intent.getStringExtra("action"); - if (action == null) return; - if (action.equals("startDefault")) { - startDefault(context); - return; - } String uuid = intent.getStringExtra("uuid"); - if (uuid == null) return; + if (action == null || uuid == null) return; if (action.equals("start")) deviceListAdapter.startByUUID(uuid); else if (action.equals("runShell")) { String cmd = intent.getStringExtra("cmd"); @@ -88,20 +85,6 @@ private void handleUSB(Context context, Intent intent) { else if (Objects.equals(action, ACTION_USB_PERMISSION)) if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) onGetUsbPer(usbDevice); } - // 启动默认设备 - public void startDefault(Context context) { - String defaultDevice = AppData.setting.getDefaultDevice(); - if (!defaultDevice.equals("")) { - deviceListAdapter.startByUUID(defaultDevice); - // 返回桌面 - if (AppData.setting.getAutoBackOnStart()) { - Intent home = new Intent(Intent.ACTION_MAIN); - home.addCategory(Intent.CATEGORY_HOME); - context.startActivity(home); - } - } - } - // 检查已连接设备 public void checkConnectedUsb(Context context) { if (AppData.usbManager == null) return; @@ -137,7 +120,7 @@ private void onGetUsbPer(UsbDevice usbDevice) { // 若没有该设备,则新建设备 Device device = AppData.dbHelper.getByUUID(uuid); if (device == null) { - device = Device.getDefaultDevice(uuid, Device.TYPE_LINK); + device = new Device(uuid, Device.TYPE_LINK); AppData.dbHelper.insert(device); } deviceListAdapter.linkDevices.put(uuid, usbDevice); diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/PublicTools.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/PublicTools.java index e1fd5ca5..78f75773 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/PublicTools.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/PublicTools.java @@ -63,10 +63,10 @@ else if (Pattern.matches(".*[a-zA-Z].*", address)) { pattern = "(.*?):(\\d+)"; } Matcher matcher = Pattern.compile(pattern).matcher(address); - if (!matcher.find()) throw new IOException(AppData.applicationContext.getString(R.string.error_address_error)); + if (!matcher.find()) throw new IOException(AppData.applicationContext.getString(R.string.toast_address_error)); String ip = matcher.group(1); String port = matcher.group(2); - if (ip == null || port == null) throw new IOException(AppData.applicationContext.getString(R.string.error_address_error)); + if (ip == null || port == null) throw new IOException(AppData.applicationContext.getString(R.string.toast_address_error)); // 特殊格式 if (type == 2) { if (ip.equals("*gateway*")) ip = getGateway(); @@ -111,8 +111,11 @@ public static String getGateway() { // 获取子网地址 public static String getNetAddress() { + int ip = AppData.wifiManager.getDhcpInfo().gateway; + // 没有wifi时,设置为1.1.1.1 + if (ip == 0) ip = 16843009; // 因为此标识符使用场景有限,为了节省资源,默认地址为24位掩码地址 - return decodeIntToIp(AppData.wifiManager.getDhcpInfo().gateway, 3); + return decodeIntToIp(ip, 3); } // 解析地址 @@ -144,7 +147,7 @@ public static void startUrl(Context context, String url) { intent.setData(Uri.parse(url)); context.startActivity(intent); } catch (Exception ignored) { - Toast.makeText(context, context.getString(R.string.error_no_browser), Toast.LENGTH_SHORT).show(); + Toast.makeText(context, context.getString(R.string.toast_no_browser), Toast.LENGTH_SHORT).show(); } } @@ -203,19 +206,26 @@ public static DisplayMetrics getScreenSize() { // 扫描局域网设备 public static ArrayList scanAddress() { ArrayList scannedAddresses = new ArrayList<>(); - String subnet = getNetAddress(); - ExecutorService executor = Executors.newFixedThreadPool(128); - for (int i = 1; i <= 255; i++) { - String host = subnet + "." + i; - executor.execute(() -> { - try { - Socket socket = new Socket(); - socket.connect(new InetSocketAddress(host, 5555), 1000); - socket.close(); - scannedAddresses.add(host + ":5555"); - } catch (Exception ignored) { + ExecutorService executor = Executors.newFixedThreadPool(256); + ArrayList ipv4List = getIp().first; + for (String ipv4 : ipv4List) { + Matcher matcher = Pattern.compile("(\\d+\\.\\d+\\.\\d+)").matcher(ipv4); + if (matcher.find()) { + String subnet = matcher.group(1); + for (int i = 1; i <= 255; i++) { + String host = subnet + "." + i; + executor.execute(() -> { + try { + Socket socket = new Socket(); + socket.connect(new InetSocketAddress(host, 5555), 800); + socket.close(); + // 标注本机 + scannedAddresses.add(host + ":5555" + (host.equals(ipv4) ? " (" + AppData.applicationContext.getString(R.string.main_scan_device_local) + ")" : "")); + } catch (Exception ignored) { + } + }); } - }); + } } executor.shutdown(); try { diff --git a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/ViewTools.java b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/ViewTools.java index 537a5133..b23822e0 100644 --- a/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/ViewTools.java +++ b/easycontrol/app/src/main/java/top/saymzx/easycontrol/app/helper/ViewTools.java @@ -12,7 +12,6 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.view.ViewPropertyAnimator; import android.view.WindowManager; import android.view.animation.DecelerateInterpolator; @@ -24,14 +23,12 @@ import java.util.Locale; import top.saymzx.easycontrol.app.R; -import top.saymzx.easycontrol.app.databinding.ItemDeviceDetailBinding; import top.saymzx.easycontrol.app.databinding.ItemLoadingBinding; import top.saymzx.easycontrol.app.databinding.ItemSpinnerBinding; import top.saymzx.easycontrol.app.databinding.ItemSwitchBinding; import top.saymzx.easycontrol.app.databinding.ItemTextBinding; import top.saymzx.easycontrol.app.databinding.ModuleDialogBinding; import top.saymzx.easycontrol.app.entity.AppData; -import top.saymzx.easycontrol.app.entity.Device; import top.saymzx.easycontrol.app.entity.MyInterface; public class ViewTools { @@ -58,7 +55,7 @@ public static void setFullScreen(Activity context) { public static void setLocale(Activity context) { Resources resources = context.getResources(); Configuration config = resources.getConfiguration(); - String locale = AppData.setting.getDefaultLocale(); + String locale = AppData.setting.getLocale(); if (locale.equals("")) config.locale = Locale.getDefault(); else if (locale.equals("en")) config.locale = Locale.ENGLISH; else if (locale.equals("zh")) config.locale = Locale.CHINESE; @@ -90,75 +87,6 @@ public static Dialog createDialog(Context context, boolean canCancel, View view) return dialog; } - // 创建新建设备弹窗 - public static Dialog createDeviceDetailView( - Context context, - Device device, - DeviceListAdapter deviceListAdapter - ) { - ItemDeviceDetailBinding itemAddDeviceBinding = ItemDeviceDetailBinding.inflate(LayoutInflater.from(context)); - Dialog dialog = createDialog(context, true, itemAddDeviceBinding.getRoot()); - // 设置值 - itemAddDeviceBinding.name.setText(device.name); - itemAddDeviceBinding.address.setText(device.address); - // 创建View - createDeviceOptionSet(context, itemAddDeviceBinding.options, device); - // 特殊设备不允许修改 - if (!device.isNormalDevice()) itemAddDeviceBinding.address.setEnabled(false); - // 是否显示高级选项 - itemAddDeviceBinding.isOptions.setOnClickListener(v -> itemAddDeviceBinding.options.setVisibility(itemAddDeviceBinding.isOptions.isChecked() ? View.VISIBLE : View.GONE)); - // 设置确认按钮监听 - itemAddDeviceBinding.ok.setOnClickListener(v -> { - if (device.type == Device.TYPE_NORMAL && String.valueOf(itemAddDeviceBinding.address.getText()).equals("")) return; - device.name = String.valueOf(itemAddDeviceBinding.name.getText()); - device.address = String.valueOf(itemAddDeviceBinding.address.getText()); - if (AppData.dbHelper.getByUUID(device.uuid) != null) AppData.dbHelper.update(device); - else AppData.dbHelper.insert(device); - deviceListAdapter.update(); - dialog.cancel(); - }); - return dialog; - } - - // 创建设备参数设置页面 - private static final String[] maxSizeList = new String[]{"2560", "1920", "1600", "1280", "1024", "800"}; - private static final String[] maxFpsList = new String[]{"90", "60", "40", "30", "20", "10"}; - private static final String[] maxVideoBitList = new String[]{"12", "8", "4", "2", "1"}; - - public static void createDeviceOptionSet(Context context, ViewGroup fatherLayout, Device device) { - // Device为null,则视为设置默认参数 - boolean setDefault = device == null; - // 数组适配器 - ArrayAdapter maxSizeAdapter = new ArrayAdapter<>(AppData.applicationContext, R.layout.item_spinner_item, maxSizeList); - ArrayAdapter maxFpsAdapter = new ArrayAdapter<>(AppData.applicationContext, R.layout.item_spinner_item, maxFpsList); - ArrayAdapter maxVideoBitAdapter = new ArrayAdapter<>(AppData.applicationContext, R.layout.item_spinner_item, maxVideoBitList); - // 添加参数视图 - fatherLayout.addView(createSwitchCard(context, context.getString(R.string.option_is_audio), context.getString(R.string.option_is_audio_detail), setDefault ? AppData.setting.getDefaultIsAudio() : device.isAudio, isChecked -> { - if (setDefault) AppData.setting.setDefaultIsAudio(isChecked); - else device.isAudio = isChecked; - }).getRoot()); - fatherLayout.addView(createSpinnerCard(context, context.getString(R.string.option_max_size), context.getString(R.string.option_max_size_detail), String.valueOf(setDefault ? AppData.setting.getDefaultMaxSize() : device.maxSize), maxSizeAdapter, str -> { - if (setDefault) AppData.setting.setDefaultMaxSize(Integer.parseInt(str)); - else device.maxSize = Integer.parseInt(str); - }).getRoot()); - fatherLayout.addView(createSpinnerCard(context, context.getString(R.string.option_max_fps), context.getString(R.string.option_max_fps_detail), String.valueOf(setDefault ? AppData.setting.getDefaultMaxFps() : device.maxFps), maxFpsAdapter, str -> { - if (setDefault) AppData.setting.setDefaultMaxFps(Integer.parseInt(str)); - else device.maxFps = Integer.parseInt(str); - }).getRoot()); - fatherLayout.addView(createSpinnerCard(context, context.getString(R.string.option_max_video_bit), context.getString(R.string.option_max_video_bit_detail), String.valueOf(setDefault ? AppData.setting.getDefaultMaxVideoBit() : device.maxVideoBit), maxVideoBitAdapter, str -> { - if (setDefault) AppData.setting.setDefaultMaxVideoBit(Integer.parseInt(str)); - else device.maxVideoBit = Integer.parseInt(str); - }).getRoot()); - fatherLayout.addView(createSwitchCard(context, context.getString(R.string.option_use_h265), context.getString(R.string.option_use_h265_detail), setDefault ? AppData.setting.getDefaultUseH265() : device.useH265, isChecked -> { - if (setDefault) AppData.setting.setDefaultUseH265(isChecked); - else device.useH265 = isChecked; - }).getRoot()); - fatherLayout.addView(createSwitchCard(context, context.getString(R.string.option_set_resolution), context.getString(R.string.option_set_resolution_detail), setDefault ? AppData.setting.getDefaultSetResolution() : device.setResolution, isChecked -> { - if (setDefault) AppData.setting.setDefaultSetResolution(isChecked); - else device.setResolution = isChecked; - }).getRoot()); - } - // 创建Client加载框 public static Pair createLoading(Context context) { ItemLoadingBinding loadingView = ItemLoadingBinding.inflate(LayoutInflater.from(context)); diff --git a/easycontrol/app/src/main/res/drawable/background_cron.xml b/easycontrol/app/src/main/res/drawable/background_cron.xml index a0117fe3..b32498a7 100644 --- a/easycontrol/app/src/main/res/drawable/background_cron.xml +++ b/easycontrol/app/src/main/res/drawable/background_cron.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/easycontrol/app/src/main/res/drawable/background_cron_stroke.xml b/easycontrol/app/src/main/res/drawable/background_cron_stroke.xml new file mode 100644 index 00000000..b89cce3e --- /dev/null +++ b/easycontrol/app/src/main/res/drawable/background_cron_stroke.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/easycontrol/app/src/main/res/drawable/background_round.xml b/easycontrol/app/src/main/res/drawable/background_round.xml new file mode 100644 index 00000000..a0117fe3 --- /dev/null +++ b/easycontrol/app/src/main/res/drawable/background_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/easycontrol/app/src/main/res/drawable/chevron_down.xml b/easycontrol/app/src/main/res/drawable/chevron_down.xml new file mode 100644 index 00000000..90e82812 --- /dev/null +++ b/easycontrol/app/src/main/res/drawable/chevron_down.xml @@ -0,0 +1,9 @@ + + + diff --git a/easycontrol/app/src/main/res/drawable/chevron_right.xml b/easycontrol/app/src/main/res/drawable/chevron_right.xml new file mode 100644 index 00000000..512f293b --- /dev/null +++ b/easycontrol/app/src/main/res/drawable/chevron_right.xml @@ -0,0 +1,9 @@ + + + diff --git a/easycontrol/app/src/main/res/drawable/chinese_yanhua.webp b/easycontrol/app/src/main/res/drawable/chinese_yanhua.webp deleted file mode 100644 index 918da0cb476d93715761fda3408d9a6039f2a34c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82252 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 z 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 b000000000000000000000000000000i_EZp diff --git a/easycontrol/app/src/main/res/drawable/main_chengxuyuan.webp b/easycontrol/app/src/main/res/drawable/main_chengxuyuan.webp new file mode 100644 index 0000000000000000000000000000000000000000..e75abcb18c4c6dc03ae1b224aec9920302af3c07 GIT binary patch literal 37066 zcmce-b9g1~wl6wk+qP}n=-BAk9i!9f*tVUHZCf4N>e#k3Z@zEswf5S3pL6aX=RS8n zb5_+;quw#b`wsoatSS{5Ny)xg06)eq|Jm1kx~MPfWY#^DTZk;Qw%9lqsjXhUV(#a#AmzT@@ObWI6EvHs7XP=I%@UL!)Iu<7pVl7=X;!m{2v&K zv-h`wc)2I-wsVe<=+#W$q#J0bBEjy9#S?4#kl# z+90UjWM7j0_(EHt7Cl%I{|3V;RiTDl;OEbEsBzUt>2twJ21+z_h);m52BD#jNA19K5xV}L@ zPsdQz@8p)7W(635>|ynd}>|J+>4BNLx*wB$)GicY~5t5>d7nf63BLm0VTp(Lzq{8=5W$ z$enL0nkI59@K*;vGplq+vGeINTl0TmZ^hxUt1v|k77`dO1*cSQnIn5pkx3-N7WqS- zjD=nrqIIECAZpwy9jE25Co?*PRI8LkUJK6nRw`LPSFoU0^Aa|* zrvMs8BFh6_7fM~rEr^bWP&(@*m@5AsN85<@n?*9o8QKI|+xSsJIg^nAZGb{DMHlWD zr4cN0KT#y>CW`2f*#>EFENm+~TL1J08exFJx)oY`RhacDI@x5mO`kiutMzy{&-}<* zUuWEW*q~E2+>iABPRYGekjIl)Dtov~+*m5Nu1Rzj!UNw{*cLi z8`_xj-M$X`$!vKOt)UH zm{kY%IHpoOx!%4jnZ6g*+p4N< z2kz>Fm~32-Y)9C)8@0$7NhI(TN8j!p=Zx!?Hjt44bSS-*EhKIqVM{)Oz-puOkwUJs z=hz(L9LYqj)g}EF&@ zxsJ{rkw}JnkHwwDcTzYdigC6*UtCmDX8v@X`tBN=2$6OA=%zy&H*yoR;O&pFB8h)f zP*j)v?$zH7T0KLVWq`+8cgpd?5Q+-7i8;x4?DX>Wqi@)58E#7ear&j(CXxknne!%2 zAco4+LT$;11Nw1}ZB08vVFio8%TRKOHS%K72Lkk?Bn$!ctea4r_7#1{!@NkuNQPMJ z4D5-S3+esZ0Lqw4YM)H-^W0m*aAqKt0|7KXC%_PL<@qOS=!P-eg(fl2S3E$1v%t}p zD~6u^M*R6AJyNZVE5KCvbb4~B@6`8h<#a1zr*Dv@=Od9zcF01UAeIWI{`Md`-Rh() zD?reJqCE=cGT$0E%7VH7NtUh~a~%Q#1k+&iEM>St_odk@tW#2nK@)MXn!aESUF9M*&N?;zkTs!m6H;Fk@Ism z9nt+IYN?g5nB{Rt#ObEe)^7pq;&!@!Vc>ft;Q4W2d^YjZ(Wg`10|?Rb>VrB)7^q!A zT#OBixRC@dUBOuS1iE?}PHYH5e3RZVi((%Dp~Qltw4$Q164{*eR{jLz(5j#z^Lvfr z;+Y%-k)i2AhBgRrNz}>(HGRxb>>`D~x2>m)CMdd}*q92pyUy8T!NEfT;vDdl+#iWl zUz`|^#M~WfKL^NZPD@BBTvM5ViaxOZxPJkRZ!6LXTN130 zKOO2+zA9+7JkM2kz1RWVZV!tG`FgvBCksAK+~?Z z91c+MP5t(P#7gEHL%w0D58S?$OAxtz{PPCQ=*T$vbuaHR4pN5oqmU)BcWj;XMxO1)fxV%RtYEB-lEynp`84IO;K& z$71MbtOQsjP)-VDeeM}>WF0-)BXDR5>;vZ=ZmO+O8A`OaPUIwZn7qLgZX#HKXof5V z2S^qw_@JpEz4)-|_fo^kmQnNC@j0?Hc(sHfDOvFl@Fs42e zUm!fYoKoPd4Gm2KjRF=~yF`YyD6!l`ZFAzjLR92?vXv5`s!@?UI$5aLrS$Le;qv;%-pg;q0UVms1sFtrz{;5| zfn8`3mz&>!iH`A=53CL@oR2^*zMlUmxm%ypYP)oz??dxVPEU)7#Xi{60K}Rqss|;w z-GT2njcW;Rc?fUl7hp`G2f8?DpaX=(_;~5g8urt2U7~Tu;gkae@w>{Cs(h!!56-eQ z(9TnfYK9jrl^AW=5&8z~^p~!{>#X(=MT>YD)~!46Z0c6nY}v{v zi{f8QAp$iVvx`N|@I-QtDjQJIiP*q+ze4$`=%o6_^2rA|YIuE9Q;{|f51Nogh%7Pj z7=}h@p&~AbzT_L1+N?q_j}!cPWSCq@??%K@ApORf0VBpS)`2qi0!%5q*Bp{JU0X%QG$M*hb-+@DFSnDw_7 zl~Tunxl*mT0C-(lh0xY5qUy0=`3CGhx^YD|wYrhyJ%xTj!srh2tQbRm#fO?@c}+MA zCp0=2TfYYyD>72Vf`{t@q-WQynw%6}2^Q|>r<6ICC5H>vKrFJ{YB==7#`RounEqhd z#~YM`N=iy92isiUbxtC;A>9c~^p=+ry8+u;dZ8E6pH=e9HuTB_zOD{hK0+z!@|DBk zEDna5M?mZ302yqCgf%j^lVQMgd52NrW)m{Qz-6^PPhPk#>H1-Dgez z8eK+>bhaoZ7+699O9GdgPiJFX!O}Qz?<;rJmc&~J5QXEZD5I3bQ#H{?YJS{P>ZcCG zH%6?cL~>dDLR^~&n@wEMwOcj@=6a9zgglBprk$r&vs(rxNW?M}Vr`trqOKzaqUDK+ zPUgg8i6RQgn-}~SGm^IOPC9>r8*HK+uS_L5!mC*;fcbL~6VaA4i?cDo4_~jr5OA13 zQCHH6Oo8amk{DkiSxT~Z$ePT50eOa!W!OrnXp`ueCxQcCXflB#@)}n z$Jv;Ycxq_MnlWj#KtU(E)C5HvqePJfBvVB`^>7J^};w07SWes6eNhiNRoTdA>A(ZD+r*#FS;w~-A zvb{CsDpC$u7^uV77Vb2Ji*H80VX2zYAgoW7tvn@YKuc)*{tQ~^&0fAHn4NdbR!6&T z#w`cc-$)%%Umy@e>1Miuu$k%#n=NhgU)=*1E`j-Ww@k9wqsTS zTu8e*dgl2A39LI()bI8DdXqUfbF?4iW5H?L3C&z^b25ze7u>SdDf9z2M8sm`n%1Ma zNf(qk>Ydsl>Bf4zoXppOrC^!q8eNQ{0+xFQ{O)(A7jF;|$@CF=wY1h7!C!Qn&X+sC z1AF_WVsgR-9q*<;1o)b5S6b{QMu!U{NDn5mYZdjoJr}$UOvHj)p{kGPA;h<@+@r*8W`w8a~h$Kpko2?*d0f zgt-#x7(WpiVB(cAwSTw4zl$)gIHeG!-R0u7N&0(8GsP2TdrTiXC*-7!PR!z z>o9rZ^pQM#($yNt1B(go>>3-(Jv}*mkNfN={=_jNu?GQ-dELNLBp%4G*>J=#2p5{m zRhGp+zKv1eEE+W7n#Zge+(@Ufmx`;`rd7ns*Dypi42aOs^cEC@-yZ7v96w*)5;k|Y zJ=s^{jw(+9`I6m%rI9v&!Xq|eh4Q<8-#us*!FiQ*Nh~qyN?NdEH^>&pH2UtHWM}2# z_3LfSZu9kP>2n=jKy|U*ahzo3RnA-*9l>~-Ov7uo z?*udlcLCUSHQR{<=`%JdzG6cl_%K|72!B!~)`^#$2x=DD^wDxX@Eo>J;ft&*KSRc-{@q}})pY46m!p)s27HiiYefcQG>k}ewP zx^D!YYIcxcgLnOPRmu%U&eOOW;+wIyWyYkXMCms(q{ zZ6|SZmYKyWy{OOupA0KNx*8d&3h+Sm2%uRdDNb%p2sN;}v9>y{#?gfUIUQ6!!)ZTz zZHo$$rzdUq!>JD~X$7RkQwv5iF3TdESCc+V*7s%uNl3Oe-m2jaaA-U@XKC+H`3nYO z7y&c@j85J0%dU-H%K!&Xo(0sT>!`tv&Q&*w{?}DRMpcBKy6PA9o!+FAecljcy@IpQ zuPg+H60*0cac+;gh7_`tn1HT#KO0H3+N(X-552EAl8FGy!C60y5^Q@r##mi^TtM&s z2o-WeWl}MxU;6ENwK`RX_LwyY7FCvZhFi66G+>D`O%5)40S`}u;Jh)+0&$)`h0+5? zRU9+dt&ww(&be)YRJnf9lj?U;80u$|1WUk??BS3mP}TWnS!p>+<2wHK;Mc*ahhLAk zFyeS-KqT)9uiN-=(jT2qlq1KT|H6IXbB!Wz>eAl`MdW&2wYh4NqpoFxM9Hd9Z%TQu z=W+H5P$yh}cfaSza8M~Mzc-QY7Ur>YX*Y8APZ_ji1+-_*qbK z{DeM(U)%>gI!X|v(K4jn1gsqk#5#Qy8VZymN zUrW-pe|JS8Bq*9I9vJ3oG>|blrOo($=a~)Kc>?oe2sO+g(si}jm)PiBo0J83Em{yD z7q00oGrZ=;@XP$%U8oc#95ILShJ}2+$u3%>BR^$Gnj1pqv|)}!Y|{cK4fTBMCbpJ3 zj?h49Z4d_s?c{ib8)9vN6;|QbTvb$@Lpa*ymcMC?nJIrZpH9pa#mZaiw8U#sPYeU6{g9Kdx;XWAbkro?yOoIRmU$1o6`n z1rCPYw`L6l$+5~T9rT(;eEfNaP@cibuwbJb(sZw)<;`=r1V9qMeWOXez*It_!OJuc)pJ4ab zn86CfGUhA>Q$A^S*xbnb-0Z!z&ma~tUc7>VX`R}yw}@Q0+HZ`cMZmj8xoTfd0X(w& zXOrf+Bw}3_wC9jqx=@5kbK(49{mGOqy!bE0lGe2gN0C$0ob+iCEhH+BS4A$97Bx}H zkuyAxY!a+}@`}U)l2yNjgvUHibQwd0qcY_y4oOYlx?dnwIIQbC?zvNhZ4-4BRe2g5 z5B(c0N>e#fxTSSCeN&iZ8xuGjM0^(D1shlJrZ&WL4$FdW8_PBvDO{czdy zsC1=|DnH_KuGHYm4)#q#tixX`ZB#&QY&c+lN#7h5@&KLKAvMf5(Z+7CxKkJt9cWS@ zH@Yw{bd5FLO-^VDZC9qD`_i|ig98H1Dc1j z<&RVW^`EdJl@+l@uw51V=pE&&M+S+5>T*67YR83>by`-CzwPIBApI(<`TfwFY=gij za>gP91KjHl%UG zLs>CAs9C^9Y3v2Bi7`XYmkfh8;X+m?6X(|mAD}lP#Tk1-jfVT3E=DvOB|*>faT$uSw{edNYGi~_4A!0Ha- zHnASRfTG-m`QuWcp);y%Z>}N8bCRDn_#&8+`}J#@4)7KTd;tYa}iIv0szdUpjjZa0B``fAPaW5*e{Yiw97jHF&KD#vnMPcxE*4PJzaY9 z7(pIamjjX^od5u_2cf+{vT`#~Y7Ugg{;_+j+qJv-^}tE-hv4Y7!4TFRpTeX4lh1?T zUKe6(%m>xe<%m$W&x6g+GaQEjkrTP{~OtdCc2Ap~WKFy}%X6Zr&4xdP-AW(#@0$o`-U?>w@nBj`v=qe z=0Qpi(=O4J&=}C|z37vcaxqtT>Id`#I=?;EFtu)~09iiJ9yMQ^`-p~sZFj1t)vpFu zK!DJ+PZ=;92=&_g@oC1DoO@5wk4qrhgZ&oNGtzzcW6qY(sP~!|r;h+I;O+8NaRbQ_ zm=25wc7FVPmpU6-_POak6S@%U_I?0n0fE5oOI=`hv;9W(N7so@wZV(HQY5LBK3$

2QuFlZN?8#ptS_e_JM`F99itk_c8_5IxoN@6)5I-2YqJ=a9rAhyV4s zf3TyG|6lR^rzk{~wErRRpR`Xk@C(`gt1kaW`&5xf*5cpv{I9f6^_>zY|2c>MLHnHA z{{LUomOGo`ubunv3(ITE^Up<>e)`g``}oT19qAu4D)pWAOri`c4hYj_?2lvf|Vv6b&? zB;ktkWik2~%M76~{J)q!&)n&s?i>FWUbg@t)qky)^-bS&F@2k!ljzo`_3~a+DEi-Y z`{aM0{I9i~&p1k0rYBf*$R!{1O9Tb!LjgM2BrODFeSbj z@2M0t^JVcBn3rGn*D zp3TUpPg2+n;lcfr{eibaE!d4XhCbS2VsqAU78m!UFAf}v1ox@`NDCD2IRA)8feN@P zCbUS!a^XJ_wee$V%JSNZ=JD-7pNl<|3}U-X7BNq=YXQ(P+5qaw*yVqukt>(gziiYs zew(?5S=BcW!8sAKQgCZItrx=S!-1AMQF$}6Re2D?uz?o(J&g(#@LVL74r||!iiJZZ zb1ygqN?za(|Id{?e@_2omItr&!D-KMY)=O9d#yfU_!gyOYu$Y^3BAt|n~?K%FIu@`HDT%Wn$3CV5AunRgg0r*D}+&XU9 z`^%n1|a77-Z-qoeIc zaS?Gm2?gU`!=Zb&O5)G?uiwi#9`uSD{$n1Fp5ks!$Rd@97ltn2>MC1w79U0(e~0ov zOhLFR*TBTAju6rp$cU-^ja?TFnPC=E3?p~PfY2u)15u#EY2RXy>N%o5P^T)~-%DH} zp;8*_V(c8ZwbK_}l%!{CX2sz837lqoLvHnN=ix*A%Y*KA-53j{dBqG3a|(Z48TlSt z4bmX4gRFhICR@X`V3gFdvQ*tU|F)#vD3v6w7T^r>N%`cD4;~7eaE7jiXw1JzTp~!b>u* zT79zA*|a6_mox7w99UoEi}9=Hzg&zyH1*|m$yX0*-o+|=eP=4=tkvdpbWQh&hy@ZZ zSSx+zGdffBcqSOyqr@{-^`iz6NgZ;yK&_i~?&UYC)v9CC{k`F}A(-w6Z{b2worPHy(k>XDs?)Lg?Q6=EuUFjg<8e{tB_`q8 z1gj&{LybDUDHR}Bc{S=|yF_~$iI3Q-9Hc`K4eNz_>EDKhsbmChdZn z99M(eR6&UF?d-%@(WSoEr9^F_m}l2k`vjCs=0qWzQb{rW+jB7(O87XJ>Q~I={ahEfE8ZqvP71>$wOx@ZoR@d@W6%Q; zi6gm3=%7!Xd4Er68kCgN$!C`DMtoeYHZw=8pOD}I*xE_c&WxWn_(y8C9?G>??|lW) zV=xyMxcLX`4%SdJf6!Vd6WxV^7xON&$L~WM1|*xZC#2E*L;-sc9y-bqnKuB6KUpbY zE4F*NepCZbSMU*IEyo@ewmmqIMLC6)-DM2ogQSJTTABG&8&8MB7dM~?TT2@7p<^9_*~xKno7eBa&uz^->7 z!TlPB;Zt(~?L~3mIwL_Bh1s}2JHULs!juh+F-zIsHM*dJ6e#PP#VchE{w#_In9Dhy z`!e-9cv141I)r%LMjvI1_?0Edny}mxEUccgMASUn9es7L5<3pytjbZH6whIdhlwA> z`#)OL>6Kbqi1^}O_n)^j`ltWt+94PN-)rPWWgqdPl(?Tv z$lOESmA8({nN9Lg$HEl3d+8KDYk52~UM?iT49R4mK6*dPDBh{-folMH|GEN^m)Bnr z`gd8p?+}1Ho9$4J1$6>x;Hy3O(Tcfch2)|*Ju&{>2;3Ci=#DLGQlpzDX+Jf7gJ8nt z*M%+fgNfD1La>RzDeOVsf{dr7;S4(DvlXdJkQHGu(#IzhBjEhZ--ICjFZ*ocu)R_% z@%_FIXza+Pa_6g2e+Z;*fBV*uzzsuHMo5nr&)!Dr0y5;xG+2@EC%!O_EGd<%>%M5f zs44rKJm&K-{=P;^;?$Hf2Fd{gC0#9}3(wXs5`pn3Gr)54BO~pTj5ba!O919JY zp6bHs_Z05YZ{#>%o$`WF_a-j5o?7?U@`xtQbVnooul>lMi60Q7yRGIJvpx%vLVugs zH--76xlf(#CThaSKlU-!qn|Vuj7_$$kc6XN9)H-EJ=3i|Rs!xE51&Xv9ygxWkSodN zw}GD!{crFQ(8KK$L)<_w#&}On<)eDFOp2|{iipI=msuYALznEEe`AOdQso{CUPCV{ zo?aTnr>>u^!{4>~g6h))*k0!OC-uPp99unZK0Yv5X)e)}tojdq-arMi^gx@uQ42o9 z<{2YEz5kr327L?YAM?;UUh;~QsmrrZ^{xatR04Tj3M`j1gucs?3 zjjl0>a!<$4`d$2ru&pkaD@H{!JUV^IVm@zws-b3`{t`<&FgNvNM+L!C0^8DWAj$p8P7>Hu_W?|NI7$pc=!K|N06lvAWi;!UlPAfKuQc(N{oEvs(h}VAeH*g zSVRVTfP^leTy1OumbJA*coBA(>IM2F30J9407PNPuj`qbrL0heugM3e!2ZyN7$`U) z=aR*$%}D4`pexykK%L)Wz8}md4wm-$?AN5{u(J>^oESJ)!scxPV!JK6I3BzYmGk&L z6shUPWr_KVG*ef~PS3`P*FrzhTs+Z#V9^!~F;A{YAaUEqJx{u1_=#DBE~|3u#Z z8WQ{Qzo&gdVUoB1iiiI-?jNVcK2zQQq2Ua<`5*HBogLC&(CxqXTK{7Ae>ZI@U%l3V?cDe^I>A}BDsnte#B<^09smFiy7z|rpy7PeB9zVl%OBinr;eM) z8C!~ZSwEkVu&I^4jZWyH(`3Xy9QxP2CE%U>?v-@4k%jVt_@1G?1H1+W?{?k2-Js(n zrh4Pu1H?l#79e2T^=4`qaq7CrLoVta<%AhIVC;6pl?~NeJN`X&F`{4GV_1RSKgKD4 zCd)6QDD!la)i2Lw9C#7>Bltze6%Xr3ai*$8*rLD8cf<)Tgg&O6D>15>?G zNGaOyQRX)Zqae&Y;CerBtX~R+A(AgjJ?e^{@i`N+5o#K@>vm{qIX~cK(rxkqAxiyl zG@i=u>tJ5Fx9<-M$r!$ST38HNccOvws#1n;>!=Hh`Dh@dc>~W}qjU-t*ZQt6=h%Dr z4MUBbj*-ic)@H zQ-I?rfQCQNm+k~Ft(M3UVr^6&7XCF$0oesb_VIWlBW6C`SRE9rrrN7jmfaUXqc-MA zQK{YH9mn|^rPpb?YDt!Cg{~D|v+EWGd-V+-|FJ8@Bp10vWGG{uIHdNtO+o53I>?Yr zSVsaDt$=DxV|AQes(@FmSWiE7*Ej7FN&IGp*{++B&+(NC?S;oh(l-)XAPBXUWY2?r zY#-&<2lUWHR#(eyNeu)#*Kd}g65s;Fg^as{H2;GpDJw$@N`ZQ(eC&D!VtH7nNVgT9 z-N$v1%TC&f)&!fY9R_?TD@7GH8LVGZ7V~$oZ+sDbVosgoj%g!xT_%>HH6{hHZO zftD`mAF5^V2+1F^R<>Fqc&RsE3xeoq)w}kfGg}x6LvwV60r12L-=Q=Jc^96h0%1$W zXkwv`+$kCO_5e8Dd0)sOquid1I|)8qwf^LGAZ#lgDQoRHSYC8HcT|FS_wfXktlOwPf&rSgWiu%60T#h^_7}D!pASDgdR8W)^0Hiy>wS4DZ_zuq`28qG_-yLm#zuB!X@_s^_V)K3qj&ZiTHH zkYRQu@*Z2VJVCi8XfuNc?Obe24XnP0k!=jCA4L{y6fw8ntHM9t#;t1AW-8m^TzkFW+r*U2V{Pa1Q|mx^RPU+k5GX9uQuf*zwFH zO6hG@v68`0t1~oJ38n8N9Sd%O7#jJ2mc-!aSMvh^;<@ry^40ApBqv#T)nq1b=gvLQ zAB@);s#6&+F#^eozL|WG=>@2~tTkUfbE_aZs+YUF8@ke>}YXd2bg~B9ctzH0@_QS!9h49>bU>4USU(WHC{_;ki(RhO2H!ckZTAtW zr46agR!5s?v#?y5JwI^$=Wa)Wh{q*%WiRJlHJ8xl=u!Oxeq48H8(USBHxHVV?R{?Q z)K@@x`pdwqdz7-T)HORpXEQ^oy}YLjPdwMj5>V3Ts~KFtJMsjnt2z5%2Q~W->lOe2 zbnCr#Fubj^$Kt7%mm33OH$qIUlE)*dKRw>m)Bl_ev4czYJsCIqvQ$d_%B+o>$V2)D zf6G+Pz<%f6`Ld&Y-!Dnr;YNaA=-Ub|ubYn^g6h(OB@6T0WSM_%w2{Id)&9J)6*&L# zah2#KBASJ!V-iJPF@x|&2i&q;%c5VCEz~YHPswa_eV2DgyJTi%SKbB`=c*9@?T1d| z%JNi3yQnNM{fXHwp60eb;-Wc`?bxkD6lOwwbgA4`%l@7lH1~*%2`hov7rpoH%cPa! zWV^-%s_%lpW)QA-89(lFcX&N#oAIFQII%9?)3m|Kj3@P^hR9II!IH>v)Y}{Wk8ZM` zCCjaLDePlAZUD)pn(0;Jf~dIh)HmpRpCcopH?ECD0Cf<+@n;- z`Ghs)XVgS)qqj#$g=*D`I3+-R0TBHZ@cq>nsGvNha5i{^;LZfVOj7rpWDG=asHLOX z(#wSoem_cD7}JIn;)E+zIm}CSowI=RTk7D0 z_-0~%w4U6>u+lu*4nAbwuI-dJPK7BPNZxBBlgh^Ulgty1BP9fi2_b|@iMb1n_#wB1 z#254jq&G1Ao9inyqAIVP=a@JkW?~=O?gi};bZ}#L5ebK-O}fU(H3ef^&jk|v#sRb6 zs`%~&PRH)x8}e((Gl&Jz0Z{3*y7>45@X(u+=Ka{;r;Yv${K2z4Myh^KO@hg5peFFQ zvF&3awtQstNe(Jl!8sZq({P+qv|Lj5g)1it4H|+a;K)!N=2CW>{%UM7;gcasf5BG% z(sKX$ydoR))-Tzd6Xt43yQV!uN^~S}Nk;8Q2vonNUzbOR&EG5Iz9Nn#*bF|ayB-)Z zpew;at4^6gB$U$WlKOlh2?UF?87GH765N7ExyYCb{L9HHrj?F&Z`Wj6653g3UD@j+ z*1QFnS1W1El#3`sp!EHq*SUKG7y9ZoX^+LL7jqp!eB`xS`#p>^;&>UQYB8tc9H{Kq z4FAO}X+7*~f4f_|RtM4H?@?mo;4AT69HbqV_*LZ2&S!iRd>X(97#{s_pxngh0^VU& zSP#ZMtNmQ6eKT3M$Gy3(8A#Kv^hO;M(bz^VR$XOeP0Y#fUnLt~hc~l4BdfsgXr0cB z@vr_EqrTr=O6bPBFp5|nj41Gf=?$g7TepNhgP;!?@L98lP+8jSO2WrkV+5~CsB0Y5 z_fL1Jo?Z@+ktt09NmjyEV+6wkyCjmC7sBS{Ph!!O9DG7`x!GPd&q?5ZLMeY;?no#7 zq8R&8-0-_K;0L**zMSwZ=}xSVdS+2>I?aRDQq^mJRH!S*bC>i}Yu-9xEe5nsL*!*~ z8MLWf`L$T*9OJQ$4OvDz9zNOJS-9eJ>UfFD6%_9F3%sJbp*d$16PzQTvKPkQdK9(1 zSVtr=dN#B!uYvbUuy+8R;;`lbH1>h8a)kjAIWV#+uu2m`pGesCMItA9ww9U_`-7{# zQfT#v;LH#Jh}~0jFx$N{Xxd%(WH3b=3?935R#z*HijO&ukKWE_L1u7wQzPM!I;RWZ zhCFp5SC47(FVz@iKf4HFD@ufVrTh*q0pcfsyW^dLooH_55xaK*a$`Z81B-vjW-}D5 zzt(mwrPZNMR3iV-hR+dRZ6qQ5^mV}Jd$`N$bX(+c=0NZ{!$c4LnWcxg=~YqulKIph zlgPWFp~oY_-JQ#O18QRyz{=`H3n6q{lS1}}EK=K{F1jZqoGN@iPQ3QwKE10OxsobG zwT~c_E9GVj&U@Ed=%q2dmw5cq6-afUdB}w*E`2HoCrpR1J<2Nn0kqYZ>TUc|pLiH= zrGR9tt`@1DT`_@;9Ja-}VQHH+vG=7HKO7xPkp$3^I0JTgmW2&MbD7S#cE&G-Z6iHk znU#z@O)4=?5O|@fAsEvhC)3g;>U1K0-&>kMz07#W^L99;RcB*sqiS_O8jmq) zj1&uh6b;Pj!InMSPOa9Zs5l7R6hwTX=ZPNbyn=qJHa#hYB^Q6QaH*60ZWjO_F4}sF zF=O-lOezQ|jIL!`rB}5%u^e0BXTplHZ1=k0h;o{d;GeH4R89k!$D}*MUtLO*rfaw>yB7KjG8{$Hc zbPv;n{fKIOQ7`W#lNI4+KNh7N#B5D_gVrQ$D`P7vZ@hO?dxrTpw$?MYvq2!92eS{T z3;3rv9`I)|Kw?jtb)vC-E)9pLKy9jwx_-YMb)OJnU!@_HxK$IZ37I5|_2y2t57Rg| zxk)iklS=BdWz*E!!;qko6cgAYCWfC@x!U#Bgm1gqSNf7DFJ##Vixbs?f6N3@+CqYr z4VRRSE1gcN2N6e1)1g?^f|l0w9@W)WOUb=8q^a?zRp6Z(U07P+hJ3ma? z`F#O^rue>#4fvX092zCei%k%8T_pJox|6wO{^BbIg)Ju@jRwqR?%0?(IlNnFFY?xw z^5B+xAjw77Fm8qRIp-e;Vbxk{g^l`7*dDcRvA+P*a_2dgwZ5rd(`=${9uY@gPK+T{ z)ZKZe{GB3{!(~lzZF-MIWoJaV@zQPg)fZNBP>PUG=AsBoMuJPSPV=TyC0}4@2c%O> z7d2~kdWgV=eII3Me{_A^?1yHvcXCjZ->U&)4UCsCC}^y)o2ni4(RT@v0U(nh4c#f& z5A{6qM~x_2@hIpWDq*?gTYjP{jn+s&&0EgmqsA4BBW~Mge{tiHkyW?fj4^EknVAUr z+c0F&XqD1y)MyQlO9&%#^(Tzhdr4D|Kl#P3dLx0`_*sjwYB)6@8R<}Pj3fs?rS2b|OdbL^ioWPrBY#!%CAPvpmJ3UIsGv|J<0RZ4lGavhl1YF$p zy>qArJB8|#%T3N|?ni%&U_(%!7ymj-*3^)4N#h!n*_iZ*9+Ei*?}2>;qieZfWpm%- z&VJxjuHf@qYr@2`FsP~#Ff6g0+9T*mJ<4XBo2FTTUEXqf|CN+$U0%4Asw1{RuTTWp z$ABS%6ufw;fBl0HY*2%=IR*y+lLLQX;K*A=@p}+NF*E-S zPsdnxm1BUZx%yN-O9zDmKpnIRFPhASy|@u$Xj(1vi;0@xo7C|1Z0<~;5rs?mJ#kuC zXiQeVLQ3)gT5C=3|od{=x1v*$qlV^dW$x0bS`sI(;wrRa-Y}wvW1dZ?yFaZv* z4tWjQxc+*SgRM{(A46LDpO5b*Y3dVfY~~sTH^n}+$!VXVZ4eLzPcuY9bFiLGH6-e; zg3SGVH%}y9q7R&$-ezsQ(#1yl{jf)v%0*|vdk0yXCyr9bx+21dUwT{r}pHC2> zWg+eqdRs}F6cb)FS~IoDmYxZ-Ems5A{mcjAg%Z1XL>YKmREP@gJBXZbElCTT^Wg^B zD_&B=%C6o>AvbN~#_gzdhj@pEbLl+}aTPnv6Ke_8L9^~^Z7)jHiPq;gJzz=Fk>ss- zGL9SAa)a^9{Z=H#PPT4rUVJc@=ERGRAW_F}C3o!=mJzXTjA7I<4Qz>1>~V=`FPnr@ls-bv5C{vz_ugLI=>OXlReRPGwX zpiQgdV)&>;C43X0+v>(s_9cz1fg%Spd?sNM1cBRo672_IGJD_QNOoR!Htx`XT$qny zwL2WA*KZJ9c75Ul>F$I6U?wnJw?L6^KWBi_UEzAcbsiTFry2-+&q5OqsLgjq2{2m; zR6hg1{1!mVxT0tJwh_2Pu)*739)8ayQ>=)FyQig5o z79-V`rfI_WS5w@qdKAx*2(5rF)nU%9>-#?s*-ZE?vY726%o-;+8PdJ-7%=M%7-D&0 z3iE}u6-f!0ROEGBR=N@LxqMjk9E$Mna>5PRVMP#;AQ$JTX?73CxzX~uih4T0JWnux z3_h@+@VI#g1%;9-?W>7~cT=-5i0m!7=P4=k=M1}2*}6sH=O^r!iZ)&m26U@(0Zu76 zT5Cn4^@m@X!J-pne?4e#k;uN1P%%WFD_!W^TD)*f@pXWLpzpLsto!HUa!(~%0FK2C z=1)hF>=QNQQV7N4XxlJ79(#GL+o&nnbYRTE%(@E=PXbF)XkK%n$vkW}z4q&YX4bx< z?}ipkw?F8Q%T`3T{anygty}ivs3PuuSI##OK()!PONrFrNRCU!zqMR49*wOqyEH13MIf@n0?1UK*~`dHsG_ z)17~B%i^2omW!{%Z2(Rq?11eVUXHw02gBBCRNj?6yy!l6gY}g@vn)g9wZ);#-)()Uj$+MaQ9fnNxwLnbvH&OA@rC@ zPq{9BsL6{)Rp2wK`@5I5fqUO8S!Eh+8P_6a5*7jEnClfshF`E<&o=q{J@D|pUpYc$ z*7R37OmvCfNVoffQ6-NT#h~y7`EI^gWz+#VCKFgey}MJ~^V$TF7Qy6D2c%bdv|wF( z$RJdTt@XV1N7wSkz^zL@UqLfZO5J+^1{j`?qnR1(2?~0^%JWhV5K&wk=9fMlT7#)P z_HW0FX@KmsVU%2e^Yl9@7in`Jc#MiT>?MwH z!BlJN0AW(g-_2^8kt=IU>i{Chet*oSu;q4YhhiF{%02ym05L$$zXx7XKC1H@?vyHP z=fp|+l}W@Qzz3^x^c<&*i8i>%cXb~nf(a_*QmqRYIP&GaBaz4%4tIAT(7+4lv{`t_ z4X+Nenm?xiRvFGZ~wwe=moSUeq6@l3cca$hzKca zGTM?DTppp76}jJUZ_>=?DXL*xTaxJPe`%b1V7RTweU0NcKPB zoK*H&uX$eFdYrz zig6F9&5Xq+FcF_mhoA{nFhE5a+VNVrnS4+NW1ZM}n&OX{_CS;@E>8x7%Z2elk`-*u z?=5T5A-JqZ9e}lOI&G7?ROLzWsq|XLSxQGSwnrl|+74zw`NM4U0JBZ`~Z;>@j{ zfpmwnv3M7AI<~b($cP;J;{=X&LV`#&2BED8qLIuMa%>9ggT_o@TxckkEvC7_%_paB zg#m(YKpXusMWY@vXxz$ac{8Zzfl}pVD+h3J2>ZDRdEa63P22x$#3-$Jd3r>9rA&A3 z%^oX|hvIWcsQc3*o@2ttRMX=|mOqk4x%hu!csq6Ft+o*D9%|C%;j4Y+uGBnuBz`(7 z4`hX}0Q5I;6(xY7vWrtHLg2zlO}!8ehN+08@iB8|06jig&f(uszyV`M25Cuw!305D zyP)Nkw%@XLQg(W_m_ja#vnSx+Ggd$7qtGC!#340nW&c;)Wrt28@mW13yq2*#f=m`* zU1)O^P!QW*t$az4g%?-nn0rMn1h8phOqG8Jr^o7CgVKsSL?cujY%r$lH6ovDa{E5i2Zv9fiB8Dm% z*scOgT}&SZ2ey=6pL}_NUuLlL1yt2M_2q(^GYra{ryvw*Re?-Rnnd?&jn#1-1N`8{92;| z3*kBo!3kUc)hM6Fd%E4svn12A5pm@@`~f~(FU2`5*G~1P*Ul)Yqy(hj`A~@Vz}t^8 zL`VE#T6xf@|1;Bzxfewj9{tUKim;|FWki->`uF5=F82V*9u)G&O%Q0BgFcZdAWf7& zD`Td)@6B_+agbZ=nco|~guQ>qPQ52_#DfKuI{C&`U9;eJ=N6*$2%VABFm+UzIv;01 zXrJ*^1-<~r>v%evk9-F_Yx~{>!JP0ZhCpG&ruMzo?AkO1kxyiPu&HKKF|r8k^# zGfT$!_Cj`pS5Lnw55Gx>UEn!9g{sYA+E-%zjDQ*~5P@-qtQ`V=Nb|&RsX)Z~!U?BV=W>xy>0? zuIzjfSI4ibZP8$&AH+($Ttctw1Zl2X;2N4piw>4#OXn`doW9*KY>RlR%pan8%0}1d zdp%ah62OE4i$A?lW{|zvR;8(CxyIEq)Zb(BInd%SSiZ0RS@^8DJ_yK%XMe%%pgyJs z0^g2Wxd*hRTWs~_=o{d{R_PPL*H&BHgrDg-w_mVsS5-~qGpWEaf*0g-O~MW~SLk1x zW(mY^hYgqXoHnvn6(;-?IFVU8;N7^}MFaB@#~f3}zADF7O9BrKPi%RdW}QIy6tk6O z^xq%#C3m@WgoRlffQ-oOF=u33@&I<3E1pN2nHdLTx;{D&rm9Bfg4MhQ8~xlNa;V!$ zgCwNA-3o794<~ng={l)t@G~oG&X1Td64F5yt1G|Dmb14>e2rh>eUo$oE5C+W2l8KqZ4upB z2~83e^1s!r!9CN=$(QFguy(GSlWhU2lKEm}G6ylSLD(Z-HbK!RD5?5wxvSk2xsK~gwm=CjQhb_?kf;z$^GTkw6N=#;)yS? zt{PI(FROBoZS~IUP%)wf0B1Thq|NdBt~Zj6g?{Qx=sildT67)=el&e$7WL>;!!)M) zuQpLm%`8NcDcYPUf~p05!?fZARpl_whB-1oB1^p__zxPhw^6j04*LxV8x^M?F>(<$ z++sK5pvjJ9Ie)eNWSUPzwan|z3n-CF*+pKZ zagJ)xoF>1VRE=owAf1O!tFRQ#Vo?zgej7&x7cAxP4At`t~s%ZHwrcUA8@T7~9YG<@Ry+%{{y2Rl0Z+ z5y1dE;NLIFy5A#7){^*!NnciGhkj)dG8mbg(84}u5_d=YO`KZR<_gLg4`qD?rT_7qo_D2 zyJN8+Lm!^75yZierN-{l{g`9M290QOkmR>=9O3MlX+D7PfP^9cjlPV27>>;7k25x3 zS0%?bGnftZM-{Arp7>RkihM1JvEVgY7#Y@pWo+jUpVf<(1YB za99Q9^^?n28a>XSsWzxe(6x#6{Dr)UMLxVMFYSTMiNbHYX|gojZVK7(+PY#${sA>g zBroZa$|`K{2-LS=P%WFOE9ySi78l?_Hh<_AUGu~$cXn-clD@DUG{YPUBce1q1TVU9)D8p%SF04pz_ z!c;l{8~Pw~cOrj%0_b&Nnv`g0)22g59s1I@K=bLPSC)=!qPotLgn?UYvDkxRt1uV0 zEUqO~eCe#g3V02Ty5_KSJVivIe+hbFDyRDcZlx;i?oH4N5VTRwn+Vy@43Pagi;JNP z@Wi>>+Z>9B#bvy!&Umwdx%N*k4pZ(8kxn+Ss;O5)lX?{VO5qF^k%6|S8mCPD6F@sm zpF5tE5EQCS%GGn$(m?mlER=ZG4g8IyBWt#Pd&@?cIr<(LyAF&`eVeMISre+ZDD>Q& z38dD?!U2dulZa}~=Q0x9tuk~2ik9vSF}h}h0ef$^nrgD>4;VZ(gL76b^pPu;*Z+ivYPK!%c_t4s5y7%9*IO96eiR>CK5|Zu zk)?5WmyJ!`efLE+5kc(9{@UMM(nC3bFTl{lZ_bicmeVa)u>?7OcT{Se@odJW(tb^65{qMF2iVwfZOGEVZjKX0O zCX@*u{eg$-M;Q&DJirtUHvZfQyL*ABMKJnP*Ev(OzF0{C7yrV#K ziCLhOf|2BFD@o%cPzxmHq5l!Mw);Ydm*9K~gAp@Zb;aVPQldWkyH4NCl!_&egKgok&NFye9^!;hD9 zh8Ff+Y>*P`i#p|YrqJNE=xR5&sQ6NEYs~>Bot(5QG_SLl=7vprR&DCZETiteis-0{ zDc9y$cw@L@Rb8+a@H5#Mo8@V)ItPPj%Tyl!-U;YF44=vkVU z%E+$Z#)=+3SDdp_kfaWzJBC(5tc?PfTAeO`N2bMtb?CZ1uxA#>r;255MhG7?0| zB@{r+{G6d(7ln^@fxZL_u%20JBeD8!`Ez-sKSLt|8DR5%c?v| z>OEGvAm29`2ZgN}YP_ZKj5pWNaIB&}VmR3grQY|Ga&CEc_lR9#Db1UBXkE?;Tn+yF z4c&iT`w4Wzo$F5=f8q)Hvzd$))495}m|`&MndX%w8Wpp2Ck2K+0&WU3K+-;f?*F`cL##0C_Ox;aV{!#? z24K_|8r{F@Y0+SGL_DtmDP!c?jd#QQpPK(4F|`$$!Ffc~|MtKEpvk5JQ=oT0lY!i* z<*$&QbXet{qz;zwZGr%Etfan|vpE!U61I8zrTsL+l+W3rE3N$o-`rF*v^$vFrc{}( zQTl>9OaJGnm9P#wz$uSCw3S9fx2hrKSpvc|f*TpcY=VZ`e=z}O(-RoQ@MD-`jmgh7 z+|67c1?9G7_iUDzo4&w+VU3LIqB&_1e-EYQkYoxK{|jzTK0}1jNwEOpFFUz`?wmji zArb7gupd58>B2N`LONelMGyzAo3UbDn*!8onl9p;XXwa% z9!B}pu>HLH$Docj9}5GExfhpvt{mpJXG2y4+hwvm7;PKc9m4Xq~QRX!pK# zpcf7_&9jw1$G}j)S1CWY!OhbH5AX=GiQQZ{N|-qkys4mtsSyQZr;_|%989eB-Z&{J zCsHU)^pMI4(y}0e2!CjE5%GCxX28xWS9v{++8f4R&sxIjdsg|w8}&CpKwm0%XsJ}K z0_HigAhIuloe&{|#7VPocR*Uy?vEn0Np;OrRp?-F{3`x7`<7VQH90FY$PAM~?>MAb z-Ka&8F$uu@+R}yKNqjNhn)7N5j%&Az94!vg)IIz4b>oOHoW4(`B_qQm@Hte4C?Yy3 zz2HXh@4(6nxfI!CLGpUCbN0IE2_a~k<=YOR>$|=?B0CrHbyl&eJBei<#B6D0H$%Q`RRmy7!LR}Q?X$jRemA4RD0Ep>6k9x05C<={u-jP2MgXl&b zp09(6Q;K%nhWG}I>7;khiS^*y$3j#%>aIHCok?`%HdF`vH?57^?8UcQnxIoC%r{eh zx*miGCl3it<@(BmVF|BT44(AOi)m=n(Ph27Ql0z3SB$!Xcc@cHB;d$4zL;vt?-^p( zF%^KlWqa6()ekBI{9o~O@r-b_$a=eD*aprDp`w*<@gZ%nRe1MYd%NhaBTfs=i=3qxetomN8HIqhVPhAtC0X$ z%lb2<)!uuQ7Do>LHG+RvJS|%J_rNyw$M+2*YP$Y7iGFNASa1H^4({Ho?aE zwy#PP(y8OngPA`v;b}nBYDsremV@yJ7nnOlg7W1R+;=d5vVo8MZ5x$QOu0vw*u|gH zh=r-Ou7F^EwW~{&PgnM@#f3_~c!<{qMVH4g?14u(y^1l@`OSyTf{-E)>)`7O3Lx3Y ze0!dd;}}HTnR_Ym8s@=SAiCLq`~Be;Y)MEE04T*4CU$WuB!4MCFjO4!BCENp_E@4U zmP32eQ{kOTA9=mpqDn%F6Qt}VYQd~9$CJEoYDHB4k$q}xYsZX+0yLE68> zpMuNXfsw<1sojmJ{MR?b0D%tv)!;ggjAYDVDpettNEeUh`$UkEF~`v*4UI?*Z!k5EuJ48014EIIaCQu`vXtemMMaoMMqkX7uq?C zPCvqT|2c0sTkLfA6$KS=6{Z@WZg ztqek-rxKTH^WoFjPF9S9+0hF`N8tU936x3ldl+mlZ40FoISD?(jnO2jR)>fQ&N5js zFUe)g@4w_v1PtQ#Z&CVmHZ)MrxVW$Iz2c&HJysag)EyAQWt}MxXV@DClG=R%Ei=o1 zBHiz^3-QRCU0J6YgB$m(2AFoX&c4A7UXOFsb!>J=DQP1$bIlK6i?zgs%VEFy`Z{f8~*4d&~+@SWR2PMWPB4wV^b|4y4;})h)cS`I1)6_LGA3a+wbssMOt99+~ z0B=q6Hs>XqecMybd%l8c7lefa$G~YFY9RZ$%h@&vES9!Y_W#@7U>rQ>MeqCr!C0m{|Z|L zFDl66`GQd0ZU^O1ga@v?`OVapAoQ%iypvIX3rA@a!bbRX6>O>Q49VzioM-^}AW~v4O-eW?%n>V;(Z9q`U2mJ+o+tk(y(lsEDcXC|ezzdoT80XEj4gVYWwTu_E za&45pL|WjQFS{ktAt)7TLX}9I41B3GqL81WG8RnL2HCuXSrWSif7z5 zf<(O8VZ3n`hkiZ+CiGRQ*7))fL3$M5+iN?(GoeO}7*tWQkGXMHDb4w(iH8id@Yy0# z8jXHUVSb#1bprB~-NBIEu^Zw-hz-lDq-HCw-gLxbCBUAU3vLJ5cV$E>jKCxq+V@k3Zj**G?Q6we^pjz2~G-khL5BH zbVkvc%y(XCtMCPZlg~Sml>D|$)@F!;4QbfQc}W8xC(;ANldrFflxm-glurH%H$3W+ z329^Y_e3)N^8evm2J`Ugck&8LhP?Ez(c)Lvyoh00!eZ{HMQm{PO=E6P*{8fpa5o2= z{VCqZEn=76#jgL8>)OK`u3CPTU9cvwNP^Lsp4=s_JcGcpX8n5`4UFG$UO%n>pdVml zQ^If*C!3izKN7ql7VDqGaK$c4u7vJAOQ>x&{HD)lE3489E#UCo zHRmr;#($^|zc3PDLG`6X;6dk&r$R}>j(50jpH1_m<$|(r>(?O`@hai$osTxKn5?+^ zWr*2@Y#m!qsg81BLT|9HvCJ63x=AJY5d3;3ICOYJn`g!~TSOkh%4_8gYcJl@O6Uld z+(-fY4HG-ZyJ^t_ZTEFvYVeP+@0foK~W4s{) zG?K^3CwVc=ZdPUqJWuu!&vr={Mp6X^qS&Wx(`m}RA6E-`>w8`waOQ`3YOaq*29|gD z+NN+xf+@p>Ta-Hsb3s-7+Ee$Z>NDan^gjx@KsirQRNk^-QQ3 z(~z*-t2ksS3kHygOi(?Rh^@54Z9ZTS*0FpnoU2m(0AM&gSx#$=*dv)*jZDoToRma(igwko>Zsw? z&1}W@G}IK(<0>O(%X#YZ42%E(6@UVNA?Ejdy{G07++ZYWg=`l_>12pEHen`BG(vjr za z6zQ!$en7~Z5lv*=zp~!)WeQWJqlJjpMPn0hU>=xj@C*runiSMCbu{?H&Xp$M_~1#R z$0S^&HAeY2Yxu#4suyZV+S~b6RwKLXs(jBWVK=s!Z=N_3CMK*dH}X(G)*_>rMZEtj zW7V=_Mnn4HCm+Bu+r>!#nitTnDhj@=86#`jy+oUGWMIC&0gmd)1vwVa@rGlTrwwpb zfY3#Qe&t_LK%)I8S&Bd}rWfbwWU@<#b2&NvYme>HW_V&M=8W^`l_--K>#sC@4A;g%j609 z)^w{yG-&j&ZG}|Z8(=b6D)+CtmcFU;@%u099LIDMPD{@AuJQ^nN44EgywZIi{BN`a z#3qzSK*8MN&UvKGHN!%Qh3eh3EWmau{=Xq_IayR;m)nxFc1EKEHHr$$8Y1OY;WuM; zpsmxF*FGrp@Cix%<(#N*Yuq7W(Al&onS1nr8ufnC;`RSUtySjrzNw+D@`D6sP4@ZCCvmI<}$(9f*|fo7&s(aGXC|lcraEL&fo82F6TPBi7JRc*TA)Q4#U}IC zL!4g<21Lu^$`Lc;>c@zHPS*XtC)By(1(T8eOz31e0jcv8jA2#yA>BG$2)w5;r|@!P zxU5IYt(~&@x973Bk$%ijNfFhuQ=dLk!u?FN0)PI456bXW|na zB$+5+YFY51*iWFx-V5f|p(ueRj7PEDio>z4O)@$EsMYTZ^|Rff&?MQ8#BMBkap!Q* z^3t7}y+rMtT3CkTkb!C1hM01LCZZc2Lfxx#cdPaYSLqKfB( z=IuYuOe1T0n|gQ4hzi>e1MaohmJ8u`*v4=fu@jr?l%O9d&u*y%ryOU#~D#zMC}-ut52 zPLlBeh>)u#abVD#-{w(&-EoSi09NRc^3}q~5-Kxg<93<3)ZmZrVWxE=pA=c62g=P5 z6pNf%gpHh$xQNrRCCEx$kN^-MxufI+z9rs3RzzPx(Wm9_Y45%Xh^Kxk=L8~~*(d@- zxg~v!=H*G!(Y`{g+ucn{p1#!HEh4ZmW*({IGg94;+!o+jxT}%=Gd$LWVXn+nD;QI#sltkdLZ#mFfiIskQV{^aY?PNSFjOW)i;eq~NrNjlhQ-I~7j zfQroQ)|Xz_p@vubI0V>eBUmSkyf+3A6ExCb{RCL1-@V=PpHyaNmxd`pc}_uy(DkVV z_s&g1$J0H582nbXhMe1a^o`Hd?rAZUk}8kN*-iOZ`p^Xz9wKa4olj zVP(WU^tI!MO$!Uwe_XOmW&qZ^|79ou{ zcg`5s1yr{02dM^vZlE(a=mbQGDyj&0sOq3A6_&8D+N)Ti)+lVwBIuhNmF)Q z+n5OxW4EnFt z&G5v&Ck$b2mW@7{4J`k~Khylt<(fm1m^`2kgA2(s+hV(Eo;@m8n(c5Vz6$_mgWL7N zKaQOxka&F;cMe!Tpt|-eJ@%V15j7Wha}CIM_mknQ3`UA9e}Nt&^(cXGi(;y}R^27{&;B;0}-Ih;IGz-FN;d)Glnx`{OQy#y}N( zku|0P_?UV8#1}NJVlrib1_#1jq2BfRypXXaIl7!1^f|QrS9AJY=;P*2u~R9ysVitTXl)sKWD z8&GQQ1DY<;=)cq+Q&L&>>z|8FNoU)xeky8L@PS}t1c|St!bv)NVt36-75u)p^Z)ht z>|!$ZH;wTRvhFABqVY=;+AZ8g=d8UXzIuj~j3s*>BsalJrzJp-_vlmT^&5d}-s`>T z0J8xi6MTc#0f2jGBsCnRpKh|>fa@p2Zys2HW=x=vkZ~DKN}(mglo~caqzn(#lHiF) z`)@OYy)W~fUR#0e2gy^Tn-K?&@m}x`a_n@{bUny0cadnB2_rn@$pRB0tSD+pE#HpW^ZJb+$aT$?ogsEVke<5Zcl2UW*P!EMLBh ze4*2K1ID&jP!J1Jk1rUL87|KKUkj=s!FR6VD zDJz&7l4RH4SU>=Fi~?-D({36h1nk^m_44im6OxQ1NC^OBZ0^|PPE76JIygLa!^h~m z3vQ|M{IxXL3H`0Yw}m*L=n&iJi_-zF!S%=NTLL@{rG`&s51)3P(0Glc9s*{Ud?522 zyp(yKFldTSU9=Vdth+SjdNcGI$ZeqWFQQlsdlDaU1bm-LpUrK5{Gh^=D$b~ah%Lz7 z6QAMTjB781E+r{2olOSRYt1}t$TzE5*#C!IN|>79UL(po_Xt8;lQ3$R%3?V0xoXtK zu_By>Sr0tR_bzgn&E8Q6Vx#kw1|E^o;+rhTe1!PFY%Bc$P=kf{D(x?;43?>tB$%;l zue_V=)dN+-ZYvF>gIMrq5`!Ueow%3my?y3Kx*3I?RgNuu%wy}1E|{Ox|8s_I4$cmp z0easFidosT*<#125B!EX_FHs@&(dOgON5Gy&b7681LiSQ?uB7!T`b9SQ7WKhE|Fpb z)up-|s}ck!+?PMSxCwt50~s*$L?ME>K#Z0(wl zjV?PeBI5j8!8RZtVb~4YsLa8RuvHd#cl$`U1b3Clttj3)+r4#9;Ov<6t~sH3odNIT zo%6uCq%`S>myM=M9C?8=kC$y)m5NUu5GHL6?Zk8$dVM%1?_+sFp_sc$h|F9Xgod~p zt`~+8I3nRs(r5K2n9Il-O@O6gURNEx&&;b=ZJ&M6XRX|xCxdwNegZsRdHQ%Ri(7eC z)(A;od>i1UJ-GL=z^|AvxC^8X{k|0q+*!9n3 z&Rw`=WH1D%Q%nB!e^4{iR(KHGR;vaqa9dGN)~Iq@D*c|ooN$PF?Q(^#EEG{j?2A}9 z=9ASf2P--gGb~EFo7ZRBq9jWw8CY1$>|P?kA$XmA)Jc{t(|tEH+_J;Foc@kI%W zb44`}Wi1q2R_@8jjR#i?V@NAxAeXMIjjaa;I*;(vl~riyw_1h03y_0AvfgwE=vGl5 z?Mh5%ui&ZY-2L>gTzGQ{l^Yy9Ec%-4!;XNnZa;qo@mq>dd0yt(WXnGs6 z$qdPb8$-vmX_j3A+d8GSBkj1aeorJ=IujGyseW0hWI`eWg zAUPZV1N6H`XZ1h~Fbtk>d^C`;w2bc+-wKb=Hb?883m5~TV(cWt#XIev2#M3?829+V7UsN! z8RT8bwXBt>V3?`tj9Yg$BnA*RTpnMo|27^qGR7F-DXskQD%TEAgO{vVfrk>JpGXZJ9H za67RZ%m(n1%@yrU^Q&B&Pe@ckk>(e4IRrT`Y@&c>_IgGu{REVs4>qX8xIS$d?koEH z9O4caC$Y;Q9Hm081c3Xb>`DV=S3ZWKqu&--;xZxHxSq~#(sv4vPnitl)G&=&EHD3APvTiUe8}0q zk@;_0pDl#+d1jqYKzEv?Q`qju%eY1PlD@CchaYF^HP{`E3^1vUTALUaYRGi5ID@@I z5%oJjm0{4B;OB>e8b2t+z+DVrM=L8<<2B`keOg`S7Mh>^e3VJybYCfVPT#mF-Yd;`iev*dT0W$@;kAD26rLma`>>HZ?_? zsw2=3B?lSNH7&|H&yo?HyfE-ZB-s(g&RW&Ud%ll?o5eLFt0I+01BKUVKdML3<|E&n zMK+Pf8%3sYt(il!fo>_yOBgd7u+Zf>t}kv~z4UuaKxP&0q=YGC(z)e&DhEWuCqYhn zmW7p#n@ZLpOQ`o%U&M|#>nzbWN3zmBD2ogh{396HXpw|+Q*aN^BD08y{nZX|#^CZ}A1fda@H8Y!!VKIG9DW+k zjTNcr9pT2onfDA;qi+CDSZ96}_q@+N%r-(|u`q0cmGcd^Nv8+A(D-d8da+qU96kUI zkFq6S-i&}KP)Md>gX#R2@vNbEPpfUscy%M%c4BTQ3D6&9j%0Tp-k7U`aK{|!So5!k zT%A4n`}7ID_;>kMq}eifuS6o%quX6Zcg-#RJvv|N+HsM>5&1CG5tzXndtFSBg~cDP z%dQ6$=2znsW;a;)Djo^0Rem3P0Pp0&SmkYqwSva4e?9qHVwB#Sco;!I()GVknR(pvQ)q8`q3fp56M^U!;N_!=esMq}5K-#tXCAep62qIWF zH#k5AFdTtLb=gAF!AdznFZUm|5c9bhNbD6VW!KsQ42Qv*TS7ZE`NvA2A|Tj16kV)` zR~%#Ohi7z)#S}35t%z+f7`FG$&hGMy!^F8hwNtlsm+Ev@$zImJ=A1@1PODR@!iWyM zTe#$$Y=Rr5^^jP{Lw>Reheh08H|>MD^#ul=AA1&=U)7~PyUMIt{~l^kyRR#*s??*IIP6pS2>6)=15}WImKrpm#lw$9;F>=w0KT1x9$IF2 zd2!h!7F?nlzT|!)OYh6Mju8)GC>`7Jy_z9Mj8nt!I9J2;TvKLn5^3eW#Le zb$D@vB5R&nx~B+8xMXIJvUq3uv>pU{qA{>(J%yMy*y46fPxddW#Yq1HSAN*jQ_Mo> z413|2Be&Bv)xzCrf4>QeS(wA%iGT(U$rxT(VgW^hMlJD@T2k+)Q;q zxJ|z{5iK=3gd?+dA>5l;QgT=^MynAgf1P+t+?T@f9fDmu;>{`a?Jej;7`V0L%fD}f zLL_-zx3KXE`7(ZuA{5$Do}F7bfQ#VwI8(@U1T3lXooUV$Eqk_~ zAXg-P1kcno@EnZ+XzP!TS+L<(6f|@*wEjd#*#$@3t>N2fd_}WgE3(;1whVu)zTW&) z>bC6rXm$kQC-84zU>N%bCW~juv`}*^@XR%b;n5*-w}xTucHyL^BK%2{SA5HS((N-M z|1l7TNyw@4iB~`By>(=Q2P;NrBwe3%M*SjrZ%#%#$L*M9gR+aI@-6k$!|a!nm_Lm; zs_*;F?_k!Gq%Mbm(LR-K04n(fk>Kp>SS?BmiC=g}ls$E*f`j|Y-XHG?!Xh*} zaSIx%3Nyf^H4vDBbK4mtP!Kgt=n|tYA$wH^5^gEWpk5ZW1q((;5G)WJ#T}x6c-uw| zLGH%t_0xG2CYp$FB@COuaQV#1%QlwzJZ+Y&nzzH$#6L5sY-}`x*zO@5tf~8KNu~(Y z-q_0YqK>{rnWBd}Y4Se9g>GqAO^ukygrPYo*Kc0*&0BL&kKY=Rb*9Vv+|E#$f>?Ru z5F=9f>ZJu4z?h~JZsb~b#<~A!b!HMxPjnP&H`9VqiQvp9q0HK)LKkb&IS)NktQi2V zV6k){a-%J^UY@)cs z04Ysw2ap9LW=o3h;}evGw(kbi`&W~hio-iW#n`Tv%mK*pXj`JplfZqZCjv5Z3%UW4 zzk#wp+so6_cC6$)6UxC|4lj7_aC0Q(Lm-_@foQM*00a`2^AtRC0EK_fM_x4yQw<~>j^C(nY*IiK9CE1e%?~-=}xTlncO06zagiyywYDxi&Q)xx!WLKof?VE9t8{UIKH~Dx*y(GGDY6a}6)A?xKU1=%DNshyF`JM1xW^ac(d^1-5LJ$YQD z{V+!VEEt@Fq1|85OE8-%t(XfvX$9V3a|X;@F{Mgea*btKEAGL=ss@WGw8Au~x6jGr z=tZKzTh=#V_U=Grr<$q*MqYHyj_$PY{j4ZJ=E|1D1k@V08QkWCC~APgkJHvfxPFZ? zS#?|6U~VexM+dgFdExgDEMeU4*g>Z~O=ufFr5sexFb#&|Hv|$r*i#6c95uye{CFr{ zU~Jr%A@;s_467b+pppA{_wlNFu4f&jNjN#4HrkaRfA=VMmZ$&llH9odGSkhb`^>D5`GH{x6)S$LU5CB2i3@Nq^rS(@|oK93QJh>K#@@+cGG_zv7i zbG{r>FNscmx8C1+7dDD+UqgSNIm_Xs!lw(QucaJqNC>Oh5{ropyv^Z zCfMEt7q)Z@4wNgNqzq@J`xktDS|?)PiU+f}!gjKzVwxkuaQS^MnGTLWqb~yIV9LL% zYbn|-6CiVk1=@xI;CCUhp;aZHvI5Z$6T4xAMc>7a^87bl%m5e}0{o_Z6UZl1A_l^8F>$?a$y9^Y1q=_v0xfw zE@u`DS+d^VfLgaNW=Auqp>O`Wus7wk)`8K~a{wjuLYOpjitoMmbhk7U;mu0d83oGL zWC1o#TKKNZK%aB*cpjJL*0zcn?fm$f|E0LjeAd+1ELtRf*0)Q9sZB*19(DzM(T>$k zC;;n(+qrO5W><`TKN0mdkc_8lUUQBDg~xdGz^FpW7>Wocz1cmsk9C8%E}qsBl9VkO#2_a>=Uw8)}mGpa1^TIs-wFPMScH*ixe(22d3G_%*%6xOKJ-XPclrN?hH!_j%O z3XNnU$#{04RQ@uV6_(5dGcJzRY*vSW1mX*pd6G9`W9NyFgt1)M%fUv7zLr3-rG;hs zEB;c$xnFek?+rq2jK=aH6GTq^@Zz}dksK^kjn;liP7~vK5kYSYzPbp3WCG+A#(8zv zqWdIr^#BkraOXeFXqAH^+O?^AI&GYPQ5DH@I_mB2w2>ftWaiI6Ie!@f5+-=;Q27SKJls#^s}aX8l~J17Z$fDRSau?x`lC?Y?^K`u+b1bisi|w8B9blo9@xF7 z!*-EP7=LF{u0RDtMuOxBhn?(@L`a!|iWVt?z{x{CBQ}zvHv|uz8yVYG`O&#kJsfwu zXXsIHM3$=6m@&X8DrM=L=tG3m2C?V!q-swM%Y#5UAB13U+>}%2*GqS!?#2SD7EqGk zO#XH6%y?c&0fdQ+CFQ>pX7Q6VQAUs|kCcHyB&+YiCQzaG%poOJV|KX>_HuhP{Rr+#BsVXW)5b zb06XYgpohC*oLEL8(6c%2C&2J+ra@%Wq1F8FR?irz9kYOv+ib&VCd?QQSto|6FJKS zgC8>{oN2+$ICbvX^=X_Rl-V-wSLt1b3#ic-cq9HId#2L_fouJ0jZ8IN9yg5v^yOEA zrJ>rLMso!lhKnrS!2!V`S$@;6-HeLSJxD(kV1CIRIniN&8gatbIFqIk3zKy$61odV2Du zVon9agMUahu~4iT>p>gi)tPBe0d(SfUcecanba`+?y@mhr?FI$8NdZo$(ajdC%Cr5 zvs~{|I)c=eQ}UxXDMQi7AzG}$=)XO);Q0mGpscqKHX%s&U;t}3w9CW`Qmd=ISFh;#ki!bQYRkj*i{iV(rUFzjFs#lFYa_#* z3+c0ZlV=|G<2eP5$wJ||C@VQwsyFjY6dFm^v;(i5GXK>f_#RPk^Oxe_R(VW+>)me+ zN6nP;w7S&j>&4^wb&a~0d#RBP6gw@WUQjETk4+UD{=4SjARiMJcf1$mZo6gOGiD7$ zD#3{}O|5x%4e{{{!4Q9!5#$?n=zW9_wH=3fky;QH|KL2g&9~N)Z_J{Sz)v#hhjpKl zRCuv1fhf|-9t{atfa>Jb%@)E{$ijd(;4naOd8Zo*gj0w31{>42>>hcAVL|G9%o@YD zeV(jwuyP3G9gqQ>%mUhdA#;Yd2xh`sUr%P`=-^g>`LcFr+$={_#}c-VGgCNI`JCe> z?)G_#T+oTqs8wfWFiFfb(_R#V_ur#SF3 zG#7;Jf&Wsg9timx3YPf1mT}8kH)8+STTSHc=de|!dVWQU#q2D6cJZp9;OZ>BpBWQs zq;qH6&v%CtN}q+GK-}rE3_FD!TcvcV-s155e#dxIsGkt~sY}Ls# zb9-_&)1XNit=Qbe9duc-dMN0)*aj4Kl>g#M+lWoVRXV7Ok z`a=r*F9*Vo`wXW%N1&XA6A6araJJvg!7QJ}tkrS~0({&CWfGOV0n4B^^c0q#=fSS! z84rABAvm<9t+&YB>??;t)+-gMG2z0lH~g!83Or1%eT}_r5c1_VzR}gK3BEEkZYssC zS2>Sqv2TQT3lsf{ovCc>;sLL)OBFFW;;(!%PWA5h?iDH1<^9GY%es#(E;o(fy#QkM zp@CO&d!yJO6w8orHlB?!xTRrzIKlv;k0mUrF#K(Od?E?`?KxF3e zvy(rO#vO_qkp>GukhR23f7bocl<4ZiABM4q?h7f}r24F+qAdPZ_2EaK{-veSWkc$# z%VtafPI#4+`ul+C{Bg*KQT`x74Xw|IwzV=U?4F)wwO}mC7tqmk7Znpt$9phw4d{0S zrvrR+#z0@`;3R){y#*-G&$$r)tw5hxNiAza3Sh_VJ7E>dX7aYLrPqljzp4e1j~+p# z#B>yPfuUfW+VFkO48B|L-h3JBwoXy^6tVr4QE@u0+<9bc5o5TtAJogab}}QW ze8DfnFdnik=0{2G)k~??Fu_nZF+!vrY7z@$ zUjOJK(2BOxG|K*$`m+kXQfJF?*fycFGOjI>2g=aUaktrtqjeqDIjvT;6MBgwMi`S_ zrmLlu4MIn;5kX}Ls&PbZ&MeUTI{*b@B#VmO_!>}rP@lSpg6{tMEG9IRIxcxn^N*po ziG!hWA;82?d6bZjK!7_IrFLogB~{}C&o6(_nZREHZv<8e8H05*na(ue;)xd*&LBKO zTLj2FiM}4m+ksOP{9wNMTt@N3R3iC3qOgM$rXFn1y%y!Q$tieVS>l4(c(&NvAaEIn zDC}LGCqmv{s@7D&Z4OgXUqFwbqD~U4PLWW!64Q5;5ufORSY8vgD5^6_~hzK z;-hrzNl3P7xgi~QTBaV--EcXeB-4K*a`DL~tOPIr+Gag8(QK)1M@YfNThFb0`5{~f z0Ey*StZgA-u5rbApqoB<`ubKXKu6wMD(91R;59DIs!|UQtxBQ1Kz6-qeeJvyY`6Sk zPzr}J#db&syxy;v4C4?oUL)>?L9z09sLFd>!L0fNqRMW7%=DTo60+>oZswJ}yzqe{_W; z3Qo&Gl{=2a=OF|5{q8M>fFEQi285k_>j6S=H5bjpvsv!l#d$L1 zPhm141D*_L>%!0T7^F=FPUEpT$RcIepQb+ty27}{g-EXmmII{L4+*U7;|ATWeb+`_ z1K-GKoUID9!aWuJaK*-Kc1}R4>=ylh#990kp%UDrR2A(xEl+qH4;wVN9?_4Evdx2w zp`vIDuE_!i@WHWR4NbYSM!s3Ro|5(q;{{phFIha-g%$};u$W{LWI?74fnLTgxAol? z@_pBb%YRl$=uH2_OIf000000000000000 f00000000000000000000000000000000000S$FJ$ literal 0 HcmV?d00001 diff --git a/easycontrol/app/src/main/res/drawable/scansion.xml b/easycontrol/app/src/main/res/drawable/scansion.xml index c6f658f4..b2ef6005 100644 --- a/easycontrol/app/src/main/res/drawable/scansion.xml +++ b/easycontrol/app/src/main/res/drawable/scansion.xml @@ -1,9 +1,9 @@ + android:width="200dp" + android:height="200dp" + android:viewportWidth="1024" + android:viewportHeight="1024"> + android:fillColor="#FF000000" + android:pathData="M783.6,240.4l-60.6,60.6A298.7,298.7 0,1 1,469.3 216.7v85.3a213.3,213.3 0,1 0,193.5 58.2l-60.4,60.4A128,128 0,1 1,469.3 391.5V512a42.7,42.7 0,0 0,85.3 0V128h-42.7a384,384 0,1 0,271.6 112.4z" /> diff --git a/easycontrol/app/src/main/res/layout/activity_active.xml b/easycontrol/app/src/main/res/layout/activity_active.xml index 7e5654b2..248e4d3e 100644 --- a/easycontrol/app/src/main/res/layout/activity_active.xml +++ b/easycontrol/app/src/main/res/layout/activity_active.xml @@ -21,27 +21,60 @@ android:paddingBottom="60dp"> + android:paddingStart="15dp" + android:paddingTop="10dp" + android:paddingEnd="15dp" + android:paddingBottom="10dp"> + + + + + + + + + + android:paddingStart="15dp" + android:paddingTop="10dp" + android:paddingEnd="15dp" + android:paddingBottom="10dp"> + android:textSize="@dimen/middleFont" /> + android:textSize="@dimen/smallSmallFont" />