【发布时间】:2018-03-06 07:43:12
【问题描述】:
我是一名 Android 应用程序开发人员,我遇到以下崩溃报告(我每天收到 5/6):
native: pc 00000000000418e0 /system/lib/libc.so (tgkill+12)
native: pc 0000000000040d59 /system/lib/libc.so (pthread_kill+32)
native: pc 000000000001c7eb /system/lib/libc.so (raise+10)
native: pc 000000000001999d /system/lib/libc.so (__libc_android_abort+34)
native: pc 0000000000017550 /system/lib/libc.so (abort+4)
native: pc 0000000000008d53 /system/lib/libcutils.so (__android_log_assert+86)
native: pc 000000000006e2c3 /system/lib/libmedia.so (_ZN7android11ClientProxy13releaseBufferEPNS_5Proxy6BufferE+94)
native: pc 000000000006c11d /system/lib/libmedia.so (_ZN7android10AudioTrack13releaseBufferEPKNS0_6BufferE+112)
native: pc 000000000006c987 /system/lib/libmedia.so (_ZN7android10AudioTrack18processAudioBufferEv+1350)
native: pc 000000000006d7f3 /system/lib/libmedia.so (_ZN7android10AudioTrack16AudioTrackThread10threadLoopEv+194)
native: pc 0000000000010079 /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+112)
native: pc 000000000004065b /system/lib/libc.so (_ZL15__pthread_startPv+30)
native: pc 000000000001a021 /system/lib/libc.so (__start_thread+6)
OpenSL 函数在 JNI 世界中调用。
这些是堆中存储的所有变量:
/* OpenSL ES audio stuff */
SLObjectItf engineObject = NULL;
SLEngineItf engineEngine = NULL;
SLObjectItf outputMixObject = NULL;
SLObjectItf playerObject = NULL;
SLPlayItf playerPlay = NULL;
SLVolumeItf playerVolume = NULL;
SLAndroidSimpleBufferQueueItf playerBufferQueue = NULL;
char openSLinited = 0;
int16_t audioBuffer1[48000];
int16_t audioBuffer2[48000];
int16_t *currentAudioBuffer;
这就是我初始化所有机器的方式:
void Java_com_myapp_myappname_MyActivity_jniOpenSLInit(JNIEnv *env,
jobject thiz,
jint freq)
{
SLresult result;
// create engine
result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
assert(SL_RESULT_SUCCESS == result);
// realize the engine
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
assert(SL_RESULT_SUCCESS == result);
// get the engine interface, which is needed to create other objects
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE,
&engineEngine);
assert(SL_RESULT_SUCCESS == result);
// create output mix
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject,
0, NULL, NULL);
assert(SL_RESULT_SUCCESS == result);
// realize the output mix
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
assert(SL_RESULT_SUCCESS == result);
SLuint32 SLfreq;
if (freq == 44100)
SLfreq = SL_SAMPLINGRATE_44_1;
else
SLfreq = SL_SAMPLINGRATE_48;
SLDataLocator_AndroidSimpleBufferQueue loc_bufq =
{SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 2, SLfreq,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_LEFT |
SL_SPEAKER_FRONT_RIGHT,
SL_BYTEORDER_LITTLEENDIAN};
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
/* configure audio sink */
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX,
outputMixObject};
SLDataSink audioSnk = {&loc_outmix, NULL};
const SLInterfaceID idsAudioPlayer[2] = {SL_IID_BUFFERQUEUE,
SL_IID_VOLUME };
const SLboolean reqAudioPlayer[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject,
&audioSrc,
&audioSnk, 2, idsAudioPlayer,
reqAudioPlayer);
assert(SL_RESULT_SUCCESS == result);
// realize the player
result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
assert(SL_RESULT_SUCCESS == result);
// get the play interface
result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY,
&playerPlay);
assert(SL_RESULT_SUCCESS == result);
// get the volume interface
result = (*playerObject)->GetInterface(playerObject, SL_IID_VOLUME,
&playerVolume);
assert(SL_RESULT_SUCCESS == result);
// get the buffer queue interface
result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE,
&playerBufferQueue);
assert(SL_RESULT_SUCCESS == result);
// register callback on the buffer queue
result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue,
audio_player_cb, NULL);
assert(SL_RESULT_SUCCESS == result);
// done!
openSLinited = 1;
}
调用它来启动机器。
void openSLStart()
{
bzero(audioBuffer1, 96000);
bzero(audioBuffer2, 96000);
if (!openSLinited)
return;
(*playerBufferQueue)->Enqueue(playerBufferQueue, audioBuffer1,
4096 * 4);
(*playerBufferQueue)->Enqueue(playerBufferQueue, audioBuffer2,
4096 * 4);
currentAudioBuffer = audioBuffer1;
// set the player's state to playing
(*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
}
这是让新样本入队的回调
void audio_player_cb(SLAndroidSimpleBufferQueueItf bq, void *context)
{
if (!openSLinited)
return;
assert(bq == playerBufferQueue);
assert(NULL == context);
// switch between audio buffer 1 and 2
if (currentAudioBuffer == audioBuffer1)
currentAudioBuffer = audioBuffer2;
else
currentAudioBuffer = audioBuffer1;
// this function read samples (4096 16 bit samples) from an internal buffer
sound_read_samples(4096, currentAudioBuffer);
// feed openSL machine
(*playerBufferQueue)->Enqueue(playerBufferQueue, currentAudioBuffer,
4096 * 2);
}
最后,这就是 OpenSL 的终止方式
void Java_com_myfirm_myappname_MyActivity_jniOpenSLTerm(JNIEnv *env,
jobject thiz)
{
// shutdown every created object
if (playerObject)
{
// stop the player
SLresult result = (*playerPlay)->SetPlayState(playerPlay,
SL_PLAYSTATE_STOPPED);
if (SL_RESULT_SUCCESS == result)
utils_log("Player succesfully stopped");
(*playerObject)->Destroy(playerObject);
playerObject = NULL;
playerPlay = NULL;
}
if (outputMixObject)
{
(*outputMixObject)->Destroy(outputMixObject);
outputMixObject = NULL;
}
if (engineObject)
{
(*engineObject)->Destroy(engineObject);
engineObject = NULL;
}
openSLinited = 0;
utils_log("OpenSLTerm complete");
}
我无法在我的手机和模拟器上重现...它永远不会以这种方式崩溃。
我没有关于如何解决此问题的想法。有人可以帮我摆脱这个崩溃吗?
10 月 8 日更新
我尝试按照建议删除日志。崩溃仍然发生。
该问题影响 Android 6.0、7.0 和 7.1(至少,我没有收到不同版本的报告)
10 月 9 日更新
应阿姆贾德汗的要求:
这是生成库的 Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libmyapp-jni
LOCAL_SRC_FILES := src.c src2.c src3.c
LOCAL_LDLIBS := -llog -landroid -ljnigraphics -lGLESv2 -lOpenSLES
LOCAL_CFLAGS += -O3 -DNDEBUG
include $(BUILD_SHARED_LIBRARY)
这是构建库的命令(生成所有 ABI)
/cygdrive/c/Android/ndk/ndk-build.cmd NDK_DEBUG=0 APP_BUILD_SCRIPT=./Android.mk NDK_PROJECT_PATH=.
提前谢谢你。
【问题讨论】:
-
由于在 Nougat 和更高版本中出现此错误,请尝试从您的本机 .so 文件中删除所有日志,我们正在使用本机 so 文件中的日志,这也会在 playstore 中生成此崩溃。 (utils_log)这个方法,你可以把[assert()]代码
-
我试图删除日志...崩溃再次发生。似乎它会影响 android 6、7.0 和 7.1。我真的迷路了
-
您能否添加您的 Android.mk 代码以及 ABI 将支持的代码
-
你可以发布你的 Application.mk...