超级强大的 Android NDK:获取 positionPercent 以更新音频进度搜索栏

Posted

技术标签:

【中文标题】超级强大的 Android NDK:获取 positionPercent 以更新音频进度搜索栏【英文标题】:Superpowered Android NDK: get positionPercent to update audio progress seekbar 【发布时间】:2017-01-03 08:06:07 【问题描述】:

我正在使用 superpowered AdvancedAudioPlayer 在 android 上播放 mp3。我想使用搜索栏来显示文件播放的进度。我的计划是使用 Java 端的 Runnable 每秒一次获取播放器的 positionPercent 属性,并使用结果更新搜索栏。我尝试了许多不同的方法,但都导致崩溃,要么使用 SIGILL,要么只是在模拟器上发出“不幸的是,xxx 已停止”的通知。 (xxx 是应用的名称。)

这是我最近的尝试。

Java 代码:

 private int timeSliderInterval = 1000; // 1 second
 Runnable doUpdateTimeSlider;
 final Handler timeSliderHandler = new Handler();

 void startUpdateTimeSlider() 
     doUpdateTimeSlider.run();
 

 void stopUpdateTimeSlider() 
     timeSliderHandler.removeCallbacks(doUpdateTimeSlider);
 

 @Override
 public void onDestroy() 
     super.onDestroy();
     stopUpdateTimeSlider();
 

 @Override
 protected void onCreate(Bundle savedInstanceState) 
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_play);;

     doUpdateTimeSlider = new Runnable() 
         @Override
         public void run() 
             updateTimeSlider();
             timeSliderHandler.postDelayed(this, timeSliderInterval);
         
         void updateTimeSlider() 
             float pp;
             // this is where problems begin!
             pp = getPositionPercent();
             int ppint = (int) (pp*100);
             timeSlider.setProgress(ppint);
         
     ;


private native int getPositionPercent();

C++ 代码:

 float SuperpoweredExample::getPositionPercent () 
     float pp = 0.01f;
     pp = player1->positionPercent;
     return pp; 

extern "C" JNIEXPORT jint Java_org_irthlingz_ChoirherenceA3_PlayActivity_getPositionPercent(JNIEnv * __unused javaEnvironment, jobject __unused obj) 
    example->getPositionPercent();

应用程序构建和启动没有错误。但是当我到达执行SuperpoweredExample::getPositionPercent 的地方时,它崩溃了。

Runnable 部分本身就可以工作。但是,一旦我尝试检索 positionPercent,我就会遇到某种崩溃。

另外一件事:如果我将强制转换注释为一个 int 并在它后面添加一行:

         int ppint = (int) (pp*100);
         timeSlider.setProgress(ppint);

我仍然得到一个 SIGILL。所以这些线在这一点上不是问题。

有什么想法吗?

这是一个堆栈跟踪:

Signal = SIGILL (signal SIGILL: illegal instruction operand)
javaEnvironment = JNIEnv * | 0xb4059a80 0xb4059a80
 [0] = JNIEnv 
  functions = const JNINativeInterface * | 0xb3fb2a40 0xb3fb2a40
   [0] = const JNINativeInterface 
    reserved0 = void * | 0x0 nil
    reserved1 = void * | 0x0 nil
    reserved2 = void * | 0x0 nil
    reserved3 = void * | 0x0 nil
    GetVersion = jint (*)(JNIEnv *) | 0xb39d05f5 (libart.so`art::CheckJNI::GetVersion(_JNIEnv*))
    DefineClass = jclass (*)(JNIEnv *, const char *, jobject, const jbyte *, jsize) | 0xb39d1ad0 (libart.so`art::CheckJNI::DefineClass(_JNIEnv*, char const*, _jobject*, signed char const*, int))
    FindClass = jclass (*)(JNIEnv *, const char *) | 0xb39d1f8c (libart.so`art::CheckJNI::FindClass(_JNIEnv*, char const*))
    FromReflectedMethod = jmethodID (*)(JNIEnv *, jobject) | 0xb39d2c2f (libart.so`art::CheckJNI::FromReflectedMethod(_JNIEnv*, _jobject*))
    FromReflectedField = jfieldID (*)(JNIEnv *, jobject) | 0xb39d31b4 (libart.so`art::CheckJNI::FromReflectedField(_JNIEnv*, _jobject*))
    ToReflectedMethod = jobject (*)(JNIEnv *, jclass, jmethodID, jboolean) | 0xb39d36f0 (libart.so`art::CheckJNI::ToReflectedMethod(_JNIEnv*, _jclass*, _jmethodID*, unsigned char))
    GetSuperclass = jclass (*)(JNIEnv *, jclass) | 0xb39d23d8 (libart.so`art::CheckJNI::GetSuperclass(_JNIEnv*, _jclass*))
    IsAssignableFrom = jboolean (*)(JNIEnv *, jclass, jclass) | 0xb39d27f0 (libart.so`art::CheckJNI::IsAssignableFrom(_JNIEnv*, _jclass*, _jclass*))
    ToReflectedField = jobject (*)(JNIEnv *, jclass, jfieldID, jboolean) | 0xb39d3b50 (libart.so`art::CheckJNI::ToReflectedField(_JNIEnv*, _jclass*, _jfieldID*, unsigned char))
    Throw = jint (*)(JNIEnv *, jthrowable) | 0xb39d3fb0 (libart.so`art::CheckJNI::Throw(_JNIEnv*, _jthrowable*))
    ThrowNew = jint (*)(JNIEnv *, jclass, const char *) | 0xb39d44c0 (libart.so`art::CheckJNI::ThrowNew(_JNIEnv*, _jclass*, char const*))
    ExceptionOccurred = jthrowable (*)(JNIEnv *) | 0xb39d49da (libart.so`art::CheckJNI::ExceptionOccurred(_JNIEnv*))
    ExceptionDescribe = void (*)(JNIEnv *) | 0xb39d4dd0 (libart.so`art::CheckJNI::ExceptionDescribe(_JNIEnv*))
    ExceptionClear = void (*)(JNIEnv *) | 0xb39d5200 (libart.so`art::CheckJNI::ExceptionClear(_JNIEnv*))
    FatalError = void (*)(JNIEnv *, const char *) | 0xb39d5a30 (libart.so`art::CheckJNI::FatalError(_JNIEnv*, char const*))
    PushLocalFrame = jint (*)(JNIEnv *, jint) | 0xb39d5e3e (libart.so`art::CheckJNI::PushLocalFrame(_JNIEnv*, int))
    PopLocalFrame = jobject (*)(JNIEnv *, jobject) | 0xb39d625d (libart.so`art::CheckJNI::PopLocalFrame(_JNIEnv*, _jobject*))
    NewGlobalRef = jobject (*)(JNIEnv *, jobject) | 0xb39d6bd5 (libart.so`art::CheckJNI::NewGlobalRef(_JNIEnv*, _jobject*))
    DeleteGlobalRef = void (*)(JNIEnv *, jobject) | 0xb39d72d9 (libart.so`art::CheckJNI::DeleteGlobalRef(_JNIEnv*, _jobject*))
    DeleteLocalRef = void (*)(JNIEnv *, jobject) | 0xb39d729f (libart.so`art::CheckJNI::DeleteLocalRef(_JNIEnv*, _jobject*))
    IsSameObject = jboolean (*)(JNIEnv *, jobject, jobject) | 0xb39d7740 (libart.so`art::CheckJNI::IsSameObject(_JNIEnv*, _jobject*, _jobject*))
    NewLocalRef = jobject (*)(JNIEnv *, jobject) | 0xb39d6b9b (libart.so`art::CheckJNI::NewLocalRef(_JNIEnv*, _jobject*))
    EnsureLocalCapacity = jint (*)(JNIEnv *, jint) | 0xb39d7313 (libart.so`art::CheckJNI::EnsureLocalCapacity(_JNIEnv*, int))
    AllocObject = jobject (*)(JNIEnv *, jclass) | 0xb39d7b90 (libart.so`art::CheckJNI::AllocObject(_JNIEnv*, _jclass*))
    NewObject = jobject (*)(JNIEnv *, jclass, jmethodID, ...) | 0xb39d867c (libart.so`art::CheckJNI::NewObject(_JNIEnv*, _jclass*, _jmethodID*, ...))
    NewObjectV = jobject (*)(JNIEnv *, jclass, jmethodID, va_list) | 0xb39d80a5 (libart.so`art::CheckJNI::NewObjectV(_JNIEnv*, _jclass*, _jmethodID*, char*))
    NewObjectA = jobject (*)(JNIEnv *, jclass, jmethodID, jvalue *) | 0xb39d86a7 (libart.so`art::CheckJNI::NewObjectA(_JNIEnv*, _jclass*, _jmethodID*, jvalue*))
    GetObjectClass = jclass (*)(JNIEnv *, jobject) | 0xb39d8c7e (libart.so`art::CheckJNI::GetObjectClass(_JNIEnv*, _jobject*))
    IsInstanceOf = jboolean (*)(JNIEnv *, jobject, jclass) | 0xb39d9090 (libart.so`art::CheckJNI::IsInstanceOf(_JNIEnv*, _jobject*, _jclass*))
    GetMethodID = jmethodID (*)(JNIEnv *, jclass, const char *, const char *) | 0xb39d99b0 (libart.so`art::CheckJNI::GetMethodID(_JNIEnv*, _jclass*, char const*, char const*))
    CallObjectMethod = jobject (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb39ea042 (libart.so`art::CheckJNI::CallObjectMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
    CallObjectMethodV = jobject (*)(JNIEnv *, jobject, jmethodID, va_list) | 0xb39e9fd9 (libart.so`art::CheckJNI::CallObjectMethodV(_JNIEnv*, _jobject*, _jmethodID*, char*))
    CallObjectMethodA = jobject (*)(JNIEnv *, jobject, jmethodID, jvalue *) | 0xb39e7197 (libart.so`art::CheckJNI::CallObjectMethodA(_JNIEnv*, _jobject*, _jmethodID*, jvalue*))
    CallBooleanMethod = jboolean (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb39e9f6f (libart.so`art::CheckJNI::CallBooleanMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
    CallBooleanMethodV = jboolean (*)(JNIEnv *, jobject, jmethodID, va_list) | 0xb39e9f05 (libart.so`art::CheckJNI::CallBooleanMethodV(_JNIEnv*, _jobject*, _jmethodID*, char*))
    CallBooleanMethodA = jboolean (*)(JNIEnv *, jobject, jmethodID, jvalue *) | 0xb39e712d (libart.so`art::CheckJNI::CallBooleanMethodA(_JNIEnv*, _jobject*, _jmethodID*, jvalue*))
    CallByteMethod = jbyte (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb39e9e9b (libart.so`art::CheckJNI::CallByteMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
    CallByteMethodV = jbyte (*)(JNIEnv *, jobject, jmethodID, va_list) | 0xb39e9e31 (libart.so`art::CheckJNI::CallByteMethodV(_JNIEnv*, _jobject*, _jmethodID*, char*))
    CallByteMethodA = jbyte (*)(JNIEnv *, jobject, jmethodID, jvalue *) | 0xb39e70c3 (libart.so`art::CheckJNI::CallByteMethodA(_JNIEnv*, _jobject*, _jmethodID*, jvalue*))
    CallCharMethod = jchar (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb39e9dc7 (libart.so`art::CheckJNI::CallCharMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
    CallCharMethodV = jchar (*)(JNIEnv *, jobject, jmethodID, va_list) | 0xb39e9d5d (libart.so`art::CheckJNI::CallCharMethodV(_JNIEnv*, _jobject*, _jmethodID*, char*))
    CallCharMethodA = jchar (*)(JNIEnv *, jobject, jmethodID, jvalue *) | 0xb39e7059 (libart.so`art::CheckJNI::CallCharMethodA(_JNIEnv*, _jobject*, _jmethodID*, jvalue*))
    CallShortMethod = jshort (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb39e9cf3 (libart.so`art::CheckJNI::CallShortMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
    CallShortMethodV = jshort (*)(JNIEnv *, jobject, jmethodID, va_list) | 0xb39e9c89 (libart.so`art::CheckJNI::CallShortMethodV(_JNIEnv*, _jobject*, _jmethodID*, char*))
    CallShortMethodA = jshort (*)(JNIEnv *, jobject, jmethodID, jvalue *) | 0xb39e6fef (libart.so`art::CheckJNI::CallShortMethodA(_JNIEnv*, _jobject*, _jmethodID*, jvalue*))
    CallIntMethod = jint (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb39e9c20 (libart.so`art::CheckJNI::CallIntMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
obj = jobject | 0xbfcda6ec 0xbfcda6ec

【问题讨论】:

当应用程序崩溃时,您是否得到任何堆栈跟踪? @kevto 我添加了堆栈轨道。感谢您的建议。 你实现了JNI桥吗? JNIEXPORT 诸如此类的东西? @Gabor Szanto - 感谢您的入住!还没有成功。我确实创建了一个基于 CrossExample 的简化项目,它只是试图返回一个 int。本题包括github上的一个完整项目:***.com/questions/41509047/… 是的,@Gabor Szanto,我确实实现了 JNIEXPORT 等 - 我在我的问题中添加了“私有原生 int getPositionPercent();” 【参考方案1】:

JNIEXPORT 语句需要一个“返回”:

return example->getPositionPercent();

而不是我所拥有的:

example->getPositionPercent();

【讨论】:

感谢这位美丽的人 Steve M.,他在这里提供了答案:***.com/questions/41509047/…

以上是关于超级强大的 Android NDK:获取 positionPercent 以更新音频进度搜索栏的主要内容,如果未能解决你的问题,请参考以下文章

获取Android NDK版本的正确方法是啥

无法配置NDK android studio并获取错误

如何在 NDK 原生代码中获取断点并在 Android Studio 中调试原生代码?

使用Android NDK Camera2获取预览帧的正确方法是啥

适用于 Android 的超级任天堂模拟器

红米手机5获取Root超级权限的步骤