Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
841 views
in Technique[技术] by (71.8m points)

cordova navigator.camera.getPicture not working in android

navigator.camera.getPicure function not working. Its callback function never gets fired in below code. This function is from cordova camera plugin.

navigator.camera.getPicture(
                            uploadPhoto,
                            function(message) {
                                alert('Failed to get a picture. Please select one.');
                            }, {
                                quality         : 50,
                                destinationType : Camera.DestinationType.FILE_URI,
                                sourceType      : Camera.PictureSourceType.SAVEDPHOTOALBUM
                            });

In the above code uploadPhoto callback function never gets fired. And there is no traces of it in chrome dev tools console when the above function is called it opens the file selection window and after the image is selected for upload it simply returns, and then the screen gets refreshed.

Update 6/26 After more testing noticed that this behavior different between two different android devices one with Jelly bean version 4.4.2 and other Jelly bean version 4.4.4. In the device running with 4.4.4 navigator.camera.getPicture was successfully called but struck at file transfer. The device running Jelly bean 4.4.2 has just failed at navigator.camera.getPicture without calling its success or error callback functions which is where I struck since few days. Looks like the cordova 5.1 with camera plugin 2.2.0 does not work with Jelly Bean or few of its versions. Maybe I will need to find cordova version & the cordova camera plugin version that works on Jelly Bean.

Update 6/25 Migrated the code from Telerik AppBuilder to PhoneGap. PhoneGap uses Cordova 5.1 and configured latest Camera Plugin 2.2.0, however issue is still the same. Not sure if this issue is same as in this post quite interesting this issue is not listed in release notes, I tested in different android versions it did not work. And atleast no response to the ticket raised in Telerik Premium support so far.

Update 6/23 1:28IST As suggested by Devid, followed this post I added below recommended fix right before the call navigator.camera.getPicture, the issue remains same.

if (device.platform === 'Android') {
  setInterval(function () {
     cordova.exec(null, null, '', '', [])
  }, 200);
}

UPDATE: 6/23 I checked the behavior in the console from chrome://inspect there is absolutely no trace during file upload activity. In the network tab could not find this http request. To understand where it stopped functioning I added console.log each stage within uploadFile function what I noticed was it did not trigger uploadPhoto callback function in navigator.camera.getPicture, but this call does invoked file chooser, but after file selection its callback uploadPhoto function did not trigger. Looks like the app is not having some access rights on the device.

navigator.camera.getPicture(
    uploadPhoto,
    function(message) {
        rst.innerHTML = "Failed to get a picture. Please select one.";
    }, {
        quality         : 50,
        destinationType : navigator.camera.DestinationType.FILE_URI,
        sourceType      : navigator.camera.PictureSourceType.PHOTOLIBRARY
    });

Here is the catlog from ADB if at all gives some clue.

Update 2/24-9:15AMIST Below is the Android manifest, is there any permission that I am missing?

<?xml version="1.0" encoding="utf-8"?>
<manifest android:versionCode="$AndroidVersionCode$"
          android:versionName="$BundleVersion$"
          package="$AppIdentifier$"
          android:windowSoftInputMode="adjustPan"
          android:hardwareAccelerated="$AndroidHardwareAcceleration$"
          xmlns:android="http://schemas.android.com/apk/res/android" >
    <supports-screens
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true"
        android:xlargeScreens="true"
        android:resizeable="true"
        android:anyDensity="true"
        />

    <application android:label="@string/app_name"
                 android:icon="@drawable/icon"
                 android:hardwareAccelerated="$AndroidHardwareAcceleration$"
                 android:debuggable="true" >
        <activity android:label="@string/app_name"
                  android:name=".TelerikCallbackActivity"
                  android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"
                  android:launchMode="singleTop"
                  android:theme="@android:style/Theme.Black.NoTitleBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21"/>
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

The below cordova file upload code works perfect in simulator but fails when deployed in Android device.

Below is config.xml

<widget xmlns     = "http://www.w3.org/ns/widgets"
        version   = "2.0.0">

    <content src="index.html" />

    <!-- Whitelist docs: https://github.com/apache/cordova-plugin-whitelist -->

    <!-- allow local pages -->
    <!-- <access origin="http://127.0.0.1*"/> -->
    <access origin="*" />

    <!-- Grant certain URLs the ability to launch external applications. This
         behaviour is set to match that of Cordova versions before 3.6.0, and
         should be reviewed before launching an application in production. It
         may be changed in the future. -->
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <allow-intent href="market:*" />

    <preference name="loglevel" value="DEBUG" />
    <!--
      <preference name="splashscreen" value="splash" />
      <preference name="backgroundColor" value="0xFFF" />
      <preference name="loadUrlTimeoutValue" value="20000" />
      <preference name="InAppBrowserStorageEnabled" value="true" />
      <preference name="disallowOverscroll" value="true" />
    -->
</widget>

Below is the client code

uploadFile: function () {
    rst = document.getElementById(this.id + 'res');
    rst.innerHTML = "";
    var uploadTYPE = this.id;
    navigator.camera.getPicture(
        uploadPhoto,
        function(message) {
            rst.innerHTML = "Failed to get a picture. Please select one.";
        }, {
            quality         : 50,
            destinationType : navigator.camera.DestinationType.FILE_URI,
            sourceType      : navigator.camera.PictureSourceType.PHOTOLIBRARY
        });

    function uploadPhoto(fileURI) {
        var options = new FileUploadOptions();
        options.fileKey = "file";
        options.fileName = fileURI.substr(fileURI.lastIndexOf('/') + 1);

        if (cordova.platformId == "android") {
            options.fileName += ".jpg" 
        }

        options.mimeType = "image/jpeg";
        //options.httpMethod = "PUT";
        //options.contentType = 'multipart/form-data';
        var params = new Object();
        params.uid = localStorage.getItem("FOSCode");
        params.utyp = uploadTYPE;
        options.params = params; 

        options.headers = {
            Connection: "close"
        };
        //options.httpMethod = 'POST';
        options.chunkedMode = false;

        var ft = new FileTransfer();

        rst.innerHTML = "Upload in progress...";
        ft.upload(
            fileURI,
            encodeURI("https://www.kinrep.com/foster/upload.php"),
            onFileUploadSuccess,
            onFileTransferFail,
            options, true);

        function onFileUploadSuccess (result) {
           // rst.innerHTML = "Upload successful";
            console.log("FileTransfer.upload");
            console.log("Code = " + result.responseCode);
            console.log("Response = " + result.response);
            console.log("Sent = " + result.bytesSent);
            console.log("Link to uploaded file: https://www.kinrep.com/foster/ws/contentlibrary/" + result.response);
            var response = result.response;
            var destination = "https://www.kinrep.com/foster/WS/ContentLibrary/" + response.substr(response.lastIndexOf('=') + 1);
            if(this.id == 'uploadcheque') {
                document.getElementById("hdnchequeimgpath").value = destination;

            } else if(this.id == 'uploaddoorlock') {

                document.getElementById("hdndoorlockedimgpath").value = destination;
            } else {

                document.getElementById("hdnothersimgpath").value = destination;
            }
            rst.innerHTML = "File uploaded to: " +
                                                          destination + 
                                                          "</br><button class="button" onclick="window.open('" + destination + "', '_blank', 'location=yes')">Open Location</button>";
            //document.getElementById("downloadedImage").style.display="none";
        }

        function onFileTransferFail (error) {

            rst.innerHTML = "File Transfer failed: " + error.code;
            alert(rst.innerHTML);
            console.log("FileTransfer Error:");
            console.log("Code: " + error.code);
            console.log("Source: " + error.source);
            console.log("Target: " + error.target);
        }
    }

From the logcat I could not trace anything from my app after reproducing the error. Android just simply does not do anything on file upload activity from my app. The same activity works perfect from simulator.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Okay, since no one answered my question posted since 12 days, decided to answer my own question. After various findings on this issue across the net. I found there is one community which is test certifying cordova builds across the devices. In their website it is clearly documented that there are issues with cordova-camera-plugin with Android devices. Below is what is mentioned at their website

cordova-plugin-camera (version 1.0.1). The camera fails many of our tests on Samsung devices running Jellybean, Kitkat, and Lollipop. We noticed various other issues across iOS and Windows Phone 8 as well. Because of these issues, we will not be including the camera as a part of this kit.

There are some suggested workarounds which I also referred in my question, but unfortunately those did not work on Jelly Bean platforms I am testing with right now.

And hence so the logical conclusion is to develop & build the native app using Android SDK in Android studio instead wasting time & energy in finding a fix for cordova-camera-plugin. I know this may not be ideal but I think this is how to deal with at this point of time. Hope this answer saves time to some who experience similar issues

Looks like corodva camera plugin works with latest android 6.x versions. https://issues.apache.org/jira/browse/CB-10857 But this will not work for my case where my users are still with old android versions. This would be the only choice when file transfers wont work even in native SDK code, but that is quite unlikely the case.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...