1

现在我可以在字符串值中获取下一个警报。我想在几毫秒内得到它。这是我尝试过的,但它不起作用。我也使用 Locale.US,但希望它适用于任何语言环境。请指教

String nextAlarm = android.provider.Settings.System.getString(getContentResolver(), android.provider.Settings.System.NEXT_ALARM_FORMATTED);

    DateFormat format = new SimpleDateFormat("EEE hh:mm aa", Locale.US);
    long nextAlarmTime = 0;
    try {
        Date date = format.parse(nextAlarm);
        nextAlarmTime = date.getTime();
    } catch (Exception e) {
    }

    long curTime = System.currentTimeMillis();
    long diff = nextAlarmTime - curTime;

    //diff would represent the time in milliseconds
4

3 回答 3

3

在具有 API 21 及更高版本的设备上,您可以通过以下方式实现毫秒数getSystemService()

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
    AlarmManager.AlarmClockInfo info = 
        ((AlarmManager)getSystemService(Context.ALARM_SERVICE)).getNextAlarmClock();
    if (info != null) {
        long alarmTime = info.getTriggerTime();
        SimpleDateFormat simpleDateFormat = 
            new SimpleDateFormat("yyyy-MM-dd hh:mm a", Locale.US);
        Log.d(getClass().getSimpleName(),
            simpleDateFormat.format(new Date(alarmTime)));
    }
}

在旧设备上,您必须在数据库中查找警报字符串:

String nextAlarm = Settings.System.getString(getContentResolver(),
                       Settings.System.NEXT_ALARM_FORMATTED);

检索到的字符串的格式取决于运行设备的区域设置。字符串由

  • 时间的数字(阿拉伯,印度,...?)

  • 字符串来自

    String[] weekdays = DateFormatSymbols.getInstance().getShortWeekdays();
    
  • 字符串来自

    String[] amPm = DateFormatSymbols.getInstance().getAmPmStrings();
    

您不能依赖 weekday-time-AmPm-components 的顺序。例如,AmPm-String 并不总是放在最后。在韩国,它通常放在工作日和时间之间。


我的解决方案:

报警时间工具.java

import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AlarmTimeTool {

    public static long getNextAlarm(String alarm, String[] weekdays, String[] amPm) {
        int alarmHours = -1, alarmMinutes = -1;
        int alarmWeekday = -1; // Calendar.SUNDAY = 1; Calendar.SATURDAY = 7;
        int alarmAmPm = -1; // Calendar.AM = 0; Calendar.PM = 1;

        for (String piece: alarm.split("\\s")) {
            if (alarmWeekday == -1) {
                alarmWeekday = getWeekday(piece, weekdays);
                if (alarmWeekday != -1) {
                    continue;
                }
            }
            if (alarmHours == -1) {
                int[] hoursMinutes = getTime(piece);
                alarmHours = hoursMinutes[0];
                alarmMinutes = hoursMinutes[1];
                if (alarmHours != -1) {
                    continue;
                }
            }
            if (alarmAmPm == -1) {
                alarmAmPm = getAmPm(piece, amPm);
            }
        }

        if (alarmWeekday == -1 || alarmHours == -1) {
            throw new RuntimeException("could not fetch alarm week or hour");
        }

        Calendar now = Calendar.getInstance();
        Calendar nextAlarm = Calendar.getInstance();
        nextAlarm.set(Calendar.DAY_OF_WEEK, alarmWeekday);
        nextAlarm.set(Calendar.MINUTE, alarmMinutes);
        nextAlarm.set(Calendar.SECOND, 0);
        nextAlarm.set(Calendar.MILLISECOND, 0);
        if (alarmAmPm == -1) {
            nextAlarm.set(Calendar.HOUR_OF_DAY, alarmHours);
        } else {
            nextAlarm.set(Calendar.AM_PM, alarmAmPm);
            nextAlarm.set(Calendar.HOUR, alarmHours % 12);
        }
        if (nextAlarm.before(now)) {
            nextAlarm.add(Calendar.DAY_OF_MONTH, 7);
        }

        return nextAlarm.getTimeInMillis();
    }

    private static int[] getTime(String piece) {
        int hours = -1;
        int minutes = -1;

        // Android only (\d has different meanings):
        Pattern p = Pattern.compile("(\\d{1,2})\\D(\\d{2})");

        Matcher m = p.matcher(piece);
        if (m.find()) {
            hours = Integer.parseInt(m.group(1));
            minutes = Integer.parseInt(m.group(2));
        }
        int[] hoursMinutes = {hours, minutes};
        return hoursMinutes;
    }

    private static int getWeekday(String piece, String[] weekdays) {
        for (int i = 1; i < weekdays.length; i++) {
            if (piece.contains(weekdays[i])) {
                return i;
            }
        }
        return -1;
    }

    private static int getAmPm(String piece, String[] amPm) {
        for (int i = 0; i < amPm.length; i++) {
            if (piece.contains(amPm[i])) {
                return i;
            }
        }
        return -1;
    }
}

MainActivity.java

import android.app.Activity;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;

import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;


public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String nextAlarm = Settings.System.getString(getContentResolver(),
                Settings.System.NEXT_ALARM_FORMATTED);
        if (nextAlarm != null && !nextAlarm.isEmpty()) {
            Log.d(getClass().getSimpleName(), nextAlarm);
            String[] weekdays = DateFormatSymbols.getInstance().getShortWeekdays();
            String[] amPm = DateFormatSymbols.getInstance().getAmPmStrings();
            long alarmTime = AlarmTimeTool.getNextAlarm(nextAlarm, weekdays, amPm);
            SimpleDateFormat simpleDateFormat =
                    new SimpleDateFormat("yyyy-MM-dd hh:mm a", Locale.US);
            Log.d(getClass().getSimpleName(), simpleDateFormat.format(new Date(alarmTime)));
        }
    }
}
于 2016-02-01T23:46:08.793 回答
2

Date 的代码不是毫秒 ;-) 但接下来调用 getTime() ,您将以毫秒为单位获得时间。

我在我的小应用程序中使用这个代码来计算我应该睡觉的时间,基于下一个闹钟的时间。它是通过 2 小时尝试不同的方法创建的,因此可以肯定它可能会被优化。

    public static Date getNextAlarm(Context context) {
    // let's collect short names of days :-)        
    DateFormatSymbols symbols = new DateFormatSymbols();
    // and fill with those names map...
    Map<String, Integer> map = new HashMap<String, Integer>();
    String[] dayNames = symbols.getShortWeekdays();
    // filing :-)
    map.put(dayNames[Calendar.MONDAY],Calendar.TUESDAY);
    map.put(dayNames[Calendar.TUESDAY],Calendar.WEDNESDAY);
    map.put(dayNames[Calendar.WEDNESDAY],Calendar.THURSDAY);
    map.put(dayNames[Calendar.THURSDAY],Calendar.FRIDAY);
    map.put(dayNames[Calendar.FRIDAY],Calendar.SATURDAY);
    map.put(dayNames[Calendar.SATURDAY],Calendar.SUNDAY);
    map.put(dayNames[Calendar.SUNDAY],Calendar.MONDAY);
    // Yeah, knowing next alarm will help.....
    String nextAlarm = Settings.System.getString(context.getContentResolver(),Settings.System.NEXT_ALARM_FORMATTED);
    // In case if it isn't set.....
    if ((nextAlarm==null) || ("".equals(nextAlarm))) return null;
    // let's see a day....
    String nextAlarmDay = nextAlarm.split(" ")[0];
    // and its number....
    int alarmDay = map.get(nextAlarmDay);

    // the same for day of week (I'm not sure why I didn't use Calendar.get(Calendar.DAY_OF_WEEK) here...
    Date now = new Date();      
    String dayOfWeek = new SimpleDateFormat("EE", Locale.getDefault()).format(now);     
    int today = map.get(dayOfWeek);

    // OK, so let's calculate how many days we have to next alarm :-)
    int daysToAlarm = alarmDay-today;
    // yep, sometimes it will  be negtive number so add 7.
    if (daysToAlarm<0) daysToAlarm+=7;



    // Now we will build date, and parse it.....
    try {
        Calendar cal2 = Calendar.getInstance();
        String str = cal2.get(Calendar.YEAR)+"-"+(cal2.get(Calendar.MONTH)+1)+"-"+(cal2.get(Calendar.DAY_OF_MONTH));

        SimpleDateFormat df  = new SimpleDateFormat("yyyy-MM-d hh:mm");

        cal2.setTime(df.parse(str+nextAlarm.substring(nextAlarm.indexOf(" "))));
        cal2.add(Calendar.DAY_OF_YEAR, daysToAlarm);
        // and return it
        return cal2.getTime();
    } catch (Exception e) {

    }
    // in case if we cannot calculate...
    return null;
}
于 2013-06-06T22:20:42.693 回答
0

Looking at Alarms.java in alarm clock app, which is responsible for setting this variable, the correct format is either "E h:mm aa" or "E k:mm" depending on 12/24 hour mode. I parse it using SimpleDateFormat and copy the valid fields using Calendar over to current date:

String format = android.text.format.DateFormat.is24HourFormat(context) ? "E k:mm" : "E h:mm aa";
Calendar nextAlarmCal = Calendar.getInstance();
Calendar nextAlarmIncomplete = Calendar.getInstance();
nextAlarmIncomplete.setTime(new SimpleDateFormat(format).parse(nextAlarm));

// replace valid fields of the current time with what we got in nextAlarm
int[] fieldsToCopy = {Calendar.HOUR_OF_DAY,Calendar.MINUTE,Calendar.DAY_OF_WEEK};
for (int field : fieldsToCopy) {
   nextAlarmCal.set(field, nextAlarmIncomplete.get(field));
}
nextAlarmCal.set(Calendar.SECOND, 0);

// if the alarm is next week we have wrong date now (in the past). Adding 7 days should fix this 
if (nextAlarmCal.before(Calendar.getInstance())) {
   nextAlarmCal.add(Calendar.DATE, 7);
}
于 2013-11-01T13:26:42.460 回答