I am trying to implement Videogular in my AngularJS App. The out of the box example works nicely, no issue. But I am unable to ask the player manually to play a different file, instead of the running audio.
Here is my HTML.
<div ng-controller="HomeCtrl as controller" class="videogular-container" ng-model="sharedProperty">
sharedProperty.data = {{sharedProperty.data}}
<button ng-click="SetValue('http://example.com/myfile.mp3')" type="button" class="btn btn-default">Change Audio</button>
<videogular vg-theme="controller.config.theme.url" class="videogular-container audio">
<vg-media vg-src="controller.config.sources"></vg-media>
<vg-controls>
<vg-play-pause-button></vg-play-pause-button>
<vg-time-display>{{ currentTime | date:'mm:ss' }}</vg-time-display>
<vg-scrub-bar>
<vg-scrub-bar-current-time></vg-scrub-bar-current-time>
</vg-scrub-bar>
<vg-time-display>{{ timeLeft | date:'mm:ss' }}</vg-time-display>
<vg-volume>
<vg-mute-button></vg-mute-button>
</vg-volume>
</vg-controls>
</videogular>
</div>
And this is the controller code:
app.controller('HomeCtrl', ["$sce","$scope", "$window", "sharedProperties",
function($sce, $scope, $window, sharedProperties) {
$scope.sharedProperty = sharedProperties.getProperty();
$scope.SetValue = function (msg)
{
$window.alert( $scope.sharedProperty.data );
$scope.setProperty = sharedProperties.setProperty;
$scope.setProperty(msg);
$window.alert( $scope.sharedProperty.data );
}
$window.alert( $scope.sharedProperty.data );
this.config = {
sources: [{
src: $sce.trustAsResourceUrl( $scope.sharedProperty.data ),
type: "audio/mpeg"
}, {
src: $sce.trustAsResourceUrl("http://static.videogular.com/assets/audios/videogular.ogg"),
type: "audio/ogg"
}],
theme: {
url: "http://www.videogular.com/styles/themes/default/latest/videogular.css"
}
};
}
]
);
The Service code is given here:
app.service('sharedProperties', function () {
var property = {
data: "http://example.com/firstaudio.mp3"
};
return {
getProperty:function () {
return property;
},
setProperty:function (value) {
property.data = value;
}
};
});
When I click on Set Value button, I am able to change the value of sharedProperty.data successfully but I don't know how to ask the player to stop the current audio and play the new file instead.
I'm the creator of Videogular.
If you have set a binding with:
<vg-media vg-src="controller.config.sources"></vg-media>
You only need to change your controller.config.sources and that's all:
app.controller('HomeCtrl', ["$sce","$scope", "$window", "sharedProperties",
function($sce, $scope, $window, sharedProperties) {
$scope.sharedProperty = sharedProperties.getProperty();
$scope.SetValue = function (msg)
{
$window.alert( $scope.sharedProperty.data );
$scope.setProperty = sharedProperties.setProperty;
$scope.setProperty(msg);
$window.alert( $scope.sharedProperty.data );
}
$scope.changeSource = function (source) {
// source should be an array of objects with src and type
this.config.sources = source;
}
$window.alert( $scope.sharedProperty.data );
this.config = {
sources: [{
src: $sce.trustAsResourceUrl( $scope.sharedProperty.data ),
type: "audio/mpeg"
}, {
src: $sce.trustAsResourceUrl("http://static.videogular.com/assets/audios/videogular.ogg"),
type: "audio/ogg"
}],
theme: {
url: "http://www.videogular.com/styles/themes/default/latest/videogular.css"
}
};
}
]);
You have an example here:
https://github.com/2fdevs/videogular/blob/master/app/scripts/controllers/main.js#L102
Related
I figured out it is not possible to share video content onto Instagram directly on Android in behalf of the user. This was my original intention.
Seems I can not use navigator.share call which works on iOS but not on Android, or only for text and url, but not for video / mp4.
I would not use MediaStore and similar React Nativ solutions as my app is a regular React.
What elso approach do you know?
I have now this:
const showShareDialog = async () => {
try {
log(
{
text: 'setIsDownloadFileInProgress(true) ' + getTempUserShortId(),
},
env
)
setIsDownloadFileInProgress(true)
const res = await axios.get(
`https://t44-post-cover.s3.eu-central-1.amazonaws.com/${imgId}.mp4`,
{ withCredentials: false, responseType: 'blob' }
)
setIsDownloadFileInProgress(false)
const shareData = {
files: [
new File([res.data], `${imgId}.mp4`, {
type: 'video/mp4',
}),
],
title: 'Megosztom',
text: 'Mentsd le a képekbe, és oszd meg storyban.',
}
//showShareDialog(shareData, 0)
if (navigator.share && !isDesktop) {
log(
{
text:
`navigator.share && !isDesktop shareData.files[0].size: ${shareData.files[0].size} ` +
getTempUserShortId(),
},
env
)
if (isAndroid()) {
const { status } = await MediaLibrary.requestPermissionsAsync()
if (status === 'granted') {
const asset = await MediaLibrary.createAssetAsync(res.data)
await MediaLibrary.createAlbumAsync(`${imgId}.mp4`, asset, false)
}
} else {
navigator
.share(shareData)
.then(() => {
log(
{
text: `'The share was successful 1 ` + getTempUserShortId(),
},
env
)
})
.catch((error) => {
log(
{
text:
`There was an error sharing 1 ${error} ` +
getTempUserShortId(),
},
env
)
})
}
} else {
log(
{
text: 'else ' + getTempUserShortId(),
},
env
)
setIsDesktopDownloadDialogVisible(true)
}
} catch (error) {
console.error(error)
log(
{
text: `a onclick error 2: ${error} ` + getTempUserShortId(),
},
env
)
}
}
I'm trying to save and load images from cache using ImageCache NativeScript Core module but it won't work.
<template>
<Page>
<StackLayout>
<Image v-for="exampleImage in exampleImages" :src="getCachedImage(exampleImage.url)"/>
</StackLayout>
</Page>
</template>
<script>
import * as imageCache from 'tns-core-modules/ui/image-cache'
import * as imageSource from 'tns-core-modules/image-source'
export defualt {
data() {
return {
exampleImages: [
{url: 'https://image.tmdb.org/t/p/w600_and_h900_bestv2/kY2c7wKgOfQjvbqe7yVzLTYkxJO.jpg'},
{url: 'https://image.tmdb.org/t/p/w600_and_h900_bestv2/svIDTNUoajS8dLEo7EosxvyAsgJ.jpg'},
{url: 'https://image.tmdb.org/t/p/w600_and_h900_bestv2/A7XkpLfNH0El2yyDLc4b0KLAKvE.jpg'},
]
}
},
methods: {
getCachedImage(imgUrl) {
const cache = new imageCache.Cache();
cache.enableDownload();
const image = cache.get(imgUrl);
let cachedImageSource;
if (image) {
console.log('getting image from cache')
cachedImageSource = imageSource.fromNativeSource(image)
} else {
console.log('downloading image, setting it in cache, and getting from cache')
cache.push({
key: imgUrl,
url: imgUrl,
completed: (image, key) => {
if (imgUrl === key) {
cachedImageSource = imageSource.fromNativeSource(image);
console.log(cachedImageSource)
}
},
error: () => {
console.log('Error')
}
});
}
cache.disableDownload();
return cachedImageSource;
}
}
}
</script>
But then, the output in my console is the following:
iOS:
{ ios: {} }
Android:
{ android:
{ constructor:
{ [Function]
[length]: 0,
[name]: '',
[arguments]: null,
[caller]: null,
[prototype]: [Object],
createBitmap: [Object],
createScaledBitmap: [Object],
extend: [Object],
CREATOR: [Object],
DENSITY_NONE: 0,
CONTENTS_FILE_DESCRIPTOR: 1,
PARCELABLE_WRITE_RETURN_VALUE: 1,
null: [Circular],
class: [Object],
CompressFormat: [Object],
Config: [Object] } } }
And of course is always outputing: downloading image, setting it in cache, and getting from cache and never getting image from cache. The image is never displayed, never saved in cache and never obtained from cache.
I don't know what I'm I doing wrong.
Thanks in advance.
Image download is asynchronously, so you can not use a direct return statement. You have to wait for the complete callback and update your data with image url.
<template>
<Page class="page">
<ActionBar title="Home" class="action-bar" />
<ScrollView>
<StackLayout>
<Image v-for="exampleImage in exampleImages" :src="exampleImage.src" />
</StackLayout>
</ScrollView>
</Page>
</template>
<script>
import * as imageCache from "tns-core-modules/ui/image-cache";
import * as imageSource from "tns-core-modules/image-source";
export default {
data() {
return {
exampleImages: [{
url: "https://image.tmdb.org/t/p/w600_and_h900_bestv2/kY2c7wKgOfQjvbqe7yVzLTYkxJO.jpg",
src: null
},
{
url: "https://image.tmdb.org/t/p/w600_and_h900_bestv2/svIDTNUoajS8dLEo7EosxvyAsgJ.jpg",
src: null
},
{
url: "https://image.tmdb.org/t/p/w600_and_h900_bestv2/A7XkpLfNH0El2yyDLc4b0KLAKvE.jpg",
src: null
}
]
};
},
methods: {
getCachedImage(exampleImage) {
const cache = new imageCache.Cache();
cache.enableDownload();
const image = cache.get(exampleImage.url);
let cachedImageSource;
if (image) {
console.log("getting image from cache");
exampleImage.src = imageSource.fromNativeSource(image);
} else {
console.log(
"downloading image, setting it in cache, and getting from cache"
);
cache.push({
key: exampleImage.url,
url: exampleImage.url,
completed: (image, key) => {
exampleImage.src = imageSource.fromNativeSource(
image);
},
error: () => {
console.log("Error");
}
});
}
// cache.disableDownload();
}
},
created() {
for (let x in this.exampleImages) {
this.getCachedImage(this.exampleImages[x]);
}
}
};
</script>
Updated Playground
I developed a mobile app to help sharing things. The user has to give infos about what he is sending and he can add a picture of the object. So i used the cordova file, camera and fileTransfert plugins. It worked fine on most of the devices i tested on, but i discovered that in some other phone, it doesn't. While doing some tests and research on one of those phones, i discovered that the upload() method of FileTransfert i use to send images to online server seems like not able to reach the folder where the image is stored. Here is a sample of my code. Would you please help me to confirm if i am rigth and how to make those phones to be able to post pictures on the platform?
public presentActionSheet(picture) {
if(this.translateService.currentLang=='fr'){
let actionSheet = this.actionSheetCtrl.create({
title: 'Quelle est la source?',
buttons: [
{
icon: 'images',
text: 'Mon téléphone',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY, picture);
}
},
{
icon: 'camera',
text: 'Ma Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA, picture);
}
},
{
text: 'Annuler',
role: 'cancel'
}
]
});
actionSheet.present();
}else{
let actionSheet = this.actionSheetCtrl.create({
title: 'What is the source?',
buttons: [
{
icon: 'images',
text: 'My Phone',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY, picture);
}
},
{
icon: 'camera',
text: 'My Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA, picture);
}
},
{
text: 'Cancel',
role: 'cancel'
}
]
});
actionSheet.present();
}
};
presentToast(message_error) {
let toast = this.toastCtrl.create({
message: message_error,
cssClass: 'alert-box',
position: 'middle',
showCloseButton: true,
closeButtonText: "OK"
});
toast.present();
}
//Here is the function to take a picture
public takePicture(sourceType, picture) {
// Create options 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 library
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(), picture);
});
} else {
console.log('In the else condition');
var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
this.copyFileToLocalDir(correctPath, currentName, this.createFileName(), picture);
}
}, (err) => {
if(this.translateService.currentLang=='fr'){
this.presentToast('Erreur, pas d\'image selectionnée.');
}else{
this.presentToast('Error, no image selected.');
}
});
}
// Create a new name for the image
private createFileName() {
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
return newFileName;
}
// Copy the image to a local folder
//cordova.file.dataDirectory
private copyFileToLocalDir(namePath, currentName, newFileName, picture) {
this.file.copyFile(namePath, currentName, cordova.file.dataDirectory, newFileName).then(success => {
if(picture == "imageOne"){
this.mainImage = newFileName;
}else if(picture == "imageTwo"){
this.secondImage = newFileName;
}else{
this.thirdImage = newFileName;
}
//this.lastImage = newFileName;
}, error => {
if(this.translateService.currentLang=='fr'){
this.presentToast('Erreur, le fichier n\'a pas pu etre sauvegardé.');
}else{
this.presentToast('Error, file could not be saved.');
}
console.log(error);
});
}
// Always get the accurate path to your apps folder
public pathForImage(img) {
if (img === null) {
return '';
} else {
return cordova.file.dataDirectory + img;
}
}
public uploadImage(picture) {
// Destination URL
var url = "http://donation.oneclub1.org/donation-new/web/api/upload/image?context=donations";
// File for Upload
var targetPath: any;
if(picture == "imageOne"){
targetPath = this.pathForImage(this.mainImage);
}else if(picture == "imageTwo"){
targetPath = this.pathForImage(this.secondImage);
}else{
targetPath = this.pathForImage(this.thirdImage);
}
// File name only
var filename: any;
if(picture == "imageOne"){
filename = this.mainImage;
}else if(picture == "imageTwo"){
filename = this.secondImage;
}else{
filename = this.thirdImage;
}
var options = {
fileKey: "file",
fileName: filename,
chunkedMode: false,
mimeType: "multipart/form-data",
params : {'fileName': filename}
};
const fileTransfer: TransferObject = this.transfer.create();
// Use the FileTransfer to upload the image
return fileTransfer.upload(targetPath, url, options);/*.then(data => {
if(picture == "imageOne"){
this.mainImageLocal = parseInt(data.response);
}else if(picture == "imageTwo"){
this.secondImageLocal = parseInt(data.response);
}else{
this.thirdImageLocal = parseInt(data.response);
}
//this.presentToast('this is your image id'+this.mainImageLocal);
}, err => {
this.loading.dismissAll();
this.presentToast('Error while uploading file.');
})*/;
}
publish(){
if(this.mainImage!=null){
this.loading = this.loadingCtrl.create({
content: this.content2,
});
this.loading.present();
//var categoryId: number;
for(let parent of this.categories){
if(parent.name == this.asking_form_group.value.subcategory){
this.categoryId=parent.id;
console.log('Id found and it is:'+this.categoryId);
break;
};
};
//var userId: number;
if(localStorage.getItem('userId')){
this.userId= parseInt(localStorage.getItem('userId'));
console.log('got the user id in nmber:'+this.userId);
};
var headers = new Headers();
headers.append("Accept", 'application/json');
headers.append('Content-Type', 'application/json' );
let options = new RequestOptions({ headers: headers });
this.uploadImage('imageOne').then(data => {
this.mainImageLocal = parseInt(data.response);
this.postParams = {
name: this.asking_form_group.value.name,
category: this.categoryId,
description: this.asking_form_group.value.description,
image: this.mainImageLocal,
user: this.userId
}
this.http.post(this.Api+"/donations/requests?api_key="+localStorage.getItem('userApiKey'), this.postParams, options).map(res => res.json())
.subscribe(data => {
this.loading.dismissAll();
if(this.translateService.currentLang=='fr'){
this.presentToast('Félicitations!!Votre demande a été postée sur la plateforme!')
}else{
this.presentToast ('Congratulations !! Your request has been posted on the platform!')
}
this.events.publish('ask:posted', 1);
this.navCtrl.setRoot(Dashboard);
}, error => {
console.log(error);
//this.asking_form_group.reset();
this.testor = error.response;
this.loading.dismissAll();
this.presentToast(this.error);
});
});
}else{
this.loading = this.loadingCtrl.create({
content: this.content2,
});
this.loading.present();
//var categoryId: number;
for(let parent of this.categories){
if(parent.name == this.asking_form_group.value.subcategory){
this.categoryId=parent.id;
console.log('Id found and it is:'+this.categoryId);
break;
};
};
if(localStorage.getItem('userId')){
this.userId= parseInt(localStorage.getItem('userId'));
console.log('got the user id in nmber:'+this.userId);
};
var headers = new Headers();
headers.append("Accept", 'application/json');
headers.append('Content-Type', 'application/json' );
let options = new RequestOptions({ headers: headers });
this.postParams = {
name: this.asking_form_group.value.name,
category: this.categoryId,
description: this.asking_form_group.value.description,
image: this.mainImageLocal,
user: this.userId
}
this.http.post(this.Api+"/donations/requests?api_key="+localStorage.getItem('userApiKey'), this.postParams, options).map(res => res.json())
.subscribe(data => {
this.loading.dismissAll();
if(this.translateService.currentLang=='fr'){
this.presentToast('Félicitations!!Votre demande a été postée sur la plateforme!')
}else{
this.presentToast ('Congratulations !! Your request has been posted on the platform!')
}
this.events.publish('ask:posted', 1);
this.navCtrl.setRoot(Dashboard);
}, error => {
console.log(error);
//this.asking_form_group.reset();
this.testor = error.response;
this.loading.dismissAll();
this.presentToast(this.error);
});
};
}
Sorry i found what the issue was and i fogot to put it here. The problem was actually about filesize. Filetransfert default limit is 7.5Mo. Sending file greater than that would fail. In some phones, camera default configurations put the picture size to 8 or greater Mpx. So that why it could not work in those phones.
I am developing an ionic app. I am using cordova's FileTransfer plugin to download pdf file. I am able to download the file to my internal memory,but not able to display single progress bar for downloaidng.
What is the best way of displaying progress for downloading.
Controller
var url = 'http://someurl.com/api/pdf_download/' + id;
// Android
var targetPath = 'file:///storage/sdcard0/' + id + '.pdf';
var trustHosts = true;
var options = {};
$cordovaFileTransfer.download(url, targetPath, options, trustHosts)
.then(function(result) {
console.log(result);
}, function() {
var alertPopup = $ionicPopup.alert({
title: 'No internet access',
buttons: [{
text: 'OK',
type: 'button-assertive'
}]
});
alertPopup.then(function() {});
}, function(progress) {
$timeout(function() {
$scope.downloadProgress = (progress.loaded / progress.total) * 100;
})
console.log('progress--->', $scope.downloadProgress);
});
I have used cordovaToast plugin for this feature.Here is the example for showing pdf download progress
html
<ion-view >
<div class="bar bar-subheader bar-positive" style="padding:0px;height: 8px;" >
<progress id="progressbar" max="100" value="{{ downloadProgress }}" class="progress"> </progress>
</div>
<ion-content>
</ion-content>
</ion-view>
css
.progress {
margin: 0 px;
height: 8 px;
background - color: #F1292B!important;
border - radius: 2 px;
box - shadow: 0 2 px 5 px rgba(0, 0, 0, 0.25) inset;
}
js
if (window.cordova) {
var url = '{{base_url}}/pdf_download/' + id;
// Android
var targetPath = 'file:///storage/sdcard0/' + 'fpl_' + id + '.pdf';
var trustHosts = true;
var options = {};
$cordovaFileTransfer.download(url, targetPath, options, trustHosts)
.then(function(result) {
$cordovaToast
.show('File downloaded successfully..', 'short', 'center')
.then(function() {
// success
}, function() {
// error
});
console.log(result);
}, function() {
var alertPopup = $ionicPopup.alert({
title: 'No internet access',
buttons: [{
text: 'OK',
type: 'button-assertive'
}]
});
alertPopup.then(function() {});
}, function(progress) {
var dnldpgs = progress.loaded.toString().substring(0, 2);
$scope.downloadProgress = parseInt(dnldpgs);
});
}
As benka already answered to my question, you should use the <progress> html element.
The full answer can be found over here -> https://stackoverflow.com/a/25553044/3671726
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");
});
}