package com.safeluck.floatwindow;
|
|
import android.app.Service;
|
import android.content.Context;
|
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;
|
|
/**
|
* 管理器类型枚举
|
*/
|
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() throws RemoteException {
|
Timber.d("stopMedia called via AIDL");
|
FloatingService.this.stopMedia();
|
}
|
|
@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<IMyCallback> 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");
|
}
|
|
@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;
|
}
|
|
// 先停止当前正在运行的管理器
|
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);
|
}
|
}
|
}
|
|
/**
|
* 停止当前管理器
|
*/
|
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;
|
}
|
|
/**
|
* 停止媒体
|
*/
|
private void stopMedia() {
|
Timber.d("stopMedia called");
|
stopCurrentManager();
|
}
|
|
@Override
|
public IBinder onBind(Intent intent) {
|
Timber.d("onBind called");
|
return mBinder;
|
}
|
|
@Override
|
public void onDestroy() {
|
super.onDestroy();
|
stopMedia();
|
mCallbacks.kill();
|
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);
|
}
|
}
|