i am working on a cross-platform mobile app using appcelerator titanium alloy. the code below opens the native camera functionality and works fine on apple devices. on android devices, the camera opens but the button to actually take a picture is disabled (greyed out). the buttons for taking video or changing camera settings work fine, just the take picture button is not working. any ideas? thanks in advance
the code below called on click of takePic button to open camera
takePic.addEventListener('click', function(e) {
var win = Titanium.UI.createWindow({ //Open Camera
});
Titanium.Media.showCamera({
success:function(event){
Ti.API.debug('Our type was: '+event.mediaTpe);
if(event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO){
***win = Titanium.UI.currentWindow;
if(osName == "android"){
win.open();
}***
try {
var image_name = "siteing.jpg";
var fileImage = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory, image_name);
fileImage.write(event.media);
Ti.API.log(event.media);
picURL = fileImage;//event.media;
picRaw = event.media; //Raw bytes of picture to save to database
pictureSet = true;
$.videoButton.enabled = false;
$.videoButton.backgroundColor = "#DDDDDD";
//$.audioButton.enabled = false;
format = "Picture";
$.savePic.show();
} catch(e){
alert("An Error:" + e.message);
}
} else {
var alert = createErrorAlert({text:"An error occured getting the media. Please check file size and format and try again."});
$.yesLatLon.add(alert);
alert.show();
}
if(osName == "android"){
win.open();
}
}, cancel:function(){
//called when user cancels taking a picture
if(osName == "android"){
//win.close();
}
}, error:function(error){
//called when there's an error
var a = Titanium.UI.createAlertDialog({title:'Camera'});
if(error.code == Titanium.Media.NO_CAMERA){
a.setMessage('Please run this test on device');
} else {
a.setMessage('Unexpected error: ' + error.code);
}
a.show();
}, saveToPhotoGallery:true,
//allowEditing and mediaTypes are iOS-only settings
allowEditing:true,
mediaTypes:[Ti.Media.MEDIA_TYPE_VIDEO, Ti.Media.MEDIA_TYPE_PHOTO]
});
alert.hide();
$.yesLatLon.removeEventListener('androidback', arguments.callee);
});
screenshot_from_phone
It's been a long time, but I did get this working and thought I'd post my code in case it helps someone else. Fair warning, I now face a different issue with the camera on certain Android devices (Samsung S-series and Google Pixel cannot open camera), which I'm posting in a separate question. However, the original issue with camera button being disabled was successfully resolved last year with the below code.
takePic.addEventListener('click', function(e) {
var win = Titanium.UI.createWindow({//Open Camera
});
Titanium.Media.showCamera({
success : function(event) {
if (event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO) {
win = Titanium.UI.currentWindow;
if (osName == "android") {
var img_view = Titanium.UI.createImageView({
height : '100%',
width : '100%',
});
win.add(img_view);
}
try {
picURL = event.media;
picRaw = event.media;
pictureSet = true;
$.videoButton.enabled = false;
$.videoButton.backgroundColor = "#DDDDDD";
$.savePic.show();
format = "Picture";
} catch(e) {
alert("An Error:" + e.message);
}
} else {
var alert = createErrorAlert({
text : "An error occured getting the media. Please check file size and format and try again."
});
$.yesLatLon.add(alert);
alert.show();
}
},
cancel : function() {
//called when user cancels taking a picture
},
error : function(error) {
//called when there's an error
var a = Titanium.UI.createAlertDialog({
title : 'Camera'
});
if (error.code == Titanium.Media.NO_CAMERA) {
a.setMessage('Please run this test on device');
} else {
a.setMessage('Unexpected error: ' + error.code);
}
a.show();
},
saveToPhotoGallery : true,
allowEditing : false,
autohide : true, //Important!
mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO]
});
alert.hide();
});
Related
I am trying to build a progressive web app that utilizes the device camera to take pictures but want it to save to their Photos gallery without being prompted to download like the native camera app does..Is this even possible..I haven't discovered a way yet and not much info on google about it would it be different if it was uploaded to the cloud?
Thanks
The link at https://whatwebcando.today/photos.html suggests that this may be possible.
capturer = ImageCapture(streamVideoTrack)
Creates an image capturer out of the Media Stream Video Track.
capturer.takePhoto()
Returns a Promise resolved with the photo taken with the current settings.
capturer.setOptions(photoSettings)
Configures the photoSettings for subsequent captures; if visible, the effects of the configuration can be seen in the Track used as input.
This is the example code:
function getUserMedia(options, successCallback, failureCallback) {
var api = navigator.getUserMedia || navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia || navigator.msGetUserMedia;
if (api) {
return api.bind(navigator)(options, successCallback, failureCallback);
}
}
var theStream;
function getStream() {
if (!navigator.getUserMedia && !navigator.webkitGetUserMedia &&
!navigator.mozGetUserMedia && !navigator.msGetUserMedia) {
alert('User Media API not supported.');
return;
}
var constraints = {
video: true
};
getUserMedia(constraints, function (stream) {
var mediaControl = document.querySelector('video');
if ('srcObject' in mediaControl) {
mediaControl.srcObject = stream;
mediaControl.src = (window.URL || window.webkitURL).createObjectURL(stream);
} else if (navigator.mozGetUserMedia) {
mediaControl.mozSrcObject = stream;
}
theStream = stream;
}, function (err) {
alert('Error: ' + err);
});
}
function takePhoto() {
if (!('ImageCapture' in window)) {
alert('ImageCapture is not available');
return;
}
if (!theStream) {
alert('Grab the video stream first!');
return;
}
var theImageCapturer = new ImageCapture(theStream.getVideoTracks()[0]);
theImageCapturer.takePhoto()
.then(blob => {
var theImageTag = document.getElementById("imageTag");
theImageTag.src = URL.createObjectURL(blob);
})
.catch(err => alert('Error: ' + err));
}
So it seems like you can take a photo... I can't see anywhere to indicate that you can then persist this photo in the users storage though. I'd love to be wrong.
I'm working out on the ionic project. I need to get the items based on current district. To get the current district I tried the below.
cordova.plugins.diagnostic.isLocationEnabled(function(enabled) {
alert("Location is " + (enabled ? "enabled" : "disabled"));
if(!enabled)
cordova.plugins.diagnostic.switchToLocationSettings();
var geocoder = new google.maps.Geocoder();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
}
function successFunction(position) {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
}
function errorFunction(){
$ionicPopup.alert({
title:"Alert",
content:"Geocoder failed"
});
}
function codeLatLng(lat, lng) {
geocoder.geocode({'latLng': new google.maps.LatLng(lat, lng)}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
for (var i=0; i<results[0].address_components.length; i++) {
for (var b=0;b<results[0].address_components[i].types.length;b++) {
if (results[0].address_components[i].types[b] == "administrative_area_level_2") {
district= results[0].address_components[i];
}
}
}
alert(distrcit.long_name);
}
else {
alert("No results");
}
}
else {
alert("Geocoder Failed");
}
});
}
}, function(error) {
});
This code is working fine if the GPS is enabled after switching to location settings. I'm getting the problem when the GPS is not enabled and getting back into the app. How can I detect whether it is enabled or not after moving to location settings and getting back to the app? Even though I referred many posts in StackOverflow, I didn't get the solution what I needed actually. So please help me out in solving it.
How can I detect whether it is enabled or not after moving to location settings and getting back to the app?
You can detect when your app is returned to the foreground using the resume event.
function onResume() {
cordova.plugins.diagnostic.isLocationEnabled(function(enabled) {
console.log("Location is " + (enabled ? "enabled" : "disabled"));
// etc.
}, function(error) {});
}
document.addEventListener("resume", onResume, false);
Im testing some media features with ionic and im stuck while trying to set the camera output into a video tag using getUserMedia using this code:
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({ audio: false, video: { width: 500, height: 500 } },
function(stream) {
console.log("Im streaming!!", stream);
var video = document.querySelector('video');
console.log("video element", video);
video.src = window.URL.createObjectURL(stream);
video.onloadedmetadata = function(e) {
console.log("stream start");
video.play();
};
},
function(err) {
console.log("The following error occurred: " + err.name);
}
);
} else {
console.log("getUserMedia not supported");
}
this is the html:
<ion-pane>
<ion-header-bar class="bar-stable">
<h1 class="title">Ionic Blank Starter</h1>
</ion-header-bar>
<ion-content>
<video id="video" autoplay="autoplay" width="500" height="500"></video>
</ion-content>
</ion-pane>
i can actually get only a black screen. Is my approach right or im missing something?
I managed to reproduce the problem and solved it by using the constraints options. Using constraints you can set the sourceId that allows you to select between front or rear camera. Im sure that your device has no front camera and i guess this is why you are getting the black screen.
First we create our constraint options:
var constraints = {};
MediaStreamTrack.getSources (function(sources) {
sources.forEach(function(info) {
if (info.facing == "environment") {
constraints = {
video: {
optional: [{sourceId: info.id}]
}
};
}
})
})
Then we call the navigator.getUserMedia:
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia(constraints,
function(stream) {
console.log("Im streaming!!", stream);
var video = document.querySelector('video');
console.log("video element", video);
video.src = window.URL.createObjectURL(stream);
video.onloadedmetadata = function(e) {
console.log("stream start");
video.play();
};
},
function(err) {
console.log("The following error occurred: " + err.name);
}
);
} else {
console.log("getUserMedia not supported");
}
Warning: MediaStreamTrack.getSources returns a promise so that means that if you try to run your navigator.getUserMedia code at once, it will fail. You will have to wrap it in a function and run it as a callback.
More info about camera and audio source selection can be found here:
https://developers.google.com/web/updates/2015/10/media-devices
also a nice example here:
https://simpl.info/getusermedia/sources/
The final solution to this problem is that getUserMedia require a runtime permission check to work. To achieve that i used this plugin. Then this worked like a charm:
cordova.plugins.diagnostic.requestRuntimePermission(function(status){
if(cordova.plugins.diagnostic.runtimePermissionStatus.GRANTED){
navigator.getUserMedia({video: true, audio: false}, function(localMediaStream) {
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(localMediaStream);
video.onloadedmetadata = function(e) {
console.log('Stream is on!!', e);
};
}, errorCallback);
}
});
I have tried numerous ways of adding a cast button to video.js player but cannot do this for the life of me. Can anyone help?
I'm using the hellovideo cms for videos and need plugins added but have no idea about jquery etc.. so please if anyone can help?
There is a really nice plugin for this: https://github.com/kim-company/videojs-chromecast
Just follow the setup instructions (adding the js and css to your page).
I tried kim-company/videojs-chromecast. It only works with an older version of videojs, I used 5.4.6. It's quite buggy. Another I tried was benjipott/video.js-chromecast, which claims to work with newer videojs, but I didn't like it at all. So I gave up on videojs, I always found the native HTML5 video player more reliable and easier to work with (videojs just wraps this anyway). For the chromecast stuff, I provide a nearby button that links to chromecast.link, where I wrote a full web chromecast sender app. Pass the video and poster URL in the fragment, per this example:
https://chromecast.link/#content=http://host/some.mp4,poster=http://host/poster.jpg,subtitles=http://host/webvtt.srt
I recently answered this question, you can check it out here: How to implement chromecast support for html5 player for more information
var session = null;
$( document ).ready(function(){
var loadCastInterval = setInterval(function(){
if (chrome.cast.isAvailable) {
console.log('Cast has loaded.');
clearInterval(loadCastInterval);
initializeCastApi();
} else {
console.log('Unavailable');
}
}, 1000);
});
function initializeCastApi() {
var applicationID = chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID;
var sessionRequest = new chrome.cast.SessionRequest(applicationID);
var apiConfig = new chrome.cast.ApiConfig(sessionRequest,
sessionListener,
receiverListener);
chrome.cast.initialize(apiConfig, onInitSuccess, onInitError);
};
function sessionListener(e) {
session = e;
console.log('New session');
if (session.media.length != 0) {
console.log('Found ' + session.media.length + ' sessions.');
}
}
function receiverListener(e) {
if( e === 'available' ) {
console.log("Chromecast was found on the network.");
}
else {
console.log("There are no Chromecasts available.");
}
}
function onInitSuccess() {
console.log("Initialization succeeded");
}
function onInitError() {
console.log("Initialization failed");
}
$('#castme').click(function(){
launchApp();
});
function launchApp() {
console.log("Launching the Chromecast App...");
chrome.cast.requestSession(onRequestSessionSuccess, onLaunchError);
}
function onRequestSessionSuccess(e) {
console.log("Successfully created session: " + e.sessionId);
session = e;
}
function onLaunchError() {
console.log("Error connecting to the Chromecast.");
}
function onRequestSessionSuccess(e) {
console.log("Successfully created session: " + e.sessionId);
session = e;
loadMedia();
}
function loadMedia() {
if (!session) {
console.log("No session.");
return;
}
var videoSrc = document.getElementById("myVideo").src;
var mediaInfo = new chrome.cast.media.MediaInfo(videoSrc);
mediaInfo.contentType = 'video/mp4';
var request = new chrome.cast.media.LoadRequest(mediaInfo);
request.autoplay = true;
session.loadMedia(request, onLoadSuccess, onLoadError);
}
function onLoadSuccess() {
console.log('Successfully loaded video.');
}
function onLoadError() {
console.log('Failed to load video.');
}
$('#stop').click(function(){
stopApp();
});
function stopApp() {
session.stop(onStopAppSuccess, onStopAppError);
}
function onStopAppSuccess() {
console.log('Successfully stopped app.');
}
function onStopAppError() {
console.log('Error stopping app.');
}
I'm getting familiar with Titanium mobile, and now I'm developing iOS app with it.
I want to create custom login button.
I followed some instructions on the web, but still its not working.
The code is below.
var win = Ti.UI.currentWindow;
Titanium.Facebook.appid = "APP ID";
Titanium.Facebook.permissions = ['permissions here'];
var login = Ti.UI.createButton({
backgroundImage:'facebooklogin.png',
width:250,
height40:
});
win.add(login);
login.addEventListener('click', function(e) {
Titanium.Facebook.authorize();
});
Titanium.Facebook.addEventListener('login', function(e) {
if (e.success) {
Titanium.Facebook.requestWithGraphPath('me', {}, 'GET', function(e) {
if (e.success) {
var data= JSON.parse(e.result);
Ti.API.info("Name:"+data.name);
Ti.API.info("email:"+data.email);
Ti.API.info("facebook Id:"+data.id);
} else if (e.error) {
alert(e.error);
} else {
alert('Unknown response.');
}
});
}else{
if(e.error){
alert(e.error);
}else{
alert("Unkown error while trying to login to facebook.");
}
}
});
}
Dose anybody show me solutions?
thanks.
If you are already Authorized the Ti.Facebook.authorize method wont do anything. Try clearing your app data from the device, and start over.