涉及BroadcastReceiver

https://blog.csdn.net/nishigesb123/article/details/89046549


概述 

下面是API的描述:

This class provides access to the system alarm services. These allow you to schedule your application to be run at some point in the future. When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running. Registered alarms are retained while the device is asleep (and can optionally wake the device up if they go off during that time), but will be cleared if it is turned off and rebooted.

  • AlarmManager提供了一种系统级的提示服务,允许你安排在将来的某个时间执行一个服务。当到时间到时,AlarmManager会为我们广播一个我们设定好的Intent。
  • 最常见的应用场景就是手机中自带的——闹钟。
  • AlarmManager对象一般不直接实例化,而是通过Context.getSystemService(Context.ALARM_ SERVICE)方法获得。

常用属性和方法

特别的,上表中的下述四个属性,即AlarmManager提供的四种闹钟类型(或者算两种?)。

  1. RTC:硬件闹钟,不唤醒手机(也可能是其他设备)休眠;当手机休眠时不发射闹钟。
  2. RTC_WAKEUP:硬件闹钟,当闹钟发射时唤醒手机休眠。
  3. ELAPSED_REALTIME:真实时间流逝闹钟,不唤醒手机休眠;当手机休眠时不发射闹钟。
  4. ELAPSED_REALTIME_WAKEUP:真实时间流逝闹钟,当闹钟发射时唤醒手机休眠。

硬件闹钟和真实时间流逝闹钟的区别前者可以通过修改手机时间触发闹钟事件,后者要通过真实时间的流逝,即使在休眠状态,时间也被计算。

 

实现

准备一个Button

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/start"
        android:onClick="start"
        app:layout_constraintTop_toTopOf="parent"
        android:text="启动闹钟"/>

准备一个广播接收器

package com.example.a4_6alarmmanager;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "这是一个测试闹钟", Toast.LENGTH_SHORT).show();
    }
}

实现button的onClikc事件

package com.example.a4_6alarmmanager;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void start(View view){
        //获取到了系统的闹钟服务
        AlarmManager am= (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        //触发闹钟的时间(毫秒),即3秒后显示...
        long triggerTime=System.currentTimeMillis()+3000;
        Intent intent=new Intent(this,MyReceiver.class);
        PendingIntent op=PendingIntent.getBroadcast(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
        //只会执行一次的闹钟
        am.set(AlarmManager.RTC_WAKEUP,triggerTime,op);
    }
}

效果为3秒后显示广播

如果想要重复显示闹钟可以使用下面的语句

am.setRepeating(AlarmManager.RTC_WAKEUP,triggerTime,2000,op);

 

实际测试发现上面的例子还是有点点问题,网上找了一下资料,发现了一篇博客提到这个问题。

关于时间不准或失效可以参考

https://blog.csdn.net/bingshushu/article/details/50433643

👆就是一个比较简单的Demo,接下来我们继续丰富这个Demo,为它创建一个启动界面

再准备一个Button

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/set"
        android:onClick="set"
        app:layout_constraintTop_toBottomOf="@+id/start"
        android:text="设置闹钟"/>

点击事件和刚才基本一样,只需要把MyReceiver替换成我们额外创建的Activity

    public void set(View view){
        //获取到了系统的闹钟服务
        AlarmManager am= (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        //触发闹钟的时间(毫秒),即3秒后显示...
        long triggerTime=System.currentTimeMillis()+3000;
        Intent intent=new Intent(this,Main2Activity.class);
        PendingIntent op=PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
        //只会执行一次的闹钟
        am.set(AlarmManager.RTC_WAKEUP,triggerTime,op);
    }

重点在这个额外创建的Activity界面如何设计,需要注意的都已经写在注释里了

注意AlertDialog不能导入v7的那个包,和@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar不兼容

package com.example.a4_6alarmmanager;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

import java.io.IOException;

//改成继承Activity!
public class Main2Activity extends Activity  {
    //MediaPlayer对象
    MediaPlayer mp;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //强制唤醒屏幕,固定写法
        //还需要在配置清单文件android:theme="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar"
        Window win=getWindow();
        win.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD|
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED|
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON|
                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
        setContentView(R.layout.activity_main2);
        mp = new MediaPlayer();
        try {
            mp.setDataSource(this, Uri.parse("/你的mp3的路径"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        mp.setLooping(true);
        mp.start();
        alarmDialog();
    }

    //结束时停止播放
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mp!=null){
            if (mp.isPlaying()){
                mp.stop();
            }
            mp.release();
        }
    }
    public void alarmDialog(){
        AlertDialog.Builder builder=new AlertDialog.Builder(this);
        builder.setMessage("闹钟提示文本");
        builder.setPositiveButton("重复", new DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int which) {
                alarm();
                finish();
            }
        });
        builder.setNegativeButton("停止", new DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int which) {
                finish();
            }
        });
        builder.show();
    }
    private void alarm(){
        //获取到了系统的闹钟服务
        AlarmManager am= (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        //触发闹钟的时间(毫秒),即5秒后显示...
        long triggerTime=System.currentTimeMillis()+5000;
        Intent intent=new Intent(this,Main2Activity.class);
        PendingIntent op=PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
        //只会执行一次的闹钟
        am.set(AlarmManager.RTC_WAKEUP,triggerTime,op);
    }
}