Android 通过轮询进行通知的学习
Android通知的两种方式
先说一下Android获取服务器的数据通知用户的两种方式,对这两种方式,网上有很多详细的讲解,我这里只简单的说一下优缺点,大家根据自己的业务需求选择使用吧。
- 轮询:基于拉取(Pull)。Android端间隔固定时间主动去请求服务端,获取相关数据,然后进行通知,相比而言,耗电,占用资源,消息可能会延迟。
- 推送:基于推送(Push)。服务端有数据时去通知Android端,比较及时
需求
我本来是集成的极光(JPush)推送,现在给了一个内网服务器,而且还要推,然后自己研究了下,还没搞完,因为我的需求是每天查一次是否需要推送,所以就用轮询了。
下面说的是通过轮询的方式,进行推送通知。
具体步骤
- 创建PollingService
public class PollingService extends Service {
private static final String TAG = "PollingService";
public static final String ACTION = "com.gzgsnet.patent.common.pull.PollingService";
// 通知
private Notification notification;
private NotificationManager manager;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
// 初始化通知
initNotification();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new PollingThread().start();
// 独立进程 + START_FLAG_REDELIVERY 可以在6.0以下的版本保活
flags = START_FLAG_REDELIVERY;
return super.onStartCommand(intent, flags, startId);
}
在onStartCommand()方法中,把flag设置为 START_FLAG_REDELIVERY 可以在App关闭后,重新启动Service。
我测了一下,清理掉App或者在设置里停止服务,都可以自动重启Service。
在Android6.0以下的版本可用。
START_FLAG_REDELIVERY
代表service被kill后重新启动,由于上次返回值为START_REDELIVER_INTENT,所以带输入参数intent
- 创建Notification
创建通知的相关设置
/**
* 初始化通知栏
*/
private void initNotification() {
// 系统通知管理类,获取NotificationManager对象
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// 初始化
Intent intent = new Intent(this, PayActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
notification = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_patent)
.setContentTitle(getResources().getString(R.string.app_name))
.setContentText("您有待缴费专利,请及时查看!")
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setPriority(Notification.PRIORITY_MAX)
.setDefaults(Notification.DEFAULT_SOUND)
.build();
// 向系统发送通知
manager.notify(0, notification);
}
- 创建子线程编写业务逻辑
class PollingThread extends Thread {
@Override
public void run() {
Log.i(TAG, "开始轮询...");
***逻辑***
initNotification();
Log.i(TAG, "进行推送...");
}
}
}
- 创建轮询管理工具类
在轮询管理类中编写管理方法
public class PollingManager {
/**
* 开启轮询
*/
public static void startPolling(Context context, int seconds, Class<?> cls, String action){
// 先获取系统AlarmManger服务
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// 得到要执行的对应的Service的意图
Intent intent = new Intent(context, cls);
intent.setAction(action);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// 启动服务的起始时间
long triggerAtTime = SystemClock.elapsedRealtime();
// 根据系统的AlarmManger服务设置轮询间隔时间和要执行的Service
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, triggerAtTime, seconds * 1000, pendingIntent);
}
/**
* 停止轮询
*/
public static void stopPolling(Context context, Class<?> cls, String action){
// 获取AlarmManager系统服务
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// 获取意图
Intent intent = new Intent(context, cls);
intent.setAction(action);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// 取消当前执行的Service
alarmManager.cancel(pendingIntent);
}
}
- Manifest.xml文件中配置Service
在Manifest.xml文件中配置PollingService就可以使用了
android:process属性单独使用一个线程
<!-- 轮询服务 -->
<service android:name=".common.pull.PollingService"
android:process=":pollingcore"
android:exported="false"/>
- 开启轮询
在MainActivity 的onCreate中开启轮询
// 开启轮询服务
PollingManager.startPolling(this, 10, PollingService.class, PollingService.ACTION);
Log.i(TAG, "onCreate: 开启轮询");
@Override
protected void onDestroy() {
super.onDestroy();
PollingManager.stopPolling(this, PollingService.class, PollingService.ACTION);
Log.i(TAG, "onDestroy: 停止轮询");
}
参考的博客:
android服务的保活,讲解的很详细,还附带一篇讲得很好的英文文章。
关于轮询、通知、Service保活这些点看了一些文章、越来越感觉自己真的是什么都不会。感觉自己快废了。