Android 上的 OpenSL 音频在我锁定屏幕时停止 5.0.1 正常 6.0.1 不正常
OpenSL audio on Android stop when I lock screen 5.0.1 OK 6.0.1 Not OK
我制作了一个 android 应用程序,可以从本地 wifi 网络传输语音。为了收听和流式传输,我在 JNI 中使用 Opus C API 进行解码,并使用 OpenSL Audio 进行读取。
我从服务中调用 JNI,就像那样。
public class StreamService extends Service {
private NativeReceiver mNativeReceiver;
...
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Gérer la requête
mNativeReceiver = new NativeReceiver();
mCanPlay = mNativeReceiver.init();
mNativeReceiver.startNativeReceiver();
...
return Service.START_NOT_STICKY;
}
它工作得很好,当我点击我的按钮时,这个服务被调用,我的 android 智能手机发出声音。
但是,当我锁定我的智能手机屏幕时,声音就像 "muted",当我解锁时,声音正在播放。只有 6.0.X 没有 5.0.X
所以我的第一个想法是网络数据包停止了,我进行了调试,我的手机继续接收网络数据包。
我的服务运行,只是静音。
对于 JNI OpenSL,我使用了这段代码:
要调用我的 JNI:
public void startNativeReceiver() {
new Thread(new Runnable() {
@Override
public void run() {
// set priority
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
start();
}
}).start();
}
那叫这个:
const int queue_elements_num = 20;
const int start_after = 4;
SpscCircularQueue *queue = NULL;
OpusDecoder *opus_dec = NULL;
uint32_t samplerate = 24000;
float frame_length = 20;
bool player_initialized = false;
bool player_started = false;
int frames_in_queue = 0;
while (!rcv_th_terminate) {
ssize_t rcv_len = read(udp_sock, rcv_buf, sizeof(rcv_buf));
if (rcv_len <= 0) {
__android_log_print(ANDROID_LOG_WARN, "SMPlayer",
"Failed to receive UDP data");
continue;
}
__android_log_print(ANDROID_LOG_INFO, "SMPlayer",
"reading");
if (!player_initialized) {
if (rcv_buf[0] != 0x01) {
__android_log_print(ANDROID_LOG_ERROR, "SMPlayer",
"Unsupported version of SMPlayer "
"streaming protocol");
return NULL;
}
/* initialize decoder */
int opus_err = 0;
opus_dec = opus_decoder_create(samplerate, 1, &opus_err);
if (!opus_dec) {
__android_log_print(ANDROID_LOG_ERROR, "SMPlayer",
"unable to initialize OPUS decoder, "
"error code - %d", opus_err);
return NULL;
}
/* initialize circular queue */
uint32_t frame_buf_size = samplerate / 1000 * frame_length * 2;
queue = spsc_circular_queue_alloc(queue_elements_num, frame_buf_size);
if (!queue) {
__android_log_print(ANDROID_LOG_ERROR, "SMPlayer",
"unable to allocate SPSC Circular Queue");
opus_decoder_destroy(opus_dec);
return NULL;
}
/* initialize the play and start the playback */
osl_player_init(queue, samplerate);
player_initialized = true;
} else {
int dec_samples = opus_decode(opus_dec, rcv_buf + 2, rcv_len - 2,
(int16_t *)dec_buf, sizeof(dec_buf), 0);
if (dec_samples <= 0) {
__android_log_print(ANDROID_LOG_ERROR, "SMPlayer",
"failed to decode the data");
osl_player_terminate();
spsc_circular_queue_free(queue);
opus_decoder_destroy(opus_dec);
exit(EXIT_FAILURE);
}
while (!spsc_circular_queue_push(queue, dec_buf) && !rcv_th_terminate)
usleep((useconds_t)(frame_length * 1000.0));
if (!player_started) {
frames_in_queue++;
if (frames_in_queue == start_after) {
osl_player_jumpstart(queue);
player_started = true;
}
}
}
}
osl_player_terminate();
if (empty_buf_cnt)
__android_log_print(ANDROID_LOG_DEBUG, "SMPlayer",
"Empty buffers played: %" PRIu64, empty_buf_cnt);
spsc_circular_queue_free(queue);
opus_decoder_destroy(opus_dec);
}
有什么想法吗?!谢谢!
编辑:在 Android 5.0.1 上有效,在 Android 6.0.1 上无效?!为什么 ??
EDIT2:我的权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application
android:allowBackup="true"
编辑 3:我不录音,我只听
编辑 4:在 Android Marshmallow (Samsung S5) 上设置权限后,录制音频,没有任何变化,当我锁定屏幕时,我的应用程序就像静音一样!
我认为您的权限在 6.0 及更高版本 android 中会过期,因此您检查您的权限,如果您的权限处于危险权限中,然后动态授予它。
我制作了一个 android 应用程序,可以从本地 wifi 网络传输语音。为了收听和流式传输,我在 JNI 中使用 Opus C API 进行解码,并使用 OpenSL Audio 进行读取。
我从服务中调用 JNI,就像那样。
public class StreamService extends Service {
private NativeReceiver mNativeReceiver;
...
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Gérer la requête
mNativeReceiver = new NativeReceiver();
mCanPlay = mNativeReceiver.init();
mNativeReceiver.startNativeReceiver();
...
return Service.START_NOT_STICKY;
}
它工作得很好,当我点击我的按钮时,这个服务被调用,我的 android 智能手机发出声音。
但是,当我锁定我的智能手机屏幕时,声音就像 "muted",当我解锁时,声音正在播放。只有 6.0.X 没有 5.0.X
所以我的第一个想法是网络数据包停止了,我进行了调试,我的手机继续接收网络数据包。
我的服务运行,只是静音。
对于 JNI OpenSL,我使用了这段代码:
要调用我的 JNI:
public void startNativeReceiver() {
new Thread(new Runnable() {
@Override
public void run() {
// set priority
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
start();
}
}).start();
}
那叫这个:
const int queue_elements_num = 20;
const int start_after = 4;
SpscCircularQueue *queue = NULL;
OpusDecoder *opus_dec = NULL;
uint32_t samplerate = 24000;
float frame_length = 20;
bool player_initialized = false;
bool player_started = false;
int frames_in_queue = 0;
while (!rcv_th_terminate) {
ssize_t rcv_len = read(udp_sock, rcv_buf, sizeof(rcv_buf));
if (rcv_len <= 0) {
__android_log_print(ANDROID_LOG_WARN, "SMPlayer",
"Failed to receive UDP data");
continue;
}
__android_log_print(ANDROID_LOG_INFO, "SMPlayer",
"reading");
if (!player_initialized) {
if (rcv_buf[0] != 0x01) {
__android_log_print(ANDROID_LOG_ERROR, "SMPlayer",
"Unsupported version of SMPlayer "
"streaming protocol");
return NULL;
}
/* initialize decoder */
int opus_err = 0;
opus_dec = opus_decoder_create(samplerate, 1, &opus_err);
if (!opus_dec) {
__android_log_print(ANDROID_LOG_ERROR, "SMPlayer",
"unable to initialize OPUS decoder, "
"error code - %d", opus_err);
return NULL;
}
/* initialize circular queue */
uint32_t frame_buf_size = samplerate / 1000 * frame_length * 2;
queue = spsc_circular_queue_alloc(queue_elements_num, frame_buf_size);
if (!queue) {
__android_log_print(ANDROID_LOG_ERROR, "SMPlayer",
"unable to allocate SPSC Circular Queue");
opus_decoder_destroy(opus_dec);
return NULL;
}
/* initialize the play and start the playback */
osl_player_init(queue, samplerate);
player_initialized = true;
} else {
int dec_samples = opus_decode(opus_dec, rcv_buf + 2, rcv_len - 2,
(int16_t *)dec_buf, sizeof(dec_buf), 0);
if (dec_samples <= 0) {
__android_log_print(ANDROID_LOG_ERROR, "SMPlayer",
"failed to decode the data");
osl_player_terminate();
spsc_circular_queue_free(queue);
opus_decoder_destroy(opus_dec);
exit(EXIT_FAILURE);
}
while (!spsc_circular_queue_push(queue, dec_buf) && !rcv_th_terminate)
usleep((useconds_t)(frame_length * 1000.0));
if (!player_started) {
frames_in_queue++;
if (frames_in_queue == start_after) {
osl_player_jumpstart(queue);
player_started = true;
}
}
}
}
osl_player_terminate();
if (empty_buf_cnt)
__android_log_print(ANDROID_LOG_DEBUG, "SMPlayer",
"Empty buffers played: %" PRIu64, empty_buf_cnt);
spsc_circular_queue_free(queue);
opus_decoder_destroy(opus_dec);
}
有什么想法吗?!谢谢!
编辑:在 Android 5.0.1 上有效,在 Android 6.0.1 上无效?!为什么 ??
EDIT2:我的权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application
android:allowBackup="true"
编辑 3:我不录音,我只听
编辑 4:在 Android Marshmallow (Samsung S5) 上设置权限后,录制音频,没有任何变化,当我锁定屏幕时,我的应用程序就像静音一样!
我认为您的权限在 6.0 及更高版本 android 中会过期,因此您检查您的权限,如果您的权限处于危险权限中,然后动态授予它。