shared SQl Lite db between phonegap app and native java app - java

I have two android apps (one written in js(using phonegap) the other in java). Both need to access one SQLite DB. Yes it's possible.
In my js file I use Cordova-sqlite-storage to create and insert data into a db:
var db = window.sqlitePlugin.openDatabase({name: "CAC.db", location: 1});
db = sqlitePlugin.openDatabase({name: "CAC.db", location: 2, createFromLocation: 1});
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data text, data_num integer)');
// demonstrate PRAGMA:
db.executeSql("pragma table_info (test_table);", [], function(res) {
console.log("PRAGMA res: " + JSON.stringify(res));
});
tx.executeSql("INSERT INTO test_table (data, data_num) VALUES (?,?)", ["MY ID", 100], function(tx, res) {
db.transaction(function(tx) {
tx.executeSql("select data as dt from test_table;", [], function(tx, res) {
var id = res.rows.item(0).dt;
console.log("res.rows.item(0).cnt: " + id);
});
});
}, function(e) {
console.log("ERROR: " + e.message);
});
});
Then I use this answer to try to connect the java app to my preexisting db:
Context sharedContext = null;
try {
sharedContext = this.createPackageContext("com.my.app", Context.CONTEXT_INCLUDE_CODE);
if (sharedContext == null) {
return;
}
} catch (Exception e) {
String error = e.getMessage();
return;
}
DbAdapter sharedDBadapter = new PerformerDbAdapter(sharedContext);
sharedDBadapter.open();
However I am required to use this code in my js app:
DBadapter hostDBAdapter = new DbAdapter(getApplicationContext());
performerDBadapter.open();
to try to get its context. (But obviously I can't because this code^ is java). So I tried to get the context using this answer.(Context context=this.cordova.getActivity().getApplicationContext();) But am not sure where to add this, and I am not even sure if this code would work anyways.
My questions are:
Where do I add this code in my application?
Am I on the right path?
What is the best way to connect a js app and Java app to the same SQLite Dtatabase on Android? (Examples would be very helpful)
INFO:
Android 5.1,
Cordova 5.0
UPDATE:
I already have android:sharedUserId="my.app" in both apps.

1) it depends from your application, please read some book on android and will able to put the code where you need. You can use also GreenDAO for a more simple access to sqlite
3) you can sign 2 different app with the same certificate, in this way the two apps are recognised as "same user id" and can share private data
2) this is a way, but a good way (the best way) is to expose data between two app on android is to use content provider
I hope this help you

Both are using different database, in this situation I recommend to use the following plug-in:
https://github.com/brodysoft/Cordova-SQLitePlugin
But, SQLite is a single-user database. If you go the "copy the database" route, then you risk losing data. If the desktop user added data and the iOS user added data, someone's data will be lost when you copy the file.
You can implement your own "syncing" algorithm that identifies changes between the databases and keeps them in sync. This can be a pain, but is a common solution and is what I would recommend. I've done it this way for a desktop/iOS app.
You can choose to use a database server, but this will require network access to connect to it.

Related

Meteor Collection-hooks not working for external DB modifications

I have a bunch of sensors scattered around.
These sensors transmit their status whenever they detect a change in their environment.
The data goes to a server(built using Java) where it processes that information then inserts it into a mongoDB.
My meteor App is essentially a dashboard for this information. I would like to do further processing on those entries as soon as they come in (analytics).
I started to use Collection-Hooks which works really nicely when the Meteor App makes changes to the database but not when the mongo Java-Driver does.
I need collection-hooks to detect new documents added to my mongoDB from the Java-driver. I'm also not married to collection-hooks, any other services suggested are welcomed.
What you want to use is an Observer on the cursor returned from a query:
https://docs.meteor.com/api/collections.html#Mongo-Cursor-observe
myCollection.find().observe({
added(document) {
// Do something with new document
},
changed(document) {
// Update analytics in response to change
},
removed(oldDocument) {
// Update analytics in response to change
}
});
This will depend on the contents of the actual database, unlike collection hooks that only operate when Meteor code is called
It's also worth noting that these hooks also track the specific query that was passed to find(). So if you only want to call these hooks for a specific subset of data, pass in the query like this this example from #scriptkid:
var date = moment().utc().format("YYYY-MM-DD HH:mm:ss.SSS");
log.find({ createdAt: { $gte: date } }).observe({
added(document) {
console.log("new document added!");
},
});

Firebase Firestore get only one field from document [duplicate]

Here is my data structure:
I have an ios app that is attempting to access data from Cloud Firestore. I have been successful in retrieving full documents and querying for documents. However I need to access specific fields from specific documents. How would I make a call that retrieves me just the value of one field from Firestore in swift? Any Help would be appreciated.
There is no API that fetches just a single field from a document with any of the web or mobile client SDKs. Entire documents are always fetched when you use getDocument(). This implies that there is also no way to use security rules to protect a single field in a document differently than the others.
If you are trying to minimize the amount of data that comes across the wire, you can put that lone field in its own document in a subcollection of the main doc, and you can request that one document individually.
See also this thread of discussion.
It is possible with server SDKs using methods like select(), but you would obviously need to be writing code on a backend and calling that from your client app.
This is actually quite simple and very much achievable using the built in firebase api.
let docRef = db.collection("users").document(name)
docRef.getDocument(source: .cache) { (document, error) in
if let document = document {
let property = document.get(field)
} else {
print("Document does not exist in cache")
}
}
There is actually a way, use this sample code provided by Firebase itself
let docRef = db.collection("cities").document("SF")
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let property = document.get('fieldname')
print("Document data: \(dataDescription)")
} else {
print("Document does not exist")
}
}
I guess I'm late but after some extensive research, there is a way in which we can fetch specific fields from firestore. We can use the select keyword, your query would be somthing like (I'm using a collection for a generalized approach):
const result = await firebase.database().collection('Users').select('name').get();
Where we can access the result.docs to further retrieved the returned filtered result. Thanks!
//this is code for javascript
var docRef = db.collection("users").doc("ID");
docRef.get().then(function(doc) {
if (doc.exists) {
//gives full object of user
console.log("Document data:", doc.data());
//gives specific field
var name=doc.get('name');
console.log(name);
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch(function(error) {
console.log("Error getting document:", error);
});

Can I access data stored in React Native's AsyncStorage from java layer?

I am storing few user preferences in React Native using AsyncStorage. Now, I need to get those preference from a background service. I can't access AsyncStorage from the Java layer. Is there a way to do it?
In iOS, We can import RCTAsyncLocalStorage.h and call _getValueForKey. But, I can't find a way to do it in Android.
I have following code which does the job.
import com.facebook.react.modules.storage.AsyncLocalStorageUtil;
import com.facebook.react.modules.storage.ReactDatabaseSupplier;
import android.database.sqlite.SQLiteDatabase;
.....
.....
SQLiteDatabase readableDatabase = null;
readableDatabase = ReactDatabaseSupplier.getInstance(this.getApplicationContext()).getReadableDatabase();
if (readableDatabase != null) {
String impl = AsyncLocalStorageUtil.getItemImpl(readableDatabase, "myTableName");
Log.d(TAG, "impl: " + impl);
}
====================
and to delete the DB
=====================
SQLiteDatabase database = ReactDatabaseSupplier.getInstance(getContext()).getWritableDatabase();
database.delete(CATALYST_LOCAL_STORAGE, null, null);
I tried to use the AsyncStorage from the java layer. But, I couldn't. So, I built a React Native plugin to access Android's Native SharedPreferences from the javascript layer. I have published it in the github (https://github.com/sriraman/react-native-shared-preferences)
Now I'm using this SharedPreferences from both Java and React Native layer.
My solution is to use directly the ReactDatabaseSupplier class (my app doesn't use Rocksdb so I can be quite sure that the SQLite DB is always used as storage (and, I guess it will always prefer the SQLite database over local storage))
The database is a simple key-value DB (two columns, key and value), with a table name 'catalystLocalStorage' (you can try to read the ReactDatabaseSupplier#TABLE_NAME but it's protected, you can try using reflection, but I'm not sure it's worth the troubles)
Cursor catalystLocalStorage = null;
SQLiteDatabase readableDatabase = null;
try {
readableDatabase = ReactDatabaseSupplier.getInstance(this.getApplicationContext()).getReadableDatabase();
catalystLocalStorage = readableDatabase.query("catalystLocalStorage", new String[]{"value"}, "key = ?", new String[] { "keyName" }, null, null, null);
final String value = catalystLocalStorage.getString(catalystLocalStorage.getColumnIndex("value"));
[...]
} finally {
if (catalystLocalStorage != null) {
catalystLocalStorage.close();
}
if (readableDatabase != null) {
readableDatabase.close();
}
}
It works to me, not sure how future-proof it can be
Use react-native-default-preference. Its way better than react-native-shared-preferences.
Yes you can.
React native
You need to create method in React native where you return values.
Native
Use PackagesModule Class Provided by facebook for access React-native method from Native
using this can able to access AsyncStorage
Android Native Modules

Google Drive script doesn't work,

I found online google drive script that sends an email with the changes on the prices of Amazon products that I insert.
This is the file
I couldn't make it work for 100%.. It work sometimes only for some of the products, and I cant find the reason.
Please help me to understand what is wrong.
Also, I wanted to know if I could modify the script so it will send me an alert twice a day and not only once, as it is now.
Configuring Email Notification Intervals
The email notifications are configured as Google Apps Scripts triggers invoking the priceEmail function. They're randomly assigned when you initialize the spreadsheet (refer to the Start_Tracking implementation).
To configure email notifications manually – e.g. adding a second daily email – open the Copy of Amazon Price Tracker by ctrlq.org script associated with the spreadsheet (via the spreadsheet Tools > Script editor... menu command). Then proceed to opening the triggers dialog (Resources > Current project's triggers menu command) and add a new time-driven trigger for the priceEmail hook.
Script Errors
By default, the priceEmail function handles all errors silently. There's not much clue to what would cause the script to not work 100% of the time. If you'd like to be notified of the errors, either remove the exception handling in the current implementation or update the priceEmail body.
I'd advice making the following modifications (again via the spreadsheet Tools > Script editor... menu command):
function priceEmail() {
var sheet, data, page, table="";
sheet = SpreadsheetApp.getActiveSheet();
data = sheet.getRange(2, 2, 21, 2).getValues(); // Note that the script will only look at the first 20 rows.
try {
for (i in data) {
if (data[i][0] !== "") {
page = UrlFetchApp.fetch(
"http://ctrlq.org/aws/lookup/", {
"method": "post", "payload": {"url":data[i][0]}
}).getContentText();
table = table + tableRow(page);
}
}
} catch (e) {
Logger.log(e.toString());
// Following line inserted to include any error messages in your daily email(s).
table += "<tr><td><strong>Error:</strong></td><td>" + e + " (url: \"" + data[i][0] + "\")</td></tr>";
}
// ...

Handle the Post Request from Android?

I am writing an application with the user of Android Java " Eclipse " + Jquery Mobile + CodeIgniter Framework
I almost finished everything but still can not proceed on the push notification issue
one big problem taken about 2 days till now from me till I have headache from such conflict :
I made the POST Request from the android and it's already sending the POST Array.
here is the php code to handle the post request...
function notification() {
if($_POST['registrationId']) {
$this->session->set_userdata('registrationId', $_POST['registrationId']);
echo 'registerationID : success'.$this->session->userdata('registrationId').'====';
}
it really echo the session userdata indeed .. but when I try to use it in any other function or pages .. it's not working ? !!! it's empty or not existed ? !!
even when I try to make the query within the function in order to store it in Database .. the session is not available like $this->session->userdata('emailid')
update 'user' set deviceid ... where emailid = $this->session->userdata('emailid')
... not working and the session is not available !!!!!
PLEASE ANYONE CAN HELP ME ? !! :(
you can ues a class to storing the post data
class PostData {
public static $registrationId = "";
}
//set data
function notification() {
if(isset($_POST['registrationId']) && empty($_POST['registrationId']) {
PostData::$registrationId = $_POST['registrationId'];
}
}
// use data
$post_registrationId = empty(PostData::$registrationId) ? PostData::$registrationId : "";
well i couldn't solve the problem through sessions .. therefore i used fopen and i have registered the registration ID in a file.txt to use it later after in the session then delete the file. hope it can help someone someday .. thank you for sharing and participating

Categories

Resources