java - Why is my background service or my broadcast receiver being killed with main activity? -
i want independent running service pushbullet, smartlockscreen or whatsapp has, waiting event happen. have tried foreground service, returning start_sticky in onstartcommand, restarting service in ontaskremoved , running service in separate process using android:process.
my service class:
public class callservice extends service { @override public ibinder onbind(intent intent) { // todo auto-generated method stub return null; } @override public int onstartcommand (intent intent, int flags, int startid){ notificationcompat.builder builder = new notificationcompat.builder(this); builder.setsmallicon(r.drawable.icon) .setcontenttitle("title") .setcontenttext("text") .setautocancel(true) .setongoing(true); intent startintent = new intent(this, mainactivity.class); pendingintent contentintent = pendingintent.getactivity(this, 1, startintent, 0); builder.setcontentintent(contentintent); this.startforeground(1, builder.build()); super.onstartcommand(intent, flags, startid); return start_sticky; } @override public void oncreate() { super.oncreate(); } @override public void ondestroy() { super.ondestroy(); } @override public void ontaskremoved(intent rootintent){ intent restartserviceintent = new intent(getapplicationcontext(), this.getclass()); restartserviceintent.setpackage(getpackagename()); pendingintent restartservicependingintent = pendingintent.getservice(getapplicationcontext(), 1, restartserviceintent, pendingintent.flag_one_shot); alarmmanager alarmservice = (alarmmanager) getapplicationcontext().getsystemservice(context.alarm_service); alarmservice.set( alarmmanager.elapsed_realtime, systemclock.elapsedrealtime() + 1000, restartservicependingintent); super.ontaskremoved(rootintent); } my androidmanifest.xml
<service android:name=".callservice" android:persistent="true"> <intent-filter> <action android:name="cz.volamakler.callservice" /> </intent-filter> </service> <receiver android:name=".callreceiver"> <intent-filter> <action android:name="android.intent.action.phone_state" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.new_outgoing_call" /> </intent-filter> </receiver> i tried using broadcast receiver , gets killed main activity too.
public abstract class phonecallreceiver extends broadcastreceiver { //the receiver recreated whenever android feels it. need static variable remember data between instantiations private static int laststate = telephonymanager.call_state_idle; private static date callstarttime; private static boolean isincoming; private static string savednumber; //because passed incoming valid in ringing @override public void onreceive(context context, intent intent) { //we listen 2 intents. new outgoing call tells of outgoing call. use number. if (intent.getaction().equals("android.intent.action.new_outgoing_call")) { savednumber = intent.getextras().getstring("android.intent.extra.phone_number"); } else{ string statestr = intent.getextras().getstring(telephonymanager.extra_state); string number = intent.getextras().getstring(telephonymanager.extra_incoming_number); int state = 0; if(statestr.equals(telephonymanager.extra_state_idle)){ state = telephonymanager.call_state_idle; } else if(statestr.equals(telephonymanager.extra_state_offhook)){ state = telephonymanager.call_state_offhook; } else if(statestr.equals(telephonymanager.extra_state_ringing)){ state = telephonymanager.call_state_ringing; } oncallstatechanged(context, state, number); } } //derived classes should override these respond specific events of interest protected void onincomingcallstarted(context ctx, string number, date start){} protected void onoutgoingcallstarted(context ctx, string number, date start){} protected void onincomingcallended(context ctx, string number, date start, date end){} protected void onoutgoingcallended(context ctx, string number, date start, date end){} protected void onmissedcall(context ctx, string number, date start){} //deals actual events //incoming call- goes idle ringing when rings, offhook when it's answered, idle when hung //outgoing call- goes idle offhook when dials out, idle when hung public void oncallstatechanged(context context, int state, string number) { if(laststate == state){ //no change, debounce extras return; } switch (state) { case telephonymanager.call_state_ringing: isincoming = true; callstarttime = new date(); savednumber = number; onincomingcallstarted(context, number, callstarttime); break; case telephonymanager.call_state_offhook: //transition of ringing->offhook pickups of incoming calls. nothing done on them if(laststate != telephonymanager.call_state_ringing){ isincoming = false; callstarttime = new date(); onoutgoingcallstarted(context, savednumber, callstarttime); } break; case telephonymanager.call_state_idle: //went idle- end of call. type depends on previous state(s) if(laststate == telephonymanager.call_state_ringing){ //ring no pickup- miss onmissedcall(context, savednumber, callstarttime); } else if(isincoming){ onincomingcallended(context, savednumber, callstarttime, new date()); } else{ onoutgoingcallended(context, savednumber, callstarttime, new date()); } break; } laststate = state; } } public class callreceiver extends phonecallreceiver { @override protected void onincomingcallstarted(context ctx, string number, date start) { toast.maketext(ctx, "call!", toast.length_long).show(); } @override protected void onoutgoingcallstarted(context ctx, string number, date start) { } @override protected void onincomingcallended(context ctx, string number, date start, date end) { } @override protected void onoutgoingcallended(context ctx, string number, date start, date end) { } @override protected void onmissedcall(context ctx, string number, date start) { } }
this happening because running service in same ui thread. looper used same of application's ui thread starting service. need following:
create seperate handler thread. tasks inside handlemessage.
public class callservice extends service { private looper mservicelooper; private servicehandler mservicehandler; // handler receives messages thread private final class servicehandler extends handler { public servicehandler(looper looper) { super(looper); } @override public void handlemessage(message msg) { // work here, download file. // our sample, sleep 5 seconds. long endtime = system.currenttimemillis() + 5*1000; while (system.currenttimemillis() < endtime) { synchronized (this) { try { wait(endtime - system.currenttimemillis()); } catch (exception e) { } } } // stop service using startid, don't stop // service in middle of handling job stopself(msg.arg1); } } @override public ibinder onbind(intent intent) { // todo auto-generated method stub return null; } @override public int onstartcommand (intent intent, int flags, int startid){ // each start request, send message start job , deliver // start id know request we're stopping when finish job message msg = mservicehandler.obtainmessage(); msg.arg1 = startid; mservicehandler.sendmessage(msg); return start_sticky; } @override public void oncreate() { // start thread running service. note create // separate thread because service runs in process's // main thread, don't want block. make // background priority cpu-intensive work not disrupt our ui. handlerthread thread = new handlerthread("servicestartarguments", process.thread_priority_background); thread.start(); // handlerthread's looper , use our handler mservicelooper = thread.getlooper(); mservicehandler = new servicehandler(mservicelooper); } @override public void ondestroy() { super.ondestroy(); } @override public void ontaskremoved(intent rootintent){ intent restartserviceintent = new intent(getapplicationcontext(), this.getclass()); restartserviceintent.setpackage(getpackagename()); pendingintent restartservicependingintent = pendingintent.getservice(getapplicationcontext(), 1, restartserviceintent, pendingintent.flag_one_shot); alarmmanager alarmservice = (alarmmanager) getapplicationcontext().getsystemservice(context.alarm_service); alarmservice.set( alarmmanager.elapsed_realtime, systemclock.elapsedrealtime() + 1000, restartservicependingintent); super.ontaskremoved(rootintent); } } i hope helps.
Comments
Post a Comment