package com.xwad.os.service; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.text.TextUtils; import android.util.Log; import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import com.blankj.utilcode.util.NetworkUtils; import com.google.gson.JsonObject; import com.tencent.mmkv.MMKV; import com.xwad.os.BuildConfig; import com.xwad.os.R; import com.xwad.os.activity.main.MainActivity; import com.xwad.os.config.CommonConfig; import com.xwad.os.manager.RemoteManager; import com.xwad.os.utils.ActivationUtil; import com.xwad.os.utils.LenovoCsdkUtil; import com.xwad.os.utils.Utils; import com.xwad.os.websocket.JWebSocketClient; import org.java_websocket.handshake.ServerHandshake; import java.net.URI; import java.util.concurrent.TimeUnit; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.functions.Consumer; /** * 【有道云笔记】学生项目-用户端websocket对接.md * https://note.youdao.com/s/Pbv87efV *

* 【有道云笔记】学生项目-设备端websocket对接.md * https://note.youdao.com/s/Ea0tebj8 *

* 【有道云笔记】学生项目-管理端websocket对接.md * https://note.youdao.com/s/MazEq49Q *

* 老人在线websocket重构了,按照这个重新对接,跟之前售后差不多是一样的。 *

* 1.设备未激活 不链接websocket 形成不了关联,设备激活后,才链接websocket * 2.已激活的设备,设备若已链接websocket,用户确认绑定后,断开websocket 等待5秒 再重新链接websocket 以刷新用户关联 * 3.设备用户解除绑定后,断开websocket 等待5秒 再重新链接websocket 以刷新用户关联 */ public class SocketService extends Service implements NetworkUtils.OnNetworkStatusChangedListener { private static final String TAG = "JWebSocketClientService"; private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); public JWebSocketClient mJWebSocketClient; // private SocketServiceBinder mBinder = new SocketServiceBinder(); @Override public void onDisconnected() { Log.i(TAG, "网络断开连接"); } @Override public void onConnected(NetworkUtils.NetworkType networkType) { Log.i(TAG, "网络已连接"); } //用于Activity和service通讯 public class SocketServiceBinder extends Binder { public SocketService getService() { return SocketService.this; } } // private ServiceConnection mServiceConnection = new ServiceConnection() { // @Override // public void onServiceConnected(ComponentName componentName, IBinder iBinder) { // Log.e(TAG, "onServiceConnected: componentName = " + componentName); // boolean isServiceRunning = ServiceAliveUtils.isServiceAlive(SocketService.this, ManagerService.class.getName()); // Log.e(TAG, "onServiceConnected: isServiceRunning = " + isServiceRunning); // if (!isServiceRunning) { // startService(new Intent(SocketService.this, ManagerService.class)); // } // } // // @Override // public void onServiceDisconnected(ComponentName componentName) { // Log.e(TAG, "onServiceDisconnected: "); // // 断开链接 // startService(new Intent(SocketService.this, ManagerService.class)); // // 重新绑定 // bindService(new Intent(SocketService.this, ManagerService.class), mServiceConnection, Context.BIND_IMPORTANT); // } // }; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); Log.e(TAG, "onCreate: "); NetworkUtils.registerNetworkStatusChangedListener(this); registerScreenLockReceiver(); registerJxwRegisterRefreshReceiver(); if (ActivationUtil.getInstance().isActivation()) { //初始化websocket initSocketClient(); startLoop(); } else { Log.e(TAG, "onCreate: 未激活不连接"); } // boolean isServiceRunning = ServiceAliveUtils.isServiceAlive(this, MainService.class.getName()); // Log.e(TAG, "onCreate: isServiceRunning = " + isServiceRunning); // if (!isServiceRunning) { // startService(new Intent(this, MainService.class)); // } // bindService(new Intent(this, ManagerService.class), mServiceConnection, Context.BIND_IMPORTANT); mNotificationManagerCompat = NotificationManagerCompat.from(this); createNotificationChannel(); // showNotification(); sendSimpleNotification(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "onStartCommand: "); return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); NetworkUtils.unregisterNetworkStatusChangedListener(this); dispose(); closeConnect(); if (mScreenLockReceiver != null) { unregisterReceiver(mScreenLockReceiver); } if (mJxwRegisterReceiver != null) { unregisterReceiver(mJxwRegisterReceiver); } // unbindService(mServiceConnection); } private static final String CHANNEL_ID = "CHANNEL_ID"; private static final String CHANNEL_NAME = "系统通知"; private static final String CHANNEL_DESCRIPTION = "学习课堂通知"; private void createNotificationChannel() { // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is new and not in the support library if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = CHANNEL_NAME; String description = CHANNEL_DESCRIPTION; int importance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); channel.setDescription(description); // Register the channel with the system; you can't change the importance // or other notification behaviors after this NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } } private NotificationManagerCompat mNotificationManagerCompat; private int NotificationID = 1; private void sendSimpleNotification() { Intent intent = new Intent(this, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "CHANNEL_ID") .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("学习课堂正在运行") // .setContentText("测试内容") .setAutoCancel(false) .setShowWhen(false) .setContentIntent(pendingIntent) .setOngoing(true) .setOnlyAlertOnce(true) .setPriority(NotificationCompat.PRIORITY_MAX); // notificationId is a unique int for each notification that you must define // mNotificationManagerCompat.notify(NotificationID, builder.build()); startForeground(NotificationID, builder.build()); } private ScreenLockReceiver mScreenLockReceiver; private void registerScreenLockReceiver() { if (null == mScreenLockReceiver) { mScreenLockReceiver = new ScreenLockReceiver(); } IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_BOOT_COMPLETED); filter.addAction(Intent.ACTION_USER_PRESENT); filter.addAction(Intent.ACTION_SHUTDOWN); filter.addAction(Intent.ACTION_FACTORY_RESET); filter.addAction(Intent.ACTION_MASTER_CLEAR); registerReceiver(mScreenLockReceiver, filter); } private class ScreenLockReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.e(TAG, "onReceive:" + action); if (TextUtils.isEmpty(action)) { Log.e(TAG, "onReceive: is NULL"); return; } switch (action) { case Intent.ACTION_BOOT_COMPLETED: case Intent.ACTION_USER_PRESENT: case Intent.ACTION_SCREEN_ON: sendMsgScreen(); break; case Intent.ACTION_SCREEN_OFF: case Intent.ACTION_SHUTDOWN: case Intent.ACTION_FACTORY_RESET: case Intent.ACTION_MASTER_CLEAR: sendMsgScreen(); break; default: break; } } } public static final String JXW_REGISTER_SUCCESS = "com.zzj.regist_success"; private JxwRegisterReceiver mJxwRegisterReceiver; private void registerJxwRegisterRefreshReceiver() { if (mJxwRegisterReceiver == null) { mJxwRegisterReceiver = new JxwRegisterReceiver(); } IntentFilter filter = new IntentFilter(); filter.addAction(JXW_REGISTER_SUCCESS); registerReceiver(mJxwRegisterReceiver, filter); } public class JxwRegisterReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.e("JxwRegisterReceiver", "onReceive: " + action); if (JXW_REGISTER_SUCCESS.equals(action)) { mMMKV.encode(JXW_REGISTER_SUCCESS, true); mMMKV.encode(CommonConfig.UIUI_ACTIVATION_KEY, ActivationUtil.getInstance().ACTIVATED_KEY); initSocketClient(); startLoop(); } } } private Disposable mDisposable; private void dispose() { if (mDisposable != null && !mDisposable.isDisposed()) { mDisposable.dispose(); mDisposable = null; } } private void startLoop() { if (mDisposable != null && !mDisposable.isDisposed()) { mDisposable.dispose(); mDisposable = null; } mDisposable = Observable.interval(30, TimeUnit.SECONDS) .subscribe(new Consumer() { @Override public void accept(Long s) throws Exception { Log.d(TAG, "startLoop accept: " + s); Log.i(TAG, "心跳包检测websocket连接状态"); if (!ActivationUtil.getInstance().isActivation()) { dispose(); } //每隔一定的时间,对长连接进行一次心跳检测 if (Utils.isScreenOn(SocketService.this)) { if (mJWebSocketClient != null) { if (mJWebSocketClient.isOpen()) { Log.i(TAG, "websocket已连接"); sendPingMsg(); } else if (mJWebSocketClient.isClosed()) { Log.i(TAG, "websocket重连中"); reconnectWs(); } } else { //如果client已为空,重新初始化连接 initSocketClient(); } } else { Log.i(TAG, "websocket息屏不重连"); } } }); } /** * 初始化websocket连接 */ private void initSocketClient() { URI uri = URI.create(BuildConfig.WEBSOCKET_URL + "?sn=" + RemoteManager.getInstance().getSerial()); mJWebSocketClient = new JWebSocketClient(uri) { @Override public void onMessage(String message) { Log.i(TAG, "onMessage: 收到服务器发来的消息:" + message); } @Override public void onOpen(ServerHandshake handshakedata) { super.onOpen(handshakedata); Log.i(TAG, "onOpen: websocket连接成功"); sendPingMsg(); } @Override public void onClose(int code, String reason, boolean remote) { super.onClose(code, reason, remote); Log.e(TAG, "onClose: websocket连接关闭:" + reason); mJWebSocketClient = null; } @Override public void onError(Exception ex) { super.onError(ex); Log.e(TAG, "onError: websocket连接错误:" + ex.getMessage()); mJWebSocketClient = null; } }; connect(); } /** * 连接websocket */ private void connect() { try { //connectBlocking多出一个等待操作,会先连接再发送,否则未连接发送会报错 Log.i(TAG, "connect: websocket连接中"); mJWebSocketClient.connectBlocking(); } catch (Exception e) { Log.i(TAG, "connect: " + e.getMessage()); } } /** * 开启重连 */ private void reconnectWs() { Log.e(TAG, "reconnectWs: "); try { Log.i(TAG, "reconnectWs: 开启重连"); mJWebSocketClient.reconnectBlocking(); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 断开连接 */ private void closeConnect() { Log.e(TAG, "closeConnect: "); try { if (null != mJWebSocketClient) { mJWebSocketClient.close(); } } catch (Exception e) { e.printStackTrace(); } finally { mJWebSocketClient = null; } } /** * 发送消息 */ public void sendPingMsg() { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("sn", RemoteManager.getInstance().getSerial()); jsonObject.addProperty("type", "ping"); if (null != mJWebSocketClient) { Log.i(TAG, "sendPingMsg: 发送的消息:" + jsonObject.toString()); mJWebSocketClient.send(jsonObject.toString()); } } public void sendMsgScreen() { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("sn", RemoteManager.getInstance().getSerial()); if (Utils.isScreenOn(SocketService.this)) { jsonObject.addProperty("type", "device_open_screen"); } else { jsonObject.addProperty("type", "device_close_screen"); //熄屏状态 } if (null != mJWebSocketClient) { Log.i(TAG, "sendMsgScreen: 发送的消息" + jsonObject.toString()); try { mJWebSocketClient.send(jsonObject.toString()); } catch (Exception e) { Log.i(TAG, "sendMsgScreen: sendMsg Exception: " + e.getLocalizedMessage()); } } else { Log.i(TAG, "sendMsgScreen: 未连接"); initSocketClient(); } } }