Android实现定点提醒

Android实现定点提醒

接下来我要教大家如何实现一个APP后台的定点提醒Service,功能包括输入时间后长期在后台运行,到达提醒时间时,发送Notification手机通知栏,提醒用户。

实现原理:
将需要提醒的内容及时间存入数据库中,启动Service时检测数据库是否有未提醒的时间,遍历数据库,从第一条最近的提醒时间开始,发送时间给手机系统闹钟,再定义一个广播接收器,接收系统闹钟到点后的提醒。再发送Notification提醒用户,需要的做的事。

步骤一

创建SQLite数据库


/**

*缓存数据的SQLite

* 2016/9/27.

*/

public class AppSQLiteData extends SQLiteOpenHelper {

public static String Remind_data="create table Remind_data("

+"id integer primary key autoincrement, "

+"remindTime long,"

+"content text,"

+"title text"+")";

private Context mContext;

public AppSQLiteData(Context context,String name,SQLiteDatabase.CursorFactory factory, intversion) {

super(context,name,factory,version);

mContext= context;

}

@Override

public void onCreate(SQLiteDatabase db) {

db.execSQL(Remind_data);

}

@Override

public void onUpgrade(SQLiteDatabase db, intoldVersion, intnewVersion) {

}

}

这里建了一个表,里面存入三个提醒时需要的信息,分别是时间,内容,跟标题。时间我采用的是毫秒型,所以存入的Long型。然后向数据库添加我们需要提醒的时间跟内容。

private AppSQLiteData mRemindSQL;
public void AddData(final Context context, final List<RemindList> data) {
//将获取到的便签列表时间缓存入SQL
new Thread(new Runnable() {
@Override
public void run() {   
 Calendar c = Calendar.getInstance();//获取当前时间,为了判断添加时间是否已经过时
 mRemindSQL= new AppSQLiteData(context, "Remind.db", null, 1);
 mRemindSQL.getWritableDatabase();
 SQLiteDatabase db = mRemindSQL.getWritableDatabase();
 ContentValues values = new ContentValues();
 for (int i = 0; i < data.size() - 1; i++) {
  if (!data.get(i).getRemindTime().equals("") && Long.parseLong(data.get(i).getRemindTime()) > c.getTimeInMillis()) {
    values.put("remindTime", Long.parseLong(data.get(i).getRemindTime()));
    values.put("title", data.get(i).getTitle());
    values.put("content", data.get(i).getLevel());
db.insert("Remind_data", null, values);
     }
values.clear();
  }}).start();

需要注意的是我这里的List是接收的一个实体类,你们可以手动添加data数据,或者自定义实体类,再传入数据,方法名请自行修改。if是判断时间是否大于当前时间,否则不添加。


步骤二

创建Service,后台处理提醒的数据。

public class AlarmService extends Service {  
  private AlarmManager am;  
  private PendingIntent pi;  
  private Long time;   
  private String title; 
  private String content;
  private AppSQLiteData mRemindSQL;    
@Nullable    
@Override    
public IBinder onBind(Intent intent) {  
      return null; 
   }    
@Override    
public void onCreate() {     
   super.onCreate();  
  }    
@Override    
public int onStartCommand(Intent intent, int flags, int startId) { 
       getAlarmTime();
       return START_REDELIVER_INTENT;    } //这里为了提高优先级,选择START_REDELIVER_INTENT 没那么容易被内存清理时杀死
@Override    
public void onDestroy() {    
    super.onDestroy();    
}    
public void getAlarmTime() {  
      mRemindSQL= new AppSQLiteData(this,"Remind.db", null, 1);  
      SQLiteDatabase db = mRemindSQL.getWritableDatabase();   
      Cursor cursor = db.query("Remind_data", null, null, null, null, null, null);        
      if (cursor.moveToFirst()) { //遍历数据库的表,拿出一条,选择最近的时间赋值,作为第一条提醒数据。
           time = cursor.getLong(cursor.getColumnIndex("remindTime")); 
           title = cursor.getString(cursor.getColumnIndex("title")); 
           content = cursor.getString(cursor.getColumnIndex("content"));   
         do {   if (time > cursor.getLong(cursor.getColumnIndex("remindTime"))) {   
                 time = cursor.getLong(cursor.getColumnIndex("remindTime"));  
                 title = cursor.getString(cursor.getColumnIndex("title"));   
                 content = cursor.getString(cursor.getColumnIndex("content")); 
                            }    
             } while (cursor.moveToNext());      
          } else {          
          time = null;    
              }     
    db.delete("Remind_data", "remindTime=?", new String[]{String.valueOf(time)});      //删除已经发送提醒的时间
    cursor.close();     //记得关闭游标,防止内存泄漏  
   Intent startNotification = new Intent(this, AlarmReceiver.class);   //这里启动的广播,下一步会教大家设置
      startNotification.putExtra("title", title);    
      startNotification.putExtra("content", content); 
     am = (AlarmManager) getSystemService(ALARM_SERVICE);   //这里是系统闹钟的对象
     pi = PendingIntent.getBroadcast(this, 0, startNotification, PendingIntent.FLAG_UPDATE_CURRENT);     //设置事件
   if (time != null) {      
      am.set(AlarmManager.RTC_WAKEUP, time, pi);    //提交事件,发送给 广播接收器
  } else {    
        //当提醒时间为空的时候,关闭服务,下次添加提醒时再开启        
    stopService(new Intent(this, AlarmService.class));  
          }   
 }}

因为是长期运行在后台,所以没有与Activity进行绑定操作,这里做的就是读取数据库的数据,然后一条一条启动闹钟事件,到点后发送广播给BroadcastReceiver,提醒完成后,再次回调服务,开启下一条提醒,直到没有提醒时关闭。

一定要记得在AndroidManifest中配置Service,这里我取名为AlarmService。优先级设置最大,防止被内存回收销毁。

Service配置.png


步骤三

设置BroadcastReceiver广播接收器,接收系统闹钟发送过来的广播。实现提醒业务,这里我采用的是Notification通知,可根据自己需求更改。

public class AlarmReceiver extends BroadcastReceiver { 
   private NotificationManager manager; 
   private static final int NOTIFICATION_ID_1 = 0x00113;  
   private String title;
   private String content = "提醒的时间到啦,快看看你要做的事..."; 
 @Override
  public void onReceive(Context context, Intent intent) { 
//此处接收闹钟时间发送过来的广播信息,为了方便设置提醒内容
        title = intent.getStringExtra("title"); 
        content = intent.getStringExtra("content ");
        showNormal(context);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setClass(context, AlarmService.class); 
        context.startService(intent);  //回调Service,同一个Service只会启动一个,所以直接再次启动Service,会重置开启新的提醒,
  }    /**     * 发送通知     */   
 private void showNormal(Context context) { 
        Intent intent = new Intent(context, BianQianDataActivity.class);//这里是点击Notification 跳转的界面,可以自己选择
        PendingIntent pi = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 
        Notification notification = new NotificationCompat.Builder(context)
                .setSmallIcon(R.mipmap.daka)     //设置通知图标。
                .setTicker(content)        //通知时在状态栏显示的通知内容
                .setContentInfo("便签提醒")        //内容信息       
                .setContentTitle(title)        //设置通知标题。
                .setContentText(content)        //设置通知内容。
                .setAutoCancel(true)                //点击通知后通知消失
                .setDefaults(Notification.DEFAULT_ALL)        //设置系统默认的通知音乐、振动、LED等。
                .setContentIntent(pi) 
               .build();
        manager.notify(NOTIFICATION_ID_1, notification);
    }}

到这里,一个基本的定点提醒服务就完成了,可以根据需求,完成提醒后的业务逻辑,比如直接弹出应用等。在存入提醒的时间后,启动服务就行,另外Receiver和Service都需要在配置文件中注册,不可忘记。

扩展

另外还可以根据个人需求,设置开机自启动该服务,只需要监听系统广播即可,我建议是开启自启动的,否则关机后,有的提醒将无法完成。

//开机广播接收
public class BootReceiver extends BroadcastReceiver { 
   public BootReceiver() {    }
    private final String ACTION = "android.intent.action.BOOT_COMPLETED"; 
   @Override 
   public void onReceive(Context context, Intent intent) {  
      if (intent.getAction().equals(ACTION)) { 
           Intent inten2 = new Intent(context, AlarmService.class); 
           context.startService(inten2);
        }  
            boolean isServiceRunning = false;
        if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) { 
           //检查Service状态   
         ActivityManager manager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);  
          for (ActivityManager.RunningServiceInfo service :manager.getRunningServices(Integer.MAX_VALUE)) {  
              if("so.xxxx.xxxxService".equals(service.service.getClassName()))                {      
              isServiceRunning = true;        
        }         
   }      
      if (!isServiceRunning) {    
    Intent i = new Intent(context, AlarmService.class); 
       context.startService(i);   
         }     
   }
    }}

在这里,我还实现了检测服务是否被关闭,每五分钟会监听到一个系统广播,如果服务被关闭,就会再次启动。当然,这个定点提醒做到这里,一般的情况下已经有点死皮赖脸难以被杀死,你如果还想更流氓一点,就去看一下守护进程的相关知识,
链接
守护进程相关知识

结语

刚开始用简书写文章,还不太习惯,代码还是自己一行一行的排版,不太好看,大家如果有什么问题,或者我代码中有什么错误,欢迎大家指出,定为修改,不懂的也可以提问,,谢谢!

本文为原创文章,未经允许不得转载

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值