app/src/main/java/com/safeluck/floatwindow/FloatingService.java
@@ -86,9 +86,7 @@ NONE, USB_PUSH, USB_RECORD, ANDROID_RECORD, P2_USB_PUSH, P2_USB_RECORD ANDROID_RECORD } // AIDL Binder @@ -107,9 +105,9 @@ } @Override public void stopMedia() throws RemoteException { public void stopMedia(MediaArgu media) throws RemoteException { Timber.d("stopMedia called via AIDL"); FloatingService.this.stopMedia(); FloatingService.this.stopMedia(media); } @Override @@ -190,14 +188,12 @@ return; } // usbCameraId == 2:走 P2 跨进程服务,支持两路 USB 同时工作 // usbCameraId == 2:走 P2 跨进程服务,支持两路 USB 同时工作(本 Service 不再跟踪其状态) if (media.isUsedOutCamera() && media.getUsbCameraId() == 2) { stopCurrentManager(); ensureP2Bound(); if (p2Service != null) { try { p2Service.startMedia(media); currentManagerType = media.isPush() ? ManagerType.P2_USB_PUSH : ManagerType.P2_USB_RECORD; } catch (RemoteException e) { Timber.e(e, "startMedia forward to P2 failed"); notifyCallback(1, -3, "启动P2服务失败: " + e.getMessage()); @@ -205,7 +201,6 @@ } else { // 等待连接完成后执行 pendingP2StartMedia = media; currentManagerType = media.isPush() ? ManagerType.P2_USB_PUSH : ManagerType.P2_USB_RECORD; } return; } @@ -242,7 +237,7 @@ } /** * 停止当前管理器 * 停止当前本地管理器(仅管理本进程中的 USB(P1)/Android 录像或推流) */ private void stopCurrentManager() { switch (currentManagerType) { @@ -261,18 +256,6 @@ androidCameraRecordManager.stopRecord(); } break; case P2_USB_PUSH: case P2_USB_RECORD: if (p2Service != null) { try { p2Service.stopMedia(); } catch (RemoteException e) { Timber.e(e, "stopMedia forward to P2 failed"); } } else { pendingP2StartMedia = null; } break; case NONE: break; } @@ -280,11 +263,26 @@ } /** * 停止媒体 * 停止媒体(通过 AIDL 调用,带 MediaArgu,用于区分 P1/P2) */ private void stopMedia() { Timber.d("stopMedia called"); stopCurrentManager(); private void stopMedia(MediaArgu media) { Timber.d("stopMedia called, media=%s", media); if (media != null && media.isUsedOutCamera() && media.getUsbCameraId() == 2) { // P2 USB 摄像头由 P2UsbCameraVideoService 管理 ensureP2Bound(); if (p2Service != null) { try { p2Service.stopMedia(media); } catch (RemoteException e) { Timber.e(e, "stopMedia forward to P2 failed"); } } else { pendingP2StartMedia = null; } } else { // 其他情况(包括 P1 USB 与 Android 相机)由本 Service 自己管理 stopCurrentManager(); } } @Override @@ -296,7 +294,7 @@ @Override public void onDestroy() { super.onDestroy(); stopMedia(); stopCurrentManager(); mCallbacks.kill(); if (p2Bound) { try { app/src/main/java/com/safeluck/floatwindow/manager/AndroidCameraRecordManager.java
@@ -179,7 +179,7 @@ try { // 创建新的视频文件 currentVideoFile = VideoFileUtils.getVideoFile(context, mediaArgu.getTfCardFlag()); currentVideoFile = VideoFileUtils.getVideoFile(context, mediaArgu.getTfCardFlag(),0); if (currentVideoFile == null) { Timber.e("Failed to create video file"); return; app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java
@@ -283,7 +283,11 @@ int fontSize= 24; private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); private void setWaterMask() { if (mediaArgu.getUsbCameraId()==2){ GlobalData.getInstance().getCameraTag="_P2"; }else{ GlobalData.getInstance().getCameraTag="_P1"; } // 防止重复 schedule(startPush 可能被多次调用) if (watermarkFuture != null && !watermarkFuture.isCancelled()) { return; @@ -329,7 +333,10 @@ double speed = GlobalData.getInstance().parseWaterMaskInfo("speed", 0.0, GlobalData.ShareType.DOUBLE); String czh = GlobalData.getInstance().parseWaterMaskInfo("car_license", "无", GlobalData.ShareType.STRING) + GlobalData.getInstance().getCameraTag; String czh = GlobalData.getInstance().parseWaterMaskInfo("car_license", "无", GlobalData.ShareType.STRING) + GlobalData.getInstance().getCameraTag; baseY = fontSize*11/10+baseY; watermarkParam = new WatermarkParam(10,resolutionArr[1]-baseY,czh +" "+String.format("速度:%.1f",speed)); watermarkParamList.add(watermarkParam); app/src/main/java/com/safeluck/floatwindow/util/VideoFileUtils.java
@@ -67,9 +67,16 @@ * 生成视频文件名(时分秒.mp4) * @return 文件名,例如:143025.mp4 */ public static String generateVideoFileName() { public static String generateVideoFileName(int usbCamId) { SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss", Locale.getDefault()); return timeFormat.format(new Date()) + ".mp4"; if (usbCamId==2){ return timeFormat.format(new Date()) + "_P2.mp4"; }else if (usbCamId==1){ return timeFormat.format(new Date()) + "_P1.mp4"; }else{ return timeFormat.format(new Date()) + ".mp4"; } } /** @@ -78,24 +85,24 @@ * @param tfCardFlag 0-内部存储,1-外部存储 * @return 完整的文件路径 */ public static File getVideoFile(Context context, int tfCardFlag) { public static File getVideoFile(Context context, int tfCardFlag,int usbCameraId) { File dateDir = getVideoDirectory(context, tfCardFlag); if (dateDir == null) { return null; } String fileName = generateVideoFileName(); String fileName = generateVideoFileName(usbCameraId); return new File(dateDir, fileName); } /** * 获取视频文件路径字符串 * 获取视频文件路径字符串 只能获取到内部相机文件的路径 * @param context 上下文 * @param tfCardFlag 0-内部存储,1-外部存储 * @return 文件路径字符串 */ public static String getVideoFilePath(Context context, int tfCardFlag) { File file = getVideoFile(context, tfCardFlag); File file = getVideoFile(context, tfCardFlag,0); return file != null ? file.getAbsolutePath() : null; } }