| app/src/main/AndroidManifest.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| app/src/main/java/com/safeluck/floatwindow/FloatingService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| app/src/main/java/com/safeluck/floatwindow/MediaArgu.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraRecordManager.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
app/src/main/AndroidManifest.xml
@@ -34,6 +34,12 @@ android:name=".FloatingService" android:enabled="true" android:exported="false" /> <service android:name=".P2UsbCameraVideoService" android:enabled="true" android:exported="false" android:process=":p2" /> </application> </manifest> app/src/main/java/com/safeluck/floatwindow/FloatingService.java
@@ -1,7 +1,9 @@ package com.safeluck.floatwindow; import android.app.Service; import android.content.ComponentName; import android.content.Context; import android.content.ServiceConnection; import android.content.Intent; import android.os.IBinder; import android.os.RemoteCallbackList; @@ -32,6 +34,50 @@ // 当前使用的管理器类型 private ManagerType currentManagerType = ManagerType.NONE; // P2 跨进程服务(用于 usbCameraId == 2) private IMediaAidlInterface p2Service; private boolean p2Bound = false; private MediaArgu pendingP2StartMedia; private final IMyCallback p2Callback = new IMyCallback.Stub() { @Override public void onResult(ResponseVO re) throws RemoteException { // 将 P2 进程回调转发给客户端 notifyCallback(re); } }; private final ServiceConnection p2Connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { p2Service = IMediaAidlInterface.Stub.asInterface(service); p2Bound = true; Timber.d("P2UsbCameraVideoService connected"); try { p2Service.registerCallback(p2Callback); } catch (RemoteException e) { Timber.e(e, "Failed to register p2Callback"); } // 如果有 pending startMedia,连接后立刻执行 if (pendingP2StartMedia != null) { try { p2Service.startMedia(pendingP2StartMedia); pendingP2StartMedia = null; } catch (RemoteException e) { Timber.e(e, "Failed to startMedia on P2 service"); } } } @Override public void onServiceDisconnected(ComponentName name) { Timber.w("P2UsbCameraVideoService disconnected"); p2Bound = false; p2Service = null; } }; /** * 管理器类型枚举 @@ -40,7 +86,9 @@ NONE, USB_PUSH, USB_RECORD, ANDROID_RECORD ANDROID_RECORD, P2_USB_PUSH, P2_USB_RECORD } // AIDL Binder @@ -116,6 +164,16 @@ Timber.d("FloatingService onCreate"); } private void ensureP2Bound() { if (p2Bound) return; Intent intent = new Intent(this, P2UsbCameraVideoService.class); try { bindService(intent, p2Connection, Context.BIND_AUTO_CREATE); } catch (Exception e) { Timber.e(e, "bindService P2UsbCameraVideoService failed"); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { @@ -129,6 +187,26 @@ if (media == null) { Timber.w("startMedia: media is null"); notifyCallback(1, -1, "MediaArgu is null"); return; } // usbCameraId == 2:走 P2 跨进程服务,支持两路 USB 同时工作 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()); } } else { // 等待连接完成后执行 pendingP2StartMedia = media; currentManagerType = media.isPush() ? ManagerType.P2_USB_PUSH : ManagerType.P2_USB_RECORD; } return; } @@ -183,6 +261,18 @@ 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; } @@ -208,6 +298,22 @@ super.onDestroy(); stopMedia(); mCallbacks.kill(); if (p2Bound) { try { if (p2Service != null) { p2Service.unregisterCallback(p2Callback); } } catch (RemoteException e) { Timber.e(e, "Failed to unregister p2Callback"); } try { unbindService(p2Connection); } catch (Exception e) { Timber.w(e, "unbindService P2 failed"); } p2Bound = false; p2Service = null; } Timber.d("FloatingService onDestroy"); } app/src/main/java/com/safeluck/floatwindow/MediaArgu.java
@@ -14,8 +14,8 @@ private boolean isPush;//是否推流 true-是 private boolean usedOutCamera;//默认false 使用内置摄像头, true使用外置摄像头 private int usbCameraId;//标记是用1- P1 usb摄像头 2-P2摄像头 private String jsonconfig ; //以后可能会用到,目前用不到 private int codeRate = 0;// 码率 private int frameRate = 0;// 帧率 private ScreenSolution m_screen; @@ -24,8 +24,23 @@ private String pwd;//ftp上传密码 private int recordTime;//分钟 public int getUsbCameraId() { return usbCameraId; } private int tfCardFlag =0; //0-内部flash 1- 外置tfcard public String getJsonconfig() { return jsonconfig; } public void setJsonconfig(String jsonconfig) { this.jsonconfig = jsonconfig; } public void setUsbCameraId(int usbCameraId) { this.usbCameraId = usbCameraId; } private int tfCardFlag =0; //0-内部flash 1- 外置tfcard public int getTfCardFlag() { return tfCardFlag; @@ -181,6 +196,7 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeByte(this.isPush ? (byte) 1 : (byte) 0); dest.writeByte(this.usedOutCamera ? (byte) 1 : (byte) 0); dest.writeInt(this.usbCameraId); dest.writeInt(this.codeRate); dest.writeInt(this.frameRate); @@ -198,6 +214,7 @@ protected MediaArgu(Parcel in) { this.isPush = in.readByte() != 0; this.usedOutCamera = in.readByte() != 0; this.usbCameraId = in.readInt(); this.codeRate = in.readInt(); this.frameRate = in.readInt(); this.m_screen = in.readParcelable(ScreenSolution.class.getClassLoader()); app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java
@@ -586,8 +586,17 @@ // 打开摄像头之前先调用setenv usbCamera.setenv(); // 使用prepareCamera方法,camera_id范围[0,2] int[] cameraIds = {0, 2}; // 使用 prepareCamera 方法;根据 MediaArgu.usbCameraId 选择具体摄像头 // usbCameraId: 1 -> P1(0), 2 -> P2(2), 其他 -> 让库自行在 {0,2} 里选择 int usbId = (mediaArgu != null) ? mediaArgu.getUsbCameraId() : 0; int[] cameraIds; if (usbId == 2) { cameraIds = new int[]{2}; } else if (usbId == 1) { cameraIds = new int[]{0}; } else { cameraIds = new int[]{0, 2}; } String cameraName = null; // 不指定特定名称 // 如果返回非0,代表打开失败,则先stopCamera再重试,最多3次 app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraRecordManager.java
@@ -288,8 +288,17 @@ // 打开摄像头之前先调用setenv usbCamera.setenv(); // 使用prepareCamera方法,camera_id范围[0,9] int[] cameraIds = {0, 2}; // 使用 prepareCamera 方法;根据 MediaArgu.usbCameraId 选择具体摄像头 // usbCameraId: 1 -> P1(0), 2 -> P2(2), 其他 -> 让库自行在 {0,2} 里选择 int usbId = (mediaArgu != null) ? mediaArgu.getUsbCameraId() : 0; int[] cameraIds; if (usbId == 2) { cameraIds = new int[]{2}; } else if (usbId == 1) { cameraIds = new int[]{0}; } else { cameraIds = new int[]{0, 2}; } String cameraName = null; // 不指定特定名称 // 如果返回非0,代表打开失败,则先stopCamera再重试,最多3次