version:
fix: update:在线状态移到桌面,更换二维码
This commit is contained in:
@@ -40,6 +40,7 @@ import com.uiui.zyos.fragment.user.UserFragment;
|
||||
import com.uiui.zyos.jxw.JxwPackageConfig;
|
||||
import com.uiui.zyos.manager.AmapManager;
|
||||
import com.uiui.zyos.manager.RemoteManager;
|
||||
import com.uiui.zyos.service.SocketService;
|
||||
import com.uiui.zyos.utils.ApkUtils;
|
||||
import com.uiui.zyos.utils.OpenApkUtils;
|
||||
import com.uiui.zyos.utils.Utils;
|
||||
@@ -193,6 +194,12 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
|
||||
// } catch (Exception e) {
|
||||
// Log.e(TAG, "openPackageWithArgs: " + e.getMessage());
|
||||
// }
|
||||
Intent intent = new Intent(MainActivity.this, SocketService.class);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
startForegroundService(intent);
|
||||
} else {
|
||||
startService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
398
app/src/main/java/com/uiui/zyos/service/SocketService.java
Normal file
398
app/src/main/java/com/uiui/zyos/service/SocketService.java
Normal file
@@ -0,0 +1,398 @@
|
||||
package com.uiui.zyos.service;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
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.uiui.zyos.BuildConfig;
|
||||
import com.uiui.zyos.R;
|
||||
import com.uiui.zyos.activity.main.MainActivity;
|
||||
import com.uiui.zyos.manager.RemoteManager;
|
||||
import com.uiui.zyos.utils.ActivationUtil;
|
||||
import com.uiui.zyos.utils.ServiceAliveUtils;
|
||||
import com.uiui.zyos.utils.Utils;
|
||||
import com.uiui.zyos.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
|
||||
* <p>
|
||||
* 【有道云笔记】学生项目-设备端websocket对接.md
|
||||
* https://note.youdao.com/s/Ea0tebj8
|
||||
* <p>
|
||||
* 【有道云笔记】学生项目-管理端websocket对接.md
|
||||
* https://note.youdao.com/s/MazEq49Q
|
||||
* <p>
|
||||
* 老人在线websocket重构了,按照这个重新对接,跟之前售后差不多是一样的。
|
||||
* <p>
|
||||
* 1.设备未激活 不链接websocket 形成不了关联,设备激活后,才链接websocket
|
||||
* 2.已激活的设备,设备若已链接websocket,用户确认绑定后,断开websocket 等待5秒 再重新链接websocket 以刷新用户关联
|
||||
* 3.设备用户解除绑定后,断开websocket 等待5秒 再重新链接websocket 以刷新用户关联
|
||||
*/
|
||||
public class SocketService extends Service implements NetworkUtils.OnNetworkStatusChangedListener {
|
||||
private final static String TAG = "JWebSocketClientService";
|
||||
|
||||
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();
|
||||
|
||||
if (ActivationUtil.isActivation(SocketService.this)) {
|
||||
//初始化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);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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<Long>() {
|
||||
@Override
|
||||
public void accept(Long s) throws Exception {
|
||||
Log.d(TAG, "startLoop accept: " + s);
|
||||
Log.i(TAG, "心跳包检测websocket连接状态");
|
||||
if (!ActivationUtil.isActivation(SocketService.this)) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
37
app/src/main/java/com/uiui/zyos/utils/ServiceAliveUtils.java
Normal file
37
app/src/main/java/com/uiui/zyos/utils/ServiceAliveUtils.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.uiui.zyos.utils;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ServiceAliveUtils {
|
||||
public static boolean isServiceAlive(Context context, String className) {
|
||||
boolean isServiceRunning = false;
|
||||
ActivityManager manager =
|
||||
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
if (manager == null) {
|
||||
return false;
|
||||
}
|
||||
List<ActivityManager.RunningServiceInfo> serviceInfos = manager.getRunningServices(Integer.MAX_VALUE);
|
||||
List<String> serviceClass = serviceInfos.stream().map(new Function<ActivityManager.RunningServiceInfo, String>() {
|
||||
@Override
|
||||
public String apply(ActivityManager.RunningServiceInfo runningServiceInfo) {
|
||||
return runningServiceInfo.service.getClassName();
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
// for (ActivityManager.RunningServiceInfo service : serviceInfos) {
|
||||
// if (className.equals(service.service.getClassName())) {
|
||||
// isServiceRunning = true;
|
||||
// }
|
||||
// }
|
||||
if (serviceClass.contains(className)) {
|
||||
isServiceRunning = true;
|
||||
}
|
||||
Log.e("ServiceAliveUtils", className + " isServiceAlice: " + isServiceRunning);
|
||||
return isServiceRunning;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.uiui.zyos.websocket;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.java_websocket.client.WebSocketClient;
|
||||
import org.java_websocket.drafts.Draft_6455;
|
||||
import org.java_websocket.handshake.ServerHandshake;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
public class JWebSocketClient extends WebSocketClient {
|
||||
public JWebSocketClient(URI serverUri) {
|
||||
super(serverUri, new Draft_6455());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(ServerHandshake handshakedata) {
|
||||
Log.i("JWebSocketClient", "onOpen()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
Log.i("JWebSocketClient", "onMessage()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(int code, String reason, boolean remote) {
|
||||
Log.i("JWebSocketClient", "onClose():" + reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception ex) {
|
||||
Log.i("JWebSocketClient", "onError():" + ex.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user