I am trying upload some message data to server from my android app.it uploaded the server data well, But problem is, it is upload all message data every time when app started.I want to upload only those message data which would not uploaded previously.How to do this?
Here is my code of fetching and uploading the message data on server:
class SmsContent {
public List<SmsInfo> getSmsInfo() {
String[] projection = new String[] { "_id", "address", "person", "body", "date", "type" };
ContentResolver cr = activity.getContentResolver();
Cursor cursor = cr.query(uri, projection, "body"+" LIKE '%"+smsBuilder1+"%'or+" + "body"+" LIKE '%"+smsBuilder2+"%'", null, "date desc");
assert cursor != null;
int nameColumn = cursor.getColumnIndex("person");
smsbodyColumn = cursor.getColumnIndex("body");
int i = 0;
while (cursor.moveToNext() && i++ < 20) {
SmsInfo smsInfo = new SmsInfo();
smsInfo.setName(cursor.getString(nameColumn));
smsInfo.setSmsbody(cursor.getString(smsbodyColumn).trim());
per = (cursor.getString(smsbodyColumn));
smsInfo.setName(null == personName ? smsInfo.getPhoneNumber() : personName);
prepareListData(per);
infos.add(smsInfo);
}
cursor.close();
return infos;
}
private void prepareListData(final String per) {
// Volley's json array request object
StringRequest stringRequest = new StringRequest(Request.Method.POST, REGISTER_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
VolleyLog.d(TAG, "Error: " + response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
// hidePDialog();
}
}){
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put(VENDOR, "test");
params.put(ORGMESSAGE, per);
return params;
}
};
// Adding request to request queue
MyApplication.getInstance().addToRequestQueue(stringRequest);
}
}
If anyone want to know more info please ask.
Save recently received message date in SharedPreferences and have a condition in query so as to select the messages which are received after that date.
String dateFromSharedPreferences="2000-01-01";
try{
String dateFromSharedPreferences=getActivity().getPreferences(Context.MODE_PRIVATE);
dateFromSharedPreferences=sharedPref.getString("LastMsgDate", "2000-01-01");
catch(Exception ex){}
Cursor cursor = cr.query(uri, projection, "(body"+" LIKE '%"+smsBuilder1+"%'or+" + "body"+" LIKE '%"+smsBuilder2+"%') and date>'"+dateFromSharedPreferences+"'", null, "date desc");
Dont forget to save the current last received sms date in the same SharedPreferences
while (cursor.moveToNext() && i++ < 20) {
if(i==1) saveDateToSharedPreferences(cursor.getString(cursor.getColumnIndex("date")))
//other codes here
}
saveDateToSharedPreferences function will be as follows
function saveDateToSharedPreferences(String LastMsgDate){
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("LastMsgDate", LastMsgDate);
editor.commit();
}
Make another column in your table and store data like whether it's uploaded or not. And upload the data which are not uploaded.
So, what you're dealing with here is local cache, mind you that this answer will give you the flow of a way to handle it, the coding is up to you, by the code you posted it seems your up to the task, here are your options:
SharedPreferences.
Android's built in sqlite.
SharedPreferences is an option, but - it would be more suitable for single variables, or for example, an object serialized into a JSON string.
In your case, creating and maintaining a local (on the phone itself, client-side) database would probably be better - since you're maintaining a messaging record, which is big and might reach numbers in the tens, you mentioned that you're not creating a custom table - you should, and since your code suggests that there IS a db somewhere in there, this is generally how I would go about this:
create a new table, holding all the known values plus 2 new columns (e.g. is_sent, is_received).
think of two situations: msg sent, vs. msg received - you might have sent it, the other side (server) might not get it.
Pull the msgs using the cursor (like you did), save them in an ArrayList, and their info in your new table, marking them all as false on the sent and received columns.
Send that list to your server (marking all of them as sent = true in the table).
make sure your server response returns a confirmation (either per id, or just a general "success:true"), and then in the onResponse callback - update your table (use you local list for id comparison if you need to, marking what is relevant with received = true).
modify the method that sends stuff on startup to pull the messages, and first compare them to your table,only send the msgs that are marked as sent=false && received=false, if in doubt - check the id, if it's not in your table - you don't know about it, so send it and make sure your server knows to compare msg id's cross-referenced with user id's to avoid duplicates.
All this requires both client side work and server side work, and possibly some help from your server-side/db guy, and again - this is a possible flow similar to chat message caching, and probably could be greatly tweaked into efficiency when coding.
Hope this Helps.
Related
I have an SQLite Db which stores call logs. Each entry has a number, date, and duration. I have seen that there are many ways we can send the data to the app server. As a JSON String and send one by one from an ArrayList of model class objects.
Which is the correct way to approach this? And how can I create a JSON from these data, I have done as much as getting these data to an ArrayList of objects. since each entry has many data, I am confused about how to do this.
public ArrayList<PhNumber> getCallLogs() {
ArrayList<PhNumber> callLogList;
callLogList = new ArrayList<PhNumber>();
String selectQuery = "SELECT * FROM callInfo where syncStatus = '" + "no" + "'";
SQLiteDatabase database = this.getWritableDatabase();
Cursor cursor = database.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
do {
callLogList.add(new PhNumber(Integer.parseInt(cursor.getString(0)), cursor.getString(1),
cursor.getString(2),
cursor.getString(3),
cursor.getString(4)));
Log.e("DbHelper:getCallLogs", callLogList.toString());
} while (cursor.moveToNext());
}
return callLogList;
}
Which is the correct way to approach this?
There is not any one solution . It depends on your use case scenario.
For making JSON , you can do this after getting your data in ArrayList<PhNumber> callLogList
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < callLogList.length(); i++) {
JSONObject jsonobject= new JSONObject();
jsonobject.put("data1",callLogList.get(i).get); //I dont know the field name of your PhNumber so fill accordingly
jsonobject.put("data2",callLogList.get(i).get);
jsonArray.put(jsonobject);
}
I would suggest you to use Retrofit for this, a library that is very easy to use, saves lot of time and code. Serialization and HTTP requests are handled seamlessly using Retrofit.
please refer to this article for simple understanding of Retrofit
I pulled my original question because I managed to figured it out through trail and error and a lot of deep searching.
So, I understand that using the latest Facebook SDK in Unity, you can pull all pending requests for a player using:
FB.API("/me/apprequests", HttpMethod.GET, RequestHandler)
Where RequestHandler is an IGraphResult, which you can then parse into a Dictionary, like so:
void RequestHandler(IGraphResult result){
if (result != null) {
Dictionary<string, object> reqResult = Json.Deserialize(result.RawResult) as Dictionary<string, object>;
}
}
The documentation explains how a singular request will be displayed in JSON format, and I've found a few examples of how to work with that information (I vaguely understand JSON's), however if pulling ALL requests for the player, how do I work with this information?
Out of the JSON, I'm just trying to pull the object ID and sender ID of each request, handle the request based on the object ID then delete the request from the graph by concatenating the two, which I think I've figured out already.
So my question is, for each request, how do I extract the object and sender ID's?
So after a LOT of trial and error and a lot of Log checks, I've figured out a really hacky way of doing it, for those that aren't sure:
public void TestRequests(){
FB.API("/me/apprequests", HttpMethod.GET, TestResponse);
}
public void TestResponse(IGraphResult result){
if (result.Error == null) {
//Grab all requests in the form of a dictionary.
Dictionary<string, object> reqResult = Json.Deserialize(result.RawResult) as Dictionary<string, object>;
//Grab 'data' and put it in a list of objects.
List<object> newObj = reqResult["data"] as List<object>;
//For every item in newObj is a separate request, so iterate on each of them separately.
for(int xx = 0; xx < newObj.Count; xx++){
Dictionary<string, object> reqConvert = newObj[0] as Dictionary<string, object>;
Dictionary<string, object> fromString = reqConvert["from"] as Dictionary<string, object>;
Dictionary<string, object> toString = reqConvert["to"] as Dictionary<string, object>;
string fromName = fromString["name"] as string;
string fromID = fromString["id"] as string;
string obID = reqConvert["id"] as string;
string message = reqConvert["message"] as string;
string toName = toString["name"] as string;
string toID = toString["id"] as string;
Debug.Log ("Object ID: " + obID);
Debug.Log ("Sender message: " + message);
Debug.Log ("Sender name: " + fromName);
Debug.Log ("Sender ID: " + fromID);
Debug.Log ("Recipient name: " + toName);
Debug.Log ("Recipient ID: " + toID);
}
}
else {
Debug.Log ("Something went wrong. " + result.Error);
}
}
Again, this is my first experience with using JSON, and I'm sure there's a much more efficient way of doing this, but basically after a lot of breaking down and converting, I've managed to extract the object ID, sender name and ID, the message attached and the recipient name and ID. The object ID comes concatenated with the recipient ID, so to operate on the object ID itself, this will need to be removed, however as is it will make it easier to pass the string on to remove the request from the Graph API.
If anyone can suggest to me a more efficient way of doing this, I'd be grateful! There's always more to learn, after all.
I'm facing an issue in my application where I send the server request once and receive a single response but my request has created duplicate rows in the database. The only primary key in the database table is the row id which gets incremented every time a request is sent so duplicate rows of values get created with different row ids. I'm using Xamarin Android. Could you please let me know if this issue is a bug related to Xamarin and if they is any way in which this can be fixed?
Thank you.
Edit:
This is my code:
I call this method in my OnCreate()
public void SendMobileNo(Activity activity)
{
Services_GetValue.GetValue client = new Services_GetValue.GetValue();
Services_GetValue.GetValueRequest request = new Services_GetValue.GetValueRequest()
{
key = "abac",
PhoneNo = "1234567890"
};
client.BeginCheckPhone(request, (ar) => {
Services_GetValue.GetValueResponse response = client.EndCheckPhone(ar);
this.IsPhoneValid = response.IsValidPhoneNo;
activity.RunOnUiThread (() => {
if (SendMobileNoCompleted != null)
{
this.SendMobileNoCompleted();
this.SendMobileNoCompleted = null;
}
});
}, null);
client.CheckPhone(request);
}
I have created a Proxy in WebReferences package with the name "Services_GetValue.GetValue" and it is a SOAP webservice.
I ran into trouble trying to send SQLite data to a web server using json (gson).
Everything was fine until the table came round 6000 rows.
I ran into Out of Memory errors.
In my datahelper I have:
public String DonneesToJson (SQLiteDatabase db, int chantier, int chantier_serveur )
{
Cursor c = db.rawQuery("select * from "+P_TABLE+" where "+P_CHANTIER+"="+chantier+ " order by "+P_TIME+" desc ", null);
List<Donnees> donnees = new ArrayList<Donnees>();
c.moveToFirst();
while (c.moveToNext())
{
Donnees d = new Donnees (
c.getInt(c.getColumnIndex(Datahelper.P_ID)),
chantier_serveur,
offset,
c.getInt(c.getColumnIndex(Datahelper.P_PLAN)),
c.getString(c.getColumnIndex(Datahelper.P_TIME)),
c.getInt(c.getColumnIndex(Datahelper.P_PRESSION)),
c.getInt(c.getColumnIndex(Datahelper.P_PROFONDEUR)),
c.getInt(c.getColumnIndex(Datahelper.P_PROFONDEUR_TOTALE)),
c.getInt(c.getColumnIndex(Datahelper.P_ANGLE_X)),
c.getInt(c.getColumnIndex(Datahelper.P_ANGLE_Y)),
c.getString(c.getColumnIndex(Datahelper.P_PIEU)),
c.getInt(c.getColumnIndex(Datahelper.P_NO_RALLONGE)),
c.getString(c.getColumnIndex(Datahelper.P_RALLONGE)),
c.getInt(c.getColumnIndex(Datahelper.P_MOTEUR)),
c.getString(c.getColumnIndex(Datahelper.P_SERIE)),
c.getDouble(c.getColumnIndex(Datahelper.P_COEFF_A)),
c.getDouble(c.getColumnIndex(Datahelper.P_COEFF_B))
);
donnees.add(d);
}
c.close();
Gson gson = new Gson();
return gson.toJson(donnees);
}
Basically I call this like that:
String resultat = dbHelper.DonneesToJson(db,i, chantier_serveur);
HttpPost post2 = new HttpPost("http://www.zzzzzzz.com/test.php");
StringEntity se = new StringEntity(resultat);
se.setContentEncoding( new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post2.setEntity(se);
response = client.execute(post2);
On the server side, it's quite basic php to store data in a big sql DB and then do analysis.
ie:
$decoded = json_decode($HTTP_RAW_POST_DATA,true);
foreach ( $decoded as $key => $value)
{
$query = ...
While doing OOM erros, it's slow. I mean getting sql data to json is slow.
I tried to go the jackson route, faster, no out of memory error, but... it can only write to a file or a stream.
I'd try to avoid writing to a file then send the file trough http post.
So I decided to open an http stream to send json data and I'm stuck.
I did not find any example on how to open an output stream to the web server using apache.
Any help appreciated.
Despite the answer from dmon to split the data into batches, you should work on other glitches. Try this code:
public String DonneesToJson (SQLiteDatabase db, int chantier, int chantier_serveur ) {
Cursor c = db.rawQuery("select * from "+P_TABLE+" where "+P_CHANTIER+"="+chantier+ " order by "+P_TIME+" desc ", null);
List<Donnees> donnees = new ArrayList<Donnees>();
if (c != null) { // nullcheck as rawQuery can return null!
Donnees d; // reuse variables for loops
while (c.moveToNext()) { // was buggy before, read comment below code
d = new Donnees (
c.getInt(c.getColumnIndex(Datahelper.P_ID)),
chantier_serveur,
offset,
c.getInt(c.getColumnIndex(Datahelper.P_PLAN)),
c.getString(c.getColumnIndex(Datahelper.P_TIME)),
c.getInt(c.getColumnIndex(Datahelper.P_PRESSION)),
c.getInt(c.getColumnIndex(Datahelper.P_PROFONDEUR)),
c.getInt(c.getColumnIndex(Datahelper.P_PROFONDEUR_TOTALE)),
c.getInt(c.getColumnIndex(Datahelper.P_ANGLE_X)),
c.getInt(c.getColumnIndex(Datahelper.P_ANGLE_Y)),
c.getString(c.getColumnIndex(Datahelper.P_PIEU)),
c.getInt(c.getColumnIndex(Datahelper.P_NO_RALLONGE)),
c.getString(c.getColumnIndex(Datahelper.P_RALLONGE)),
c.getInt(c.getColumnIndex(Datahelper.P_MOTEUR)),
c.getString(c.getColumnIndex(Datahelper.P_SERIE)),
c.getDouble(c.getColumnIndex(Datahelper.P_COEFF_A)),
c.getDouble(c.getColumnIndex(Datahelper.P_COEFF_B)));
donnees.add(d);
}
c.close();
}
return new Gson().toJson(donnees);
}
Your current implementation is buggy and you will never get the first entry. The reason for that is your call to moveToFirst() which moves you to the first. The while loop will move the internal pointer to the second entry with moveToNext() which will result in starting with the second element and completely ignoring the first one. Always and forever...
in my app i have two edit boxes for email and username. Whatever the user types in it i am trying to move it over an url as follows
http//xxxxxxx.com/id?mail=*email&user=*usernane
By this i am getting a return data from the url, this is what i am doing if network is available. But if network is not available i am storing those two values in Sqlite database and in another activity if network is available i will be fetching the above said data and i will move them to the server.
My problem is, at the time of network not available if the user tries to send two set of username and email to the server it gets stored in database. How can i store those values in an array and how can i fetch them one by one. Please help me friends
Following is the part of my code for database
off = openOrCreateDatabase("Offline.db", SQLiteDatabase.CREATE_IF_NECESSARY, null);
off.setVersion(1);
off.setLocale(Locale.getDefault());
off.setLockingEnabled(true);
final String CREATE_TABLE_OFFLINEDATA ="CREATE TABLE IF NOT EXISTS offlinedata(spotid INTEGER, username TEXT, email TEXT);";
off.execSQL(CREATE_TABLE_OFFLINEDATA);
ContentValues values = new ContentValues();
values.put("id", millis);
values.put("name", username);
values.put("mail", email);
off.insert("offlinedata", null, values);
Cursor con = off.rawQuery("select * from offlinedata" , null);
if (con != null )
{
if (con.moveToFirst())
{
do
{
int spotid = con.getInt(con.getColumnIndex("id"));
String first = con.getString(con.getColumnIndex("username"));
String middle = con.getString(con.getColumnIndex("email"));
}
while (con.moveToNext());
}
}
off.close();
Please help me friends....
From looking at your sample code, it seems like you're storing them properly(ish), and you've managed an exhaustive job fetching them in a really narrow scope, so make first and middle more globalish and since you have two strings available, put them in an array.
Though I must say if this is your actual code it probably won't work the way you want this whole offline thing to work.