Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
AloqaIM-Android
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
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
Administrator
AloqaIM-Android
Commits
739efd88
Commit
739efd88
authored
Nov 10, 2017
by
Leonardo Aramaki
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Keep always a single thread for any number of signed-in servers
parent
c6132148
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
256 additions
and
218 deletions
+256
-218
DDPClient.java
...-ddp/src/main/java/chat/rocket/android_ddp/DDPClient.java
+153
-154
MainPresenter.java
...main/java/chat/rocket/android/activity/MainPresenter.java
+4
-1
RealmBasedConnectivityManager.java
...rocket/android/service/RealmBasedConnectivityManager.java
+5
-4
RocketChatService.java
...n/java/chat/rocket/android/service/RocketChatService.java
+39
-14
RocketChatWebSocketThread.java
...hat/rocket/android/service/RocketChatWebSocketThread.java
+46
-44
ServerConnectivity.java
.../java/chat/rocket/android/service/ServerConnectivity.java
+9
-1
No files found.
android-ddp/src/main/java/chat/rocket/android_ddp/DDPClient.java
View file @
739efd88
...
@@ -20,165 +20,164 @@ import io.reactivex.annotations.Nullable;
...
@@ -20,165 +20,164 @@ import io.reactivex.annotations.Nullable;
import
okhttp3.OkHttpClient
;
import
okhttp3.OkHttpClient
;
public
class
DDPClient
{
public
class
DDPClient
{
// reference: https://github.com/eddflrs/meteor-ddp/blob/master/meteor-ddp.js
// reference: https://github.com/eddflrs/meteor-ddp/blob/master/meteor-ddp.js
public
static
final
int
REASON_CLOSED_BY_USER
=
1000
;
private
static
volatile
DDPClient
singleton
;
public
static
final
int
REASON_NETWORK_ERROR
=
1001
;
private
static
volatile
OkHttpClient
client
;
private
final
DDPClientImpl
impl
;
private
static
volatile
DDPClient
singleton
;
private
final
AtomicReference
<
String
>
hostname
=
new
AtomicReference
<>();
private
static
volatile
OkHttpClient
client
;
private
final
DDPClientImpl
impl
;
public
static
void
initialize
(
OkHttpClient
okHttpClient
)
{
private
final
AtomicReference
<
String
>
hostname
=
new
AtomicReference
<>();
client
=
okHttpClient
;
}
public
static
void
initialize
(
OkHttpClient
okHttpClient
)
{
client
=
okHttpClient
;
public
static
DDPClient
get
()
{
}
DDPClient
result
=
singleton
;
if
(
result
==
null
)
{
public
static
DDPClient
get
()
{
synchronized
(
DDPClient
.
class
)
{
DDPClient
result
=
singleton
;
result
=
singleton
;
if
(
result
==
null
)
{
if
(
result
==
null
)
{
singleton
=
result
=
new
DDPClient
(
client
);
synchronized
(
DDPClient
.
class
)
{
result
=
singleton
;
if
(
result
==
null
)
{
singleton
=
result
=
new
DDPClient
(
client
);
}
}
}
}
}
return
result
;
}
}
return
result
;
}
private
DDPClient
(
OkHttpClient
client
)
{
impl
=
new
DDPClientImpl
(
this
,
client
);
private
DDPClient
(
OkHttpClient
client
)
{
}
impl
=
new
DDPClientImpl
(
this
,
client
);
}
public
Task
<
DDPClientCallback
.
Connect
>
connect
(
String
url
,
String
session
)
{
hostname
.
set
(
url
);
public
Task
<
DDPClientCallback
.
Connect
>
connect
(
String
url
,
String
session
)
{
TaskCompletionSource
<
DDPClientCallback
.
Connect
>
task
=
new
TaskCompletionSource
<>();
String
oldHostname
=
hostname
.
getAndSet
(
url
);
impl
.
connect
(
task
,
url
,
session
);
if
(
oldHostname
!=
null
&&
!
oldHostname
.
equalsIgnoreCase
(
url
))
{
return
task
.
getTask
();
close
();
}
}
TaskCompletionSource
<
DDPClientCallback
.
Connect
>
task
=
new
TaskCompletionSource
<>();
public
Task
<
DDPClientCallback
.
Ping
>
ping
(
@Nullable
String
id
)
{
impl
.
connect
(
task
,
url
,
session
);
TaskCompletionSource
<
DDPClientCallback
.
Ping
>
task
=
new
TaskCompletionSource
<>();
return
task
.
getTask
();
impl
.
ping
(
task
,
id
);
}
return
task
.
getTask
();
}
public
Task
<
DDPClientCallback
.
Ping
>
ping
(
@Nullable
String
id
)
{
TaskCompletionSource
<
DDPClientCallback
.
Ping
>
task
=
new
TaskCompletionSource
<>();
public
Maybe
<
DDPClientCallback
.
Base
>
doPing
(
@Nullable
String
id
)
{
impl
.
ping
(
task
,
id
);
return
impl
.
ping
(
id
);
return
task
.
getTask
();
}
}
public
Task
<
DDPSubscription
.
Ready
>
sub
(
String
id
,
String
name
,
JSONArray
params
)
{
public
Maybe
<
DDPClientCallback
.
Base
>
doPing
(
@Nullable
String
id
)
{
TaskCompletionSource
<
DDPSubscription
.
Ready
>
task
=
new
TaskCompletionSource
<>();
return
impl
.
ping
(
id
);
impl
.
sub
(
task
,
name
,
params
,
id
);
}
return
task
.
getTask
();
}
public
Task
<
DDPSubscription
.
Ready
>
sub
(
String
id
,
String
name
,
JSONArray
params
)
{
TaskCompletionSource
<
DDPSubscription
.
Ready
>
task
=
new
TaskCompletionSource
<>();
public
Task
<
DDPSubscription
.
NoSub
>
unsub
(
String
id
)
{
impl
.
sub
(
task
,
name
,
params
,
id
);
TaskCompletionSource
<
DDPSubscription
.
NoSub
>
task
=
new
TaskCompletionSource
<>();
return
task
.
getTask
();
impl
.
unsub
(
task
,
id
);
}
return
task
.
getTask
();
}
public
Task
<
DDPSubscription
.
NoSub
>
unsub
(
String
id
)
{
TaskCompletionSource
<
DDPSubscription
.
NoSub
>
task
=
new
TaskCompletionSource
<>();
public
Task
<
RxWebSocketCallback
.
Close
>
getOnCloseCallback
()
{
impl
.
unsub
(
task
,
id
);
return
impl
.
getOnCloseCallback
();
return
task
.
getTask
();
}
}
public
void
close
()
{
public
Task
<
RxWebSocketCallback
.
Close
>
getOnCloseCallback
()
{
impl
.
close
(
REASON_CLOSED_BY_USER
,
"closed by DDPClient#close()"
);
return
impl
.
getOnCloseCallback
();
}
}
/**
public
void
close
()
{
* check WebSocket connectivity with ping.
impl
.
close
(
1000
,
"closed by DDPClient#close()"
);
*/
}
public
Task
<
Void
>
ping
()
{
final
String
pingId
=
UUID
.
randomUUID
().
toString
();
/**
RCLog
.
d
(
"ping[%s] >"
,
pingId
);
* check WebSocket connectivity with ping.
return
ping
(
pingId
)
*/
.
continueWithTask
(
task
->
{
public
Task
<
Void
>
ping
()
{
if
(
task
.
isFaulted
())
{
final
String
pingId
=
UUID
.
randomUUID
().
toString
();
RCLog
.
d
(
task
.
getError
(),
"ping[%s] xxx failed xxx"
,
pingId
);
RCLog
.
d
(
"ping[%s] >"
,
pingId
);
return
Task
.
forError
(
task
.
getError
());
return
ping
(
pingId
)
}
else
{
.
continueWithTask
(
task
->
{
RCLog
.
d
(
"pong[%s] <"
,
pingId
);
if
(
task
.
isFaulted
())
{
return
Task
.
forResult
(
null
);
RCLog
.
d
(
task
.
getError
(),
"ping[%s] xxx failed xxx"
,
pingId
);
}
return
Task
.
forError
(
task
.
getError
());
});
}
else
{
}
RCLog
.
d
(
"pong[%s] <"
,
pingId
);
return
Task
.
forResult
(
null
);
/**
}
* check WebSocket connectivity with ping.
*/
public
Maybe
<
DDPClientCallback
.
Base
>
doPing
()
{
final
String
pingId
=
UUID
.
randomUUID
().
toString
();
RCLog
.
d
(
"ping[%s] >"
,
pingId
);
return
doPing
(
pingId
);
}
/**
* Connect to WebSocket server with DDP client.
*/
public
Task
<
DDPClientCallback
.
Connect
>
connect
(
@NonNull
String
hostname
,
@Nullable
String
session
,
boolean
usesSecureConnection
)
{
final
String
protocol
=
usesSecureConnection
?
"wss://"
:
"ws://"
;
return
connect
(
protocol
+
hostname
+
"/websocket"
,
session
);
}
/**
* Subscribe with DDP client.
*/
public
Task
<
DDPSubscription
.
Ready
>
subscribe
(
final
String
name
,
JSONArray
param
)
{
final
String
subscriptionId
=
UUID
.
randomUUID
().
toString
();
RCLog
.
d
(
"sub:[%s]> %s(%s)"
,
subscriptionId
,
name
,
param
);
return
sub
(
subscriptionId
,
name
,
param
);
}
/**
* Unsubscribe with DDP client.
*/
public
Task
<
DDPSubscription
.
NoSub
>
unsubscribe
(
final
String
subscriptionId
)
{
RCLog
.
d
(
"unsub:[%s]>"
,
subscriptionId
);
return
unsub
(
subscriptionId
);
}
/**
* Returns Observable for handling DDP subscription.
*/
public
Flowable
<
DDPSubscription
.
Event
>
getSubscriptionCallback
()
{
return
impl
.
getDDPSubscription
();
}
/**
* Execute raw RPC.
*/
public
Task
<
DDPClientCallback
.
RPC
>
rpc
(
String
methodCallId
,
String
methodName
,
String
params
,
long
timeoutMs
)
{
TaskCompletionSource
<
DDPClientCallback
.
RPC
>
task
=
new
TaskCompletionSource
<>();
RCLog
.
d
(
"rpc:[%s]> %s(%s) timeout=%d"
,
methodCallId
,
methodName
,
params
,
timeoutMs
);
if
(
TextUtils
.
isEmpty
(
params
))
{
impl
.
rpc
(
task
,
methodName
,
null
,
methodCallId
,
timeoutMs
);
return
task
.
getTask
().
continueWithTask
(
task_
->
{
if
(
task_
.
isFaulted
())
{
RCLog
.
d
(
"rpc:[%s]< error = %s"
,
methodCallId
,
task_
.
getError
());
}
else
{
RCLog
.
d
(
"rpc:[%s]< result = %s"
,
methodCallId
,
task_
.
getResult
().
result
);
}
return
task_
;
});
});
}
/**
* check WebSocket connectivity with ping.
*/
public
Maybe
<
DDPClientCallback
.
Base
>
doPing
()
{
final
String
pingId
=
UUID
.
randomUUID
().
toString
();
RCLog
.
d
(
"ping[%s] >"
,
pingId
);
return
doPing
(
pingId
);
}
/**
* Connect to WebSocket server with DDP client.
*/
public
Task
<
DDPClientCallback
.
Connect
>
connect
(
@NonNull
String
hostname
,
@Nullable
String
session
,
boolean
usesSecureConnection
)
{
final
String
protocol
=
usesSecureConnection
?
"wss://"
:
"ws://"
;
return
connect
(
protocol
+
hostname
+
"/websocket"
,
session
);
}
/**
* Subscribe with DDP client.
*/
public
Task
<
DDPSubscription
.
Ready
>
subscribe
(
final
String
name
,
JSONArray
param
)
{
final
String
subscriptionId
=
UUID
.
randomUUID
().
toString
();
RCLog
.
d
(
"sub:[%s]> %s(%s)"
,
subscriptionId
,
name
,
param
);
return
sub
(
subscriptionId
,
name
,
param
);
}
/**
* Unsubscribe with DDP client.
*/
public
Task
<
DDPSubscription
.
NoSub
>
unsubscribe
(
final
String
subscriptionId
)
{
RCLog
.
d
(
"unsub:[%s]>"
,
subscriptionId
);
return
unsub
(
subscriptionId
);
}
/**
* Returns Observable for handling DDP subscription.
*/
public
Flowable
<
DDPSubscription
.
Event
>
getSubscriptionCallback
()
{
return
impl
.
getDDPSubscription
();
}
/**
* Execute raw RPC.
*/
public
Task
<
DDPClientCallback
.
RPC
>
rpc
(
String
methodCallId
,
String
methodName
,
String
params
,
long
timeoutMs
)
{
TaskCompletionSource
<
DDPClientCallback
.
RPC
>
task
=
new
TaskCompletionSource
<>();
RCLog
.
d
(
"rpc:[%s]> %s(%s) timeout=%d"
,
methodCallId
,
methodName
,
params
,
timeoutMs
);
if
(
TextUtils
.
isEmpty
(
params
))
{
impl
.
rpc
(
task
,
methodName
,
null
,
methodCallId
,
timeoutMs
);
return
task
.
getTask
().
continueWithTask
(
task_
->
{
if
(
task_
.
isFaulted
())
{
RCLog
.
d
(
"rpc:[%s]< error = %s"
,
methodCallId
,
task_
.
getError
());
}
else
{
RCLog
.
d
(
"rpc:[%s]< result = %s"
,
methodCallId
,
task_
.
getResult
().
result
);
}
}
return
task_
;
});
}
try
{
try
{
impl
.
rpc
(
task
,
methodName
,
new
JSONArray
(
params
),
methodCallId
,
timeoutMs
);
impl
.
rpc
(
task
,
methodName
,
new
JSONArray
(
params
),
methodCallId
,
timeoutMs
);
return
task
.
getTask
().
continueWithTask
(
task_
->
{
return
task
.
getTask
().
continueWithTask
(
task_
->
{
if
(
task_
.
isFaulted
())
{
if
(
task_
.
isFaulted
())
{
RCLog
.
d
(
"rpc:[%s]< error = %s"
,
methodCallId
,
task_
.
getError
());
RCLog
.
d
(
"rpc:[%s]< error = %s"
,
methodCallId
,
task_
.
getError
());
}
else
{
}
else
{
RCLog
.
d
(
"rpc:[%s]< result = %s"
,
methodCallId
,
task_
.
getResult
().
result
);
RCLog
.
d
(
"rpc:[%s]< result = %s"
,
methodCallId
,
task_
.
getResult
().
result
);
}
return
task_
;
});
}
catch
(
JSONException
exception
)
{
return
Task
.
forError
(
exception
);
}
}
return
task_
;
});
}
catch
(
JSONException
exception
)
{
return
Task
.
forError
(
exception
);
}
}
}
}
}
app/src/main/java/chat/rocket/android/activity/MainPresenter.java
View file @
739efd88
...
@@ -18,6 +18,7 @@ import chat.rocket.android.log.RCLog;
...
@@ -18,6 +18,7 @@ import chat.rocket.android.log.RCLog;
import
chat.rocket.android.service.ConnectivityManagerApi
;
import
chat.rocket.android.service.ConnectivityManagerApi
;
import
chat.rocket.android.service.ServerConnectivity
;
import
chat.rocket.android.service.ServerConnectivity
;
import
chat.rocket.android.shared.BasePresenter
;
import
chat.rocket.android.shared.BasePresenter
;
import
chat.rocket.android_ddp.DDPClient
;
import
chat.rocket.core.PublicSettingsConstants
;
import
chat.rocket.core.PublicSettingsConstants
;
import
chat.rocket.core.interactors.CanCreateRoomInteractor
;
import
chat.rocket.core.interactors.CanCreateRoomInteractor
;
import
chat.rocket.core.interactors.RoomInteractor
;
import
chat.rocket.core.interactors.RoomInteractor
;
...
@@ -227,7 +228,9 @@ public class MainPresenter extends BasePresenter<MainContract.View>
...
@@ -227,7 +228,9 @@ public class MainPresenter extends BasePresenter<MainContract.View>
view
.
showConnectionOk
();
view
.
showConnectionOk
();
view
.
refreshRoom
();
view
.
refreshRoom
();
}
else
if
(
connectivity
.
state
==
ServerConnectivity
.
STATE_DISCONNECTED
)
{
}
else
if
(
connectivity
.
state
==
ServerConnectivity
.
STATE_DISCONNECTED
)
{
view
.
showConnectionError
();
if
(
connectivity
.
code
==
DDPClient
.
REASON_NETWORK_ERROR
)
{
view
.
showConnectionError
();
}
}
else
{
}
else
{
view
.
showConnecting
();
view
.
showConnecting
();
}
}
...
...
app/src/main/java/chat/rocket/android/service/RealmBasedConnectivityManager.java
View file @
739efd88
...
@@ -16,6 +16,7 @@ import java.util.concurrent.TimeUnit;
...
@@ -16,6 +16,7 @@ import java.util.concurrent.TimeUnit;
import
chat.rocket.android.RocketChatCache
;
import
chat.rocket.android.RocketChatCache
;
import
chat.rocket.android.helper.RxHelper
;
import
chat.rocket.android.helper.RxHelper
;
import
chat.rocket.android.log.RCLog
;
import
chat.rocket.android.log.RCLog
;
import
chat.rocket.android_ddp.DDPClient
;
import
chat.rocket.core.models.ServerInfo
;
import
chat.rocket.core.models.ServerInfo
;
import
chat.rocket.persistence.realm.models.RealmBasedServerInfo
;
import
chat.rocket.persistence.realm.models.RealmBasedServerInfo
;
import
hugo.weaving.DebugLog
;
import
hugo.weaving.DebugLog
;
...
@@ -79,7 +80,7 @@ import rx.subjects.PublishSubject;
...
@@ -79,7 +80,7 @@ import rx.subjects.PublishSubject;
.
subscribe
(
_val
->
{
.
subscribe
(
_val
->
{
},
error
->
{
},
error
->
{
RCLog
.
e
(
error
);
RCLog
.
e
(
error
);
notifyConnectionLost
(
hostname
,
REASON_NETWORK_ERROR
);
notifyConnectionLost
(
hostname
,
DDPClient
.
REASON_NETWORK_ERROR
);
});
});
}
}
...
@@ -138,10 +139,10 @@ import rx.subjects.PublishSubject;
...
@@ -138,10 +139,10 @@ import rx.subjects.PublishSubject;
@DebugLog
@DebugLog
@Override
@Override
public
void
notifyConnectionLost
(
String
hostname
,
int
reason
)
{
public
void
notifyConnectionLost
(
String
hostname
,
int
code
)
{
serverConnectivityList
.
put
(
hostname
,
ServerConnectivity
.
STATE_DISCONNECTED
);
serverConnectivityList
.
put
(
hostname
,
ServerConnectivity
.
STATE_DISCONNECTED
);
connectivitySubject
.
onNext
(
connectivitySubject
.
onNext
(
new
ServerConnectivity
(
hostname
,
ServerConnectivity
.
STATE_DISCONNECTED
));
new
ServerConnectivity
(
hostname
,
ServerConnectivity
.
STATE_DISCONNECTED
,
code
));
}
}
@DebugLog
@DebugLog
...
@@ -197,7 +198,7 @@ import rx.subjects.PublishSubject;
...
@@ -197,7 +198,7 @@ import rx.subjects.PublishSubject;
if
(
connectivity
==
ServerConnectivity
.
STATE_CONNECTING
)
{
if
(
connectivity
==
ServerConnectivity
.
STATE_CONNECTING
)
{
return
waitForConnected
(
hostname
)
return
waitForConnected
(
hostname
)
.
doOnError
(
err
->
notifyConnectionLost
(
hostname
,
REASON_NETWORK_ERROR
))
.
doOnError
(
err
->
notifyConnectionLost
(
hostname
,
DDPClient
.
REASON_NETWORK_ERROR
))
.
flatMap
(
_val
->
disconnectFromServerIfNeeded
(
hostname
));
.
flatMap
(
_val
->
disconnectFromServerIfNeeded
(
hostname
));
}
}
...
...
app/src/main/java/chat/rocket/android/service/RocketChatService.java
View file @
739efd88
...
@@ -8,11 +8,11 @@ import android.os.Binder;
...
@@ -8,11 +8,11 @@ import android.os.Binder;
import
android.os.IBinder
;
import
android.os.IBinder
;
import
android.support.annotation.Nullable
;
import
android.support.annotation.Nullable
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.Semaphore
;
import
java.util.concurrent.Semaphore
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
import
chat.rocket.android.helper.Logger
;
import
chat.rocket.android.helper.Logger
;
import
chat.rocket.android.log.RCLog
;
import
chat.rocket.persistence.realm.RealmStore
;
import
chat.rocket.persistence.realm.RealmStore
;
import
hugo.weaving.DebugLog
;
import
hugo.weaving.DebugLog
;
import
rx.Observable
;
import
rx.Observable
;
...
@@ -24,8 +24,8 @@ import rx.Single;
...
@@ -24,8 +24,8 @@ import rx.Single;
public
class
RocketChatService
extends
Service
implements
ConnectivityServiceInterface
{
public
class
RocketChatService
extends
Service
implements
ConnectivityServiceInterface
{
private
ConnectivityManagerInternal
connectivityManager
;
private
ConnectivityManagerInternal
connectivityManager
;
private
static
volatile
ConcurrentHashMap
<
String
,
RocketChatWebSocketThread
>
webSocketThreads
;
private
static
volatile
Semaphore
webSocketThreadLock
=
new
Semaphore
(
1
);
private
static
volatile
Semaphore
webSocketThreadLock
=
new
Semaphore
(
1
);
private
static
volatile
RocketChatWebSocketThread
currentWebSocketThread
;
public
class
LocalBinder
extends
Binder
{
public
class
LocalBinder
extends
Binder
{
ConnectivityServiceInterface
getServiceInterface
()
{
ConnectivityServiceInterface
getServiceInterface
()
{
...
@@ -57,7 +57,6 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
...
@@ -57,7 +57,6 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
super
.
onCreate
();
super
.
onCreate
();
connectivityManager
=
ConnectivityManager
.
getInstanceForInternal
(
getApplicationContext
());
connectivityManager
=
ConnectivityManager
.
getInstanceForInternal
(
getApplicationContext
());
connectivityManager
.
resetConnectivityStateList
();
connectivityManager
.
resetConnectivityStateList
();
webSocketThreads
=
new
ConcurrentHashMap
<>();
}
}
@DebugLog
@DebugLog
...
@@ -72,7 +71,7 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
...
@@ -72,7 +71,7 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
return
getOrCreateWebSocketThread
(
hostname
)
return
getOrCreateWebSocketThread
(
hostname
)
.
doOnError
(
err
->
{
.
doOnError
(
err
->
{
err
.
printStackTrace
();
err
.
printStackTrace
();
webSocketThreads
.
remove
(
hostname
)
;
currentWebSocketThread
=
null
;
// connectivityManager.notifyConnectionLost(hostname, ConnectivityManagerInternal.REASON_NETWORK_ERROR);
// connectivityManager.notifyConnectionLost(hostname, ConnectivityManagerInternal.REASON_NETWORK_ERROR);
})
})
.
flatMap
(
webSocketThreads
->
webSocketThreads
.
keepAlive
());
.
flatMap
(
webSocketThreads
->
webSocketThreads
.
keepAlive
());
...
@@ -81,17 +80,15 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
...
@@ -81,17 +80,15 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
@Override
@Override
public
Single
<
Boolean
>
disconnectFromServer
(
String
hostname
)
{
//called via binder.
public
Single
<
Boolean
>
disconnectFromServer
(
String
hostname
)
{
//called via binder.
return
Single
.
defer
(()
->
{
return
Single
.
defer
(()
->
{
if
(!
webSocketThreads
.
containsKey
(
hostname
))
{
if
(!
threadCreatedForHostname
(
hostname
))
{
return
Single
.
just
(
true
);
return
Single
.
just
(
true
);
}
}
RocketChatWebSocketThread
thread
=
webSocketThreads
.
get
(
hostname
);
if
(
currentWebSocketThread
!=
null
)
{
if
(
thread
!=
null
)
{
return
currentWebSocketThread
.
terminate
()
return
thread
.
terminate
()
// after disconnection from server
// after disconnection from server
.
doAfterTerminate
(()
->
{
.
doAfterTerminate
(()
->
{
// remove RCWebSocket key from HashMap
currentWebSocketThread
=
null
;
webSocketThreads
.
remove
(
hostname
);
// remove RealmConfiguration key from HashMap
// remove RealmConfiguration key from HashMap
RealmStore
.
sStore
.
remove
(
hostname
);
RealmStore
.
sStore
.
remove
(
hostname
);
});
});
...
@@ -108,24 +105,52 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
...
@@ -108,24 +105,52 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
webSocketThreadLock
.
acquire
();
webSocketThreadLock
.
acquire
();
int
connectivityState
=
ConnectivityManager
.
getInstance
(
getApplicationContext
()).
getConnectivityState
(
hostname
);
int
connectivityState
=
ConnectivityManager
.
getInstance
(
getApplicationContext
()).
getConnectivityState
(
hostname
);
boolean
isConnected
=
connectivityState
==
ServerConnectivity
.
STATE_CONNECTED
;
boolean
isConnected
=
connectivityState
==
ServerConnectivity
.
STATE_CONNECTED
;
if
(
webSocketThreads
.
containsKey
(
hostname
)
&&
isConnected
)
{
if
(
currentWebSocketThread
!=
null
&&
threadCreatedForHostname
(
hostname
))
{
RocketChatWebSocketThread
thread
=
webSocketThreads
.
get
(
hostname
);
webSocketThreadLock
.
release
();
webSocketThreadLock
.
release
();
return
Single
.
just
(
t
hread
);
return
Single
.
just
(
currentWebSocketT
hread
);
}
}
connectivityManager
.
notifyConnecting
(
hostname
);
connectivityManager
.
notifyConnecting
(
hostname
);
if
(
currentWebSocketThread
!=
null
)
{
return
currentWebSocketThread
.
terminate
()
.
doOnError
(
RCLog:
:
e
)
.
flatMap
(
terminated
->
RocketChatWebSocketThread
.
getStarted
(
getApplicationContext
(),
hostname
)
.
doOnSuccess
(
thread
->
{
currentWebSocketThread
=
thread
;
webSocketThreadLock
.
release
();
})
.
doOnError
(
throwable
->
{
currentWebSocketThread
=
null
;
RCLog
.
e
(
throwable
);
Logger
.
report
(
throwable
);
webSocketThreadLock
.
release
();
})
);
}
return
RocketChatWebSocketThread
.
getStarted
(
getApplicationContext
(),
hostname
)
return
RocketChatWebSocketThread
.
getStarted
(
getApplicationContext
(),
hostname
)
.
doOnSuccess
(
thread
->
{
.
doOnSuccess
(
thread
->
{
webSocketThreads
.
put
(
hostname
,
thread
)
;
currentWebSocketThread
=
thread
;
webSocketThreadLock
.
release
();
webSocketThreadLock
.
release
();
})
})
.
doOnError
(
throwable
->
{
.
doOnError
(
throwable
->
{
currentWebSocketThread
=
null
;
RCLog
.
e
(
throwable
);
Logger
.
report
(
throwable
);
Logger
.
report
(
throwable
);
webSocketThreadLock
.
release
();
webSocketThreadLock
.
release
();
});
});
});
});
}
}
private
boolean
threadCreatedForHostname
(
String
hostname
)
{
if
(
hostname
==
null
||
currentWebSocketThread
==
null
)
{
return
false
;
}
return
currentWebSocketThread
.
getName
().
equals
(
"RC_thread_"
+
hostname
);
}
@Nullable
@Nullable
@Override
@Override
public
IBinder
onBind
(
Intent
intent
)
{
public
IBinder
onBind
(
Intent
intent
)
{
...
...
app/src/main/java/chat/rocket/android/service/RocketChatWebSocketThread.java
View file @
739efd88
...
@@ -35,6 +35,7 @@ import chat.rocket.android.service.observer.PushSettingsObserver;
...
@@ -35,6 +35,7 @@ import chat.rocket.android.service.observer.PushSettingsObserver;
import
chat.rocket.android.service.observer.SessionObserver
;
import
chat.rocket.android.service.observer.SessionObserver
;
import
chat.rocket.android_ddp.DDPClient
;
import
chat.rocket.android_ddp.DDPClient
;
import
chat.rocket.android_ddp.DDPClientCallback
;
import
chat.rocket.android_ddp.DDPClientCallback
;
import
chat.rocket.android_ddp.rx.RxWebSocketCallback
;
import
chat.rocket.core.models.ServerInfo
;
import
chat.rocket.core.models.ServerInfo
;
import
chat.rocket.persistence.realm.RealmHelper
;
import
chat.rocket.persistence.realm.RealmHelper
;
import
chat.rocket.persistence.realm.RealmStore
;
import
chat.rocket.persistence.realm.RealmStore
;
...
@@ -155,14 +156,14 @@ public class RocketChatWebSocketThread extends HandlerThread {
...
@@ -155,14 +156,14 @@ public class RocketChatWebSocketThread extends HandlerThread {
RCLog
.
d
(
"thread %s: terminated()"
,
Thread
.
currentThread
().
getId
());
RCLog
.
d
(
"thread %s: terminated()"
,
Thread
.
currentThread
().
getId
());
unregisterListenersAndClose
();
unregisterListenersAndClose
();
connectivityManager
.
notifyConnectionLost
(
hostname
,
connectivityManager
.
notifyConnectionLost
(
hostname
,
ConnectivityManagerInternal
.
REASON_CLOSED_BY_USER
);
DDPClient
.
REASON_CLOSED_BY_USER
);
RocketChatWebSocketThread
.
super
.
quit
();
RocketChatWebSocketThread
.
super
.
quit
();
emitter
.
onSuccess
(
true
);
emitter
.
onSuccess
(
true
);
});
});
});
});
}
else
{
}
else
{
connectivityManager
.
notifyConnectionLost
(
hostname
,
connectivityManager
.
notifyConnectionLost
(
hostname
,
ConnectivityManagerInternal
.
REASON_NETWORK_ERROR
);
DDPClient
.
REASON_NETWORK_ERROR
);
super
.
quit
();
super
.
quit
();
return
Single
.
just
(
true
);
return
Single
.
just
(
true
);
}
}
...
@@ -206,7 +207,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
...
@@ -206,7 +207,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
Exception
error
=
task
.
getError
();
Exception
error
=
task
.
getError
();
RCLog
.
e
(
error
);
RCLog
.
e
(
error
);
connectivityManager
.
notifyConnectionLost
(
connectivityManager
.
notifyConnectionLost
(
hostname
,
ConnectivityManagerInternal
.
REASON_NETWORK_ERRO
R
);
hostname
,
DDPClient
.
REASON_CLOSED_BY_USE
R
);
emitter
.
onError
(
error
);
emitter
.
onError
(
error
);
}
else
{
}
else
{
keepAliveTimer
.
update
();
keepAliveTimer
.
update
();
...
@@ -258,42 +259,43 @@ public class RocketChatWebSocketThread extends HandlerThread {
...
@@ -258,42 +259,43 @@ public class RocketChatWebSocketThread extends HandlerThread {
}
}
RCLog
.
d
(
"DDPClient#connect"
);
RCLog
.
d
(
"DDPClient#connect"
);
DDPClient
.
get
().
connect
(
hostname
,
info
.
getSession
(),
info
.
isSecure
())
DDPClient
.
get
().
connect
(
hostname
,
info
.
getSession
(),
info
.
isSecure
())
.
onSuccessTask
(
task
->
{
.
onSuccessTask
(
task
->
{
final
String
newSession
=
task
.
getResult
().
session
;
final
String
newSession
=
task
.
getResult
().
session
;
connectivityManager
.
notifyConnectionEstablished
(
hostname
,
newSession
);
connectivityManager
.
notifyConnectionEstablished
(
hostname
,
newSession
);
// handling WebSocket#onClose() callback.
// handling WebSocket#onClose() callback.
task
.
getResult
().
client
.
getOnCloseCallback
().
onSuccess
(
_task
->
{
task
.
getResult
().
client
.
getOnCloseCallback
().
onSuccess
(
_task
->
{
if
(
_task
.
getResult
().
code
!=
1000
)
{
RxWebSocketCallback
.
Close
result
=
_task
.
getResult
();
reconnect
();
if
(
result
.
code
==
DDPClient
.
REASON_NETWORK_ERROR
)
{
}
reconnect
();
return
null
;
}
});
return
null
;
});
return
realmHelper
.
executeTransaction
(
realm
->
{
RealmSession
sessionObj
=
RealmSession
.
queryDefaultSession
(
realm
).
findFirst
();
return
realmHelper
.
executeTransaction
(
realm
->
{
if
(
sessionObj
==
null
)
{
RealmSession
sessionObj
=
RealmSession
.
queryDefaultSession
(
realm
).
findFirst
();
realm
.
createOrUpdateObjectFromJson
(
RealmSession
.
class
,
if
(
sessionObj
==
null
)
{
new
JSONObject
().
put
(
RealmSession
.
ID
,
RealmSession
.
DEFAULT_ID
));
realm
.
createOrUpdateObjectFromJson
(
RealmSession
.
class
,
}
else
{
new
JSONObject
().
put
(
RealmSession
.
ID
,
RealmSession
.
DEFAULT_ID
));
// invalidate login token.
}
else
{
if
(!
TextUtils
.
isEmpty
(
sessionObj
.
getToken
())
&&
sessionObj
.
isTokenVerified
())
{
// invalidate login token.
sessionObj
.
setTokenVerified
(
false
);
if
(!
TextUtils
.
isEmpty
(
sessionObj
.
getToken
())
&&
sessionObj
.
isTokenVerified
())
{
sessionObj
.
setError
(
null
);
sessionObj
.
setTokenVerified
(
false
);
}
sessionObj
.
setError
(
null
);
}
}
}
return
null
;
return
null
;
});
});
})
})
.
continueWith
(
task
->
{
.
continueWith
(
task
->
{
if
(
task
.
isFaulted
())
{
if
(
task
.
isFaulted
())
{
emitter
.
onError
(
task
.
getError
());
emitter
.
onError
(
task
.
getError
());
}
else
{
}
else
{
emitter
.
onSuccess
(
true
);
emitter
.
onSuccess
(
true
);
}
}
return
null
;
return
null
;
});
});
}));
}));
}
}
...
@@ -318,8 +320,10 @@ public class RocketChatWebSocketThread extends HandlerThread {
...
@@ -318,8 +320,10 @@ public class RocketChatWebSocketThread extends HandlerThread {
error
->
{
error
->
{
logErrorAndUnsubscribe
(
reconnectSubscription
,
error
);
logErrorAndUnsubscribe
(
reconnectSubscription
,
error
);
connectivityManager
.
notifyConnectionLost
(
hostname
,
connectivityManager
.
notifyConnectionLost
(
hostname
,
ConnectivityManagerInternal
.
REASON_NETWORK_ERROR
);
DDPClient
.
REASON_CLOSED_BY_USER
);
new
Handler
(
getLooper
()).
post
(
this
::
unregisterListeners
);
if
(
isAlive
())
{
new
Handler
(
getLooper
()).
post
(
this
::
unregisterListeners
);
}
}
}
)
)
);
);
...
@@ -445,10 +449,8 @@ public class RocketChatWebSocketThread extends HandlerThread {
...
@@ -445,10 +449,8 @@ public class RocketChatWebSocketThread extends HandlerThread {
@DebugLog
@DebugLog
private
void
unregisterListenersAndClose
()
{
private
void
unregisterListenersAndClose
()
{
unregisterListeners
();
unregisterListeners
();
if
(
DDPClient
.
get
()
!=
null
)
{
DDPClient
.
get
().
close
();
DDPClient
.
get
().
close
();
}
}
}
@DebugLog
@DebugLog
...
...
app/src/main/java/chat/rocket/android/service/ServerConnectivity.java
View file @
739efd88
...
@@ -11,10 +11,18 @@ public class ServerConnectivity {
...
@@ -11,10 +11,18 @@ public class ServerConnectivity {
public
final
String
hostname
;
public
final
String
hostname
;
public
final
int
state
;
public
final
int
state
;
public
final
int
code
;
public
ServerConnectivity
(
String
hostname
,
int
state
)
{
ServerConnectivity
(
String
hostname
,
int
state
)
{
this
.
hostname
=
hostname
;
this
.
hostname
=
hostname
;
this
.
state
=
state
;
this
.
state
=
state
;
this
.
code
=
-
1
;
}
ServerConnectivity
(
String
hostname
,
int
state
,
int
code
)
{
this
.
hostname
=
hostname
;
this
.
state
=
state
;
this
.
code
=
code
;
}
}
/**
/**
...
...
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