device.uuid undefined in PhoneGap on Android? - android

I'm writing a PhoneGap application that sends requests to a central database. It needs to be able to identify the unique devices that connect to it.
PhoneGap's device.uuid property would seem to do the trick. On webOS and iPhone, I get back a unique string of alphanumeric characters, which will satisfy my need. However, the Android devices I've tested (Motorola Droid and the Android SDK emulator, both running Android 2.1) return "undefined" as the device.uuid.
device.platform and device.name return correct values on all three platforms, so the problem doesn't have to do with the device object itself (it's defined in the code blocks where I use it).
Is this an Android limitation? A problem with PhoneGap?
Is there any other way to get such a globally unique identifier if not through device.uuid?
EDIT: It appears that the deviceready event is never getting fired, which needs to happen before the device.uuid property becomes available.

Depending on Phonegap version and/or device, you might need to install the plugin explicitly. In our project, device was present but device.uuid was undefined. Running cordova plugin add org.apache.cordova.device fixed the issue in our case.

I haven't yet found a solution for this, but it is worth noting that this issue is fixed in Android 2.2. But other than that, you'll have to find some other way of getting a unique device identifier if the device is running 2.1 or earlier.

I had the same problem. It was working previously, and I eventually traced the problem back to the manifest permissions.
If android.permission.ACCESS_NETWORK_STATE is not enabled, deviceready will not fire, and device.uuid will not be available.

this works for me:
first installation of device plugin:
cordova plugin add cordova-plugin-device
and in my index.js i have this:
var app = {
initialize: function() {
$.support.cors = true;
this.bindEvents();
},
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
onDeviceReady: function() {
app.receivedEvent('deviceready');
},
receivedEvent: function(id) {
console.log('Received Event: ' + id);
},
getDeviceInfo: function() {
var aio = new Object();
aio.agent = device.platform + "," + device.version + "," + device.model;
aio.deviceid = device.uuid;
return aio;
}
};
app.initialize();
module.controller('AppController',function($scope) {
console.log('GOOOO');
ons.ready(function() {
console.log("ons ready");
var appInfoObj = app.getDeviceInfo();
console.log("Agent: " + appInfoObj.agent);
console.log("UUID: " + appInfoObj.deviceid);
});
});

Related

Phonegap compass plugin not working

I am trying to get a compass function working on my app with no success. Judging by the errors I am inclined to think that the plugin is not being added or the device is not ready. But as far as I can tell I have done both things. I am using phonegap build, so the only code I use to include it is:
<gap:plugin name="org.apache.cordova.device-orientation" version="0.3.9" />
Which as far as I know is all that is required. When I click on the plugins tab in the phonegap build page for my app it shows up as being there.
watchDirection = null;
//Phonegap is ready
var whenDeviceReady = function(){
console.log("deviceready");
console.log(navigator.compass);
var findMyDirection = function(){
console.log("find my heading fired");
watchDirection = navigator.compass.watchHeading(
//onSuccess
function(heading){
console.log(heading);
var magnetDirection = heading.magneticHeading;
$("#movingCompass").css("transform", "rotate(" + magnetDirection + "deg)");
},
//onError
function(error){
console.log('code: ' + error.code +' message: ' + error.message);
},
//Update Frequency
{ frequency: 1000});
}
findMyDirection();
}
//Wait for phonegap to load
document.addEventListener("deviceready", whenDeviceReady, false);
The above code works as expected with the exception of the compass object. The console.log(navigator.compass); returns as undefined. And there is an error on the line which includes watchDirection = navigator.compass.watchHeading( saying Uncaught TypeError: Cannot read property 'watchHeading' of undefined.
It gets listed in the phonegap build list of installed plugins, and I already have the geolocation working with the same code format I have posted above.
#Marty.H, I have working demos here: http://codesnippets.altervista.org/examples/phonegap/demos/PUBLIC.Apps.html Go to the lower half of the page and try pre-built app, Phonegap-Compass-Test. If it works, the top half of the page has the links to github where you can get the source code. --Jesse

Protractor's waitForAngular() fails on angular-webapp (appium/chrome on real device)

I'm (newly) using protractor to run e2e cucumber tests.
I got a web-app which is angularJS based. I'm using appium to remotely run the test on a real android device. Here are the versions i'm using :
windows8.1
protractor#1.3.1 (with submodule selenium-webdriver#2.43.5)
appium#1.3.0beta1
android device with 4.4.4
my protractor configuration (extracts), corresponding to https://github.com/angular/protractor/blob/master/docs/browser-setup.md:
currentDeviceUDID = (...);
var appToTestURL = 'http://my.website.com:9000/app/index.html';
exports.config = {
seleniumAddress: 'http://localhost:4723/wd/hub';
chromeOnly: false,
specs: ['features/sample.feature'],
capabilities: {
browserName: 'chrome',
'appium-version': '1.0',
platformName: 'Android',
platformVersion: '4.4.4',
udid: currentDeviceUDID
},
baseUrl: appToTestURL
framework: 'cucumber',
cucumberOpts: {
require: 'features/stepDefinitionsSample.js',
tags: '#dev',
format: 'progress'
},
// configuring wd in onPrepare
onPrepare: function () {
var wd = require('wd'),
protractor = require('protractor'),
wdBridge = require('wd-bridge')(protractor, wd);
wdBridge.initFromProtractor(exports.config);
},
allScriptsTimeout: 30000,
getPageTimeout: 30000
};
As you can see, i have replaced the protractor's webdriver url with the appium webdriver. i start the appium from commandline with "appium &", then i run the test with "protactor cucumbertest.conf"
The phone opens chrome browser and navigates to the url i give it with "browser.get(url)"
the problem is the following:
the call waitForAngular(), which is asynchronously waiting for the website to load and on all open http request (as far as i understand), is not executed sucessfully on the phone. the phone does not react to the call, and the webdriver proxy returns a 500.
Corresponding to https://github.com/angular/protractor/issues/1358, i understood that the waitForAngular() function is mixed in protractor into the calls
['getCurrentUrl', 'getPageSource', 'getTitle'];
Behind waitForAngular() in the file protractor.js is the function below, which is proxied to the phone:
functions.waitForAngular = function(selector, callback) {
var el = document.querySelector(selector);
try {
if (angular.getTestability) {
angular.getTestability(el).whenStable(callback);
} else {
angular.element(el).injector().get('$browser').
notifyWhenNoOutstandingRequests(callback);
}
} catch (e) {
callback(e);
}
};
Additional information: when i stimulate an error on the webdriver (browser) object, the error message points to the chromedriver.exe inside the protractor directory. i dont understand why the error is not from appium's chromedriver
so tldr;
without the successful call waitForAngular, i cannot (stable or at all) access elements on the page on the phone, so not testing. maybe im misunderstanding some fundamental configuration detail here, all hints are welcome.
edit: added appium server logs here: http://pastebin.com/vqBGUdXH
I assume i have identified the problem. Appium and Protractor work fine.
My angularJS app causes the issue. It uses $timeout for polling (im forced on angular 1.07 which has no $interval). This causes protractor to expect the page to be still in the loading stage and not finished. Therefore the function call waitForAngular() never returns and the test timeouts after the specified timeout-timespan.
This behaviour is expected and known, also documented (better read doc first ;) ) at http://angular.github.io/protractor/#/timeouts
The doc suggests the following for continuous polling: replace $timeout with $interval:
If your application continuously polls $timeout or $http, it will never be registered as completely loaded. You should use the $interval service (interval.js) for anything that polls continuously (introduced in Angular 1.2rc3).
For now, i fixed the issue another way: disable the built-in angular sync and manually sync
this.Before(function(next){
ptor = protractor.getInstance();
ptor.ignoreSynchronization = true; //disables waitForangular()
next();
});
Sync method 1:
//at a testcase, wait for an element to be visible with a promise/then
browser.wait(function () {
element.all(by.css('.myCssClass')).then(function (items) {
items[0].getText().then(function (text) {
console.log(text);
});
});
return true;
}
Sync method 2 :
// "eventually" (chai-as-promised) internally uses "promise" (and therefore acts like "then")
browser.get(url);
expect(browser.getTitle()).to.eventually.equal("connect me").and.notify(next);

Phonegap Detect Device GPS Status

After hours of search I finally decided to post a question here.
I am using cordova/phonegap version 3 library and trying to build an app based on geolocation.
What I need to do is to check if the user has their GPS enabled before they can do something else but this doesn't seems to be possible as far as i can see.
The code I am using is:
function onDeviceReady() {
// Throw an error if no update is received every 30 seconds
var options = {maximumAge: 0, timeout: 10000, enableHighAccuracy: true};
watchID = navigator.geolocation.watchPosition(onSuccess, onGeoError, options);
}
function onSuccess(position) {
//DO WHATEVER
}
function onGeoError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
I expect an error to be thrown with error.POSITION_UNAVAILABLE message but no matter what I do TIMEOUT error (error.TIMEOUT) gets thrown every single time. I even put the device in flight mode with everything (gps, etc) turned off and still got TIMEOUT error.
Can anyone please suggest a better way to achieve this.
The problem with my application was that I didn't run the build command (cordova prepare) after installing the plugin. Backup your www folder before running 'cordova build' command as this will replace www folder with default content

phonegap android app only showing connecting to device

I AM creating a phonegap android app. I am creating this app using help of this tutorial. When i am istalling this app on device its onDeviceReady function is not working. It is only showing coneecting to device. My onDeviceReady function is below:-
onDeviceReady: function() {
app.receivedEvent('deviceready');
alert('device ready');
try {
var pushNotification = window.plugins.pushNotification;
pushNotification.register(app.successHandler, app.errorHandler,{"senderID":"41327727848","ecb":"app.onNotificationGCM"});
} catch (ex) {
alert('error: ' + ex);
}
},
It does not alert anything. I can't find the error.
Here are the suggestions you can try:
make sure you have added cordova.js into your html file.
deviceready function should be called after cordova.js is loaded.
the link you've provided is using old version version of plugin.(link-old plugin).I advice you to follow the new one which is this

phonegap geolocation always fail on timeout

I'm using sencha-touch 2.0 and phonegap 2.0.0 in my app to retrieve user's location.
When runing on my locahost, everything works just fine. However, when loading the .apk to my android 15 api's device (using eclipse and the adt plugin), every call to getCurrentLocation or watchPosition never returns...
here is my code:
geoOn: function(){
var geoReady = navigator.geolocation || undefined;
var onSuccess = function(position){
Top5.app.alert('Geolocation success '+String(position.coords.latitude) + ' ' + String(position.coords.longitude),'Geolocation');
var scope = Ext.getCmp('nestedList');
scope.updateDistance(position.coords);
};
var onFailure = function(error){Top5.app.alert('Geolocation failed: '+String(error.code) + ' '+String(error.message),'Geolocation');};
if (geoReady) {
this.watchId = navigator.geolocation.watchPosition(onSuccess ,onFailure,{timeout:6000,maximumAge: 3000,enableHighAccuracy: true});
}
else{
Ext.device.Geolocation.watchPosition({
frequency: 3000, // Update every 3 seconds
callback: function(position) {
this.updateDistance(position.coords);
},
failure: function() {
console.log('Geolocation Failure!');
},
scope:this
});
}
},
geoGet: function(){
var geoReady = navigator.geolocation || undefined;
if (geoReady) {
var onSuccess = function(position){
Top5.app.alert('Geolocation successful!!!');
var scope = Ext.getCmp('nestedList');
scope.updateDistance(position.coords);
};
var onFailure = function(error){Top5.app.alert('Geolocation failed: '+String(error.code) + ' '+String(error.message),'Geolocation');};
navigator.geolocation.getCurrentPosition(onSuccess,onFailure);
}
else{}
},
geoOff:function(){
var geoReady = navigator.geolocation || undefined;
if (geoReady) {
navigator.geolocation.clearWatch(this.watchId);
this.watchId = null;
}
else{
Ext.device.Geolocation.clearWatch();
}
},
updateDistance:function(coords){
Top5.app.alert('updateDist','');
var scope = Ext.getCmp('nestedList');
var lat = coords.latitude,lon = coords.longitude;
var store = scope.getStore();
var i,record;
for(i = 0; i < store.data.all.length; i++)
{
record = store.data.all[i];
if(record.data.locationX){
record.set('distance',Top5.app.getDistance(record.data.locationX,record.data.locationY,lat,lon).toFixed(3));
}
}
}
UPDATE: So I walked out of my building and it worked... I need to go outside more often.
However, when I'm disabling the gps, I thought geoLocation will find my location using wifi connection - but it failes (I'm setting enableHighAccuracy: false). Why is that?
UPDATE: Let me rephrase my question:
Does navigator.geolocation.watchPosition suppose to work both with GPS signal and wifi/g3 signals? How can I detect user location using internet connection only? currently, my code is working only with GPS, and when that option disabled or signal is blocked, geolocation isn't working.
I know that maybe it is too late, but today i struggled with the same issue! The solution turned out to be very simple!
SOLUTION: Reboot the device.
That's all.
The problem is, that you never know when i user will get this kind of bug, so if your application relies heavily on geolocation i recommend you set a timeout in location options navigator.geolocation.getCurrentPosition(geoSuccess, geoError, {timeout: 15000}) and alert user about the problem and possible solution.
P.S.
Keep in mind, that Geolocation can timeout for example if mobile data is turned off too, so reboot won't always fix it. On iPhone it uses cellular data to get your position, but on Android, it looks like the phone does not have access to cellular data unless 3G is turned on
It could sound stupid, but, did you activate the "Use Networks" option?
Go to Settings -> Location and security -> Use networks; and active it. I have passed all the afternoon watching the problem and it was that.
I restarted and restarted. I reset my phone to factory settings.
But nothing worked.
Until I set enablHighAccuracy from true to false.
And... Tada.... it works.
So :
var options;
options = {
maximumAge: 30000,
timeout: 5000,
enableHighAccuracy: false
};
This used to work fine using PhoneGap 2.6.0. I needed to make this change since I'm now using Phonegap 3.3 - tested on a Wiko Cink+ phone.
Try removing the Phonegap plugin geolocation plugin from your project. You won't need to make any changes to your JavaScript code as your device will fall back on the standard HTML5 navigator.geolocation functionality which has the same method signature.
Assuming you're using PhoneGap 3.3, you just need to run:
cordova plugin rm org.apache.cordova.geolocation
If you are running on an emulator, it may be because the device does not have a geolocation set. Try setting the location by running the following, assuming your android emulator is on port 5554:
telnet localhost 5554
geo fix -0.001 51.5
Restart your phone or Go to google map and check if gps is working over there.
I got it working.
I had this happen to a working app after updating PhoneGap to version 3.6.3 from 3.5. After trying many other suggestions Arthur's answer worked. 15 seconds seemed too long to me so I used {timeout: 2000}. I'm guessing the new version is slower as my code worked fine before the update on the same devices. Thought I'd post as well as upvote him as everything I found in Google was about initial setup and mostly irrelevant to my situation.
You just need to add enableHighAccuracy: true, maximumAge: 60000 and then reboot your device.
From my trial and error analysis, its most likely:
1. The version of android you're using. On Lollipop and lower you may need to go to the phones location settings and enable high accuracy settings (using gps, wlan and mobile networks to get location). I had to do this on a kitkat phone.
2. As others have mentioned, you can try changing the settings of getCurrentPosition by either enabling/disabling highaccuracy and adding a timeout.
3.If you're using ngCordova, make sure you installed it right and the location functions are actually being called. Use console to verify
Try This Solution:
window.setInterval(checkPosition, 5000);
function checkPosition() {
function onSuccess(position) {
document.getElementById('result1').innerHTML = position.coords.latitude;
document.getElementById('result2').innerHTML = position.coords.longitude;
}
// onError Callback receives a PositionError object
//
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
I've managed to work it out.... However , I have no idea what actually solved it. All I've done is to change one of my model's structure. Can anyone see the connection to geolocation?

Categories

Resources