Android Alarm Clock Setup Solution _android

Source: Internet
Author: User
Tags static class

The Android setting alarm clock is not as simple as iOS, and developers who have made the Android alarm clock know how deep the hole is. Here's a note of my solution to the Android alarm set.
Major problems
1, API19 began to alarmmanager mechanism changes.
2, the application is killed, set the alarm clock does not ring.
3, more than 6.0 into the doze mode will make Jobscheduler stop working.
4, the phone set reboot, the alarm clock failure problem.
Modification of Alarmmanager mechanism above API19
Prior to API19, Alarmmanager provided three methods for setting the alarm clock, so the set (int type,long starttime,pendingintent pi) was used, because the business requirement alarm clock needed only one one-time.
Starting with API 19, the Alarmmanager mechanism is accurate, and the operating system converts the alarm to minimize wake-up and battery usage.


As a result of previous procedures, no API19 above the alarm set to do processing, resulting in more than 4.4 of the phone set the alarm clock is not responding (the application is not killed in case there is no alarm clock).

Because of this, setting the alarm clock needs to be handled separately according to the version of the API. The code is as follows:

Alarmmanager am = (alarmmanager) getactivity ()
 . Getsystemservice (context.alarm_service);
if (Build.VERSION.SDK_INT >= build.version_codes. KitKat) {
 am.setexact (alarmmanager.rtc_wakeup, Timeutils
 . Stringtolong (Recordtime, Timeutils.no_second_ FORMAT), sender);
else {
 Am.set (alarmmanager.rtc_wakeup, Timeutils
 . Stringtolong (Recordtime, Timeutils.no_second_format), sender);
}

This ensures that the alarm clock is not killed in the application.

Processing of applications being killed
when the application is killed, the set alarm clock fails, and the daemon and the Gray Guard are used to ensure that the backend alarm service is not killed. When the application and alarm service is killed, the daemon and the Gray guard restart the alarm service and reset the alarm.
With regard to daemon processing, the Open Source Daemon library is used here. Android-appdaemon

In the alarm clock service oncreat joins Android-appdaemon this open source daemon. The code is as follows:

@Override public
void OnCreate () {
 super.oncreate ();
 Daemon.run (Daemonservice.this, 
  Daemonservice.class, daemon.interval_one_minute);
 Starttimetask ();
 Grayguard ();
}

To further ensure the survival of the alarm clock service, with the addition of gray security (the use of system vulnerabilities to start the front service). The
code is as follows:

private void Grayguard () {if (Build.VERSION.SDK_INT <) {//api < 18), this method can effectively hide the icons on notification Startforegroun
 D (gray_service_id, New Notification ());
 else {Intent innerintent = new Intent (this, daemoninnerservice.class);
 StartService (innerintent);
 Startforeground (gray_service_id, New Notification ());
 //Send wakeup broadcast to cause the pending UI process to reboot Alarmmanager Alarmmanager = (alarmmanager) getsystemservice (Context.alarm_service);
 Intent alarmintent = new Intent ();
 Alarmintent.setaction (wakereceiver.gray_wake_action); Pendingintent operation = Pendingintent.getbroadcast (this, Wake_request_code, Alarmintent, pendingintent.flag_update
 _current); if (Build.VERSION.SDK_INT >= build.version_codes.
 KitKat) {Alarmmanager.setwindow (Alarmmanager.rtc_wakeup, System.currenttimemillis (), ALARM_INTERVAL, operation); }else {alarmmanager.setinexactrepeating (Alarmmanager.rtc_wakeup, System.currenttimemillis (), ALARM_INTERVAL,
 operation);
}/** * for the API >= 18 platform on the gray-preserving means * *public static class Daemoninnerservice extends Service {@Override public void onCreate () {log.i (Log_tag, "Innerservi
 Ce-> onCreate ");
 Super.oncreate (); @Override public int Onstartcommand (Intent Intent, int flags, int startid) {log.i (Log_tag, Innerservice,->
 Artcommand ");
 Startforeground (gray_service_id, New Notification ());
 Stopforeground (TRUE);
 Stopself ();
 Return Super.onstartcommand (Intent, flags, Startid);
 @Override public IBinder onbind (Intent Intent) {throw new unsupportedoperationexception (' not yet implemented ');
 @Override public void OnDestroy () {log.i (Log_tag, "Innerservice-> OnDestroy");
 Super.ondestroy ();

 }
}

The above operation enhances the survival of the alarm service as much as possible. But in more than 5.0 of the mobile phone, using the system's own clean function, the alarm clock service will be completely killed. To solve more than 5.0 of the problems, this introduces more than 5.0 of the new features Jobscheduler.

More than 5.0 of the Jobscheduler
here use more than 5.0 of Jobscheduler to create a timed task, timed to detect whether the alarm service exists, not in existence, restart the alarm clock service. (Here I set every minute to detect an alarm clock service)

Detects whether the current system is 5.0 or more when entering the application, and starts Jobscheduler this service if it is. The code is as follows:

if (Build.VERSION.SDK_INT >= build.version_codes. Lollipop) {
 Mjobscheduler = (jobscheduler) getsystemservice (context.job_scheduler_service);
 Jobinfo.builder Builder = new Jobinfo.builder (job_id,
  new ComponentName (Getpackagename), JobSchedulerService.class.getName ()));

 Builder.setperiodic (60 * 1000); Run
 builder.setrequirescharging (true) once every 60 seconds;
 Builder.setpersisted (TRUE); Reset the Task
 Builder.setrequiresdeviceidle (true) after setting the device reboot;

 if (Mjobscheduler.schedule (Builder.build ()) <= 0) {
 //if something goes
 }
}

One of the builder.setpersisted (true); method is whether the task is rerun after the device restarts, and the task can be restarted on this test.

The above operation further ensures that the alarm service is killed after the service is restarted. But in more than 6.0 of the introduction of the Doze mode, when more than 6.0 of the mobile phone into this mode, it will make Jobscheduler stop working.

6.0 and above doze mode processing
in order to allow Jobscheduler to enter the Doze mode in more than 6.0, here for more than 6.0 of the doze mode to do special treatment-ignore the battery optimization.

Add permissions to the Manifest.xml.
<uses-permission android:name= "Android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>

When setting the alarm clock, judge whether the system is over 6.0, and if so, whether or not to ignore the optimization of the battery. Determine if the battery optimization code is ignored as follows:

@TargetApi (build.version_codes. M) Public
static Boolean isignoringbatteryoptimizations (activity activity) {
 String PackageName = Activity.getpackagename ();
 PowerManager pm = (powermanager) activity
  . Getsystemservice (context.power_service);
 if (Pm.isignoringbatteryoptimizations (PackageName)) {return
 true;
 } else {return
 false;
 }
}

If the battery optimization is not ignored, a pop-up Reminder dialog box prompts the user to ignore the battery optimization operation. The code is as follows:

/**
* For n above doze mode
*
* @param activity/
public
static void Isignorebatteryoption Activity) {
 if (Build.VERSION.SDK_INT >= build.version_codes). M) {
 try {
  Intent Intent = new Intent ();
  String PackageName = Activity.getpackagename ();
  PowerManager pm = (powermanager) activity.getsystemservice (context.power_service);
  if (!pm.isignoringbatteryoptimizations (PackageName)) {
//  intent.setaction (settings.action_ignore_ battery_optimization_settings);
  Intent.setaction (settings.action_request_ignore_battery_optimizations);
  Intent.setdata (Uri.parse ("package:" + PackageName));
  Activity.startactivityforresult (Intent, Request_ignore_battery_code);
  }
 catch (Exception e) {
  e.printstacktrace ();}}}

Rewrite the Onactivityresult method in the interface to capture the user's choice. For example, the code is as follows:

@Override
protected void onactivityresult (int requestcode, int resultcode, Intent data) {
 if (ResultCode = = Resul T_OK) {
 if (Requestcode = = Batteryutils.request_ignore_battery_code) {
  //todo something
 }
 }else if ( ResultCode = = result_canceled) {
 if (Requestcode = = Batteryutils.request_ignore_battery_code) {
  Toastutils.show (Getactivity (), "Turn on ignoring battery optimization ~");
 }

Add
When the application is killed, but the alarm service is not killed, then set the alarm clock. This means that the set alarm is not placed on the alarm clock service. So in this case, the set alarm clock will fail. To address this situation, reset the alarm clock by invoking the reset alarm method for the alarm service by using the AIDL (Alarm clock service needs interprocess communication in another process).

The Oncreat () method of the application starts the alarm service and then binds the alarm clock service.

private void Initalarmservice () {
 startservice (new Intent (this, daemonservice.class));/Start alarm service
 if ( Build.VERSION.SDK_INT >= build.version_codes. Lollipop) {
 //jobscheduler
 ...
 }

 Bind Alarm Clock Service
 Intent Intent = new Intent (this, daemonservice.class);
 Intent.setaction ("Android.intent.action.DaemonService");
 Bindservice (Intent, mconnection, context.bind_auto_create);
}

In the OnDestroy () method, call the reset alarm method for the alarm clock service. The code is as follows:

@Override
protected void OnDestroy () {
 Super.ondestroy ();
 try {//Judge if there is an alarm clock, no turn off alarm clock service
 String alarm = localpreferenceshelper.getstring (localpreferenceshelper.alarm_clock);
 if (Daemonservice!=-1 && miremoteservice!= null) {
//  android.os.Process.killProcess (Daemonservice) ;
  Miremoteservice.resetalarm ();
 }

 if (!alarm.equals ("[]")) {
  if (daemonservice!=-1) {
  StartService (new Intent (this, daemonservice.class)); c13/>}
 } else {
  if (Build.VERSION.SDK_INT >= build.version_codes. Lollipop) {
  mjobscheduler.cancel (job_id);
  }

 }
 Unbindservice (mconnection); Unbind the service.
 catch (Exception e) {

 }
}

This explains that when the service is started and bound, Unbindservice does not stop the service.

At last

The above does not mean that all of the Android phone's alarm clocks can be used, and this is just the best possible guarantee for most mobile phones.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.