Dana
7 天以前 8b004066992c3ff21348a7bfa44042d44d0b7088
1.p2摄像头 跨进程服务,未测试
5个文件已修改
161 ■■■■■ 已修改文件
app/src/main/AndroidManifest.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/safeluck/floatwindow/FloatingService.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/safeluck/floatwindow/MediaArgu.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraRecordManager.java 13 ●●●● 补丁 | 查看 | 原始文档 | 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;
@@ -33,6 +35,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
@@ -117,6 +165,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) {
        return START_STICKY;
@@ -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,6 +24,21 @@
    private String pwd;//ftp上传密码
    private int recordTime;//分钟
    public int getUsbCameraId() {
        return usbCameraId;
    }
    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
@@ -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次