How to Send All SQLite Data to online Server - android

I am storing data into SQLiteDatabase which is stored into SD Card, now i have to send all SQLite data to server.
Note: I have created same fields to server database as well (simillar to SQLite DB) for an eg: PersonName
Below code i used to check, am i able to store data to server (for testing purpose - i accepted data by user into edittext) and then sent to server, and i was successful in that.
String url = "http://localhost/ChurchData.php";
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("sPersonName", editPersonName.getText().toString()));
String resultServer = getHttpPost(url,params);
Log.d("Entire string::", " " + resultServer);
/*** Default Value ***/
strStatusID = "0";
strError = "";
JSONObject c;
try {
c = new JSONObject(resultServer);
strStatusID = c.getString("StatusID");
strError = c.getString("Message");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// prepare save data
if(strStatusID.equals("0"))
{
Toast.makeText(getApplicationContext(), "Already Exist !", Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(getApplicationContext(), "Data Uploaded Successfully!", Toast.LENGTH_SHORT).show();
}
return true;
}
private String getHttpPost(String url,
List<NameValuePair> params) {
StringBuilder str = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
try {
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = client.execute(httpPost);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) { // Status OK
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
str.append(line);
}
} else {
Log.e("Log", "Failed to download result..");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return str.toString();
}
So may i know, How can i send SQLite database records to server ? My database class looks like this:
public class myDBClasss extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 2;
// Database Name
private static final String DATABASE_NAME = "ChurchDB";
// Table Name
private static final String TABLE_MEMBER = "DataTable";
public myDBClasss(Context context) {
// to store data into SD Card
super(context, Environment.getExternalStorageDirectory()
+ File.separator + "ChurchData"
+ File.separator + DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
// Create Table Name
db.execSQL("CREATE TABLE " + TABLE_MEMBER +
"(PersonName VARCHAR(100)," +
" PersonEmail VARCHAR(100)," +
" PersonTelephone VARCHAR(100)," +
" Newsletter VARCHAR(100));"); // checkbox
Log.d("CREATE TABLE","Create Table Successfully - classs");
}
// Insert Data
public long insertData(String strPersonName, String strPersonEmail, String strPersonTelephone, String strNewsletter) {
// TODO Auto-generated method stub
try {
SQLiteDatabase db;
db = this.getWritableDatabase(); // Write Data
ContentValues Val = new ContentValues();
Val.put("PersonName", strPersonName);
Val.put("PersonEmail", strPersonEmail);
Val.put("PersonTelephone", strPersonTelephone);
Val.put("Newsletter", strNewsletter); // checkbox
long rows = db.insert(TABLE_MEMBER, null, Val);
db.close();
return rows; // return rows inserted.
} catch (Exception e) {
return -1;
}
}
// Update Data
public long updateData(String strPersonName, String strPersonEmail, String strPersonTelephone, String strNewsletter){
// TODO Auto-generated method stub
try {
SQLiteDatabase db;
db = this.getWritableDatabase(); // Write Data
ContentValues Val = new ContentValues();
Val.put("PersonName", strPersonName);
Val.put("PersonEmail", strPersonEmail);
Val.put("PersonTelephone", strPersonTelephone);
Val.put("Newsletter", strNewsletter); // checkbox
long rows = db.update(TABLE_MEMBER, Val, "PersonName=?",
new String[] { String.valueOf(strPersonName) });
db.close();
return rows; // return rows updated.
} catch (Exception e) {
return -1;
}
}
// Fetch data
public String[] selectData(String strPersonName) {
// TODO Auto-generated method stub
try {
String arrData[] = null;
SQLiteDatabase db;
db = this.getReadableDatabase(); // Read Data
Cursor cursor = db.query(TABLE_MEMBER, new String[] { "*" },
"PersonName=?",
new String[] { String.valueOf(strPersonName) }, null, null, null, null);
if(cursor != null)
{
if (cursor.moveToFirst()) {
arrData = new String[cursor.getColumnCount()];
arrData[0] = cursor.getString(0);
arrData[1] = cursor.getString(1);
arrData[2] = cursor.getString(2);
arrData[3] = cursor.getString(3); // checkbox
}
}
cursor.close();
db.close();
return arrData;
} catch (Exception e) {
return null;
}
}
// Check for data(s) using PersonName field
public boolean exists(String strImageName) {
SQLiteDatabase db;
db = this.getReadableDatabase(); // Read Data
Cursor cursor = db.rawQuery("select 1 from DataTable where PersonName= ?",
new String[] { strImageName });
boolean exists = (cursor.getCount() > 0);
cursor.close();
return exists;
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS " + TABLE_MEMBER);
// Re Create on method onCreate
onCreate(db);
}
}

I think easy way is that you convert all your sqlite data into xml or json and then only one http request is required to send all your data to online server. At online server you can easily parse your data as you already know the structure of your xml or json whatever you used.
let say you have 2 fields in your database. ID , Name. you have 10 records. you convert all your records into json .
let say you query your database for all records and now cursor object will hold all your sqlite data.
add getAllData() method to retrieve all your database data.
public Cursor getAllData() {
String selectQuery = "Select * from "+TABLE_MEMBER;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
return cursor;
}
now do,
Cursor cursor = getAllData(); //cursor hold all your data
JSONObject jobj ;
JSONArray arr = new JSONArray();
cursor.moveToFIrst();
while(cursor.moveToNext()) {
jobj = new JSONObject();
jboj.put("Id", cursor.getInt("Id"));
jboj.put("Name", cursor.getString("Name"));
arr.put(jobj);
}
jobj = new JSONObject();
jobj.put("data", arr);
String st = jboj.toString();
now simply make an http call with string parameter and send to server.and parse at server by converting this string into jsonobject.
now according to your code, do
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("allData", st));
String resultServer = getHttpPost(url,params);

I have some snippet of code just for your idea.If it help you it my pleasure.
protected void startSync(Context aContext) {
try {
AccountManager am = AccountManager.get(getBaseContext());
Account[] ac = am.getAccountsByType(Constants.ACCOUNT_TYPE);
if (ac.length > 0) {
Toast.makeText(SuperHomeActivity.this,
"Synchronization Started", Toast.LENGTH_SHORT).show();
List<PeriodicSync> aList = ContentResolver.getPeriodicSyncs(
ac[0], Constants.AUTHORITY);
Bundle bundle = new Bundle();
bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
if (aList != null && aList.size() > 0) {
while (aList != null && !aList.isEmpty()) {
ContentResolver.removePeriodicSync(ac[0],
Constants.AUTHORITY, aList.get(0).extras);
aList.remove(0);
}
}
// mention only in seconds -> 120 minutes 60 seconds
ContentResolver.addPeriodicSync(ac[0], Constants.AUTHORITY,
bundle, 5 * 60); //15
ContentResolver.requestSync(ac[0], Constants.AUTHORITY, bundle);
}
} catch (Exception ex) {
Log.e("SyncAccountTriggerError", ex.getMessage());
}
}
And you can call it by
startSync(getApplicationContext());
For any more clarification you can ping me.

you can use Http Post method or Get method or if you directly wants to update your server DB then use Put method. You can send data by http request with NameValue pair and just get that data from server and update your DB. That's it.

Related

How to check if data exists in a record before performing an action in SQLite?

I made an app to scan qr code. I want the data scanned from the qr code(which will be a number like 2300, 2301, 2302) to be compared to a column called ID in the sqlite database. Some of the values in the sqlite database for column ID are 2301, 2302, 2303. I want that the data scanned will be compared to the values in ID and if they match an action will be performed. If not an error message will be shown. If the qr code has value 2301, then the action will be perform. If it is 8900(a number not in the database) it displays a message:Student not found. I would also like to clarify that the scannedData is not being entered into the sqlite database but sent to a google script link. The sqlite database contains a list of students. I want that if the scanned data is not similar to nay ID in the sqlite database then the sannedData will not be sent to google app script destination.
This my database code for activity DatabaseHelper
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "Student.db";
public static final String TABLE_NAME = "student_table";
public static final String COL_1 = "ID";
public static final String COL_2 = "NAME";
public static final String COL_3 = "SURNAME";
public static final String COL_4 = "MARKS";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + TABLE_NAME +" (ID INT PRIMARY KEY UNIQUE,NAME TEXT,SURNAME TEXT,MARKS TEXT)");
}
Below is the code i want to modify to check if it is in the database. This is another activity called MainActivity.
public class ArrivalTime extends AppCompatActivity {
String scannedData;
Button scanBtn;
//-----------------------------------------------------------
//DatabaseHelper myDb;
//------------------------------------------------------------
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_arrival_time);
final Activity activity = this;
scanBtn = (Button) findViewById(R.id.scan_btn);
//-------------------------------------------------------
// myDb = new DatabaseHelper(this);
//---------------------------------------------------------
scanBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
IntentIntegrator integrator = new IntentIntegrator(activity);
integrator.setDesiredBarcodeFormats(IntentIntegrator.ALL_CODE_TYPES);
integrator.setPrompt("Place barcode in window to Scan it");
integrator.setBeepEnabled(true);
integrator.setCameraId(0);
integrator.setBarcodeImageEnabled(false);
integrator.initiateScan();
}
});
}
//-----------------------------------------------------------------------------------------
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result= IntentIntegrator.parseActivityResult(requestCode,resultCode,data);
if(result!=null){
scannedData = result.getContents();
if(scannedData != null){
// here we need to handle scanned data
// Cursor c = myDb.getId(String);
// if(c.getCount() == 0) {
// show message
// Toast.makeText(ArrivalTime.this,"Student doesn't exist in database",Toast.LENGTH_LONG).show();
// return;
//}
new SendRequest().execute();
}
else{
}
}
super.onActivityResult(requestCode, resultCode, data);
}
//-----------------------------------------------------------------------------------------
public class SendRequest extends AsyncTask<String, Void, String>{
protected void onPreExecute(){}
protected String doInBackground(String... arg0){
try{
URL url = new URL("https://script.google.com/macros/s/ttttttttttttttttttttttttttttttttttttttttttttt/exec");
JSONObject postDataParams = new JSONObject();
postDataParams.put("sdata",scannedData);
Log.e("params", postDataParams.toString());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(getPostDataString(postDataParams));
writer.flush();
writer.close();
os.close();
int responseCode=conn.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
BufferedReader in=new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuffer sb = new StringBuffer("");
String line="";
while((line = in.readLine()) != null) {
sb.append(line);
break;
}
in.close();
return sb.toString();
}
else {
return new String("false : "+responseCode);
}
}
catch(Exception e){
return new String("Exception: " + e.getMessage());
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(getApplicationContext(), result,
Toast.LENGTH_LONG).show();
}
}
public String getPostDataString(JSONObject params) throws Exception {
StringBuilder result = new StringBuilder();
boolean first = true;
Iterator<String> itr = params.keys();
while(itr.hasNext()){
String key= itr.next();
Object value = params.get(key);
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(key, "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(value.toString(), "UTF-8"));
}
return result.toString();
}
//-----------------------------------------------------------------------------------------
I want the function to check if the scanned data in not null and that it exists in the database. I tried just doing if(scannedData != null && scanned==id) but i'm not sure how to call database data from another activity and perform a comparison
I've been given an example below but it assumes that i'm checking if there is a similar value as whatever's been scanned so that it can be entered into the sqlite database which is not what i want.
Any suggestions.
You can check bellow like..
public Boolean getId(String id) {
boolean rValue = false;
String selectQuery = "SELECT * FROM " + TABLE_NAME + " where "+ COL_1 +" = ? " ;
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.rawQuery(selectQuery, new String[]{id});
if (c.moveToFirst()) {
do {
// Data Is Exist;
rValue = true;
} while (c.moveToNext());
}
db.close();
c.close();
return rValue;
}
the answer is very simple,you have to make a select query using a given value for the ID column and check the Cursor.getCount() method like this.
Cursor.getCount(); // returns number of rows from this query.
if it returns 0 so there are some rows in there that means the ID do exist
public boolean Contains(String ID) {
Cursor cursor = null;
cursor = db.rowQuery("SELECT * FROM student_table WHERE ID === ? ", new String[]{ID});
if (cursor.getCount() == 0) {
return false;
}
return true;
}

How to retrieve a single column data from a Android sugar orm database

I have created a Sugar ORM database successfully in my app, I can update, delete and also get all data from a row, but I want a single column data matched with another data...
I mean, I have a registration database with fields: username, password, first_name, last_name, email fields.
After login a user with right username and password, I want THAT User's First_Name in a Textview sent to the Next Activity...
How can I do this? Over last two days I have tried but failed, please help me...
Thanks in advance...
public static List<String> getResultWithRawQuery(String rawQuery, Context mContext) {
List<String> stringList = new ArrayList<>();
if (mContext != null) {
long startTime = System.currentTimeMillis();
SugarDb sugarDb = new SugarDb(mContext);
SQLiteDatabase database = sugarDb.getDB();
try {
Cursor cursor = database.rawQuery(rawQuery, null);
try {
if (cursor.moveToFirst()) {
do {
stringList.add(cursor.getString(0));
} while (cursor.moveToNext());
}
Timber.d(cursor.getString(0), "hi");
} finally {
try {
cursor.close();
} catch (Exception ignore) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println("total time query" + totalTime);
}
return stringList;
}
Another example that returns a List of values in the column. Use as such:
String rawQuery = ("SELECT feed_key FROM team_feed_key WHERE team_id = " + mTeam_id + " ORDER BY feed_key DESC");
Did you try to run a raw query like this?
List<Note> notes = Note.findWithQuery(Note.class, "Select * from Note where name = ?", "satya");
from: http://satyan.github.io/sugar/query.html
you can add function to SugarRecord.java forever
public static String Scaler(String Query) {
String Result = "";
SugarDb db = getSugarContext().getSugarDb();
SQLiteDatabase sqLiteDatabase = db.getDB();
SQLiteStatement sqLiteStatament = sqLiteDatabase
.compileStatement(Query);
try {
Result = sqLiteStatament.simpleQueryForString();
} catch (Exception e) {
e.printStackTrace();
} finally {
sqLiteStatament.close();
}
return Result;
}
or
public static String Scaler(String Query) {
String Result = "";
SQLiteDatabase sqLiteDatabase = SugarContext.getSugarContext().getSugarDb().getDB();
SQLiteStatement sqLiteStatament = sqLiteDatabase
.compileStatement(Query);
try {
Result = sqLiteStatament.simpleQueryForString();
} catch (Exception e) {
e.printStackTrace();
} finally {
sqLiteStatament.close();
}
return Result;
}
Scaler("Select First_Name from Note where name ='ali' limit 1");
I had the same problem.
I hope this helps someone:
String firstName = Select.from(User.class).where("EMAIL = "+ user.getEmail()).first().getFirstName();
Hi this must work you can not edit the libraries but you can extend them so check this out:
public class DBUtils extends SugarRecord {
public static <T> List<Object> findByColumn(Context context, String tableName,T ColumnObjectType, String columnName) {
Cursor cursor = new SugarDb(context).getDB().query(tableName, new String[]{columnName}, null, null,
null, null, null, null);
List<Object> objects = new ArrayList<>();
while (cursor.moveToNext()){
if (ColumnObjectType.equals(long.class) || ColumnObjectType.equals(Long.class)) {
objects.add(cursor.getLong(0));
}else if(ColumnObjectType.equals(float.class) || ColumnObjectType.equals(Float.class)){
objects.add(cursor.getFloat(0));
}else if(ColumnObjectType.equals(double.class) || ColumnObjectType.equals(Double.class)){
objects.add(cursor.getDouble(0));
}else if(ColumnObjectType.equals(int.class) || ColumnObjectType.equals(Integer.class)){
objects.add(cursor.getInt(0));
}else if(ColumnObjectType.equals(short.class) || ColumnObjectType.equals(Short.class)){
objects.add(cursor.getShort(0));
}else if(ColumnObjectType.equals(String.class)){
objects.add(cursor.getString(0));
}else{
Log.e("SteveMoretz","Implement other types yourself if you needed!");
}
}
if (objects.isEmpty()) return null;
return objects;
}
}
The usage is simple use DBUtils.findByColumn(...);
Any where you like and from now on you can use only this class instead of SugarRecord and add your own other functions as well.
hint:
ColumnObjectType as the name Suggest tells the type of column like you send Integer.class

ListView not showing anything

My ListView is not showing anything.
I'm downloading the top stories API from Hacker-News and putting them in my app. I want to put the titles of those stories in my list view (they are over 100).
I download them and store them in a database for permanent storage and then add them to my list view, but NOTHING is showing up in my app. Can anyone explain to me why?
UPDATE: I get a CursorIndexOutOfBoundException problem. ( index 350 out of 350)
public class MainActivity extends AppCompatActivity {
ListView listView;
private SQLiteDatabase myDatabase;
private Cursor cursor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
DownloadIDs ids = new DownloadIDs();
String URL = "https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty";
ids.execute(URL);
try {
ArrayList<String> titles = new ArrayList<String>();
ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, titles);
listView.setAdapter(arrayAdapter);
myDatabase = this.openOrCreateDatabase("HackerNews", MODE_PRIVATE, null);
Cursor cursor1 = myDatabase.rawQuery("SELECT * FROM ids", null);
int index = cursor1.getColumnIndex("urlID");
cursor1.moveToFirst();
while (cursor1 != null) {
String newUrl = "https://hacker-news.firebaseio.com/v0/item/" + cursor1.getString(index) + ".json?print=pretty";
new DownloadContent().execute(newUrl);
cursor1.moveToNext();
}
Cursor cursor2 = myDatabase.rawQuery("SELECT * FROM content", null);
int titleIndex = cursor2.getColumnIndex("title");
cursor2.moveToFirst();
titles.add("Hello");
while(cursor2 != null){
titles.add(cursor2.getString(titleIndex));
arrayAdapter.notifyDataSetChanged();
cursor2.moveToNext();
}
}catch (Exception e){
e.printStackTrace();
}
}
public class DownloadIDs extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String result = "";
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
int data = reader.read();
while (data >= 0) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
myDatabase.execSQL("CREATE TABLE IF NOT EXISTS ids (id INTEGER PRIMARY KEY, urlID VARCHAR)");
cursor = myDatabase.rawQuery("SELECT COUNT(*) FROM ids", null);
cursor.moveToFirst();
int count = cursor.getInt(0);
if (!(count > 0)) {
JSONArray ids = new JSONArray(s);
for (int i = 0; i < ids.length(); i++) {
myDatabase.execSQL("INSERT INTO ids (urlID) VALUES ('" + ids.getString(i) + "')");
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
public class DownloadContent extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String result = "";
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
int data = reader.read();
while (data >= 0) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
myDatabase.execSQL("CREATE TABLE IF NOT EXISTS content(id INTEGER PRIMARY KEY, title VARCHAR, url VARCHAR)");
cursor = myDatabase.rawQuery("SELECT COUNT(*) FROM content", null);
cursor.moveToFirst();
int count = cursor.getInt(0);
if (!(count > 0)) {
JSONObject jsonObject = new JSONObject(s);
String title = jsonObject.getString("title");
Log.i("title", title);
String url = jsonObject.getString("url");
Log.i("url", url);
myDatabase.execSQL("INSERT INTO content (title, url) VALUES('" + title + "','" + url + "')");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
Got it! I fixed it. I just had to reduce the amount of news (I decided to choose the top 20 ones), and I decided to run only one ASyncTask on my app.
Here is the edited code:
PD: Thanks to #cafebabe1991 as he gave me tips on how to fix it. Thanks!
public class MainActivity extends AppCompatActivity {
ListView listView;
private SQLiteDatabase myDatabase;
ArrayList<String> titles;
ArrayList<String> urls;
ArrayAdapter arrayAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
titles = new ArrayList<>();
urls = new ArrayList<>();
arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, titles);
listView.setAdapter(arrayAdapter);
try {
myDatabase = this.openOrCreateDatabase("HackerNews", MODE_PRIVATE, null);
DownloadTask downloadTask = new DownloadTask();
String URL = "https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty";
downloadTask.execute(URL);
Cursor cursor = myDatabase.rawQuery("SELECT * FROM content", null);
int titleIndex = cursor.getColumnIndex("title");
int urlIndex = cursor.getColumnIndex("url");
cursor.moveToFirst();
while(cursor!=null){
titles.add(cursor.getString(titleIndex));
urls.add(cursor.getString(urlIndex));
cursor.moveToNext();
}
arrayAdapter.notifyDataSetChanged();
} catch (Exception e) {
e.printStackTrace();
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(getApplicationContext(), MainActivity2.class);
MainActivity2.url = urls.get(position);
startActivity(intent);
}
});
}
public class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String articleInfo = "";
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
int data = reader.read();
while (data >= 0) {
char current = (char) data;
articleInfo += current;
data = reader.read();
}
//myDatabase.execSQL("CREATE TABLE IF NOT EXISTS ids (id INTEGER PRIMARY KEY, urlID VARCHAR)");
myDatabase.execSQL("CREATE TABLE IF NOT EXISTS content (id INTEGER PRIMARY KEY, title VARCHAR, url VARCHAR)");
myDatabase.delete("content", null, null);
JSONArray ids = new JSONArray(articleInfo);
for (int i = 0; i < 20; i++) {
//myDatabase.execSQL("INSERT INTO ids (urlID) VALUES ('" + ids.getString(i) + "')");
String articleInfo2 = "";
URL url2 = new URL("https://hacker-news.firebaseio.com/v0/item/" + ids.getString(i) + ".json?print=pretty");
HttpURLConnection urlConnection2 = (HttpURLConnection) url2.openConnection();
InputStream inputStream2 = urlConnection2.getInputStream();
InputStreamReader reader2 = new InputStreamReader(inputStream2);
int data2 = reader2.read();
while (data2 >= 0) {
char current2 = (char) data2;
articleInfo2 += current2;
data2 = reader2.read();
}
JSONObject jsonObject = new JSONObject(articleInfo2);
String title = "'" + jsonObject.getString("title").replaceAll("'", "") + "'";
String articleURL = "'" + jsonObject.getString("url") + "'";
myDatabase.execSQL("INSERT INTO content (title, url) VALUES (" + title + "," + articleURL + ")");
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
}
The problem lies in this code
1.)
Cursor cursor1 = myDatabase.rawQuery("SELECT * FROM ids", null);
int index = cursor1.getColumnIndex("urlID");
cursor1.moveToFirst();
while (cursor1 != null) {
String newUrl = "https://hacker-news.firebaseio.com/v0/item/" + cursor1.getString(index) + ".json?print=pretty";
new DownloadContent().execute(newUrl);
cursor1.moveToNext();
}
How ?
You say to to cursor to get you the column index and from that you fetch the item id, but when database is empty the value will be null. Hence the api will not return a response. Additionally you do the same mistake with the cursor as mentioned in the point below.
2.)
int titleIndex = cursor2.getColumnIndex("title");
cursor2.moveToFirst();
titles.add("Hello");
while(cursor2 != null){
titles.add(cursor2.getString(titleIndex));
arrayAdapter.notifyDataSetChanged();
cursor2.moveToNext();
}
How ?
You said to the cursor to move to the first record (moveToFirst()) , what if the currently no record exist. This method returns false if the cursor is empty. So make sure that this method returns true and then proceed.
OR
Do this(Better approach)...
while(cursor.moveToNext()) {
//If inside , that means you are on the next record.Fetch the column values here
}
References :
Cursor methods
Discussion about best ways to iterate a cursor
For loading data into the listview from the database

Run Two ASyncTasks Android Studio [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Can anyone help me in fixing my code?
Apparently the problem is that I can't run more than one ASyncTask on my main thread. Can anyone give me some advise as to how I can fix my code?
Thank you!
I apologize for not commenting my code. I can explain if you guys get confused while reading it.
public class MainActivity extends AppCompatActivity {
ListView listView;
private SQLiteDatabase myDatabase;
private Cursor cursor;
boolean finished = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
myDatabase = this.openOrCreateDatabase("HackerNews", MODE_PRIVATE, null);
Cursor cursor = myDatabase.rawQuery("SELECT * FROM ids", null);
int index = cursor.getColumnIndex("urlID");
cursor.moveToFirst();
DownloadContent content = new DownloadContent();
while(cursor != null){
String newUrl = "https://hacker-news.firebaseio.com/v0/item/" + cursor.getString(index) + ".json?print=pretty";
content.execute(newUrl);
cursor.moveToNext();
}
}
public class DownloadIDs extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String result = "";
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
int data = reader.read();
while (data >= 0) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (Exception e) {
e.printStackTrace();
return "Fail";
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
myDatabase.execSQL("CREATE TABLE IF NOT EXISTS ids (id INTEGER PRIMARY KEY, urlID VARCHAR)");
cursor = myDatabase.rawQuery("SELECT COUNT(*) FROM ids", null);
cursor.moveToFirst();
int count = cursor.getInt(0);
if (!(count > 0)) {
try {
JSONArray ids = new JSONArray(s);
for (int i = 0; i < ids.length(); i++) {
myDatabase.execSQL("INSERT INTO ids (urlID) VALUES ('" + ids.getString(i) + "')");
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.i("message", "TABLE1 IS NOT EMPTY");
}
}
}
public class DownloadContent extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String result = "";
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
int data = reader.read();
while (data >= 0) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
myDatabase.execSQL("CREATE TABLE IF NOT EXISTS content(id INTEGER PRIMARY KEY, title VARCHAR, url VARCHAR)");
cursor = myDatabase.rawQuery("SELECT COUNT(*) FROM content", null);
cursor.moveToFirst();
int count = cursor.getInt(0);
if (!(count > 0)) {
try {
JSONObject jsonObject = new JSONObject(s);
String title = jsonObject.getString("title");
String url = jsonObject.getString("url");
myDatabase.execSQL("INSERT INTO content (title, url) VALUES('" + title +"','" + url + "')");
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.i("mess2", "table 2 is NOT EMPTY");
}
}
}
}
Each AsyncTask instance can only be run once. Simplest way to resolve this is to just create a new instance whenever you need to run it.
while(cursor != null) {
String newUrl = "https://hacker-news.firebaseio.com/v0/item/" + cursor.getString(index) + ".json?print=pretty";
new DownloadContent().execute(newUrl);
cursor.moveToNext();
}

Android Java JSON parser/insert database optimization

I'm not pretty sure if this question is for here, but I want to ask all of you guys, who really can give me some advices of how to optimize better this piece of code, to run better in proper way and faster. The thing that I'm doing is that I'm downloading data over internet as JSON, parsing it and insert it in sqlite database. If the json string is not big, there is not a big problem for me, but when my json contains a lot of arrays and objects in some situations I'm waiting like 10-13 minutes to download/parse/insert all data in database, which is too much time.
The code that I'm showing is some kind of test code, because I was trying to implement InsertHelper to see if there will be a bit difference in speed, but the result is the same for now. Here is the code :
UserDatabaseHelper userDbHelper = RPCCommunicator.rpcUserDbHelper;
SQLiteDatabase db = userDbHelper.getWritableDatabase();
InsertHelper ih = new InsertHelper(db, "cards");
ih.prepareForInsert();
//ContentValues values = new ContentValues();
ContentValues valuess = new ContentValues();
try {
int objectid = ih.getColumnIndex("objectId");
ih.bind(objectid, objectId);
//values.put("objectId", objectId);
Log.d("", "ObjectId: " + objectId);
int objectoid = ih.getColumnIndex("objectOid");
ih.bind(objectoid, objectOid);
//values.put("objectOid", objectOid);
String jsonData = new String(cardBuffer, "UTF-8");
Log.d("JSONDATA", "JSONDATA VALID OR NOT : " + jsonData);
json = new JSONObject(jsonData);
JSONObject jsonObj = (JSONObject) new JSONTokener(jsonData).nextValue();
int collectionID = ih.getColumnIndex("collectionId");
int collectionId = Integer.parseInt(jsonObj.optString("collection_id","0"));
Log.d("Collection Id ", "Show Collection Id : " + collectionId);
if(collectionId!=0)
ih.bind(collectionID, collectionId);
//values.put("collectionId", collectionId);
int categoryID = ih.getColumnIndex("categoryId");
int categoryId = Integer.parseInt(jsonObj.optString("category_id", "0"));
Log.d("Category Id ", "Show Category Id : " + categoryId);
if(categoryId!=0)
ih.bind(categoryID, categoryId);
//values.put("categoryId", categoryId);
int dateCreated = ih.getColumnIndex("dateCreated");
String date = jsonObj.optString("date_created");
if(date!=null)
ih.bind(dateCreated, date);
//values.put("dateCreated", date);
int titlee = ih.getColumnIndex("title");
String title = jsonObj.optString("title");
Log.d("Title", "Show Title : " + title);
if(title!=null)
ih.bind(titlee, title);
//values.put("title", title);
// ... some other variables to get from JSON
JSONObject stats = jsonObj.optJSONObject("statistics");
if (jsonObj.has("statistics")) {
ContentValues values2 = new ContentValues();
InsertHelper ihr = new InsertHelper(db, "cardstats");
Iterator<Object> keys = stats.keys();
while (keys.hasNext()) {
ihr.prepareForInsert();
String key = (String) keys.next();
JSONObject obj = new JSONObject();
obj = stats.getJSONObject(key);
int paramId = Integer.parseInt(obj.optString("param_id"));
int cardIdTable = ihr.getColumnIndex("cardId");
ihr.bind(cardIdTable, objectId);
values2.put("cardId", objectId);
int statKey = ihr.getColumnIndex("statKeyId");
ihr.bind(statKey, paramId);
values2.put("statKeyId", paramId);
int catIdTable = ihr.getColumnIndex("catId");
int catId = Integer.parseInt(obj.optString("cat_id"));
ihr.bind(catIdTable, catId);
values2.put("catId", catId);
int paramtitle = ihr.getColumnIndex("title");
String paramTitle = obj.optString("param_title");
ihr.bind(paramtitle, paramTitle);
values2.put("title", paramTitle);
String cardstats = "SELECT cardId , statKeyId FROM cardstats WHERE cardId="+objectId+" AND statKeyId="+catId;
Cursor cardStats = userDbHelper.executeSQLQuery(cardstats);
if(cardStats.getCount()==0){
//userDbHelper.executeQuery("cardstats", values2);
ihr.execute();
} else {
for(cardStats.moveToFirst(); cardStats.moveToNext(); cardStats.isAfterLast()){
//int card = Integer.parseInt(cardStats.getString(cardStats.getColumnIndex("cardId")));
int statId = Integer.parseInt(cardStats.getString(cardStats.getColumnIndex("statKeyId")));
if(paramId != statId){
ihr.execute();
//userDbHelper.executeQuery("cardstats", values2);
} else {
userDbHelper.updateSQL("cardstats", values2, "cardId=?", new String[]{Integer.toString(objectId)});
}
}
}
cardStats.close();
//userDbHelper.executeQuery("cardstats", values2);
}
}// end if
String sql = "SELECT objectId FROM cards WHERE objectId = " + objectId;
Cursor cursor = userDbHelper.executeSQLQuery(sql);
if (cursor.getCount() == 0) {
ih.execute();
//userDbHelper.executeQuery("cards", values);
} else {
for (cursor.move(0); cursor.moveToNext(); cursor.isAfterLast()) {
int objectID = Integer.parseInt(cursor.getString(cursor.getColumnIndex("objectId")));
Log.d("","objectId : objectID - "+objectId+" "+objectID );
if (objectId != objectID) {
ih.execute();
//userDbHelper.executeQuery("cards", values);
} else if(objectId == objectID){
userDbHelper.updateSQL("cards", valuess, "objectId=?", new String[] {Integer.toString(objectId)});
}
}
}
cursor.close();
} catch (Exception e) {
e.printStackTrace();
Log.d("Error", ": " + e);
}
db.close();
return true;
}
*Edit: *
And here is how I save the binary data (images) which I get from internet :
public static void saveToExternalStorage(String servername, int userId, String filename, byte[] buffer){
try {
File myDir=new File("/sdcard/.Stampii/Users/"+servername+"/"+userId+"/Storage");
myDir.mkdirs();
File file = new File(myDir, filename);
FileOutputStream fos = new FileOutputStream(file);
fos.write(buffer);
fos.flush();
fos.close();
} catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
So any kind of suggestions/advices are welcomed which will help me to improve this piece of code and make it run faster.
Thanks in advance!
Even if you have a lot of HTTP traffic (which you appear to have) you can still optimize your use of the database.
This naïve example that does 10000 inserts will show you the scale of improvement we're talking about here:
public class BombasticActivity extends Activity {
DBHelper mHelper;
SQLiteDatabase mDb;
InsertHelper mInsertHelper;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mHelper = new DBHelper(this);
mDb = mHelper.getWritableDatabase();
mInsertHelper = new InsertHelper(mDb, "table1");
}
#Override
protected void onStart() {
super.onStart();
AsyncTask.SERIAL_EXECUTOR.execute(new MeasureTime(new Insert(10000, mInsertHelper)));
AsyncTask.SERIAL_EXECUTOR.execute(new MeasureTime(new DoInTransaction(mDb, new Insert(10000, mInsertHelper))));
}
#Override
protected void onDestroy() {
super.onDestroy();
mInsertHelper.close();
mDb.close();
mHelper.close();
}
static class MeasureTime implements Runnable {
final Runnable mAction;
MeasureTime(Runnable action) {
mAction = action;
}
public void run() {
final String name = mAction.getClass().getSimpleName();
System.out.println("Starting action (" + name + ")");
long t0 = System.currentTimeMillis();
try {
mAction.run();
} finally {
t0 = System.currentTimeMillis() - t0;
System.out.println("Time to complete action (" + name + "): " + t0 + "ms");
}
}
}
static class DoInTransaction implements Runnable {
final Runnable mAction;
final SQLiteDatabase mDb;
DoInTransaction(SQLiteDatabase db, Runnable action) {
mAction = action;
mDb = db;
}
public void run() {
mDb.beginTransaction();
try {
mAction.run();
mDb.setTransactionSuccessful();
} finally {
mDb.endTransaction();
}
}
}
static class Insert implements Runnable {
final int mNumberOfInserts;
final InsertHelper mInsertHelper;
Insert(int numberOfInserts, InsertHelper insertHelper) {
mNumberOfInserts = numberOfInserts;
mInsertHelper = insertHelper;
}
public void run() {
Random rnd = new Random(0xDEADBEEF);
ContentValues values = new ContentValues();
for (int i = 0; i < mNumberOfInserts; i++) {
values.put("text1", String.valueOf(rnd.nextDouble()));
values.put("text2", String.valueOf(rnd.nextFloat()));
values.put("text3", String.valueOf(rnd.nextLong()));
values.put("int1", rnd.nextInt());
mInsertHelper.insert(values);
if (i % 200 == 0) {
System.out.println("Done " + i + " inserts");
}
}
}
}
}
class DBHelper extends SQLiteOpenHelper {
DBHelper(Context context) {
super(context.getApplicationContext(), "bombastic", null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE table1 (_id INTEGER PRIMARY KEY AUTOINCREMENT, text1 TEXT, text2 TEXT, text3 TEXT, int1 INTEGER)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
On an ICS device (you can run it on Gingerbread if you start a thread or threadpool instead of abusing AsyncTask.SERIAL_EXECUTOR) the non-transaction version takes almost 4 minutes to complete (229484ms) while the version running in the transaction only takes about 3 seconds (2975ms).
So put it shortly, do a lot of updates - do it in a transaction.
To optimize your HTTP you should ensure that you are keeping the HTTP connection alive (keep-alive) and downloading larger chunks. Much larger than the ones you are doing now - if possible switch to a JSON parser that supports reading from a stream instead of loading the entire thing into a String before parsing it.
There are two time consuming activity involved in your case.
a. Downloading data in packets (assuming it to be HTTP). For a single packet it should take you about 1-3 sec depending on the network latency.
For 200 = 2X100 = 200 seconds ~ 3 mins
You can save lots of seconds, if you download entire data in say not more than 3-5 round-trip calls.
b. Database insert
You need to do file operation specifically write file operation which takes time. Honestly you cannot much optimization here
Check my other answer here

Categories

Resources