You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

解决方案建议

  1. 修复VideoService空指针问题
    崩溃源于DalvikVideoService中MediaPlayer实例为null时调用setSurface,可尝试:

    • 升级Gluon Attach到最新稳定版,底层空指针问题通常会在新版本中修复;
    • 加强VideoService生命周期管理,调用play()/stop()前检查实例状态,通过监听statusProperty()处理状态变化,避免在实例释放后执行操作。
  2. 解决AudioService音量调节问题
    若使用AudioService无法调节音量,需确保音频流类型正确,可通过Android原生API强制绑定媒体音量:

    // 获取Android AudioManager实例
    AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    // 设置使用媒体音量控制
    setVolumeControlStream(AudioManager.STREAM_MUSIC);
    

    这段代码需在Android Activity中执行,可通过Gluon Attach的LifecycleService获取Activity实例调用。

  3. 优化音频切换逻辑
    当前每秒调用一次alert(),频繁的stop()和play()易导致MediaPlayer状态异常,可优化:

    • 避免在非播放状态下重复调用stop();
    • 使用MediaPlayer的prepareAsync()替代同步操作,避免阻塞主线程;
    • 增加状态校验,仅当实例处于空闲状态时切换播放列表。

内容的提问来源于stack exchange,提问作者user1803551

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 05:51:18