My issue is very similar to this question Cordova - Reading Large Image corrupts image
but I haven't had any success with the solution. I'm also attempting to use the image picker plugin for Cordova
Cordova 7.0.1
Android 6.2.3
SapUI5 1.44.17
fileToBase64: function(fileUrl, callback) {
window.resolveLocalFileSystemURL(fileUrl, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onload = function(evt) {
callback(evt.target.result);
};
reader.readAsDataURL(file);
}, function(error) {
console.log("File entry error " + error);
});
}, function(error) {
console.log("Resolve system file error " + error);
});
},
The result returned is an incomplete base64 string. Here's the loop through my images
handleImagePicker: function(oEvent) {
var _this = this;
window.imagePicker.getPictures(
function(results) {
var numOfImagesLeftToProcess = results.length;
if(numOfImagesLeftToProcess)
_this.appBusy(true);
for (var i = 0; i < results.length; i++) {
_this.fileToBase64(results[i], function(base64Str) {
console.log(base64Str);
numOfImagesLeftToProcess--;
if(numOfImagesLeftToProcess == 0) {
_this.appBusy(false);
}
});
}
}, function (error) {
console.log('Error: ' + error);
},
{
//outputType: imagePicker.OutputType.BASE64_STRING // default .FILE_URI
}
);
},
Not sure if the callback is being called prematurely. I'm able to view the images fine on the device and I've tested this code on two different devices with two different version of Android.
Any help would be appreciated.
Related
I am creating an app with cordova for android using plugin file-transfer. The download is going to a certain folder but I can't read the file despite indicating the correct path follows the code
var uri = encodeURI(mypage);
var fileURL = cordova.file.externalDataDirectory + "teste.ogg";
fileTransfer.download(
uri, fileURL, function(entry) {
console.log("download complete: " + entry.toURL());
$("#audio-teste").attr('src',fileURL)
/*--codigo de teste--*/
var meuFile = cordova.file.externalDataDirectory;
resolveLocalFileSystemURL(meuFile, function(entry) {
var readerN = fileSystem.createReader();
readerN.readEntries(
function (entry) {
var arrayN =[];
for(var i="0"; i < entry.length; ++i){
var entradaN = entry[i].name;
arrayN.push(entradaN);
//console.log(array);
console.log('teste aq' + arrayN);
}
}
)
//console.log(entry);
});
/*----*/
},
function(error) {
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("download error code" + error.code);
},
false, {
headers: {
"Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
}
}
);
/*----*/
The cordova plugin cordova-plugin-file-transfer is due to be deprecated and its latest npm version fails on iOS.
Therefore these two working functions are purely based on vanilla JS, and thus no need to use extra plugins, besides the standard plugin cordova-plugin-file. Therefore this is compatible with any platform.
https://gist.github.com/jfoclpf/07e52f6bdf9c967449c4bc06af44c94a
I paste here for your convenience:
// for different types of cordovaFileSystem check here:
// https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/#where-to-store-files
// or simply type in the console `console.log(cordova.file)`
function downloadFileToDevice (fileurl, filename, cordovaFileSystem, callback) {
var onerror = (err) => {
console.error(`Error downloading from ${fileurl} to cordovaFileSystem ${cordovaFileSystem}`,
err, new Error(err))
if (typeof callback === 'function') { callback(Error(err)) }
}
var blob = null
var xhr = new XMLHttpRequest()
xhr.open('GET', fileurl)
xhr.responseType = 'blob' // force the HTTP response, response-type header to be blob
xhr.onload = () => {
blob = xhr.response // xhr.response is now a blob object
var DataBlob = blob
window.resolveLocalFileSystemURL(cordovaFileSystem, (dirEntry) => {
const sanitizedFilename = filename.replace(/[^a-z0-9\.]/gi, '_').toLowerCase() // sanitize filename
dirEntry.getFile(sanitizedFilename, { create: true }, (file) => {
file.createWriter((fileWriter) => {
fileWriter.write(DataBlob)
if (typeof callback === 'function') { callback(null, cordovaFileSystem + sanitizedFilename) }
}, (err) => { console.error('Error on file.createWriter'); onerror(err) })
}, (err) => { console.error('Error on dirEntry.getFile'); onerror(err) })
}, (err) => { console.error('Error on resolveLocalFileSystemURL'); onerror(err) })
}
xhr.onerror = (err) => { console.error('Error on XMLHttpRequest'); onerror(err) }
xhr.send()
}
An example for downloading a file
downloadFileToDevice('https://example.com/img.jpg',
'myImg.jpg',
cordova.file.cacheDirectory,
(err, localFilePath) => {
if (err) {
console.error('An error occured downloading file:', err)
} else {
console.log('Download file with success: ' + localFilePath)
}
})
Can you try with this? I tried and it works like a charm
I have the error like in question, when I'm trying to design my application to call native.camera, I see my console in ionic 3 project, I saw this error :
Native : tried calling Camera.getPicture, but Cordova is not available. Make sure to include cordova.js or run in a device / simulator.
Here is the code that I used to called native camera.
This is the code in my problem.html
<button class="logoCamera" ion-button (click)="presentActionSheet()">
<ion-icon name="camera" ></ion-icon>
This is the code in my problem.ts
import { File } from '#ionic-native/file';
import { Transfer, TransferObject} from '#ionic-native/transfer';
import { FilePath } from '#ionic-native/file-path';
import { Camera } from '#ionic-native/camera';
public presentActionSheet(){
let actionSheet = this.actionSheetCtrl.create({
title: 'Select Image',
buttons: [
{
text: 'Load from Library',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY);
}
},
{
text: 'Use Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA);
}
},
{
text: 'Cancel',
role: 'cancel'
}
]
});
actionSheet.present();
}
public takePicture(sourceType){
//Create option for the Camera dialog
var options = {
quality: 100,
sourceType : sourceType,
saveToPhotoAlbum: false,
correctOrientation: true
};
//Get the data of an image
this.camera.getPicture(options).then((imagePath) => {
//special handling for android lib
if(this.platform.is('android') && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) {
this.filePath.resolveNativePath(imagePath)
.then(filePath => {
let correctPath = filePath.substr(0, filePath.lastIndexOf('/') + 1 );
let currentName = imagePath.substring(imagePath.lastIndexOf('/') + 1, imagePath.lastIndexOf('?'));
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
});
} else {
var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/')+ 1);
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
}
}, (err) => {
this.presentToast('Error while selecting Image.');
});
}
//Create a new name for image
private createFileName() {
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
return newFileName;
}
//copy image to local folder
private copyFileToLocalDir(namePath, currentName, newFileName) {
this.file.copyFile(namePath, currentName, cordova.file.dataDirectory, newFileName).then(success => {
this.lastImage = newFileName;
}, error => {
this.presentToast('Error while storing file.');
});
}
private presentToast(text) {
let toast = this.toastCtrl.create({
message: text,
duration: 3000,
position: 'middle'
});
toast.present();
}
public pathForImage(img){
if (img === null) {
return '';
} else {
return cordova.file.dataDirectory + img;
}
}
public uploadImage() {
//destination URL
var url = "";
//file to upload
var targetPath = this.pathForImage(this.lastImage);
//file name only
var filename = this.lastImage;
var options = {
fileKey: "file",
fileName: filename,
chunkedMode: false,
mimeType: "multipart/form-data",
params: {'fileName': filename}
};
const fileTransfer: TransferObject = this.transfer.create();
this.loading = this.loadingCtrl.create({
content: 'Uploading...',
});
this.loading.present();
//use FileTransfer to upload image
fileTransfer.upload(targetPath, url, options).then(data => {
this.loading.dismissAll()
this.presentToast('Image successful uploaded.');
}, err => {
this.loading.dismissAll()
this.presentToast('Error while uploading file.');
});
}
When I run ionic serve, everything is smooth, no error, no nothing.
But when I click my button to access natve camera, the error shows, please help me figure out the problem, I check a lot of web, and none of it solve my question.
After I try run ionic cordova run ios --simulator, there are error coming out, but I am pretty sure that this error does not exist before I run this command.
May I know how to solve this problem ??
The error message is pretty accurate here:
Native : tried calling Camera.getPicture, but Cordova is not available. Make sure to include cordova.js or run in a device / simulator.
Running ionic serve does not include cordova.js nor does it run your application in a simulator or on a device which is why you get the error. You can fix it either by running your application on the device or simulator:
ionic cordova run android/ios --device/--simulator
Or by adding the browser platform:
cordova platform add browser
And running the browser platform:
ionic cordova run browser
Am trying to user the $cordovaFileTransfer plugin from ngCordovato upload images in my ionic app.
However the images, never seem to upload. The app is running on my android phone and am debugging with chrome remote inspector, the network tab does not show any request for the upload.
This method gets images from the device
$scope.getImages = function() {
var options = {
maximumImagesCount: 2,
width: 800,
height: 800,
quality: 80
};
$cordovaImagePicker.getPictures(options)
.then(function (results) {
for (var i = 0; i < results.length; i++) {
$scope.queue.push({
filepath: results[i],
progress: 0.00
});
}
$scope.$emit('process:queue');
}, function(error) {
// error getting photos
});
};
And am handling the 'process:queue' event with this method
$scope.startUploadQueue = function() {
var server = encodeURI(serviceUrl());
var options = {
fileKey: "image",
httpMethod: 'PUT',
headers: {
"Authorization": "Bearer "+$user.getToken()
}
};
angular.forEach($scope.queue, function(item) {
$cordovaFileTransfer.upload(server, item.filepath, options, true)
.then(function (result) {
console.log(result);
$scope.media.push(result.data);
}, function (error) {
}, function (progress) {
item.progress = (progress.loaded / progress.total) * 100;
});
});
};
Am doing something incorrectly?. Any help will be appreciated
Let's say I have a API that stores some .mp3 music.
The sample link here:
https://118.69.201.34:8882/api/ApiMusic/Download?songId=2000
Now I want to write an API calling function in Angularjs to download the music to my Android devices with the song's Id number as in the link.
How can I do that? Please help :(
You can use the ngCordova FileTransfer library here: http://ngcordova.com/docs/plugins/fileTransfer/
Here's example code from that page, tweaked to your example URL:
document.addEventListener('deviceready', function () {
var fileid = "2000";
var url = "https://118.69.201.34:8882/api/ApiMusic/Download?songId=" + fileid;
var targetPath = cordova.file.documentsDirectory + fileid + ".mp3";
var trustHosts = true
var options = {};
$cordovaFileTransfer.download(url, targetPath, options, trustHosts)
.then(function(result) {
// Success!
}, function(err) {
// Error
}, function (progress) {
$timeout(function () {
$scope.downloadProgress = (progress.loaded / progress.total) * 100;
})
});
}, false);
I did it finally, here is my code. Just share for those who want to refer to this issue in the future. Thanks you guys for your answers
$scope.download = function(songId, songName) {
$ionicLoading.show({
template: 'Downloading...'
});
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
fs.root.getDirectory(
"fMusic",
{
create: true
},
function (dirEntry) {
dirEntry.getFile(
songName + ".mp3",
{
create: true,
exclusive: false
},
function gotFileEntry(fe) {
var p = fe.toURL();
fe.remove();
ft = new FileTransfer();
ft.download(
encodeURI(APIUrl + songId),
p,
function (entry) {
$ionicLoading.hide();
$scope.mp3File = entry.toURL();
},
function (error) {
$ionicLoading.hide();
alert("Download Error Source --> " + error.source);
},
false,
null
);
},
function () {
$ionicLoading.hide();
console.log("Get the file failed");
}
);
}
);
},
function () {
$ionicLoading.hide();
console.log("Request for filesystem failed");
});
}
I'm developing a cordova/phonegap app. Right now, I'm testing the app on Android.
If I include files (audio, video, ...) by default, I can access to that files indicating the "url" like audio/filesong.mp3 or video/filevideo.mp4.
But if I download files with the next code:
function downloadFile() {
var fileTransfer = new FileTransfer();
var uri = encodeURI("UrlOfTheFile");
var fileURL = "cdvfile://localhost/persistent/appcustomstorage/";
fileTransfer.download(
uri, fileURL + "file.extension", function(entry) {
console.log("download complete: " + entry.toURL());
}, function(error) {
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("upload error code" + error.code);
}, false, {
headers: {
"Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
}
});
}
I download the file in StorageRoot/appcustomstorage/file.extension
It is possible to store the file in the app package, i.e., in, for example, Android/data/com.example.app??
Or a method to get the Android/data/com.example.app url and then add the necessary folder?
Solution:
In this case I find all mp3 in the device. It works on Nexus 4.
index.html
<ul data-role="listview" data-inset="true" id="ulsongs">
</ul>
index JavaScript:
document.addEventListener("deviceready", onDeviceReady, false);
// device APIs are available
function onDeviceReady() {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
}
function gotFS(fileSystem) {
FileSystem = fileSystem;
// Call to start to find all files
getFileSystem();
}
storageScript:
var FileSystem = null;
var AudioExtensions = [ '.mp3' ];// , '.wav', '.m4a' ];
var my_media = null;
function listDir(directoryEntry, level) {
if (level === undefined)
level = 0;
var directoryReader = directoryEntry.createReader();
directoryReader.readEntries(function(entries) { // success get files and
// folders
for ( var i = 0; i < entries.length; ++i) {
if (entries[i].name === '.')
continue;
if (entries[i].isDirectory) {
FileSystem.root.getDirectory(entries[i].fullPath.slice(1,
entries[i].fullPath.length), {
create : false
}, function(dirEntry) {
listDir(dirEntry, level + 1);
}, function(error) {
console.log('ERROR');
alert(error.code);
});
}
if (entries[i].isFile) {
var extension;
extension = entries[i].name.substr(entries[i].name
.lastIndexOf('.'));
if (entries[i].isFile === true
&& $.inArray(extension, AudioExtensions) >= 0) {
// Add a song to the list
$("#ulsongs").append(
"<li id='" + entries[i].fullPath + "'"
+ " data-icon=\"audio\"><a>"
+ entries[i].name + "</a></li>");
$('#ulsongs').listview('refresh');
}
}
}
}, function(error) { // error get files and folders
alert('Error. Code: ' + error.code);
});
// Action listener
$('#ulsongs li').click(function(e) {
pathsong = $(this).attr('id');
console.log('item clicked. Path: ' + pathsong);
if (typeof (pathsong) != 'undefined' && pathsong != null) {
// Stop previous song
if ((audio_status != null) && (audio_status == 2)) {
console.log('STOP AUDIO');
my_media.stop();
my_media.release();
}
// Play the audio file at url
my_media = new Media(pathsong,
// success callback
function() {
console.log("playAudio():Audio Success");
},
// error callback
function(err) {
console.log("playAudio():Audio Error: " + err);
}, status);
// Play audio
my_media.play();
}
});
}
var audio_status = null;
function status(stat) {
audio_status = stat;
}
/**
*
*/
function getFileSystem() {
console.log('entra getFileSystem');
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
function(fileSystem) { // success get file system
var sdcard = fileSystem.root;
sdcard.getDirectory('', {
create : false
}, function(dirEntry) {
listDir(dirEntry);
}, function(error) {
alert(error.code);
})
}, function(evt) { // error get file system
console
.log('ERROR GETTING FILE SYSTEM'
+ evt.target.error.code);
});
}
I create a list of mp3.
I use jQuery and jQueryMobile
Edit
The process may need a bit of time. It is recommended to show a loading popup.