time - Android: How to set a timer that notifies you, even if app is minimized? -
i want ability set reusable timer (e.g. 20 seconds) , have start counting down, minimize app, else, , have timer still notify me. timer should start / stop / pause / reset-able.
i've seen alarmmanager read seems broken on several devices. there more robust solution?
edit: trying service
the manifest:
<?xml version="1.0" encoding="utf-8"?> <manifest package="com.packagename.timertest" xmlns:android="http://schemas.android.com/apk/res/android"> <application android:allowbackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundicon="@mipmap/ic_launcher_round" android:supportsrtl="true" android:theme="@style/apptheme"> <activity android:name=".mainactivity"> <intent-filter> <action android:name="android.intent.action.main"/> <category android:name="android.intent.category.launcher"/> </intent-filter> </activity> <service android:name=".timerservice" android:exported="false"/> </application> </manifest>
mainactivity launching fragment:
public class mainactivity extends appcompatactivity { private button launchtimerpanelbutton; private fragmentmanager fragmentmanager; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); fragmentmanager = getsupportfragmentmanager(); launchtimerpanelbutton = (button) findviewbyid(r.id.launch_timer_button); launchtimerpanelbutton.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { timerdialogfragment dialogfragment = timerdialogfragment.newinstance(10); dialogfragment.setstyle(dialogfragment.style_normal, r.style.customdialog); dialogfragment.show(fragmentmanager,""); } }); } }
the xml mainactivity:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.constraintlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.packagename.timertest.mainactivity"> <button android:id="@+id/launch_timer_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="launch timer panel"/> </android.support.constraint.constraintlayout>
the dialogfragment:
public class timerdialogfragment extends dialogfragment { private static final string argument_num_seconds = "state_num_seconds"; private static final string state_num_seconds = "state_num_seconds"; public static final string state_is_broadcast_receiver_registered = "state_is_broadcast_receiver_registered"; private int numsecondsinitial; private int numseconds; private textview secondsremainingtextview; private button startbutton; private button pausebutton; private button resetbutton; private button closebutton; private broadcastreceiver resttimerreceiver; private boolean isbroadcastreceiverregistered; public static timerdialogfragment newinstance(int numseconds) { bundle args = new bundle(); timerdialogfragment fragment = new timerdialogfragment(); args.putint(argument_num_seconds, numseconds); fragment.setarguments(args); return fragment; } @override public void oncreate(@nullable bundle savedinstancestate) { super.oncreate(savedinstancestate); numsecondsinitial = getarguments().getint(argument_num_seconds); if (savedinstancestate == null) { numseconds = numsecondsinitial; } else { numseconds = savedinstancestate.getint(state_num_seconds); } isbroadcastreceiverregistered = false; if (savedinstancestate != null) { isbroadcastreceiverregistered = savedinstancestate.getboolean(state_is_broadcast_receiver_registered); } resttimerreceiver = new broadcastreceiver() { @override public void onreceive(context context, intent intent) { //??????? } }; registerbroadcastreceiver(); } @nullable @override public view oncreateview(layoutinflater inflater, @nullable viewgroup container, @nullable bundle savedinstancestate) { view contentview = inflater.inflate(r.layout.dialogfragment_timer, container, false); getdialog().settitle("timer"); secondsremainingtextview = (textview) contentview.findviewbyid(r.id.seconds_remaining_textview); secondsremainingtextview.settext(numseconds + ""); startbutton = (button) contentview.findviewbyid(r.id.start_button); pausebutton = (button) contentview.findviewbyid(r.id.pause_button); resetbutton = (button) contentview.findviewbyid(r.id.reset_button); closebutton = (button) contentview.findviewbyid(r.id.close_button); startbutton.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { } }); pausebutton.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { } }); resetbutton.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { } }); closebutton.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { //end timer first? unregisterbroadcastreceiver(); dismiss(); } }); return contentview; } @override public void onsaveinstancestate(bundle outstate) { outstate.putint(state_num_seconds, numseconds); super.onsaveinstancestate(outstate); } @override public void onresume() { registerbroadcastreceiver(); super.onresume(); } @override public void onpause() { unregisterbroadcastreceiver(); super.onpause(); } @override public void ondestroy() { unregisterbroadcastreceiver(); super.ondestroy(); } private void registerbroadcastreceiver() { if (!isbroadcastreceiverregistered) { localbroadcastmanager.getinstance(getactivity()).registerreceiver(resttimerreceiver, new intentfilter(timerservice.timer_service)); isbroadcastreceiverregistered = true; } } private void unregisterbroadcastreceiver() { if (isbroadcastreceiverregistered) { isbroadcastreceiverregistered = false; localbroadcastmanager.getinstance(getactivity()).unregisterreceiver(resttimerreceiver); } } }
its layout:
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:gravity="center"> <textview android:id="@+id/seconds_remaining_textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:textappearance="?android:attr/textappearancelarge" android:gravity="center" android:text="10"/> <button android:id="@+id/start_button" android:layout_margintop="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:textappearance="?android:attr/textappearancemedium" android:gravity="center" android:text="start timer"/> <button android:id="@+id/pause_button" android:layout_margintop="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:textappearance="?android:attr/textappearancemedium" android:gravity="center" android:text="pause timer"/> <button android:id="@+id/reset_button" android:layout_margintop="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:textappearance="?android:attr/textappearancemedium" android:gravity="center" android:text="reset timer"/> <button android:id="@+id/close_button" android:layout_margintop="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:textappearance="?android:attr/textappearancemedium" android:gravity="center" android:text="close / end timer"/> </linearlayout>
the service:
public class timerservice extends service { private string log_tag = timerservice.class.getsimplename(); public static final string timer_service = "timer_service"; @override public void oncreate() { super.oncreate(); log.i(log_tag, "oncreate"); } @override public int onstartcommand(intent intent, int flags, int startid) { log.i(log_tag, "in onstartcommand"); new thread(new runnable() { public void run() { //something } }).start(); return start_redeliver_intent; } @nullable @override public ibinder onbind(intent intent) { log.i(log_tag, "onbind"); return null; } @targetapi(build.version_codes.ice_cream_sandwich) @override public void ontaskremoved(intent rootintent) { super.ontaskremoved(rootintent); log.i(log_tag, "in ontaskremoved"); } @override public void ondestroy() { super.ondestroy(); log.i(log_tag, "in ondestroy"); } }
if one-time process, think service best option. can whatever want there and, when process finished, send broadcast notify has finished.
Comments
Post a Comment