Android 通过轮询进行通知的学习

Android通知的两种方式

先说一下Android获取服务器的数据通知用户的两种方式,对这两种方式,网上有很多详细的讲解,我这里只简单的说一下优缺点,大家根据自己的业务需求选择使用吧。

  • 轮询:基于拉取(Pull)。Android端间隔固定时间主动去请求服务端,获取相关数据,然后进行通知,相比而言,耗电,占用资源,消息可能会延迟。
  • 推送:基于推送(Push)。服务端有数据时去通知Android端,比较及时

需求

我本来是集成的极光(JPush)推送,现在给了一个内网服务器,而且还要推,然后自己研究了下,还没搞完,因为我的需求是每天查一次是否需要推送,所以就用轮询了。
下面说的是通过轮询的方式,进行推送通知。

具体步骤

  1. 创建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

  1. 创建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);
    }
  1. 创建子线程编写业务逻辑
class PollingThread extends Thread {
        @Override
        public void run() {
            Log.i(TAG, "开始轮询...");
            ***逻辑***
            initNotification();
            Log.i(TAG, "进行推送...");
            }
        }
    }
  1. 创建轮询管理工具类

在轮询管理类中编写管理方法

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);
    }
}

  1. Manifest.xml文件中配置Service

在Manifest.xml文件中配置PollingService就可以使用了
android:process属性单独使用一个线程

<!-- 轮询服务 -->
        <service android:name=".common.pull.PollingService"
            android:process=":pollingcore"
            android:exported="false"/>
  1. 开启轮询

在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服务的保活,讲解的很详细,还附带一篇讲得很好的英文文章。

android轮询的方案

关于轮询、通知、Service保活这些点看了一些文章、越来越感觉自己真的是什么都不会。感觉自己快废了。
Android 通过轮询进行通知的学习