cordova background geolocation plugin on reboot - ionic-framework

I am building an ionic app with background geolocation plugin https://github.com/mauron85/cordova-plugin-background-geolocation.
I want to make an app to send its location after reboot. The plugin I am using seems to have the option, but it is not working properly. An app only sends its location to the server only after execute an app at least once after every boot.
Any help or suggestion would be appreciated. Thank you in advance!
My code is below
Configuration
backgroundGeolocation.configure(callbackFn, failureFn, {
locationProvider: backgroundGeolocation.provider.ANDROID_ACTIVITY_PROVIDER,
desiredAccuracy: 10,
stationaryRadius: 10,
distanceFilter: 10,
interval: 60000,
maxLocations: 50,
startOnBoot: true, // from my understanding, this should make an app track its location even after reboot
stopOnTerminate: false
});
Callback Function
var callbackFn = function(location) {
console.log('[js] BackgroundGeolocation callback: ' + location.latitude + ',' + location.longitude);
// Do your HTTP request here to POST location to your server.
var link = API_URL;
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
$http({
method: 'POST',
url: link,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
params: {
'device': 'android',
},
data: {
lat:location.latitude,
lng:location.longitude,
}
}).success(function(data){
console.log(data);
}).error(function(data){
console.log(data);
});
backgroundGeolocation.finish();
};

i hope you would have found your answer by now, posting this might help others too.
don't expect your callback to be executed after the reboot, as the activity might be killed, instead use url option of the plugin to continue sending your location updates to the server.

Related

Sending voip push notification from one signal triggered firebase cloud functions

I`m trying to send Voip push notification from one signal triggered by firebase cloud functions. So far it being able to send normal message push notifications from one signal to IOS devices using firebase cloud functions with below code.
var sendNotification = function(data) {
var headers = {
"Content-Type": "application/json; charset=utf-8"
};
var options = {
host: "onesignal.com",
port: 443,
path: "/api/v1/notifications",
method: "POST",
headers: headers
};
var https = require('https');
var req = https.request(options, function(res) {
res.on('data', function(data) {
console.log("Response:");
console.log(JSON.parse(data));
});
});
req.on('error', function(e) {
console.log("ERROR:");
console.log(e);
});
req.write(JSON.stringify(data));
req.end();
};
var message = {
app_id: "*********************",
contents: {"en": "English Message"},
include_player_ids: ["******************7b0bdc38"]
};
sendNotification(message);
Does anyone know how to send Voip push notifications from one signal using firebase cloud functions??
(If the above code is required to change some part of it, it would be very thankful telling me where it is.)
As per one signal documentation (https://documentation.onesignal.com/docs/voip-notifications) you are missing the DEVICE_VOIP_TOKEN that you should have received from the iOS application.
Please try adding that and let me know, think of adding the exact error message if any.

Keep track of installed pwa instances

We want to keep track of each pwa installation for a user. So we could track notifications, like did every instance of the app user installed (pc or phone, or ff, or chrome) have received the update. Can we know the pwa instance was uninstalled? Can we know web push was delivered to every instance?
In your service worker, fire a http post to your server in the "install" event. You'll need to get your userID from indexdb or similar. Use "fetch" not xmlhttp the service worker.
self.addEventListener('install', function(e) {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then(function(cache) {
console.log('[ServiceWorker] Caching app shell');
var rc = cache.addAll(filesToCache);
postServerStatus( "installcomplete" );
return rc;
})
);
});
function postServerStatus( strStatus ) {
var strUserID = "getfromindexdb";
fetch('./datasvc.aspx', {
method: 'post',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify({
service: strStatus,
userid: strUserID
}),
});
}

Puppeteer's page.cookies() not retrieving all cookies shown in the Chrome dev tools

Using puppeteer, I am trying to retrieve all cookies for a specific web site (i.e. https://google.com) from Node.js.
My code is:
// Launch browser and open a new page
const browser = await puppeteer.launch({ headless: true, args: ['--disable-dev-shm-usage'] });
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
var cookies = await page.cookies();
console.log(cookies);
await browser.close();
It only retrieves 2 cookies, named 1P_JAR and NID. However, when I open the Chrome Dev tools, it shows a lot more.
I tried using the Chrome Dev Tools directly instead of puppeteer but I am getting the same results.
Is there another function I should call? Am I doing it correctly?
The page.cookies() call only gets cookies that are available to JavaScript applications inside the browser, and not the ones marked httpOnly, which you see in the Chrome DevTools. The solution is to ask for all available cookies through the Devtools protocol and then filter for the site you're interested in.
var data = await page._client.send('Network.getAllCookies');
You can utilise Chrome DevTools Protocol -> getAllCookies
To get all browser cookies, regardless of any flags.
const client = await page.target().createCDPSession();
const cookies = (await client.send('Network.getAllCookies')).cookies;
This will also play nice with typescript and tslint since something like
const cookies = await page._client.send('Network.getAllCookies');
Will raise an error TS2341: Property '_client' is private and only accessible within class 'Page'..
Thanks #try-catch-finally. I got it resolved and it was a simple rookie mistake.
I was comparing cookies in my own Google Chrome instance with the Puppeteer instance. However, in my instance, I was logged in to my Google account and Puppeteer (obviously) was not.
Google uses 2 cookies when you are NOT logged in and 12 when you are logged in.
If you use Playwright in place of Puppeteer, httponly cookies are readily accessible:
const { chromium } = require('playwright')
(async () => {
const browser = await chromium.launch()
const context = await browser.newContext()
const page = await context.newPage()
await page.goto('https://google.com', { waitUntil: 'networkidle' })
let allCookies = await context.cookies()
console.log (allCookies)
})();
returns:
[
{
sameSite: 'None',
name: '1P_JAR',
value: '2021-01-27-19',
domain: '.google.com',
path: '/',
expires: 1614369040.389115,
httpOnly: false,
secure: true
},
{
sameSite: 'None',
name: 'NID',
value: '208=VXtmbaUL...',
domain: '.google.com',
path: '/',
expires: 1627588239.572781,
httpOnly: true,
secure: false
}
]
Just use it await page.goto('https://google.com', { waitUntil: 'networkidle2' }). And you can get all the cookies related.

How to use botkit with facebook and wit.ai

I am a novice in chatbot development and I would like some help.
While it seems quite simple to connect botkit with facebook messenger and wit.ai in orger to use NLP. I haven't managed to do so. My initial goal is to have a simple conversation like hello-hello but using wit.ai as middleware.
Below I attach the code. What it should do is receive a "hello" message, pass it to wit.ai and then respond "I heard hello!" as a reply (without using wit at this stage). Instead I just receive
debug: RECEIVED MESSAGE
debug: CUSTOM FIND CONVO XXXXXXXXXXXXXX XXXXXXXXXXXXXX
debug: No handler for message_received
after every message I send to facebook messenger bot. In wit it seems like I am getting the messages since I receive messages in my inbox to update the intents.
If there is any code much simpler than the one below I would be very happy to have it so that I can start with something much simpler :).
Thanks
<pre><code>
if (!process.env.page_token) {
console.log('Error: Specify page_token in environment');
process.exit(1);
}
if (!process.env.page_token) {
console.log('Error: Specify page_token in environment');
process.exit(1);
}
if (!process.env.verify_token) {
console.log('Error: Specify verify_token in environment');
process.exit(1);
}
if (!process.env.app_secret) {
console.log('Error: Specify app_secret in environment');
process.exit(1);
}
var Botkit = require('./lib/Botkit.js');
var wit = require('./node_modules/botkit-middleware-witai')({
token: process.env.wit,
minConfidence: 0.6,
logLevel: 'debug'
});
var os = require('os');
var commandLineArgs = require('command-line-args');
var localtunnel = require('localtunnel');
const ops = commandLineArgs([
{name: 'lt', alias: 'l', args: 1, description: 'Use localtunnel.me to make your bot available on the web.',
type: Boolean, defaultValue: false},
{name: 'ltsubdomain', alias: 's', args: 1,
description: 'Custom subdomain for the localtunnel.me URL. This option can only be used together with --lt.',
type: String, defaultValue: null},
]);
if(ops.lt === false && ops.ltsubdomain !== null) {
console.log("error: --ltsubdomain can only be used together with --lt.");
process.exit();
}
var controller = Botkit.facebookbot({
debug: true,
log: true,
access_token: process.env.page_token,
verify_token: process.env.verify_token,
app_secret: process.env.app_secret,
validate_requests: true, // Refuse any requests that don't come from FB on your receive webhook, must provide FB_APP_SECRET in environment variables
});
var bot = controller.spawn({
});
controller.setupWebserver(process.env.port || 3000, function(err, webserver) {
controller.createWebhookEndpoints(webserver, bot, function() {
console.log('ONLINE!');
if(ops.lt) {
var tunnel = localtunnel(process.env.port || 3000, {subdomain: ops.ltsubdomain}, function(err, tunnel) {
if (err) {
console.log(err);
process.exit();
}
console.log("Your bot is available on the web at the following URL: " + tunnel.url + '/facebook/receive');
});
tunnel.on('close', function() {
console.log("Your bot is no longer available on the web at the localtunnnel.me URL.");
process.exit();
});
}
});
});
controller.middleware.receive.use(wit.receive);
controller.hears(['hello'], 'direct_message', wit.hears, function(bot, message) {
bot.reply(message, 'I heard hello!');
});
function formatUptime(uptime) {
var unit = 'second';
if (uptime > 60) {
uptime = uptime / 60;
unit = 'minute';
}
if (uptime > 60) {
uptime = uptime / 60;
unit = 'hour';
}
if (uptime != 1) {
unit = unit + 's';
}
uptime = uptime + ' ' + unit;
return uptime;
}
Make sure you have a few conversations in Wit.ai beforehand so for example hello there and highlight the hello in that statement as something like, greetings.
Now i'm not sure what your intents are called in wit.ai but in your statement controller.hears(['hello'] you're actually listening to the wit.ai intents. So in the example i mentioned above, we'd be using hears(['greetings']) since that's the intent in wit.ai.
Also, instead of using direct_message use message_received this is what it should look like:
controller.hears(['hello'], 'message_received', wit.hears, function(bot, message) {
bot.reply(message, 'I heard hello!');
});
If you're struggling tracking down the problem you can stick a console statement in your controller so something like console.log("Wit.ai detected entities", message.entities); and see what you get back from that.
Let me know if you're still having any issues :)

Error 2500 when trying to get Facebook Email in Appcelerator Titanium

I try to get email address of a user logged in via Facebook Module. But get error every time {"error":"An error code 2500 has occured. An active access token must be used to query information about the current user."}
My code is:
var viewClick = function() {
fb.logout();
fb.initialize();
fb.authorize();
};
var facebookLogged = function(e) {
fb.requestWithGraphPath("me?fields=name,email,first_name,last_name", {}, 'GET', function(result) {
Ti.API.info(JSON.stringify(result))
// var data = JSON.parse(e.result);
});
};
var window = Ti.UI.createWindow({exitOnClose: true, navBarHidden: true, fullscreen: true, orientationModes: [
Ti.UI.PORTRAIT,
Ti.UI.UPSIDE_PORTRAIT,
],
backgroundColor: '#f0f2f2'
});
var fb = require('facebook');
if(Ti.Platform.osname === 'android') {
window.fbProxy = fb.createActivityWorker({lifecycleContainer: window});
}
//fb.setLoginBehavior(fb.LOGIN_BEHAVIOR_NATIVE);
fb.permissions = ['email'];
window.open();
var view = Ti.UI.createView({
height: 200,
width: 200,
backgroundColor: 'red'
});
view.addEventListener('click', viewClick);
window.add(view);
fb.addEventListener('login', facebookLogged);
I also tried to provide access token code by modyfing requestWithGraphPath parameters:
fb.requestWithGraphPath("me?fields=name,email,first_name,last_name&access_token=" + e.source.accessToken, {}, 'GET', function(result) {}
but in such case I get infromation that accessToken is malformed.
TiFacebookModule: (main) [117,178060] requestWithGraphPath callback error: Malformed access token [Here is access token value]?access_token=[Here is access token value]
What I do wrong? How to get Email from FB? Any help deeply appreciated.
I had the same problem and this is what I do, for Android the requestWithGraphPath doesn't work like its IOS counterpart and the documentation is not updated either. You need to send the fields in the object and only the "me" in the first parameter:
var facebookLogged = function(e) {
fb.requestWithGraphPath("me", { fields: "name,email,first_name,last_name"}, 'GET', function(result) {
Ti.API.info(JSON.stringify(result))
// var data = JSON.parse(e.result);
});
};
Hope it helps.