java - Android Service only runs whilst debugging -


background

i creating service syncs local realm database (stored on phone) online database. database stores users , measurements.

i initialise service calling 'startservice(new intent(this, syncservice.class));' during splash activity's oncreate() method, , specify in manifest service should run length of application.

the service has broadcast receiver. when receiver detects network change 'not connected' 'connected', fires method called syncdatabases().

this method finds measurements recorded locally after timestamp of last api callback, , sends them database. api responds request returning object + unique id.

when measurement made whilst device offline, stored locally. when internet connection made, syncdatabases() method should called in order update online server local measurements.

my steps...

steps when debugging project:

with wifi open app , external device make new measurement. appears on both app , in database. turn wifi off , make measurement - appears on device.

i attach debugger.

i turn on wifi , triggers services' receivers' onreceive() method. step through , works according plan. reach syncdatabases() method, , there receive callback api, , updates realm database new id value.

the problem...

if don't attach debugger, nothing happens. new measurements aren't pushed database, , none of log.e calls printed.

why happening? , there alternative solution / fix problem?

code

service class

public class syncservice extends service {                private static final string tag = "syncservice";          private boolean mconnected = false;                private broadcastreceiver mreceiver = new broadcastreceiver() {              @override              public void onreceive(context context, intent intent) {                  if (intent.getextras() != null) {                            final connectivitymanager connectivitymanager = (connectivitymanager) context.getsystemservice(context.connectivity_service);                      final networkinfo netinfo = connectivitymanager.getactivenetworkinfo();                            if (netinfo != null) {                                switch (netinfo.getstate()) {                              case connected:                                  if (!mconnected) {                                      log.e("network", "network " + netinfo.gettypename() + " connected");                                      syncdatabases();                                      mconnected = true;                                  }                                  break;                                    default:                                  mconnected = false;                                  break;                          }                      } else mconnected = false;                  }              }          };                @override          public void oncreate() {              super.oncreate();              initreceiver();              connectivitymanager connectivitymanager = (connectivitymanager) getapplicationcontext().getsystemservice(context.connectivity_service);                    if (connectivitymanager.getactivenetworkinfo() != null) {                  mconnected = true;              }              android.util.log.e(tag, "oncreate: syncservice created");          }                @override          public void ondestroy() {              super.ondestroy();              uninitreceiver();              android.util.log.e(tag, "ondestroy: syncservice destroyed");          }                @nullable          @override          public ibinder onbind(intent intent) {              android.util.log.e(tag, "onbind: syncservice bound");              return null;          }                @override          public boolean onunbind(intent intent) {              android.util.log.e(tag, "onunbind: syncservice unbound");              return super.onunbind(intent);          }                @override          public void onrebind(intent intent) {              super.onrebind(intent);              android.util.log.e(tag, "onrebind: syncservice rebound");          }                private void initreceiver() {              intentfilter filters = new intentfilter();              filters.addaction("android.net.wifi.wifi_state_changed");              filters.addaction("android.net.wifi.state_change");              registerreceiver(mreceiver, filters);          }                private void uninitreceiver() {              unregisterreceiver(mreceiver);          }                public void syncdatabases() {              realmresults<userdb> users = realmdb.getinstance(getapplicationcontext()).where(userdb.class).findall();                    if (users.size() > 0) {                  int userid = users.get(0).getmuserid();                  log.e("message", preferenceutils.getinstance().getlastsyncdate());                        date lastsync = null;                  simpledateformat sdf = new simpledateformat("eee mmm dd hh:mm:ss zzz yyyy", locale.getdefault());                        try {                      lastsync = sdf.parse(preferenceutils.getinstance().getlastsyncdate());                  }                  catch (parseexception e) {                      e.printstacktrace();                            try {                          lastsync = basefragment.format.parse(preferenceutils.getinstance().getlastsyncdate());                      }                      catch (parseexception e1) {                          e1.printstacktrace();                      }                  }                        if (lastsync != null) {                      date lastsyncoffset = new date(lastsync.gettime() + 1000);                      /** local results have been made after last sync date
     **/                      realmresults<measurementdb> newlocalmeasurements = realmdb.getinstance(getapplicationcontext())                              .where(measurementdb.class).equalto("user_id", userid)                              .greaterthan("datecreated", lastsyncoffset)                              .findall();                            /** each measurement made after last sync, add server
     **/                      (measurementdb measurement : newlocalmeasurements) {                          temperaturelistener mlistener = new temperaturelistener(measurement);                          apirequest.getinstance(getapplicationcontext()).registernewmeasurement(measurement.getaverage(),                                  measurement.getdatecreated().tostring(), mlistener, mlistener);                      }                  }              }          }                /**           * temperature listener receives local copy of temperature item. onresponse can           * directly mutate object instead of searching local db           */          private class temperaturelistener implements response.listener<measurement>, response.errorlistener {              private measurementdb measurement;                    public temperaturelistener(measurementdb measurement) {                  this.measurement = measurement;              }                    @override              public void onerrorresponse(volleyerror error) {                  log.e("onresponse", "failure");              }                    @override              public void onresponse(measurement response) {                  log.e("onresponse", "success");                        /** update our local measurement's id value (supplied server)
     **/                  realmdb.getinstance(getapplicationcontext()).begintransaction();                  measurement.setmeasurement_id(response.getmmeasurementid());                  realmdb.getinstance(getapplicationcontext()).committransaction();                        /** update last sync date
     **/                  preferenceutils.getinstance().setlastsyncdate(response.getmdatecreated());              }          }      }

initialisation of service in splash activity

@override     protected void oncreate(bundle savedinstancestate) {         super.oncreate(savedinstancestate);          setcontentview(r.layout.activity_splash);          new handler().postdelayed(new runnable() {             @override             public void run() {                 mtimedout = true;                 finishactivity();             }         }, duration);      /** sync application / cloud databases in background of app when network connected. **/     startservice(new intent(this, syncservice.class));     doapiwork(); } 

manifest entry

stop task kill service @ same time app. exported 'false' stops other apps using service.

    <service         android:name=".network.syncservice"         android:stopwithtask="true"         android:enabled="true"         android:exported="false"/> 

edit removed service , left receiver class, registered in manifest, triggers methods on class when needed. the receiver triggered in debug mode.


Comments