Commit e0a99c4a authored by gaoyingxiang's avatar gaoyingxiang

新增socket

parent 653082d6
......@@ -7,3 +7,4 @@ include ':wheelview'
include ':pickerview'
include ':dialog'
include ':websocket'
apply plugin: 'com.android.library'
apply plugin: "com.whl.gradle-publish-plugin"
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 27
defaultConfig {
minSdkVersion 15
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
group 'com.qmai.android.sdk.websocket'
version '2.0.5.11-SNAPSHOT'
gradlePublish {
sourceJarEnabled = true
javaDocEnabled = false
signEnabled = false
releaseRepository {
url = "https://hub.zmcms.cn/repository/maven-releases/"
userName = "wanglei1"
password = "woshiwanglei123"
}
snapshotRepository {
url = "https://hub.zmcms.cn/repository/maven-snapshots/"
userName = "wanglei1"
password = "woshiwanglei123"
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
// implementation 'com.squareup.okhttp3:okhttp:3.9.0'
implementation "com.squareup.okhttp3:okhttp:3.13.1"
implementation 'io.reactivex.rxjava2:rxjava:2.1.5'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'com.google.code.gson:gson:2.8.2'
api 'org.litepal.guolindev:core:3.2.3'
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
package com.zhimai.websocket;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.zhimai.websocket.test", appContext.getPackageName());
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zhimai.websocket">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application>
<activity android:name=".activity.WebsocketMainActivity"></activity>
</application>
</manifest>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<!--
Define the database name of your application.
By default each database name should be end with .db.
If you didn't name your database end with .db,
LitePal would plus the suffix automatically for you.
For example:
<dbname value="demo" />
-->
<dbname value="sllibrary" />
<!--
Define the version of your database. Each time you want
to upgrade your database, the version tag would helps.
Modify the models you defined in the mapping tag, and just
make the version value plus one, the upgrade of database
will be processed automatically without concern.
For example:
<version value="1" />
-->
<version value="2" />
<!--
Define your models in the list with mapping tag, LitePal will
create tables for each mapping class. The supported fields
defined in models will be mapped into columns.
For example:
<list>
<mapping class="com.test.model.Reader" />
<mapping class="com.test.model.Magazine" />
</list>
-->
<list>
<mapping class="com.zhimai.websocket.bean.MessageSqlBean" />
<mapping class="com.zhimai.websocket.bean.SocketOrderInfoBean"/>
</list>
<!--
Define where the .db file should be. "internal" means the .db file
will be stored in the database folder of internal storage which no
one can access. "external" means the .db file will be stored in the
path to the directory on the primary external storage device where
the application can place persistent files it owns which everyone
can access. "internal" will act as default.
For example:
<storage value="external" />
-->
</litepal>
package com.zhimai.websocket;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
public final class Config {
protected long reconnectInterval = 1;
protected TimeUnit reconnectIntervalTimeUnit = TimeUnit.SECONDS;
protected boolean showLog = false;
protected String logTag = "RxWebSocket";
protected OkHttpClient client = new OkHttpClient();
protected SSLSocketFactory sslSocketFactory;
protected X509TrustManager trustManager;
private Config() {
}
public static final class Builder {
private Config config;
public Builder() {
config = new Config();
}
/**
* set your client
*
* @param client
*/
public Builder setClient(OkHttpClient client) {
config.client = client;
return this;
}
/**
* wss support
*
* @param sslSocketFactory
* @param trustManager
*/
public Builder setSSLSocketFactory(SSLSocketFactory sslSocketFactory, X509TrustManager trustManager) {
config.sslSocketFactory = sslSocketFactory;
config.trustManager = trustManager;
return this;
}
/**
* set reconnect interval
*
* @param Interval reconncet interval
* @param timeUnit unit
* @return
*/
public Builder setReconnectInterval(long Interval, TimeUnit timeUnit) {
config.reconnectInterval = Interval;
config.reconnectIntervalTimeUnit = timeUnit;
return this;
}
public Builder setShowLog(boolean showLog) {
config.showLog = showLog;
return this;
}
public Builder setShowLog(boolean showLog, String logTag) {
config.showLog = showLog;
config.logTag = logTag;
return this;
}
public Config build() {
return config;
}
}
}
package com.zhimai.websocket;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import okio.ByteString;
public final class RxWebSocket {
public static void setConfig(Config config) {
RxWebSocketUtil instance = RxWebSocketUtil.getInstance();
instance.setShowLog(config.showLog, config.logTag);
instance.setClient(config.client);
instance.setReconnectInterval(config.reconnectInterval, config.reconnectIntervalTimeUnit);
if (config.sslSocketFactory != null && config.trustManager != null) {
instance.setSSLSocketFactory(config.sslSocketFactory, config.trustManager);
}
}
/**
* default timeout: 30 days
* <p>
* 若忽略小米平板,请调用这个方法
* </p>
*/
public static Observable<WebSocketInfo> get(String url) {
return RxWebSocketUtil.getInstance().getWebSocketInfo(url);
}
/**
* @param url ws://127.0.0.1:8080/websocket
* @param timeout The WebSocket will be reconnected after the specified time interval is not "onMessage",
* <p>
* 在指定时间间隔后没有收到消息就会重连WebSocket,为了适配小米平板,因为小米平板断网后,不会发送错误通知
* @param timeUnit unit
* @return
*/
public static Observable<WebSocketInfo> get(String url, long timeout, TimeUnit timeUnit) {
return RxWebSocketUtil.getInstance().getWebSocketInfo(url, timeout, timeUnit);
}
/**
* 如果url的WebSocket已经打开,可以直接调用这个发送消息.
*
* @param url
* @param msg
*/
public static void send(String url, String msg) {
RxWebSocketUtil.getInstance().send(url, msg);
}
/**
* 如果url的WebSocket已经打开,可以直接调用这个发送消息.
*
* @param url
* @param byteString
*/
public static void send(String url, ByteString byteString) {
RxWebSocketUtil.getInstance().send(url, byteString);
}
/**
* 不用关心url 的WebSocket是否打开,可以直接发送
*
* @param url
* @param msg
*/
public static void asyncSend(String url, String msg) {
RxWebSocketUtil.getInstance().asyncSend(url, msg);
}
/**
* 不用关心url 的WebSocket是否打开,可以直接发送
*
* @param url
* @param byteString
*/
public static void asyncSend(String url, ByteString byteString) {
RxWebSocketUtil.getInstance().asyncSend(url, byteString);
}
}
package com.zhimai.websocket;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class SSLHelper {
public static class SSLParams {
public SSLSocketFactory sSLSocketFactory;
public X509TrustManager trustManager;
}
/**
* @param certificates
* @param bksFile
* @param password
* @return
*/
public static SSLParams getSslSocketFactory(InputStream[] certificates, InputStream bksFile, String password) {
SSLParams sslParams = new SSLParams();
try {
TrustManager[] trustManagers = prepareTrustManager(certificates);
KeyManager[] keyManagers = prepareKeyManager(bksFile, password);
SSLContext sslContext = SSLContext.getInstance("TLS");
X509TrustManager trustManager = null;
if (trustManagers != null) {
trustManager = new MyTrustManager(chooseTrustManager(trustManagers));
} else {
trustManager = new UnSafeTrustManager();
}
sslContext.init(keyManagers, new TrustManager[]{trustManager}, null);
sslParams.sSLSocketFactory = sslContext.getSocketFactory();
sslParams.trustManager = trustManager;
return sslParams;
} catch (Exception e) {
throw new AssertionError(e);
}
}
private class UnSafeHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
private static class UnSafeTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
private static TrustManager[] prepareTrustManager(InputStream... certificates) {
if (certificates == null || certificates.length <= 0) return null;
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
int index = 0;
for (InputStream certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
try {
if (certificate != null)
certificate.close();
} catch (IOException e)
{
}
}
TrustManagerFactory trustManagerFactory = null;
trustManagerFactory = TrustManagerFactory.
getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
return trustManagers;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static KeyManager[] prepareKeyManager(InputStream bksFile, String password) {
try {
if (bksFile == null || password == null) return null;
KeyStore clientKeyStore = KeyStore.getInstance("BKS");
clientKeyStore.load(bksFile, password.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, password.toCharArray());
return keyManagerFactory.getKeyManagers();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
for (TrustManager trustManager : trustManagers) {
if (trustManager instanceof X509TrustManager) {
return (X509TrustManager) trustManager;
}
}
return null;
}
private static class MyTrustManager implements X509TrustManager {
private X509TrustManager defaultTrustManager;
private X509TrustManager localTrustManager;
public MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException {
TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
var4.init((KeyStore) null);
defaultTrustManager = chooseTrustManager(var4.getTrustManagers());
this.localTrustManager = localTrustManager;
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
try {
defaultTrustManager.checkServerTrusted(chain, authType);
} catch (CertificateException ce) {
localTrustManager.checkServerTrusted(chain, authType);
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}
package com.zhimai.websocket;
import androidx.annotation.CallSuper;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import okhttp3.WebSocket;
import okio.ByteString;
@Deprecated
public abstract class WebSocketConsumer implements Consumer<WebSocketInfo> {
@CallSuper
@Override
public void accept(WebSocketInfo webSocketInfo) throws Exception {
if (webSocketInfo.isOnOpen()) {
onOpen(webSocketInfo.getWebSocket());
} else if (webSocketInfo.getString() != null) {
onMessage(webSocketInfo.getString());
} else if (webSocketInfo.getByteString() != null) {
onMessage(webSocketInfo.getByteString());
}
}
public abstract void onOpen(@NonNull WebSocket webSocket);
public abstract void onMessage(@NonNull String text);
public abstract void onMessage(@NonNull ByteString bytes);
}
package com.zhimai.websocket;
import androidx.annotation.Nullable;
import okhttp3.WebSocket;
import okio.ByteString;
public class WebSocketInfo {
private WebSocket mWebSocket;
private String mString;
private ByteString mByteString;
private boolean onOpen;
private boolean onReconnect;
private WebSocketInfo() {
}
WebSocketInfo(WebSocket webSocket, boolean onOpen) {
mWebSocket = webSocket;
this.onOpen = onOpen;
}
WebSocketInfo(WebSocket webSocket, String mString) {
mWebSocket = webSocket;
this.mString = mString;
}
WebSocketInfo(WebSocket webSocket, ByteString byteString) {
mWebSocket = webSocket;
mByteString = byteString;
}
static WebSocketInfo createReconnect() {
WebSocketInfo socketInfo = new WebSocketInfo();
socketInfo.onReconnect = true;
return socketInfo;
}
public WebSocket getWebSocket() {
return mWebSocket;
}
public void setWebSocket(WebSocket webSocket) {
mWebSocket = webSocket;
}
@Nullable
public String getString() {
return mString;
}
public void setString(String string) {
this.mString = string;
}
@Nullable
public ByteString getByteString() {
return mByteString;
}
public void setByteString(ByteString byteString) {
mByteString = byteString;
}
public boolean isOnOpen() {
return onOpen;
}
public boolean isOnReconnect() {
return onReconnect;
}
}
package com.zhimai.websocket;
import io.reactivex.Observer;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import okhttp3.WebSocket;
import okio.ByteString;
public abstract class WebSocketSubscriber implements Observer<WebSocketInfo> {
private boolean hasOpened;
protected Disposable disposable;
@Override
public final void onNext(@NonNull WebSocketInfo webSocketInfo) {
if (webSocketInfo.isOnOpen()) {
hasOpened = true;
onOpen(webSocketInfo.getWebSocket());
} else if (webSocketInfo.getString() != null) {
onMessage(webSocketInfo.getString());
} else if (webSocketInfo.getByteString() != null) {
onMessage(webSocketInfo.getByteString());
} else if (webSocketInfo.isOnReconnect()) {
onReconnect();
}
}
/**
* Callback when the WebSocket is opened
*
* @param webSocket
*/
protected void onOpen(@NonNull WebSocket webSocket) {
}
protected void onMessage(@NonNull String text) {
}
protected void onMessage(@NonNull ByteString byteString) {
}
protected void onCatchMsg(String errorMsg){
}
/**
* Callback when the WebSocket is reconnecting
*/
protected void onReconnect() {
}
protected void onClose() {
}
@Override
public final void onSubscribe(Disposable disposable) {
this.disposable = disposable;
}
public final void dispose() {
if (disposable != null) {
disposable.dispose();
}
}
@Override
public final void onComplete() {
if (hasOpened) {
onClose();
}
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
}
package com.zhimai.websocket;
import android.annotation.SuppressLint;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
public abstract class WebSocketSubscriber2<T> extends WebSocketSubscriber {
private static final Gson GSON = new Gson();
protected Type type;
public WebSocketSubscriber2() {
analysisType();
}
private void analysisType() {
Type superclass = getClass().getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("No generics found!");
}
ParameterizedType type = (ParameterizedType) superclass;
this.type = type.getActualTypeArguments()[0];
}
@SuppressLint("CheckResult")
@Override
@CallSuper
protected void onMessage(@NonNull String text) {
Observable.just(text)
.map(new Function<String, T>() {
@Override
public T apply(String s) throws Exception {
try {
return GSON.fromJson(s, type);
} catch (JsonSyntaxException e) {
return GSON.fromJson(GSON.fromJson(s, String.class), type);
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<T>() {
@Override
public void accept(T t) throws Exception {
onMessage(t);
}
});
}
protected abstract void onMessage(T t);
}
package com.zhimai.websocket.activity;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.zhimai.websocket.R;
import com.zhimai.websocket.listener.QueueMessageBackListener;
import com.zhimai.websocket.listener.SocketMessageBackListener;
import com.zhimai.websocket.util.MsgWebSocketUtil;
/**
* 这里只是启动socket的示例,也可以放全局或者其它地方启动
*/
public class WebsocketMainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_websocket);
//开启消息长连接 websocket
// MsgWebSocketUtil
// .getInstance()
// .showLog(true)//是否打印日志
// .setUrl("")//socket链接地址
// .setDeviceName("")//设备号
//// .setPingRate(5000)//socket ping频率 默认5000
//// .setPingData("")//socket ping内容 默认 "{\"type\":\"ping\",\"data\":\"\"}"
// .useQueue(true)//是否开启 队列
// //不开启队列时,消息回调
// .setSocketMessageListener(new SocketMessageBackListener() {
// @Override
// public void recieveMessage(String message) {
//
// }
// })
// //开启队列 消息回调
// //消费完消息 注意:调用 QueueMessageService.getInstance().consumMessage(); 否则 队列服务不会主动下放消息
// .setQueueMessageListener(new QueueMessageBackListener() {
// @Override
// public void reciever(String message) {
//
// }
// })
// .initSocket();
}
}
package com.zhimai.websocket.bean;
/**
* Explain:socket 2.0 外侧数据 结构
* Created on 2021/6/4.
*
* @author zhangshenglong
*/
public class CommonMsgData {
int storeId;
String clientUid;
String tag;
String id;
public int getStoreId() {
return storeId;
}
public void setStoreId(int storeId) {
this.storeId = storeId;
}
public String getClientUid() {
return clientUid;
}
public void setClientUid(String clientUid) {
this.clientUid = clientUid;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
package com.zhimai.websocket.bean;
import org.litepal.annotation.Column;
import org.litepal.crud.LitePalSupport;
/**
* Explain:
* Created on 2020/10/30.
*
* @author zhangshenglong
*/
public class MessageSqlBean extends LitePalSupport {
@Column(unique = true)
private String tag;
@Column(defaultValue = "false")
private boolean confirm;
@Column(defaultValue = "false")
private boolean print;
private String content;
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public boolean isConfirm() {
return confirm;
}
public void setConfirm(boolean confirm) {
this.confirm = confirm;
}
public boolean isPrint() {
return print;
}
public void setPrint(boolean print) {
this.print = print;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
package com.zhimai.websocket.bean;
import org.litepal.crud.LitePalSupport;
/**
* <pre>
* author leiwang
* e-mail xxx@xx
* time 2021/07/08
* desc
* version 1.0
* </pre>
*/
public class SocketOrderInfoBean extends LitePalSupport {
public String tag_id;//标记id
public String order_no; //订单no
public String order_info; //订单信息
public int is_print; //是否打印
public int is_voice; //是否播报
public long save_currentTime; //保存的时间戳
public String save_time; //保存时间
public int is_confirm; //是否确认
public String confirm_time; // 确认时间
public int is_upload; //是否上报
public String upload_time; //上报上次
public String socket_receive_time; //socket收到时间
public String order_create_time; //订单创建时间
public String order_print_time; //订单打印时间
public String order_get_time; //订单列表获取时间
}
package com.zhimai.websocket.db;
import android.content.Context;
import com.zhimai.websocket.bean.MessageSqlBean;
import com.zhimai.websocket.util.SpUtils;
import com.zhimai.websocket.util.TimeUtils;
import org.litepal.LitePal;
import org.litepal.crud.callback.FindMultiCallback;
import java.util.List;
/**
* Explain:
* Created on 2020/10/30.
*
* @author zhangshenglong
*/
public class MessageDBManager {
/**
* 查询是否存在消息记录
*/
public static boolean isRecieverMessage(String tag) {
List<MessageSqlBean> lsPrintHistory = LitePal.where("tag=?", tag).find(MessageSqlBean.class);
if (lsPrintHistory == null || lsPrintHistory.size() == 0) {
return false;
} else {
return true;
}
}
/**
* 写入记录
*/
public static void addMessage(String tag) {
MessageSqlBean messageSqlBean = new MessageSqlBean();
messageSqlBean.setTag(tag);
messageSqlBean.save();
}
public static void addMessage(String tag, String content) {
MessageSqlBean messageSqlBean = new MessageSqlBean();
messageSqlBean.setTag(tag);
messageSqlBean.setContent(content);
messageSqlBean.save();
}
/**
* 如果数据量超过一定数额,删除历史数据
* 可在每次启动的时候调用
*/
public static void checkHistoryCount(final int maxNum) {
List<MessageSqlBean> lsPrintHistory = LitePal.findAll(MessageSqlBean.class);
if (lsPrintHistory.size() > 2000) {
LitePal.deleteAll(MessageSqlBean.class);
}
}
/**
* 建议初始化litepal时调用此方法
* 隔天删除 历史数据
* 使用本地存储 当天年月日
*/
public static void deleteYesterdayAllHistory(Context context) {
//获取当天时间 年月日
String todyTime = TimeUtils.getTodayTimeStr();
//获取存储时间 年月日
String myTime = SpUtils.getInstance(context).getMyTime();
//比对日期,如果不一致,初始化时 删除所有记录
if (!todyTime.equals(myTime)) {
LitePal.deleteAll(MessageSqlBean.class);
SpUtils.getInstance(context).setMyTime(todyTime);
}
}
}
package com.zhimai.websocket.http;
public interface CallBackListener {
void error(String error);
void fail(String message);
void success(String content);
}
package com.zhimai.websocket.http;
import android.os.Looper;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
public class CallbackToMainThread implements Callback {
private MCallback mCallback = null;
private Call mCall = null;
private IOException mIOException = null;
private Response mStringResponse = null;
/**
* @param callback 这里是请求结果的回调,其回调方法将会在UI线程内执行
*/
public CallbackToMainThread(MCallback callback) {
mCallback = callback;
}
/**
* 此处new android.os.Handler(Looper.getMainLooper()).post(runnableFailureUI)是将失败通过UI线程返回
*/
@Override
public void onFailure(Call call, IOException e) {
mCall = call;
mIOException = e;
new android.os.Handler(Looper.getMainLooper()).post(runnableFailureUI);
}
/**
* 这里会根据主线程内Callback的getTClassName实现来获取想要得到的数据类型,然后去做类型转化
*/
@Override
public void onResponse(Call call, Response response) {
mCall = call;
mStringResponse = response;
new android.os.Handler(Looper.getMainLooper()).post(runnableSuccessUI);
}
Runnable runnableFailureUI = new Runnable() {
@Override
public void run() {
mCallback.onFailure(mCall, mIOException);
}
};
Runnable runnableSuccessUI = new Runnable() {
@Override
public void run() {
try {
if (mStringResponse != null) {
mCallback.onResponse(mCall, mStringResponse);
}
} catch (IOException e) {
mCallback.onFailure(mCall, e);
}
}
};
/**
* 此处接口将会在UI线程内实现
* 成功失败都将会通过这里面的方法返回给UI线程
*/
public interface MCallback {
void onFailure(Call call, IOException e);
void onResponse(Call call, Response response) throws IOException;
}
}
package com.zhimai.websocket.http;//package com.slzhang.update.http;
//
//
//import com.slzhang.update.util.Logger;
//
//import okhttp3.logging.HttpLoggingInterceptor;
//
//public class HttpLogger implements HttpLoggingInterceptor.Logger {
// @Override
// public void log(String message) {
// Logger.e("-----------------",message);
// }
//
//}
package com.zhimai.websocket.http;//package com.slzhang.update.http;
//
//import com.tsy.sdk.myokhttp.MyOkHttp;
//
//import java.util.ArrayList;
//import java.util.HashMap;
//import java.util.List;
//import java.util.concurrent.TimeUnit;
//
//import okhttp3.Cookie;
//import okhttp3.CookieJar;
//import okhttp3.HttpUrl;
//import okhttp3.OkHttpClient;
//import okhttp3.logging.HttpLoggingInterceptor;
//
//public class HttpUtil {
// public static MyOkHttp mMyOkhttp;
// public static String headkey="Authorization";
// public static String headvalue="";
//
// public static MyOkHttp getInstance() {
// if (mMyOkhttp == null) {
// HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(new HttpLogger());//创建拦截对象
// logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//这一句一定要记得写,否则没有数据输出
// OkHttpClient okHttpClient = new OkHttpClient.Builder()
//
//
// .cookieJar(new CookieJar() {
//
// private final HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>();
//
// @Override
// public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
//
// cookieStore.put(url, cookies);
//
// }
//
// @Override
// public List<Cookie> loadForRequest(HttpUrl url) {
//
// List<Cookie> cookies = cookieStore.get(url);
//
// return cookies != null ? cookies : new ArrayList<Cookie>();
// }
// })
// .connectTimeout(10000L, TimeUnit.MILLISECONDS)
// .readTimeout(10000L, TimeUnit.MILLISECONDS)
// .addInterceptor(logInterceptor) //设置打印拦截日志
//// .addInterceptor(new LogInterceptor()) //自定义的拦截日志,拦截简单东西用,后面会有介绍/////下载打印日志的话,打印内容会超
// //其他配置
// .build();
// mMyOkhttp = new MyOkHttp(okHttpClient);
// }
// return mMyOkhttp;
// }
//
// public static void setHead(String token_type,String access_token){
// headvalue=token_type+" "+access_token;
// }
//}
package com.zhimai.websocket.http;//package com.slzhang.update.http;
//
//import com.tsy.sdk.myokhttp.MyOkHttp;
//import com.tsy.sdk.myokhttp.builder.GetBuilder;
//import com.tsy.sdk.myokhttp.builder.PostBuilder;
//
///**
// * 这个供收银接口使用,因为请求头不一样
// */
//public class HttpUtil2 {
// private static HttpUtil2 httpUtil2;
// public static MyOkHttp mMyOkhttp;
//
// private HttpUtil2() {
// }
//
// public static HttpUtil2 getInstance() {
// if (httpUtil2 == null) {
// httpUtil2 = new HttpUtil2();
// mMyOkhttp = HttpUtil.getInstance();
// }
// return httpUtil2;
// }
//
// public GetBuilder get() {
// return mMyOkhttp.get()
// .addHeader("Accept", "application/json, text/plain, */*")
// .addHeader("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2")
// .addHeader("QM-STORE-AUTH", "undefined")
// .addHeader("X-CSRF-TOKEN", "{{csrf_token()}}")
// .addHeader("Connection", "keep-alive")
// .addHeader("Accept", "*/*; v=1.0")
//// .addHeader("Referer", MyApplication.INAPI_BASE_RUL_HEAD)
//// .addHeader("Qm-From", "android")
// .addHeader("Qm-From-Type", "cy")
//// .addHeader("Qm-Account-Token", Constant.Token)
// .addHeader("Qm-From", "android" );
//
// }
//
// public PostBuilder post() {
// return mMyOkhttp.post()
// .addHeader("Accept", "application/json, text/plain, */*")
// .addHeader("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2")
// .addHeader("QM-STORE-AUTH", "undefined")
// .addHeader("X-CSRF-TOKEN", "{{csrf_token()}}")
// .addHeader("Connection", "keep-alive")
// .addHeader("Accept", "*/*; v=1.0")
//// .addHeader("Referer", MyApplication.INAPI_BASE_RUL_HEAD)
//// .addHeader("Qm-From", "android")
// .addHeader("Qm-From-Type", "cy")
//// .addHeader("Qm-Account-Token", Constant.Token)
// .addHeader("Qm-From", "android" );
//
// }
//
//}
package com.zhimai.websocket.http;
import com.zhimai.websocket.util.Logger;
import java.io.IOException;
import java.nio.charset.Charset;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
public class NetworkIntercepter implements Interceptor {
private static final String TAG = "*---------------*";
@Override
public Response intercept(Chain chain) {
long start = System.currentTimeMillis();
Response response=null;
String responseBody = null;
String responseCode = null;
String url = null;
String requestBody = null;
try {
Request request = chain.request();
url = request.method()+" "+request.url().toString();
requestBody = getRequestBody(request);
response = chain.proceed(request);
responseBody = response.body().string();
responseCode = String.valueOf(response.code());
MediaType mediaType = response.body().contentType();
response = response.newBuilder().body(ResponseBody.create(mediaType,responseBody)).build();
}
catch (Exception e){
Logger.e(TAG,e.getMessage());
}
finally {
long end = System.currentTimeMillis();
String duration = String.valueOf(end - start);
// Logger.e(TAG,("responseTime= {}, requestUrl= {}, params={}, responseCode= {}, result= {}",
// duration, url,requestBody,responseCode,responseBody);
Logger.e(TAG,"responseTime="+duration);
Logger.e(TAG,"requestUrl="+url);
Logger.e(TAG,"params="+requestBody);
Logger.e(TAG,"responseCode="+responseCode);
Logger.e(TAG,"result="+responseBody);
}
return response;
}
private String getRequestBody(Request request) {
String requestContent = "";
if (request == null) {
return requestContent;
}
RequestBody requestBody = request.body();
if (requestBody == null) {
return requestContent;
}
try {
Buffer buffer = new Buffer();
requestBody.writeTo(buffer);
Charset charset = Charset.forName("utf-8");
requestContent = buffer.readString(charset);
} catch (IOException e) {
e.printStackTrace();
}
return requestContent;
}
}
package com.zhimai.websocket.http;
import java.io.IOException;
import java.net.UnknownHostException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class RetryIntercepter implements Interceptor {
public int maxRetryCount;
private int count = 0;
public RetryIntercepter(int maxRetryCount) {
this.maxRetryCount = maxRetryCount;
}
@Override
public Response intercept(Chain chain) throws IOException {
return retry(chain);
}
public Response retry(Chain chain) throws IOException {
Response response = null;
Request request = chain.request();
try {
response = chain.proceed(request);
while (!response.isSuccessful() && count < maxRetryCount) {
count++;
response = retry(chain);
}
}
catch( UnknownHostException ignored){
throw ignored;
}
catch (Exception e){
while (count < maxRetryCount){
count++;
response = retry(chain);
}
}
if (response==null){
throw new IOException("");
}
return response;
}
}
package com.zhimai.websocket.listener;
/**
* 消费消息 监听
* 配合队列使用
*/
public interface ConsumeMessageListener {
//消息处理后回调此接口,销毁队列第一个消息,然后队列消息回调 会自动发下一个消息
void consumeMessage();
}
package com.zhimai.websocket.listener;
/**
* 队列取消息监听
*/
public interface MessageQueueServiceListner {
void getMessage(String message);
}
package com.zhimai.websocket.listener;
/**
* 队列消息回调 监听
*/
public interface QueueMessageBackListener {
void reciever(String message);
}
package com.zhimai.websocket.listener;
public interface SocketConnectListener {
//已连接
void connected();
//断连
void disconnect();
//关闭,暂时没写关闭方法,所以这个方法一般不会被调用
void closed();
}
package com.zhimai.websocket.listener;
public interface SocketConnectListener2 extends SocketConnectListener {
//
void ping(boolean status);
}
package com.zhimai.websocket.listener;
/**
* socket消息接收 监听
*/
public interface SocketMessageBackListener {
void recieveMessage(String message);
}
package com.zhimai.websocket.listener;
/**
* @author: 高英祥
* @github:
* @time: 2021/7/9 15:12
* @desc:
* @doc:
*/
public interface SocketTimerMessageListener {
void timerMessage();
}
package com.zhimai.websocket.listener;
import com.zhimai.websocket.WebSocketSubscriber;
import okhttp3.WebSocket;
import okio.ByteString;
public interface WebSocketSubscriberListener {
void onClose() ;
void onMessage( String text);
void onMessage( ByteString byteString) ;
void onOpen( WebSocket webSocket);
void onReconnect();
void onError(Throwable e);
}
package com.zhimai.websocket.queue;
import com.zhimai.websocket.util.Logger;
import java.util.LinkedList;
public class MessageQueue {
private static final String TAG = "---QueueMessageService---";
private static MessageQueue printMessageQueue;
private static LinkedList<String> list = new LinkedList();
private MessageQueue(){}
public static MessageQueue getInstance(){
if(printMessageQueue==null){
printMessageQueue=new MessageQueue();
}
return printMessageQueue;
}
//进队
public void enQueue(String o) {
Logger.e(TAG,"-*-*-*-队列尾部插入消息:"+o);
list.addLast(o);
}
//出队
public Object deQueue() {
if (!list.isEmpty()) {
String deletestr=list.removeFirst();
Logger.e(TAG,"-*-*-*-队列移出消息:"+deletestr);
return deletestr;
}
return "队列为空";
}
//添加消息到头部(比较优先的消息可以调用此方法)
public void enQueueHead(String o){
Logger.e(TAG,"-*-*-*-队列头部插入消息:"+o);
list.add(0,o);
}
//判断队列是否为空
public boolean QueueEmpty() {
return list.isEmpty();
}
//获取队列长度
public int QueueLength() {
return list.size();
}
//查看队首元素
public String QueuePeek() {
return list.getFirst();
}
//销毁队列
public void clear() {
list.clear();
}
}
package com.zhimai.websocket.queue;
import com.zhimai.websocket.listener.MessageQueueServiceListner;
import com.zhimai.websocket.util.Logger;
import com.zhimai.websocket.util.RxTimerUtil;
import com.zhimai.websocket.util.SysCode;
/**
* 队列取消息服务
*/
public class QueueMessageService {
private static final String TAG = "---QueueMessageService---";
private static QueueMessageService queueMessageService;
private boolean isPlay = false;
private int waiteTime=0;//锁住的等待时间,加一个保护,等待时间过长,直接释放锁
private int interval = 1000;
public void setInterval(int interval) {
this.interval = interval;
}
private QueueMessageService() {
}
public static QueueMessageService getInstance() {
if (queueMessageService == null) {
queueMessageService = new QueueMessageService();
}
return queueMessageService;
}
public void startPrintService(final MessageQueueServiceListner messageQueueServiceListner) {
RxTimerUtil.cancel(SysCode.RX_TIMER_TYPE.PRINT);
RxTimerUtil.interval(SysCode.RX_TIMER_TYPE.PRINT, interval, new RxTimerUtil.IRxNext() {
@Override
public void doNext(long number) {
if (isPlay) {
Logger.e(TAG,"-------正在消费消息-------");
if(waiteTime>10){
Logger.e(TAG,"-------锁定超过10S,自动解锁-------");
consumMessage();
}else{
waiteTime++;
}
return;
}
waiteTime=0;
Logger.e(TAG,"Queue.length="+MessageQueue.getInstance().QueueLength());
//如果播报队列不为空,则开始播报
if (!MessageQueue.getInstance().QueueEmpty()) {
//通过接口下放消息
if (messageQueueServiceListner != null) {
isPlay = true;
String message = MessageQueue.getInstance().QueuePeek();
Logger.e(TAG,"||||||||||-队列下放消息:"+message);
messageQueueServiceListner.getMessage(message);
//成功下放消息后,队列第一条数据出栈
MessageQueue.getInstance().deQueue();
} else {
Logger.e(TAG, "messageQueueServiceListner==null");
}
}
}
});
}
/**
* 消费完一条消息后,调用此方法
* 注:调用后 服务继续下放消息
*/
public void consumMessage() {
//第一条数据出栈
// MessageQueue.getInstance().deQueue();//根据需要,下放消息时 该消息出栈
//重置状态,允许再次下放消息
isPlay = false;
}
}
package com.zhimai.websocket.util;
import android.util.Log;
/**
* Created by efan on 2017/4/13.
*/
public class Logger {
public static boolean LOG_ENABLE = true;
public static void i(String tag, String msg){
if (LOG_ENABLE){
Log.i(tag, msg);
}
}
public static void v(String tag, String msg){
if (LOG_ENABLE){
Log.v(tag, msg);
}
}
public static void d(String tag, String msg){
if (LOG_ENABLE){
Log.d(tag, msg);
}
}
public static void w(String tag, String msg){
if (LOG_ENABLE){
Log.w(tag, msg);
}
}
public static void e(String tag, String msg){
if (LOG_ENABLE){
Log.e(tag, msg);
}
}
}
package com.zhimai.websocket.util;
import android.content.Context;
import android.net.ConnectivityManager;
/**
* Explain:
* Created on 2020/9/25.
*
* @author zhangshenglong
*/
public class NetWorkUtils {
public static boolean isOnline(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm == null) {
return false;
}
if (cm.getActiveNetworkInfo() == null) {
return false;
}
return cm.getActiveNetworkInfo().isAvailable();
}
public static boolean isOffline(Context context) {
return false==isOnline(context);
}
}
package com.zhimai.websocket.util;
import android.util.Log;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
/**
* 隔时请求刷新
*/
public class RxTimerUtil {
private static final String TAG = "RxTimerUtil";
private static Disposable mDisposableTime;
private static Disposable mDisposableSocket;
private static Disposable mDisposablepPrint;
/**
* milliseconds毫秒后执行next操作
*
* @param milliseconds
* @param next
*/
// public static void timer(long milliseconds, final IRxNext next) {
// Observable.timer(milliseconds, TimeUnit.MILLISECONDS)
// .observeOn(AndroidSchedulers.mainThread())
// .subscribe(new Observer<Long>() {
// @Override
// public void onSubscribe(@NonNull Disposable disposable) {
// mDisposableTime = disposable;
// }
//
// @Override
// public void onNext(@NonNull Long number) {
// if (next != null) {
// next.doNext(number);
// }
// }
//
// @Override
// public void onError(@NonNull Throwable e) {
// //取消订阅
// cancel();
// }
//
// @Override
// public void onComplete() {
// //取消订阅
// cancel();
// }
// });
// }
/**
* 每隔milliseconds毫秒后执行next操作
*
* @param milliseconds
* @param next
*/
public static void interval(final int which, long milliseconds, final IRxNext next) {
Observable.interval(milliseconds, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
// .subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(@NonNull Disposable disposable) {
switch (which) {
case SysCode.RX_TIMER_TYPE.TIME:
mDisposableTime = disposable;
break;
case SysCode.RX_TIMER_TYPE.SOCKET:
mDisposableSocket = disposable;
break;
case SysCode.RX_TIMER_TYPE.PRINT:
mDisposablepPrint = disposable;
break;
}
}
@Override
public void onNext(@NonNull Long number) {
if (next != null) {
// Logger.e("************",Thread.currentThread().getName());
next.doNext(number);
}
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
}
});
}
/**
* 取消订阅
*/
public static void cancel(int which) {
switch (which) {
case SysCode.RX_TIMER_TYPE.TIME:
if (mDisposableTime != null && !mDisposableTime.isDisposed()) {
mDisposableTime.dispose();
Log.e(TAG, "====定时器取消mDisposableTime======");
}
break;
case SysCode.RX_TIMER_TYPE.SOCKET:
if (mDisposableSocket != null && !mDisposableSocket.isDisposed()) {
mDisposableSocket.dispose();
Log.e(TAG, "====定时器取消mDisposableSocket======");
}
break;
case SysCode.RX_TIMER_TYPE.PRINT:
if (mDisposablepPrint != null && !mDisposablepPrint.isDisposed()) {
mDisposablepPrint.dispose();
Log.e(TAG, "====定时器取消mDisposablepPrint======");
}
break;
}
}
public interface IRxNext {
void doNext(long number);
}
}
package com.zhimai.websocket.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
/***
* 需要提前初始化
* */
public class SpUtils {
private static SpUtils spUtils;
private static final String TAG = "SpUtils";
private SharedPreferences.Editor editor;
private SharedPreferences sharedPreferences;
private final String timeKey = "time_today";
public static SpUtils getInstance(Context context) {
if (spUtils == null) {
spUtils = new SpUtils(context);
}
return spUtils;
}
public SpUtils(Context context) {
if (sharedPreferences == null) {
sharedPreferences = context.getSharedPreferences("qmzs", Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
}
}
public String getMyTime() {
return sharedPreferences.getString(timeKey, "");
}
public void setMyTime(String time) {
put(timeKey, time);
}
public boolean getBoolean(String key, boolean defaultValue) {
return sharedPreferences.getBoolean(key, defaultValue);
}
public void clearAll() {
editor.clear().commit();
}
// public void clearAllWithOutUsrPwd() {
//
// String userName = getString(ParamsUtils.USERNAME, "");
// String pwd = getString(ParamsUtils.PWD, "");
// String deviceId = getString(ParamsUtils.DEVICEID, "");
// editor.clear().commit();
// put(ParamsUtils.USERNAME, userName);
// put(ParamsUtils.PWD, pwd);
// put(ParamsUtils.DEVICEID, deviceId);
// put(ParamsUtils.IS_LOGIN, false);
//
// put(ParamsUtils.MULTIID, 0);
// put(ParamsUtils.ORG_ID, 0);
// }
private SpUtils() {
}
public String getString(String key, String defaultValue) {
return sharedPreferences.getString(key, defaultValue);
}
public int getInt(String key, int defaultValue) {
return sharedPreferences.getInt(key, defaultValue);
}
public Object get(String key, Object defaultValue) {
if (defaultValue instanceof Integer) {
return (int) sharedPreferences.getInt(key, (int) defaultValue);
} else if (defaultValue instanceof String) {
return (String) (sharedPreferences.getString(key, (String) defaultValue));
} else if (defaultValue instanceof Float) {
return (Float) sharedPreferences.getFloat(key, (Float) defaultValue);
} else if (defaultValue instanceof Boolean) {
return (Boolean) sharedPreferences.getBoolean(key, (Boolean) defaultValue);
}
return null;
}
public void put(String key, Object value) {
if (value instanceof Integer) {
editor.putInt(key, (Integer) value);
} else if (value instanceof String) {
editor.putString(key, (String) value);
} else if (value instanceof Float) {
editor.putFloat(key, (Float) value);
} else if (value instanceof Boolean) {
editor.putBoolean(key, (Boolean) value);
}
editor.commit();
}
}
package com.zhimai.websocket.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* 字符串操作工具类
*/
public class StringUtil {
/**
* 判断字符串是否为空
* @param str
* @return
*/
public static boolean isNull(String str) {
if (str == null) {
return true;
} else if (str.equals("")) {
return true;
}else if(str.equals("null")){
return true;
} else {
return false;
}
}
/**
* 判断字符串是否为非空
* @param str
* @return
*/
public static boolean isNotNull(String str){
return !isNull(str);
}
/**
* 字符串超过制定长度 截取字符串,拼接后缀
* @param str
* @param maxlength
* @param endWith
* @return
*/
public String cutStringWithEnd(String str,int maxlength,String endWith){
if (isNull(str)) {
return "";
}
if(str.length()>maxlength){
String newStr=str.substring(0,maxlength);
return newStr+endWith;
}else{
return str;
}
}
public static String getNotNullNumber(String numStr){
if(isNull(numStr)){
return "0";
}else {
return numStr;
}
}
/**
* MD5加密
*/
public static String md5(String string) {
if (isNull(string)) {
return "";
}
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
byte[] bytes = md5.digest(string.getBytes());
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
String temp = Integer.toHexString(b & 0xff);
if (temp.length() == 1) {
temp = "0" + temp;
}
result.append(temp);
}
return result.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
/**
* 获取字符串占用空间长度 字符一个 汉字 两个
* @param str
* @return
*/
public static int getStrSpace(String str) {
if (str == null) {
return 0;
}
return str.replaceAll("[^\\x00-\\xff]", "**").length();
}
/**
* 获取 截取指定宽度 的 index
*/
public static int getSubIndexByWidth(String content,int width){
int index=content.length()-1;
while(getStrSpace(content.substring(0,index))>width){
index--;
}
return index;
}
}
package com.zhimai.websocket.util;
/**
* 常量
*/
public class SysCode {
/**
* 定时器类型
*/
public interface RX_TIMER_TYPE {
int TIME = 0;
int SOCKET = 1;
int PRINT = 2;
}
}
package com.zhimai.websocket.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* Explain:
* Created on 2020/10/30.
*
* @author zhangshenglong
*/
public class TimeUtils {
private static SimpleDateFormat simpleFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static SimpleDateFormat simpleFormatter_day = new SimpleDateFormat("yyyy-MM-dd");
public static String convertTimeStampToDate(String timeStamp) {
Long time = new Long(timeStamp);
time = time * 1000;
return simpleFormatter.format(time);
}
public static String convertTimeStampToDate(int timeStamp) {
Long time = new Long(timeStamp);
time = time * 1000;
return simpleFormatter.format(time);
}
public static String getTodayTimeStr() {
Date curDate = new Date(System.currentTimeMillis());
String str = simpleFormatter_day.format(curDate);
return str;
}
/**
* 获得指定日期的前一天
*
* @param specifiedDay
* @return
* @throws Exception
*/
public static String getLastDay(String specifiedDay) {
//SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
Date date = null;
try {
date = new SimpleDateFormat("yy-MM-dd").parse(specifiedDay);
} catch (ParseException e) {
e.printStackTrace();
}
c.setTime(date);
int day = c.get(Calendar.DATE);
c.set(Calendar.DATE, day - 1);
String dayBefore = new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
return dayBefore;
}
/**
* 获得指定日期的后一天
*
* @param specifiedDay
* @return
*/
public static String getNextDay(String specifiedDay) {
Calendar c = Calendar.getInstance();
Date date = null;
try {
date = new SimpleDateFormat("yy-MM-dd").parse(specifiedDay);
} catch (ParseException e) {
e.printStackTrace();
}
c.setTime(date);
int day = c.get(Calendar.DATE);
c.set(Calendar.DATE, day + 1);
String dayAfter = new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
return dayAfter;
}
public static String formateTime2(String time) {
if (time.length() == 1)
return 0 + time;
return time;
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.WebsocketMainActivity">
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<resources>
<string name="app_name">websocket</string>
</resources>
package com.zhimai.websocket;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment