Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
W
Widget
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Android Widget
Widget
Commits
e0a99c4a
Commit
e0a99c4a
authored
Jul 09, 2021
by
gaoyingxiang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新增socket
parent
653082d6
Changes
50
Hide whitespace changes
Inline
Side-by-side
Showing
50 changed files
with
4187 additions
and
0 deletions
+4187
-0
settings.gradle
settings.gradle
+1
-0
.gitignore
websocket/.gitignore
+1
-0
build.gradle
websocket/build.gradle
+60
-0
proguard-rules.pro
websocket/proguard-rules.pro
+21
-0
ExampleInstrumentedTest.java
...st/java/com/zhimai/websocket/ExampleInstrumentedTest.java
+26
-0
AndroidManifest.xml
websocket/src/main/AndroidManifest.xml
+10
-0
litepal.xml
websocket/src/main/assets/litepal.xml
+50
-0
Config.java
websocket/src/main/java/com/zhimai/websocket/Config.java
+81
-0
RxWebSocket.java
...ocket/src/main/java/com/zhimai/websocket/RxWebSocket.java
+82
-0
RxWebSocketUtil.java
...t/src/main/java/com/zhimai/websocket/RxWebSocketUtil.java
+395
-0
SSLHelper.java
websocket/src/main/java/com/zhimai/websocket/SSLHelper.java
+172
-0
WebSocketConsumer.java
...src/main/java/com/zhimai/websocket/WebSocketConsumer.java
+28
-0
WebSocketInfo.java
...ket/src/main/java/com/zhimai/websocket/WebSocketInfo.java
+72
-0
WebSocketSubscriber.java
...c/main/java/com/zhimai/websocket/WebSocketSubscriber.java
+75
-0
WebSocketSubscriber2.java
.../main/java/com/zhimai/websocket/WebSocketSubscriber2.java
+65
-0
WebsocketMainActivity.java
.../com/zhimai/websocket/activity/WebsocketMainActivity.java
+48
-0
CommonMsgData.java
...rc/main/java/com/zhimai/websocket/bean/CommonMsgData.java
+46
-0
MessageSqlBean.java
...c/main/java/com/zhimai/websocket/bean/MessageSqlBean.java
+53
-0
SocketOrderInfoBean.java
...n/java/com/zhimai/websocket/bean/SocketOrderInfoBean.java
+32
-0
MessageDBManager.java
...c/main/java/com/zhimai/websocket/db/MessageDBManager.java
+76
-0
CallBackListener.java
...main/java/com/zhimai/websocket/http/CallBackListener.java
+7
-0
CallbackToMainThread.java
.../java/com/zhimai/websocket/http/CallbackToMainThread.java
+74
-0
HttpLogger.java
...t/src/main/java/com/zhimai/websocket/http/HttpLogger.java
+14
-0
HttpUtil.java
...ket/src/main/java/com/zhimai/websocket/http/HttpUtil.java
+61
-0
HttpUtil2.java
...et/src/main/java/com/zhimai/websocket/http/HttpUtil2.java
+57
-0
MyOkHttpUtils.java
...rc/main/java/com/zhimai/websocket/http/MyOkHttpUtils.java
+323
-0
NetworkIntercepter.java
...in/java/com/zhimai/websocket/http/NetworkIntercepter.java
+75
-0
RetryIntercepter.java
...main/java/com/zhimai/websocket/http/RetryIntercepter.java
+47
-0
ConsumeMessageListener.java
...com/zhimai/websocket/listener/ConsumeMessageListener.java
+10
-0
MessageQueueServiceListner.java
...zhimai/websocket/listener/MessageQueueServiceListner.java
+8
-0
QueueMessageBackListener.java
...m/zhimai/websocket/listener/QueueMessageBackListener.java
+8
-0
SocketConnectListener.java
.../com/zhimai/websocket/listener/SocketConnectListener.java
+10
-0
SocketConnectListener2.java
...com/zhimai/websocket/listener/SocketConnectListener2.java
+6
-0
SocketMessageBackListener.java
.../zhimai/websocket/listener/SocketMessageBackListener.java
+8
-0
SocketTimerMessageListener.java
...zhimai/websocket/listener/SocketTimerMessageListener.java
+12
-0
WebSocketSubscriberListener.java
...himai/websocket/listener/WebSocketSubscriberListener.java
+25
-0
MessageQueue.java
...rc/main/java/com/zhimai/websocket/queue/MessageQueue.java
+62
-0
QueueMessageService.java
.../java/com/zhimai/websocket/queue/QueueMessageService.java
+78
-0
BaseMsgWebSocket.java
...main/java/com/zhimai/websocket/util/BaseMsgWebSocket.java
+559
-0
Logger.java
...ocket/src/main/java/com/zhimai/websocket/util/Logger.java
+39
-0
MsgWebSocketUtil.java
...main/java/com/zhimai/websocket/util/MsgWebSocketUtil.java
+759
-0
NetWorkUtils.java
...src/main/java/com/zhimai/websocket/util/NetWorkUtils.java
+27
-0
RxTimerUtil.java
.../src/main/java/com/zhimai/websocket/util/RxTimerUtil.java
+137
-0
SpUtils.java
...cket/src/main/java/com/zhimai/websocket/util/SpUtils.java
+140
-0
StringUtil.java
...t/src/main/java/com/zhimai/websocket/util/StringUtil.java
+113
-0
SysCode.java
...cket/src/main/java/com/zhimai/websocket/util/SysCode.java
+17
-0
TimeUtils.java
...et/src/main/java/com/zhimai/websocket/util/TimeUtils.java
+88
-0
activity_main_websocket.xml
websocket/src/main/res/layout/activity_main_websocket.xml
+9
-0
strings.xml
websocket/src/main/res/values/strings.xml
+3
-0
ExampleUnitTest.java
...t/src/test/java/com/zhimai/websocket/ExampleUnitTest.java
+17
-0
No files found.
settings.gradle
View file @
e0a99c4a
...
...
@@ -7,3 +7,4 @@ include ':wheelview'
include
':pickerview'
include
':dialog'
include
':websocket'
websocket/.gitignore
0 → 100644
View file @
e0a99c4a
/build
websocket/build.gradle
0 → 100644
View file @
e0a99c4a
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'
}
websocket/proguard-rules.pro
0 → 100644
View file @
e0a99c4a
# 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
websocket/src/androidTest/java/com/zhimai/websocket/ExampleInstrumentedTest.java
0 → 100644
View file @
e0a99c4a
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
());
}
}
websocket/src/main/AndroidManifest.xml
0 → 100644
View file @
e0a99c4a
<?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
websocket/src/main/assets/litepal.xml
0 → 100644
View file @
e0a99c4a
<?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>
websocket/src/main/java/com/zhimai/websocket/Config.java
0 → 100644
View file @
e0a99c4a
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
;
}
}
}
websocket/src/main/java/com/zhimai/websocket/RxWebSocket.java
0 → 100644
View file @
e0a99c4a
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
);
}
}
websocket/src/main/java/com/zhimai/websocket/RxWebSocketUtil.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
;
import
android.os.SystemClock
;
import
android.util.Log
;
import
java.io.IOException
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeoutException
;
import
javax.net.ssl.SSLSocketFactory
;
import
javax.net.ssl.X509TrustManager
;
import
io.reactivex.Observable
;
import
io.reactivex.ObservableEmitter
;
import
io.reactivex.ObservableOnSubscribe
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.annotations.NonNull
;
import
io.reactivex.disposables.Disposable
;
import
io.reactivex.functions.Action
;
import
io.reactivex.functions.Cancellable
;
import
io.reactivex.functions.Consumer
;
import
io.reactivex.functions.Function
;
import
io.reactivex.functions.Predicate
;
import
io.reactivex.schedulers.Schedulers
;
import
okhttp3.OkHttpClient
;
import
okhttp3.Request
;
import
okhttp3.Response
;
import
okhttp3.WebSocket
;
import
okhttp3.WebSocketListener
;
import
okio.ByteString
;
@Deprecated
public
class
RxWebSocketUtil
{
private
static
RxWebSocketUtil
instance
;
private
OkHttpClient
client
;
private
Map
<
String
,
Observable
<
WebSocketInfo
>>
observableMap
;
private
Map
<
String
,
WebSocket
>
webSocketMap
;
private
boolean
showLog
;
private
String
logTag
=
"RxWebSocket"
;
private
long
interval
=
1
;
private
TimeUnit
reconnectIntervalTimeUnit
=
TimeUnit
.
SECONDS
;
private
RxWebSocketUtil
()
{
try
{
Class
.
forName
(
"okhttp3.OkHttpClient"
);
}
catch
(
ClassNotFoundException
e
)
{
throw
new
RuntimeException
(
"Must be dependency okhttp3 !"
);
}
try
{
Class
.
forName
(
"io.reactivex.Observable"
);
}
catch
(
ClassNotFoundException
e
)
{
throw
new
RuntimeException
(
"Must be dependency rxjava 2.x"
);
}
try
{
Class
.
forName
(
"io.reactivex.android.schedulers.AndroidSchedulers"
);
}
catch
(
ClassNotFoundException
e
)
{
throw
new
RuntimeException
(
"Must be dependency rxandroid 2.x"
);
}
observableMap
=
new
ConcurrentHashMap
<>();
webSocketMap
=
new
ConcurrentHashMap
<>();
client
=
new
OkHttpClient
();
}
/**
* please use {@link RxWebSocket} to instead of it
*
* @return
*/
@Deprecated
public
static
RxWebSocketUtil
getInstance
()
{
if
(
instance
==
null
)
{
synchronized
(
RxWebSocketUtil
.
class
)
{
if
(
instance
==
null
)
{
instance
=
new
RxWebSocketUtil
();
}
}
}
return
instance
;
}
/**
* set your client
*
* @param client
*/
public
void
setClient
(
OkHttpClient
client
)
{
if
(
client
==
null
)
{
throw
new
NullPointerException
(
" Are you kidding me ? client == null"
);
}
this
.
client
=
client
;
}
public
void
setSSLSocketFactory
(
SSLSocketFactory
sslSocketFactory
,
X509TrustManager
trustManager
)
{
client
=
client
.
newBuilder
().
sslSocketFactory
(
sslSocketFactory
,
trustManager
).
build
();
}
public
void
setShowLog
(
boolean
showLog
)
{
this
.
showLog
=
showLog
;
}
public
void
setShowLog
(
boolean
showLog
,
String
logTag
)
{
setShowLog
(
showLog
);
this
.
logTag
=
logTag
;
}
public
void
setReconnectInterval
(
long
interval
,
TimeUnit
timeUnit
)
{
this
.
interval
=
interval
;
this
.
reconnectIntervalTimeUnit
=
timeUnit
;
}
/**
* @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
Observable
<
WebSocketInfo
>
getWebSocketInfo
(
final
String
url
,
final
long
timeout
,
final
TimeUnit
timeUnit
)
{
Observable
<
WebSocketInfo
>
observable
=
observableMap
.
get
(
url
);
if
(
observable
==
null
)
{
observable
=
Observable
.
create
(
new
WebSocketOnSubscribe
(
url
))
//自动重连
.
timeout
(
timeout
,
timeUnit
)
.
retry
(
new
Predicate
<
Throwable
>()
{
@Override
public
boolean
test
(
Throwable
throwable
)
throws
Exception
{
return
throwable
instanceof
IOException
||
throwable
instanceof
TimeoutException
;
}
})
//共享
.
doOnDispose
(
new
Action
()
{
@Override
public
void
run
()
throws
Exception
{
observableMap
.
remove
(
url
);
webSocketMap
.
remove
(
url
);
if
(
showLog
)
{
// Log.d(logTag, "OnDispose");
}
}
})
.
doOnError
(
new
Consumer
<
Throwable
>()
{
@Override
public
void
accept
(
Throwable
throwable
)
throws
Exception
{
if
(
showLog
)
{
// Log.d(logTag, "doOnError");
}
}
})
.
doOnNext
(
new
Consumer
<
WebSocketInfo
>()
{
@Override
public
void
accept
(
WebSocketInfo
webSocketInfo
)
throws
Exception
{
if
(
webSocketInfo
.
isOnOpen
())
{
webSocketMap
.
put
(
url
,
webSocketInfo
.
getWebSocket
());
}
}
})
.
share
()
.
subscribeOn
(
Schedulers
.
io
())
.
observeOn
(
AndroidSchedulers
.
mainThread
());
observableMap
.
put
(
url
,
observable
);
}
else
{
WebSocket
webSocket
=
webSocketMap
.
get
(
url
);
if
(
webSocket
!=
null
)
{
observable
=
observable
.
startWith
(
new
WebSocketInfo
(
webSocket
,
true
));
}
}
return
observable
.
observeOn
(
AndroidSchedulers
.
mainThread
());
}
/**
* default timeout: 30 days
* <p>
* 若忽略小米平板,请调用这个方法
* </p>
*/
public
Observable
<
WebSocketInfo
>
getWebSocketInfo
(
String
url
)
{
return
getWebSocketInfo
(
url
,
30
,
TimeUnit
.
DAYS
);
}
public
Observable
<
String
>
getWebSocketString
(
String
url
)
{
return
getWebSocketInfo
(
url
)
.
filter
(
new
Predicate
<
WebSocketInfo
>()
{
@Override
public
boolean
test
(
@NonNull
WebSocketInfo
webSocketInfo
)
throws
Exception
{
return
webSocketInfo
.
getString
()
!=
null
;
}
})
.
map
(
new
Function
<
WebSocketInfo
,
String
>()
{
@Override
public
String
apply
(
@NonNull
WebSocketInfo
webSocketInfo
)
throws
Exception
{
return
webSocketInfo
.
getString
();
}
});
}
public
Observable
<
ByteString
>
getWebSocketByteString
(
String
url
)
{
return
getWebSocketInfo
(
url
)
.
filter
(
new
Predicate
<
WebSocketInfo
>()
{
@Override
public
boolean
test
(
@NonNull
WebSocketInfo
webSocketInfo
)
throws
Exception
{
return
webSocketInfo
.
getByteString
()
!=
null
;
}
})
.
map
(
new
Function
<
WebSocketInfo
,
ByteString
>()
{
@Override
public
ByteString
apply
(
WebSocketInfo
webSocketInfo
)
throws
Exception
{
return
webSocketInfo
.
getByteString
();
}
});
}
public
Observable
<
WebSocket
>
getWebSocket
(
String
url
)
{
return
getWebSocketInfo
(
url
)
//fix #31
.
filter
(
new
Predicate
<
WebSocketInfo
>()
{
@Override
public
boolean
test
(
WebSocketInfo
webSocketInfo
)
throws
Exception
{
return
webSocketInfo
.
getWebSocket
()
!=
null
;
}
})
.
map
(
new
Function
<
WebSocketInfo
,
WebSocket
>()
{
@Override
public
WebSocket
apply
(
@NonNull
WebSocketInfo
webSocketInfo
)
throws
Exception
{
return
webSocketInfo
.
getWebSocket
();
}
});
}
/**
* 如果url的WebSocket已经打开,可以直接调用这个发送消息.
*
* @param url
* @param msg
*/
public
void
send
(
String
url
,
String
msg
)
{
WebSocket
webSocket
=
webSocketMap
.
get
(
url
);
if
(
webSocket
!=
null
)
{
webSocket
.
send
(
msg
);
}
else
{
throw
new
IllegalStateException
(
"The WebSokcet not open"
);
}
}
/**
* 如果url的WebSocket已经打开,可以直接调用这个发送消息.
*
* @param url
* @param byteString
*/
public
void
send
(
String
url
,
ByteString
byteString
)
{
WebSocket
webSocket
=
webSocketMap
.
get
(
url
);
if
(
webSocket
!=
null
)
{
webSocket
.
send
(
byteString
);
}
else
{
throw
new
IllegalStateException
(
"The WebSokcet not open"
);
}
}
/**
* 不用关心url 的WebSocket是否打开,可以直接发送
*
* @param url
* @param msg
*/
public
void
asyncSend
(
String
url
,
final
String
msg
)
{
getWebSocket
(
url
)
.
take
(
1
)
.
subscribe
(
new
Consumer
<
WebSocket
>()
{
@Override
public
void
accept
(
WebSocket
webSocket
)
throws
Exception
{
webSocket
.
send
(
msg
);
}
});
}
/**
* 不用关心url 的WebSocket是否打开,可以直接发送
*
* @param url
* @param byteString
*/
public
void
asyncSend
(
String
url
,
final
ByteString
byteString
)
{
getWebSocket
(
url
)
.
take
(
1
)
.
subscribe
(
new
Consumer
<
WebSocket
>()
{
@Override
public
void
accept
(
WebSocket
webSocket
)
throws
Exception
{
webSocket
.
send
(
byteString
);
}
});
}
private
Request
getRequest
(
String
url
)
{
return
new
Request
.
Builder
().
get
().
url
(
url
).
build
();
}
private
final
class
WebSocketOnSubscribe
implements
ObservableOnSubscribe
<
WebSocketInfo
>
{
private
String
url
;
private
WebSocket
webSocket
;
public
WebSocketOnSubscribe
(
String
url
)
{
this
.
url
=
url
;
}
@Override
public
void
subscribe
(
@NonNull
ObservableEmitter
<
WebSocketInfo
>
emitter
)
throws
Exception
{
if
(
webSocket
!=
null
)
{
//降低重连频率
if
(!
"main"
.
equals
(
Thread
.
currentThread
().
getName
()))
{
long
ms
=
reconnectIntervalTimeUnit
.
toMillis
(
interval
);
if
(
ms
==
0
)
{
ms
=
1000
;
}
SystemClock
.
sleep
(
ms
);
emitter
.
onNext
(
WebSocketInfo
.
createReconnect
());
}
}
//emitter.onError(new Throwable("test"));
initWebSocket
(
emitter
);
}
private
void
initWebSocket
(
final
ObservableEmitter
<
WebSocketInfo
>
emitter
)
{
webSocket
=
client
.
newWebSocket
(
getRequest
(
url
),
new
WebSocketListener
()
{
@Override
public
void
onOpen
(
final
WebSocket
webSocket
,
Response
response
)
{
if
(
showLog
)
{
Log
.
d
(
logTag
,
url
+
" --> onOpen"
);
}
webSocketMap
.
put
(
url
,
webSocket
);
if
(!
emitter
.
isDisposed
())
{
emitter
.
onNext
(
new
WebSocketInfo
(
webSocket
,
true
));
}
}
@Override
public
void
onMessage
(
WebSocket
webSocket
,
String
text
)
{
// Log.e(logTag, "onMessage1 status= " + emitter.isDisposed());
if
(!
emitter
.
isDisposed
())
{
emitter
.
onNext
(
new
WebSocketInfo
(
webSocket
,
text
));
}
}
@Override
public
void
onMessage
(
WebSocket
webSocket
,
ByteString
bytes
)
{
// Log.e(logTag, "onMessage2 status= " + emitter.isDisposed());
if
(!
emitter
.
isDisposed
())
{
emitter
.
onNext
(
new
WebSocketInfo
(
webSocket
,
bytes
));
}
}
@Override
public
void
onFailure
(
WebSocket
webSocket
,
Throwable
t
,
Response
response
)
{
if
(
showLog
)
{
Log
.
e
(
logTag
,
t
.
toString
()
+
webSocket
.
request
().
url
().
uri
().
getPath
()
+
" status= "
+
emitter
.
isDisposed
());
}
if
(!
emitter
.
isDisposed
())
{
emitter
.
onError
(
t
);
}
}
@Override
public
void
onClosing
(
WebSocket
webSocket
,
int
code
,
String
reason
)
{
webSocket
.
close
(
1000
,
null
);
}
@Override
public
void
onClosed
(
WebSocket
webSocket
,
int
code
,
String
reason
)
{
if
(
showLog
)
{
Log
.
d
(
logTag
,
url
+
" --> onClosed:code= "
+
code
);
}
}
});
emitter
.
setCancellable
(
new
Cancellable
()
{
@Override
public
void
cancel
()
throws
Exception
{
webSocket
.
close
(
3000
,
"close WebSocket"
);
if
(
showLog
)
{
Log
.
d
(
logTag
,
url
+
" --> cancel "
);
}
}
});
}
}
}
websocket/src/main/java/com/zhimai/websocket/SSLHelper.java
0 → 100644
View file @
e0a99c4a
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
];
}
}
}
websocket/src/main/java/com/zhimai/websocket/WebSocketConsumer.java
0 → 100644
View file @
e0a99c4a
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
);
}
websocket/src/main/java/com/zhimai/websocket/WebSocketInfo.java
0 → 100644
View file @
e0a99c4a
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
;
}
}
websocket/src/main/java/com/zhimai/websocket/WebSocketSubscriber.java
0 → 100644
View file @
e0a99c4a
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
();
}
}
websocket/src/main/java/com/zhimai/websocket/WebSocketSubscriber2.java
0 → 100644
View file @
e0a99c4a
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
);
}
websocket/src/main/java/com/zhimai/websocket/activity/WebsocketMainActivity.java
0 → 100644
View file @
e0a99c4a
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();
}
}
websocket/src/main/java/com/zhimai/websocket/bean/CommonMsgData.java
0 → 100644
View file @
e0a99c4a
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
;
}
}
websocket/src/main/java/com/zhimai/websocket/bean/MessageSqlBean.java
0 → 100644
View file @
e0a99c4a
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
;
}
}
websocket/src/main/java/com/zhimai/websocket/bean/SocketOrderInfoBean.java
0 → 100644
View file @
e0a99c4a
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
;
//订单列表获取时间
}
websocket/src/main/java/com/zhimai/websocket/db/MessageDBManager.java
0 → 100644
View file @
e0a99c4a
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
);
}
}
}
websocket/src/main/java/com/zhimai/websocket/http/CallBackListener.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
http
;
public
interface
CallBackListener
{
void
error
(
String
error
);
void
fail
(
String
message
);
void
success
(
String
content
);
}
websocket/src/main/java/com/zhimai/websocket/http/CallbackToMainThread.java
0 → 100644
View file @
e0a99c4a
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
;
}
}
websocket/src/main/java/com/zhimai/websocket/http/HttpLogger.java
0 → 100644
View file @
e0a99c4a
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);
// }
//
//}
websocket/src/main/java/com/zhimai/websocket/http/HttpUtil.java
0 → 100644
View file @
e0a99c4a
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;
// }
//}
websocket/src/main/java/com/zhimai/websocket/http/HttpUtil2.java
0 → 100644
View file @
e0a99c4a
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" );
//
// }
//
//}
websocket/src/main/java/com/zhimai/websocket/http/MyOkHttpUtils.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
http
;
import
android.content.Context
;
import
android.net.ConnectivityManager
;
import
android.net.NetworkInfo
;
import
com.zhimai.websocket.util.Logger
;
import
org.json.JSONObject
;
import
java.io.IOException
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
import
okhttp3.Call
;
import
okhttp3.Callback
;
import
okhttp3.ConnectionPool
;
import
okhttp3.HttpUrl
;
import
okhttp3.OkHttpClient
;
import
okhttp3.Request
;
import
okhttp3.RequestBody
;
import
okhttp3.Response
;
/**
* 新版本okhttp
*/
public
class
MyOkHttpUtils
{
private
static
final
String
TAG
=
"----MyOkHttpUtils----"
;
private
static
MyOkHttpUtils
myOkHttpUtils
;
private
static
final
int
CONNECTION_TIME_OUT
=
2000
;
//连接超时时间
private
static
final
int
SOCKET_TIME_OUT
=
2000
;
//读写超时时间
private
static
final
int
MAX_IDLE_CONNECTIONS
=
30
;
// 空闲连接数
private
static
final
long
KEEP_ALLIVE_TIME
=
60000L
;
//保持连接时间
//1. 创建OkhttpClient 对象
// private static OkHttpClient client=new OkHttpClient.Builder().connectTimeout(10000L, TimeUnit.MILLISECONDS)
// .readTimeout(10000L, TimeUnit.MILLISECONDS).build();
private
OkHttpClient
client
;
public
static
MyOkHttpUtils
getInstance
()
{
if
(
myOkHttpUtils
==
null
)
{
myOkHttpUtils
=
new
MyOkHttpUtils
();
}
return
myOkHttpUtils
;
}
public
MyOkHttpUtils
()
{
// client=new OkHttpClient.Builder().connectTimeout(10000L, TimeUnit.MILLISECONDS)
// .readTimeout(10000L, TimeUnit.MILLISECONDS).build();
// client=new OkHttpClient();
ConnectionPool
connectionPool
=
new
ConnectionPool
(
MAX_IDLE_CONNECTIONS
,
KEEP_ALLIVE_TIME
,
TimeUnit
.
MILLISECONDS
);
this
.
client
=
new
OkHttpClient
()
.
newBuilder
()
.
readTimeout
(
SOCKET_TIME_OUT
,
TimeUnit
.
MILLISECONDS
)
.
writeTimeout
(
SOCKET_TIME_OUT
,
TimeUnit
.
MILLISECONDS
)
.
connectionPool
(
connectionPool
)
.
retryOnConnectionFailure
(
false
)
//自动重连设置为false
.
connectTimeout
(
CONNECTION_TIME_OUT
,
TimeUnit
.
MILLISECONDS
)
.
addInterceptor
(
new
RetryIntercepter
(
2
))
//重试拦截器2次
.
addNetworkInterceptor
(
new
NetworkIntercepter
())
//网络拦截器,统一打印日志---
.
build
();
}
private
void
init
()
{
}
public
void
get
(
String
url
,
Map
<
String
,
String
>
pathParams
,
String
token
,
final
CallBackListener
callBackListener
)
{
HttpUrl
.
Builder
builder
=
HttpUrl
.
parse
(
url
).
newBuilder
();
for
(
String
key
:
pathParams
.
keySet
())
{
builder
.
addQueryParameter
(
key
,
pathParams
.
get
(
key
));
}
//2. 创建请求的Request 对象
Request
request
=
new
Request
.
Builder
()
.
get
()
.
url
(
builder
.
build
().
toString
())
.
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"
,
token
)
.
addHeader
(
"Qm-seller-Token"
,
token
)
// .addHeader("Qm-Account-Token", Constant.Token)
.
addHeader
(
"Qm-From"
,
"android"
)
.
addHeader
(
"Accept-Encoding"
,
"identity"
)
//服务器发的数据 压缩了,需要解压
.
build
();
//3. 在Okhttp中创建Call 对象,将request和Client进行绑定
//4. 执行Call对象(call 是interface 实际执行的是RealCall)中的`execute`方法
// try (Response response = client.newCall(request).execute()) {
// return response.body().string();
// }
Call
call
=
client
.
newCall
(
request
);
// try {
//
// String result2=call.execute().body().string();
// Logger.e(TAG,"返回数据:"+result2);
// }catch (IOException e){
// Logger.e(TAG,"返回数据异常:"+e.getMessage());
// }
call
.
enqueue
(
new
Callback
()
{
@Override
public
void
onFailure
(
Call
call
,
IOException
e
)
{
if
(
callBackListener
!=
null
)
{
callBackListener
.
error
(
e
.
getMessage
());
}
}
@Override
public
void
onResponse
(
Call
call
,
Response
response
)
{
if
(
callBackListener
!=
null
)
{
try
{
String
result
=
response
.
body
().
string
();
Logger
.
e
(
TAG
,
"返回数据:"
+
result
);
JSONObject
jsonObject
=
new
JSONObject
(
result
);
if
(
jsonObject
.
optBoolean
(
"status"
,
false
))
{
if
(
callBackListener
!=
null
)
{
callBackListener
.
success
(
jsonObject
.
optString
(
"data"
));
}
}
else
{
if
(
callBackListener
!=
null
)
{
callBackListener
.
fail
(
jsonObject
.
optString
(
"message"
));
}
}
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"返回数据异常:"
+
e
.
getMessage
());
if
(
callBackListener
!=
null
)
{
callBackListener
.
fail
(
"返回数据异常"
);
}
}
}
}
});
}
public
void
post
(
String
url
,
Map
<
String
,
String
>
pathParams
,
String
token
,
String
baseUrl
,
final
CallBackListener
callBackListener
)
{
RequestBody
body
=
setRequestBody
(
pathParams
);
post
(
url
,
body
,
token
,
baseUrl
,
callBackListener
);
}
public
void
post
(
String
url
,
RequestBody
body
,
String
token
,
String
baseUrl
,
final
CallBackListener
callBackListener
)
{
Logger
.
e
(
TAG
,
"请求数据: url = "
+
url
+
" ;; baseUrl = "
+
baseUrl
);
//1构造RequestBody
// RequestBody body = setRequestBody(pathParams);
//2. 创建请求的Request 对象
Request
request
=
new
Request
.
Builder
()
.
post
(
body
)
.
url
(
url
)
//Accept-Encoding: identity
// .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", UrlUtils.BASICKURL)
// .addHeader("Referer", baseUrl)
// .addHeader("Qm-From-Type", "cy")
// .addHeader("Qm-Account-Token", token)///----新机构中心不用这个 用 qm_seller_token
// .addHeader("Qm-seller-Token", token)//新机构中心 token
// .addHeader("Qm-From", "android")
.
addHeader
(
"Accept"
,
"*/*; v=1.0"
)
.
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
(
"Accept-Encoding"
,
"identity"
)
//服务器发的数据 压缩了,需要解压
.
addHeader
(
"QM-STORE-AUTH"
,
"undefined"
)
.
addHeader
(
"X-CSRF-TOKEN"
,
"{{csrf_token()}}"
)
.
addHeader
(
"Connection"
,
"keep-alive"
)
.
addHeader
(
"Referer"
,
baseUrl
)
.
addHeader
(
"Cookie"
,
"qm_account_token="
+
token
)
.
addHeader
(
"content-type"
,
"application/json"
)
.
addHeader
(
"User-Agent"
,
"wechatdevtools appservice port/62739"
)
.
addHeader
(
"Qm-From-Type"
,
"retail"
)
.
addHeader
(
"Authorization"
,
"Bearer $CommParamsRegister.instance.getToken()"
)
.
addHeader
(
"Qm-Account-Token"
,
token
)
.
addHeader
(
"Qm-seller-Token"
,
token
)
.
addHeader
(
"Qm-From"
,
"android"
)
.
build
();
Call
call
=
client
.
newCall
(
request
);
// try {
//
// String result2=call.execute().body().string();
// Logger.e(TAG,"返回数据:"+result2);
// }catch (IOException e){
// Logger.e(TAG,"返回数据异常:"+e.getMessage());
// }
call
.
enqueue
(
new
CallbackToMainThread
(
new
CallbackToMainThread
.
MCallback
()
{
@Override
public
void
onFailure
(
Call
call
,
IOException
e
)
{
if
(
callBackListener
!=
null
)
{
callBackListener
.
error
(
e
.
getMessage
());
}
}
@Override
public
void
onResponse
(
Call
call
,
Response
response
)
{
if
(
callBackListener
!=
null
)
{
try
{
String
result
=
response
.
body
().
string
();
Logger
.
e
(
TAG
,
"返回数据:"
+
result
);
JSONObject
jsonObject
=
new
JSONObject
(
result
);
if
(
jsonObject
.
optBoolean
(
"status"
,
false
))
{
if
(
callBackListener
!=
null
)
{
callBackListener
.
success
(
jsonObject
.
optString
(
"data"
));
}
}
else
{
if
(
callBackListener
!=
null
)
{
callBackListener
.
fail
(
jsonObject
.
optString
(
"message"
));
}
}
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"返回数据异常:"
+
e
.
getMessage
());
if
(
callBackListener
!=
null
)
{
callBackListener
.
fail
(
"返回数据异常:"
+
e
.
getMessage
());
}
}
}
}
}));
// call.enqueue(new Callback() {
// @Override
// public void onFailure(Call call, IOException e) {
// if (callBackListener != null) {
// callBackListener.error(e.getMessage());
// }
// }
//
// @Override
// public void onResponse(Call call, Response response) {
// if (callBackListener != null) {
// try {
// String result = response.body().string();
// Logger.e(TAG, "返回数据:" + result);
// JSONObject jsonObject = new JSONObject(result);
// if (jsonObject.optBoolean("status", false)) {
// if (callBackListener != null) {
// callBackListener.success(jsonObject.optString("data"));
// }
// } else {
// if (callBackListener != null) {
// callBackListener.fail(jsonObject.optString("message"));
// }
// }
//
// } catch (Exception e) {
// Logger.e(TAG, "返回数据异常:" + e.getMessage());
// if (callBackListener != null) {
// callBackListener.fail("返回数据异常");
// }
// }
//
// }
// }
// });
}
/**
* post的请求参数,构造RequestBody
*
* @param BodyParams
* @return
*/
private
RequestBody
setRequestBody
(
Map
<
String
,
String
>
BodyParams
)
{
RequestBody
body
=
null
;
okhttp3
.
FormBody
.
Builder
formEncodingBuilder
=
new
okhttp3
.
FormBody
.
Builder
();
if
(
BodyParams
!=
null
)
{
Iterator
<
String
>
iterator
=
BodyParams
.
keySet
().
iterator
();
String
key
=
""
;
while
(
iterator
.
hasNext
())
{
key
=
iterator
.
next
().
toString
();
formEncodingBuilder
.
add
(
key
,
BodyParams
.
get
(
key
));
// Log.d("post http", "post_Params==="+key+"===="+BodyParams.get(key));
}
}
body
=
formEncodingBuilder
.
build
();
return
body
;
}
/**
* 判断网络是否可用
*
* @param context
* @return
*/
public
static
boolean
isNetworkAvailable
(
Context
context
)
{
ConnectivityManager
cm
=
(
ConnectivityManager
)
context
.
getSystemService
(
Context
.
CONNECTIVITY_SERVICE
);
if
(
cm
==
null
)
{
}
else
{
//如果仅仅是用来判断网络连接
//则可以使用cm.getActiveNetworkInfo().isAvailable();
NetworkInfo
[]
info
=
cm
.
getAllNetworkInfo
();
if
(
info
!=
null
)
{
for
(
int
i
=
0
;
i
<
info
.
length
;
i
++)
{
if
(
info
[
i
].
getState
()
==
NetworkInfo
.
State
.
CONNECTED
)
{
return
true
;
}
}
}
}
return
false
;
}
}
websocket/src/main/java/com/zhimai/websocket/http/NetworkIntercepter.java
0 → 100644
View file @
e0a99c4a
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
;
}
}
websocket/src/main/java/com/zhimai/websocket/http/RetryIntercepter.java
0 → 100644
View file @
e0a99c4a
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
;
}
}
websocket/src/main/java/com/zhimai/websocket/listener/ConsumeMessageListener.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
listener
;
/**
* 消费消息 监听
* 配合队列使用
*/
public
interface
ConsumeMessageListener
{
//消息处理后回调此接口,销毁队列第一个消息,然后队列消息回调 会自动发下一个消息
void
consumeMessage
();
}
websocket/src/main/java/com/zhimai/websocket/listener/MessageQueueServiceListner.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
listener
;
/**
* 队列取消息监听
*/
public
interface
MessageQueueServiceListner
{
void
getMessage
(
String
message
);
}
websocket/src/main/java/com/zhimai/websocket/listener/QueueMessageBackListener.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
listener
;
/**
* 队列消息回调 监听
*/
public
interface
QueueMessageBackListener
{
void
reciever
(
String
message
);
}
websocket/src/main/java/com/zhimai/websocket/listener/SocketConnectListener.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
listener
;
public
interface
SocketConnectListener
{
//已连接
void
connected
();
//断连
void
disconnect
();
//关闭,暂时没写关闭方法,所以这个方法一般不会被调用
void
closed
();
}
websocket/src/main/java/com/zhimai/websocket/listener/SocketConnectListener2.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
listener
;
public
interface
SocketConnectListener2
extends
SocketConnectListener
{
//
void
ping
(
boolean
status
);
}
websocket/src/main/java/com/zhimai/websocket/listener/SocketMessageBackListener.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
listener
;
/**
* socket消息接收 监听
*/
public
interface
SocketMessageBackListener
{
void
recieveMessage
(
String
message
);
}
websocket/src/main/java/com/zhimai/websocket/listener/SocketTimerMessageListener.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
listener
;
/**
* @author: 高英祥
* @github:
* @time: 2021/7/9 15:12
* @desc:
* @doc:
*/
public
interface
SocketTimerMessageListener
{
void
timerMessage
();
}
websocket/src/main/java/com/zhimai/websocket/listener/WebSocketSubscriberListener.java
0 → 100644
View file @
e0a99c4a
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
);
}
websocket/src/main/java/com/zhimai/websocket/queue/MessageQueue.java
0 → 100644
View file @
e0a99c4a
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
();
}
}
websocket/src/main/java/com/zhimai/websocket/queue/QueueMessageService.java
0 → 100644
View file @
e0a99c4a
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
;
}
}
websocket/src/main/java/com/zhimai/websocket/util/BaseMsgWebSocket.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
util
;
import
android.content.Context
;
import
android.util.Log
;
import
android.widget.Toast
;
import
com.google.gson.Gson
;
import
com.zhimai.websocket.Config
;
import
com.zhimai.websocket.RxWebSocket
;
import
com.zhimai.websocket.RxWebSocketUtil
;
import
com.zhimai.websocket.WebSocketSubscriber
;
import
com.zhimai.websocket.bean.CommonMsgData
;
import
com.zhimai.websocket.db.MessageDBManager
;
import
com.zhimai.websocket.http.CallBackListener
;
import
com.zhimai.websocket.http.MyOkHttpUtils
;
import
com.zhimai.websocket.listener.MessageQueueServiceListner
;
import
com.zhimai.websocket.listener.QueueMessageBackListener
;
import
com.zhimai.websocket.listener.SocketConnectListener
;
import
com.zhimai.websocket.listener.SocketConnectListener2
;
import
com.zhimai.websocket.listener.SocketMessageBackListener
;
import
com.zhimai.websocket.listener.SocketTimerMessageListener
;
import
com.zhimai.websocket.listener.WebSocketSubscriberListener
;
import
com.zhimai.websocket.queue.MessageQueue
;
import
com.zhimai.websocket.queue.QueueMessageService
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
import
org.litepal.LitePal
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
import
io.reactivex.annotations.NonNull
;
import
okhttp3.RequestBody
;
import
okhttp3.WebSocket
;
import
okio.ByteString
;
/**
* @author: 高英祥
* @github:
* @time: 2021/7/9 11:43
* @desc:
* @doc:
*/
public
class
BaseMsgWebSocket
{
private
static
final
String
TAG
=
"---BaseMsgWebSocket----"
;
private
WebSocketSubscriber
webSocketSubscriber
;
/**
* 心跳ping的内容
*/
private
String
pingData
=
""
;
/**
* 心跳Ping的频率
*/
private
int
pingRate
=
5000
;
//ping 频率
private
static
BaseMsgWebSocket
mBaseMsgWebSocket
;
private
WebSocket
mWebSocket
;
private
int
mQueueInterval
=
1000
;
/**
* socket链接状态
*/
private
boolean
isConnected
=
false
;
/**
* socket地址
*/
private
String
webSocketUrl
=
""
;
//通道
private
String
socketWay
=
""
;
/**
* 设备号
* 绑定socket连接时使用,也是推送唯一标识
*/
private
String
DeviceName
=
""
;
/**
* 是否打印日志
*/
private
boolean
isShowLog
=
true
;
/**
* 是否开启队列
*/
private
boolean
useQueue
=
false
;
/**
* 禁用队列时 消息监听
*/
private
SocketMessageBackListener
socketMessageListener
;
/**
* 开启队列时 消息监听
*/
private
QueueMessageBackListener
queueMessageListener
;
/**
* socket连接监听
*/
private
SocketConnectListener
socketConnectListener
;
private
WebSocketSubscriberListener
mWebSocketSubscriberListener
;
/**
* 定时数据消息
*/
private
SocketTimerMessageListener
mSocketTimerMessageListener
;
/**
* 离线时间
* 离线达到一定时间,自动重启socket
*/
private
int
offLineTime
=
0
;
//定时操作
private
boolean
openTimingGetMessage
=
false
;
//是否开启定时获取数据
private
int
getMessageInterval
=
60000
;
// 定时的时间
private
Context
context
;
private
Gson
gson
;
private
BaseMsgWebSocket
()
{
}
private
BaseMsgWebSocket
(
Context
context
)
{
this
.
context
=
context
.
getApplicationContext
();
gson
=
new
Gson
();
}
public
static
BaseMsgWebSocket
getInstance
(
Context
context
)
{
if
(
mBaseMsgWebSocket
==
null
)
{
mBaseMsgWebSocket
=
new
BaseMsgWebSocket
(
context
);
}
return
mBaseMsgWebSocket
;
}
/**
* 初始化数据库,此方法必须在 application 中调用
*/
public
void
initSql
()
{
LitePal
.
initialize
(
context
);
MessageDBManager
.
deleteYesterdayAllHistory
(
context
);
}
/**
* 设置socket地址
*
* @param url
*/
public
BaseMsgWebSocket
setUrl
(
String
url
)
{
webSocketUrl
=
url
;
if
(
StringUtil
.
isNotNull
(
webSocketUrl
))
{
socketWay
=
webSocketUrl
.
substring
(
webSocketUrl
.
lastIndexOf
(
"/"
)
+
1
);
}
return
mBaseMsgWebSocket
;
}
/**
* 设置是否打印日志
*
* @param is_show
*/
public
BaseMsgWebSocket
showLog
(
boolean
is_show
)
{
Logger
.
LOG_ENABLE
=
isShowLog
=
is_show
;
return
mBaseMsgWebSocket
;
}
/**
* 设置设备号
*
* @param device_name 绑定socket时使用
*/
public
BaseMsgWebSocket
setDeviceName
(
String
device_name
)
{
DeviceName
=
device_name
;
return
mBaseMsgWebSocket
;
}
/**
* ping频率
* socket ping的频率
* 默认 5000ms
*
* @param ping_rate
*/
public
BaseMsgWebSocket
setPingRate
(
int
ping_rate
)
{
pingRate
=
ping_rate
;
return
mBaseMsgWebSocket
;
}
/**
* 设置ping内容
* 默认 "{\"type\":\"ping\",\"data\":\"\"}"
* 如有改动可用此方法修改 ping的内容
*
* @param ping_data
*/
public
BaseMsgWebSocket
setPingData
(
String
ping_data
)
{
pingData
=
ping_data
;
return
mBaseMsgWebSocket
;
}
/**
* 是否开启队列
* 若不开启 接收到消息直接下放
*
* @param use_queue
*/
public
BaseMsgWebSocket
useQueue
(
boolean
use_queue
)
{
useQueue
=
use_queue
;
return
mBaseMsgWebSocket
;
}
/**
* socket消息回调
* 不开启队列时,使用此消息监听
*
* @param socketMessageListener_
*/
public
BaseMsgWebSocket
setSocketMessageListener
(
SocketMessageBackListener
socketMessageListener_
)
{
socketMessageListener
=
socketMessageListener_
;
return
mBaseMsgWebSocket
;
}
/**
* queue消息回调
* 开启队列时,使用此消息监听
*
* @param queueMessageListener_
*/
public
BaseMsgWebSocket
setQueueMessageListener
(
QueueMessageBackListener
queueMessageListener_
)
{
queueMessageListener
=
queueMessageListener_
;
return
mBaseMsgWebSocket
;
}
public
BaseMsgWebSocket
setSocketConnectListener
(
SocketConnectListener
socketConnectListener_
)
{
socketConnectListener
=
socketConnectListener_
;
return
mBaseMsgWebSocket
;
}
/**
* 连接socket
* 最后调用此方法
*/
public
void
initSocket
()
{
if
(
StringUtil
.
isNull
(
webSocketUrl
))
{
Logger
.
e
(
TAG
,
"webSocketUrl is null"
);
return
;
}
if
(
StringUtil
.
isNull
(
DeviceName
))
{
Logger
.
e
(
TAG
,
"DeviceName is null"
);
return
;
}
Logger
.
e
(
TAG
,
"初始化socket initSocket()"
);
//是否开启日志
RxWebSocketUtil
.
getInstance
().
setShowLog
(
isShowLog
);
//初始化ping定时器
initPing
();
Config
config
=
new
Config
.
Builder
()
// .setClient(client) //if you want to set your okhttpClient
.
setShowLog
(
isShowLog
,
TAG
)
.
setReconnectInterval
(
2
,
TimeUnit
.
SECONDS
)
//set reconnect interval
// .setSSLSocketFactory(yourSSlSocketFactory, yourX509TrustManager) // wss support
.
build
();
RxWebSocket
.
setConfig
(
config
);
Logger
.
e
(
TAG
,
"开启长连接;;"
+
webSocketUrl
);
// RxWebSocket.get(MyApplication.WEBSOCKET_HOST_AND_PORT)
webSocketSubscriber
=
new
WebSocketSubscriber
()
{
@Override
public
void
onOpen
(
@NonNull
WebSocket
webSocket
)
{
Logger
.
e
(
TAG
,
"onOpen1:"
);
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onOpen
(
webSocket
);
}
mWebSocket
=
webSocket
;
isConnected
=
true
;
if
(
socketConnectListener
!=
null
)
{
socketConnectListener
.
connected
();
}
else
{
Logger
.
e
(
TAG
,
"socketConnectListener==null"
);
}
}
@Override
public
void
onMessage
(
@NonNull
String
text
)
{
Logger
.
e
(
TAG
,
"onMessage;;"
+
text
);
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onMessage
(
text
);
}
else
{
// checkMessage(text);
}
}
@Override
public
void
onMessage
(
@NonNull
ByteString
bytes
)
{
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onMessage
(
bytes
);
}
Logger
.
e
(
TAG
,
bytes
.
toString
());
}
@Override
protected
void
onReconnect
()
{
Logger
.
e
(
TAG
,
"重连"
);
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onReconnect
();
}
isConnected
=
false
;
if
(
socketConnectListener
!=
null
)
{
socketConnectListener
.
disconnect
();
}
else
{
Logger
.
e
(
TAG
,
"socketConnectListener==null"
);
}
}
@Override
protected
void
onClose
()
{
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onClose
();
}
Logger
.
e
(
TAG
,
"关闭"
);
if
(
socketConnectListener
!=
null
)
{
socketConnectListener
.
closed
();
}
else
{
Logger
.
e
(
TAG
,
"socketConnectListener==null"
);
}
}
@Override
public
void
onError
(
Throwable
e
)
{
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onError
(
e
);
}
Logger
.
e
(
TAG
,
"错误:"
+
e
.
getMessage
());
}
};
RxWebSocket
.
get
(
webSocketUrl
)
// RxWebSocket.get("ws://qmapp.dev.zmcms.cn:8282")
//RxLifecycle : https://github.com/dhhAndroid/RxLifecycle
// .compose(RxLifecycle.with(MyApplication.mContext).<WebSocketInfo>bindToLifecycle())//如果需要跟activity生命绑定,防止内存泄漏,可以用这个方法
.
subscribe
(
webSocketSubscriber
);
//如果开启队列,则启动队列消息服务
if
(
useQueue
)
{
QueueMessageService
.
getInstance
().
setInterval
(
mQueueInterval
);
QueueMessageService
.
getInstance
().
startPrintService
(
new
MessageQueueServiceListner
()
{
@Override
public
void
getMessage
(
String
message
)
{
if
(
queueMessageListener
!=
null
)
{
queueMessageListener
.
reciever
(
message
);
}
else
{
Logger
.
e
(
TAG
,
"queueMessageListener==null"
);
}
}
});
}
}
/**
* 处理分发接收到的消息
* 根据接收的消息,进行相应的处理,这里随便写的,要根据自己定的规则进行处理
*/
// private void checkMessage (String message) {
// 这里需要去调整,最好是调整成,任意结构的解析。
// 思路: 1、外部传入一个类型,T ,2、判断的条件是什么?能否传入或者注解。
// try {
// Log.d(TAG, "checkMessage: message= " + message);
// JSONObject jsonObject = new JSONObject(message);
// String type = jsonObject.optString("type");
// switch (type) {
// case "init"://初始化/验证
// sendBind(jsonObject);
// break;
// case "success"://验证成功//2.0有消息的时候,type返回的竟然也是这个 0.o
// //这里优化,如果是通知 有新消息,请求接口后 筛重 再塞队列
// if (StringUtil.isNotNull(jsonObject.optString("new_message"))) {
// if (jsonObject.optString("new_message").equals("true")) {
// getSocketServiceMessage();
// }
// } else {
// Logger.e(TAG, "socket绑定成功");
// }
// break;
// case "error"://验证失败
// Logger.e(TAG, "socket绑定失败");
// break;
// default://其它的消息 下放给调用者 或 直接扔到队列中
// //判断是否存在tag,tag不为空就 通知socket服务端,收到了此消息-----------
// if (StringUtil.isNotNull(jsonObject.optString("tag"))) {
// String tag = jsonObject.optString("tag");
// boolean needConfirm = jsonObject.optBoolean("needConfirm");
// Logger.e(TAG, "发送确认消息数据:needConfirm = " + needConfirm + " 内容:" + getConfirmMessage(tag));
// if (mWebSocket != null && needConfirm) {
// mWebSocket.send(getConfirmMessage(tag));
// }
//
// //数据库 存储消息id,判断数据库是否已有此消息,如果存在 忽略消息,不存在则存储消息,继续下一步--------------------------------
// if (MessageDBManager.isRecieverMessage(tag)) {
// Logger.e(TAG, "------该消息数据库已存在 tag = " + tag);
// return;
// }
// //数据库记录消息id
// MessageDBManager.addMessage(tag);
// }
// //入队
// joinMessageQueue(message);
// break;
// }
// } catch (JSONException e) {
//
// }
// }
/**
* 发送绑定/验证 请求
*/
private
void
sendBind
(
JSONObject
jsonObject
)
{
}
/**
* 入队操作
*/
public
void
joinMessageQueue
(
String
message
){
if
(
useQueue
)
{
//如果开启队列,消息加入队列---------------------------------------------
Logger
.
e
(
TAG
,
"------消息加入队列 "
);
MessageQueue
.
getInstance
().
enQueue
(
message
);
}
else
{
//直接 回调 传消息
if
(
socketMessageListener
!=
null
)
{
socketMessageListener
.
recieveMessage
(
message
);
}
else
{
Logger
.
e
(
TAG
,
"socketMessageListener==null"
);
}
}
}
/**
* 通知服务端 消息收到成功
*
* @param tag
* @return
*/
private
String
getConfirmMessage
(
String
tag
)
{
return
"{\"type\": \"msg-confirm\",\"data\":{\"tag\":\""
+
tag
+
"\"}}"
;
}
/**
* 发送消息方法
*
* @param message
* @return
*/
public
boolean
sendMessage
(
String
message
)
{
if
(!
isConnected
)
{
Logger
.
e
(
TAG
,
"socket已断开"
+
message
);
return
false
;
}
Logger
.
e
(
TAG
,
"sendMessage()被调用"
);
if
(
mWebSocket
!=
null
)
{
Logger
.
e
(
TAG
,
"发送数据:"
+
message
);
mWebSocket
.
send
(
message
);
return
true
;
}
else
{
Logger
.
e
(
TAG
,
"mWebSocket==null"
);
return
false
;
}
}
/**
* 获取socket连接状态
* true:已连接
* false:连接断开 或 未初始化
*
* @return
*/
public
boolean
getConnectStatus
()
{
return
isConnected
;
}
/**
* 开始定时发送心跳
* 这个是监测 连接是否正常的规则,可自定义
*/
private
void
initPing
()
{
RxTimerUtil
.
cancel
(
SysCode
.
RX_TIMER_TYPE
.
SOCKET
);
RxTimerUtil
.
interval
(
SysCode
.
RX_TIMER_TYPE
.
SOCKET
,
pingRate
,
new
RxTimerUtil
.
IRxNext
()
{
@Override
public
void
doNext
(
long
number
)
{
if
(
isConnected
)
{
if
(
mWebSocket
!=
null
)
{
boolean
isPing
=
mWebSocket
.
send
(
pingData
);
if
(
socketConnectListener
!=
null
&&
socketConnectListener
instanceof
SocketConnectListener2
)
{
((
SocketConnectListener2
)
socketConnectListener
).
ping
(
isPing
);
}
if
(
isPing
)
{
offLineTime
=
0
;
}
else
{
offLineTime
++;
}
Logger
.
e
(
TAG
,
isPing
?
(
"ping... 内容:"
+
pingData
)
:
"ping失败..."
);
}
}
else
{
offLineTime
++;
Logger
.
e
(
TAG
,
"Socket中断,停止ping...offLineTime"
+
offLineTime
);
}
if
(
offLineTime
>
10
)
{
//超过10次ping(50S)失败/离线50S 重启socket
destroySocket
();
initSocket
();
}
if
(
context
!=
null
)
{
if
(
NetWorkUtils
.
isOffline
(
context
))
{
Toast
.
makeText
(
context
,
"请检查当前网络"
,
Toast
.
LENGTH_SHORT
).
show
();
}
}
//在ping里面触发 定时消息请求
if
(
openTimingGetMessage
)
{
if
(
number
*
pingRate
%
getMessageInterval
==
0
)
{
//定时拉取服务端打印消息
if
(
mSocketTimerMessageListener
!=
null
){
mSocketTimerMessageListener
.
timerMessage
();
}
}
else
{
Logger
.
e
(
TAG
,
"number = "
+
number
+
" ;; pingRate = "
+
pingRate
+
" ;; getMessageInterval = "
+
getMessageInterval
);
}
}
else
{
Logger
.
e
(
TAG
,
"isSocket2 = "
+
" ;; openTimingGetMessage = "
+
openTimingGetMessage
);
}
}
});
}
public
void
destroySocket
()
{
if
(
webSocketSubscriber
!=
null
)
{
webSocketSubscriber
.
dispose
();
Logger
.
e
(
TAG
,
"socket服务已关闭..."
);
}
RxTimerUtil
.
cancel
(
SysCode
.
RX_TIMER_TYPE
.
SOCKET
);
Logger
.
e
(
TAG
,
"socket心跳已关闭..."
);
}
public
BaseMsgWebSocket
setWebSocketSubscriberListener
(
WebSocketSubscriberListener
mWebSocketSubscriberListener
)
{
this
.
mWebSocketSubscriberListener
=
mWebSocketSubscriberListener
;
return
this
;
}
public
BaseMsgWebSocket
setQueueInterval
(
int
mQueueInterval
)
{
this
.
mQueueInterval
=
mQueueInterval
;
return
this
;
}
public
BaseMsgWebSocket
setSocketTimerMessageListener
(
SocketTimerMessageListener
mSocketTimerMessageListener
)
{
this
.
mSocketTimerMessageListener
=
mSocketTimerMessageListener
;
return
this
;
}
}
websocket/src/main/java/com/zhimai/websocket/util/Logger.java
0 → 100644
View file @
e0a99c4a
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
);
}
}
}
websocket/src/main/java/com/zhimai/websocket/util/MsgWebSocketUtil.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
util
;
import
android.content.Context
;
import
android.text.TextUtils
;
import
android.util.Log
;
import
android.widget.Toast
;
import
com.google.gson.Gson
;
import
com.zhimai.websocket.Config
;
import
com.zhimai.websocket.RxWebSocket
;
import
com.zhimai.websocket.RxWebSocketUtil
;
import
com.zhimai.websocket.WebSocketSubscriber
;
import
com.zhimai.websocket.bean.CommonMsgData
;
import
com.zhimai.websocket.bean.MessageSqlBean
;
import
com.zhimai.websocket.db.MessageDBManager
;
import
com.zhimai.websocket.http.CallBackListener
;
import
com.zhimai.websocket.http.MyOkHttpUtils
;
import
com.zhimai.websocket.listener.MessageQueueServiceListner
;
import
com.zhimai.websocket.listener.QueueMessageBackListener
;
import
com.zhimai.websocket.listener.SocketConnectListener
;
import
com.zhimai.websocket.listener.SocketConnectListener2
;
import
com.zhimai.websocket.listener.SocketMessageBackListener
;
import
com.zhimai.websocket.listener.WebSocketSubscriberListener
;
import
com.zhimai.websocket.queue.MessageQueue
;
import
com.zhimai.websocket.queue.QueueMessageService
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
import
org.litepal.LitePal
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
import
io.reactivex.annotations.NonNull
;
import
okhttp3.RequestBody
;
import
okhttp3.WebSocket
;
import
okio.ByteString
;
/**
* 推送消息websocket通用工具
* 工具调用入口
*/
public
class
MsgWebSocketUtil
{
private
static
final
String
TAG
=
"---MsgWebSocketUtil----"
;
private
WebSocketSubscriber
webSocketSubscriber
;
public
final
static
int
BUILD_TYPE_DEV
=
0
;
public
final
static
int
BUILD_TYPE_SHOP
=
1
;
public
final
static
int
BUILD_TYPE_BETA
=
2
;
public
final
static
int
BUILD_TYPE_RELEASE
=
3
;
private
String
basicUrl
=
"https://inapi.qimai.cn/"
;
//默认正式环境接口
private
String
baseUrl
=
basicUrl
+
"gw/"
;
private
String
getMsgUrl_end
=
"soc-center/soc-msg/list-soc-msg"
;
private
String
confirmMsgUrl_end
=
"soc-center/soc-msg/confirm-soc-msg"
;
private
String
confirmMoreMsgUrl_end
=
"soc-center/soc-msg/batch-confirm-soc-msg"
;
private
String
getMsgUrl
=
baseUrl
+
getMsgUrl_end
;
private
String
confirmMsgUrl
=
baseUrl
+
confirmMsgUrl_end
;
private
String
confirmMoreMsgUrl
=
baseUrl
+
confirmMoreMsgUrl_end
;
private
String
token
=
""
;
private
String
client_id
=
""
;
/**
* 心跳ping的内容
*/
private
String
pingData
=
"{\"type\":\"ping\",\"data\":{\"newVerWithMsgConfirm\":true}}"
;
/**
* 心跳Ping的频率
*/
private
int
pingRate
=
5000
;
//ping 频率
private
static
MsgWebSocketUtil
msgWebSocketUtil
;
private
WebSocket
mWebSocket
;
private
int
mQueueInterval
=
1000
;
/**
* socket链接状态
*/
private
boolean
isConnected
=
false
;
/**
* socket地址
*/
private
String
webSocketUrl
=
""
;
//通道
private
String
socketWay
=
""
;
/**
* 设备号
* 绑定socket连接时使用,也是推送唯一标识
*/
private
String
DeviceName
=
""
;
/**
* 是否打印日志
*/
private
boolean
isShowLog
=
true
;
/**
* 是否开启队列
*/
private
boolean
useQueue
=
false
;
/**
* 禁用队列时 消息监听
*/
private
SocketMessageBackListener
socketMessageListener
;
/**
* 开启队列时 消息监听
*/
private
QueueMessageBackListener
queueMessageListener
;
/**
* socket连接监听
*/
private
SocketConnectListener
socketConnectListener
;
private
WebSocketSubscriberListener
mWebSocketSubscriberListener
;
/**
* 离线时间
* 离线达到一定时间,自动重启socket
*/
private
int
offLineTime
=
0
;
private
Context
context
;
//socket2.0 涉及参数
private
boolean
isSocket2
=
false
;
private
boolean
openTimingGetMessage
=
false
;
private
int
getMessageInterval
=
60000
;
private
Gson
gson
;
private
MsgWebSocketUtil
()
{
}
private
MsgWebSocketUtil
(
Context
context
)
{
this
.
context
=
context
.
getApplicationContext
();
gson
=
new
Gson
();
}
/**
* 入口
*
* @return
*/
// public static MsgWebSocketUtil getInstance() {
// if (msgWebSocketUtil == null) {
// msgWebSocketUtil = new MsgWebSocketUtil();
// }
// return msgWebSocketUtil;
// }
public
static
MsgWebSocketUtil
getInstance
(
Context
context
)
{
if
(
msgWebSocketUtil
==
null
)
{
msgWebSocketUtil
=
new
MsgWebSocketUtil
(
context
);
}
return
msgWebSocketUtil
;
}
/**
* 初始化数据库,此方法必须在 application 中调用
*/
public
void
initSql
()
{
LitePal
.
initialize
(
context
);
MessageDBManager
.
deleteYesterdayAllHistory
(
context
);
}
/**
* 设置socket地址
*
* @param url
*/
public
MsgWebSocketUtil
setUrl
(
String
url
)
{
webSocketUrl
=
url
;
if
(
StringUtil
.
isNotNull
(
webSocketUrl
))
{
socketWay
=
webSocketUrl
.
substring
(
webSocketUrl
.
lastIndexOf
(
"/"
)
+
1
);
}
return
msgWebSocketUtil
;
}
/**
* 设置 socket 2.0 接口基地址
*
* @param url
* @return
*/
public
MsgWebSocketUtil
setHttpBasicUrl
(
String
url
)
{
// basicUrl = "http://inapi.qimai.shop";
basicUrl
=
url
;
baseUrl
=
basicUrl
+
"gw/"
;
getMsgUrl
=
baseUrl
+
getMsgUrl_end
;
confirmMsgUrl
=
baseUrl
+
confirmMsgUrl_end
;
confirmMoreMsgUrl
=
baseUrl
+
confirmMoreMsgUrl_end
;
return
msgWebSocketUtil
;
}
//与上面接口一样功能,使用一个即可
public
MsgWebSocketUtil
setHttpBasicUrl
(
int
build_type
)
{
// basicUrl = "http://inapi.qimai.shop";
switch
(
build_type
)
{
case
BUILD_TYPE_DEV:
basicUrl
=
"http://inapi.zmcms.cn/"
;
break
;
case
BUILD_TYPE_SHOP:
basicUrl
=
"http://inapi.qimai.shop/"
;
break
;
case
BUILD_TYPE_BETA:
basicUrl
=
"http://inapi.qimai.co/"
;
break
;
case
BUILD_TYPE_RELEASE:
default
:
basicUrl
=
"http://inapi.qimai.cn/"
;
break
;
}
baseUrl
=
basicUrl
+
"gw/"
;
getMsgUrl
=
baseUrl
+
getMsgUrl_end
;
confirmMsgUrl
=
baseUrl
+
confirmMsgUrl_end
;
confirmMoreMsgUrl
=
baseUrl
+
confirmMoreMsgUrl_end
;
return
msgWebSocketUtil
;
}
public
MsgWebSocketUtil
setToken
(
String
token
)
{
this
.
token
=
token
;
return
msgWebSocketUtil
;
}
/**
* 设置是否打印日志
*
* @param is_show
*/
public
MsgWebSocketUtil
showLog
(
boolean
is_show
)
{
Logger
.
LOG_ENABLE
=
isShowLog
=
is_show
;
return
msgWebSocketUtil
;
}
/**
* 设置设备号
*
* @param device_name 绑定socket时使用
*/
public
MsgWebSocketUtil
setDeviceName
(
String
device_name
)
{
DeviceName
=
device_name
;
return
msgWebSocketUtil
;
}
/**
* ping频率
* socket ping的频率
* 默认 5000ms
*
* @param ping_rate
*/
public
MsgWebSocketUtil
setPingRate
(
int
ping_rate
)
{
pingRate
=
ping_rate
;
return
msgWebSocketUtil
;
}
/**
* 设置ping内容
* 默认 "{\"type\":\"ping\",\"data\":\"\"}"
* 如有改动可用此方法修改 ping的内容
*
* @param ping_data
*/
public
MsgWebSocketUtil
setPingData
(
String
ping_data
)
{
pingData
=
ping_data
;
return
msgWebSocketUtil
;
}
/**
* 是否开启队列
* 若不开启 接收到消息直接下放
*
* @param use_queue
*/
public
MsgWebSocketUtil
useQueue
(
boolean
use_queue
)
{
useQueue
=
use_queue
;
return
msgWebSocketUtil
;
}
/**
* socket消息回调
* 不开启队列时,使用此消息监听
*
* @param socketMessageListener_
*/
public
MsgWebSocketUtil
setSocketMessageListener
(
SocketMessageBackListener
socketMessageListener_
)
{
socketMessageListener
=
socketMessageListener_
;
return
msgWebSocketUtil
;
}
/**
* queue消息回调
* 开启队列时,使用此消息监听
*
* @param queueMessageListener_
*/
public
MsgWebSocketUtil
setQueueMessageListener
(
QueueMessageBackListener
queueMessageListener_
)
{
queueMessageListener
=
queueMessageListener_
;
return
msgWebSocketUtil
;
}
public
MsgWebSocketUtil
setSocketConnectListener
(
SocketConnectListener
socketConnectListener_
)
{
socketConnectListener
=
socketConnectListener_
;
return
msgWebSocketUtil
;
}
/**
* 是否是socket2.0
*
* @param is_socket_2
* @return
*/
public
MsgWebSocketUtil
isSocket2
(
boolean
is_socket_2
)
{
this
.
isSocket2
=
is_socket_2
;
return
msgWebSocketUtil
;
}
/**
* 是否开启 定时拉取消息
*
* @param is_open_timing_getmessage
* @return
*/
public
MsgWebSocketUtil
isopenTimingGetMessage
(
boolean
is_open_timing_getmessage
)
{
this
.
openTimingGetMessage
=
is_open_timing_getmessage
;
return
msgWebSocketUtil
;
}
/**
* 设置拉取消息 间隔 时间
*
* @param time_interval
* @return
*/
public
MsgWebSocketUtil
setTimingGetMessageInterval
(
int
time_interval
)
{
this
.
getMessageInterval
=
time_interval
;
return
msgWebSocketUtil
;
}
/**
* 连接socket
* 最后调用此方法
*/
public
void
initSocket
()
{
if
(
StringUtil
.
isNull
(
webSocketUrl
))
{
Logger
.
e
(
TAG
,
"webSocketUrl is null"
);
return
;
}
if
(
StringUtil
.
isNull
(
DeviceName
))
{
Logger
.
e
(
TAG
,
"DeviceName is null"
);
return
;
}
Logger
.
e
(
TAG
,
"初始化socket initSocket()"
);
//是否开启日志
RxWebSocketUtil
.
getInstance
().
setShowLog
(
isShowLog
);
//初始化ping定时器
initPing
();
// ping/pong 设置:在设置config的时候,从okhttpclient中配置,设置5秒的心跳
// OkHttpClient client = new OkHttpClient.Builder()
// .connectTimeout(5, TimeUnit.SECONDS)
// .readTimeout(3,TimeUnit.SECONDS)
// .writeTimeout(3,TimeUnit.SECONDS)
// .pingInterval(3, TimeUnit.SECONDS)
// .build();
Config
config
=
new
Config
.
Builder
()
// .setClient(client) //if you want to set your okhttpClient
.
setShowLog
(
isShowLog
,
TAG
)
.
setReconnectInterval
(
2
,
TimeUnit
.
SECONDS
)
//set reconnect interval
// .setSSLSocketFactory(yourSSlSocketFactory, yourX509TrustManager) // wss support
.
build
();
RxWebSocket
.
setConfig
(
config
);
Logger
.
e
(
TAG
,
"开启长连接;;"
+
webSocketUrl
);
// RxWebSocket.get(MyApplication.WEBSOCKET_HOST_AND_PORT)
webSocketSubscriber
=
new
WebSocketSubscriber
()
{
@Override
public
void
onOpen
(
@NonNull
WebSocket
webSocket
)
{
Logger
.
e
(
TAG
,
"onOpen1:"
);
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onOpen
(
webSocket
);
}
mWebSocket
=
webSocket
;
isConnected
=
true
;
if
(
socketConnectListener
!=
null
)
{
socketConnectListener
.
connected
();
}
else
{
Logger
.
e
(
TAG
,
"socketConnectListener==null"
);
}
}
@Override
public
void
onMessage
(
@NonNull
String
text
)
{
Logger
.
e
(
TAG
,
"onMessage;;"
+
text
);
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onMessage
(
text
);
}
checkMessage
(
text
);
}
@Override
public
void
onMessage
(
@NonNull
ByteString
bytes
)
{
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onMessage
(
bytes
);
}
Logger
.
e
(
TAG
,
bytes
.
toString
());
}
@Override
protected
void
onReconnect
()
{
Logger
.
e
(
TAG
,
"重连"
);
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onReconnect
();
}
isConnected
=
false
;
if
(
socketConnectListener
!=
null
)
{
socketConnectListener
.
disconnect
();
}
else
{
Logger
.
e
(
TAG
,
"socketConnectListener==null"
);
}
}
@Override
protected
void
onClose
()
{
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onClose
();
}
Logger
.
e
(
TAG
,
"关闭"
);
if
(
socketConnectListener
!=
null
)
{
socketConnectListener
.
closed
();
}
else
{
Logger
.
e
(
TAG
,
"socketConnectListener==null"
);
}
}
@Override
public
void
onError
(
Throwable
e
)
{
if
(
mWebSocketSubscriberListener
!=
null
)
{
mWebSocketSubscriberListener
.
onError
(
e
);
}
Logger
.
e
(
TAG
,
"错误:"
+
e
.
getMessage
());
}
};
RxWebSocket
.
get
(
webSocketUrl
)
// RxWebSocket.get("ws://qmapp.dev.zmcms.cn:8282")
//RxLifecycle : https://github.com/dhhAndroid/RxLifecycle
// .compose(RxLifecycle.with(MyApplication.mContext).<WebSocketInfo>bindToLifecycle())//如果需要跟activity生命绑定,防止内存泄漏,可以用这个方法
.
subscribe
(
webSocketSubscriber
);
//如果开启队列,则启动队列消息服务
if
(
useQueue
)
{
QueueMessageService
.
getInstance
().
setInterval
(
mQueueInterval
);
QueueMessageService
.
getInstance
().
startPrintService
(
new
MessageQueueServiceListner
()
{
@Override
public
void
getMessage
(
String
message
)
{
if
(
queueMessageListener
!=
null
)
{
queueMessageListener
.
reciever
(
message
);
}
else
{
Logger
.
e
(
TAG
,
"queueMessageListener==null"
);
}
}
});
}
}
/**
* 处理分发接收到的消息
* 根据接收的消息,进行相应的处理,这里随便写的,要根据自己定的规则进行处理
*/
private
void
checkMessage
(
String
message
)
{
try
{
Log
.
d
(
TAG
,
"checkMessage: message= "
+
message
);
JSONObject
jsonObject
=
new
JSONObject
(
message
);
String
type
=
jsonObject
.
optString
(
"type"
);
switch
(
type
)
{
case
"init"
:
//初始化/验证
sendBind
(
jsonObject
);
break
;
case
"success"
:
//验证成功//2.0有消息的时候,type返回的竟然也是这个 0.o
//这里优化,如果是通知 有新消息,请求接口后 筛重 再塞队列
if
(
StringUtil
.
isNotNull
(
jsonObject
.
optString
(
"new_message"
)))
{
if
(
jsonObject
.
optString
(
"new_message"
).
equals
(
"true"
))
{
getSocketServiceMessage
();
}
}
else
{
Logger
.
e
(
TAG
,
"socket绑定成功"
);
}
//判断是否存在tag,tag不为空就 通知socket服务端,收到了此消息-----------
// if (useQueue) {//如果开启队列,消息加入队列---------------------------------------------
// MessageQueue.getInstance().enQueue(message);
// } else {//直接 回调 传消息
// if (socketMessageListener != null) {
// socketMessageListener.recieveMessage(message);
// } else {
// Logger.e(TAG, "socketMessageListener==null");
// }
// }
break
;
case
"error"
:
//验证失败
Logger
.
e
(
TAG
,
"socket绑定失败"
);
break
;
default
:
//其它的消息 下放给调用者 或 直接扔到队列中
//判断是否存在tag,tag不为空就 通知socket服务端,收到了此消息-----------
if
(
StringUtil
.
isNotNull
(
jsonObject
.
optString
(
"tag"
)))
{
String
tag
=
jsonObject
.
optString
(
"tag"
);
boolean
needConfirm
=
jsonObject
.
optBoolean
(
"needConfirm"
);
Logger
.
e
(
TAG
,
"发送确认消息数据:needConfirm = "
+
needConfirm
+
" 内容:"
+
getConfirmMessage
(
tag
));
if
(
mWebSocket
!=
null
&&
needConfirm
)
{
mWebSocket
.
send
(
getConfirmMessage
(
tag
));
}
//数据库 存储消息id,判断数据库是否已有此消息,如果存在 忽略消息,不存在则存储消息,继续下一步--------------------------------
if
(
MessageDBManager
.
isRecieverMessage
(
tag
))
{
Logger
.
e
(
TAG
,
"------该消息数据库已存在 tag = "
+
tag
);
return
;
}
//数据库记录消息id
MessageDBManager
.
addMessage
(
tag
);
}
if
(
useQueue
)
{
//如果开启队列,消息加入队列---------------------------------------------
Logger
.
e
(
TAG
,
"------消息加入队列 "
);
MessageQueue
.
getInstance
().
enQueue
(
message
);
}
else
{
//直接 回调 传消息
if
(
socketMessageListener
!=
null
)
{
socketMessageListener
.
recieveMessage
(
message
);
}
else
{
Logger
.
e
(
TAG
,
"socketMessageListener==null"
);
}
}
break
;
}
}
catch
(
JSONException
e
)
{
}
}
/**
* 通知服务端 消息收到成功
*
* @param tag
* @return
*/
private
String
getConfirmMessage
(
String
tag
)
{
return
"{\"type\": \"msg-confirm\",\"data\":{\"tag\":\""
+
tag
+
"\"}}"
;
}
/**
* 发送绑定/验证 请求
*/
private
void
sendBind
(
JSONObject
jsonObject
)
{
try
{
Logger
.
e
(
TAG
,
"sendBind()被调用"
);
JSONObject
bindJson
=
new
JSONObject
();
bindJson
.
put
(
"type"
,
"bind-uid"
);
client_id
=
jsonObject
.
optString
(
"client_id"
);
bindJson
.
put
(
"key"
,
jsonObject
.
optString
(
"client_id"
));
//data数据组装
JSONObject
dataJson
=
new
JSONObject
();
dataJson
.
put
(
"id"
,
DeviceName
);
bindJson
.
put
(
"data"
,
dataJson
);
if
(
mWebSocket
!=
null
)
{
Logger
.
e
(
TAG
,
"发送绑定数据:"
+
bindJson
.
toString
());
mWebSocket
.
send
(
bindJson
.
toString
());
}
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"sendBind 错误:"
+
e
.
getMessage
());
}
}
/**
* 发送消息方法
*
* @param message
* @return
*/
public
boolean
sendMessage
(
String
message
)
{
if
(!
isConnected
)
{
Logger
.
e
(
TAG
,
"socket已断开"
+
message
);
return
false
;
}
Logger
.
e
(
TAG
,
"sendMessage()被调用"
);
if
(
mWebSocket
!=
null
)
{
Logger
.
e
(
TAG
,
"发送数据:"
+
message
);
mWebSocket
.
send
(
message
);
return
true
;
}
else
{
Logger
.
e
(
TAG
,
"mWebSocket==null"
);
return
false
;
}
}
/**
* 获取socket连接状态
* true:已连接
* false:连接断开 或 未初始化
*
* @return
*/
public
boolean
getConnectStatus
()
{
return
isConnected
;
}
/**
* 开始定时发送心跳
* 这个是监测 连接是否正常的规则,可自定义
*/
private
void
initPing
()
{
RxTimerUtil
.
cancel
(
SysCode
.
RX_TIMER_TYPE
.
SOCKET
);
RxTimerUtil
.
interval
(
SysCode
.
RX_TIMER_TYPE
.
SOCKET
,
pingRate
,
new
RxTimerUtil
.
IRxNext
()
{
@Override
public
void
doNext
(
long
number
)
{
if
(
isConnected
)
{
if
(
mWebSocket
!=
null
)
{
boolean
isPing
=
mWebSocket
.
send
(
pingData
);
if
(
socketConnectListener
!=
null
&&
socketConnectListener
instanceof
SocketConnectListener2
)
{
((
SocketConnectListener2
)
socketConnectListener
).
ping
(
isPing
);
}
if
(
isPing
)
{
offLineTime
=
0
;
}
else
{
offLineTime
++;
}
Logger
.
e
(
TAG
,
isPing
?
(
"ping... 内容:"
+
pingData
)
:
"ping失败..."
);
}
}
else
{
offLineTime
++;
Logger
.
e
(
TAG
,
"Socket中断,停止ping...offLineTime"
+
offLineTime
);
}
if
(
offLineTime
>
10
)
{
//超过10次ping(50S)失败/离线50S 重启socket
destroySocket
();
initSocket
();
}
if
(
context
!=
null
)
{
if
(
NetWorkUtils
.
isOffline
(
context
))
{
Toast
.
makeText
(
context
,
"请检查当前网络"
,
Toast
.
LENGTH_SHORT
).
show
();
}
}
//在ping里面触发 定时消息请求
if
(
isSocket2
&&
openTimingGetMessage
)
{
if
(
number
*
pingRate
%
getMessageInterval
==
0
)
{
//定时拉取服务端打印消息
getSocketServiceMessage
();
}
else
{
Logger
.
e
(
TAG
,
"number = "
+
number
+
" ;; pingRate = "
+
pingRate
+
" ;; getMessageInterval = "
+
getMessageInterval
);
}
}
else
{
Logger
.
e
(
TAG
,
"isSocket2 = "
+
isSocket2
+
" ;; openTimingGetMessage = "
+
openTimingGetMessage
);
}
}
});
}
public
void
destroySocket
()
{
if
(
webSocketSubscriber
!=
null
)
{
webSocketSubscriber
.
dispose
();
Logger
.
e
(
TAG
,
"socket服务已关闭..."
);
}
RxTimerUtil
.
cancel
(
SysCode
.
RX_TIMER_TYPE
.
SOCKET
);
Logger
.
e
(
TAG
,
"socket心跳已关闭..."
);
}
public
MsgWebSocketUtil
setWebSocketSubscriberListener
(
WebSocketSubscriberListener
mWebSocketSubscriberListener
)
{
this
.
mWebSocketSubscriberListener
=
mWebSocketSubscriberListener
;
return
this
;
}
public
MsgWebSocketUtil
setQueueInterval
(
int
mQueueInterval
)
{
this
.
mQueueInterval
=
mQueueInterval
;
return
this
;
}
/**
* socket 2.0
* 从接口拉取消息
*/
private
void
getSocketServiceMessage
()
{
Map
<
String
,
String
>
params
=
new
HashMap
<>();
params
.
put
(
"pageNum"
,
"1"
);
params
.
put
(
"pageSize"
,
"10"
);
params
.
put
(
"clientUid"
,
socketWay
+
"_"
+
DeviceName
);
// params.put("version_num", BuildConfig.VERSION_CODE + "");
MyOkHttpUtils
.
getInstance
().
post
(
getMsgUrl
,
params
,
token
,
basicUrl
,
new
CallBackListener
()
{
@Override
public
void
error
(
String
error
)
{
Logger
.
e
(
TAG
,
"get_msg_error : "
+
error
);
}
@Override
public
void
fail
(
String
message
)
{
Logger
.
e
(
TAG
,
"get_msg_fail : "
+
message
);
}
@Override
public
void
success
(
String
content
)
{
Logger
.
e
(
TAG
,
"get_msg_success : "
+
content
);
try
{
JSONObject
jsonObject
=
new
JSONObject
(
content
);
JSONArray
jsonArray
=
jsonObject
.
optJSONArray
(
"list"
);
ArrayList
<
CommonMsgData
>
lsTag
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
jsonArray
.
length
();
i
++)
{
JSONObject
object
=
jsonArray
.
getJSONObject
(
i
);
checkMessage
(
object
.
toString
());
//check 消息
lsTag
.
add
(
gson
.
fromJson
(
object
.
toString
(),
CommonMsgData
.
class
));
}
batchConfirmMsg
(
lsTag
);
}
catch
(
Exception
e
)
{
Logger
.
e
(
TAG
,
"get_msg_success : 遍历解析数据失败"
+
e
.
getMessage
());
}
}
});
}
private
void
batchConfirmMsg
(
ArrayList
<
CommonMsgData
>
ls_tag
)
{
//////////////
RequestBody
body
=
null
;
okhttp3
.
FormBody
.
Builder
formEncodingBuilder
=
new
okhttp3
.
FormBody
.
Builder
();
for
(
int
i
=
0
;
i
<
ls_tag
.
size
();
i
++)
{
formEncodingBuilder
.
add
(
"tag[]"
,
ls_tag
.
get
(
i
).
getTag
());
}
formEncodingBuilder
.
add
(
"storeId"
,
ls_tag
.
get
(
0
).
getStoreId
()
+
""
);
formEncodingBuilder
.
add
(
"clientUid"
,
socketWay
+
"_"
+
DeviceName
);
body
=
formEncodingBuilder
.
build
();
//////////////
MyOkHttpUtils
.
getInstance
().
post
(
confirmMoreMsgUrl
,
body
,
token
,
basicUrl
,
new
CallBackListener
()
{
@Override
public
void
error
(
String
error
)
{
Logger
.
e
(
TAG
,
"confirm_msg_error : "
+
error
);
}
@Override
public
void
fail
(
String
message
)
{
Logger
.
e
(
TAG
,
"confirm_msg_fail : "
+
message
);
}
@Override
public
void
success
(
String
content
)
{
Logger
.
e
(
TAG
,
"confirm_msg_success : "
+
content
);
}
});
}
}
websocket/src/main/java/com/zhimai/websocket/util/NetWorkUtils.java
0 → 100644
View file @
e0a99c4a
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
);
}
}
websocket/src/main/java/com/zhimai/websocket/util/RxTimerUtil.java
0 → 100644
View file @
e0a99c4a
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
);
}
}
websocket/src/main/java/com/zhimai/websocket/util/SpUtils.java
0 → 100644
View file @
e0a99c4a
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
();
}
}
websocket/src/main/java/com/zhimai/websocket/util/StringUtil.java
0 → 100644
View file @
e0a99c4a
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
;
}
}
websocket/src/main/java/com/zhimai/websocket/util/SysCode.java
0 → 100644
View file @
e0a99c4a
package
com
.
zhimai
.
websocket
.
util
;
/**
* 常量
*/
public
class
SysCode
{
/**
* 定时器类型
*/
public
interface
RX_TIMER_TYPE
{
int
TIME
=
0
;
int
SOCKET
=
1
;
int
PRINT
=
2
;
}
}
websocket/src/main/java/com/zhimai/websocket/util/TimeUtils.java
0 → 100644
View file @
e0a99c4a
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
;
}
}
websocket/src/main/res/layout/activity_main_websocket.xml
0 → 100644
View file @
e0a99c4a
<?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
websocket/src/main/res/values/strings.xml
0 → 100644
View file @
e0a99c4a
<resources>
<string
name=
"app_name"
>
websocket
</string>
</resources>
websocket/src/test/java/com/zhimai/websocket/ExampleUnitTest.java
0 → 100644
View file @
e0a99c4a
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment