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
abe34222
Commit
abe34222
authored
Dec 12, 2017
by
Leonardo Aramaki
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix reconnection loop issue when add new server
parent
65d5c3a7
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
527 additions
and
459 deletions
+527
-459
DDPClientImpl.java
.../src/main/java/chat/rocket/android_ddp/DDPClientImpl.java
+425
-398
ConnectionStatusManager.kt
.../main/java/chat/rocket/android/ConnectionStatusManager.kt
+30
-3
RocketChatCache.kt
app/src/main/java/chat/rocket/android/RocketChatCache.kt
+4
-4
MethodCallHelper.java
...c/main/java/chat/rocket/android/api/MethodCallHelper.java
+1
-1
LoginPresenter.kt
...t/rocket/android/fragment/server_config/LoginPresenter.kt
+25
-15
RealmBasedConnectivityManager.java
...rocket/android/service/RealmBasedConnectivityManager.java
+4
-0
RocketChatService.java
...n/java/chat/rocket/android/service/RocketChatService.java
+19
-20
RocketChatWebSocketThread.java
...hat/rocket/android/service/RocketChatWebSocketThread.java
+19
-18
No files found.
android-ddp/src/main/java/chat/rocket/android_ddp/DDPClientImpl.java
View file @
abe34222
This diff is collapsed.
Click to expand it.
app/src/main/java/chat/rocket/android/ConnectionStatusManager.kt
View file @
abe34222
...
@@ -11,6 +11,10 @@ object ConnectionStatusManager {
...
@@ -11,6 +11,10 @@ object ConnectionStatusManager {
}
}
private
const
val
DEBUG
=
false
private
const
val
DEBUG
=
false
private
val
DEFAULT_CALLBACK
=
object
:
TransitionCallback
{
override
fun
onTransitioned
(
success
:
Boolean
)
{
}
}
private
val
stateMachine
:
EnumStateMachine
<
State
>
private
val
stateMachine
:
EnumStateMachine
<
State
>
init
{
init
{
...
@@ -28,23 +32,46 @@ object ConnectionStatusManager {
...
@@ -28,23 +32,46 @@ object ConnectionStatusManager {
fun
currentState
()
=
stateMachine
.
currentState
()
fun
currentState
()
=
stateMachine
.
currentState
()
@Synchronized
@Synchronized
fun
setOnline
(
callback
:
TransitionCallback
)
{
fun
setOnline
(
callback
:
TransitionCallback
=
DEFAULT_CALLBACK
)
{
KeepAliveJob
.
cancelPendingJobRequests
()
KeepAliveJob
.
cancelPendingJobRequests
()
tryTransitionTo
(
State
.
ONLINE
,
callback
)
tryTransitionTo
(
State
.
ONLINE
,
callback
)
}
}
@Synchronized
@Synchronized
fun
setConnecting
(
callback
:
TransitionCallback
)
{
fun
setOnline
()
{
KeepAliveJob
.
cancelPendingJobRequests
()
tryTransitionTo
(
State
.
ONLINE
,
DEFAULT_CALLBACK
)
}
@Synchronized
fun
setConnecting
(
callback
:
TransitionCallback
=
DEFAULT_CALLBACK
)
{
KeepAliveJob
.
cancelPendingJobRequests
()
KeepAliveJob
.
cancelPendingJobRequests
()
tryTransitionTo
(
State
.
CONNECTING
,
callback
)
tryTransitionTo
(
State
.
CONNECTING
,
callback
)
}
}
@Synchronized
@Synchronized
fun
setConnectionError
(
callback
:
TransitionCallback
)
{
fun
setConnecting
()
{
KeepAliveJob
.
cancelPendingJobRequests
()
tryTransitionTo
(
State
.
CONNECTING
,
DEFAULT_CALLBACK
)
}
@Synchronized
fun
setConnectionError
(
callback
:
TransitionCallback
=
DEFAULT_CALLBACK
)
{
KeepAliveJob
.
schedule
()
KeepAliveJob
.
schedule
()
tryTransitionTo
(
State
.
OFFLINE
,
callback
)
tryTransitionTo
(
State
.
OFFLINE
,
callback
)
}
}
@Synchronized
fun
setConnectionError
()
{
KeepAliveJob
.
schedule
()
tryTransitionTo
(
State
.
OFFLINE
,
DEFAULT_CALLBACK
)
}
@Synchronized
fun
setOffline
()
{
stateMachine
.
reset
()
}
private
fun
tryTransitionTo
(
newState
:
State
,
callback
:
TransitionCallback
)
{
private
fun
tryTransitionTo
(
newState
:
State
,
callback
:
TransitionCallback
)
{
try
{
try
{
stateMachine
.
transition
(
newState
)
stateMachine
.
transition
(
newState
)
...
...
app/src/main/java/chat/rocket/android/RocketChatCache.kt
View file @
abe34222
...
@@ -72,7 +72,7 @@ object RocketChatCache {
...
@@ -72,7 +72,7 @@ object RocketChatCache {
return
getString
(
KEY_SELECTED_SERVER_HOSTNAME
,
null
)
return
getString
(
KEY_SELECTED_SERVER_HOSTNAME
,
null
)
}
}
fun
setSelectedRoomId
(
roomId
:
String
)
{
fun
setSelectedRoomId
(
roomId
:
String
?
)
{
try
{
try
{
val
jsonObject
=
getSelectedRoomIdJsonObject
()
val
jsonObject
=
getSelectedRoomIdJsonObject
()
jsonObject
.
put
(
getSelectedServerHostname
(),
roomId
)
jsonObject
.
put
(
getSelectedServerHostname
(),
roomId
)
...
@@ -81,7 +81,6 @@ object RocketChatCache {
...
@@ -81,7 +81,6 @@ object RocketChatCache {
RCLog
.
e
(
e
)
RCLog
.
e
(
e
)
Logger
.
report
(
e
)
Logger
.
report
(
e
)
}
}
}
}
@Throws
(
JSONException
::
class
)
@Throws
(
JSONException
::
class
)
...
@@ -234,10 +233,11 @@ object RocketChatCache {
...
@@ -234,10 +233,11 @@ object RocketChatCache {
fun
clearSelectedHostnameReferences
()
{
fun
clearSelectedHostnameReferences
()
{
val
hostname
=
getSelectedServerHostname
()
val
hostname
=
getSelectedServerHostname
()
if
(
hostname
!=
null
)
{
if
(
hostname
!=
null
)
{
setString
(
KEY_OPENED_ROOMS
,
null
)
removeSiteName
(
hostname
)
removeSiteName
(
hostname
)
removeHostname
(
hostname
)
removeHostname
(
hostname
)
removeSiteUrl
(
hostname
)
removeSiteUrl
(
hostname
)
setSelectedServerHostname
(
null
)
setSelectedServerHostname
(
getFirstLoggedHostnameIfAny
()
)
}
}
}
}
...
@@ -308,7 +308,7 @@ object RocketChatCache {
...
@@ -308,7 +308,7 @@ object RocketChatCache {
fun
setSessionToken
(
sessionToken
:
String
)
{
fun
setSessionToken
(
sessionToken
:
String
)
{
val
selectedServerHostname
=
getSelectedServerHostname
()
?:
val
selectedServerHostname
=
getSelectedServerHostname
()
?:
throw
IllegalStateException
(
"Trying to set sessionToken to null hostname"
)
throw
IllegalStateException
(
"Trying to set sessionToken to null hostname"
)
val
sessions
=
getS
essionToken
(
)
val
sessions
=
getS
tring
(
KEY_SESSION_TOKEN
,
null
)
try
{
try
{
val
jsonObject
=
if
(
sessions
==
null
)
JSONObject
()
else
JSONObject
(
sessions
)
val
jsonObject
=
if
(
sessions
==
null
)
JSONObject
()
else
JSONObject
(
sessions
)
jsonObject
.
put
(
selectedServerHostname
,
sessionToken
)
jsonObject
.
put
(
selectedServerHostname
,
sessionToken
)
...
...
app/src/main/java/chat/rocket/android/api/MethodCallHelper.java
View file @
abe34222
...
@@ -118,7 +118,7 @@ public class MethodCallHelper {
...
@@ -118,7 +118,7 @@ public class MethodCallHelper {
}
else
if
(
exception
instanceof
DDPClientCallback
.
RPC
.
Timeout
)
{
}
else
if
(
exception
instanceof
DDPClientCallback
.
RPC
.
Timeout
)
{
return
Task
.
forError
(
new
MethodCall
.
Timeout
());
return
Task
.
forError
(
new
MethodCall
.
Timeout
());
}
else
if
(
exception
instanceof
DDPClientCallback
.
Closed
)
{
}
else
if
(
exception
instanceof
DDPClientCallback
.
Closed
)
{
return
Task
.
forError
(
new
Exception
(
"Oops, your connection seems off..."
));
return
Task
.
forError
(
new
Exception
(
exception
.
getMessage
()
));
}
else
{
}
else
{
return
Task
.
forError
(
exception
);
return
Task
.
forError
(
exception
);
}
}
...
...
app/src/main/java/chat/rocket/android/fragment/server_config/LoginPresenter.kt
View file @
abe34222
...
@@ -17,6 +17,7 @@ import chat.rocket.core.models.PublicSetting
...
@@ -17,6 +17,7 @@ import chat.rocket.core.models.PublicSetting
import
chat.rocket.core.repositories.LoginServiceConfigurationRepository
import
chat.rocket.core.repositories.LoginServiceConfigurationRepository
import
chat.rocket.core.repositories.PublicSettingRepository
import
chat.rocket.core.repositories.PublicSettingRepository
import
com.hadisatrio.optional.Optional
import
com.hadisatrio.optional.Optional
import
io.reactivex.Completable
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.rxkotlin.subscribeBy
import
io.reactivex.rxkotlin.subscribeBy
...
@@ -74,25 +75,34 @@ class LoginPresenter(private val loginServiceConfigurationRepository: LoginServi
...
@@ -74,25 +75,34 @@ class LoginPresenter(private val loginServiceConfigurationRepository: LoginServi
}
}
private
fun
doLogin
(
username
:
String
,
password
:
String
,
optional
:
Optional
<
PublicSetting
>)
{
private
fun
doLogin
(
username
:
String
,
password
:
String
,
optional
:
Optional
<
PublicSetting
>)
{
call
(
username
,
password
,
optional
)
addSubscription
(
.
continueWith
(
object
:
Continuation
<
Void
,
Any
?>
{
Completable
.
create
{
override
fun
then
(
task
:
Task
<
Void
>?):
Any
?
{
call
(
username
,
password
,
optional
)
if
(
task
!=
null
&&
task
.
isFaulted
())
{
.
continueWith
(
object
:
Continuation
<
Void
,
Any
?>
{
view
.
hideLoader
()
override
fun
then
(
task
:
Task
<
Void
>?):
Any
?
{
if
(
task
!=
null
&&
task
.
isFaulted
())
{
view
.
hideLoader
()
val
error
=
task
.
getError
()
val
error
=
task
.
getError
()
error
?.
let
{
error
?.
let
{
if
(
error
is
TwoStepAuthException
)
{
if
(
error
is
TwoStepAuthException
)
{
view
.
showTwoStepAuth
()
view
.
showTwoStepAuth
()
}
else
{
}
else
{
view
.
showError
(
error
.
message
)
view
.
showError
(
error
.
message
)
}
}
return
Completable
.
complete
()
}
return
null
}
}
}
},
Task
.
UI_THREAD_EXECUTOR
)
}.
subscribeBy
(
onError
=
{
view
.
showError
(
it
.
message
)
}
}
return
null
)
}
)
},
Task
.
UI_THREAD_EXECUTOR
)
}
}
private
fun
call
(
username
:
String
,
password
:
String
,
optional
:
Optional
<
PublicSetting
>):
Task
<
Void
>
{
private
fun
call
(
username
:
String
,
password
:
String
,
optional
:
Optional
<
PublicSetting
>):
Task
<
Void
>
{
...
...
app/src/main/java/chat/rocket/android/service/RealmBasedConnectivityManager.java
View file @
abe34222
...
@@ -14,6 +14,7 @@ import java.util.Map;
...
@@ -14,6 +14,7 @@ import java.util.Map;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
import
chat.rocket.android.ConnectionStatusManager
;
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
;
...
@@ -260,6 +261,7 @@ import io.reactivex.subjects.BehaviorSubject;
...
@@ -260,6 +261,7 @@ import io.reactivex.subjects.BehaviorSubject;
private
Single
<
Boolean
>
connectToServer
(
String
hostname
)
{
private
Single
<
Boolean
>
connectToServer
(
String
hostname
)
{
return
Single
.
defer
(()
->
{
return
Single
.
defer
(()
->
{
if
(!
serverConnectivityList
.
containsKey
(
hostname
))
{
if
(!
serverConnectivityList
.
containsKey
(
hostname
))
{
ConnectionStatusManager
.
INSTANCE
.
setConnectionError
();
return
Single
.
error
(
new
IllegalArgumentException
(
"hostname not found"
));
return
Single
.
error
(
new
IllegalArgumentException
(
"hostname not found"
));
}
}
...
@@ -270,8 +272,10 @@ import io.reactivex.subjects.BehaviorSubject;
...
@@ -270,8 +272,10 @@ import io.reactivex.subjects.BehaviorSubject;
}
}
if
(
serviceInterface
!=
null
)
{
if
(
serviceInterface
!=
null
)
{
ConnectionStatusManager
.
INSTANCE
.
setConnecting
();
return
serviceInterface
.
ensureConnectionToServer
(
hostname
);
return
serviceInterface
.
ensureConnectionToServer
(
hostname
);
}
else
{
}
else
{
ConnectionStatusManager
.
INSTANCE
.
setConnectionError
();
return
Single
.
error
(
new
ThreadLooperNotPreparedException
(
"not prepared"
));
return
Single
.
error
(
new
ThreadLooperNotPreparedException
(
"not prepared"
));
}
}
});
});
...
...
app/src/main/java/chat/rocket/android/service/RocketChatService.java
View file @
abe34222
...
@@ -38,7 +38,8 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
...
@@ -38,7 +38,8 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
/**
/**
* ensure RocketChatService alive.
* ensure RocketChatService alive.
*/
*/
/*package*/
static
void
keepAlive
(
Context
context
)
{
/*package*/
static
void
keepAlive
(
Context
context
)
{
context
.
startService
(
new
Intent
(
context
,
RocketChatService
.
class
));
context
.
startService
(
new
Intent
(
context
,
RocketChatService
.
class
));
}
}
...
@@ -99,31 +100,29 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
...
@@ -99,31 +100,29 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
return
Single
.
defer
(()
->
{
return
Single
.
defer
(()
->
{
webSocketThreadLock
.
acquire
();
webSocketThreadLock
.
acquire
();
int
connectivityState
=
ConnectivityManager
.
getInstance
(
getApplicationContext
()).
getConnectivityState
(
hostname
);
int
connectivityState
=
ConnectivityManager
.
getInstance
(
getApplicationContext
()).
getConnectivityState
(
hostname
);
boolean
isDisconnected
=
connectivityState
<
ServerConnectivity
.
STATE_CONNECTED
;
boolean
isDisconnected
=
connectivityState
<
ServerConnectivity
.
STATE_CONNECTED
;
if
(
currentWebSocketThread
!=
null
&&
existsThreadForHostname
(
hostname
)
&&
!
isDisconnected
)
{
if
(
currentWebSocketThread
!=
null
&&
existsThreadForHostname
(
hostname
)
&&
!
isDisconnected
)
{
webSocketThreadLock
.
release
();
webSocketThreadLock
.
release
();
return
Single
.
just
(
currentWebSocketThread
);
return
Single
.
just
(
currentWebSocketThread
);
}
}
if
(
currentWebSocketThread
!=
null
)
{
if
(
currentWebSocketThread
!=
null
)
{
if
(
isDisconnected
)
{
boolean
hasFailed
=
existsThreadForHostname
(
hostname
);
return
currentWebSocketThread
.
terminate
(
true
)
return
currentWebSocketThread
.
terminate
(
hasFailed
)
.
doAfterTerminate
(()
->
currentWebSocketThread
=
null
)
.
doAfterTerminate
(()
->
currentWebSocketThread
=
null
)
.
flatMap
(
terminated
->
.
flatMap
(
terminated
->
RocketChatWebSocketThread
.
getStarted
(
getApplicationContext
(),
hostname
)
RocketChatWebSocketThread
.
getStarted
(
getApplicationContext
(),
hostname
)
.
doOnSuccess
(
thread
->
{
.
doOnSuccess
(
thread
->
{
currentWebSocketThread
=
thread
;
currentWebSocketThread
=
thread
;
webSocketThreadLock
.
release
();
webSocketThreadLock
.
release
();
})
})
.
doOnError
(
throwable
->
{
.
doOnError
(
throwable
->
{
currentWebSocketThread
=
null
;
currentWebSocketThread
=
null
;
RCLog
.
e
(
throwable
);
RCLog
.
e
(
throwable
);
Logger
.
INSTANCE
.
report
(
throwable
);
Logger
.
INSTANCE
.
report
(
throwable
);
webSocketThreadLock
.
release
();
webSocketThreadLock
.
release
();
})
})
);
);
}
return
Single
.
just
(
currentWebSocketThread
);
}
}
return
RocketChatWebSocketThread
.
getStarted
(
getApplicationContext
(),
hostname
)
return
RocketChatWebSocketThread
.
getStarted
(
getApplicationContext
(),
hostname
)
...
...
app/src/main/java/chat/rocket/android/service/RocketChatWebSocketThread.java
View file @
abe34222
...
@@ -14,6 +14,7 @@ import java.util.concurrent.TimeUnit;
...
@@ -14,6 +14,7 @@ import java.util.concurrent.TimeUnit;
import
java.util.concurrent.TimeoutException
;
import
java.util.concurrent.TimeoutException
;
import
bolts.Task
;
import
bolts.Task
;
import
chat.rocket.android.ConnectionStatusManager
;
import
chat.rocket.android.api.MethodCallHelper
;
import
chat.rocket.android.api.MethodCallHelper
;
import
chat.rocket.android.helper.LogIfError
;
import
chat.rocket.android.helper.LogIfError
;
import
chat.rocket.android.helper.RxHelper
;
import
chat.rocket.android.helper.RxHelper
;
...
@@ -123,26 +124,26 @@ public class RocketChatWebSocketThread extends HandlerThread {
...
@@ -123,26 +124,26 @@ public class RocketChatWebSocketThread extends HandlerThread {
}
}
/**
/**
* terminate WebSocket thread.
* Terminate WebSocket thread. If {@code hasFailed} is {@code true} it means that a connection was
* in progress but failed and got offline. If it's {@code false} means that the user explicitly
* disconnected from server either by logging out or by means of changing servers.
*
*
* @param
isDisconnected {@code true} If we're trying to terminate a disconnected a websocket
* @param
hasFailed {@code true} if the termination is due to a network error, otherwise
*
thread which means it has failed.
*
return false
*/
*/
@DebugLog
@DebugLog
/* package */
Single
<
Boolean
>
terminate
(
boolean
isDisconnect
ed
)
{
/* package */
Single
<
Boolean
>
terminate
(
boolean
hasFail
ed
)
{
if
(
isAlive
())
{
if
(
isAlive
())
{
return
Single
.
create
(
emitter
->
{
return
Single
.
create
(
emitter
->
new
Handler
(
getLooper
()).
post
(()
->
{
new
Handler
(
getLooper
()).
post
(()
->
{
RCLog
.
d
(
"thread %s: terminated()"
,
Thread
.
currentThread
().
getId
());
RCLog
.
d
(
"thread %s: terminated()"
,
Thread
.
currentThread
().
getId
());
int
reason
=
(
hasFailed
)
?
int
reason
=
(
isDisconnected
)
?
DDPClient
.
REASON_NETWORK_ERROR
:
DDPClient
.
REASON_CLOSED_BY_USER
;
DDPClient
.
REASON_NETWORK_ERROR
:
DDPClient
.
REASON_CLOSED_BY_USER
;
unregisterListenersAndClose
(
reason
);
unregisterListenersAndClose
(
reason
);
connectivityManager
.
notifyConnectionLost
(
hostname
,
reason
);
connectivityManager
.
notifyConnectionLost
(
hostname
,
RocketChatWebSocketThread
.
super
.
quit
();
isDisconnected
?
DDPClient
.
REASON_NETWORK_ERROR
:
DDPClient
.
REASON_CLOSED_BY_USER
);
ConnectionStatusManager
.
INSTANCE
.
setOffline
();
RocketChatWebSocketThread
.
super
.
quit
();
emitter
.
onSuccess
(
true
);
emitter
.
onSuccess
(
true
);
}));
});
});
}
else
{
}
else
{
connectivityManager
.
notifyConnectionLost
(
hostname
,
connectivityManager
.
notifyConnectionLost
(
hostname
,
DDPClient
.
REASON_NETWORK_ERROR
);
DDPClient
.
REASON_NETWORK_ERROR
);
...
@@ -166,7 +167,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
...
@@ -166,7 +167,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
@DebugLog
@DebugLog
/* package */
Single
<
Boolean
>
keepAlive
()
{
/* package */
Single
<
Boolean
>
keepAlive
()
{
return
checkIfConnectionAlive
()
return
checkIfConnectionAlive
()
.
flatMap
(
alive
->
alive
?
Single
.
just
(
true
)
:
connectWithExponentialBackoff
());
.
flatMap
(
alive
->
connectWithExponentialBackoff
());
}
}
@DebugLog
@DebugLog
...
@@ -227,7 +228,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
...
@@ -227,7 +228,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
.
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.
task
.
getResult
().
client
.
getOnCloseCallback
().
onSuccess
(
_task
->
{
task
.
getResult
().
client
.
getOnCloseCallback
().
onSuccess
(
_task
->
{
RxWebSocketCallback
.
Close
result
=
_task
.
getResult
();
RxWebSocketCallback
.
Close
result
=
_task
.
getResult
();
if
(
result
.
code
==
DDPClient
.
REASON_NETWORK_ERROR
)
{
if
(
result
.
code
==
DDPClient
.
REASON_NETWORK_ERROR
)
{
...
...
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