【问题标题】:Accessing an Android device's Camera through the HTML5 <video> element through CodeName One mobile app通过 CodeName One 移动应用程序通过 HTML5 <video> 元素访问 Android 设备的相机
【发布时间】:2019-02-08 18:57:36
【问题描述】:

我们正在使用 CodeName One 构建适用于 Android 的移动应用。作为我们要求的一部分,我们已经有一个 HTML5 页面,其中包含一个视频元素,用于使用设备的相机拍摄照片。我们需要在 CodeName One 应用程序中调用这个 HTML5 页面。但是这段代码没有按照预期工作,但是当直接从 chrome 浏览器调用时,html 文件 URL 工作得很好。从 chrome 浏览器查看时,我收到询问相机权限的提示,而在 CodeName One 应用程序中我没有看到权限提示。

我最近看到一个类似的问题 html video control is not working in codenameone app for android

我已经尝试了那里给出的建议,但对我没有用。也许我在这里做错了什么?

在我的 CodeName 一类中,我有以下代码。该代码基本上创建了一个新的 BrowserComponent 并在该组件中设置了 camera1.html URL。 camera1.html 包含显示用于拍照的视频元素的 HTML5 代码。 `

private Form current;
private Resources theme;

public void init(Object context) {
    theme = UIManager.initFirstTheme("/theme");

    // Enable Toolbar on all Forms by default
    Toolbar.setGlobalToolbar(true);    
}

public void start(){
    if(current != null) {
        current.show();
        return;
    }

    Form f = new Form("Camera", new BorderLayout());
    try {
        CN1NativeCameraInterface cnci = NativeLookup.create(CN1NativeCameraInterface.class);
        if (cnci != null && cnci.isSupported()) {

            boolean cameraPerm = cnci.promptCameraPermission();
            if (cameraPerm) {
               f.setTitle("Camera Permission true");
            }              
        }

        BrowserComponent browser = new BrowserComponent();

        browser.setURL("https://8c10ec77.ngrok.io/app/camera1.html");
        f.add(BorderLayout.CENTER, browser);
    }
    catch (Exception ex) {
        ex.printStackTrace();
    }
    finally {
        f.show();
    }
}

public void stop(){
    current = Display.getInstance().getCurrent();
}

public void destroy(){
}

` 我已经定义了一个看起来像这样的本机接口

public interface CN1NativeCameraInterface extends NativeInterface {
    public boolean promptCameraPermission();
}

在CodeName One中生成了该接口的原生访问代码,Android实现如下

import com.codename1.impl.android.AndroidImplementation;
import android.Manifest;

public class CN1NativeCameraInterfaceImpl {
    public boolean promptCameraPermission() {
        return AndroidImplementation.checkForPermission(Manifest.permission.CAMERA, "This is required to take a picture");
    }

    public boolean isSupported() {
        return true;
    }

}

当我在 Android 设备上运行它时,我可以看到 HTML 页面正在加载,但视频元素没有加载,我看到的只是视频元素的占位符。 该应用程序也不要求相机许可,这是其他相关问题中所建议的。

我在这里做错了什么?

更新 1:

我在使用从设备获取的日志中看到以下错误 adb shell "logcat --pid=$(pidof -s com.codename1)" 命令:

错误1 -

09-06 11:48:42.530 10172 10202 I WebViewFactory:正在加载 com.android.chrome 版本 69.0.3497.76(代码 349707652) 09-06 11:48:42.595 10172 10202 I zygote64:拒绝重新初始化以前失败的类 java.lang.Class:java.lang.NoClassDefFoundError:解析失败:Landroid/webkit/TracingController; 09-06 11:48:42.595 10172 10202 I zygote64: 在 java.lang.Class java.lang.Class.classForName(java.lang.String, boolean, java.lang.ClassLoader) (Class.java:-2) 09-06 11:48:42.595 10172 10202 I zygote64: 在 java.lang.Class java.lang.Class.forName(java.lang.String, boolean, java.lang.ClassLoader) (Class.java:453) 09-06 11:48:42.595 10172 10202 I zygote64: 在 java.lang.Class android.webkit.WebViewFactory.getWebViewProviderClass(java.lang.ClassLoader) (WebViewFactory.java:151) 09-06 11:48:42.595 10172 10202 I zygote64: 在 java.lang.Class android.webkit.WebViewFactory.getProviderClass() (WebViewFactory.java:472) 09-06 11:48:42.595 10172 10202 I zygote64: 在 android.webkit.WebViewFactoryProvider android.webkit.WebViewFactory.getProvider() (WebViewFactory.java:212) 09-06 11:48:42.595 10172 10202 I zygote64: 在 android.webkit.CookieManager android.webkit.CookieManager.getInstance() (CookieManager.java:39) 09-06 11:48:42.595 10172 10202 I zygote64: 在 android.webkit.CookieManager com.codename1.impl.android.AndroidImplementation.getCookieManager() (AndroidImplementation.java:4511) 09-06 11:48:42.595 10172 10202 I zygote64: at java.util.Vector com.codename1.impl.android.AndroidImplementation.getCookiesForURL(java.lang.String) (AndroidImplementation.java:4528) 09-06 11:48:42.595 10172 10202 I zygote64: 在 void com.codename1.io.ConnectionRequest.performOperation() (ConnectionRequest.java:633) 09-06 11:48:42.595 10172 10202 I zygote64: at void com.codename1.io.NetworkManager$NetworkThread.run() (NetworkManager.java:282) 09-06 11:48:42.595 10172 10202 I zygote64: at void com.codename1.impl.CodenameOneThread$1.run() (CodenameOneThread.java:60) 09-06 11:48:42.595 10172 10202 I zygote64: 在 void java.lang.Thread.run() (Thread.java:764) 09-06 11:48:42.595 10172 10202 I zygote64:由:java.lang.ClassNotFoundException:在路径上找不到类“android.webkit.TracingController”:DexPathList [[zip 文件“/data/app/com. android.chrome-fq476TNc_btk-Vb0sBbuyw==/base.apk"],nativeLibraryDirectories=[/data/app/com.android.chrome-fq476TNc_btk-Vb0sBbuyw==/lib/arm64, /data/app/com.android.chrome -fq476TNc_btk-Vb0sBbuyw==/base.apk!/lib/arm64-v8a, /system/lib64, /system/vendor/lib64]] 09-06 11:48:42.595 10172 10202 I zygote64: 在 java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:93) 09-06 11:48:42.595 10172 10202 I zygote64: 在 java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379) 09-06 11:48:42.595 10172 10202 I zygote64: 在 java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312) 09-06 11:48:42.595 10172 10202 I zygote64: 在 java.lang.Class java.lang.Class.classForName(java.lang.String, boolean, java.lang.ClassLoader) (Class.java:-2) 09-06 11:48:42.595 10172 10202 I zygote64: 在 java.lang.Class java.lang.Class.forName(java.lang.String, boolean, java.lang.ClassLoader) (Class.java:453) 09-06 11:48:42.595 10172 10202 I zygote64: 在 java.lang.Class android.webkit.WebViewFactory.getWebViewProviderClass(java.lang.ClassLoader) (WebViewFactory.java:151) 09-06 11:48:42.595 10172 10202 I zygote64: 在 java.lang.Class android.webkit.WebViewFactory.getProviderClass() (WebViewFactory.java:472) 09-06 11:48:42.595 10172 10202 I zygote64: 在 android.webkit.WebViewFactoryProvider android.webkit.WebViewFactory.getProvider() (WebViewFactory.java:212) 09-06 11:48:42.595 10172 10202 I zygote64: 在 android.webkit.CookieManager android.webkit.CookieManager.getInstance() (CookieManager.java:39) 09-06 11:48:42.595 10172 10202 I zygote64: 在 android.webkit.CookieManager com.codename1.impl.android.AndroidImplementation.getCookieManager() (AndroidImplementation.java:4511) 09-06 11:48:42.595 10172 10202 I zygote64: at java.util.Vector com.codename1.impl.android.AndroidImplementation.getCookiesForURL(java.lang.String) (AndroidImplementation.java:4528) 09-06 11:48:42.595 10172 10202 I zygote64: at void com.codename1.io.ConnectionRequest.performOperation() (ConnectionRequest.java:633)

错误 2 -

09-06 11:48:44.506 10172 10266 W VideoCapabilities:视频/avc 无法识别的配置文件 2130706433 09-06 11:48:44.506 10172 10266 W VideoCapabilities:视频/avc 无法识别的配置文件 2130706434 09-06 11:48:44.536 10172 10266 W VideoCapabilities:视频/avc 无法识别的配置文件 2130706433 09-06 11:48:44.536 10172 10266 W VideoCapabilities:视频/avc 无法识别的配置文件 2130706434 09-06 11:48:44.542 10172 10266 W VideoCapabilities:视频/avc 无法识别的配置文件 2130706433 09-06 11:48:44.542 10172 10266 W VideoCapabilities:视频/avc 无法识别的配置文件 2130706434 09-06 11:48:44.551 10172 10266 W VideoCapabilities:视频/mpeg2 无法识别的配置文件/级别 0/3 09-06 11:48:44.555 10172 10266 W VideoCapabilities:视频/mpeg2 无法识别的配置文件/级别 0/3 09-06 11:48:44.564 10172 10266 W VideoCapabilities:不支持的 mime 视频/x-ms-wmv 09-06 11:48:44.568 10172 10266 W VideoCapabilities:不支持的 mime 视频/x-ms-wmv 09-06 11:48:44.574 10172 10266 W VideoCapabilities:不支持的 mime 视频/divx 09-06 11:48:44.577 10172 10177 I zygote64:做部分代码缓存收集,代码=55KB,数据=56KB 09-06 11:48:44.580 10172 10266 W VideoCapabilities:不支持的 mime 视频/divx311 09-06 11:48:44.584 10172 10266 W VideoCapabilities:不支持的 mime 视频/divx4 09-06 11:48:44.585 10172 10177 I zygote64:代码缓存收集后,代码=55KB,数据=56KB 09-06 11:48:44.585 10172 10177 I zygote64:将代码缓存容量增加到 256KB 09-06 11:48:44.605 10172 10266 W VideoCapabilities:不支持的 mime 视频/mp4v-esdp 09-06 11:48:44.633 10172 10266 I VideoCapabilities:视频/mp4v-es 不支持的配置文件 4 09-06 11:48:44.867 10172 10282 W cr_CrashFileManager: /data/user/0/com.codename1/cache/WebView/Crash Reports 不存在或不是目录

错误 3 -

09-06 11:48:47.715 10172 10253 I CameraManagerGlobal: 连接到相机服务 09-06 11:48:47.799 10172 10172 D 代号一:onPermissionRequest 09-06 11:48:50.952 10172 10172 E Android 实施:空 09-06 11:48:50.952 10172 10172 E AndroidImplementation: java.io.FileNotFoundException: /data/user/0/com.codename1/files/CN1$AndroidServiceProperties (没有这样的文件或目录) 09-06 11:48:50.952 10172 10172 E Android 实施:在 java.io.FileInputStream.open0(本机方法) 09-06 11:48:50.952 10172 10172 E Android 实施:在 java.io.FileInputStream.open(FileInputStream.java:200) 09-06 11:48:50.952 10172 10172 E Android 实施:在 java.io.FileInputStream.(FileInputStream.java:150) 09-06 11:48:50.952 10172 10172 E AndroidImplementation:在 android.app.ContextImpl.openFileInput(ContextImpl.java:515) 09-06 11:48:50.952 10172 10172 E Android 实施:在 android.content.ContextWrapper.openFileInput(ContextWrapper.java:190) 09-06 11:48:50.952 10172 10172 E AndroidImplementation:在 com.codename1.impl.android.AndroidImplementation.getServiceProperties(AndroidImplementation.java:6081) 09-06 11:48:50.952 10172 10172 E AndroidImplementation:在 com.codename1.impl.android.AndroidImplementation.writeServiceProperties(AndroidImplementation.java:6107) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at com.codename1.CameraDemoStub.onStop(CameraDemoStub.java:166) 09-06 11:48:50.952 10172 10172 E AndroidImplementation:在 android.app.Instrumentation.callActivityOnStop(Instrumentation.java:1486) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: 在 android.app.Activity.performStop(Activity.java:7178) 09-06 11:48:50.952 10172 10172 E Android 实现:在 android.app.ActivityThread.performStopActivityInner(ActivityThread.java:4274) 09-06 11:48:50.952 10172 10172 E Android 实施:在 android.app.ActivityThread.handleStopActivity(ActivityThread.java:4333) 09-06 11:48:50.952 10172 10172 E Android 实现:在 android.app.ActivityThread.-wrap24(未知来源:0) 09-06 11:48:50.952 10172 10172 E Android 实施:在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1722) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: 在 android.os.Handler.dispatchMessage(Handler.java:105) 09-06 11:48:50.952 10172 10172 E Android 实现:在 android.os.Looper.loop(Looper.java:164) 09-06 11:48:50.952 10172 10172 E Android 实现:在 android.app.ActivityThread.main(ActivityThread.java:6798) 09-06 11:48:50.952 10172 10172 E Android 实现:在 java.lang.reflect.Method.invoke(本机方法) 09-06 11:48:50.952 10172 10172 E Android 实施:在 com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

错误 4 -

09-06 11:48:51.005 10172 10172 D CameraDemo: [main] 0:0:0,3 - [LOG] 发生以下错误:NotAllowedError: Permission denied On line 55 of https://8319bf05.ngrok.io/ventasys/venta/code/camera1.html

上述错误(错误 4)来自从 CodeName One 调用的 .html。 这是 HTML 的代码:

<!DOCTYPE HTML>
<html>
  <head>
    <script>
        function copyPhoto() {
            var imgName;
            imgName = getParamValues("imgNm");        
            window.opener.document.getElementById(imgName).src = document.getElementById("theimage1").src;
            window.close();
        }

        function getParamValues(paramNm) {
            var qstring = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
            for (var i = 0; i < qstring.length; i++) {
                var urlparam = qstring[i].split('='); 
                if (urlparam[0] == paramNm) {                        
                    return urlparam[1];
                }
            }
        }

        function snapshot() {

            var canvas = document.getElementById("thecanvas");

            var ctx = canvas.getContext("2d");

            //var constraints = { video: { facingMode: "user" }, audio: false };
            //var constraints = {
            //    video: {
            //        width: { min: 640, ideal: 1920 },
            //        height: { min: 400, ideal: 1080 },
            //        aspectRatio: { ideal: 1.7777777778 },
            //        facingMode: "environment"
            //    },
            //    audio: false
            //};

            var constraints = {
                video: { facingMode: "user" },
                audio: false
            };

            try {

                navigator.mediaDevices.getUserMedia(constraints).then(                        
                    // successCallback
                    function (localMediaStream) {
                        document.getElementById("mylog").innerHTML = document.getElementById("mylog").innerHTML + '1.3 ';
                        video = document.querySelector('video');
                        video.srcObject = localMediaStream;
                    })
                    .catch(function (err) {
                        console.log("The following error occured: " + err);
                        document.getElementById("mylog").innerHTML = document.getElementById("mylog").innerHTML + ' <br> 5 Err' + err;
                    });

            }
            catch (e)
            {
                document.getElementById("mylog").innerHTML = document.getElementById("mylog").innerHTML + ' 6 catch ##** ' + e;
            }
            document.getElementById("mylog").innerHTML = document.getElementById("mylog").innerHTML + '10 ';
            canvas.width = 640;
            canvas.height = video.videoHeight / (video.videoWidth / canvas.width);

            // Draws current image from the video element into the canvas               
            //ctx.drawImage(video, 0,0, video.videoWidth, video.videoHeight);
            ctx.drawImage(video, 0, 0, canvas.width, canvas.height);

            var canvas = document.getElementById("thecanvas");
            var dataUrl = canvas.toDataURL('image/jpeg', 0.6);
        }
    </script>
</head>
<body onload="snapshot();">
    <div id='mylog'></div>
    <p><video id="video" controls autoplay></video></p>
    <p><button onclick="snapshot();">Take Snapshot</button></p>
    <div id='item' hidden>
        <p><canvas id="thecanvas"></canvas></p>
    </div>        
    <p><image id="theimage1"></image></p>
    <p><button onclick="copyPhoto()">Done</button></p>
    <p><button onclick="copyPhoto()">Reload</button></p>
</body>
</html>

【问题讨论】:

  • 标题是否设置为“相机权限为真”?当您进入Android中的应用程序设置时,它有摄像头吗?您是否还通过构建提示将相机权限添加到清单 XML 中?
  • 对不起,我没看懂第一条评论 Android 中的应用设置没有显示相机。不,我也没有提供构建提示......让我尝试添加它。
  • 在构建提示中添加了 android.permission.CAMERA true。现在,一旦打开应用程序,它就会要求相机许可。我说允许。标题栏显示“Camera Permission True”。但仍然在浏览器中,视频控件不起作用...
  • 好的,现在看一下日志。当您杀死并重新启动应用程序时,是否还打印了其他内容?
  • 如何从设备获取日志?我在开发人员工具下找到了“提交错误报告”。是那个吗?

标签: android camera codenameone


【解决方案1】:

尝试将此添加到您的 init(Object) 方法中:

Display.getInstance().setProperty("android.WebView.grantPermissionsFrom", url_of_your_video_page);

您可以添加多个以空格分隔的 URL。如果这不起作用,我们可能需要其他东西。

【讨论】:

  • 谢谢谢。我添加了您建议的属性并重建了应用程序。但它没有用。得到相同的权限被拒绝错误。
  • 我的错!!我已将视频页面的 URI 指定为 .html 的完整路径。将其更改为根 URL。所以,例如如果正在加载的页面是“example.com/video/loadVideo.html”,则上述属性的 URL 应设置为“example.com”。请注意,URL 中的尾随“/”很关键。没有尾随的“/”,它不起作用。非常感谢 Shai 的帮助!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-11
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
  • 2013-01-20
相关资源
最近更新 更多