1
votes

We're building a mobile app for Android using CodeName One. As part of our requirement, we already have an HTML5 page that contains a video element to use a device's camera for capturing photos. We need to call this HTML5 page from within our CodeName One app. But this code is not working as per the expectations, however the html file URL is working perfectly fine when called directly from chrome browser. When viewed from the chrome browser I get the prompt for asking camera permission where as in CodeName One app I don't see the permission prompt.

I saw a similar question posted recently html video control is not working in codenameone app for android

I've tried the recommendations given there, but it hasn't worked for me. Maybe something wrong that I'm doing here?

In my CodeName one class, I have the following code. The code basically creates a new BrowserComponent and sets the camera1.html URL in this component. The camera1.html contains HTML5 code that displays the video element for taking pictures. `

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(){
}

` I have defined a native interface that looks like this

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

Generated the native access code for this interface in CodeName One and the implementation for Android is as follows

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;
    }

}

When I run this on an Android device, I can see the HTML page getting loaded, but the video element doesn't load, All I see is the placeholder for the video element. The app does not ask for camera permission either, something that was suggested in the other related question.

What am I doing wrong here?

Update 1:

I see the following errors in the log obtained from the device using the adb shell "logcat --pid=$(pidof -s com.codename1)" command:

Error1 -

09-06 11:48:42.530 10172 10202 I WebViewFactory: Loading com.android.chrome version 69.0.3497.76 (code 349707652) 09-06 11:48:42.595 10172 10202 I zygote64: Rejecting re-init on previously-failed class java.lang.Class: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/webkit/TracingController; 09-06 11:48:42.595 10172 10202 I zygote64: at 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: at 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: at java.lang.Class android.webkit.WebViewFactory.getWebViewProviderClass(java.lang.ClassLoader) (WebViewFactory.java:151) 09-06 11:48:42.595 10172 10202 I zygote64: at java.lang.Class android.webkit.WebViewFactory.getProviderClass() (WebViewFactory.java:472) 09-06 11:48:42.595 10172 10202 I zygote64: at android.webkit.WebViewFactoryProvider android.webkit.WebViewFactory.getProvider() (WebViewFactory.java:212) 09-06 11:48:42.595 10172 10202 I zygote64: at android.webkit.CookieManager android.webkit.CookieManager.getInstance() (CookieManager.java:39) 09-06 11:48:42.595 10172 10202 I zygote64: at 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) 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: at void java.lang.Thread.run() (Thread.java:764) 09-06 11:48:42.595 10172 10202 I zygote64: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.webkit.TracingController" on path: DexPathList[[zip file "/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: at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:93) 09-06 11:48:42.595 10172 10202 I zygote64: at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379) 09-06 11:48:42.595 10172 10202 I zygote64: at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312) 09-06 11:48:42.595 10172 10202 I zygote64: at 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: at 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: at java.lang.Class android.webkit.WebViewFactory.getWebViewProviderClass(java.lang.ClassLoader) (WebViewFactory.java:151) 09-06 11:48:42.595 10172 10202 I zygote64: at java.lang.Class android.webkit.WebViewFactory.getProviderClass() (WebViewFactory.java:472) 09-06 11:48:42.595 10172 10202 I zygote64: at android.webkit.WebViewFactoryProvider android.webkit.WebViewFactory.getProvider() (WebViewFactory.java:212) 09-06 11:48:42.595 10172 10202 I zygote64: at android.webkit.CookieManager android.webkit.CookieManager.getInstance() (CookieManager.java:39) 09-06 11:48:42.595 10172 10202 I zygote64: at 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)

Error 2 -

09-06 11:48:44.506 10172 10266 W VideoCapabilities: Unrecognized profile 2130706433 for video/avc 09-06 11:48:44.506 10172 10266 W VideoCapabilities: Unrecognized profile 2130706434 for video/avc 09-06 11:48:44.536 10172 10266 W VideoCapabilities: Unrecognized profile 2130706433 for video/avc 09-06 11:48:44.536 10172 10266 W VideoCapabilities: Unrecognized profile 2130706434 for video/avc 09-06 11:48:44.542 10172 10266 W VideoCapabilities: Unrecognized profile 2130706433 for video/avc 09-06 11:48:44.542 10172 10266 W VideoCapabilities: Unrecognized profile 2130706434 for video/avc 09-06 11:48:44.551 10172 10266 W VideoCapabilities: Unrecognized profile/level 0/3 for video/mpeg2 09-06 11:48:44.555 10172 10266 W VideoCapabilities: Unrecognized profile/level 0/3 for video/mpeg2 09-06 11:48:44.564 10172 10266 W VideoCapabilities: Unsupported mime video/x-ms-wmv 09-06 11:48:44.568 10172 10266 W VideoCapabilities: Unsupported mime video/x-ms-wmv 09-06 11:48:44.574 10172 10266 W VideoCapabilities: Unsupported mime video/divx 09-06 11:48:44.577 10172 10177 I zygote64: Do partial code cache collection, code=55KB, data=56KB 09-06 11:48:44.580 10172 10266 W VideoCapabilities: Unsupported mime video/divx311 09-06 11:48:44.584 10172 10266 W VideoCapabilities: Unsupported mime video/divx4 09-06 11:48:44.585 10172 10177 I zygote64: After code cache collection, code=55KB, data=56KB 09-06 11:48:44.585 10172 10177 I zygote64: Increasing code cache capacity to 256KB 09-06 11:48:44.605 10172 10266 W VideoCapabilities: Unsupported mime video/mp4v-esdp 09-06 11:48:44.633 10172 10266 I VideoCapabilities: Unsupported profile 4 for video/mp4v-es 09-06 11:48:44.867 10172 10282 W cr_CrashFileManager: /data/user/0/com.codename1/cache/WebView/Crash Reports does not exist or is not a directory

Error 3 -

09-06 11:48:47.715 10172 10253 I CameraManagerGlobal: Connecting to camera service 09-06 11:48:47.799 10172 10172 D Codename One: onPermissionRequest 09-06 11:48:50.952 10172 10172 E AndroidImplementation: null 09-06 11:48:50.952 10172 10172 E AndroidImplementation: java.io.FileNotFoundException: /data/user/0/com.codename1/files/CN1$AndroidServiceProperties (No such file or directory) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at java.io.FileInputStream.open0(Native Method) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at java.io.FileInputStream.open(FileInputStream.java:200) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at java.io.FileInputStream.(FileInputStream.java:150) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at android.app.ContextImpl.openFileInput(ContextImpl.java:515) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at android.content.ContextWrapper.openFileInput(ContextWrapper.java:190) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at com.codename1.impl.android.AndroidImplementation.getServiceProperties(AndroidImplementation.java:6081) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at 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: at android.app.Instrumentation.callActivityOnStop(Instrumentation.java:1486) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at android.app.Activity.performStop(Activity.java:7178) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:4274) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4333) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at android.app.ActivityThread.-wrap24(Unknown Source:0) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1722) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at android.os.Handler.dispatchMessage(Handler.java:105) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at android.os.Looper.loop(Looper.java:164) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at android.app.ActivityThread.main(ActivityThread.java:6798) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at java.lang.reflect.Method.invoke(Native Method) 09-06 11:48:50.952 10172 10172 E AndroidImplementation: at 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)

Error 4 -

09-06 11:48:51.005 10172 10172 D CameraDemo: [main] 0:0:0,3 - [LOG] The following error occured: NotAllowedError: Permission denied On line 55 of https://8319bf05.ngrok.io/ventasys/venta/code/camera1.html

This above error (Error 4) is coming out of the .html that is called from CodeName One. Here's the code for 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>
1
Was the title set to "Camera Permission True"? When you go into the app settings in Android does it have the camera? Did you also add the camera permissions to the manifest XML via the build hints? - Shai Almog
I am sorry I did not understand the first comment The app settings in Android is not showing the camera. And no, I did not provide the build hints either...let me try to add that. - Girish
Added android.permission.CAMERA true in build hints. Now as soon as the app is opened it is asking for the camera permission. I said allow. The title bar showing "Camera Permission True". But still in the browser the video control is not working... - Girish
OK, so now take a look in the logs. Is something else printed there when you kill and restart the app? - Shai Almog
How do I get the logs from the device? I found "Take a bug report" under Developer tools. Is that the one? - Girish

1 Answers

0
votes

Try adding this to your init(Object) method:

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

You can add multiple URL's separated by spaces. If this doesn't work we might need something else.