Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Web and WebWorks Development

Reply
Developer
Posts: 29
Registered: ‎04-01-2013
My Device: Z10
My Carrier: Rogers

Re: Cordova 3.2.0 Capture Plugin not working

[ Edited ]

Also, just for **bleep**s and giggles, I tried doing as you suggested and I quickly hacked in a test where I don't use the resolveLocalFileSystemURI and instead just take the fileURI and remove the "file://" from the front of it, and pass that in as the path to the FileTransfer (so now I am passing in "/accounts/1000/shared/camera/IMG_00000015.jpg") and the FileTransfer returns with error code 1 which is FileTransferError.FILE_NOT_FOUND_ERR, so that doesn't seem to work either...unless I need some other permission now

Retired
Posts: 1,561
Registered: ‎04-12-2010
My Device: BlackBerry Z10
My Carrier: Bell

Re: Cordova 3.2.0 Capture Plugin not working

I have a feeling that both approaches are hitting the same issue.

 

When the Capture APIs save a screenshot, they, by default, are saving it outside of the sandbox to the shared folders.

 

However, I believe the application is still configured to be in the sandbox, resulting in the behaviour you're seeing with window.resolveLocalFileSystemURI (i.e. sandboxState = true) and also the file not found error if you drop the file:// protocol (i.e. we're looking inside the sandbox by default, but the Capture plugin saved the image outside of the sandbox in the shared folders.)

 

I believe either approach should work if we can configure the sandbox properly.

 

I need to check if there is a Cordova-specific way to accomplish this, but in WebWorks we have the blackberry.io.sandbox variable which you can set to true or false during runtime. For WebWorks filesystem access, this dictates whether to look inside (default) our outside of the sandbox.

 

While different context, what's mentioned here is likely what is the root:

http://stackoverflow.com/a/15883952

 

As you are using direct Cordova, we'll need to get webworks going. To do so, you'll need to add the following feature to your config.xml:

 

<feature id="blackberry.io" />

 

 

And we'll also need to load the webworks script:

 

<script type="text/javascript" src="local:///chrome/webworks.js"></script>

 

 

Following that, we want to set an event listener for webworksready to know when the blackberry object is available, and once it is, set the sandbox:

 

document.addEventListener('webworksready', function () {

    blackberry.io.sandbox = false;

}, false);

 

 

Tim gives some good advice in the Stack Overflow post. Basically, dropping the file:// tends to be safe, but best practices are to use the blackberry.io variables to specify the root of the path, and then provide the file name, example:

blackberry.io.sharedFolder + 'camera/IMG_00000037.jpg'

 

 

I believe you will need to dip into the WebWorks APIs to set the sandbox state properly, which should hopefully resolve the issue with both approaches. I'll start up on a test project in the meantime.


Erik Oros | @WaterlooErik | eoros@blackberry.com | Developer Issue Tracker

If a reply has answered your question, please click Accept as Solution to help other visitors in the future.
Developer
Posts: 29
Registered: ‎04-01-2013
My Device: Z10
My Carrier: Rogers

Re: Cordova 3.2.0 Capture Plugin not working

The resolveLocalFileSystemURI plugin tries to set sandbox to false if it thinks the file is outside the sandbox (look at my previous comment again) but it doesn't think it is outside the sandbox and therefore doesn't turn it off. Also, I tried modifying the plugin to turn sandbox mode off all the time and that didn't seem to do anything either
Developer
Posts: 29
Registered: ‎04-01-2013
My Device: Z10
My Carrier: Rogers

Re: Cordova 3.2.0 Capture Plugin not working

Erik, haven't heard back from you in a while. Did you get my pervious comment? It already seems like the cordova plugin is trying to check to see if the file is outside the sandbox and trying to set the sandbox state already. So either there is a bug in that code, or the sandbox isn't the issue.

 

cordova-app\plugins\org.apache.cordova.file\www\blackberry10\resolveLocalFileSystemURI.js:

/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

var fileUtils = require('./BB10Utils'),
    FileError = require('./FileError');

function stripURI(uri) {
    var rmFsLocal = uri.substring("filesystem:local:///".length);
    return rmFsLocal.substring(rmFsLocal.indexOf('/') + 1);
}

module.exports = function (uri, success, fail) {
    var sandboxState,
        decodedURI = decodeURI(uri);

    cordova.exec(function (sandboxed) {
        sandboxState = sandboxed;
    }, function (e) {
        console.log("[ERROR]: Could not retrieve sandbox state ", e);
    }, "org.apache.cordova.file", "isSandboxed");

    if (fileUtils.isOutsideSandbox(stripURI(decodedURI))) {
        cordova.exec(null, null, "org.apache.cordova.file", "setSandbox", [false]);
    } else {
        cordova.exec(null, null, "org.apache.cordova.file", "setSandbox", [true]);
    }
    window.webkitResolveLocalFileSystemURL(decodedURI, function (entry) {
        success(fileUtils.createEntry(entry));
    }, function (e) {
        window.webkitResolveLocalFileSystemURL(decodedURI + '/', function (entry) {
            success(fileUtils.createEntry(entry));
        }, function (e) {
            fail(e);
        });
    });
    cordova.exec(null, null, "org.apache.cordova.file", "setSandbox", [sandboxState]);
};

 

 

Retired
Posts: 1,561
Registered: ‎04-12-2010
My Device: BlackBerry Z10
My Carrier: Bell

Re: Cordova 3.2.0 Capture Plugin not working

I see what you mean.

 

I'm in the middle of buliding out a test app for this. I should have a follow-up soon. If we can't get it to work, I'll be logging a JIRA with our development teams.


Erik Oros | @WaterlooErik | eoros@blackberry.com | Developer Issue Tracker

If a reply has answered your question, please click Accept as Solution to help other visitors in the future.
Highlighted
Retired
Posts: 1,561
Registered: ‎04-12-2010
My Device: BlackBerry Z10
My Carrier: Bell

Re: Cordova 3.2.0 Capture Plugin not working

[ Edited ]

oros wrote:

Hi Jeff, I just managed to get a sample of this working. Here is what I did.

 

From the command-line, here are the webworks commands I ran:

 

C:\webworks>webworks create capture

C:\webworks>cd capture

C:\webworks\capture>webworks plugin add org.apache.cordova.media-capture

C:\webworks\capture>webworks run

 

Prior to executing the webworks run command, I madea few modifications. To config.xml, at the root www folder I added:

 

	<access origin="file:///" subdomains="true" />
	<rim:permissions>
		<rim:permit>access_shared</rim:permit>
	</rim:permissions>

 

Note that the <access> origin has three / characters.

 

In my config.xml, I added two HTML element for my testing, wrapped in a div:

 

		<div>
			<img id="imgTarget" width="480" height="480" src="" />
			<button onclick="captureImage();">Capture Image</button> <br>
		</div>

 And I defined the captureImage function as follows:

 

        <script type="text/javascript">
			function captureImage() {
				navigator.device.capture.captureImage(
					function captureSuccess(result) {
						document.querySelector('#imgTarget').src='file://' + result[0].fullPath;
					},
					function captureError(result) {
						console.log('error');
						console.log(result);
					}
				);
			}
		
            app.initialize();
        </script>

 

Note that the app.initialize() call is from the auto-generated code. I left it in just to show where in the code I added the function.

 

With this, the <img> element successfully loads the image.

 


Building off this sample, with the intent of calling FileTransfer.upload on the resulting file, I took the following steps.

 

From my root project folder, using the command-line, added the FileTransfer plugin:

webworks plugin add com.blackberry.io.filetransfer

 

Modified the captureSuccess function to:

 

function captureSuccess(result) {
	try {
		blackberry.io.filetransfer.upload(
			result[0].fullPath,
			'http://myserver.oros.net/fileTransfer/upload.php',
			function uploadSuccess(result) {
				console.log('Bytes sent: ' + result.bytesSent);
				console.log('Response code: ' + result.responseCode);
				console.log('Response: ' + result.response);
			},
			function uploadError(result) {
				console.log('Error code: ' + result.code);
				console.log('Source: ' + result.source);
				console.log('Target: ' + result.target);
				console.log('HTTP Status: ' + result.https_status);
			},
			{
				'fileKey': 'file',
				'fileName': 'upload.jpg',
				'mimeType': 'image/jpeg',
				'params': {
					'app': 'webworks'
				},
				'chunkedMode': true,
				'chunkSize': 1024
			}
		);
	} catch (err) {
		console.log(err);
	}
},

 

I also made sure my local web server was live/running (matching the URL used in the upload call), it is an Apache instance, and in httpd.conf I enabled access from all outside devices:

 

<Directory "c:/wamp/www">
    # ...other default stuff was here... #

    Allow from all
</Directory>

Finally, upload.php was defined as in the sample code here:

https://developer.blackberry.com/html5/apis/beta/blackberry_io_filetransfer_upload.html

 

With this, I saw success. The image was uploaded to my web server, and the resulting output was:

 

Bytes sent: 802144 index.html:53
Response code: 200 index.html:54
Response: Success 

 


Erik Oros | @WaterlooErik | eoros@blackberry.com | Developer Issue Tracker

If a reply has answered your question, please click Accept as Solution to help other visitors in the future.
Developer
Posts: 29
Registered: ‎04-01-2013
My Device: Z10
My Carrier: Rogers

Re: Cordova 3.2.0 Capture Plugin not working

ok, I finally have time to get back on this. First, my appologies, I mentioned the capture plugin when what I really meant was the camera plugin. We use both, I don't know if the capture plugin works as I am currently trying to get the camera plugin working. The difference is that the capture plugin returns a media object which has the fullPath property and you can just send that to the file transfer, whereas the camera plugin returns an imageURI which you need to resolve to an actual fileEntry to get the fullPath. I've put together a simple example using a brand new cordova 3.2.0 project (I've marked my file additions with ++):

 

run:

cordova create hello com.hello Hello
cd hello
cordova platform add blackberry10
cordova plugin add org.apache.cordova.camera
cordova plugin add org.apache.cordova.file

 

edit www/config.xml

<?xml version='1.0' encoding='utf-8'?>
<widget
	id="com.hello"
	version="0.0.1"
	xmlns="http://www.w3.org/ns/widgets"
	xmlns:cdv="http://cordova.apache.org/ns/1.0"
	xmlns:rim="http://www.blackberry.com/ns/widgets">
    <name>Hello</name>
    <description>
        A sample Apache Cordova application that responds to the deviceready event.
    </description>
    <author email="dev@cordova.apache.org" href="http://cordova.io">
        Apache Cordova Team
    </author>
    <content src="index.html" />
    <access origin="*" />
++	<access origin="file:///" subdomains="true" />
++	<rim:permissions>
++		<rim:permit>access_shared</rim:permit>
++	</rim:permissions>
</widget>

 

edit www/index.html

<html>
    <head>
        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
        <link rel="stylesheet" type="text/css" href="css/index.css" />
        <title>Hello World</title>
    </head>
    <body>
        <div class="app">
            <h1>Apache Cordova</h1>
            <div id="deviceready" class="blink">
                <p class="event listening">Connecting to Device</p>
                <p class="event received">Device is Ready</p>
            </div>
++			<div>
++				<img id="imgTarget" width="80" height="80" src="" />
++				<button onclick="takePhoto();">Take Photo</button>
++			</div>
        </div>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
        <script type="text/javascript">
            app.initialize();
++			
++			function takePhoto() {
++				//
++				// Take a photo
++				//
++				navigator.camera.getPicture(
++					/**
++					* Success (getPicture)
++					*/
++					function(imageURI) {
++						//
++						// Add the imageURI to the page so we can see we got it
++						//
++						var image = document.getElementById('imgTarget');
++						image.src=imageURI;
++						
++						//
++						// Now resolve the imageURI to a fileEntry so we can get the fullPath
++						//
++						window.resolveLocalFileSystemURI(
++							imageURI,
++							/**
++							* Success (resolveLocalFileSystemURI)
++							*/
++							function(fileEntry) {
++								alert(fileEntry.fullPath);
++							},
++							/**
++							* Fail (resolveLocalFileSystemURI)
++							*/
++							function(error) {
++								alert('resolveLocalFileSystemURI failed because: ' + JSON.stringify(error));
++							}
++						);
++					},
++					/**
++					* Fail (getPicture)
++					*/
++					function(message) {
++						alert('getPicture failed because: ' + message);
++					},
++					/**
++					* Options
++					*/
++					{
++						quality: 50,
++						destinationType: Camera.DestinationType.FILE_URI
++					}
++				);
++			}
        </script>
    </body>
</html>

 

run:

cordova emulate blackberry10 --devicepass <devicepass>

 

When you tap the "Take Photo" button, I can take a photo, the image is updated on the page, but the resolve fails with code 5.

Retired
Posts: 1,382
Registered: ‎07-02-2009
My Device: BlackBerry Bold 9900
My Carrier: Bell

Re: Cordova 3.2.0 Capture Plugin not working

Error code 5 is an encoding error, which leads me to believe the path being passed into resolveLocalFileSystemURI is not a valid URI.  I'm not sure what format the org.apache.cordova.camera API is return values for getPicture().

 

Can you inspect the value of the imageURI variable?  If it doesn't have a "file:///" prefix, then you should include that when calling resolveLocalFileSystemURI, like this:

 

window.resolveLocalFileSystemURI(
   "file:///" + imageURI,
   /**
   * Success (resolveLocalFileSystemURI)
   */
   function(fileEntry) {
      alert(fileEntry.fullPath);
   },

I'm not 100% familiar with the org.apache.cordova.camera API, but I believe the value that getPicture returns is

 

Follow me on Twitter: @n_adam_stanley
-------------------------------------------------------------------------------------------------------------------------
Your app doesn't work? Use BlackBerry remote web inspector to find out why.
Developer
Posts: 29
Registered: ‎04-01-2013
My Device: Z10
My Carrier: Rogers

Re: Cordova 3.2.0 Capture Plugin not working

I modified my error alert to output the imageURI, and it looks somethings like:

file:///accounts/1000/shared/camera/IMG_00000015.jpg

 

So the imageURI is formatted correctly. As I mentioned in a previous post this is the same error I get in my app. I also mentioned that the resolveLocalFileSystemURI provided by cordova trys to turn the sandbox off if needed. So, either there is something wrong with the way cordova does that, or the sandbox isn't the issue either.

 

Here is my previous post (or just scroll up a bit to post #14):

http://supportforums.blackberry.com/t5/Web-and-WebWorks-Development/Cordova-3-2-0-Capture-Plugin-not...

 

 

Retired
Posts: 1,561
Registered: ‎04-12-2010
My Device: BlackBerry Z10
My Carrier: Bell

Re: Cordova 3.2.0 Capture Plugin not working

Definitely seeing an issue here as well. Is started with your sample and included the org.apache.cordova-file-transfer plugin (as that was the intended goal as I recall, plus for comparison purposes.)

 

The WebWorks Capture plugin I previously used leverages the following file path:

/accounts/1000/removable/sdcard/camera/IMG_20131220_182442.jpg

 

The Cordova Camera plugin leverages the followign file path:

/accounts/1000/removable/sdcard/camera/IMG_20131220_182724.jpg

 

Basically the same starting point for the actual file path. In both cases, using the URL on an <img> src requires prepending file:// as previously noted and succeeds.

 

For the actual FileTransfer portion:

  • WebWorks, the upload succeeds.
  • Cordova, I am getting the file not found error.

I am inclined to agree that Cordova is stuck inside the sandbox. Let me reach out to our WebWorks team (as they commit back to Cordova as well) to see if they have any input here.


Erik Oros | @WaterlooErik | eoros@blackberry.com | Developer Issue Tracker

If a reply has answered your question, please click Accept as Solution to help other visitors in the future.