Camera not working using phonegap build - android

I'm making an app capable of take photos and upload them to a server. The phone will save the id generated.
I made a class abstractApp that creates an App object with a couple of helpers and variables. I'm using Framework7.
var App;
document.addEventListener("deviceready", function() {
App = new abstractApp();
var i;
App.f7Ref = new Framework7({init: false});
for (i = 0; i < App.constants.views.length; i++)
{
if (i==0)
App.mainView = App.f7Ref.addView (
App.constants.views[i].selector,
App.constants.views[i].settings );
else
App.f7Ref.addView (
App.constants.views[i].selector,
App.constants.views[i].settings );
}
// Checks if there exists register of remote photos
if ( App.local.get('remotephotos', false) == null || App.local.get('remotephotos', false) == '' )
{
App.remotephotos = [];
App.local.set('remotephotos', []);
}
else
{
App.remotephotos = App.local.get('remotephotos');
}
// Checks if there exists register of local photos
if ( App.local.get('localphotos', false) == null || App.local.get('localphotos', false) == '' )
{
App.localphotos = [];
App.local.set('localphotos', []);
}
else
{
App.localphotos = App.local.get('localphotos');
}
for (i = 0; i < appControllers.length; i++)
{
appControllers[i].apply(App);
}
console.log(App);
}, false);
In appControllers I'm saving functions related to each page (so it is a bit more organized). With only index and new-photo controllers I have no problem, I can attach events to elements and navigate between views. The problem is calling the camera object.
window.appControllers.push(function()
{
var $$ = Dom7;
var Ref = this.f7Ref;
var server = new serverInterface();
var photos = this.remotephotos;
var App = this;
Ref.onPageInit('new', function (page) {
Ref.alert('entra', 'entra');
$$('.capture').on('click', function () {
Ref.alert('Click', 'Click detected');
navigator.camera.getPicture(onSuccess, onFail,
{
quality: 20,
destinationType: destinationType.FILE_URI
});
function onSuccess(imageURI) {
Ref.alert('Photo captured.', 'Bien');
}
function onFail(message) {
Ref.alert('There was a problem.', 'Ups');
}
});
});
});
So, I enter the new page and I click the button with cass capture and the alert (click detected) appears, but it doesn't show the camera to take the photo.
I'm using Phonegap Build and an android phone, do you have any idea of what's happening?
Thank you very much in advance

The problem wasn't the javascript code I quoted.
I was loading the camera plugin in the config.xml like this
<gap:plugin name="org.apache.cordova.camera" />
But it should be loaded this way:
<plugin name="cordova-plugin-camera" />
If the plugin is not loaded correctly, in Phonegap Build appears: version n/a installed. In this case, when it is correctly loaded, appears: version 2.1.0 installed.
More information about this thread can be found here: http://phonegap.com/blog/2015/11/19/config_xml_changes_part_two/
Hope it helps someone else too
Regards

Related

How to integrate OpenCV with Ionic 3?

I am building a mobile app for body measurement through photo I capture. how I can use OpenCV for the same? How to integrate OpenCV with Ionic framework? Kindly help.
Essentially you can pull in a flavor of the opencv.js framework. The way I've done it is by pulling down some reference like https://docs.opencv.org/3.4.1/opencv.js, and then hosting it somewhere (in case opencv moves it on you). Then include that script in the Ionic project. Be careful how you do that though. It is a big file, so it could take the app longer to load. Some options I've used:
Local Asset
Store the js file in the local assets, and include it in the index.js. If the Ionic app is deployed as a native app, then this asset is already in the app and fairly fast to load.
<script src="assets/js/opencv.js" async></script>
Dynamically load the file (example below)
async ionViewDidLoad() {
let loadingScreen = this.loadingCtrl.create({ content: "Loading Scripts. Please Wait..." });
//Show loading screen & load scripts
try {
await loadingScreen.present();
await this.loadScript();
}
catch (error) {
this.errorMessage = "We had some trouble loading scripts...";
}
finally {
loadingScreen && loadingScreen.dismiss();
}
}
public loadScript(): Promise<any> {
return new Promise((resolve, reject) => {
var isFound = false;
var scripts = document.getElementsByTagName("script")
for (var i = 0; i < scripts.length; ++i) {
if (scripts[i].getAttribute('src') != null &&
scripts[i].getAttribute('src').includes("opencv")) {
isFound = true;
return resolve();
}
}
if (!isFound) {
var dynamicScripts = ["https://docs.opencv.org/3.4.1/opencv.js"];
for (var i = 0; i < dynamicScripts.length; i++) {
let scriptNode = document.createElement('script');
scriptNode.src = dynamicScripts[i];
scriptNode.type = 'text/javascript';
scriptNode.async = false;
scriptNode.charset = 'utf-8';
document.getElementsByTagName('head')[0].appendChild(scriptNode);
scriptNode.onload = resolve;
}
}
});
}

InAppBrowser not closing?

I'm using the InAppBrowser plugin (v1.1.1) with Cordova for an OAuth login process. Unfortunately, the InAppBrowser doesn't appear to be closing the browser. My "closeBrowser" function instead continually triggers the interval, and the browser remains on-screen on the Android (I have not tried other devices at this time.)
Is there a way to forcibly close the InAppBrowser other than .close(), or hide it? Or maybe there's a flaw in my code somewhere that is locking the browser.
LogInPage.prototype.handleExternalLogin = function (externalLogin) {
var _this = this;
var ref = window.open(Environment_1.settings.baseUrl + externalLogin.route.url, "_blank", "location=no");
ref.addEventListener('loadstart', function (event) {
if (_.startsWith(event.url, Environment_1.settings.baseUrl + "/api/Account/account/ExternalLoginCallback")) {
// Now we want to load a different url that will give us the mobile access token
console.log('get external-mobile-token');
_this.closeBrowser(ref);
var ref2 = window.open(Environment_1.settings.baseUrl + "/api/Account/external-mobile-token", "_blank" /*, "location=no"*/);
ref2.addEventListener('loadstop', function (event) {
console.log('loadstop ' + event.url);
if (event.url == Environment_1.settings.baseUrl + "/api/Account/external-mobile-token") {
ref2.executeScript({ code: 'window.document.documentElement.innerText' }, function (contents) {
_this.login(contents);
_this.closeBrowser(ref2);
});
}
});
ref2.addEventListener('loaderror', function (event) {
console.log(event);
_this.closeBrowser(ref2);
// TODO - do something?
});
}
});
ref.addEventListener('loaderror', function (event) {
console.log(event);
_this.closeBrowser(ref);
// TODO - do something?
});
};
LogInPage.prototype.closeBrowser = function (browser) {
var interval = setInterval(function () {
console.log('closing');
browser.close();
}, 10);
browser.addEventListener('exit', function () {
console.log('closed');
clearInterval(interval);
});
};
LogInPage.prototype.login = function (token) {
console.log(token);
};
The above code is actually generated from TypeScript, but I figured I wouldn't confuse the issue.
It appears that closing an InAppBrowser and opening another at the same time was causing the issue; rewriting the process to only need one window solved my issue.

jsPDF with Cordova - Adding images

I am trying to generate a PDF using the jsPDF library (https://github.com/MrRio/jsPDF) from within a mobile Cordova app. I am currently testing the app on an Android 4.0.4 device but it also needs to run on Windows mobile 8. The text in the PDF document is shown correctly however any images are scrambled. See image below
I did find this page (https://coderwall.com/p/nc8hia) that seemed to indicate there is a problem with jsPDF displaying images in Cordova (see comments) but the author never posted the follow-up. Has anyone been able to use jsPDF with Cordova and properly add images to the generated PDF? My code is below, any assistance or advice would be greatly appreciated.
function demoReceipt() {
var img = new Image();
img.onError = function() {
alert('Cannot load image: "' + url + '"');
};
img.onload = function() {
createPdf2(img);
};
img.src = 'img/testlogo.png';
}
function createPdf2(myLogo) {
// var doc = new jsPDF('p', 'pt', 'jontype');
var doc = new jsPDF('p', 'pt', 'letter');
doc.setProperties({
title : 'Fueling Receipt',
author : 'Jon Hoffman',
creater : 'Jon Hoffman'
});
doc.addImage(myLogo, 'PNG', 5, 5, 140, 30);
doc.setFontSize(12);
doc.text(10, 40, 'Sample PDF receipt');
doc.setFontSize(8);
doc.text(10, 45, 'Smaller text - new');
var pdfOutput = doc.output();
//NEXT SAVE IT TO THE DEVICE'S LOCAL FILE SYSTEM
//Requires cordova plugin add org.apache.cordova.file
console.log("file system...");
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem) {
console.log(fileSystem.name);
console.log(fileSystem.root.name);
console.log(fileSystem.root.fullPath);
fileSystem.root.getDirectory("myPDFs", {
create : true,
exclusive : false
}, function(dir) {
fileSystem.root.getFile("myPDFs/test.pdf", {
create : true
}, function(entry) {
var fileEntry = entry;
console.log(entry);
entry.createWriter(function(writer) {
writer.onwrite = function(evt) {
console.log("write success");
};
console.log("writing to file");
writer.write(pdfOutput);
}, function(error) {
console.log(error);
});
}, function(error) {
console.log(error);
});
}, function(error) {
});
}, function(event) {
console.log(evt.target.error.code);
});
}
I solved the issue with help from this blog post: https://coderwall.com/p/nc8hia. There does seems to be significant differences between the 0.90 version used in that post and the version that I am using from https://github.com/MrRio/jsPDF however the solution is pretty much the same.
First off, in the version from MyRio, you can get the PDF generation working without fixing the Blob issue noted in Igor’s post. All you need is to generate the PDF output by calling “doc.ouput()” and then save it using the Cordova filesystem plugin. So I thought I did not have to create the Blob (this is where I was wrong).
Igor (from the coderwall post) responded back to my question with some additional code but when I searched the jspdf.js file from MyRio version, I saw that the code (more compact version) was already in the code on lines 734 – 738:
var data = buildDocument(), len = data.length,
ab = new ArrayBuffer(len), u8 = new Uint8Array(ab);
while(len--) u8[len] = data.charCodeAt(len);
return new Blob([ab], { type : "application/pdf" });
But I also notice that the blob creation code that Igor fixed in his initial post was at the end of this block of code. So I commented out the “return new Blob([ab], { type : “application/pdf”});” line and put in the following code from Igor’s post with minor variable name changes:
try
{
var blob = new Blob([ab], {type: "application/pdf"});
console.debug("case 1");
return blob;
}
catch (e)
{
window.BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder;
if (e.name == 'TypeError' && window.BlobBuilder)
{
var bb = new BlobBuilder();
bb.append(ab);
console.debug("case 2");
return bb.getBlob("application/pdf");
}
else if (e.name == "InvalidStateError")
{
// InvalidStateError (tested on FF13 WinXP)
console.debug("case 3");
return new Blob([ab], {type: "application/pdf"});
}
else
{
// We're screwed, blob constructor unsupported entirely
console.debug("Errore");
}
}
Then when I generate that pdfOutput, in my code, I changed
var pdfOutput = doc.output();
to
var pdfOutput = doc.output(“blob”);
and it worked.
I hope this post is able to help out others experiencing the same issues.

Pull to refresh in Titanium for Android

How to pull to refresh?
In Titanium appcelerator I need to show a list of content in tableview. If I pull the view it needs to update. In iPhone I complete but in Android it won't work. Please any one help to solve this problem in Android.
My Android code:-
tableView.addEventListener('scroll',function(e)
{
var offset = e.contentOffset.y;
if (offset < -65.0 && !pulling && !reloading)
{
var t = Ti.UI.create2DMatrix();
t = t.rotate(-180);
pulling = true;
arrow.animate({transform:t,duration:180});
statusLabel.text = "Release to refresh...";
}
else if((offset > -65.0 && offset < 0 ) && pulling && !reloading)
{
pulling = false;
var t = Ti.UI.create2DMatrix();
arrow.animate({transform:t,duration:180});
statusLabel.text = "Pull down to refresh...";
}
});
tableView.addEventListener('dragEnd', function(e)
{
if(pulling && !reloading)
{
reloading = true;
pulling = false;
arrow.hide();
actInd.show();
statusLabel.text = "Reloading...";
tableView.setContentInsets({top:60},{animated:true});
tableView.scrollToTop(-60,true);
arrow.transform=Ti.UI.create2DMatrix();
beginReloading();
}
});
Titanium now supports pull to refresh for BOTH Android (> v6.2.0) and iOS (>3.2.0) with a Titanium.UI.TableView, Titanium.UI.ListView or Titanium.UI.ScrollView object.
See the docs:
https://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.ListView
https://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.RefreshControl
Sample code taken from the docs:
var win = Ti.UI.createWindow({
fullscreen:true
});
var counter = 0;
function genData() {
var data = [];
for (var i=1; i<=3; i++) {
data.push({properties:{title:'ROW '+(counter+i)}})
}
counter += 3;
return data;
}
var section = Ti.UI.createListSection();
section.setItems(genData());
var control = Ti.UI.createRefreshControl({
tintColor:'red'
})
var listView = Ti.UI.createListView({
sections:[section],
refreshControl:control
});
control.addEventListener('refreshstart',function(e){
Ti.API.info('refreshstart');
setTimeout(function(){
Ti.API.debug('Timeout');
section.appendItems(genData());
control.endRefreshing();
}, 2000);
})
win.add(listView);
win.open();
Is this just the IOS code form the Kitchen Sink example?
There are a couple of attempts at getting this working on Android, though I haven't confirmed that any of them work as expected. From what I understand, the problem is that you can't get the offset the same way in Android as in IOS.
A quick Google search turned up this link, which was referenced from the official Appcelerator forums.
https://gist.github.com/903895

Why is the link element's onload attribute unreliable for android stock browsers?

var style1 = document.createElement("link");
style1.id = "rel";
style1.rel = "stylesheet";
style1.href = "http://www.mysite.com/css.css";
style1.onload = function(){document.body.innerHTML+="fffffff";};
document.getElementsByTagName("head")[0].appendChild(style1);
This code works in Chrome/Firefox, and yet stock browsers on my Froyo (2.3) and Jellybean (4.1) Android devices will print nothing. What's the problem? I'd like if I could execute some js onload of a link. Anything else would in my case amount to a hack. :/
The problem isn't innerHTML. Try it with alerts if you want (at your own peril).
Another answer mentions checking for this functionality by doing
var huh = 'onload' in document.createElement('link');
..but this is true in both stock browsers! wtf guys?
Android browser doesn't support "onload" / "onreadystatechange" events for element: http://pieisgood.org/test/script-link-events/
But it returns:
"onload" in link === true
So, my solution is to detect Android browser from userAgent and then wait for some special css rule in your stylesheet (e.g., reset for "body" margins).
If it's not Android browser and it supports "onload" event- we will use it:
var userAgent = navigator.userAgent,
iChromeBrowser = /CriOS|Chrome/.test(userAgent),
isAndroidBrowser = /Mozilla\/5.0/.test(userAgent) && /Android/.test(userAgent) && /AppleWebKit/.test(userAgent) && !iChromeBrowser;
addCssLink('PATH/NAME.css', function(){
console.log('css is loaded');
});
function addCssLink(href, onload) {
var css = document.createElement("link");
css.setAttribute("rel", "stylesheet");
css.setAttribute("type", "text/css");
css.setAttribute("href", href);
document.head.appendChild(css);
if (onload) {
if (isAndroidBrowser || !("onload" in css)) {
waitForCss({
success: onload
});
} else {
css.onload = onload;
}
}
}
// We will check for css reset for "body" element- if success-> than css is loaded
function waitForCss(params) {
var maxWaitTime = 1000,
stepTime = 50,
alreadyWaitedTime = 0;
function nextStep() {
var startTime = +new Date(),
endTime;
setTimeout(function () {
endTime = +new Date();
alreadyWaitedTime += (endTime - startTime);
if (alreadyWaitedTime >= maxWaitTime) {
params.fail && params.fail();
} else {
// check for style- if no- revoke timer
if (window.getComputedStyle(document.body).marginTop === '0px') {
params.success();
} else {
nextStep();
}
}
}, stepTime);
}
nextStep();
}
Demo: http://codepen.io/malyw/pen/AuCtH

Categories

Resources