使用Gluon Attach VideoService在Android上崩溃问题求助
Android平台使用Gluon Attach VideoService崩溃问题求解
问题概述
在Android平台使用Gluon Attach的VideoService播放音频时,应用运行一段时间后崩溃。alert(Alert)方法每秒被调用一次,用于切换不同音频文件播放。尝试改用AudioService无崩溃,但无法通过音量键调节音量。
调用VideoService的MobileNotifier类代码
private final class MobileNotifier { private static final String SHORT_BEEP_PATH = "/sounds/ShortBeep.wav"; private static final String LONG_BEEP_PATH = "/sounds/LongBeep.wav"; VideoService service; MobileNotifier() { this.service = VideoService.create().get(); service.getPlaylist().add(SHORT_BEEP_PATH); } public void alert(Alert alert) { switch (alert) { case NONE -> { System.out.println("NONE: stopping"); service.stop(); System.out.println("NONE: stopped"); } case ORANGE -> play(alert, SHORT_BEEP_PATH); case RED -> play(alert, LONG_BEEP_PATH); }; } private void play(Alert alert, String audioPath) { System.out.println(alert); if (!audioPath.equals(service.getPlaylist().get(0))) { if (service.statusProperty().get() != Status.PLAYING) { System.out.println(alert + ": not being played - stopping"); service.stop(); System.out.println(alert + ": not being played - stopped"); } System.out.println(alert + ": setting"); service.getPlaylist().set(0, audioPath); System.out.println(alert + ": set"); } System.out.println(alert + ": playing"); service.play(); System.out.println(alert + ": played"); } }
崩溃日志(adb logcat片段)
E/AndroidRuntime(29381): FATAL EXCEPTION: main E/AndroidRuntime(29381): Process: com.gps.demo, PID: 29381 E/AndroidRuntime(29381): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.media.MediaPlayer.setSurface(android.view.Surface)' on a null object reference E/AndroidRuntime(29381): at com.gluonhq.helloandroid.DalvikVideoService.onSurfaceTextureAvailable(DalvikVideoService.java:381) E/AndroidRuntime(29381): at android.view.TextureView.getHardwareLayer(TextureView.java:390) E/AndroidRuntime(29381): at android.view.TextureView.draw(TextureView.java:339) E/AndroidRuntime(29381): at android.view.View.updateDisplayListIfDirty(View.java:19315) E/AndroidRuntime(29381): at android.view.View.draw(View.java:20093) E/AndroidRuntime(29381): at android.view.ViewGroup.drawChild(ViewGroup.java:4421) E/AndroidRuntime(29381): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) E/AndroidRuntime(29381): at android.view.View.draw(View.java:20373) E/AndroidRuntime(29381): at android.view.View.updateDisplayListIfDirty(View.java:19315) E/AndroidRuntime(29381): at android.view.View.draw(View.java:20093) E/AndroidRuntime(29381): at android.view.ViewGroup.drawChild(ViewGroup.java:4421) E/AndroidRuntime(29381): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) E/AndroidRuntime(29381): at android.view.View.draw(View.java:20373) E/AndroidRuntime(29381): at com.android.internal.policy.DecorView.draw(DecorView.java:980) E/AndroidRuntime(29381): at android.view.View.updateDisplayListIfDirty(View.java:19315) E/AndroidRuntime(29381): at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:686) E/AndroidRuntime(29381): at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:692) E/AndroidRuntime(29381): at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:800) E/AndroidRuntime(29381): at android.view.ViewRootImpl.draw(ViewRootImpl.java:3496) E/AndroidRuntime(29381): at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3283) E/AndroidRuntime(29381): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2818) E/AndroidRuntime(29381): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1780) E/AndroidRuntime(29381): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7827) E/AndroidRuntime(29381): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911) E/AndroidRuntime(29381): at android.view.Choreographer.doCallbacks(Choreographer.java:723) E/AndroidRuntime(29381): at android.view.Choreographer.doFrame(Choreographer.java:658) E/AndroidRuntime(29381): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897) E/AndroidRuntime(29381): at android.os.Handler.handleCallback(Handler.java:789) E/AndroidRuntime(29381): at android.os.Handler.dispatchMessage(Handler.java:98) E/AndroidRuntime(29381): at android.os.Looper.loop(Looper.java:164) E/AndroidRuntime(29381): at android.app.ActivityThread.main(ActivityThread.java:6944) E/AndroidRuntime(29381): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(29381): at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) E/AndroidRuntime(29381): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374) W/ActivityManager( 1525): crash : com.gps.demo,0 W/ActivityManager( 1525): Force finishing activity com.gps.demo/com.gluonhq.helloandroid.MainActivity
使用的技术版本
<gluonfx-maven-plugin-version>1.0.15</gluonfx-maven-plugin-version> <java-version>17</java-version> <javafx-version>19</javafx-version> <charm-version>6.2.2</charm-version> <attach-version>4.0.15</attach-version>
javafxStaticSdkVersion: 19- GraalVM版本: graalvm-svm-java17-linux-gluon-22.1.0.1-Final
- 运行设备: Android 8-12
解决方案建议
修复VideoService空指针问题
崩溃源于DalvikVideoService中MediaPlayer实例为null时调用setSurface,可尝试:- 升级Gluon Attach到最新稳定版,底层空指针问题通常会在新版本中修复;
- 加强
VideoService生命周期管理,调用play()/stop()前检查实例状态,通过监听statusProperty()处理状态变化,避免在实例释放后执行操作。
解决AudioService音量调节问题
若使用AudioService无法调节音量,需确保音频流类型正确,可通过Android原生API强制绑定媒体音量:// 获取Android AudioManager实例 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); // 设置使用媒体音量控制 setVolumeControlStream(AudioManager.STREAM_MUSIC);这段代码需在Android Activity中执行,可通过Gluon Attach的
LifecycleService获取Activity实例调用。优化音频切换逻辑
当前每秒调用一次alert(),频繁的stop()和play()易导致MediaPlayer状态异常,可优化:- 避免在非播放状态下重复调用
stop(); - 使用
MediaPlayer的prepareAsync()替代同步操作,避免阻塞主线程; - 增加状态校验,仅当实例处于空闲状态时切换播放列表。
- 避免在非播放状态下重复调用
内容的提问来源于stack exchange,提问作者user1803551
相关产品推荐
相关产品推荐

