我想在我的Java桌面应用程序上生成警报:
我正在使用Java,Eclipse,SWT进行开发,并且使用Java Web Start从服务器部署了我的应用程序。我正在使用Mac OS X.6进行开发。
我认为我有几种选择:
如果将其作为系统服务运行,则可以从中受益,因为操作系统将确保我的软件:
我研究了一些可以使用的资源:
我对系统服务选项的疑问是:
我的计划实施是否正确:
因此,在第一次运行时,应用程序将安装该服务并启动它。当应用程序关闭时,该服务仍在运行,并且不再需要该应用程序,除非该应用程序未注册。 但是,我认为我仍然想念“启动时运行”功能。
我对吗?我想念什么吗?
在Unix上,我可以轻松地使用cron表,而无需应用程序将用户升级为root用户。我不需要处理重启,系统日期更改等问题。看起来不错。
在Windows上,即使在命令行中使用At或SchTasks,我也可以使用Task Scheduler。这看起来不错,但是我需要与XP兼容,直到7,而且我无法轻松对其进行测试。
那你会怎么做?我错过了什么?您有什么建议可以帮助我选择最佳,最优雅的解决方案吗?
这是我最终实现的:
public class AlarmManager { public static final String ALARM_CLI_FORMAT = "startalarm:"; public static SupportedOS currentOS = SupportedOS.UNSUPPORTED_OS; public enum SupportedOS { UNSUPPORTED_OS, MAC_OS, WINDOWS, } public AlarmManager() { final String osName = System.getProperty("os.name"); if (osName == null) { L.e("Unable to retrieve OS!"); } else if ("Mac OS X".equals(osName)) { currentOS = SupportedOS.MAC_OS; } else if (osName.contains("Windows")) { currentOS = SupportedOS.WINDOWS; } else { L.e("Unsupported OS: "+osName); } } /** * Windows only: name of the scheduled task */ private String getAlarmName(final long alarmId) { return new StringBuilder("My_Alarm_").append(alarmId).toString(); } /** * Gets the command line to trigger an alarm * @param alarmId * @return */ private String getAlarmCommandLine(final long alarmId) { return new StringBuilder("javaws -open ").append(ALARM_CLI_FORMAT).append(alarmId).append(" ").append(G.JNLP_URL).toString(); } /** * Adds an alarm to the system list of scheduled tasks * @param when */ public void createAlarm(final Calendar when) { // Create alarm // ... stuff here final long alarmId = 42; // Schedule alarm String[] commandLine; Process child; final String alarmCL = getAlarmCommandLine(alarmId); try { switch (currentOS) { case MAC_OS: final String cron = new SimpleDateFormat("mm HH d M '*' ").format(when.getTime()) + alarmCL; commandLine = new String[] { "/bin/sh", "-c", "crontab -l | (cat; echo \"" + cron + "\") | crontab" }; child = Runtime.getRuntime().exec(commandLine); break; case WINDOWS: commandLine = new String[] { "schtasks", "/Create", "/ST "+when.get(Calendar.HOUR_OF_DAY) + ":" + when.get(Calendar.MINUTE), "/SC ONCE", "/SD "+new SimpleDateFormat("dd/MM/yyyy").format(when.getTime()), // careful with locale here! dd/MM/yyyy or MM/dd/yyyy? I'm French! :) "/TR \""+alarmCL+"\"", "/TN \""+getAlarmName(alarmId)+"\"", "/F", }; L.d("create command: "+Util.join(commandLine, " ")); child = Runtime.getRuntime().exec(commandLine); break; } } catch (final IOException e) { L.e("Unable to schedule alarm #"+alarmId, e); return; } L.i("Created alarm #"+alarmId); } /** * Removes an alarm from the system list of scheduled tasks * @param alarmId */ public void removeAlarm(final long alarmId) { L.i("Removing alarm #"+alarmId); String[] commandLine; Process child; try { switch (currentOS) { case MAC_OS: commandLine = new String[] { "/bin/sh", "-c", "crontab -l | (grep -v \""+ALARM_CLI_FORMAT+"\") | crontab" }; child = Runtime.getRuntime().exec(commandLine); break; case WINDOWS: commandLine = new String[] { "schtasks", "/Delete", "/TN \""+getAlarmName(alarmId)+"\"", "/F", }; child = Runtime.getRuntime().exec(commandLine); break; } } catch (final IOException e) { L.e("Unable to remove alarm #"+alarmId, e); } } public void triggerAlarm(final long alarmId) { // Do stuff //... L.i("Hi! I'm alarm #"+alarmId); // Remove alarm removeAlarm(alarmId); } }
用法很简单。使用以下命令安排新警报:
final AlarmManager m = new AlarmManager(); final Calendar cal = new GregorianCalendar(); cal.add(Calendar.MINUTE, 1); m.createAlarm(cal);
触发这样的警报:
public static void main(final String[] args) { if (args.length >= 2 && args[1] != null && args[1].contains(AlarmManager.ALARM_CLI_FORMAT)) { try { final long alarmId = Long.parseLong(args[1].replace(AlarmManager.ALARM_CLI_FORMAT, "")); final AlarmManager m = new AlarmManager(); m.triggerAlarm(alarmId); } catch (final NumberFormatException e) { L.e("Unable to parse alarm !", e); } } }
在Mac OS X.6和Windows Vista上进行了测试。该类L是我的助手,System.out.println并G保存我的全局常量(在这里,服务器上用于启动应用程序的JNLP文件)。
L
System.out.println
G