Search code examples
androidsqliteandroid-volleyjobservice

JobService not working properly while posting data to server using volley


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


Solution

  • 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