In Nativescript the result from imageSource.fromUrl is coming as {"android":{}} - android

While following the link https://docs.nativescript.org/cookbook/image-source, in the console, am getting the result as {"android":{}} in my android device.
Below is my js code
var createViewModel = require("./main-view-model").createViewModel;
var imageSource = require("image-source");
function onNavigatingTo(args) {
var page = args.object;
imageSource.fromUrl("https://www.google.com/images/errors/logo_sm_2.png")
.then(function (res) {
console.log("Image successfully loaded");
console.log(JSON.stringify(res));
}, function (error) {
//console.log("Error loading image: " + error);
});
page.bindingContext = createViewModel();
}
exports.onNavigatingTo = onNavigatingTo;
Should we do anything more to get the image. Apologies if the question is too basic, just getting to know Nativescript

There are several approaches to load an image from URL - you can create an instance of image via code behind and attach the imageSource to its src and then dynamically added the image to a page container element (e.g. grid-layout, stack-layout or else)
Or, you can use data binding and once you get the imaageSource to bind it with your view model.
example given:
page.js
var observable_1 = require('data/observable');
var imageSource = require("image-source");
function navigatingTo(args) {
var page = args.object;
var viewModel = new observable_1.Observable();
imageSource.fromUrl("https://www.google.com/images/errors/logo_sm_2.png")
.then(function (res) {
viewModel.set("myUrl", res);
}, function (error) {
//console.log("Error loading image: " + error);
});
page.bindingContext = viewModel;
}
exports.navigatingTo = navigatingTo;
page.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo">
<StackLayout>
<Label text="ImageSource fromUrl example" class="title"/>
<Image src="{{ myUrl }}" stretch="none" />
</StackLayout>
</Page>

Related

Display image from internal storage in Vue + Cordova

I am trying to display an image from download folder.
imagePath: file:///storage/emulated/0/Download/sample.png
Set Image URL:
window.resolveLocalFileSystemURL(this.imagePath, function success(fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function() {
if (this.result) {
var blob = new Blob([new Uint8Array(this.result)], { type: "image/png" });
this.imgUrl = window.URL.createObjectURL(blob);
}
};
reader.readAsArrayBuffer(file);
});
}, function (err) {
this.info = 'An error was found: '+ err;
});
Display it on UI:
<img class="img-fluid" src="{{imgUrl}}" />
But code is not reaching inside onloadend callback.

Uploading to Firebase Storage using uri from GIF [duplicate]

I'm wondering how to upload file onto Firebase's storage via URL instead of input (for example). I'm scrapping images from a website and retrieving their URLS. I want to pass those URLS through a foreach statement and upload them to Firebase's storage. Right now, I have the firebase upload-via-input working with this code:
var auth = firebase.auth();
var storageRef = firebase.storage().ref();
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
var file = evt.target.files[0];
var metadata = {
'contentType': file.type
};
// Push to child path.
var uploadTask = storageRef.child('images/' + file.name).put(file, metadata);
// Listen for errors and completion of the upload.
// [START oncomplete]
uploadTask.on('state_changed', null, function(error) {
// [START onfailure]
console.error('Upload failed:', error);
// [END onfailure]
}, function() {
console.log('Uploaded',uploadTask.snapshot.totalBytes,'bytes.');
console.log(uploadTask.snapshot.metadata);
var url = uploadTask.snapshot.metadata.downloadURLs[0];
console.log('File available at', url);
// [START_EXCLUDE]
document.getElementById('linkbox').innerHTML = 'Click For File';}
Question what do I replace
var file = evt.target.files[0];
with to make it work with external URL instead of a manual upload process?
var file = "http://i.imgur.com/eECefMJ.jpg"; doesn't work!
There's no need to use Firebase Storage if all you're doing is saving a url path. Firebase Storage is for physical files, while the Firebase Realtime Database could be used for structured data.
Example . once you get the image url from the external site this is all you will need :
var externalImageUrl = 'https://foo.com/images/image.png';
then you would store this in your json structured database:
databaseReference.child('whatever').set(externalImageUrl);
OR
If you want to actually download the physical images straight from external site to storage then this will require making an http request and receiving a blob response or probably may require a server side language ..
Javascript Solution : How to save a file from a url with javascript
PHP Solution : Saving image from PHP URL
This answer is similar to #HalesEnchanted's answer but with less code. In this case it's done with a Cloud Function but I assume the same can be done from the front end. Notice too how createWriteStream() has an options parameter similar to bucket.upload().
const fetch = require("node-fetch");
const bucket = admin.storage().bucket('my-bucket');
const file = bucket.file('path/to/image.jpg');
fetch('https://example.com/image.jpg').then((res: any) => {
const contentType = res.headers.get('content-type');
const writeStream = file.createWriteStream({
metadata: {
contentType,
metadata: {
myValue: 123
}
}
});
res.body.pipe(writeStream);
});
Javascript solution to this using fetch command.
var remoteimageurl = "https://example.com/images/photo.jpg"
var filename = "images/photo.jpg"
fetch(remoteimageurl).then(res => {
return res.blob();
}).then(blob => {
//uploading blob to firebase storage
firebase.storage().ref().child(filename).put(blob).then(function(snapshot) {
return snapshot.ref.getDownloadURL()
}).then(url => {
console.log("Firebase storage image uploaded : ", url);
})
}).catch(error => {
console.error(error);
});
Hopefully this helps somebody else :)
// Download a file form a url.
function saveFile(url) {
// Get file name from url.
var filename = url.substring(url.lastIndexOf("/") + 1).split("?")[0];
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", transferComplete);
xhr.addEventListener("error", transferFailed);
xhr.addEventListener("abort", transferCanceled);
xhr.responseType = 'blob';
xhr.onload = function() {
var a = document.createElement('a');
a.href = window.URL.createObjectURL(xhr.response); // xhr.response is a blob
a.download = filename; // Set the file name.
a.style.display = 'none';
document.body.appendChild(a);
a.click();
delete a;
if (this.status === 200) {
// `blob` response
console.log(this.response);
var reader = new FileReader();
reader.onload = function(e) {
var auth = firebase.auth();
var storageRef = firebase.storage().ref();
var metadata = {
'contentType': 'image/jpeg'
};
var file = e.target.result;
var base64result = reader.result.split(',')[1];
var blob = b64toBlob(base64result);
console.log(blob);
var uploadTask = storageRef.child('images/' + filename).put(blob, metadata);
uploadTask.on('state_changed', null, function(error) {
// [START onfailure]
console.error('Upload failed:', error);
// [END onfailure]
}, function() {
console.log('Uploaded',uploadTask.snapshot.totalBytes,'bytes.');
console.log(uploadTask.snapshot.metadata);
var download = uploadTask.snapshot.metadata.downloadURLs[0];
console.log('File available at', download);
// [START_EXCLUDE]
document.getElementById('linkbox').innerHTML = 'Click For File';
// [END_EXCLUDE]
});
// `data-uri`
};
reader.readAsDataURL(this.response);
};
};
xhr.open('GET', url);
xhr.send();
}
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {type: contentType});
return blob;
}
function transferComplete(evt) {
window.onload = function() {
// Sign the user in anonymously since accessing Storage requires the user to be authorized.
auth.signInAnonymously().then(function(user) {
console.log('Anonymous Sign In Success', user);
document.getElementById('file').disabled = false;
}).catch(function(error) {
console.error('Anonymous Sign In Error', error);
});
}
}
function transferFailed(evt) {
console.log("An error occurred while transferring the file.");
}
function transferCanceled(evt) {
console.log("The transfer has been canceled by the user.");
}

Nativescript pass fetch response data to a level text

In my nativescript app,I am trying to bulid a level from the response of my API through fetch module.But I don't know how to bind the context in obserable.How to bind the context when page loaded.Here is my code-
Response from my api-
[{"value":"12000$"}]
I want to get that value from response in {{price}} in my level text.
view file-
<Page loaded="loaded">
<GridLayout>
<Label text="{{ price }}" horizontalAlignment="left" verticalAlignment="center" tap="model" />
</GridLayout>
</Page>
Fetch request-
fetch("http://10.0.2.2:8000/get_model", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
brand: data,
})
}).then(r => { return r.json(); }).then(function (data) {
console.log(data[0].value);
//How to push the value in obserable?
}, function (e) {
console.log("Error occurred " + e);
});
var observableModule = require("data/observable");
var viewModel = new observableModule.Observable();
viewModel.set("ip", "none"); // initial value
function onLoaded(args) {
var page = args.object;
page.bindingContext = viewModel;
fetch("http://httpbin.org/ip", {
method: "GET",
headers: { "Content-Type": "application/json" }
})
.then(function (res) { return res.json(); })
.then(function (data) {
console.log(data.origin); // make sure you are getting the value
viewModel.set("ip", data.origin); // binding to "price"
})
}
exports.onLoaded = onLoaded;
and in your page.xml use the loaded event
<Page loaded="onLoaded">
<Label text="{{ ip }}"/>
</page>
In this case, httpbin.org is returning the data in format
{"origin" : "some-ip-address-here"}

Video intend can't be used on android (Appcelerator)

Video recording works fine on IOS, Android can't catch data.
problem seems to be the
var curActivity = Ti.Android.currentActivity;
curActivity.startActivityForResult(intent, function(e) { ....
there was some advise to use win.getActivity() instead, but i have no variable I can use.
$.cameraWin
this
is not working.
Any advise?
index.xml
<Alloy>
<TabGroup>
<Tab id="websiteTab" title="Web">
<Require backgroundColor="black" color="white" id="webTab" src="website" type="view"/>
</Tab>
<Tab id="cameraTab" title="Camera">
<Require backgroundColor="black" color="white" id="cameraTab" src="camera" type="view"/>
</Tab>
<Tab backgroundColor="black" color="white" id="loginTab" title="Login">
<Require backgroundColor="black" color="white" id="loginTab" src="login" type="view"/>
</Tab>
<Tab backgroundColor="black" color="white" id="registerTab" title="Map">
<Require backgroundColor="black" color="white" id="registerTab" src="register" type="view"/>
</Tab>
</TabGroup>
</Alloy>
camera.xml
<Alloy>
<Window id="cameraWin">
<Label id="Label_1" text="Gib Deinem Video einen Namen"/>
<TextField id="TextField_1"/>
<Button id="Button_1" onClick="doClick" title="Aufnehmen und hochladen"/>
<ProgressBar id="ProgressBar_1"/>
<Picker id="Picker_1" selectionIndicator="true" useSpinner="true">
<PickerColumn id="PickerColumn_1" title="Kategorie">
<Row title="Fußball"/>
<Row title="Handball"/>
<Row title="Schifahren"/>
<Row title="Einkehren"/>
</PickerColumn>
</Picker>
<Label id="Label_2" text="Veranstaltung/Kategorie"/>
</Window>
</Alloy>
camera.js
function doClick(e) {
Ti.API.info(Titanium.Platform.osname);
if (Titanium.Platform.osname == 'iphone') {
//record for iphone
$.ProgressBar_1.value = 0;
$.ProgressBar_1.message = "Hochladen"
Titanium.Media.showCamera({
success: function(event) {
var video = event.media;
movieFile = Titanium.Filesystem.getFile(
Titanium.Filesystem.applicationDataDirectory,
'mymovie.mov');
movieFile.write(video);
videoFile = movieFile.nativePath;
var xhr = Titanium.Network.createHTTPClient();
xhr.onload = function(e) {
Ti.UI.createAlertDialog({
title: 'Success',
message: 'status code ' + this.status
}).show();
Ti.API.info(this.responseText);
};
xhr.open('POST', 'XXXXXXXXXX');
xhr.send({
Filedata: event.media,
/* event.media holds blob from gallery */
title: $.TextField_1.value,
catid: 17
});
// onsendstream called repeatedly, use the progress property to
// update the progress bar
xhr.onsendstream = function(e) {
$.ProgressBar_1.value = e.progress * 100;
$.ProgressBar_1.message = "Hochladen von Video";
Ti.API.info('ONSENDSTREAM - PROGRESS: ' + e.progress * 100);
};
},
cancel: function() {},
error: function(error) {
// create alert
var a =
Titanium.UI.createAlertDialog({
title: 'Video'
});
// set message
if (error.code == Titanium.Media.NO_VIDEO) {
a.setMessage('Device does not have video recording
capabilities ');
} else {
a.setMessage('Unexpected error: ' + error.code);
}
// show alert
a.show();
},
mediaTypes: Titanium.Media.MEDIA_TYPE_VIDEO,
videoMaximumDuration: 120000,
videoQuality: Titanium.Media.QUALITY_MEDIUM
});
} else {
var intent = Titanium.Android.createIntent({
action: 'android.media.action.VIDEO_CAPTURE'
});
Ti.API.info('Intent created. ..');
var curActivity = Ti.Android.currentActivity;
curActivity.startActivityForResult(intent, function(e) {
if (e.error) {
Ti.UI.createNotification({
duration: Ti.UI.NOTIFICATION_DURATION_LONG,
message: 'Error: ' + e.error
}).show();
} else {
Ti.API.info('Drinnen');
Ti.Api.info(e.resultCode);
if (e.resultCode === Titanium.Android.RESULT_OK) {
Ti.API.info('Drinnen');
videoFile = e.intent.data;
var source = Ti.Filesystem.getFile(videoFile);
var movieFile =
Titanium.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'mymovie.3gp');
Ti.API.info('Sichert');
source.copy(movieFile.nativePath);
Titanium.Media.saveToPhotoGallery(movieFile);
var xhr = Titanium.Network.createHTTPClient();
xhr.onload = function(e) {
Ti.UI.createAlertDialog({
title: 'Success',
message: 'status code ' + this.status
}).show();
Ti.API.info(this.responseText);
};
var fileContent = movieFile.read();
Ti.API.info('Video rauf');
xhr.open('POST', 'XXXXXXXXXXX'
Filedata: fileContent,
/* event.media holds blob from gallery */
title: $.TextField_1.value,
catid: 17
});
// onsendstream called repeatedly, use the progress property to
// update the progress bar
xhr.onsendstream = function(e) {
$.ProgressBar_1.value = e.progress * 100;
$.ProgressBar_1.message = "Hochladen von Video";
Ti.API.info('ONSENDSTREAM - PROGRESS: ' + e.progress * 100);
};
} else {
Ti.UI.createNotification({
duration: Ti.UI.NOTIFICATION_DURATION_LONG,
message: 'Canceled/Error? Result code: ' +
e.resultCode
}).show();
}
}
});
}
};
Alternative way:
I'm currently working on getting video recording to android in the normal SDK:
https://github.com/appcelerator/titanium_mobile/pull/7929
It is already working (Samsung Galaxy S6 has a problem a the moment I need to fix: you need to rotate the phone ones to have the proper preview size) but needs some more testing. With this you can use the back/front camera to record video the same way as on iOS.
But it still needs some time to be in the GA version. You can always compile an own sdk for yourself if you need it right away (I can provide a linux build).
I have a similar project, though mine is taking stills, not video, but for all intents and purposes they should behave the same.
In my code I have:
var win = $.camera_view;
This allows me later to start my activity with:
win.activity.startActivityForResult(...
Per your example you would probably set curActivity like this:
var curActivity = $.cameraWin.activity;
[EDIT]
If you still get no result you can try using .putExtraUri to specify the location to store the video:
var tempfile = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory, "tempvideo.mpg");
intent.putExtraUri("output",tempfile.nativePath);
You would set this before calling startActivityForResult.

ngcordova android file select and upload to server

I want to upload file from my ionic application to server. I am using cordovafiletransfer plugin. Using that I am able to upload file by providing static path in controller code. My question is how to get selected file path by user? I only get filename from input tag on the relative path of selected file. How to get that?
View Page Code:
<label class="item item-input">
<div class="input-label">Upload Photo</div>
<input type="file" onchange="angular.element(this).scope().setFile(this)" accept="image/*"/>
</label>
<div class="padding">
<button ng-click="upload()" class="button button-block button-assertive">Upload</button>
</div>
Controller Code:
$scope.upload = function() {
var filename, options, targetPath;
console.log($scope.theFile);
targetPath = cordova.file.externalRootDirectory + '/Download/androidify.png';
filename = targetPath.split('/').pop();
options = {};
options.fileKey = 'image_file';
options.fileName = $scope.theFile.name;
options.chunkedMode = false;
options.mimeType = $scope.theFile.type;
options.headers = {
'Authorization': getDeviceToken()
};
console.log(options);
return $cordovaFileTransfer.upload(domain.uploadphoto(), targetPath, options).then(
(function(result) {
console.log('SUCCESS: ' + JSON.stringify(result.response));
}),
(function(err) {
console.log('ERROR: ' + JSON.stringify(err));
}),
function(progress) {}
);
};
$scope.setFile = function(element) {
return $scope.$apply(function($scope) {
console.log(element);
return $scope.theFile = element.files[0];
});
};
How to get proper target path of selected file?
I came across this post which should solve the problem, (it works for me, with some modification):
In my template:
<input type="file" fileread="file.path" />
<button type="button" class="button button-small button-assertive" ng-click="vm.upload(file)">Upload PDF</button>
and my modified Directive:
.directive("fileread", ['$cordovaFile', function ($cordovaFile) {
return {
scope: {
fileread: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
var reader = new FileReader();
reader.onload = function (loadEvent) {
var fileName = changeEvent.target.files[0].name;
$cordovaFile.writeFile(cordova.file.dataDirectory, fileName, loadEvent.target.result, true)
.then(function (result) {
console.log(result)
}, function (err) {
console.warn(err)
});
scope.$apply(function () {
scope.fileread = cordova.file.dataDirectory + fileName;
});
}
reader.readAsArrayBuffer(changeEvent.target.files[0]);
});
}
}
}]);
Remember to clean up after you uploaded the document
use:
$cordovaFile.removeFile(cordova.file.dataDirectory, fileName)
.then(function (success) {
// success
}, function (error) {
// error
});
Also see http://www.javascripture.com/FileReader for more info regarding FileReader

Categories

Resources