android 建立长连接的方法
1、方案一:service +Thread
在service中开启一个带有while循环的线程,使其不断的从服务器查询数据(一定时间间隔内),当发现有需要通知用户的情况下发送notification。这种方案的代码大致是:
/***************************************************** * author: wz * email: wangzhong0116@foxmail.com * version: 1.0 * date: 2016/12/2 16:11 * description: *****************************************************/ public class SocketService extends Service { public static WebSocketClient client; private ConnectivityManager connectivityManager; private NetworkInfo info; private boolean iscon = true;//用于在broadcast中判断是否是需要重新连接的 private NotificationManager manager; private NotificationCompat.Builder notifyBuilder; private Vibrator vibrator; private MyThread myThread; @Override public void onCreate() { super.onCreate(); manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); IntentFilter mFilter = new IntentFilter(); mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(mReceiver, mFilter); this.myThread = new MyThread(); this.myThread.start(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } private void connectClient() { //此处为连接websocket大家如果有兴趣的话 可以去看看我的上一篇博客
} @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public boolean stopService(Intent name) { return super.stopService(name); } @Override public void onDestroy() { super.onDestroy(); } @Override public IBinder onBind(Intent intent) { return null; } /** * 接受到网络重连的广播时重新执行startcommoned方法让client重连 */ private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); info = connectivityManager.getActiveNetworkInfo(); if (info != null && info.isAvailable() && iscon == false) { //断网的时候client会被close (调用了onclose方法) Intent serviceIntent = new Intent(context, SocketService.class); context.startService(serviceIntent); // client.connect(); //不能用client直接connect,具体原因期待有人指出,可能是classnotfind? } } } }; private class MyThread extends Thread { @Override public void run() { while (true) { System.out.println("发送请求"); try { // 每个10秒向服务器发送一次请求 Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } // 如果websocket是断开则重新连接 // if (client!=null){ // try { // System.out.println("=====not null======"); // } catch (InterruptedException e) { // e.printStackTrace(); // } // }else{ // System.out.println("=====yes null======"); // connectClient(); // } } } } }2、 service+AlarmManager+Thread
虽然alarm的意思是闹钟,而且在原生android自带的闹钟应用中AlarmManager也确实非常重要,但并不代表AlarmManager只是用来做闹钟应用的,作为一个一种系统级别的提示服务,肯定应该有着非常重要的地位,实际上android中很多东西都可以利用AlarmManager来实现。
AlarmManager在特定的时刻为我们广播一个指定的Intent。简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定的Intent。这个intent可以指向一个activity,也可以指向一个service。
下面就是使用alarm定时调用service实现轮询的实现方法:
-
public class ArUtils { //开启轮询服务 public static void startPollingService(Context context, int seconds, Class<?> cls, String action) { //获取AlarmManager系统服务 AlarmManager manager = (AlarmManager) context .getSystemService(Context.ALARM_SERVICE); //包装需要执行Service的Intent 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的setRepeating方法设置定期执行的时间间隔(seconds秒)和需要执行的Service manager.setRepeating(AlarmManager.ELAPSED_REALTIME, triggerAtTime, seconds * 1000, pendingIntent); } //停止轮询服务 public static void stopPollingService(Context context, Class<?> cls,String action) { AlarmManager manager = (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); //取消正在执行的服务 manager.cancel(pendingIntent); } }
public class ArService extends Service { public static final String ACTION = "com.wz.service.ArService"; private Notification mNotification; private NotificationManager mManager; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { initNotifiManager(); } @Override public void onStart(Intent intent, int startId) { new PollingThread().start(); } //初始化通知栏配置 private void initNotifiManager() { mManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); int icon = R.mipmap.ic_launcher; mNotification = new Notification(); mNotification.icon = icon; mNotification.tickerText = "New Message"; mNotification.defaults |= Notification.DEFAULT_SOUND; mNotification.flags = Notification.FLAG_AUTO_CANCEL; } //弹出Notification private void showNotification() { mNotification.when = System.currentTimeMillis(); //Navigator to the new activity when click the notification title // Intent i = new Intent(this, LoginActivity.class); // PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, // Intent.FLAG_ACTIVITY_NEW_TASK); // mNotification.setLatestEventInfo(this, // getResources().getString(R.string.app_name), "You have new message!", pendingIntent); // mManager.notify(0, mNotification); } /** * 模拟向Server轮询的异步线程 */ int count = 0; class PollingThread extends Thread { @Override public void run() { System.out.println("Polling..."); count ++; //当计数能被5整除时弹出通知 if (count % 5 == 0) { showNotification(); System.out.println("New message!"); } } } @Override public void onDestroy() { super.onDestroy(); System.out.println("Service:onDestroy"); } }
public class ArActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); //Start polling service System.out.println("Start polling service..."); ArUtils.startPollingService(this, 5, ArService.class, ArService.ACTION); } @Override protected void onDestroy() { super.onDestroy(); //Stop polling service System.out.println("Stop polling service..."); ArUtils.stopPollingService(this, ArService.class, ArService.ACTION); } }
,一种是利用系统服务,一种是自己通过while循环。显然使用系统服务具有更高的稳定性,而且恰好解决了休眠状态下轮询中断的问题,因为AlarmManager是始终运行者的。