Just getting started with PhoneGap File API / Cordova 3.0 and I have a little issue looking up a file
using getFile(). Don't know if the chaining is wrong. Or just missing the obvious...
I get to gotFS, passing in the full path as file:///storage/emulated/0/DCIM/Camera/... and the result is an error 5. I am guessing the path is not correct, or I can't get to storage/emulated?
The whole point is to return the file as a base64-encoded data URL e.g.,readAsDataURL.
// I just finished taking a video
//
function captureSuccess(mediaFile) {
// Store the results
//
window.media = mediaFile;
// Get started with the file request
//
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
function gotFS(fileSystem) {
// Get the path of the file
// Will return something like //file:///storage/emulated/0/DCIM/Camera/....
//
var fullPath = window.media[0].fullPath;
// Let's try and resolve, make sure I'm not crazy. I might be.
//
window.resolveLocalFileSystemURI(fullPath, winConvert, failConvert);
function winConvert(uri){
// The resolve matches file location stored at window.media
//
console.log(uri);
}
function failConvert(error){
console.log('Something happend resolving uri: '+error.code);
}
fileSystem.root.getFile(fullPath, null, gotFileEntry, fail);
}
function gotFileEntry(fileEntry) {
console.log('gotFileEntry');
fileEntry.file(gotFile, fail);
}
function gotFile(file){
console.log('gotFile');
readDataUrl(file);
}
function readDataUrl(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log(evt.target.result);
};
reader.readAsDataURL(file);
}
function fail(error) {
console.log(error.code);
}
}
Related
I have the contacts plugin in my app and on one test device (iPhone 5, iOS 9.02) the contact list does not show. And when I do a search, nothing appears. I get no error messages. On some of my other devices like some Android or iOS 8.x devices it does work. This particular problem device has 1200 contacts. Anyone have some suggestions on how to fix? I'll paste the relevant part of my code. Although maybe it is more of a configuration issue?
$scope.getAllContacts = function(searchQuery) {
try {
var opts = { //search options
filter: searchQuery, // 'Bob'
multiple: true, // Yes, return any contact that matches criteria
fields: ['displayName', 'name']
};
if (ionic.Platform.isAndroid()) {
opts.hasPhoneNumber = true; //hasPhoneNumber only works for android.
};
$ionicLoading.show();
$cordovaContacts.find(opts).then(function(contactsFound) {
$scope.contacts = contactsFound;
$ionicLoading.hide();
});
} catch (err) {
alert(err.message);
}
};
$scope.getAllContacts("Ak");
Hi use this to save all contacts in sdcard and display. (default Cordova contacts and file plugin)
document.addEventListener("deviceReady", deviceReady, false);
function deviceReady() {
navigator.contacts.find(["*"], function(contacts) {
// alert("contacts.length = " + contacts.length);
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem) {
fileSystem.root.getFile("contacts.json", {create: true, exclusive: false}, function(fileEntry) {
fileEntry.createWriter(function(writer) {
writer.onwriteend = function(){
// Success Contacts saved to sdcard as a contacts.json file
// Now get and read the json file
var path = fileSystem.root.getFile("contacts.json", {create:false},gotFileEntry, fail);
// jquery
$.getJSON(path, function (data) {
user = data;
$.each(user, function (index, user) {
var all_item = '<p id="'+user.id+'">'+user.displayName+'</p>';
$('#allcontacts').append(all_item);
});
});
};
writer.write(JSON.stringify(contacts));
}, onError);
}, onError);
}, onError);
}, onError,{"multiple": true});}
function onError(){
alert("Error");
}
You may use navigator.contacts.find, and see if this works in your phone.
For more details
https://github.com/apache/cordova-plugin-contacts
I have a app using cordova 3.4 and file 1.1.0.
If I copy a image using the camera-modul, I use
myFileObj.path = file.toNativeURL()
to get the file-path. If I put this path into a img-tag I get shown the picture on Android.
On iOS it doesn't work. The result of file.toNativeURL():
myFileObj.path -> file:///Users/.../Library/Application%20Support/..../myFolder/myImage.JPG
Using file 1.0 I had to build the url and it looked like this:
myFileObj.path = dirTarget.toURL() + '/' + targetFileName
myFileObj.path -> cdvfile://localhost/persisten/myFolder/myImage.JPG
Where videos and audios didn't work, but at least pictures.
Using file 1.1.0/1.1.1 the result of this method is different too:
myFileObj.path -> file:///Users/mak/Library/.../myFolder/myImage.JPG?id=.....&ext=JPG
This doesn't work on iOS either.
How can I get a working file-path by using cordova file-module version 1.1.0 and 1.1.1?
EDIT: What am I doing and what doesn't work:
I copy images from the media-library and put it into a folder I create myself.
What works in Android and doesn't work in iOS:
In Android the media-tags src attribute is able to display the resource, iOS can't find a resource at the src-path.
catching a file from the media-library:
navigator.camera.getPicture(onSuccess, onFail, {
destinationType: Camera.DestinationType.NATIVE_URI,
sourceType : Camera.PictureSourceType.PHOTOLIBRARY,
mediaType: Camera.MediaType.ALLMEDIA
});
success-callback:
function onSuccess(imageData) {
A.StoreFile(imageData, id);
}
create a folder and store file:
A.StoreFile = function(file, idBox) {
var targetDirectory = Config.getRootPath();
window.resolveLocalFileSystemURL(file, resolveFileSystemSuccess, resolveFileSystemError);
function resolveFileSystemSuccess(fileEntry) {
fileEntry.file(function(filee) {
mimeType = filee.type;
getFileSuccess(fileEntry, mimeType);
}, function() {
});
}
function getFileSuccess(fileEntry, mimeType) {
var targetFileName = name + '.' + fileNativeType;
var parentName = targetDirectory.substring(targetDirectory.lastIndexOf('/')+1),
parentEntry = new DirectoryEntry(parentName, targetDirectory);
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem) {
fileSystem.root.getDirectory(targetDirectory, {create: true, exclusive: false}, function(dirTarget) {
fileEntry.copyTo(dirTarget, targetFileName, function(entry) {
addFileToLocalStorage(entry);
}, function() {
})
})
}, resolveFileSystemError);
}
store file-information to a localStorageObject
function addFileToLocalStorage(file) {
fileList.addFile(
{
name:file.name,
internalURL: file.toNativeURL()
});
}
adding files dynamically to the dom:
myElement.find('.myMimeTypeTag').attr('src', fileList[f].internalURL);
This works with android, and not with iOS.
iOS-result of img-container:
Error-message:
DEPRECATED: Update your code to use 'toURL'
toURL doesn't work either
id="org.apache.cordova.file"
version="1.1.1-dev"
I've just tested this out, with a slightly simplified version of your code (you seem to have a lot of extra structure to your code that isn't shown, but if there's a significant difference between what I've done here and what your app does, then let me know. The problem will be in the difference.)
I've run this with Cordova 3.5.0, just released, using File 1.1.0 and Camera 0.2.9.
To create the app, I used the cordova command line tool, and just ran
cordova create so23801369 com.example.so23801369 so23801369
cd so23801369
cordova platform add ios
cordova plugin add org.apache.cordova.file
cordova plugin add org.apache.cordova.camera
This creates a default "Hello, Cordova" app, to which I've added some code that (I believe) replicates what your code does.
I added two lines to index.html:
<button id="doit">Do it</button>
<img class="myMimeTypeTag" src="file:///nothing" />
And I edited www/js/index.js to look like this:
var app = {
initialize: function() {
// Don't activate the button until Cordova is initialized
document.addEventListener('deviceready', this.onDeviceReady, false);
},
onDeviceReady: function() {
document.getElementById('doit').addEventListener('click', app.runTest, false);
},
runTest: function(ev) {
var StoreFile = function(file) {
var targetDirectory = "myFolder";
window.resolveLocalFileSystemURL(file, resolveFileSystemSuccess, resolveFileSystemError);
function resolveFileSystemSuccess(fileEntry) {
console.log("resolveLocalFileSystemURL returned: ", fileEntry.toURL());
fileEntry.file(function(filee) {
mimeType = filee.type;
getFileSuccess(fileEntry, mimeType);
}, function() {
});
}
function resolveFileSystemError() {
console.log("resolveFileSystemError: FAIL");
console.log(arguments);
alert("FAIL");
}
function getFileSuccess(fileEntry, mimeType) {
var targetFileName = "myImage.JPG";
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem) {
fileSystem.root.getDirectory(targetDirectory, {create: true, exclusive: false}, function(dirTarget) {
fileEntry.copyTo(dirTarget, targetFileName, function(entry) {
console.log("copyTo returned: ", entry.toURL());
// I have replaced the localstorage handling with this code
// addFileToLocalStorage(entry);
var img = document.querySelector('.myMimeTypeTag');
img.setAttribute('src', entry.toNativeURL());
}, function() {
});
});
}, resolveFileSystemError);
}
};
var onSuccess = function(imageData) {
console.log("getPicture returned: ", imageData);
StoreFile(imageData);
};
var onFail = function() {
console.log("getPicture FAIL");
console.log(arguments);
alert("FAIL");
};
ev.preventDefault();
ev.stopPropagation();
navigator.camera.getPicture(onSuccess, onFail, {
destinationType: Camera.DestinationType.NATIVE_URI,
sourceType : Camera.PictureSourceType.PHOTOLIBRARY,
mediaType: Camera.MediaType.ALLMEDIA
});
}
};
When I run this, I can pick an image from the media library, and it successfully displays it in the page, with the image src set to the URL of the copied image file. If I connect Safari dev tools to the iPad, I see this console output:
[Log] getPicture returned: assets-library://asset/asset.JPG?id=F9B8C942-367E-433A-9A71-40C5F2806A74&ext=JPG (index.js, line 49)
[Log] resolveLocalFileSystemURL returned: cdvfile://localhost/assets-library/asset/asset.JPG?id=F9B8C942-367E-433A-9A71-40C5F2806A74&ext=JPG (index.js, line 18)
[Log] copyTo returned: file:///var/mobile/Applications/9C838867-30BE-4703-945F-C9DD48AB4D64/Documents/myFolder/myImage.JPG (index.js, line 36)
[Log] DEPRECATED: Update your code to use 'toURL' (Entry.js, line 202)
This shows the camera and file plugins going through three different types of URL:
Camera returns an assets-library:// URL, with query parameters to identify the asset
calling resolveLocalFileSystemURL on that turns it into a cdvfile:// URL, also with query paramaters, as an internal Cordova representation.
After being copied, File returns a new file:/// URL showing the image's new place on the filesystem. This URL has no query parameters. (Calling toNativeURL() on this entry returns the same URL now, as of File 1.1.0)
This final URL is usable by iOS as an image source, and so that's what gets assigned to the <img> element.
The problem was, that the new file-plugin has to be case-sensitve.
I created a folder with capital letters and refered the copy-instruction to a folder with lowercase letters. The point is that android is case insensitive and ios is not.
This came out with the new file-plugin where the output was case sensitive.
I'm using Phonegap 3.3.0, earlier i used 2.5.0 where entry.fullPath will give the Device full path.
These paths would typically look like
/var/mobile/Applications/<application UUID>/Documents/path/to/file (iOS)
/storage/emulated/0/path/to/file (Android)
since that method is deprecated am using entry.toURL() method to get the path.This method will now return filesystem URLs of the form
cdvfile://localhost/persistent/path/to/file
In My application, am passing the URL to Native function and from native am opening a file. But If I pass the path to Native, iOS could not able to detect the file. The same If i hardcode the Absolute path, application detects the file.
How to use the fileSystem URL to access the file in native or any other method to get the device absolute path ?
Thanks in advance.
The toURL() method or the nativeURL attribute should return the result wanted:
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
console.log("fileSystem.root.toURL()="+fileSystem.root.toURL());
console.log("fileSystem.root.toInternalURL()="+fileSystem.root.toInternalURL());
console.log("fileSystem.root.nativeURL="+fileSystem.root.nativeURL);
}, function(){
alert("fails!");
});
Using cordova 3.5, the output in iPad simulator is:
fileSystem.root.toURL()=file:///Users/myuser/Library/Application%20Support/iPhone%20Simulator/7.1/Applications/1717CB5F-4032-45C7-8CA2-342502447F36/Documents/
fileSystem.root.toInternalURL()=cdvfile://localhost/persistent/
fileSystem.root.nativeURL=file:///Users/myuser/Library/Application%20Support/iPhone%20Simulator/7.1/Applications/1717CB5F-4032-45C7-8CA2-342502447F36/Documents/
...and in Android simulator (Genymotion) is:
fileSystem.root.toURL()=file:///storage/emulated/0/
fileSystem.root.toInternalURL()=cdvfile://localhost/persistent/
fileSystem.root.nativeURL=file:///storage/emulated/0/
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log("device is ready");
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
}
function fail() {
console.log("failed to get filesystem");
}
function gotFS(fileSystem) {
console.log("got filesystem");
// save the file system for later access
console.log(fileSystem.root.fullPath);
window.rootFS = fileSystem.root;
}
function downloadImage(url, fileName){
var ft = new FileTransfer();
ft.download(
url,
window.rootFS.fullPath + "/" + fileName,
function(entry) {
console.log("download complete: " + entry.fullPath);
},
function(error) {
console.log("download error" + error.code);
}
);
}
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
function gotFS(fileSystem) {
alert("entered gotFS: " + fileSystem.root.toURL);
}
I am downloading a file to the local file system. I can successfully create the empty file via fileSystem.root.getFile but fileTransfer.download fails with FILE_NOT_FOUND_ERR even though it's using the same path.
The problem is that my file is being created at //sdcard/MyDir/test.pdf (I confirmed using adb shell) but the fileEntry returned a path without sdcard: //MyDir/test.pdf. fileTransfer.download fails with this path. It also fails with the relative path MyDir/test.pdf.
If I hardcode the full path with 'sdcard' in it I can avoid the FILE_NOT_FOUND_ERR (specifically, in FileTransfer.java the resourceApi.mapUriToFile call succeeds) but then I get a CONNECTION_ERR and the console shows "File plugin cannot represent download path". (In FileTransfer.java, the filePlugin.getEntryForFile call returns null. I assume it doesn't like 'sdcard' in the path.)
Is there a better way to specify the target path in fileTransfer.download?
var downloadUrl = "http://mysite/test.pdf";
var relativeFilePath = "MyDir/test.pdf"; // using an absolute path also does not work
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) {
fileSystem.root.getFile(relativeFilePath, { create: true }, function (fileEntry) {
console.log(fileEntry.fullPath); // outputs: "//MyDir/test.pdf"
var fileTransfer = new FileTransfer();
fileTransfer.download(
downloadUrl,
/********************************************************/
/* THE PROBLEM IS HERE */
/* These paths fail with FILE_NOT_FOUND_ERR */
//fileEntry.fullPath, // this path fails. it's "//MyDir/test.pdf"
//relativeFilePath, // this path fails. it's "MyDir/test.pdf"
/* This path gets past the FILE_NOT_FOUND_ERR but generates a CONNECTION_ERR */
"//sdcard/MyDir/test.pdf"
/********************************************************/
function (entry) {
console.log("Success");
},
function (error) {
console.log("Error during download. Code = " + error.code);
}
);
});
});
I'm using the Android SDK emulator if that makes a difference.
I was able to resolve this by using a URI for the file's path. (I also removed the unnecessary call to fileSystem.root.getFile per #Regent's comment.)
var downloadUrl = "http://mysite/test.pdf";
var relativeFilePath = "MyDir/test.pdf"; // using an absolute path also does not work
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) {
var fileTransfer = new FileTransfer();
fileTransfer.download(
downloadUrl,
// The correct path!
fileSystem.root.toURL() + '/' + relativeFilePath,
function (entry) {
console.log("Success");
},
function (error) {
console.log("Error during download. Code = " + error.code);
}
);
});
Hi im currently trying to create an gallery app with phonegap build, but i cant read files from the local storage. I`m using this function:
function listDir(directoryEntry){
var directoryReader = directoryEntry.createReader();
directoryReader.readEntries(function(entries){ // success get files and folders
for(var i=0; i<entries.length; ++i){
alert(entries[i].name) // this is just for checking purposes, no matter what i put here it wont fire
}
}, function(error){ // error get files and folders
alert(error.code);
});
}
function getFileSystem(){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){ // success get file system
var sdcard = fileSystem.root;
sdcard.getDirectory('dcim',{create:false}, function(dirEntry){
listDir(dirEntry);
}, function(error){
alert(error.code);
})
}, function(evt){ // error get file system
console.log(evt.target.error.code);
});
}
getFileSystem();
The listDir function wont even fire (the error function wont too). I have tried to add an "OnDeviceReady" listener to call the getFileSystem() function but it wont work too, plus i have tried toons of ways, even using the official phonegap docs, but it cant read my directory. Anyone know how to do this (im currently using android)? Thanks in advance.
You need remember that the cordova api is async.
This code read the list of files in my app external storage directory:
function getFilesList(callback) {
console.log('getFilesList');
var fileList = [];
function onDirResolved(dir) {
var reader =dir.createReader();
reader.readEntries(function(entries) {
console.log('readEntries');
for (var i=0; i<entries.length; i++) {
if (entries[i].name.indexOf(".fototoon") != -1) {
fileList.push(entries[i].fullPath);
};
};
console.log('fileList ' + fileList);
callback(fileList);
}, errorHandler);
};
function onFsResolved(fs) {
window.resolveLocalFileSystemURL(
cordova.file.externalApplicationStorageDirectory,
onDirResolved, errorHandler);
};
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
onFsResolved, errorHandler);
};
The callback function will receive the list of files read.