uni-app android 播放视频打开摄像头确认返回后崩溃

uni-app android 播放视频打开摄像头确认返回后崩溃

操作步骤:

  • 点开播放视频然后打开摄像头拍照,拍完确认后会crash

预期结果:

  • 点开播放视频然后打开摄像头拍照,拍完确认后不会crash

实际结果:

  • 点开播放视频然后打开摄像头拍照,拍完确认后会crash

bug描述:

  • 应用原生崩溃怎么解决?日志如下
2022/04/21 17:52:20 [crash] imei: md:OPPO A57 p:a os:23 net:3 vb:1.9.9.81245 mc: appid:*UNI*64C4596 appcount:1 wvcount:6 pn:com.qishikj.learn mem:27280kb etype:1 eurl: carsh_info:java.lang.IllegalArgumentException: Cannot setSurfaceTexture to a released SurfaceTexture
at android.view.TextureView.setSurfaceTexture(TextureView.java:725)
at io.dcloud.media.video.ijkplayer.media.TextureRenderView$InternalSurfaceHolder.bindToMediaPlayer(TextureRenderView.java:171)
at io.dcloud.media.video.ijkplayer.media.IjkVideoView.bindSurfaceHolder(IjkVideoView.java:1038)
at io.dcloud.media.video.ijkplayer.media.IjkVideoView.access$2500(IjkVideoView.java:68)
at io.dcloud.media.video.ijkplayer.media.IjkVideoView$9.onSurfaceCreated(IjkVideoView.java:1070)
at io.dcloud.media.video.ijkplayer.media.TextureRenderView$SurfaceCallback.onSurfaceTextureAvailable(TextureRenderView.java:288)
at android.view.TextureView.getHardwareLayer(TextureView.java:368)
at android.view.View.updateDisplayListIfDirty(View.java:15195)
at android.view.View.draw(View.java:15991)
at android.view.ViewGroup.drawChild(ViewGroup.java:3648)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3438)
at android.view.View.updateDisplayListIfDirty(View.java:15213)
at android.view.View.draw(View.java:15991)
at android.view.ViewGroup.drawChild(ViewGroup.java:3648)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3438)
at android.view.View.draw(View.java:16224)
at android.view.View.updateDisplayListIfDirty(View.java:15218)
at android.view.View.draw(View.java:15991)
at android.view.ViewGroup.drawChild(ViewGroup.java:3648)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3438)
at android.view.View.updateDisplayListIfDirty(View.java:15213)
at android.view.View.draw(View.java:15991)
at android.view.ViewGroup.drawChild(ViewGroup.java:3648)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3438)
at android.view.View.updateDisplayListIfDirty(View.java:15213)
at android.view.View.draw(View.java:15991)
at android.view.ViewGroup.drawChild(ViewGroup.java:3648)
at com.tencent.tbs.core.webkit.tencent.TencentWebViewProxy$InnerWebView.super_drawChild(TbsJavaCore:1874)
at com.tencent.tbs.core.webkit.tencent.TencentWebViewProxy.super_drawChild(TbsJavaCore:3576)
at com.tencent.tbs.core.webkit.adapter.X5WebViewAdapter.drawChild(TbsJavaCore:657)
at com.tencent.tbs.core.webkit.tencent.TencentWebViewProxy$InnerWebView.drawChild(TbsJavaCore:1869)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3438)
at com.tencent.tbs.core.webkit.WebView.dispatchDraw(TbsJavaCore:2645)
at android.view.View.draw(View.java:16224)
at com.tencent.tbs.core.webkit.tencent.TencentWebViewProxy$InnerWebView.super_draw(TbsJavaCore:1905)
at com.tencent.tbs.core.webkit.tencent.TencentWebViewProxy.super_draw(TbsJavaCore:3571)
at com.tencent.tbs.core.webkit.adapter.X5WebViewAdapter.draw(TbsJavaCore:872)
at com.tencent.tbs.core.webkit.tencent.TencentWebViewProxy$InnerWebView.draw(TbsJavaCore:1900)
at android.view.View.updateDisplayListIfDirty(View.java:15218)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3632)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3612)
at android.view.View.updateDisplayListIfDirty(View.java:15178)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3632)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3612)
at android.view.View.updateDisplayListIfDirty(View.java:15178)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3632)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3612)
at android.view.View.updateDisplayListIfDirty(View.java:15178)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3632)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3612)
at android.view.View.updateDisplayListIfDirty(View.java:15178)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3632)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3612)
at android.view.View.updateDisplayListIfDirty(View.java:15178)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3632)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3612)
at android.view.View.updateDisplayListIfDirty(View.java:15178)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3632)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3612)
at android.view.View.updateDisplayListIfDirty(View.java:15178)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3632)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3612)
at android.view.View.updateDisplayListIfDirty(View.java:15178)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:281)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:287)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:322)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2773)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2592)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2200)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1209)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6330)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:862)
at android.view.Choreographer.doCallbacks(Choreographer.java:674)
at android.view.Choreographer.doFrame(Choreographer.java:610)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:848)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:179)
at android.app.ActivityThread.main(ActivityThread.java:5769)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:674)

更多关于uni-app android 播放视频打开摄像头确认返回后崩溃的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

demo给一下

更多关于uni-app android 播放视频打开摄像头确认返回后崩溃的实战教程也可以访问 https://www.itying.com/category-93-b0.html


给个可以复现问题的简单示例。

在 Uni-app 中,如果在 Android 平台上播放视频并打开摄像头确认后出现崩溃问题,可能是由于以下原因之一导致的。以下是一些可能的解决方案和排查步骤:


1. 检查权限

确保应用已经正确获取了摄像头和存储权限。在 manifest.json 中添加以下权限:

{
  "permission": {
    "android": {
      "request": [
        "android.permission.CAMERA",
        "android.permission.WRITE_EXTERNAL_STORAGE",
        "android.permission.READ_EXTERNAL_STORAGE"
      ]
    }
  }
}

在代码中动态请求权限:

uni.authorize({
  scope: 'scope.camera',
  success() {
    console.log('摄像头权限已授权');
  },
  fail() {
    console.log('摄像头权限未授权');
  }
});

2. 检查生命周期

在打开摄像头或播放视频时,确保正确处理了页面的生命周期。例如,在 onHideonUnload 中释放资源:

onUnload() {
  // 释放视频播放器或摄像头资源
  this.videoContext && this.videoContext.destroy();
}

3. 检查视频播放器组件

如果使用 video 组件播放视频,确保正确初始化和销毁视频播放器:

<video id="myVideo" src="video.mp4" controls></video>
onReady() {
  this.videoContext = uni.createVideoContext('myVideo');
},
onUnload() {
  this.videoContext && this.videoContext.destroy();
}

4. 检查摄像头组件

如果使用 camera 组件,确保正确初始化和销毁摄像头:

<camera id="myCamera" device-position="back"></camera>
onReady() {
  this.cameraContext = uni.createCameraContext('myCamera');
},
onUnload() {
  this.cameraContext && this.cameraContext.stopRecord();
}

5. 检查返回逻辑

在返回页面时,确保没有重复调用摄像头或视频播放器的销毁方法。可以在 onBackPress 中处理返回逻辑:

onBackPress() {
  // 释放资源
  this.videoContext && this.videoContext.destroy();
  this.cameraContext && this.cameraContext.stopRecord();
  return false; // 阻止默认返回行为
}

6. 检查日志

通过 Android Studio 或 adb logcat 查看崩溃日志,定位具体错误。常见的错误可能包括:

  • 权限未授权
  • 资源未释放
  • 内存泄漏

7. 更新 Uni-app 版本

确保使用的是最新版本的 Uni-app 和 HBuilderX,旧版本可能存在兼容性问题。


8. 测试真机

在真机上测试,模拟器可能存在兼容性问题。


9. 示例代码

以下是一个完整的示例代码,结合了视频播放和摄像头功能:

<template>
  <view>
    <video id="myVideo" src="video.mp4" controls></video>
    <camera id="myCamera" device-position="back"></camera>
    <button @click="openCamera">打开摄像头</button>
  </view>
</template>

<script>
export default {
  data() {
    return {
      videoContext: null,
      cameraContext: null,
    };
  },
  onReady() {
    this.videoContext = uni.createVideoContext('myVideo');
    this.cameraContext = uni.createCameraContext('myCamera');
  },
  onUnload() {
    this.videoContext && this.videoContext.destroy();
    this.cameraContext && this.cameraContext.stopRecord();
  },
  methods: {
    openCamera() {
      uni.authorize({
        scope: 'scope.camera',
        success() {
          console.log('摄像头权限已授权');
        },
        fail() {
          console.log('摄像头权限未授权');
        },
      });
    },
  },
};
</script>
回到顶部