【问题标题】:How to create persistent alarms even after rebooting即使在重新启动后如何创建持久警报
【发布时间】:2013-05-14 02:18:29
【问题描述】:

目前,我正在开发类似于“待办事项列表”的应用程序。我已经在我的应用程序中成功实现了 NotificationService 和 SchedularService。我还在为任务设置的时间收到警报(通知)。 以下是我的查询:

  1. 使用此代码,我的警报会在重启后被删除吗?如果是,如何克服这个问题。
  2. 我保留了任务的优先级功能。但我想要这样的机制,如果用户选择优先级“高”,那么他应该收到三次通知,例如,在 30 分钟之前、15 分钟之前和设定的时间。如何做到这一点?
  3. 我想在通知出现时设置手机的振动功能。如何做到这一点?
  4. 我想知道,可以为 NotifyService.java 中已弃用的方法和构造函数做些什么。这些在 API 级别 11 中已弃用:Notification notification = new Notification(icon, text, time);notification.setLatestEventInfo(this, title, text, contentIntent);。在 developer.android.com 上,他们建议改用 Notification.Builder。那么如何让我的应用兼容所有 API 级别。

这是我用于安排闹钟的 sn-p 代码:

...
scheduleClient.setAlarmForNotification(c, tmp_task_id);
...

这是 ScheduleClient.java 类:

public class ScheduleClient {

    private ScheduleService mBoundService;
    private Context mContext;
    private boolean mIsBound;

    public ScheduleClient(Context context)
    {
        mContext = context;
    }

    public void doBindService()
    {   
        mContext.bindService(new Intent(mContext, ScheduleService.class), mConnection, Context.BIND_AUTO_CREATE);
        mIsBound = true;
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {

            mBoundService = ((ScheduleService.ServiceBinder) service).getService();
        }

        public void onServiceDisconnected(ComponentName className) {

            mBoundService = null;
        }
    };

    public void setAlarmForNotification(Calendar c, int tmp_task_id){

        mBoundService.setAlarm(c, tmp_task_id);
    }

    public void doUnbindService() {
        if (mIsBound)
        {           
            mContext.unbindService(mConnection);
            mIsBound = false;
        }
    }
}

这是 ScheduleService.java:

public class ScheduleService extends Service {

    int task_id;

    public class ServiceBinder extends Binder {

        ScheduleService getService() {

            return ScheduleService.this;
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {

        return mBinder;
    }

    private final IBinder mBinder = new ServiceBinder();

    public void setAlarm(Calendar c, int tmp_task_id) {

        new AlarmTask(this, c, tmp_task_id).run();
    }
}

这是 AlarmTask.java:

public class AlarmTask implements Runnable{

    private final Calendar date;
    private final AlarmManager am;
    private final Context context;
    int task_id;

    public AlarmTask(Context context, Calendar date, int tmp_task_id) {
        this.context = context;
        this.am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        this.date = date;

        task_id = tmp_task_id;
    }

    @Override
    public void run() {

        Intent intent = new Intent(context, NotifyService.class);
        intent.putExtra(NotifyService.INTENT_NOTIFY, true);
        intent.putExtra("task_id", task_id);
        PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);

        am.set(AlarmManager.RTC, date.getTimeInMillis(), pendingIntent);
    }
}

这是 NotifyService.java:

public class NotifyService extends Service {

    public class ServiceBinder extends Binder
    {   
        NotifyService getService()
        {
            return NotifyService.this;
        }
    }

    int task_id;
    private static final int NOTIFICATION = 123;
    public static final String INTENT_NOTIFY = "com.todotaskmanager.service.INTENT_NOTIFY";
    private NotificationManager mNM;
    SQLiteDatabase database;

    @Override
    public void onCreate() {

        mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        String tmp_task_brief = null;
        task_id = intent.getIntExtra("task_id", 0);

        loadDatabase();
        Cursor cursor = database.query("task_info", new String[]{"task_brief"}, "task_id=?", new String[]{task_id+""}, null, null, null);
        while(cursor.moveToNext())
        {
            tmp_task_brief = cursor.getString(0);
        }
        cursor.close();

        if(intent.getBooleanExtra(INTENT_NOTIFY, false))
            showNotification(tmp_task_brief);

        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {

        return mBinder;
    }

    private final IBinder mBinder = new ServiceBinder();

    private void showNotification(String tmp_task_brief) {

        CharSequence title = "To Do Task Notification!!";
        int icon = R.drawable.e7ca62cff1c58b6709941e51825e738f;
        CharSequence text = tmp_task_brief;     
        long time = System.currentTimeMillis();

        Notification notification = new Notification(icon, text, time);

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, TaskDetails.class), 0);

        notification.setLatestEventInfo(this, title, text, contentIntent);

        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        mNM.notify(NOTIFICATION, notification);

        stopSelf();
    }

    void loadDatabase()
    {
        database = openOrCreateDatabase("ToDoDatabase.db",
                SQLiteDatabase.OPEN_READWRITE, null);
    }
}

【问题讨论】:

    标签: android android-notifications android-alarms


    【解决方案1】:

    使用此代码,我的警报会在重启后被删除吗?如果是,如何克服。

    是的,警报会被删除,要解决这个问题,您需要使用Android的名为BroadcastReceiver的组件,如下所示,

    首先,您需要清单中的权限:

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    

    另外,在您的清单中,定义您的服务并监听启动完成的操作:

    <receiver
        android:name=".receiver.StartMyServiceAtBootReceiver"
        android:enabled="true"
        android:exported="true"
        android:label="StartMyServiceAtBootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    

    然后您需要定义将获得 BOOT_COMPLETED 操作并启动您的服务的接收器。

    public class StartMyServiceAtBootReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
                Intent serviceIntent = new Intent("com.myapp.NotifyService");
                context.startService(serviceIntent);
            }
        }
    }
    

    现在您的服务应该在手机启动时运行。

    2 振动

    同样需要在AndroidManifest.xml文件中定义一个权限,如下,

    <uses-permission android:name="android.permission.VIBRATE"/>
    

    这是振动的代码,

    // Get instance of Vibrator from current Context
    Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
    
    // Vibrate for 300 milliseconds
    v.vibrate(300);
    

    【讨论】:

    • 所以你的问题的答案,......使用此代码,通过实施,我的警报不会被删除,不是吗?我应该为此创建单独的java文件还是将此类添加为其他类的子类?
    • 是的,警报将持续存在,因为它会在每次设备启动时调用。您可以在同一个包中创建,无需创建不同的包。
    • 对不起,你能告诉我在哪里实现你的代码,因为我是BroadCastReceiver的新手
    • 当然,就像你为Service创建了一个新类一样,你需要为BroadcastReceiver创建一个文件/类
    • 非常感谢朋友。我非常感谢您对 android 的了解。继续努力吧。你能帮我解决剩下的两个问题吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多