JSONStore code not working - android

I am trying to learn JSONStore and in process of that I am trying to execute a piece of code which will first check if a particular JSONStore is already there in the device or not and based on the result it will execute if-else statement. If it is not there, it will create one and add some data in it. In case the jsonStore is already present, code will replace the previously stored data with new data. But when I am trying to execute the code, my device shows the html contents for a while and then the screen gets blank. When I checked the logcat, I didn't get any of my console log statements which I have added in my code. Can anyone please help me in understanding this behavior and what could be done to achieve the requirement.
var JSONStoreCollections = {};
var collectionName = 'Person';
function wlCommonInit(){
require([ "layers/core-web-layer", "layers/mobile-ui-layer" ], dojoInit);
}
function dojoInit() {
require([ "dojo/ready", "dojo/parser", "dojox/mobile", "dojo/dom", "dijit/registry", "dojox/mobile/ScrollableView" ], function(ready) {
ready(function() {
if(!(WL.JSONStore.get(collectionName))){
console.log("i am in if codition");
var Data={
Name:'name',
Age:27
};
JSONStoreCollections[collectionName] = {};
JSONStoreCollections[collectionName].searchFields = {Name: 'string'};
WL.JSONStore.init(JSONStoreCollections)
.then(function () {
console.log("store created");
})
.fail(function (errorObject) {
console.log("store creation failed");
});
WL.JSONStore.get(collectionName).add(Data)
.then(function () {
console.log("data added");
})
.fail(function (errorObject) {
console.log("data addition failed");
});
var query = {Name: 'name'};
WL.JSONStore.get(collectionName)
.find(query)
.then(function (arrayResults) {
console.log(arrayResults);
WL.Logger.debug(arrayResults);
})
.fail(function (errorObject) {
console.log(errorObject);
WL.Logger.debug(errorObject);
});
}
else{
var Data1={
Name:'name1',
Age:30
};
WL.JSONStore.get(collectionName).replace(Data1)
.then(function () {
console.log("data replaced");
})
.fail(function (errorObject) {
console.log("data replacement failed");
});
var query = {Name: 'name1'};
WL.JSONStore.get(collectionName)
.find(query)
.then(function (arrayResults) {
console.log(arrayResults);
WL.Logger.debug(arrayResults);
})
.fail(function (errorObject) {
console.log(errorObject);
WL.Logger.debug(errorObject);
});
}
});
});
}

You need to initialize first, otherwise WL.JSONStore.get(collectionName) will always return undefined. If you never initialize JSONStore, you can not use it.
The replace API works with JSONStore documents (objects that have keys for _id and json).
You only need one .fail, the error object will tell you the source of the error (errorObject.src).
See the untested pseudocode below for what you want to do:
function wlCommonInit () {
var collectionName = 'Person';
var Data = {
Name: 'name',
Age: 27
};
var JSONStoreCollections = {};
JSONStoreCollections[collectionName] = {};
JSONStoreCollections[collectionName].searchFields = {Name: 'string'};
WL.JSONStore.init(JSONStoreCollections)
.then(function () {
WL.Logger.debug('Init done');
return WL.JSONStore.get(collectionName).findAll();
})
.then(function (res) {
WL.Logger.debug('Find All returned:', res);
if (res.length < 1) {
return WL.JSONStore.get(collectionName).add(Data);
} else {
res[0].json = {
Name:'name1',
Age:30
};
return WL.JSONStore.get(collectionName).replace(res[0]);
}
})
.then(function () {
WL.Logger.debug('Add or Replace done');
return WL.JSONStore.get(collectionName).find({Name: 'name'});
})
.then(function (res) {
WL.Logger.info('Final Find returned:', res);
})
.fail(function (err) {
WL.Logger.error(err);
});
}
Expected output the first time executed:
Init done
Find All returned: []
Add or Replace done
Final Find returned: [{"_id":1,"json":{"Name":"name","Age":27}}]
Expected output other than the first time executed:
Init done
Find All returned: [{"_id":1,"json":{"Name":"name","Age":27}}]
Add or Replace done
Final Find returned: [{"_id":1,"json":{"Name":"name1","Age":30}}]

Related

Calling cloud function admin.auth().createUser() from android does not work

I am trying to call a Google cloud function from an Android app that does not work (First call just after deployment works 90 % of the times but subsequent calls fails, nothing is displayed on firebase log console either).
public Task<String> myCloudFunction() {
return FirebaseFunctions.getInstance()
.getHttpsCallable("createUser")
.call(data)
.continueWith(task -> {
String result = (String) task.getResult().getData();
return result;
});
}
Endpoint in Functions Dashboard
https://us-central1-xyz:555.cloudfunctions.net/createUser
This is how I call it.
public void callCloudFunction() {
createFirebaseUserAccount.myCloudFunction()
.addOnCompleteListener(new OnCompleteListener<String>() {
#Override
public void onComplete(#NonNull Task<String> task) {
if (!task.isSuccessful()) {
Exception e = task.getException();
if (e instanceof FirebaseFunctionsException) {
FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
FirebaseFunctionsException.Code code = ffe.getCode();
Object details = ffe.getDetails();
} else {
Timber.d(task.getResult());
}
}
}
});
}
Here is the cloud function:
$GOOGLE_APPLICATION_CREDENTIALS is pointing to service_key.json file which contains the private key.
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: "https://XYZ.firebaseio.com"
});
exports.createUser = functions.https.onCall((data, context) => {
const callerEmail = data.email;
const callerPassword = data.password;
const callerDisplayName = data.displayName;
return admin.auth().createUser({
email: callerEmail,
emailVerified: false,
password: callerPassword,
displayName: callerDisplayName,
disabled: false
}).then(userRecord => {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully created new user:", userRecord.uid);
return userRecord.uid;
}).catch(error => {
console.log("Error creating new user ", error);
return error;
});
});
Thanks for reading! :)
You're not returning a promise from the the function that contains the data to send to the client. Actually, you're not passing anything at all. You should instead return the promise chain from your async work:
return admin.auth().createUser({
email: callerEmail,
emailVerified: false,
password: callerPassword,
displayName: callerDisplayName,
disabled: false
}).then(userRecord => {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully created new user:", userRecord.uid);
return userRecord.uid;
}).catch(error => {
console.log("Error creating new user ", error);
return error;
});
Note the new return before the whole thing. You should definitely take some time to learn about how JavaScript promises work in order to make effective use of Cloud Functions, and they will not work correctly without observing their rules and conventions.

React Native, AWS, Error only on Android "TypeError: Cannot read Property 'handle' of null"

I ran into a bug whenever I run my React Native app on an Android device (physical and emulator). Yet, no problem at all on iOS. These functions are supposed to scan the database table for user handles and return an object if the handle already exists.
This is what the error looks like:
TypeError: Cannot read property 'handle' of null
at exports.handler (/var/task/index.js:7:36)
I'm using React Native, AWS Lambda, and EXPO.
This code lives within dbfunctions.js on the front end.
export async function scanHandles(){
return new Promise((resolve, reject) => {
let { auth } = store.getState()
let reqBody = {
userId: auth.user.username,
handle: auth.handle_update,
}
let path = '/u/scan-handle'
let myInit = {
headers: { 'Content-Type': 'application/json' },
body: reqBody,
}
console.log('myInit', myInit)
console.log('handle', auth.handle_update)
API.get(apiName, path, myInit)
.then((resp) => {
// if false, then handle does not exist
// if true, then handle already exists
resolve(resp)
})
.catch((error) => {
console.warn('Scan Handle', error)
reject(error)
})
})
}
Console logging auth.handle_update does print out the expected string. myInit also prints out the expected object.
On the back end, I'm using this for my scan:
const AWS = require("aws-sdk");
const docClient = new AWS.DynamoDB.DocumentClient({ region: "us-west-1" });
exports.handler = (event, context, callback) => {
let e = JSON.parse(event.body);
var params = {
TableName: event.stageVariables.user,
FilterExpression: "handle = :handle",
ExpressionAttributeValues: { ":handle": e.handle }
};
docClient.scan(params, function(err, data) {
if (err) {
console.log("ERROR:", err);
let response = {
statusCode: err.statusCode,
headers: {},
body: JSON.stringify(err)
};
callback(response);
}
if (data.Count >= 1) {
// if user name exists
// call back handle exists response
let handleExistsResponse = {
statusCode: 200,
body: JSON.stringify({ Success: true })
};
callback(null, handleExistsResponse);
} else {
let response = {
statusCode: 200,
body: JSON.stringify({ Success: false })
};
callback(null, response);
}
});
};
Any idea as to why this would work on iOS and not Android?
EDIT:
Upon further testing, let e = JSON.parse(event.body) is returning null. So I console logged event and got a big ol object. Within this object, I found body and it's still null. So the body object isn't being passed it properly. Still confused about it working on iOS and not Android.
Did it!
Okay so API.get doesn't like body's being passed in. Instead, it wants a query parameter. So the lambda params looks like:
var params = {
TableName: event.stageVariables.user,
FilterExpression: "handle = :handle",
ExpressionAttributeValues: {
":handle": event["queryStringParameters"]["handle"]
}
};
And the front end function is:
export async function scanHandles(){
return new Promise((resolve, reject) => {
let { auth } = store.getState()
let handle = auth.handle_update
let path = `/u/scan-handle?handle=${handle}`
let myInit = {
headers: { 'Content-Type': 'application/json' },
}
API.get(apiName, path, myInit)
.then((resp) => {
// if false, then handle does not exist
// if true, then handle already exists
resolve(resp)
})
.catch((error) => {
console.warn('Scan Handle', error)
reject(error)
})
})
}
Works on both iOS and Android. Wonder why it wasn't working before?

TypeError: _this2.setState is not a function, Cant bind state

I am getting this this error. As I am already using ES6 format, That arrow but also getting same error. And somewhat confuse that how to use bind. How can I get out of this error.
code:
async fetchData() {
const { navigate } = this.props.navigation;
var DEMO_TOKEN = await AsyncStorage.getItem(STORAGE_KEY);
NetInfo.isConnected.fetch().then((isConnected) => {
if ( isConnected )
{
return fetch(`${url}`,
{
method: "GET",
headers: {
'Authorization': `JWT ${DEMO_TOKEN}`,
}
})
.then(
function(response) {
console.log(response.headers);
console.log(response.status);
console.log(response.url);
if (response.status !== 200) {
console.log('Status Code: ' + response.status);
return;
}
response.json().then((responseData) => {
console.log(responseData);
this.setState({
ver: responseData.results.appversion, // getting error here
});
});
}
)
.catch(function(err) {
console.log('Fetch Error', err);
});
Just to be clear about which this you're trying to reference, could you do this?
async fetchData() {
const ctx = this
And then reference ctx instead of this:
ctx.setState({
ver: responseData.results.appversion,
});

Android SQ Lite - How to insert more than 1000 rows at a time efficiently?

I am using Ionic Framework. I want to ask for help about how to insert more than 1000 rows at a time and while insertion showing a loading spinner to user so that there wont be any mess in database.
First, I have two services/factories.
Database :
.factory('DB', function ($ionicPopup, $cordovaSQLite, $q, $ionicPlatform, $cordovaNetwork,$ionicLoading) {
var self = this;
self.query = function (query, parameters) {
parameters = parameters || [];
var q = $q.defer();
$ionicPlatform.ready(function () {
$cordovaSQLite.execute(db, query, parameters)
.then(function (result) {
console.log(result);
q.resolve(result);
}, function (error) {
console.log(error+" .."+error.message);
alert('I found an error' + error.message);
q.reject(error);
});
});
return q.promise;
}
// Proces a result set
self.getAll = function (result) {
var output = [];
for (var i = 0; i < result.rows.length; i++) {
output.push(result.rows.item(i));
}
return output;
}
// Proces a single result
self.getById = function (result) {
var output = null;
output = angular.copy(result.rows.item(0));
return output;
}
return self;
})
Secondly, AsyncService for downloading data from multiple urls
.service('asyncService', function ($http, $q) {
return {
loadDataFromUrls: function (urls) {
alert("I am inside new Service ");
var deferred = $q.defer();
var urlCalls = [];
angular.forEach(urls, function (url) {
urlCalls.push($http.get(url.url));
});
// they may, in fact, all be done, but this
// executes the callbacks in then, once they are
// completely finished.
$q.all(urlCalls)
.then(
function (results) {
deferred.resolve(results)
},
function (errors) {
console.log(errors);
deferred.reject(errors);
},
function (updates) {
console.log(updates);
deferred.update(updates);
});
return deferred.promise;
}
};
})
And the method that firstly, should download the datas and then insert them into their belonged tables.
asyncService.loadDataFromUrls(urLs).then(function (result) {
DB.query("DELETE FROM INV");
// when i have to update the tables, i first delete them and then fill them back again.
$ionicLoading.show({
template : 'Processing into Database. Please Wait...',
timeout : '6000'
});
result.forEach(function (rows) {
console.log(rows.config.url);
var i = 0;
if (rows.config.url == 'http://11.444.222.55:55/mobil_op?op=get_inv') {
rows.data.forEach(function (entry) {
var parameters = [entry.code, entry.name,];
DB.query("INSERT INTO INV (CODE,NAME,......) VALUES(?,?........)",parameters);
})
}
})
}, function (err) {
alert("OOpsss ! : " + err.message);
console.log("error");
}, function (updates) {
alert("updates");
console.log("updates" + updates);
})
How should I work while inserting 4453 elements into array ?
db.executeSql("BEGIN TRANSACTION",{})
.then(( res )=> {
console.log(res);
// DO ALL INSERTION ON THE TABLES
// e.g
// AT LAST
db.executeSql("COMMIT",{})
.then(()=> console.log("COMMIT")
.catch(e => console.log(e));
}).catch(e => console.log(e));
// This process provided me much more faster way . The method above in the question dialog was inserting 4553 items in 3 minutes on Asus Zenphone 1. This method let me insert 10000 items less then 3 minutes.

How to pass a value between factorys in Ionic?

I need yours help.
I have two .factory's in Services.js
The first .factory works with a database, the second .factory with e-mail, files and so on.
How to pass a value from first factory to second? How to select data from the first factory?
//first factory
angular.module('starter.services', ['ngCordova', 'ngSanitize', 'ngCsv'])
.factory('NotesDataService', function ($cordovaSQLite, $ionicPlatform) {
var db, dbName = "CONTACTS_DB"
function useWebSql() {
db = window.openDatabase(dbName, "1.0", "Contacts database", 200000)
console.info('Using webSql')
}
function useSqlLite() {
db = $cordovaSQLite.openDB({name: dbName, location : 1})
console.info('Using SQLITE')
}
function initDatabase(){
$cordovaSQLite.execute(db, 'CREATE TABLE IF NOT EXISTS T_CONTACTS (id integer primary key, nom, prenom, codePostale, ville, email, portable)')
.then(function(res){
}, onErrorQuery)
}
$ionicPlatform.ready(function () {
if(window.cordova){
useSqlLite()
} else {
useWebSql()
}
initDatabase()
})
function onErrorQuery(err){
console.error(err)
}
return{
getAll: function(callback){
$ionicPlatform.ready(function () {
$cordovaSQLite.execute(db, 'SELECT * FROM T_CONTACTS').then(function (results) {
var data = []
for (i = 0, max = results.rows.length; i < max; i++) {
data.push(results.rows.item(i))
}
callback(data)
}, onErrorQuery)
})
}})
//second factory, here I need to get data from first factory
//to create a text file with the data from the database
// and attach this file to the e-mail
.factory('ContactsService', function ($ionicPlatform, $cordovaEmailComposer, $cordovaSQLite, $cordovaFile, NotesDataService) {
$ionicPlatform.ready(function () {
initCordovaEmailComposer();
})
function initCordovaEmailComposer() {
$cordovaEmailComposer.isAvailable().then(function () {
//is available
alert('avaible');
}, function () {
//not available
alert('not available');
})
}
return {
createEmail: function () {
var email = {
to: 'test#gmail.com',
cc: 'test#gmail.com',
bcc: 'test#gmail.com',
attachments: [
'file://cordova.file.externalDataDirectory/contacts.txt',
],
subject: 'Cordova Icons',
body: "Hello, mon ami",
isHtml: true
};
$cordovaEmailComposer.open(email).then(null, function () {
});
},
debugMessage: function (data) {
console.log('debug message', data);
},
createFile: function () {
var fileContacts = document.addEventListener('deviceready', function () {
NotesDataService.getAll(function (data) {
console.log(data)
return data
})
console.log('file contacts in console: ',fileContacts)
var fileName = 'contacts.txt'
var fileText = fileContacts
var filePath = cordova.file.externalDataDirectory
//CHECK file
$cordovaFile.checkFile(filePath, fileName).then(function (success) {
alert("file exist")
}, function (error) {
alert("file not exist", filePath)
//WRITE NEW FILE
$cordovaFile.writeFile(cordova.file.externalDataDirectory, fileName, fileText, true).then(function (success) {
// success
}, function (error) {
// error
});
});
})
},
}
})
Thank you all for your advice and support
Inject these factories into one another :
.factory('NotesDataService',['$cordovaSQLite','$ionicPlatform','ContactsService', function ($cordovaSQLite, $ionicPlatform,ContactsService) ....
.factory('ContactsService',['$ionicPlatform',.....,'NotesDataService', function ($ionicPlatform, $cordovaEmailComposer, $cordovaSQLite, $cordovaFile, NotesDataService) {
Now you can use either factory variables and functions in other factory.

Categories

Resources