[英]Why Bluetooth Microphone stops recording in Background Mode?
我的目標是在后台模式下從藍牙麥克風錄制音頻。
預期結果:A2DPService 在后台模式下錄制音頻。
實際結果:A2DPService 在后台模式下 2 分鍾后無法錄制音頻。 音頻文件將為空。
如何重現該問題:
connectDevice(address: string)
。startBluetoothSco()
錄制音頻stopBluetoothSco()
來停止錄音機。A2DPService.java
package com.satpam.RNBluetoothNM.A2DP;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.media.AudioManager;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class A2DPService {
private BluetoothDevice mBluetoothDevice;
private BluetoothA2dp mBluetoothA2dp;
private AudioManager mAudioManager;
public A2DPService(ReactApplicationContext reactContext) {
mAudioManager = (AudioManager) reactContext.getSystemService(Context.AUDIO_SERVICE);
BluetoothAdapter
.getDefaultAdapter()
.getProfileProxy(reactContext, new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int i, BluetoothProfile bluetoothProfile) {
if (i == BluetoothProfile.A2DP) {
mBluetoothA2dp = (BluetoothA2dp) bluetoothProfile;
}
}
@Override
public void onServiceDisconnected(int i) {
if (i == BluetoothProfile.A2DP) {
mBluetoothA2dp = null;
}
}
}, BluetoothProfile.A2DP);
}
public boolean createBond(BluetoothDevice bluetoothDevice) {
mBluetoothDevice = bluetoothDevice;
return mBluetoothDevice.createBond();
}
public boolean connectA2DP(BluetoothDevice bluetoothDevice) {
if (mBluetoothDevice == null) {
return false;
} else {
try {
Method method = BluetoothA2dp.class.getMethod("connect", BluetoothDevice.class);
method.invoke(mBluetoothA2dp, bluetoothDevice);
return true;
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
return false;
}
}
}
public int getConnectedState() {
return mBluetoothA2dp.getConnectionState(mBluetoothDevice);
}
public boolean startBluetoothSco() {
if (getConnectedState() != BluetoothProfile.STATE_CONNECTED) {
return false;
} else {
mAudioManager.setBluetoothScoOn(true);
mAudioManager.startBluetoothSco();
return true;
}
}
public boolean stopBluetoothSco() {
if (getConnectedState() != BluetoothProfile.STATE_CONNECTED) {
return false;
} else {
mAudioManager.setBluetoothScoOn(false);
mAudioManager.stopBluetoothSco();
return true;
}
}
}
RN藍牙NM.java
package com.satpam.RNBluetoothNM;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.util.Log;
import androidx.annotation.NonNull;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.BaseActivityEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.satpam.RNBluetoothNM.A2DP.A2DPService;
import com.satpam.RNBluetoothNM.SPP.SPPService;
import java.util.Set;
public class RNBluetoothNMPackage extends ReactContextBaseJavaModule {
@NonNull
@Override
public String getName() {
return "RNBluetoothNM";
}
private static final int getBondedDeviceRequestCode = 0;
private Promise mPromise;
private final ActivityEventListener activityListener = new BaseActivityEventListener() {
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
super.onActivityResult(activity, requestCode, resultCode, data);
if (requestCode == getBondedDeviceRequestCode && resultCode == activity.RESULT_OK) {
getBondedDevices(mPromise);
mPromise = null;
}
}
};
public RNBluetoothNMPackage(ReactApplicationContext reactContext) {
super(reactContext);
// Add a listener for `onActivityResult`
reactContext.addActivityEventListener(activityListener);
}
private void _requestEnableBluetooth(Promise promise) {
Intent enableAdapter = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
Activity activity = getCurrentActivity();
// Store the promise to resolve/reject when onActivityResult returns value;
mPromise = promise;
activity.startActivityForResult(enableAdapter, getBondedDeviceRequestCode);
}
@ReactMethod
public void getBondedDevices(final Promise promise) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
promise.reject("getBondedDevices", "BluetoothAdapter is not supported");
} else {
if (!bluetoothAdapter.isEnabled()) {
_requestEnableBluetooth(promise);
}
Set<BluetoothDevice> devices = bluetoothAdapter.getBondedDevices();
if (devices.size() > 0) {
WritableArray array = Arguments.createArray();
for (BluetoothDevice device : devices) {
WritableMap writableMap = Arguments.createMap();
writableMap.putString("name", device.getName());
writableMap.putString("address", device.getAddress());
writableMap.putInt("bondState", device.getBondState());
array.pushMap(writableMap);
}
promise.resolve(array);
}
}
}
private A2DPService a2DPService;
private SPPService sppService;
@ReactMethod
public void connectDevice(String address, final Promise promise) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
promise.reject("connectDevice", "BluetoothAdapter is not supported");
} else {
if (!bluetoothAdapter.isEnabled()) {
_requestEnableBluetooth(promise);
}
BluetoothDevice bluetoothDevice = bluetoothAdapter.getRemoteDevice(address);
a2DPService = new A2DPService(getReactApplicationContext());
boolean a2dpIsBonded = a2DPService.createBond(bluetoothDevice);
if (a2dpIsBonded == false) {
promise.reject("A2DPService", "A2DP failed to bond");
} else {
boolean a2dpIsConnected = a2DPService.connectA2DP(bluetoothDevice);
if (a2dpIsConnected == false) {
promise.reject("A2DP", "A2DP failed to connect");
} else {
sppService = new SPPService(getReactApplicationContext());
boolean sppIsConnected = sppService.connectSPP(bluetoothDevice);
if (sppIsConnected == false) {
promise.reject("SPPService", "A2DP failed to bond");
} else {
promise.resolve(true);
Thread listener = new Thread(sppService);
listener.start();
}
}
}
}
}
@ReactMethod
public void startBluetoothSco(final Promise promise) {
if (a2DPService == null) {
promise.reject("startBluetoothSco", "A2DPService is null");
} else {
boolean isBluetoothScoStarted = a2DPService.startBluetoothSco();
if (isBluetoothScoStarted == false) {
promise.reject("startBluetoothSco", "A2DPService is not connected");
} else {
promise.resolve(true);
}
}
}
@ReactMethod
public void stopBluetoothSco(final Promise promise) {
if (a2DPService == null) {
promise.reject("stopBluetoothSco", "A2DPService is null");
} else {
boolean isBluetoothScoStopped = a2DPService.stopBluetoothSco();
if (isBluetoothScoStopped == false) {
promise.reject("stopBluetoothSco", "A2DPService is not connected");
} else {
promise.resolve(true);
}
}
}
}
您正在使用后台服務。 那些被允許運行的時間是有限的。 使用沒有時間限制的前台服務。 這不需要您的應用程序在前面,它只會導致出現一個通知,說明您正在運行。
您唯一需要更改的是使用 startForegroundService() 啟動服務並在服務本身中調用 startForegound。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.