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; import android.os.RemoteException; import com.safeluck.floatwindow.manager.AndroidCameraRecordManager; import com.safeluck.floatwindow.manager.UsbCameraPushManager; import com.safeluck.floatwindow.manager.UsbCameraRecordManager; import timber.log.Timber; /** * 悬浮窗服务,用于处理推流和录像 * 根据MediaArgu参数选择使用不同的管理器: * - USB摄像头推流:UsbCameraPushManager * - USB摄像头录像:UsbCameraRecordManager * - Android相机录像:AndroidCameraRecordManager */ public class FloatingService extends Service { private static final String TAG = "FloatingService"; private Context context; // 管理器实例 private UsbCameraPushManager usbCameraPushManager; private UsbCameraRecordManager usbCameraRecordManager; private AndroidCameraRecordManager androidCameraRecordManager; // 当前使用的管理器类型 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; } }; /** * 管理器类型枚举 */ private enum ManagerType { NONE, USB_PUSH, USB_RECORD, ANDROID_RECORD } // AIDL Binder private final IMediaAidlInterface.Stub mBinder = new IMediaAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { Timber.d("basicTypes called: anInt=%d, aLong=%d, aBoolean=%s, aFloat=%f, aDouble=%f, aString=%s", anInt, aLong, aBoolean, aFloat, aDouble, aString); } @Override public void startMedia(MediaArgu media) throws RemoteException { Timber.d("startMedia called via AIDL"); FloatingService.this.startMedia(media); } @Override public void stopMedia(MediaArgu media) throws RemoteException { Timber.d("stopMedia called via AIDL"); FloatingService.this.stopMedia(media); } @Override public void registerCallback(IMyCallback cb) throws RemoteException { if (cb != null) { mCallbacks.register(cb); Timber.d("Callback registered"); } } @Override public void unregisterCallback(IMyCallback cb) throws RemoteException { if (cb != null) { mCallbacks.unregister(cb); Timber.d("Callback unregistered"); } } }; // 回调列表,使用 RemoteCallbackList 管理跨进程回调 private final RemoteCallbackList mCallbacks = new RemoteCallbackList<>(); @Override public void onCreate() { super.onCreate(); context = this; // 初始化管理器 usbCameraPushManager = new UsbCameraPushManager(context); usbCameraPushManager.setCallback(new UsbCameraPushManager.PushCallback() { @Override public void onResult(ResponseVO response) { notifyCallback(response); } }); usbCameraRecordManager = new UsbCameraRecordManager(context); usbCameraRecordManager.setCallback(new UsbCameraRecordManager.RecordCallback() { @Override public void onResult(ResponseVO response) { notifyCallback(response); } }); androidCameraRecordManager = new AndroidCameraRecordManager(context); androidCameraRecordManager.setCallback(new AndroidCameraRecordManager.RecordCallback() { @Override public void onResult(ResponseVO response) { notifyCallback(response); } }); 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; } /** * 启动媒体(通过 AIDL 调用) */ private void startMedia(MediaArgu media) { if (media == null) { Timber.w("startMedia: media is null"); notifyCallback(1, -1, "MediaArgu is null"); return; } // usbCameraId == 2:走 P2 跨进程服务,支持两路 USB 同时工作(本 Service 不再跟踪其状态) if (media.isUsedOutCamera() && media.getUsbCameraId() == 2) { ensureP2Bound(); if (p2Service != null) { try { p2Service.startMedia(media); } catch (RemoteException e) { Timber.e(e, "startMedia forward to P2 failed"); notifyCallback(1, -3, "启动P2服务失败: " + e.getMessage()); } } else { // 等待连接完成后执行 pendingP2StartMedia = media; } return; } // 先停止当前正在运行的管理器 stopCurrentManager(); // 根据参数选择管理器 if (media.isPush()) { // 推流 if (media.isUsedOutCamera()) { // USB摄像头推流 Timber.i("启动USB摄像头推流"); currentManagerType = ManagerType.USB_PUSH; usbCameraPushManager.startPush(media); } else { Timber.w("推流仅支持USB摄像头"); notifyCallback(1, -4, "推流仅支持USB摄像头"); } } else { // 录像 if (media.isUsedOutCamera()) { // USB摄像头录像 Timber.i("启动USB摄像头录像"); currentManagerType = ManagerType.USB_RECORD; usbCameraRecordManager.startRecord(media); } else { // Android相机录像 Timber.i("启动Android相机录像"); currentManagerType = ManagerType.ANDROID_RECORD; androidCameraRecordManager.startRecord(media); } } } /** * 停止当前本地管理器(仅管理本进程中的 USB(P1)/Android 录像或推流) */ private void stopCurrentManager() { switch (currentManagerType) { case USB_PUSH: if (usbCameraPushManager != null) { usbCameraPushManager.stopPush(); } break; case USB_RECORD: if (usbCameraRecordManager != null) { usbCameraRecordManager.stopRecord(); } break; case ANDROID_RECORD: if (androidCameraRecordManager != null) { androidCameraRecordManager.stopRecord(); } break; case NONE: break; } currentManagerType = ManagerType.NONE; } /** * 停止媒体(通过 AIDL 调用,带 MediaArgu,用于区分 P1/P2) */ 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 public IBinder onBind(Intent intent) { Timber.d("onBind called"); return mBinder; } @Override public void onDestroy() { super.onDestroy(); stopCurrentManager(); 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"); } /** * 通知回调:统一使用 ResponseVO * @param response ResponseVO 对象,包含 type、errCode、message */ private void notifyCallback(ResponseVO response) { if (response == null) { return; } int count = mCallbacks.beginBroadcast(); for (int i = 0; i < count; i++) { try { mCallbacks.getBroadcastItem(i).onResult(response); } catch (RemoteException e) { Timber.e(e, "Error notifying callback"); } } mCallbacks.finishBroadcast(); } /** * 创建并发送回调 * @param type 类型:0-录像 1-推流 2-文件名类型等 * @param errCode 错误码:0-成功,其他为错误码 * @param message 消息内容 */ private void notifyCallback(int type, int errCode, String message) { ResponseVO response = new ResponseVO(); response.setType(type); response.setErrCode(errCode); response.setMessage(message); notifyCallback(response); } }