android - How to stop a thread in a service -
today have problem in android project. use service thread in log location information in period of 10s. however, when change screen orientation (portrait -> landscape), period messed up.
i think may run thread got 1 more thread running behind once rotate screen. have print log messages , seems guessing right.
here code:
public class locationservice extends service { public location loc; public locationservice() { } @override public int onstartcommand(intent intent, int flags, int id) { thread thread = new thread(new runnable() { @override public void run() { locationmanager locationmanager = (locationmanager)getsystemservice(context.location_service); if ( contextcompat.checkselfpermission(locationservice.this, android.manifest.permission.access_coarse_location ) == packagemanager.permission_granted ) { loc = locationmanager.getlastknownlocation(locationmanager.gps_provider); if(loc == null) // fall network if gps not available { loc = locationmanager.getlastknownlocation(locationmanager.network_provider); } if(loc != null) { timer timer = new timer(); final string time = (new date()).tostring(); timer.scheduleatfixedrate(new timertask() { @override public void run() { log.d(time, "hehe"); double currentlat = loc.getlatitude(); double currentlng = loc.getlongitude(); intent done = new intent(); done.setaction("location"); done.putextra("currentlat", currentlat); done.putextra("currentlng", currentlng); sendbroadcast(done); //toast.maketext(locationservice.this, string.valueof(currentlat) + string.valueof(currentlng), toast.length_long).show(); } }, 10000, 10000); } } else { toast.maketext(locationservice.this, "please allow app access location", toast.length_long).show(); } } }); thread.start(); return start_sticky; // stay running } @override public ibinder onbind(intent intent) { // // todo: return communication channel service. // throw new unsupportedoperationexception("not yet implemented"); return null; } // @override // public void ondestroy() // { // log.d("hehe","ondestroy"); // super.ondestroy(); // } }
here code activity:
public class mainactivity extends appcompatactivity { private toolbar toolbar; private fragmentmanager fragmentmanager; private localfragment localfragment; private serverfragment serverfragment; private queryfragment queryfragment; private fragmenttransaction transaction; public sqlitehelper dbhelper; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); dbhelper = new sqlitehelper(this); //garb handlers fragmentmanager = getfragmentmanager(); localfragment = (localfragment) fragmentmanager.findfragmentbyid(r.id.fragment_local); serverfragment = (serverfragment) fragmentmanager.findfragmentbyid(r.id.fragment_server); queryfragment = (queryfragment) fragmentmanager.findfragmentbyid(r.id.fragment_query); // initial visibility transaction = fragmentmanager.begintransaction(); if(this.getresources().getconfiguration().orientation == configuration.orientation_portrait) { // toolbar (must put in checking orientation because landscape layout not have toolbar here) toolbar = (toolbar) findviewbyid(r.id.toolbar); toolbar.settitle(r.string.toolbar_title); setsupportactionbar(toolbar); transaction.show(localfragment); transaction.hide(serverfragment); transaction.hide(queryfragment); transaction.commit(); } else // orientation_landscape { transaction.hide(queryfragment); // landscape orientation not need query function (?) transaction.show(localfragment); transaction.show(serverfragment); transaction.commit(); } // register network status receiver intentfilter intentfilter = new intentfilter(); intentfilter.addaction(connectivitymanager.connectivity_action); networkstatusreceiver mynetworkreceiver = new networkstatusreceiver(); registerreceiver(mynetworkreceiver, intentfilter); // start location service intent intent = new intent(this, locationservice.class); intent.setaction("location"); startservice(intent); // register location receiver intentfilter intentfilterlocation = new intentfilter(); intentfilterlocation.addaction("location"); locationreceiver mylocationreceiver = new locationreceiver(); registerreceiver(mylocationreceiver, intentfilterlocation); } @override public boolean oncreateoptionsmenu(menu menu) { menuinflater inflater = getmenuinflater(); inflater.inflate(r.menu.menu_main_activity, menu); return super.oncreateoptionsmenu(menu); } @override public boolean onoptionsitemselected(menuitem item) { transaction = fragmentmanager.begintransaction(); // handle click event if(item.getitemid() == r.id.action_online) { transaction.hide(localfragment); transaction.hide(queryfragment); transaction.show(serverfragment); transaction.commit(); } else if(item.getitemid() == r.id.action_offline) { transaction.hide(serverfragment); transaction.hide(queryfragment); transaction.show(localfragment); transaction.commit(); } else // query { transaction.hide(localfragment); transaction.hide(serverfragment); transaction.show(queryfragment); transaction.commit(); } return super.onoptionsitemselected(item); } // receiver network change action private class networkstatusreceiver extends broadcastreceiver { @override public void onreceive(context context, intent intent) { string action = intent.getaction(); if (action.equals(connectivitymanager.connectivity_action)) // if receive network change event broadcast { toast.maketext(context, "network status changed!", toast.length_long).show(); // why cannot use thread so? calledfromwrongthreadexception: original thread created view hierarchy can touch views. // thread thread = new thread(new runnable() // { // @override // public void run() // { int type = 0; connectivitymanager connectivitymanager = (connectivitymanager) getsystemservice(context.connectivity_service); networkinfo networkinfo = connectivitymanager.getactivenetworkinfo(); // current network type if (networkinfo != null && networkinfo.isavailable()) { type = networkinfo.gettype(); string typename = networkinfo.gettypename(); // (?) //serverfragment = (serverfragment)fragmentmanager.findfragmentbyid(r.id.fragment_server); if (type == connectivitymanager.type_wifi) // wifi { wifimanager wifimanager = (wifimanager) getsystemservice(wifi_service); wifiinfo wifiinfo = wifimanager.getconnectioninfo(); log.d("wifiinfo", wifiinfo.tostring()); log.d("ssid",wifiinfo.getssid()); serverfragment.setnetworkstatustext("wifi: " + wifiinfo.getssid()); // thread issues here. wtf } else if (type == connectivitymanager.type_mobile) // cellar { serverfragment.setnetworkstatustext("mobile data"); } else // no network { serverfragment.setnetworkstatustext("no network"); } } else // no network { serverfragment.setnetworkstatustext("no network"); } // } // }); // thread.start(); } } } // receiver location per 10s public class locationreceiver extends broadcastreceiver { @override public void onreceive(context context, intent intent) { string action = intent.getaction(); if(action.equals("location")) { double currentlat = intent.getdoubleextra("currentlat", 0.0); double currentlng = intent.getdoubleextra("currentlng", 0.0); date = new date(); localfragment.addnewlocation(now, currentlat, currentlng); // add list listview // todo: 11/5/16 implement sqlite insert dbhelper.addentry(now, currentlat, currentlng); toast.maketext(mainactivity.this, "current location: " + string.valueof(currentlat) + ", " + string.valueof(currentlng), toast.length_long).show(); } } } public void setnetworkstatus(string networkstatus) { serverfragment.setnetworkstatustext(networkstatus); } }
my question are:
- it seems
ondestroy ()
method not called when rotate screen? - a new
service
not created when rotate screen? - how can stop thread created previously? or best way handle problem?
it seems
ondestroy()
method not called when rotate screen?
no, isn't. changing screen orientation kills activity
, creates new one, service
still running. screen orientation has no effect on this.
a new
service
not created when rotate screen?
no. service
singleton. android not create new instance of service
if there 1 running. however, onstartcommand()
called again because activity
calls startservice()
when created.
how can stop thread created previously? or best way handle problem?
the easiest way deal check in onstartcommand()
if thread running. if so, don't need start again. save reference thread
in member variable (a field) in service
, call isalive()
on see if running.
also, in ondestroy()
should make sure thread
shuts down, otherwise continue run after service
dead. should create boolean
member variable (field) in thread
, check in each loop. in ondestroy()
of service
, set boolean
thread
exits.
Comments
Post a Comment