-1

I'm trying to sync SQLite data with mysql, for this created JobService which sync data every 15 seconds(Sync only those data which status unsync with mysql). This works perfectly with localhost(xampp server). but problems occurred with web server : it results duplicate entries with every 15 seconds of JobService.

MyService.java

    public class MyService extends JobService {

    private DatabaseHelper db;
    SQLiteDatabase sqLiteDatabase;

    private Handler mJobHandler = new Handler( new Handler.Callback() {
        @Override
        public boolean handleMessage( Message msg ) {
            Toast.makeText( getApplicationContext(), "JobService task running", Toast.LENGTH_SHORT ).show();
            jobFinished( (JobParameters) msg.obj, false );
            return true;
        }
    } );

    @Override
    public boolean onStartJob(JobParameters params ) {
        mJobHandler.sendMessage( Message.obtain( mJobHandler, 1, params ) );
        db = DatabaseHelper.getInstance(getApplicationContext());
        postData();
        //db.close();
        return true;
    }

    @Override
    public boolean onStopJob( JobParameters params ) {
        mJobHandler.removeMessages( 1 );
        return false;
    }

    private void postData() {

        Cursor cursor = db.getUnsyncedNames();
        try {
            if (cursor != null) {

                if (cursor.moveToFirst()) {

                    do {
                        saveName(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.COLUMN_ID)), cursor.getString(cursor.getColumnIndex(DatabaseHelper.COLUMN_FROM_NO)), cursor.getString(cursor.getColumnIndex(DatabaseHelper.COLUMN_TO_NO)));
                    } while (cursor.moveToNext());
                }
            }
        }  finally {
            if (cursor != null && !cursor.isClosed())
                cursor.close();
            db.close();
        }
    }

    private void saveName(final int id, final String fromNo, final String toNo) {
        StringRequest stringRequest = new StringRequest(Request.Method.POST, Config.URL_REQUEST_SMS,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        try {
                            JSONObject obj = new JSONObject(response);
                            if (!obj.getBoolean("error")) {
                                //updating the status in sqlite
                                db.updateNameStatus(id,NAME_SYNCED_WITH_SERVER);

                                sqLiteDatabase = db.getWritableDatabase();
                                if (sqLiteDatabase != null) {
                                    sqLiteDatabase.delete(DatabaseHelper.TABLE_NAME, null, null);
                                }
                               // db.close();

                                Toast.makeText(getApplicationContext(),"Unsynced no. submitted!",Toast.LENGTH_LONG).show();

                                //calls.clear();

                            }
                        } catch (JSONException e) {
                            e.printStackTrace();

                            Toast.makeText(getApplicationContext(),"JSONException error1 : "+e,Toast.LENGTH_LONG).show();

                        }
                        finally {
                            db.close();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(getApplicationContext(),"VolleyError error2 : "+error,Toast.LENGTH_LONG).show();
                        error.printStackTrace();
                    }
                }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<>();
                params.put("mobile", fromNo);
                params.put("toMob", toNo);
                return params;
            }
        };

                int socketTimeout = 60000;
                RetryPolicy policy = new DefaultRetryPolicy(socketTimeout,
                        DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
                stringRequest.setRetryPolicy(policy);

        MyApplication.getInstance().addToRequestQueue(stringRequest);
    }
}

MainActivity.java

  JobInfo.Builder builder = new JobInfo.Builder( 1,
            new ComponentName( getPackageName(), MyService.class.getName() ) );

    builder.setPeriodic(15000);

also my logcat shows

E/Surface: getSlotFromBufferLocked: unknown buffer: 0x7f517cd1b540

Thientvse
  • 1,753
  • 1
  • 14
  • 23
Omkar
  • 3,040
  • 1
  • 22
  • 42

2 Answers2

1

Yeah I had the same issue, turns out that volley once allocates the memory, does not de-allocate the memory. It bloats up the memory and forces an os GC, which will stop all such services, Moved to Retrofit 2 with Job service works perfectly

The best solution is to move to retrofit 2. as we have stress tested it

Niraj Sanghani
  • 1,493
  • 15
  • 23
0

Your Handler is circumventing the entire JobService process. It is marking the job as successfully finished even before it actually has finished.

I see multiple issues with the code provided:

  • All of your database logic is happening on the main thread instead of a background thread.
  • You are creating a new database connection for every job.
  • You are leaking database connections (because you are not connecting or running the query inside the try block).

I really don't think your problem is with Volley.

Paul Smith
  • 166
  • 3
  • 13