赞
踩
1.导入Java-WebSocket依赖
implementation "org.java-websocket:Java-WebSocket:1.5.2"
2.AndroidManifest 添加权限和service 代码
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<service android:name=".WebSocketService"></service>
3.服务包含心跳检测和连接操作
public class WebSocketService extends Service { private final static String TAG = "WebSocketService"; public JWebSocketClient client; private JWebSocketClientBinder mBinder = new JWebSocketClientBinder(); private final static int GRAY_SERVICE_ID = 1001; private static final long CLOSE_RECON_TIME = 15000;//连接断开或者连接错误立即重连 private Notification notification; //用于Activity和service通讯 public class JWebSocketClientBinder extends Binder { public WebSocketService getService() { return WebSocketService.this; } } //灰色保活 public static class GrayInnerService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { startForeground(GRAY_SERVICE_ID, new Notification()); stopForeground(true); stopSelf(); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return null; } } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { //初始化WebSocket initSocketClient(); mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//开启心跳检测 //设置service为前台服务,提高优先级 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { //Android4.3以下 ,隐藏Notification上的图标 startForeground(GRAY_SERVICE_ID, new Notification()); } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { //Android4.3 - Android8.0,隐藏Notification上的图标 Intent innerIntent = new Intent(this, GrayInnerService.class); startService(innerIntent); startForeground(GRAY_SERVICE_ID, new Notification()); } else { Intent nfIntent = new Intent(this, MainActivity.class); @SuppressLint("UnspecifiedImmutableFlag") Notification.Builder builder = new Notification.Builder(this.getApplicationContext()) .setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0)) // 设置PendingIntent .setSmallIcon(R.mipmap.ic_launcher) // 设置状态栏内的小图标 .setPriority(Notification.PRIORITY_MIN) .setContentTitle(getResources().getString(R.string.app_name)) .setContentText("正在前台运行") // 设置上下文内容 .setWhen(System.currentTimeMillis()); // 设置该通知发生的时间 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { //修改安卓8.1以上系统报错 NotificationChannel notificationChannel = new NotificationChannel("1", "CHANNEL_ONE_NAME", NotificationManager.IMPORTANCE_MIN); notificationChannel.enableLights(false);//如果使用中的设备支持通知灯,则说明此通知通道是否应显示灯 notificationChannel.setShowBadge(false);//是否显示角标 notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); manager.createNotificationChannel(notificationChannel); builder.setChannelId("1"); } // 获取构建好的Notification notification = builder.build(); notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音 startForeground(GRAY_SERVICE_ID, notification); } return START_STICKY; } //这里是处理webscoket private void initSocketClient() { String url = "ws://端口号:ip地址"; //协议标识符是ws //ws://172.18.130.52:8089/webSocket/notice/117 //协议标识符是ws //(如果加密,则为wss),服务器网址就是 URL。 此处增加了请求头不需要的将map去掉即可 URI uri = URI.create(url); HashMap<String, String> map = new HashMap<>(); map.put("Authorization","eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjMyMjUwNTAzLTBlZmEtNDM5Mi1hYTQwLWRjNzk4YzE5M2Y3MSJ9.9mIXUU7UtdGm8ze6KhfSaeBPmeCelzd1RQn1B7akK-CF38MwVPwjqaknasjMiDI4WBUzX_2PRw2rQaYuOiSjlw"); client = new JWebSocketClient(uri,map) { @Override public void onMessage(String message) { //message就是接收到的消息 Log.d(TAG, "WebSocketService收到的消息:" + message); //这里我通过EvenBus获取接收的消息并更新ui //EventBus.getDefault().post(new WebSocketEvent(message)); } @Override public void onOpen(ServerHandshake handShakeData) {//在webSocket连接开启时调用 //EventBus.getDefault().post("WebSocket 连接成功"); Log.d(TAG, "WebSocket 连接成功" ); } @Override public void onClose(int code, String reason, boolean remote) {//在连接断开时调用 Log.d(TAG, "onClose() 连接断开_reason:" + reason ); //EventBus.getDefault().post("onClose() 连接断开_reason:" + reason ); mHandler.removeCallbacks(heartBeatRunnable); mHandler.postDelayed(heartBeatRunnable, CLOSE_RECON_TIME);//开启心跳检测 } @Override public void onError(Exception ex) {//在连接出错时调用 //EventBus.getDefault().post("onError() 连接出错:" + ex.getMessage() ); Log.d(TAG, "onError() 连接出错:" + ex.getMessage() ); mHandler.removeCallbacks(heartBeatRunnable); mHandler.postDelayed(heartBeatRunnable, CLOSE_RECON_TIME);//开启心跳检测 } }; connect(); } /** * 连接WebSocket */ private void connect() { new Thread() { @Override public void run() { try { //connectBlocking多出一个等待操作,会先连接再发送,否则未连接发送会报错 client.connectBlocking(); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); } /** * 发送消息 */ public void sendMsg(String msg) { if (null != client) { try { client.send(msg); } catch (Exception e) { e.printStackTrace(); } } } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public void onDestroy() { closeConnect(); super.onDestroy(); } /** * 断开连接 */ public void closeConnect() { mHandler.removeCallbacks(heartBeatRunnable); try { if (null != client) { client.close(); } } catch (Exception e) { e.printStackTrace(); } finally { client = null; } } // -------------------------------------WebSocket心跳检测------------------------------------------------ private static final long HEART_BEAT_RATE = 5 * 1000; //每隔10秒进行一次对长连接的心跳检测 private Handler mHandler = new Handler(); private Runnable heartBeatRunnable = new Runnable() { @Override public void run() { if (client != null) { if (client.isClosed()) { reconnectWs(); Log.d(TAG, "心跳包检测WebSocket连接状态:已关闭" ); //EventBus.getDefault().post("WebSocket 已关闭"); } else if (client.isOpen()) { Log.d(TAG, "心跳包检测WebSocket连接状态:已连接" ); //EventBus.getDefault().post("WebSocket 已连接"); } else { //EventBus.getDefault().post("WebSocket 已断开"); Log.d(TAG, "心跳包检测WebSocket连接状态:已断开" ); } } else { //如果client已为空,重新初始化连接 initSocketClient(); Log.d(TAG, "心跳包检测WebSocket连接状态:client已为空,重新初始化连接" ); } //每隔一定的时间,对长连接进行一次心跳检测 mHandler.postDelayed(this, HEART_BEAT_RATE); } }; /** * 开启重连 */ private void reconnectWs() { mHandler.removeCallbacks(heartBeatRunnable); new Thread() { @Override public void run() { try { Log.d(TAG, "开启重连" ); client.reconnectBlocking(); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); } public class AuxiliaryService extends Service { @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) { startNotification(); return super.onStartCommand(intent, flags, startId); } /** 启动通知*/ private void startNotification(){ Notification notification = new Notification(); this.startForeground(GRAY_SERVICE_ID, notification); stopSelf(); //关键 如果AuxiliaryService 没有与什么组件绑定 系统就会回收 stopForeground(true); } } }
4.工具类
public class JWebSocketClient extends WebSocketClient { public JWebSocketClient(URI serverUri ,Map<String,String> map) { super(serverUri, new Draft_6455(),map); } @Override public void onOpen(ServerHandshake handshakedata) { Log.e("JWebSocketClient", "onOpen()"); //ToastUtils.show(getmContext(),"onOpen()"); } @Override public void onMessage(String message) { Log.e("JWebSocketClient", "onMessage():"+message); } @Override public void onClose(int code, String reason, boolean remote) { Log.e("JWebSocketClient", "onClose()"); //ToastUtils.show(getmContext(),"onClose()"); } @Override public void onError(Exception ex) { Log.e("JWebSocketClient", "onError()"+ex.getMessage()); //ToastUtils.show(getmContext(),"onError()"); } }
5.在appliction启动也可以在其他地方看需求别忘了在清单文件注册
public class App extends Application { public static Context mContext; public WebSocketService mWebSocketService; private final static String TAG = "Application"; private static final String DEVICE_TOKEN = "device_token";//设备token @Override public void onCreate() { super.onCreate(); mContext=this; //开启 startWebSocketService(DEVICE_TOKEN); } private static final long HEART_BEAT_RATE = 5 * 1000;//每隔1分钟发送空消息保持WebSocket长连接 public static Context getmContext() { return mContext; } private Handler mHandler = new Handler(); private Runnable webSocketRunnable = new Runnable() { @Override public void run() { if (mWebSocketService != null && mWebSocketService.client != null && mWebSocketService.client.isOpen()) { try { JSONObject jsonObject = new JSONObject(); jsonObject.put("from",""); jsonObject.put("to", ""); mWebSocketService.sendMsg(jsonObject.toString()); } catch (JSONException e) { e.printStackTrace(); } } //每隔一定的时间,对长连接进行一次心跳检测 mHandler.postDelayed(this, HEART_BEAT_RATE); } }; public WebSocketService getWebSocketService() { return mWebSocketService; } /** * 开启并绑定WebSocket服务 */ public void startWebSocketService(String deviceToken) { Intent bindIntent = new Intent(this, WebSocketService.class); bindIntent.putExtra(DEVICE_TOKEN, deviceToken); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //android8.0以上通过startForegroundService启动service startForegroundService(bindIntent); } else { startService(bindIntent); } bindService(bindIntent, serviceConnection, BIND_AUTO_CREATE); mHandler.removeCallbacks(webSocketRunnable); mHandler.postDelayed(webSocketRunnable, HEART_BEAT_RATE);//开启心跳检测 } private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { //服务与活动成功绑定 mWebSocketService = ((WebSocketService.JWebSocketClientBinder) iBinder).getService(); Log.d(TAG, "WebSocket服务与Application成功绑定"); } @Override public void onServiceDisconnected(ComponentName componentName) { //服务与活动断开 mWebSocketService = null; Log.d(TAG, "WebSocket服务与Application成功断开: "); } }; }
6.至此就可简单实现Android端的代码后台有需要demo的可以私聊我
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。