diff --git a/.idea/misc.xml b/.idea/misc.xml index a740c72..1945de5 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java b/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java index f4b76a7..f9cb506 100644 --- a/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java +++ b/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java @@ -21,6 +21,7 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.KeyEvent; import android.view.View; +import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AlphaAnimation; @@ -391,15 +392,17 @@ public class WebViewActivity extends BaseActivity { webSettings.setBuiltInZoomControls(false); webSettings.setDisplayZoomControls(false); webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); + webSettings.setDatabaseEnabled(true); + webSettings.setAllowContentAccess(true); webSettings.setAllowFileAccess(true); + webSettings.setJavaScriptCanOpenWindowsAutomatically(true); webSettings.setLoadsImagesAutomatically(true); webSettings.setDefaultTextEncodingName("utf-8"); webSettings.setUserAgentString(""); - webSettings.setMediaPlaybackRequiresUserGesture(false); // 允许自动播放 - - // 适配HTTPS/HTTP混合内容 + webSettings.setMediaPlaybackRequiresUserGesture(false); + binding.web.setLayerType(View.LAYER_TYPE_HARDWARE, null); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE); + webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } //加载web @@ -414,26 +417,37 @@ public class WebViewActivity extends BaseActivity { @RequiresApi(api = Build.VERSION_CODES.O) @Override public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) { - LoggerUtil.e("WebViewCrash", "WebView 渲染进程崩溃,OOM被杀: " + !detail.didCrash()); + LoggerUtil.e("WebViewCrash", "WebView渲染进程崩溃,OOM: " + !detail.didCrash()); webViewAlreadyDestroyed = true; try { - view.stopLoading(); - view.loadUrl("about:blank"); - view.clearHistory(); - view.clearCache(true); - view.removeAllViews(); - view.destroy(); + if (view != null) { + ViewGroup parent = (ViewGroup) view.getParent(); + if (parent != null) parent.removeView(view); + view.stopLoading(); + view.loadUrl("about:blank"); + view.clearHistory(); + view.clearCache(true); + view.removeAllViews(); + view.destroy(); + } } catch (Exception e) { LoggerUtil.e("WebViewCrash", e.toString()); } - ProcessPhoenix.triggerRebirth(WebViewActivity.this); + handler.removeMessages(TYPE_REFURBISH_WEBVIEW); + handler.sendEmptyMessageDelayed(TYPE_REFURBISH_WEBVIEW, 2000); return true; } @Override + @RequiresApi(api = Build.VERSION_CODES.N) + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + return false; + } + + @Override + @SuppressWarnings("deprecation") public boolean shouldOverrideUrlLoading(WebView view, String url) { - view.loadUrl(url); - return true; + return false; } }); binding.web.setOnLongClickListener((View v) -> { @@ -498,6 +512,10 @@ public class WebViewActivity extends BaseActivity { @Override protected void onResume() { super.onResume(); + if (binding != null && binding.web != null) { + binding.web.onResume(); + binding.web.resumeTimers(); + } resumeTimeMs = System.currentTimeMillis(); leaveScreenSave(); binding.layoutPass.setVisibility(View.GONE); @@ -515,6 +533,10 @@ public class WebViewActivity extends BaseActivity { @Override protected void onPause() { super.onPause(); + if (binding != null && binding.web != null) { + binding.web.onPause(); + binding.web.pauseTimers(); + } KeyboardUtil.hideKeyboard(binding.getRoot()); } @@ -534,6 +556,8 @@ public class WebViewActivity extends BaseActivity { try { binding.web.loadUrl("about:blank"); } catch (Exception ignore) {} try { binding.web.clearHistory(); } catch (Exception ignore) {} try { binding.web.clearCache(true); } catch (Exception ignore) {} + ViewGroup webParent = (ViewGroup) binding.web.getParent(); + if (webParent != null) webParent.removeView(binding.web); try { binding.web.removeAllViews(); } catch (Exception ignore) {} try { binding.web.destroy(); } catch (Exception ignore) {} } diff --git a/app/src/main/java/qianmu/container/handler/ContainerHandler.java b/app/src/main/java/qianmu/container/handler/ContainerHandler.java index 534217f..603839a 100644 --- a/app/src/main/java/qianmu/container/handler/ContainerHandler.java +++ b/app/src/main/java/qianmu/container/handler/ContainerHandler.java @@ -66,13 +66,13 @@ public class ContainerHandler extends Handler { public static final int CLOSE_LOCAL_SOCKET = 4; //关闭本地socket public static final int START_SOCKET_SERVER = 5; //启动socket服务 public static final int STOP_SOCKET_SERVER = 6; //停止socket服务 - public static final int UPDATE_APP = 120 * 1000; //app更新包时间间隔 + public static final int UPDATE_APP = 180 * 1000; //app更新包时间间隔 public static final int MQTT_ALIVE = 7; //app更新包时间间隔 public static final int GET_TIME_TAMP = 8; //获取时间戳 public static final int INIT_NOVA = 9; //获取时间戳 public static final int INIT_JXB = 10; //设置机械臂 public static final int INIT_JXB2 = 11; //设置机械臂 - public long goNavTime =0; + public int goMemoryTime =0; private WeakReference weakReference; @@ -83,7 +83,7 @@ public class ContainerHandler extends Handler { sendEmptyMessageDelayed(DELAY_TIME, DELAY_TIME); sendEmptyMessageDelayed(UPDATE_APP, UPDATE_APP);//app更新 sendEmptyMessageDelayed(GET_TIME_TAMP, 100000);//获取时间戳 - sendEmptyMessageDelayed(INIT_NOVA,1000);//获取时间戳 + sendEmptyMessageDelayed(INIT_NOVA,60000);//获取时间戳 sendEmptyMessageDelayed(INIT_JXB,182000);//设置机械臂 sendEmptyMessageDelayed(INIT_JXB2,186000);//设置机械臂 } @@ -128,9 +128,9 @@ public class ContainerHandler extends Handler { public void onSuccess() { //检查,MQTT状态 mqttState(); - sendEmptyMessageDelayed(MQTT_ALIVE,15000); - sendEmptyMessageDelayed(MQTT_ALIVE,35000); - sendEmptyMessageDelayed(MQTT_ALIVE,55000); + removeMessages(MQTT_ALIVE); + sendEmptyMessageDelayed(MQTT_ALIVE,20000); + sendEmptyMessageDelayed(MQTT_ALIVE,40000); Constant.networkState=true; } },new QueryErrorListener() { @@ -139,8 +139,11 @@ public class ContainerHandler extends Handler { Constant.networkState = false; } } ); - - getMemory(); + if(goMemoryTime>5){ + goMemoryTime = 0; + getMemory(); + } + goMemoryTime++; // watchDog(); getCoreServiceState(); // DeviceData.getPrimaryMachine(null, this::updateClientStateByIP); @@ -192,15 +195,6 @@ public class ContainerHandler extends Handler { // LoggerUtil.e("ContainerHandler","cpu使用率:"+cpuUsage+"%"); // } // - if(totalPss/1024>1000 && DeviceData.getDeviceInfo(DeviceData.HINT_DEVICE_TYPE).equals("导视") && !Constant.whoActivity.equals(Constant.ROUTE_WEB_VIEW)){ - //内存超过了1G会出现卡顿 - long currentTime = System.currentTimeMillis(); - if(currentTime-goNavTime>360000){ - LoggerUtil.e("getMemory()","内存超过1000 进入导视释放内存"); - ARouter.getInstance().build(Constant.ROUTE_WEB_VIEW).withBoolean(Constant.KEY_LOAD_H5_URL, true).navigation(); - goNavTime = currentTime; - } - } if(totalPss/1024>1400){ //内存超过了1G会出现卡顿,内存溢出问题。重启设备。 LoggerUtil.e("getMemory()","内存溢出重启软件"); @@ -340,7 +334,9 @@ public class ContainerHandler extends Handler { //30分钟定时定时拉取更新APP private void updateApp(){ sendEmptyMessageDelayed(UPDATE_APP, 1800*1000);//app更新 - weakReference.get().appUpdate(); + ContainerService service = weakReference.get(); + if(service == null) return; + service.appUpdate(); //同屏接口 DeviceData.getPrimaryMachine(null, this::updateClientStateByIP); } @@ -349,7 +345,9 @@ public class ContainerHandler extends Handler { * 获取时间戳设置系统时间 * */ private void setSystemTime(){ - weakReference.get().getCurrentTimestamp(); + ContainerService service = weakReference.get(); + if(service == null) return; + service.getCurrentTimestamp(); if("指路机".equals(DeviceData.getDeviceInfo(DeviceData.HINT_DEVICE_TYPE))){ //开启背景音乐 diff --git a/app/src/main/java/qianmu/container/mqtt/MQTTService.java b/app/src/main/java/qianmu/container/mqtt/MQTTService.java index b7b535c..80944b6 100644 --- a/app/src/main/java/qianmu/container/mqtt/MQTTService.java +++ b/app/src/main/java/qianmu/container/mqtt/MQTTService.java @@ -143,7 +143,7 @@ public class MQTTService extends Service { userName= DeviceData.getDeviceInfo(DeviceData.HINT_DEVICE_CODE); if(Constant.tywx){ passWord= AesUtil.md5(DeviceData.getDeviceInfo(DeviceData.HINT_DEVICE_MAC, SignWayUtil.getEthMacAddress())); - Log.e("MQTTService","passWord:"+passWord); + LoggerUtil.e("MQTTService","passWord:"+passWord); }else { passWord= MqttData.getMqttToken().getPassword(); } @@ -185,8 +185,9 @@ public class MQTTService extends Service { // 用户名 conOpt.setUserName(userName); // 密码 - conOpt.setPassword(passWord.toCharArray()); //将字符串转换为字符串数组 - + if(!StringUtil.isEmpty(passWord)){ + conOpt.setPassword(passWord.toCharArray()); //将字符串转换为字符串数组 + } // conOpt.setAutomaticReconnect(true); // last will message @@ -234,11 +235,11 @@ public class MQTTService extends Service { sendOffline(); disconnectMqtt(); stopSelf(); -// try { -// client.disconnect(); -// } catch (MqttException e) { -// e.printStackTrace(); -// } + try { + client.disconnect(); + } catch (MqttException e) { + e.printStackTrace(); + } EventBus.getDefault().unregister(this); super.onDestroy(); } @@ -255,8 +256,8 @@ public class MQTTService extends Service { LoggerUtil.e(TAG,"MQTT尝试重连"); client.connect(conOpt, null, iMqttActionListener); } - } catch (MqttException e) { - e.printStackTrace(); + } catch (Exception e) { + LoggerUtil.e(TAG, "MQTT连接异常: " + e.getMessage()); } } @@ -462,7 +463,10 @@ public class MQTTService extends Service { CloseMqttBean closeMqttBean =new Gson().fromJson(msg, new TypeToken() { }.getType()); - LoggerUtil.e(TAG, "MQTT:"+closeMqttBean.getType()); + if(closeMqttBean == null || closeMqttBean.getType() == null){ + LoggerUtil.e(TAG,"sendCommand: type为空,忽略消息:"+msg); + return; + } if(closeMqttBean.getType().equals("app-update")){ //APP下发 appUpdate(closeMqttBean); @@ -484,6 +488,7 @@ public class MQTTService extends Service { SignWayUtil.shutDown(); }else if(closeMqttBean.getType().equals("device-time-update")){ //定时开关机 + if(closeMqttBean.getData() == null || closeMqttBean.getData().getTime() == null) return; PowerData.savePowerList(closeMqttBean.getData().getTime()); }else if(closeMqttBean.getType().equals("device-time-clear")){ @@ -518,6 +523,7 @@ public class MQTTService extends Service { } }else if(closeMqttBean.getType().equals("device-edit")){ //设备信息编辑 + if(closeMqttBean.getData() == null || closeMqttBean.getData().getDevice() == null) return; MqttDataBean.deviceData device = closeMqttBean.getData().getDevice(); DeviceData.saveDeviceName(device.getName()); DeviceData.saveDeviceInfo(DeviceData.HINT_DEVICE_TOUCH, String.valueOf(device.getTouch()));//设备触摸 @@ -531,7 +537,6 @@ public class MQTTService extends Service { DeviceData.saveDeviceInfo(DeviceData.FLOOR_NAME, device.getFloor());//楼层名称 if(device.getFloorCode()!=null){ DeviceData.saveDeviceInfo(DeviceData.FLOOR_CODE, device.getFloorCode());//楼层code - } FloorData.getDeviceOptionsNew(DeviceData.getDeviceInfo(DeviceData.HINT_REG_KEY),null, null); } @@ -663,9 +668,9 @@ public class MQTTService extends Service { } else if (!"".equals(Constant.androidBoardType)) { SignWayUtil.takeScreenshot(path); int retryCount = 0; - final int MAX_RETRY = 15; - final long SLEEP_MS = 300; - long lastSize = 0; + final int MAX_RETRY = 16; + final long SLEEP_MS = 1000; + long lastSize = -1; while (retryCount < MAX_RETRY) { File f = new File(path); if (f.exists()) { @@ -679,12 +684,12 @@ public class MQTTService extends Service { } lastSize = currentSize; } + retryCount++; try { Thread.sleep(SLEEP_MS); } catch (InterruptedException e) { break; } - retryCount++; } } else { LoggerUtil.e("screenShot", "root截屏"); @@ -749,6 +754,7 @@ public class MQTTService extends Service { final String localPath = StringUtil.strSplice(Constant.CACHE_PATH, "update/", appName); FileUtil.downloadFile(url, localPath, () -> { isDownloadFile = false; + LoggerUtil.e("uploadApp", "APP下载完成"); AppUtil.installApp(localPath, DeviceUtil.getPackageName(), DeviceUtil.getPackageName(), true); }); } @@ -763,7 +769,7 @@ public class MQTTService extends Service { try { SSLContext sc = SSLContext.getInstance("SSL"); try { - sc.init(null,trustAllCerts,null); + sc.init(null,trustAllCerts,new SecureRandom()); SSLSocketFactory factory = sc.getSocketFactory(); conOpt.setSocketFactory(factory); } catch (KeyManagementException e) { diff --git a/app/src/main/java/qianmu/container/service/ContainerService.java b/app/src/main/java/qianmu/container/service/ContainerService.java index f8a72dc..76eae45 100644 --- a/app/src/main/java/qianmu/container/service/ContainerService.java +++ b/app/src/main/java/qianmu/container/service/ContainerService.java @@ -89,6 +89,7 @@ public class ContainerService extends Service { initFirstTime(); initTempTime(); EventBus.getDefault().register(this); + LoggerUtil.e(TAG,"启动ContainerService"); handler = new ContainerHandler(this); } @@ -154,7 +155,7 @@ public class ContainerService extends Service { try { ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); List appProcesses = am.getRunningAppProcesses(); - if (appProcesses == null) return false; + if (appProcesses == null || appProcesses.isEmpty()) return false; for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { if (!appProcess.processName.equals(DeviceUtil.getPackageName())) continue; if (appProcess.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) @@ -172,32 +173,56 @@ public class ContainerService extends Service { * 检测应用状态 如果在后台 唤醒到前台 */ public void detectionAppState() { - final ActivityManager manager = (ActivityManager) MyApplication.getInstance().getSystemService(Context.ACTIVITY_SERVICE); - // 获得手机进程列表 - List infoList = manager.getRunningAppProcesses(); - String packageName = DeviceUtil.getPackageName(); - for (ActivityManager.RunningAppProcessInfo info : infoList) { - if (packageName.equals(info.processName) - || "com.android.packageinstaller".equals(info.processName) - || "com.google.android.packageinstaller".equals(info.processName) - || "com.frogshealth.qianmu".equals(info.processName) - || "com.tencent.wmpf".equals(info.processName)) { - if (info.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { - return; + try { + ActivityManager manager =(ActivityManager) MyApplication.getInstance().getSystemService(Context.ACTIVITY_SERVICE); + if (manager == null) { + LoggerUtil.e("detectionAppState","ActivityManager is null"); + return; + } + // 获取运行中的进程 + List infoList; + try { + infoList = manager.getRunningAppProcesses(); + } catch (Exception e) { + LoggerUtil.e("detectionAppState", "getRunningAppProcesses error:" + e); + return; + } + if (infoList == null || infoList.isEmpty()) { + LoggerUtil.e("detectionAppState", "RunningAppProcesses is null"); + return; + } + String packageName = DeviceUtil.getPackageName(); + for (ActivityManager.RunningAppProcessInfo info : infoList) { + if (info == null) { + continue; + } + String processName = info.processName; + if (packageName.equals(processName) + || "com.android.packageinstaller".equals(processName) + || "com.google.android.packageinstaller".equals(processName) + || "com.frogshealth.qianmu".equals(processName) + || "com.tencent.wmpf".equals(processName)) { + if (info.importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE) { + return; + } } } + LoggerUtil.e("detectionAppState", "检测应用被退到后台,重新唤醒到前台"); + String deviceType = DeviceData.getDeviceInfo(DeviceData.HINT_DEVICE_TYPE); + if ("信发".equals(deviceType) || "双面屏".equals(deviceType)) { + Intent intent = new Intent( MyApplication.getInstance(), ScreenSaverActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MyApplication.getInstance().startActivity(intent); + } else { + LoggerUtil.e("detectionAppState", "跳转到导视"); + ARouter.getInstance() + .build(Constant.ROUTE_WEB_VIEW) + .withBoolean(Constant.KEY_LOAD_H5_URL, true) + .navigation(); + } + } catch (Exception e) { + LoggerUtil.e("detectionAppState","error:" + Log.getStackTraceString(e)); } - LoggerUtil.e("detectionAppState","检测应用被退到后台,重新唤醒到前台"); - if("信发".equals( DeviceData.getDeviceInfo(DeviceData.HINT_DEVICE_TYPE))||"双面屏".equals( DeviceData.getDeviceInfo(DeviceData.HINT_DEVICE_TYPE))){ - //信发 - Intent intent = new Intent(MyApplication.getInstance(), ScreenSaverActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MyApplication.getInstance().startActivity(intent); - }else { - LoggerUtil.e("detectionAppState","跳转到导视"); - ARouter.getInstance().build(Constant.ROUTE_WEB_VIEW).withBoolean(Constant.KEY_LOAD_H5_URL, true).navigation(); - } - } /**