7月第一周学习(模块化闹钟实现)

本文介绍了如何在Android中实现模块化的闹钟功能,利用AlarmManager和PendingIntent结合BroadcastReceiver在指定时间触发操作。同时,文章还提到Android Studio模拟器logcat显示时间不一致的问题,解决方案是调整模拟器的时区设置为上海。
摘要由CSDN通过智能技术生成

本周完成将闹钟代码实现模块化,该程序不需要UI,只需要在Mainactivity中给予一个实例化闹钟即可设定闹钟。
AlarmManager是Android中常用的一种系统级别的提示服务,在特定的时刻为我们广播一个指定的Intent。简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定的Intent,通常我们使用 PendingIntent,PendingIntent可以理解为Intent的封装包,简单的说就是在Intent上在加个指定的动作。在使用Intent的时候,我们还需要在执行startActivity、startService或sendBroadcast才能使Intent有用。而PendingIntent的话就是将这个动作包含在内了。
入口类
Mainactivity.class

package com.example.alarmmodule;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    Button setTime1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        InitSetTime1();
    }
    private void InitSetTime1(){
        setTime1 = (Button)findViewById(R.id.settime1);
        setTime1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                MyAlarmManager alarm = new MyAlarmManager();
                alarm.setNoRepeatAlarmUsingTimePicker(MainActivity.this,16,39,1);
            }
        });
    }
}

MyAlarmManager.class
AlarmManager使用:
1 获得ALarmManager实例 ALarmManager am=(ALarmManager)getSystemService(ALARM_SERVICE);
2 定义一个PendingIntent发出广播
3 调用ALarmManager方法,设置定时或重复提醒
4 取消提醒
set(int type,long startTime,PendingIntent pi);
该方法用于设置一次性闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟执行时间,第三个参数表示闹钟响应动作。

PendingIntent sender:是闹钟的执行动作,比如发送一个广播、给出提示等等。PendingIntent是Intent的封装类。需要注意的是,如果是通过启动服务来实现闹钟提示的话,PendingIntent对象的获取就应该采用Pending.getService( Context c,int i,Intent intent,int j)方法;如果是通过广播来实现闹钟提示的话PendingIntent对象的获取就应该采用PendingIntent.getBroadcast(Contex
c,int i,Intent intent,int j)方法;如果是采用Activity的方式来实现闹钟提示的话,PendingIntent对象的获取就应该采用PendingIntent.getActivity(Context c,int i,Intent intent,int j)方法。如果这三种方法错用了的话,虽然不会报错,但是看不到闹钟提示效果。本程序采用广播来实现闹钟提示。

PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);

通过上述方法,可在指定时间使pendingIntnet发送广播,然后程序实现BrodcastReceiver,接收此广播。这样就可在指定时间,作出动作。getBroadcast方法发出广播,这样在service中可以接收到所发出的广播来获取其中intent中携带的数据,然后再执行其他的逻辑。

取消闹钟

noRepeatAlarm.cancel(pi);
package com.example.alarmmodule;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;

import java.util.Calendar;


public class MyAlarmManager{
//需要知道用户想要执行闹钟响应的方式

    public static final int TYPE_ALARM_RING = 1;//响铃

    public static final int TYPE_ALARM_TOAST = 2;//弹框

    public static final int TYPE_ALARM_VIBRATE = 3;//震动

    /**
     * 设置当日一次性闹钟
     * @param hourOfDay,minute 用户设置时间
     * @param responseType 反馈模式
     */
    public void setNoRepeatAlarmUsingTimePicker(Context context,int hourOfDay,int minute,int responseType){

        Calendar c = Calendar.getInstance();
        // 根据用户选择的时间来设置Calendar对象
        c.setTimeInMillis(System.currentTimeMillis());
        c.set(Calendar.HOUR_OF_DAY,hourOfDay);
        c.set(Calendar.MINUTE,minute);
        c.set(Calendar.SECOND,0);
        c.set(Calendar.MILLISECOND,0);
        //设置AlarmManager在Calendar对应的时间启动Activity
        AlarmManager noRepeatAlarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context,AlarmReceiver.class);
        intent.putExtra("responseType", responseType);
        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);

        int type = AlarmManager.RTC_WAKEUP;
        noRepeatAlarm.set(type,c.getTimeInMillis(),pi);
        //获取当前毫秒值
        long systemTime = System.currentTimeMillis();
        long selectTime = c.getTimeInMillis();
        // 如果当前时间大于设置的时间,那么就从第二天的设定时间开始
        if(systemTime > selectTime) {
            c.add(Calendar.DAY_OF_MONTH, 1);
        }
    }


    /**
     * 设置按周定制闹钟
     * @param hourOfDay 小时
     * @param minute 分钟
     * @param weekDayArray 周几
     * @param responseType 反馈类型
     */
    public void setWeekAlarmUsingTimePicker(Context context,int hourOfDay,int minute,int weekDayArray[],int responseType){

        AlarmManager weekAlarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent weekIntent = new Intent(context, AlarmReceiver.class);
        weekIntent.putExtra("responseType", responseType);
        PendingIntent weekPi=PendingIntent.getBroadcast(
                context,0, weekIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        Calendar weekc = Calendar.getInstance();
        weekc.setTimeInMillis(System.currentTimeMillis());
        // 根据用户选择的时间来设置Calendar对象
        weekc.set(Calendar.HOUR, hourOfDay);
        weekc.set(Calendar.MINUTE, minute);

        int nowDay = Contants.getNowWeek();
        int setDay = 0;
        setDay = Contants.getResultDifferDay1(weekDayArray, nowDay);
        int differDay = Contants.compareDayNowToNext(nowDay, setDay);
        if(differDay == 0){
            weekAlarm.set(AlarmManager.RTC_WAKEUP,weekc.getTimeInMillis() + Contants.getDifferMillis(7),weekPi);
        }else{
            weekAlarm.set(AlarmManager.RTC_WAKEUP,weekc.getTimeInMillis() + Contants.getDifferMillis(differDay),weekPi);
        }
    }


    /**
     * 设置按日期定制闹钟
     * @param Month 月份
     * @param Day 日期
     * @param hourOfDay 小时
     * @param Minute 分钟
     * @param responseType 反馈类型
     */
    public void setDayAlarmUsingTimePicker(Context context,int Month, int Day, int hourOfDay, int Minute, int responseType){

        Calendar calendar = Calendar.getInstance();//获取系统的日期
        int year = calendar.get(Calendar.YEAR);//年
        // 设置闹钟时间
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.set(year,Month,Day,hourOfDay,Minute);

        Intent DayIntent = new Intent(context,AlarmReceiver.class);
        DayIntent.putExtra("responseType", responseType);

        AlarmManager dayAlarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        PendingIntent Daypi = PendingIntent.getBroadcast(context, 0, DayIntent, PendingIntent.FLAG_CANCEL_CURRENT);
        dayAlarm.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), Daypi);
            }
    
    public String setToastContent(String content){
        content = "闹钟响了";
        return content;
    }
}

主要是要继承 BroadcastReceiver 这个类,然后重写onRecive方法。onRecive方法在闹钟的时间达到之后会执行,在这里我们可以做自己的事情,比如启动某个程序,或者播放铃声,该类定义一个Receiver类通过广播来接收并处理闹钟响应事件。
注意:要将该广播接收器添加到清单文件当中。

 <receiver android:name=".AlarmReceiver" android:process=":remote" />

在该程序中,参数responseType代表的是闹钟响应方式,要通过Intent从MyAlarmManager传递整型到AlarmReceiver,使之判断响应方式。需要用到的方法(通过数据类型转换)如下:
发送端:

int id = 0;
Intent intent = new Intent(this,EditActivity.class);
intent.putExtra("id",id+"")//id+""这样是把int型转化为string
startActivity(intent);

接收端:

String sID = gerStringExtra("id");
int id = Interger.parseInt(sID); //String转int

AlarmReceiver.class

package com.example.alarmmodule;

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

public class AlarmReceiver extends BroadcastReceiver {//接受广播BroadcastReceiver的类:

    @Override
    public void onReceive(Context context, Intent intent) {
            //当系统到我们设定的时间点的时候会发送广播,执行这里
        if ("android.alarm.demo.action".equals(intent.getAction())) {
            System.out.println("设置成功");
            String getresponseType = intent.getStringExtra("responseType");
            int responseType = Integer.parseInt(getresponseType);
            System.out.println(responseType);
            switch (responseType) {
                case MyAlarmManager.TYPE_ALARM_RING:
                    System.out.println("闹钟响了");
                    Intent intent1 = new Intent(context, AlarmAlert.class);
                    context.startActivity(intent1);
                    MediaUtil.playRing(context);//开启
                    MediaUtil.stopRing();//关闭
                    Contants.cancelAlarmTimer(context,"android.alarm.demo.action");//取消闹钟
                    break;
                case MyAlarmManager.TYPE_ALARM_TOAST:
                    Intent intent2 = new Intent(context, AlarmAlert.class);
                    context.startActivity(intent2);
                    Toast toast = Toast.makeText(context, "Toast提示消息", Toast.LENGTH_SHORT);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();
                    Contants.cancelAlarmTimer(context,"android.alarm.demo.action");
                    break;
                case MyAlarmManager.TYPE_ALARM_VIBRATE:
                    Intent intent3 = new Intent(context, AlarmAlert.class);
                    context.startActivity(intent3);
                    // 开启震动
                    boolean isVirating = true;
                    VibrateUtil.vibrate(context, 1000);//震动一次,1000ms
                    //关闭震动
                    if (isVirating) {//防止多次关闭抛出异常,这里加个参数判断一下
                        isVirating = false;
                        VibrateUtil.virateCancle(context);
                        Contants.cancelAlarmTimer(context,"android.alarm.demo.action");
                        break;
                    }
                default:
                    System.out.println("error\n");
            }
        }
    }
}

播放音乐模块
MediaUtil.class

package com.example.alarmmodule;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.Uri;

public class MediaUtil {

    private static MediaPlayer mMediaPlayer;

    //开始播放
    public static void playRing(Context context){
        try {
            //用于获取手机默认铃声的Uri
            Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setDataSource(context, alert);
            //告诉mediaPlayer播放的是铃声流
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);
            mMediaPlayer.setLooping(true);
            mMediaPlayer.prepare();
            mMediaPlayer.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //停止播放
    public static void stopRing(){
        if (mMediaPlayer!=null){
            if (mMediaPlayer.isPlaying()){
                mMediaPlayer.stop();
                mMediaPlayer.release();
            }
        }
    }
}

震动模块
VibrateUtil.class

package com.example.alarmmodule;

import android.app.Service;
import android.content.Context;
import android.os.Vibrator;

public class VibrateUtil {
    /**
     * 让手机振动milliseconds毫秒
     */
    public static void vibrate(Context context, long milliseconds) {
        Vibrator vib = (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE);
        if(vib.hasVibrator()){  //判断手机硬件是否有振动器
            vib.vibrate(milliseconds);
        }
    }
    /**
     * 让手机以我们自己设定的pattern[]模式振动
     * long pattern[] = {1000, 20000, 10000, 10000, 30000};
     */
    public static void vibrate(Context context, long[] pattern,int repeat){
        Vibrator vib = (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE);
        if(vib.hasVibrator()){
            vib.vibrate(pattern,repeat);
        }
    }
    /**
     * 取消震动
     */
    public static void virateCancle(Context context){
        //关闭震动
        Vibrator vib = (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE);
        vib.cancel();
    }
}

工具类
Contants.class

package com.example.alarmmodule;

import java.text.SimpleDateFormat;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;



public class Contants {

    //repeated day of week define
    public static Map<String, Integer> mapWeek = new HashMap<String,Integer>();


    public static void addMapWeek(){
        mapWeek.put("周一", 1);
        mapWeek.put("周二", 2);
        mapWeek.put("周三", 3);
        mapWeek.put("周四", 4);
        mapWeek.put("周五", 5);
        mapWeek.put("周六", 6);
        mapWeek.put("周日", 7);
        mapWeek.put("无重复", 0);
    }


    public static int getMapWeek(String str){
        Contants.addMapWeek();
        int dayOfMapWeek = 0;
        if(str != null){
            dayOfMapWeek = mapWeek.get(str);
        }
        return dayOfMapWeek;
    }


    public static String[] getDatetimeString(){
        Date date = new Date();
        String[] tempStr = new String[2];
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String str = format.format(date);
        tempStr[0] = str.substring(0, 10);
        tempStr[1] = str.substring(11, str.length());
        return tempStr;
    }


    public static long getNowTimeMinuties()
    {
        return System.currentTimeMillis();
    }


    public static boolean differSetTimeAndNowTime(long setTime)
    {
        if(setTime >= getNowTimeMinuties()){
            return true;
        }else{
            return false;
        }
    }



    public static long getDifferMillis(int differDays)
    {
        return differDays * 24 * 60 * 60 * 1000;
    }


    //compare nowDay to nextDay

    public static int compareDayNowToNext(int nowDay,int nextDay){
        if(nextDay > nowDay){
            return (nextDay-nowDay);
        }else if(nextDay == nowDay){
            return 0;
        }else{
            return (7-(nowDay-nextDay));
        }
    }


    //turn the nowday to China`s day of Week
    public static Map<String, Integer> nowWeek = new HashMap<String,Integer>();

    public static void addNowWeek()
    {
        nowWeek.put("1", 7);
        nowWeek.put("2", 1);
        nowWeek.put("3", 2);
        nowWeek.put("4", 3);
        nowWeek.put("5", 4);
        nowWeek.put("6", 5);
        nowWeek.put("7", 6);
    }

  /**
   * @return 返回星期几
   */
    public static int getNowWeek()
    {
        Calendar nowCal = Calendar.getInstance();
        Date nowDate = new Date(System.currentTimeMillis());
        nowCal.setTime(nowDate);
        int nowNum = nowCal.get(nowCal.DAY_OF_WEEK);
        String nowNumStr = String.valueOf(nowNum);
        Contants.addNowWeek();
        int nowDayOfWeek = 0;
        if(nowNumStr != null){
            nowDayOfWeek = nowWeek.get(nowNumStr);
        }
        return nowDayOfWeek;
    }


    public static int getSetDay(String str)
    {
        if(str.equals("周一")){
            return 1;
        }
        if(str.equals("周二")){
            return 2;
        }
        if(str.equals("周三")){
            return 3;
        }
        if(str.equals("周四")){
            return 4;
        }
        if(str.equals("周五")){
            return 5;
        }
        if(str.equals("周六")){
            return 6;
        }
        if(str.equals("周日")){
            return 7;
        }
        return 0;
    }

    public static int[] getDayOfNum(String[] str)
    {
        int[] dayOfInt = new int[str.length];
        for(int i=0;i<str.length;i++){
            dayOfInt[i] = getSetDay(str[i]);
        }
        return dayOfInt;
    }


    public static int getResultDifferDay(int[] in,int nowDay)

    {
        int result = 0;
        for(int i=0;i<in.length;i++){
            if(in[i] >= nowDay){
                result = in[i];
                break;
            }
        }
        if(result == 0){
            result = in[0];
        }
        return result;
    }


    public static int getResultDifferDay1(int[] in,int nowDay)

    {
        int result = 0;
        for(int i=0;i<in.length;i++){
            if(in[i] > nowDay){
                result = in[i];
                break;
            }
        }
        if(result == 0){
            result = in[0];
        }
        return result;
    }
    
/**
 * 取消闹钟
 * @param context
 * @param action
 */
public static void cancelAlarmTimer(Context context, String action) {
    Intent myIntent = new Intent();
    myIntent.setAction(action);
    PendingIntent sender = PendingIntent.getBroadcast(context, 0, myIntent,0);
    AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarm.cancel(sender);
}
}

AndroidManifest.xml
核心的配置为<receiver android:name=".AlarmReceiver" android:process=":remote" />,这也是闹钟程序的关键,如果不做这个配置,那么时间到了之后,闹钟将不会提示。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.alarmmodule">

    <uses-permission android:name="android.permission.VIBRATE" />
    <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">
        <!--闹钟接收广播-->
        <receiver android:name=".AlarmReceiver" android:process=":remote" />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".AlarmAlert"
            android:label="@string/app_name">
        </activity>
    </application>
</manifest>

如何解决AndroidStudio logcat显示时间与当前系统时间不一致
今天在用模拟器调试程序的时候,突然发现AndroidStudio的logcat显示的调试信息时间跟当前系统的时间不一致,这对于我们查看调试信息无疑带来了很大的不便,所以就在此将解决方法稍微记录下。
出现这个问题的原因是模拟器所默认的时区是美国太平洋时区,导致模拟器的时间与我们系统的时间不一致,而logcat显示的是模拟器的当前时间。解决方法很简单,只要将模拟器的时区改变下就OK了。步骤如下:
1.打开模拟器,打开Settings,打开Date&time
在这里插入图片描述
2.选择Select time zone
在这里插入图片描述
3.选择Shanghai
在这里插入图片描述

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值