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
f6ccb19b
Commit
f6ccb19b
authored
Jul 27, 2017
by
Lucio Maciel
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into coding-style
parents
4232331f
3bcbbfbd
Changes
23
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
655 additions
and
273 deletions
+655
-273
DDPClientImpl.java
.../src/main/java/chat/rocket/android_ddp/DDPClientImpl.java
+64
-60
RxWebSocket.java
...src/main/java/chat/rocket/android_ddp/rx/RxWebSocket.java
+13
-6
RxWebSocketCallback.java
.../java/chat/rocket/android_ddp/rx/RxWebSocketCallback.java
+2
-21
build.gradle
app/build.gradle
+1
-1
MainActivity.java
.../main/java/chat/rocket/android/activity/MainActivity.java
+8
-3
MainPresenter.java
...main/java/chat/rocket/android/activity/MainPresenter.java
+25
-8
DDPClientWrapper.java
...c/main/java/chat/rocket/android/api/DDPClientWrapper.java
+3
-1
RoomContract.java
...a/chat/rocket/android/fragment/chatroom/RoomContract.java
+2
-0
RoomFragment.java
...a/chat/rocket/android/fragment/chatroom/RoomFragment.java
+14
-7
RoomPresenter.java
.../chat/rocket/android/fragment/chatroom/RoomPresenter.java
+4
-0
UsersOfRoomDialogFragment.java
...d/fragment/chatroom/dialog/UsersOfRoomDialogFragment.java
+1
-1
PushNotificationHandler.java
...ava/chat/rocket/android/push/PushNotificationHandler.java
+413
-131
ConnectivityManagerInternal.java
...t/rocket/android/service/ConnectivityManagerInternal.java
+2
-0
RealmBasedConnectivityManager.java
...rocket/android/service/RealmBasedConnectivityManager.java
+8
-0
RocketChatService.java
...n/java/chat/rocket/android/service/RocketChatService.java
+10
-1
RocketChatWebSocketThread.java
...hat/rocket/android/service/RocketChatWebSocketThread.java
+61
-17
ServerConnectivity.java
.../java/chat/rocket/android/service/ServerConnectivity.java
+1
-1
AbstractDDPDocEventSubscriber.java
...et/android/service/ddp/AbstractDDPDocEventSubscriber.java
+1
-1
AbstractRocketChatCacheObserver.java
...oid/service/internal/AbstractRocketChatCacheObserver.java
+2
-1
MethodCallObserver.java
...t/rocket/android/service/observer/MethodCallObserver.java
+7
-9
strings.xml
app/src/main/res/values/strings.xml
+8
-2
circle.yml
circle.yml
+1
-1
RocketChatWidgets.java
...in/java/chat/rocket/android/widget/RocketChatWidgets.java
+4
-1
No files found.
android-ddp/src/main/java/chat/rocket/android_ddp/DDPClientImpl.java
View file @
f6ccb19b
...
...
@@ -3,26 +3,29 @@ package chat.rocket.android_ddp;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
android.text.TextUtils
;
import
io.reactivex.Flowable
;
import
io.reactivex.disposables.CompositeDisposable
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeoutException
;
import
bolts.Task
;
import
bolts.TaskCompletionSource
;
import
chat.rocket.android.log.RCLog
;
import
chat.rocket.android_ddp.rx.RxWebSocket
;
import
chat.rocket.android_ddp.rx.RxWebSocketCallback
;
import
io.reactivex.Flowable
;
import
io.reactivex.disposables.CompositeDisposable
;
import
okhttp3.OkHttpClient
;
public
class
DDPClientImpl
{
private
final
DDPClient
client
;
private
final
RxWebSocket
websocket
;
private
RxWebSocket
websocket
;
private
Flowable
<
RxWebSocketCallback
.
Base
>
flowable
;
private
CompositeDisposable
subscriptions
;
private
CompositeDisposable
disposables
;
private
String
currentSession
;
public
DDPClientImpl
(
DDPClient
self
,
OkHttpClient
client
)
{
websocket
=
new
RxWebSocket
(
client
);
...
...
@@ -51,26 +54,24 @@ public class DDPClientImpl {
public
void
connect
(
final
TaskCompletionSource
<
DDPClientCallback
.
Connect
>
task
,
final
String
url
,
String
session
)
{
try
{
flowable
=
websocket
.
connect
(
url
).
autoConnect
();
CompositeDisposable
subscription
s
=
new
CompositeDisposable
();
flowable
=
websocket
.
connect
(
url
).
autoConnect
(
2
);
CompositeDisposable
disposable
s
=
new
CompositeDisposable
();
subscription
s
.
add
(
flowable
.
filter
(
callback
->
callback
instanceof
RxWebSocketCallback
.
Open
)
disposable
s
.
add
(
flowable
.
retry
().
filter
(
callback
->
callback
instanceof
RxWebSocketCallback
.
Open
)
.
subscribe
(
callback
->
{
callback
->
sendMessage
(
"connect"
,
json
->
(
TextUtils
.
isEmpty
(
session
)
?
json
:
json
.
put
(
"session"
,
s
ession
))
json
->
(
TextUtils
.
isEmpty
(
session
)
?
json
:
json
.
put
(
"session"
,
DDPClientImpl
.
this
.
currentS
ession
))
.
put
(
"version"
,
"pre2"
)
.
put
(
"support"
,
new
JSONArray
().
put
(
"pre2"
).
put
(
"pre1"
)),
task
);
},
err
->
{
}
task
),
RCLog:
:
e
)
);
subscription
s
.
add
(
disposable
s
.
add
(
flowable
.
filter
(
callback
->
callback
instanceof
RxWebSocketCallback
.
Message
)
.
map
(
callback
->
((
RxWebSocketCallback
.
Message
)
callback
).
responseBodyString
)
...
...
@@ -79,24 +80,25 @@ public class DDPClientImpl {
.
subscribe
(
response
->
{
String
msg
=
extractMsg
(
response
);
if
(
"connected"
.
equals
(
msg
)
&&
!
response
.
isNull
(
"session"
))
{
currentSession
=
response
.
optString
(
"session"
);
task
.
trySetResult
(
new
DDPClientCallback
.
Connect
(
client
,
response
.
optString
(
"session"
)));
subscriptions
.
dispose
();
disposables
.
clear
();
}
else
if
(
"error"
.
equals
(
msg
)
&&
"Already connected"
.
equals
(
response
.
optString
(
"reason"
)))
{
task
.
trySetResult
(
new
DDPClientCallback
.
Connect
(
client
,
null
));
subscriptions
.
dispose
();
disposables
.
clear
();
}
else
if
(
"failed"
.
equals
(
msg
))
{
task
.
trySetError
(
new
DDPClientCallback
.
Connect
.
Failed
(
client
,
response
.
optString
(
"version"
)));
subscriptions
.
dispose
();
disposables
.
clear
();
}
},
err
->
task
.
trySetError
(
new
DDPClientCallback
.
Connect
.
Timeout
(
client
))
)
);
addErrorCallback
(
subscription
s
,
task
);
addErrorCallback
(
disposable
s
,
task
);
subscribeBaseListeners
();
}
catch
(
Exception
e
)
{
...
...
@@ -112,34 +114,35 @@ public class DDPClientImpl {
sendMessage
(
"ping"
,
json
->
json
.
put
(
"id"
,
id
));
if
(
requested
)
{
CompositeDisposable
subscription
s
=
new
CompositeDisposable
();
CompositeDisposable
disposable
s
=
new
CompositeDisposable
();
subscription
s
.
add
(
disposable
s
.
add
(
flowable
.
filter
(
callback
->
callback
instanceof
RxWebSocketCallback
.
Message
)
.
timeout
(
8
,
TimeUnit
.
SECONDS
)
.
map
(
callback
->
((
RxWebSocketCallback
.
Message
)
callback
).
responseBodyString
)
.
map
(
DDPClientImpl:
:
toJson
)
.
timeout
(
4
,
TimeUnit
.
SECONDS
)
.
subscribe
(
response
->
{
String
msg
=
extractMsg
(
response
);
if
(
"pong"
.
equals
(
msg
))
{
if
(
response
.
isNull
(
"id"
))
{
task
.
setResult
(
new
DDPClientCallback
.
Ping
(
client
,
null
));
subscriptions
.
dispose
();
disposables
.
clear
();
}
else
{
String
_id
=
response
.
optString
(
"id"
);
if
(
id
.
equals
(
_id
))
{
task
.
setResult
(
new
DDPClientCallback
.
Ping
(
client
,
id
));
subscriptions
.
dispose
();
disposables
.
clear
();
}
}
disposables
.
clear
();
}
},
err
->
task
.
setError
(
new
DDPClientCallback
.
Ping
.
Timeout
(
client
))
)
);
addErrorCallback
(
subscription
s
,
task
);
addErrorCallback
(
disposable
s
,
task
);
}
else
{
task
.
trySetError
(
new
DDPClientCallback
.
Closed
(
client
));
}
...
...
@@ -151,9 +154,9 @@ public class DDPClientImpl {
sendMessage
(
"sub"
,
json
->
json
.
put
(
"id"
,
id
).
put
(
"name"
,
name
).
put
(
"params"
,
params
));
if
(
requested
)
{
CompositeDisposable
subscription
s
=
new
CompositeDisposable
();
CompositeDisposable
disposable
s
=
new
CompositeDisposable
();
subscription
s
.
add
(
disposable
s
.
add
(
flowable
.
filter
(
callback
->
callback
instanceof
RxWebSocketCallback
.
Message
)
.
map
(
callback
->
((
RxWebSocketCallback
.
Message
)
callback
).
responseBodyString
)
.
map
(
DDPClientImpl:
:
toJson
)
...
...
@@ -166,7 +169,7 @@ public class DDPClientImpl {
String
_id
=
ids
.
optString
(
i
);
if
(
id
.
equals
(
_id
))
{
task
.
setResult
(
new
DDPSubscription
.
Ready
(
client
,
id
));
subscriptions
.
dispose
();
disposables
.
clear
();
break
;
}
}
...
...
@@ -176,16 +179,15 @@ public class DDPClientImpl {
if
(
id
.
equals
(
_id
))
{
task
.
setError
(
new
DDPSubscription
.
NoSub
.
Error
(
client
,
id
,
response
.
optJSONObject
(
"error"
)));
subscriptions
.
dispose
();
disposables
.
clear
();
}
}
},
err
->
{
}
RCLog:
:
e
)
);
addErrorCallback
(
subscription
s
,
task
);
addErrorCallback
(
disposable
s
,
task
);
}
else
{
task
.
trySetError
(
new
DDPClientCallback
.
Closed
(
client
));
}
...
...
@@ -197,9 +199,9 @@ public class DDPClientImpl {
final
boolean
requested
=
sendMessage
(
"unsub"
,
json
->
json
.
put
(
"id"
,
id
));
if
(
requested
)
{
CompositeDisposable
subscription
s
=
new
CompositeDisposable
();
CompositeDisposable
disposable
s
=
new
CompositeDisposable
();
subscription
s
.
add
(
disposable
s
.
add
(
flowable
.
filter
(
callback
->
callback
instanceof
RxWebSocketCallback
.
Message
)
.
map
(
callback
->
((
RxWebSocketCallback
.
Message
)
callback
).
responseBodyString
)
.
map
(
DDPClientImpl:
:
toJson
)
...
...
@@ -210,7 +212,7 @@ public class DDPClientImpl {
String
_id
=
response
.
optString
(
"id"
);
if
(
id
.
equals
(
_id
))
{
task
.
setResult
(
new
DDPSubscription
.
NoSub
(
client
,
id
));
subscriptions
.
dispose
();
disposables
.
clear
();
}
}
},
...
...
@@ -219,7 +221,7 @@ public class DDPClientImpl {
)
);
addErrorCallback
(
subscription
s
,
task
);
addErrorCallback
(
disposable
s
,
task
);
}
else
{
task
.
trySetError
(
new
DDPClientCallback
.
Closed
(
client
));
}
...
...
@@ -232,9 +234,9 @@ public class DDPClientImpl {
json
->
json
.
put
(
"method"
,
method
).
put
(
"params"
,
params
).
put
(
"id"
,
id
));
if
(
requested
)
{
CompositeDisposable
subscription
s
=
new
CompositeDisposable
();
CompositeDisposable
disposable
s
=
new
CompositeDisposable
();
subscription
s
.
add
(
disposable
s
.
add
(
flowable
.
filter
(
callback
->
callback
instanceof
RxWebSocketCallback
.
Message
)
.
map
(
callback
->
((
RxWebSocketCallback
.
Message
)
callback
).
responseBodyString
)
.
map
(
DDPClientImpl:
:
toJson
)
...
...
@@ -252,7 +254,7 @@ public class DDPClientImpl {
String
result
=
response
.
optString
(
"result"
);
task
.
setResult
(
new
DDPClientCallback
.
RPC
(
client
,
id
,
result
));
}
subscriptions
.
dispose
();
disposables
.
clear
();
}
}
},
...
...
@@ -264,20 +266,20 @@ public class DDPClientImpl {
)
);
addErrorCallback
(
subscription
s
,
task
);
addErrorCallback
(
disposable
s
,
task
);
}
else
{
task
.
trySetError
(
new
DDPClientCallback
.
Closed
(
client
));
}
}
private
void
subscribeBaseListeners
()
{
if
(
subscription
s
!=
null
&&
subscriptions
.
size
()
>
0
&&
!
subscription
s
.
isDisposed
())
{
if
(
disposable
s
!=
null
&&
disposables
.
size
()
>
0
&&
!
disposable
s
.
isDisposed
())
{
return
;
}
subscription
s
=
new
CompositeDisposable
();
subscription
s
.
add
(
disposable
s
=
new
CompositeDisposable
();
disposable
s
.
add
(
flowable
.
filter
(
callback
->
callback
instanceof
RxWebSocketCallback
.
Message
)
.
map
(
callback
->
((
RxWebSocketCallback
.
Message
)
callback
).
responseBodyString
)
.
map
(
DDPClientImpl:
:
toJson
)
...
...
@@ -292,8 +294,7 @@ public class DDPClientImpl {
}
}
},
err
->
{
}
RCLog:
:
e
)
);
}
...
...
@@ -342,8 +343,8 @@ public class DDPClientImpl {
}
public
void
unsubscribeBaseListeners
()
{
if
(
subscriptions
.
size
()
>
0
||
!
subscription
s
.
isDisposed
())
{
subscriptions
.
dispose
();
if
(
disposables
.
size
()
>
0
||
!
disposable
s
.
isDisposed
())
{
disposables
.
clear
();
}
}
...
...
@@ -354,13 +355,7 @@ public class DDPClientImpl {
.
cast
(
RxWebSocketCallback
.
Close
.
class
)
.
subscribe
(
task:
:
setResult
,
err
->
{
if
(
err
instanceof
Exception
)
{
task
.
setError
((
Exception
)
err
);
}
else
{
task
.
setError
(
new
Exception
(
err
));
}
}
err
->
setTaskError
(
task
,
err
)
);
return
task
.
getTask
().
onSuccessTask
(
_task
->
{
...
...
@@ -373,28 +368,29 @@ public class DDPClientImpl {
try
{
JSONObject
origJson
=
new
JSONObject
().
put
(
"msg"
,
msg
);
String
msg2
=
(
json
==
null
?
origJson
:
json
.
create
(
origJson
)).
toString
();
return
websocket
.
sendText
(
msg2
);
websocket
.
sendText
(
msg2
);
}
catch
(
Exception
e
)
{
RCLog
.
e
(
e
);
return
false
;
}
return
true
;
// ignore exception here.
}
private
void
sendMessage
(
String
msg
,
@Nullable
JSONBuilder
json
,
TaskCompletionSource
<?>
taskForSetError
)
{
if
(!
sendMessage
(
msg
,
json
))
{
if
(!
sendMessage
(
msg
,
json
)
&&
taskForSetError
!=
null
)
{
taskForSetError
.
trySetError
(
new
DDPClientCallback
.
Closed
(
client
));
}
}
private
void
addErrorCallback
(
CompositeDisposable
subscription
s
,
TaskCompletionSource
<?>
task
)
{
subscription
s
.
add
(
private
void
addErrorCallback
(
CompositeDisposable
disposable
s
,
TaskCompletionSource
<?>
task
)
{
disposable
s
.
add
(
flowable
.
subscribe
(
base
->
{
},
err
->
{
task
.
trySetError
(
new
Exception
(
err
));
subscriptions
.
dispose
();
disposables
.
clear
();
}
)
);
...
...
@@ -408,6 +404,14 @@ public class DDPClientImpl {
}
}
private
void
setTaskError
(
TaskCompletionSource
<?
extends
RxWebSocketCallback
.
Base
>
task
,
Throwable
throwable
)
{
if
(
throwable
instanceof
Exception
)
{
task
.
setError
((
Exception
)
throwable
);
}
else
{
task
.
setError
(
new
Exception
(
throwable
));
}
}
private
interface
JSONBuilder
{
@NonNull
JSONObject
create
(
JSONObject
root
)
throws
JSONException
;
...
...
android-ddp/src/main/java/chat/rocket/android_ddp/rx/RxWebSocket.java
View file @
f6ccb19b
package
chat
.
rocket
.
android_ddp
.
rx
;
import
java.io.IOException
;
import
java.util.concurrent.TimeUnit
;
import
chat.rocket.android.log.RCLog
;
import
io.reactivex.BackpressureStrategy
;
import
io.reactivex.Flowable
;
import
io.reactivex.FlowableOnSubscribe
;
import
io.reactivex.exceptions.OnErrorNotImplementedException
;
import
io.reactivex.flowables.ConnectableFlowable
;
import
java.io.IOException
;
import
chat.rocket.android.log.RCLog
;
import
okhttp3.OkHttpClient
;
import
okhttp3.Request
;
import
okhttp3.Response
;
...
...
@@ -15,8 +16,10 @@ import okhttp3.WebSocket;
import
okhttp3.WebSocketListener
;
public
class
RxWebSocket
{
public
static
final
int
REASON_NETWORK_ERROR
=
100
;
private
OkHttpClient
httpClient
;
private
WebSocket
webSocket
;
private
boolean
hadErrorsBefore
;
public
RxWebSocket
(
OkHttpClient
client
)
{
httpClient
=
client
;
...
...
@@ -30,6 +33,7 @@ public class RxWebSocket {
.
newWebSocket
(
request
,
new
WebSocketListener
()
{
@Override
public
void
onOpen
(
WebSocket
webSocket
,
Response
response
)
{
hadErrorsBefore
=
false
;
RxWebSocket
.
this
.
webSocket
=
webSocket
;
emitter
.
onNext
(
new
RxWebSocketCallback
.
Open
(
RxWebSocket
.
this
.
webSocket
,
response
));
}
...
...
@@ -37,7 +41,11 @@ public class RxWebSocket {
@Override
public
void
onFailure
(
WebSocket
webSocket
,
Throwable
err
,
Response
response
)
{
try
{
emitter
.
onError
(
new
RxWebSocketCallback
.
Failure
(
webSocket
,
err
,
response
));
if
(!
hadErrorsBefore
)
{
hadErrorsBefore
=
true
;
emitter
.
onNext
(
new
RxWebSocketCallback
.
Close
(
webSocket
,
REASON_NETWORK_ERROR
,
err
.
getMessage
()));
emitter
.
onComplete
();
}
}
catch
(
OnErrorNotImplementedException
ex
)
{
RCLog
.
w
(
ex
,
"OnErrorNotImplementedException ignored"
);
}
...
...
@@ -51,11 +59,10 @@ public class RxWebSocket {
@Override
public
void
onClosed
(
WebSocket
webSocket
,
int
code
,
String
reason
)
{
emitter
.
onNext
(
new
RxWebSocketCallback
.
Close
(
webSocket
,
code
,
reason
));
emitter
.
onComplete
();
}
}),
BackpressureStrategy
.
BUFFER
).
publish
();
).
delay
(
4
,
TimeUnit
.
SECONDS
).
publish
();
}
public
boolean
sendText
(
String
message
)
throws
IOException
{
...
...
android-ddp/src/main/java/chat/rocket/android_ddp/rx/RxWebSocketCallback.java
View file @
f6ccb19b
package
chat
.
rocket
.
android_ddp
.
rx
;
import
static
android
.
R
.
attr
.
type
;
import
chat.rocket.android.log.RCLog
;
import
okhttp3.Response
;
import
okhttp3.WebSocket
;
...
...
@@ -28,25 +26,8 @@ public class RxWebSocketCallback {
public
Open
(
WebSocket
websocket
,
Response
response
)
{
super
(
"Open"
,
websocket
);
this
.
response
=
response
;
}
}
public
static
class
Failure
extends
Exception
{
public
WebSocket
ws
;
public
Response
response
;
public
Failure
(
WebSocket
websocket
,
Throwable
err
,
Response
response
)
{
super
(
err
);
this
.
ws
=
websocket
;
this
.
response
=
response
;
}
@Override
public
String
toString
()
{
if
(
response
!=
null
)
{
return
"["
+
type
+
"] "
+
response
.
message
();
}
else
{
return
super
.
toString
();
if
(
response
!=
null
&&
response
.
body
()
!=
null
)
{
this
.
response
.
body
().
close
();
}
}
}
...
...
app/build.gradle
View file @
f6ccb19b
...
...
@@ -35,7 +35,7 @@ android {
applicationId
"chat.rocket.android"
minSdkVersion
16
targetSdkVersion
rootProject
.
ext
.
targetSdkVersion
versionCode
2
6
versionCode
2
7
versionName
"1.0.16"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
...
...
app/src/main/java/chat/rocket/android/activity/MainActivity.java
View file @
f6ccb19b
...
...
@@ -16,11 +16,11 @@ import chat.rocket.android.fragment.chatroom.HomeFragment;
import
chat.rocket.android.fragment.chatroom.RoomFragment
;
import
chat.rocket.android.fragment.sidebar.SidebarMainFragment
;
import
chat.rocket.android.helper.KeyboardHelper
;
import
chat.rocket.android.service.ConnectivityManager
;
import
chat.rocket.android.widget.RoomToolbar
;
import
chat.rocket.core.interactors.CanCreateRoomInteractor
;
import
chat.rocket.core.interactors.RoomInteractor
;
import
chat.rocket.core.interactors.SessionInteractor
;
import
chat.rocket.android.service.ConnectivityManager
;
import
chat.rocket.android.widget.RoomToolbar
;
import
chat.rocket.persistence.realm.repositories.RealmRoomRepository
;
import
chat.rocket.persistence.realm.repositories.RealmSessionRepository
;
import
chat.rocket.persistence.realm.repositories.RealmUserRepository
;
...
...
@@ -34,6 +34,7 @@ public class MainActivity extends AbstractAuthedActivity implements MainContract
private
StatusTicker
statusTicker
;
private
MainContract
.
Presenter
presenter
;
private
RoomFragment
roomFragment
;
@Override
protected
int
getLayoutContainerForFragment
()
{
...
...
@@ -179,7 +180,8 @@ public class MainActivity extends AbstractAuthedActivity implements MainContract
@Override
public
void
showRoom
(
String
hostname
,
String
roomId
)
{
showFragment
(
RoomFragment
.
create
(
hostname
,
roomId
));
roomFragment
=
RoomFragment
.
create
(
hostname
,
roomId
);
showFragment
(
roomFragment
);
closeSidebarIfNeeded
();
KeyboardHelper
.
hideSoftKeyboard
(
this
);
}
...
...
@@ -222,6 +224,9 @@ public class MainActivity extends AbstractAuthedActivity implements MainContract
@Override
public
void
showConnectionOk
()
{
statusTicker
.
updateStatus
(
StatusTicker
.
STATUS_DISMISS
,
null
);
if
(
roomFragment
!=
null
)
{
roomFragment
.
refreshRoom
();
}
}
//TODO: consider this class to define in layouthelper for more complicated operation.
...
...
app/src/main/java/chat/rocket/android/activity/MainPresenter.java
View file @
f6ccb19b
...
...
@@ -3,22 +3,23 @@ package chat.rocket.android.activity;
import
android.support.annotation.NonNull
;
import
android.support.v4.util.Pair
;
import
io.reactivex.Flowable
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.disposables.Disposable
;
import
chat.rocket.android.BackgroundLooper
;
import
chat.rocket.android.RocketChatCache
;
import
chat.rocket.android.api.MethodCallHelper
;
import
chat.rocket.android.helper.LogIfError
;
import
chat.rocket.android.helper.Logger
;
import
chat.rocket.android.service.ConnectivityManagerApi
;
import
chat.rocket.android.service.ServerConnectivity
;
import
chat.rocket.android.shared.BasePresenter
;
import
chat.rocket.core.interactors.CanCreateRoomInteractor
;
import
chat.rocket.core.interactors.RoomInteractor
;
import
chat.rocket.core.interactors.SessionInteractor
;
import
chat.rocket.core.models.Session
;
import
chat.rocket.core.models.User
;
import
hu.akarnokd.rxjava.interop.RxJavaInterop
;
import
io.reactivex.Flowable
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.disposables.Disposable
;
public
class
MainPresenter
extends
BasePresenter
<
MainContract
.
View
>
implements
MainContract
.
Presenter
{
...
...
@@ -63,6 +64,7 @@ public class MainPresenter extends BasePresenter<MainContract.View>
openRoom
();
subscribeToNetworkChanges
();
subscribeToUnreadCount
();
subscribeToSession
();
setUserOnline
();
...
...
@@ -96,10 +98,8 @@ public class MainPresenter extends BasePresenter<MainContract.View>
@Override
public
void
onRetryLogin
()
{
final
Disposable
subscription
=
sessionInteractor
.
retryLogin
()
.
subscribe
();
addSubscription
(
subscription
);
view
.
showConnecting
();
connectivityManagerApi
.
keepAliveServer
();
}
private
void
openRoom
()
{
...
...
@@ -161,6 +161,23 @@ public class MainPresenter extends BasePresenter<MainContract.View>
addSubscription
(
subscription
);
}
private
void
subscribeToNetworkChanges
()
{
Disposable
disposable
=
RxJavaInterop
.
toV2Flowable
(
connectivityManagerApi
.
getServerConnectivityAsObservable
())
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
subscribe
(
connectivity
->
{
if
(
connectivity
.
state
==
ServerConnectivity
.
STATE_CONNECTED
)
{
view
.
showConnectionOk
();
return
;
}
view
.
showConnecting
();
},
Logger:
:
report
);
addSubscription
(
disposable
);
}
private
void
setUserOnline
()
{
methodCallHelper
.
setUserPresence
(
User
.
STATUS_ONLINE
)
.
continueWith
(
new
LogIfError
());
...
...
app/src/main/java/chat/rocket/android/api/DDPClientWrapper.java
View file @
f6ccb19b
package
chat
.
rocket
.
android
.
api
;
import
android.support.annotation.Nullable
;
import
io.reactivex.Flowable
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
java.util.UUID
;
import
bolts.Task
;
import
chat.rocket.android.helper.OkHttpHelper
;
import
chat.rocket.android.helper.TextUtils
;
...
...
@@ -13,6 +14,7 @@ import chat.rocket.android.log.RCLog;
import
chat.rocket.android_ddp.DDPClient
;
import
chat.rocket.android_ddp.DDPClientCallback
;
import
chat.rocket.android_ddp.DDPSubscription
;
import
io.reactivex.Flowable
;
/**
* DDP client wrapper.
...
...
app/src/main/java/chat/rocket/android/fragment/chatroom/RoomContract.java
View file @
f6ccb19b
...
...
@@ -49,5 +49,7 @@ public interface RoomContract {
void
onUnreadCount
();
void
onMarkAsRead
();
void
refreshRoom
();
}
}
app/src/main/java/chat/rocket/android/fragment/chatroom/RoomFragment.java
View file @
f6ccb19b
...
...
@@ -21,6 +21,14 @@ import android.support.v7.widget.LinearLayoutManager;
import
android.support.v7.widget.RecyclerView
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
com.fernandocejas.arrow.optional.Optional
;
import
com.jakewharton.rxbinding2.support.v4.widget.RxDrawerLayout
;
import
java.lang.reflect.Field
;
import
java.util.ArrayList
;
import
java.util.List
;
import
chat.rocket.android.BackgroundLooper
;
import
chat.rocket.android.R
;
import
chat.rocket.android.api.MethodCallHelper
;
...
...
@@ -70,15 +78,10 @@ import chat.rocket.persistence.realm.repositories.RealmSessionRepository;
import
chat.rocket.persistence.realm.repositories.RealmSpotlightRoomRepository
;
import
chat.rocket.persistence.realm.repositories.RealmSpotlightUserRepository
;
import
chat.rocket.persistence.realm.repositories.RealmUserRepository
;
import
com.fernandocejas.arrow.optional.Optional
;
import
com.jakewharton.rxbinding2.support.v4.widget.RxDrawerLayout
;
import
io.reactivex.Single
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.disposables.CompositeDisposable
;
import
io.reactivex.disposables.Disposable
;
import
java.lang.reflect.Field
;
import
java.util.ArrayList
;
import
java.util.List
;
import
permissions.dispatcher.NeedsPermission
;
import
permissions.dispatcher.RuntimePermissions
;
...
...
@@ -251,8 +254,8 @@ public class RoomFragment extends AbstractChatRoomFragment implements
protected
Snackbar
getUnreadCountIndicatorView
(
int
count
)
{
// TODO: replace with another custom View widget, not to hide message composer.
final
String
caption
=
getResources
().
getString
(
R
.
string
.
fmt_dialog_view_latest_message_title
,
count
);
final
String
caption
=
getResources
().
get
Quantity
String
(
R
.
plurals
.
fmt_dialog_view_latest_message_title
,
count
,
count
);
return
Snackbar
.
make
(
rootView
,
caption
,
Snackbar
.
LENGTH_LONG
)
.
setAction
(
R
.
string
.
dialog_view_latest_message_action
,
view
->
scrollToLatestMessage
());
...
...
@@ -599,4 +602,8 @@ public class RoomFragment extends AbstractChatRoomFragment implements
edittingMessage
=
message
;
messageFormManager
.
setEditMessage
(
message
.
getMessage
());
}
public
void
refreshRoom
()
{
presenter
.
loadMessages
();
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/fragment/chatroom/RoomPresenter.java
View file @
f6ccb19b
...
...
@@ -55,7 +55,11 @@ public class RoomPresenter extends BasePresenter<RoomContract.View>
@Override
public
void
bindView
(
@NonNull
RoomContract
.
View
view
)
{
super
.
bindView
(
view
);
refreshRoom
();
}
@Override
public
void
refreshRoom
()
{
getRoomRoles
();
getRoomInfo
();
getRoomHistoryStateInfo
();
...
...
app/src/main/java/chat/rocket/android/fragment/chatroom/dialog/UsersOfRoomDialogFragment.java
View file @
f6ccb19b
...
...
@@ -192,7 +192,7 @@ public class UsersOfRoomDialogFragment extends AbstractChatRoomDialogFragment {
*/
private
void
onRenderTotalCount
(
long
total
)
{
TextView
userCount
=
(
TextView
)
getDialog
().
findViewById
(
R
.
id
.
room_user_count
);
userCount
.
setText
(
get
String
(
R
.
string
.
fmt_room_user_count
,
total
));
userCount
.
setText
(
get
Resources
().
getQuantityString
(
R
.
plurals
.
fmt_room_user_count
,
(
int
)
total
,
total
));
}
/**
...
...
app/src/main/java/chat/rocket/android/push/PushNotificationHandler.java
View file @
f6ccb19b
package
chat
.
rocket
.
android
.
push
;
import
android.app.Notification
;
import
android.app.NotificationChannel
;
import
android.app.NotificationManager
;
import
android.app.PendingIntent
;
import
android.content.ContentResolver
;
...
...
@@ -13,13 +14,16 @@ import android.graphics.Bitmap;
import
android.graphics.BitmapFactory
;
import
android.graphics.Color
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.os.Bundle
;
import
android.support.annotation.RequiresApi
;
import
android.support.v4.app.NotificationCompat
;
import
android.support.v4.app.RemoteInput
;
import
android.support.v4.util.SparseArrayCompat
;
import
android.text.Html
;
import
android.text.Spanned
;
import
android.util.Log
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
...
...
@@ -31,6 +35,7 @@ import java.net.URL;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Random
;
import
chat.rocket.android.activity.MainActivity
;
import
chat.rocket.android.helper.ServerPolicyHelper
;
import
chat.rocket.android.service.ConnectivityManager
;
...
...
@@ -93,7 +98,7 @@ public class PushNotificationHandler implements PushConstants {
}
public
void
createNotification
(
Context
context
,
Bundle
extras
)
{
NotificationManager
mN
otificationManager
=
NotificationManager
n
otificationManager
=
(
NotificationManager
)
context
.
getSystemService
(
Context
.
NOTIFICATION_SERVICE
);
String
appName
=
getAppName
(
context
);
String
packageName
=
context
.
getPackageName
();
...
...
@@ -117,13 +122,6 @@ public class PushNotificationHandler implements PushConstants {
PendingIntent
contentIntent
=
PendingIntent
.
getActivity
(
context
,
requestCode
,
notificationIntent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
);
NotificationCompat
.
Builder
notificationBuilder
=
new
NotificationCompat
.
Builder
(
context
)
.
setWhen
(
System
.
currentTimeMillis
())
.
setContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)))
.
setTicker
(
fromHtml
(
extras
.
getString
(
TITLE
)))
.
setContentIntent
(
contentIntent
)
.
setAutoCancel
(
true
);
SharedPreferences
prefs
=
context
.
getSharedPreferences
(
PushConstants
.
COM_ADOBE_PHONEGAP_PUSH
,
Context
.
MODE_PRIVATE
);
String
localIcon
=
prefs
.
getString
(
ICON
,
null
);
...
...
@@ -135,91 +133,62 @@ public class PushNotificationHandler implements PushConstants {
Log
.
d
(
LOG_TAG
,
"stored sound="
+
soundOption
);
Log
.
d
(
LOG_TAG
,
"stored vibrate="
+
vibrateOption
);
/*
* Notification Vibration
*/
setNotificationVibration
(
extras
,
vibrateOption
,
notificationBuilder
);
if
(
Build
.
VERSION
.
SDK_INT
>=
26
)
{
String
channelId
=
"rocket-chat-channel"
;
CharSequence
name
=
"RocketChatMessage"
;
int
importance
=
NotificationManager
.
IMPORTANCE_HIGH
;
NotificationChannel
channel
=
new
NotificationChannel
(
channelId
,
name
,
importance
);
channel
.
enableLights
(
true
);
notificationManager
.
createNotificationChannel
(
channel
);
/*
* Notification Icon Color
*
* Sets the small-icon background color of the notification.
* To use, add the `iconColor` key to plugin android options
*
*/
setNotificationIconColor
(
extras
.
getString
(
"color"
),
notificationBuilder
,
localIconColor
);
Notification
.
Builder
notificationBuilder
=
new
Notification
.
Builder
(
context
,
channelId
)
.
setWhen
(
System
.
currentTimeMillis
())
.
setContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)))
.
setTicker
(
fromHtml
(
extras
.
getString
(
TITLE
)))
.
setContentIntent
(
contentIntent
)
.
setChannelId
(
channelId
)
.
setAutoCancel
(
true
);
/*
* Notification Icon
*
* Sets the small-icon of the notification.
*
* - checks the plugin options for `icon` key
* - if none, uses the application icon
*
* The icon value must be a string that maps to a drawable resource.
* If no resource is found, falls
*
*/
setNotificationSmallIcon
(
context
,
extras
,
packageName
,
resources
,
notificationBuilder
,
setNotificationImportance
(
extras
,
channel
);
setNotificationVibration
(
extras
,
vibrateOption
,
channel
);
setNotificationMessage
(
notId
,
extras
,
notificationBuilder
);
setNotificationCount
(
context
,
extras
,
notificationBuilder
);
setNotificationSmallIcon
(
extras
,
packageName
,
resources
,
notificationBuilder
,
localIcon
);
/*
* Notification Large-Icon
*
* Sets the large-icon of the notification
*
* - checks the gcm data for the `image` key
* - checks to see if remote image, loads it.
* - checks to see if assets image, Loads It.
* - checks to see if resource image, LOADS IT!
* - if none, we don't set the large icon
*
*/
setNotificationLargeIcon
(
context
,
extras
,
packageName
,
resources
,
notificationBuilder
);
setNotificationLedColor
(
extras
,
channel
);
if
(
soundOption
)
{
setNotificationSound
(
context
,
extras
,
channel
);
}
createActions
(
context
,
extras
,
notificationBuilder
,
resources
,
packageName
,
notId
);
notificationManager
.
notify
(
notId
,
notificationBuilder
.
build
());
}
else
{
NotificationCompat
.
Builder
notificationBuilder
=
new
NotificationCompat
.
Builder
(
context
)
.
setWhen
(
System
.
currentTimeMillis
())
.
setContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)))
.
setTicker
(
fromHtml
(
extras
.
getString
(
TITLE
)))
.
setContentIntent
(
contentIntent
)
.
setAutoCancel
(
true
);
/*
* Notification Sound
*/
setNotificationCount
(
context
,
extras
,
notificationBuilder
);
setNotificationVibration
(
extras
,
vibrateOption
,
notificationBuilder
);
setNotificationIconColor
(
extras
.
getString
(
"color"
),
notificationBuilder
,
localIconColor
);
setNotificationSmallIcon
(
extras
,
packageName
,
resources
,
notificationBuilder
,
localIcon
);
setNotificationLargeIcon
(
context
,
extras
,
packageName
,
resources
,
notificationBuilder
);
if
(
soundOption
)
{
setNotificationSound
(
context
,
extras
,
notificationBuilder
);
}
/*
* LED Notification
*/
setNotificationLedColor
(
extras
,
notificationBuilder
);
/*
* Priority Notification
*/
setNotificationPriority
(
extras
,
notificationBuilder
);
/*
* Notification message
*/
setNotificationMessage
(
notId
,
extras
,
notificationBuilder
);
/*
* Notification count
*/
setNotificationCount
(
context
,
extras
,
notificationBuilder
);
/*
* Notification count
*/
setVisibility
(
context
,
extras
,
notificationBuilder
);
/*
* Notification add actions
*/
createActions
(
context
,
extras
,
notificationBuilder
,
resources
,
packageName
,
notId
);
mNotificationManager
.
notify
(
appName
,
notId
,
notificationBuilder
.
build
());
notificationManager
.
notify
(
appName
,
notId
,
notificationBuilder
.
build
());
}
}
private
void
createActions
(
Context
context
,
Bundle
extras
,
NotificationCompat
.
Builder
mB
uilder
,
private
void
createActions
(
Context
context
,
Bundle
extras
,
NotificationCompat
.
Builder
b
uilder
,
Resources
resources
,
String
packageName
,
int
notId
)
{
Log
.
d
(
LOG_TAG
,
"create actions: with in-line"
);
String
actions
=
extras
.
getString
(
ACTIONS
);
...
...
@@ -298,16 +267,112 @@ public class PushNotificationHandler implements PushConstants {
wActions
.
add
(
actionBuilder
.
build
());
if
(
inline
)
{
mBuilder
.
addAction
(
wAction
);
builder
.
addAction
(
wAction
);
}
else
{
builder
.
addAction
(
resources
.
getIdentifier
(
action
.
optString
(
ICON
,
""
),
DRAWABLE
,
packageName
),
action
.
getString
(
TITLE
),
pIntent
);
}
wAction
=
null
;
pIntent
=
null
;
}
builder
.
extend
(
new
NotificationCompat
.
WearableExtender
().
addActions
(
wActions
));
wActions
.
clear
();
}
catch
(
JSONException
e
)
{
// nope
}
}
@RequiresApi
(
api
=
Build
.
VERSION_CODES
.
KITKAT_WATCH
)
private
void
createActions
(
Context
context
,
Bundle
extras
,
Notification
.
Builder
builder
,
Resources
resources
,
String
packageName
,
int
notId
)
{
Log
.
d
(
LOG_TAG
,
"create actions: with in-line"
);
String
actions
=
extras
.
getString
(
ACTIONS
);
if
(
actions
==
null
)
{
return
;
}
try
{
JSONArray
actionsArray
=
new
JSONArray
(
actions
);
ArrayList
<
Notification
.
Action
>
wActions
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
actionsArray
.
length
();
i
++)
{
int
min
=
1
;
int
max
=
2000000000
;
Random
random
=
new
Random
();
int
uniquePendingIntentRequestCode
=
random
.
nextInt
((
max
-
min
)
+
1
)
+
min
;
Log
.
d
(
LOG_TAG
,
"adding action"
);
JSONObject
action
=
actionsArray
.
getJSONObject
(
i
);
Log
.
d
(
LOG_TAG
,
"adding callback = "
+
action
.
getString
(
CALLBACK
));
boolean
foreground
=
action
.
optBoolean
(
FOREGROUND
,
true
);
boolean
inline
=
action
.
optBoolean
(
"inline"
,
false
);
Intent
intent
;
PendingIntent
pIntent
;
if
(
inline
)
{
Log
.
d
(
LOG_TAG
,
"Version: "
+
android
.
os
.
Build
.
VERSION
.
SDK_INT
+
" = "
+
android
.
os
.
Build
.
VERSION_CODES
.
M
);
if
(
android
.
os
.
Build
.
VERSION
.
SDK_INT
<=
android
.
os
.
Build
.
VERSION_CODES
.
M
)
{
Log
.
d
(
LOG_TAG
,
"push activity"
);
intent
=
new
Intent
(
context
,
MainActivity
.
class
);
}
else
{
Log
.
d
(
LOG_TAG
,
"push receiver"
);
intent
=
new
Intent
(
context
,
BackgroundActionButtonHandler
.
class
);
}
updateIntent
(
intent
,
action
.
getString
(
CALLBACK
),
extras
,
foreground
,
notId
);
if
(
android
.
os
.
Build
.
VERSION
.
SDK_INT
<=
android
.
os
.
Build
.
VERSION_CODES
.
M
)
{
Log
.
d
(
LOG_TAG
,
"push activity for notId "
+
notId
);
pIntent
=
PendingIntent
.
getActivity
(
context
,
uniquePendingIntentRequestCode
,
intent
,
PendingIntent
.
FLAG_ONE_SHOT
);
}
else
{
Log
.
d
(
LOG_TAG
,
"push receiver for notId "
+
notId
);
pIntent
=
PendingIntent
.
getBroadcast
(
context
,
uniquePendingIntentRequestCode
,
intent
,
PendingIntent
.
FLAG_ONE_SHOT
);
}
}
else
if
(
foreground
)
{
intent
=
new
Intent
(
context
,
MainActivity
.
class
);
updateIntent
(
intent
,
action
.
getString
(
CALLBACK
),
extras
,
foreground
,
notId
);
pIntent
=
PendingIntent
.
getActivity
(
context
,
uniquePendingIntentRequestCode
,
intent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
);
}
else
{
intent
=
new
Intent
(
context
,
BackgroundActionButtonHandler
.
class
);
updateIntent
(
intent
,
action
.
getString
(
CALLBACK
),
extras
,
foreground
,
notId
);
pIntent
=
PendingIntent
.
getBroadcast
(
context
,
uniquePendingIntentRequestCode
,
intent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
);
}
Notification
.
Action
.
Builder
actionBuilder
=
new
Notification
.
Action
.
Builder
(
resources
.
getIdentifier
(
action
.
optString
(
ICON
,
""
),
DRAWABLE
,
packageName
),
action
.
getString
(
TITLE
),
pIntent
);
android
.
app
.
RemoteInput
remoteInput
;
if
(
inline
)
{
Log
.
d
(
LOG_TAG
,
"create remote input"
);
String
replyLabel
=
"Enter your reply here"
;
remoteInput
=
new
android
.
app
.
RemoteInput
.
Builder
(
INLINE_REPLY
)
.
setLabel
(
replyLabel
)
.
build
();
actionBuilder
.
addRemoteInput
(
remoteInput
);
}
Notification
.
Action
wAction
=
actionBuilder
.
build
();
wActions
.
add
(
actionBuilder
.
build
());
if
(
inline
)
{
builder
.
addAction
(
wAction
);
}
else
{
mB
uilder
.
addAction
(
b
uilder
.
addAction
(
resources
.
getIdentifier
(
action
.
optString
(
ICON
,
""
),
DRAWABLE
,
packageName
),
action
.
getString
(
TITLE
),
pIntent
);
}
wAction
=
null
;
pIntent
=
null
;
}
mBuilder
.
extend
(
new
NotificationCompat
.
WearableExtender
().
addActions
(
wActions
));
builder
.
extend
(
new
Notification
.
WearableExtender
().
addActions
(
wActions
));
wActions
.
clear
();
}
catch
(
JSONException
e
)
{
// nope
...
...
@@ -315,15 +380,24 @@ public class PushNotificationHandler implements PushConstants {
}
private
void
setNotificationCount
(
Context
context
,
Bundle
extras
,
NotificationCompat
.
Builder
mBuilder
)
{
NotificationCompat
.
Builder
builder
)
{
int
count
=
extractBadgeCount
(
extras
);
if
(
count
>=
0
)
{
Log
.
d
(
LOG_TAG
,
"count =["
+
count
+
"]"
);
builder
.
setNumber
(
count
);
}
}
private
void
setNotificationCount
(
Context
context
,
Bundle
extras
,
Notification
.
Builder
builder
)
{
int
count
=
extractBadgeCount
(
extras
);
if
(
count
>=
0
)
{
Log
.
d
(
LOG_TAG
,
"count =["
+
count
+
"]"
);
mB
uilder
.
setNumber
(
count
);
b
uilder
.
setNumber
(
count
);
}
}
private
void
setVisibility
(
Context
context
,
Bundle
extras
,
NotificationCompat
.
Builder
mB
uilder
)
{
private
void
setVisibility
(
Context
context
,
Bundle
extras
,
NotificationCompat
.
Builder
b
uilder
)
{
String
visibilityStr
=
extras
.
getString
(
VISIBILITY
);
if
(
visibilityStr
==
null
)
{
return
;
...
...
@@ -333,7 +407,7 @@ public class PushNotificationHandler implements PushConstants {
Integer
visibility
=
Integer
.
parseInt
(
visibilityStr
);
if
(
visibility
>=
NotificationCompat
.
VISIBILITY_SECRET
&&
visibility
<=
NotificationCompat
.
VISIBILITY_PUBLIC
)
{
mB
uilder
.
setVisibility
(
visibility
);
b
uilder
.
setVisibility
(
visibility
);
}
else
{
Log
.
e
(
LOG_TAG
,
"Visibility parameter must be between -1 and 1"
);
}
...
...
@@ -343,7 +417,28 @@ public class PushNotificationHandler implements PushConstants {
}
private
void
setNotificationVibration
(
Bundle
extras
,
Boolean
vibrateOption
,
NotificationCompat
.
Builder
mBuilder
)
{
NotificationCompat
.
Builder
builder
)
{
String
vibrationPattern
=
extras
.
getString
(
VIBRATION_PATTERN
);
if
(
vibrationPattern
!=
null
)
{
String
[]
items
=
vibrationPattern
.
replaceAll
(
"\\["
,
""
).
replaceAll
(
"\\]"
,
""
).
split
(
","
);
long
[]
results
=
new
long
[
items
.
length
];
for
(
int
i
=
0
;
i
<
items
.
length
;
i
++)
{
try
{
results
[
i
]
=
Long
.
parseLong
(
items
[
i
].
trim
());
}
catch
(
NumberFormatException
nfe
)
{
}
}
builder
.
setVibrate
(
results
);
}
else
{
if
(
vibrateOption
)
{
builder
.
setDefaults
(
Notification
.
DEFAULT_VIBRATE
);
}
}
}
@RequiresApi
(
api
=
26
)
private
void
setNotificationVibration
(
Bundle
extras
,
Boolean
vibrateOption
,
NotificationChannel
channel
)
{
String
vibrationPattern
=
extras
.
getString
(
VIBRATION_PATTERN
);
if
(
vibrationPattern
!=
null
)
{
String
[]
items
=
vibrationPattern
.
replaceAll
(
"\\["
,
""
).
replaceAll
(
"\\]"
,
""
).
split
(
","
);
...
...
@@ -354,23 +449,23 @@ public class PushNotificationHandler implements PushConstants {
}
catch
(
NumberFormatException
nfe
)
{
}
}
mBuilder
.
setVibrate
(
results
);
channel
.
setVibrationPattern
(
results
);
}
else
{
if
(
vibrateOption
)
{
mBuilder
.
setDefaults
(
Notification
.
DEFAULT_VIBRATE
);
channel
.
enableVibration
(
true
);
}
}
}
private
void
setNotificationMessage
(
int
notId
,
Bundle
extras
,
NotificationCompat
.
Builder
mB
uilder
)
{
NotificationCompat
.
Builder
b
uilder
)
{
String
message
=
extras
.
getString
(
MESSAGE
);
String
style
=
extras
.
getString
(
STYLE
,
STYLE_TEXT
);
if
(
STYLE_INBOX
.
equals
(
style
))
{
setNotification
(
notId
,
message
);
mB
uilder
.
setContentText
(
fromHtml
(
message
));
b
uilder
.
setContentText
(
fromHtml
(
message
));
ArrayList
<
String
>
messageList
=
getMessageList
(
notId
);
Integer
sizeList
=
messageList
.
size
();
...
...
@@ -389,13 +484,13 @@ public class PushNotificationHandler implements PushConstants {
notificationInbox
.
addLine
(
fromHtml
(
messageList
.
get
(
i
)));
}
mB
uilder
.
setStyle
(
notificationInbox
);
b
uilder
.
setStyle
(
notificationInbox
);
}
else
{
NotificationCompat
.
BigTextStyle
bigText
=
new
NotificationCompat
.
BigTextStyle
();
if
(
message
!=
null
)
{
bigText
.
bigText
(
fromHtml
(
message
));
bigText
.
setBigContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)));
mB
uilder
.
setStyle
(
bigText
);
b
uilder
.
setStyle
(
bigText
);
}
}
}
else
if
(
STYLE_PICTURE
.
equals
(
style
))
{
...
...
@@ -406,17 +501,17 @@ public class PushNotificationHandler implements PushConstants {
bigPicture
.
setBigContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)));
bigPicture
.
setSummaryText
(
fromHtml
(
extras
.
getString
(
SUMMARY_TEXT
)));
mB
uilder
.
setContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)));
mB
uilder
.
setContentText
(
fromHtml
(
message
));
b
uilder
.
setContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)));
b
uilder
.
setContentText
(
fromHtml
(
message
));
mB
uilder
.
setStyle
(
bigPicture
);
b
uilder
.
setStyle
(
bigPicture
);
}
else
{
setNotification
(
notId
,
""
);
NotificationCompat
.
BigTextStyle
bigText
=
new
NotificationCompat
.
BigTextStyle
();
if
(
message
!=
null
)
{
mB
uilder
.
setContentText
(
fromHtml
(
message
));
b
uilder
.
setContentText
(
fromHtml
(
message
));
bigText
.
bigText
(
fromHtml
(
message
));
bigText
.
setBigContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)));
...
...
@@ -426,30 +521,145 @@ public class PushNotificationHandler implements PushConstants {
bigText
.
setSummaryText
(
fromHtml
(
summaryText
));
}
mB
uilder
.
setStyle
(
bigText
);
b
uilder
.
setStyle
(
bigText
);
}
}
}
private
void
setNotificationMessage
(
int
notId
,
Bundle
extras
,
Notification
.
Builder
builder
)
{
String
message
=
extras
.
getString
(
MESSAGE
);
String
style
=
extras
.
getString
(
STYLE
,
STYLE_TEXT
);
if
(
STYLE_INBOX
.
equals
(
style
))
{
setNotification
(
notId
,
message
);
builder
.
setContentText
(
fromHtml
(
message
));
ArrayList
<
String
>
messageList
=
getMessageList
(
notId
);
Integer
sizeList
=
messageList
.
size
();
if
(
sizeList
>
1
)
{
String
sizeListMessage
=
sizeList
.
toString
();
String
stacking
=
sizeList
+
" more"
;
if
(
extras
.
getString
(
SUMMARY_TEXT
)
!=
null
)
{
stacking
=
extras
.
getString
(
SUMMARY_TEXT
);
stacking
=
stacking
.
replace
(
"%n%"
,
sizeListMessage
);
}
Notification
.
InboxStyle
notificationInbox
=
new
Notification
.
InboxStyle
()
.
setBigContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)))
.
setSummaryText
(
fromHtml
(
stacking
));
for
(
int
i
=
messageList
.
size
()
-
1
;
i
>=
0
;
i
--)
{
notificationInbox
.
addLine
(
fromHtml
(
messageList
.
get
(
i
)));
}
builder
.
setStyle
(
notificationInbox
);
}
else
{
Notification
.
BigTextStyle
bigText
=
new
Notification
.
BigTextStyle
();
if
(
message
!=
null
)
{
bigText
.
bigText
(
fromHtml
(
message
));
bigText
.
setBigContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)));
builder
.
setStyle
(
bigText
);
}
}
}
else
if
(
STYLE_PICTURE
.
equals
(
style
))
{
setNotification
(
notId
,
""
);
Notification
.
BigPictureStyle
bigPicture
=
new
Notification
.
BigPictureStyle
();
bigPicture
.
bigPicture
(
getBitmapFromURL
(
extras
.
getString
(
PICTURE
)));
bigPicture
.
setBigContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)));
bigPicture
.
setSummaryText
(
fromHtml
(
extras
.
getString
(
SUMMARY_TEXT
)));
builder
.
setContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)));
builder
.
setContentText
(
fromHtml
(
message
));
builder
.
setStyle
(
bigPicture
);
}
else
{
setNotification
(
notId
,
""
);
Notification
.
BigTextStyle
bigText
=
new
Notification
.
BigTextStyle
();
if
(
message
!=
null
)
{
builder
.
setContentText
(
fromHtml
(
message
));
bigText
.
bigText
(
fromHtml
(
message
));
bigText
.
setBigContentTitle
(
fromHtml
(
extras
.
getString
(
TITLE
)));
String
summaryText
=
extras
.
getString
(
SUMMARY_TEXT
);
if
(
summaryText
!=
null
)
{
bigText
.
setSummaryText
(
fromHtml
(
summaryText
));
}
builder
.
setStyle
(
bigText
);
}
}
}
private
void
setNotificationSound
(
Context
context
,
Bundle
extras
,
NotificationCompat
.
Builder
builder
)
{
String
soundname
=
extras
.
getString
(
SOUNDNAME
);
if
(
soundname
==
null
)
{
soundname
=
extras
.
getString
(
SOUND
);
}
if
(
SOUND_RINGTONE
.
equals
(
soundname
))
{
builder
.
setSound
(
android
.
provider
.
Settings
.
System
.
DEFAULT_RINGTONE_URI
);
}
else
if
(
soundname
!=
null
&&
!
soundname
.
contentEquals
(
SOUND_DEFAULT
))
{
Uri
sound
=
Uri
.
parse
(
ContentResolver
.
SCHEME_ANDROID_RESOURCE
+
"://"
+
context
.
getPackageName
()
+
"/raw/"
+
soundname
);
Log
.
d
(
LOG_TAG
,
sound
.
toString
());
builder
.
setSound
(
sound
);
}
else
{
builder
.
setSound
(
android
.
provider
.
Settings
.
System
.
DEFAULT_NOTIFICATION_URI
);
}
}
@RequiresApi
(
api
=
26
)
private
void
setNotificationSound
(
Context
context
,
Bundle
extras
,
NotificationC
ompat
.
Builder
mBuilder
)
{
NotificationC
hannel
channel
)
{
String
soundname
=
extras
.
getString
(
SOUNDNAME
);
if
(
soundname
==
null
)
{
soundname
=
extras
.
getString
(
SOUND
);
}
if
(
SOUND_RINGTONE
.
equals
(
soundname
))
{
mBuilder
.
setSound
(
android
.
provider
.
Settings
.
System
.
DEFAULT_RINGTONE_URI
);
channel
.
setSound
(
android
.
provider
.
Settings
.
System
.
DEFAULT_RINGTONE_URI
,
Notification
.
AUDIO_ATTRIBUTES_DEFAULT
);
}
else
if
(
soundname
!=
null
&&
!
soundname
.
contentEquals
(
SOUND_DEFAULT
))
{
Uri
sound
=
Uri
.
parse
(
ContentResolver
.
SCHEME_ANDROID_RESOURCE
+
"://"
+
context
.
getPackageName
()
+
"/raw/"
+
soundname
);
Log
.
d
(
LOG_TAG
,
sound
.
toString
());
mBuilder
.
setSound
(
sound
);
channel
.
setSound
(
sound
,
Notification
.
AUDIO_ATTRIBUTES_DEFAULT
);
}
else
{
channel
.
setSound
(
android
.
provider
.
Settings
.
System
.
DEFAULT_NOTIFICATION_URI
,
Notification
.
AUDIO_ATTRIBUTES_DEFAULT
);
}
}
private
void
setNotificationLedColor
(
Bundle
extras
,
NotificationCompat
.
Builder
builder
)
{
String
ledColor
=
extras
.
getString
(
LED_COLOR
);
if
(
ledColor
==
null
)
{
return
;
}
// Converts parse Int Array from ledColor
String
[]
items
=
ledColor
.
replaceAll
(
"\\["
,
""
).
replaceAll
(
"\\]"
,
""
).
split
(
","
);
int
[]
results
=
new
int
[
items
.
length
];
for
(
int
i
=
0
;
i
<
items
.
length
;
i
++)
{
try
{
results
[
i
]
=
Integer
.
parseInt
(
items
[
i
].
trim
());
}
catch
(
NumberFormatException
nfe
)
{
}
}
if
(
results
.
length
==
4
)
{
builder
.
setLights
(
Color
.
argb
(
results
[
0
],
results
[
1
],
results
[
2
],
results
[
3
]),
500
,
500
);
}
else
{
mBuilder
.
setSound
(
android
.
provider
.
Settings
.
System
.
DEFAULT_NOTIFICATION_URI
);
Log
.
e
(
LOG_TAG
,
"ledColor parameter must be an array of length == 4 (ARGB)"
);
}
}
private
void
setNotificationLedColor
(
Bundle
extras
,
NotificationCompat
.
Builder
mBuilder
)
{
@RequiresApi
(
api
=
26
)
private
void
setNotificationLedColor
(
Bundle
extras
,
NotificationChannel
channel
)
{
String
ledColor
=
extras
.
getString
(
LED_COLOR
);
if
(
ledColor
==
null
)
{
return
;
...
...
@@ -466,14 +676,14 @@ public class PushNotificationHandler implements PushConstants {
}
if
(
results
.
length
==
4
)
{
mBuilder
.
setLights
(
Color
.
argb
(
results
[
0
],
results
[
1
],
results
[
2
],
results
[
3
]),
500
,
500
);
channel
.
setLightColor
(
Color
.
argb
(
results
[
0
],
results
[
1
],
results
[
2
],
results
[
3
])
);
}
else
{
Log
.
e
(
LOG_TAG
,
"ledColor parameter must be an array of length == 4 (ARGB)"
);
}
}
private
void
setNotificationPriority
(
Bundle
extras
,
NotificationCompat
.
Builder
mB
uilder
)
{
private
void
setNotificationPriority
(
Bundle
extras
,
NotificationCompat
.
Builder
b
uilder
)
{
String
priorityStr
=
extras
.
getString
(
PRIORITY
);
if
(
priorityStr
==
null
)
{
return
;
...
...
@@ -483,7 +693,28 @@ public class PushNotificationHandler implements PushConstants {
Integer
priority
=
Integer
.
parseInt
(
priorityStr
);
if
(
priority
>=
NotificationCompat
.
PRIORITY_MIN
&&
priority
<=
NotificationCompat
.
PRIORITY_MAX
)
{
mBuilder
.
setPriority
(
priority
);
builder
.
setPriority
(
priority
);
}
else
{
Log
.
e
(
LOG_TAG
,
"Priority parameter must be between -2 and 2"
);
}
}
catch
(
NumberFormatException
e
)
{
e
.
printStackTrace
();
}
}
@RequiresApi
(
api
=
26
)
private
void
setNotificationImportance
(
Bundle
extras
,
NotificationChannel
channel
)
{
String
priorityStr
=
extras
.
getString
(
PRIORITY
);
if
(
priorityStr
==
null
)
{
return
;
}
try
{
Integer
priority
=
Integer
.
parseInt
(
priorityStr
);
if
(
priority
>=
NotificationCompat
.
PRIORITY_MIN
&&
priority
<=
NotificationCompat
.
PRIORITY_MAX
)
{
channel
.
setImportance
(
priority
);
}
else
{
Log
.
e
(
LOG_TAG
,
"Priority parameter must be between -2 and 2"
);
}
...
...
@@ -494,14 +725,14 @@ public class PushNotificationHandler implements PushConstants {
}
private
void
setNotificationLargeIcon
(
Context
context
,
Bundle
extras
,
String
packageName
,
Resources
resources
,
NotificationCompat
.
Builder
mB
uilder
)
{
Resources
resources
,
NotificationCompat
.
Builder
b
uilder
)
{
String
gcmLargeIcon
=
extras
.
getString
(
IMAGE
);
// from gcm
if
(
gcmLargeIcon
==
null
||
""
.
equals
(
gcmLargeIcon
))
{
return
;
}
if
(
gcmLargeIcon
.
startsWith
(
"http://"
)
||
gcmLargeIcon
.
startsWith
(
"https://"
))
{
mB
uilder
.
setLargeIcon
(
getBitmapFromURL
(
gcmLargeIcon
));
b
uilder
.
setLargeIcon
(
getBitmapFromURL
(
gcmLargeIcon
));
Log
.
d
(
LOG_TAG
,
"using remote large-icon from gcm"
);
}
else
{
AssetManager
assetManager
=
context
.
getAssets
();
...
...
@@ -509,13 +740,13 @@ public class PushNotificationHandler implements PushConstants {
try
{
istr
=
assetManager
.
open
(
gcmLargeIcon
);
Bitmap
bitmap
=
BitmapFactory
.
decodeStream
(
istr
);
mB
uilder
.
setLargeIcon
(
bitmap
);
b
uilder
.
setLargeIcon
(
bitmap
);
Log
.
d
(
LOG_TAG
,
"using assets large-icon from gcm"
);
}
catch
(
IOException
e
)
{
int
largeIconId
=
resources
.
getIdentifier
(
gcmLargeIcon
,
DRAWABLE
,
packageName
);
if
(
largeIconId
!=
0
)
{
Bitmap
largeIconBitmap
=
BitmapFactory
.
decodeResource
(
resources
,
largeIconId
);
mB
uilder
.
setLargeIcon
(
largeIconBitmap
);
b
uilder
.
setLargeIcon
(
largeIconBitmap
);
Log
.
d
(
LOG_TAG
,
"using resources large-icon from gcm"
);
}
else
{
Log
.
d
(
LOG_TAG
,
"Not setting large icon"
);
...
...
@@ -524,8 +755,59 @@ public class PushNotificationHandler implements PushConstants {
}
}
private
void
setNotificationSmallIcon
(
Context
context
,
Bundle
extras
,
String
packageName
,
Resources
resources
,
NotificationCompat
.
Builder
mBuilder
,
private
void
setNotificationLargeIcon
(
Context
context
,
Bundle
extras
,
String
packageName
,
Resources
resources
,
Notification
.
Builder
builder
)
{
String
gcmLargeIcon
=
extras
.
getString
(
IMAGE
);
// from gcm
if
(
gcmLargeIcon
==
null
||
""
.
equals
(
gcmLargeIcon
))
{
return
;
}
if
(
gcmLargeIcon
.
startsWith
(
"http://"
)
||
gcmLargeIcon
.
startsWith
(
"https://"
))
{
builder
.
setLargeIcon
(
getBitmapFromURL
(
gcmLargeIcon
));
Log
.
d
(
LOG_TAG
,
"using remote large-icon from gcm"
);
}
else
{
AssetManager
assetManager
=
context
.
getAssets
();
InputStream
istr
;
try
{
istr
=
assetManager
.
open
(
gcmLargeIcon
);
Bitmap
bitmap
=
BitmapFactory
.
decodeStream
(
istr
);
builder
.
setLargeIcon
(
bitmap
);
Log
.
d
(
LOG_TAG
,
"using assets large-icon from gcm"
);
}
catch
(
IOException
e
)
{
int
largeIconId
=
resources
.
getIdentifier
(
gcmLargeIcon
,
DRAWABLE
,
packageName
);
if
(
largeIconId
!=
0
)
{
Bitmap
largeIconBitmap
=
BitmapFactory
.
decodeResource
(
resources
,
largeIconId
);
builder
.
setLargeIcon
(
largeIconBitmap
);
Log
.
d
(
LOG_TAG
,
"using resources large-icon from gcm"
);
}
else
{
Log
.
d
(
LOG_TAG
,
"Not setting large icon"
);
}
}
}
}
private
void
setNotificationSmallIcon
(
Bundle
extras
,
String
packageName
,
Resources
resources
,
NotificationCompat
.
Builder
builder
,
String
localIcon
)
{
int
iconId
=
0
;
String
icon
=
extras
.
getString
(
ICON
);
if
(
icon
!=
null
&&
!
""
.
equals
(
icon
))
{
iconId
=
resources
.
getIdentifier
(
icon
,
DRAWABLE
,
packageName
);
Log
.
d
(
LOG_TAG
,
"using icon from plugin options"
);
}
else
if
(
localIcon
!=
null
&&
!
""
.
equals
(
localIcon
))
{
iconId
=
resources
.
getIdentifier
(
localIcon
,
DRAWABLE
,
packageName
);
Log
.
d
(
LOG_TAG
,
"using icon from plugin options"
);
}
if
(
iconId
==
0
)
{
Log
.
d
(
LOG_TAG
,
"no icon resource found - using default icon"
);
iconId
=
resources
.
getIdentifier
(
"rocket_chat_notification"
,
DRAWABLE
,
packageName
);
}
builder
.
setSmallIcon
(
iconId
);
}
private
void
setNotificationSmallIcon
(
Bundle
extras
,
String
packageName
,
Resources
resources
,
Notification
.
Builder
builder
,
String
localIcon
)
{
int
iconId
=
0
;
String
icon
=
extras
.
getString
(
ICON
);
...
...
@@ -540,10 +822,10 @@ public class PushNotificationHandler implements PushConstants {
Log
.
d
(
LOG_TAG
,
"no icon resource found - using default icon"
);
iconId
=
resources
.
getIdentifier
(
"rocket_chat_notification"
,
DRAWABLE
,
packageName
);
}
mB
uilder
.
setSmallIcon
(
iconId
);
b
uilder
.
setSmallIcon
(
iconId
);
}
private
void
setNotificationIconColor
(
String
color
,
NotificationCompat
.
Builder
mB
uilder
,
private
void
setNotificationIconColor
(
String
color
,
NotificationCompat
.
Builder
b
uilder
,
String
localIconColor
)
{
int
iconColor
=
0
;
if
(
color
!=
null
&&
!
""
.
equals
(
color
))
{
...
...
@@ -560,7 +842,7 @@ public class PushNotificationHandler implements PushConstants {
}
}
if
(
iconColor
!=
0
)
{
mB
uilder
.
setColor
(
iconColor
);
b
uilder
.
setColor
(
iconColor
);
}
}
...
...
app/src/main/java/chat/rocket/android/service/ConnectivityManagerInternal.java
View file @
f6ccb19b
...
...
@@ -23,4 +23,6 @@ import chat.rocket.core.models.ServerInfo;
void
notifyConnectionEstablished
(
String
hostname
,
String
session
);
void
notifyConnectionLost
(
String
hostname
,
int
reason
);
void
notifyConnecting
(
String
hostname
);
}
app/src/main/java/chat/rocket/android/service/RealmBasedConnectivityManager.java
View file @
f6ccb19b
...
...
@@ -133,6 +133,14 @@ import rx.subjects.PublishSubject;
new
ServerConnectivity
(
hostname
,
ServerConnectivity
.
STATE_DISCONNECTED
));
}
@DebugLog
@Override
public
void
notifyConnecting
(
String
hostname
)
{
serverConnectivityList
.
put
(
hostname
,
ServerConnectivity
.
STATE_CONNECTING
);
connectivitySubject
.
onNext
(
new
ServerConnectivity
(
hostname
,
ServerConnectivity
.
STATE_CONNECTING
));
}
@Override
public
Observable
<
ServerConnectivity
>
getServerConnectivityAsObservable
()
{
return
Observable
.
concat
(
Observable
.
from
(
getCurrentConnectivityList
()),
connectivitySubject
);
...
...
app/src/main/java/chat/rocket/android/service/RocketChatService.java
View file @
f6ccb19b
...
...
@@ -9,6 +9,7 @@ import android.os.IBinder;
import
android.support.annotation.Nullable
;
import
java.util.HashMap
;
import
java.util.concurrent.Semaphore
;
import
java.util.concurrent.TimeUnit
;
import
chat.rocket.android.activity.MainActivity
;
...
...
@@ -24,6 +25,7 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
private
ConnectivityManagerInternal
connectivityManager
;
private
HashMap
<
String
,
RocketChatWebSocketThread
>
webSocketThreads
;
private
Semaphore
webSocketThreadLock
=
new
Semaphore
(
1
);
public
class
LocalBinder
extends
Binder
{
ConnectivityServiceInterface
getServiceInterface
()
{
...
...
@@ -49,6 +51,7 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
context
.
unbindService
(
serviceConnection
);
}
@DebugLog
@Override
public
void
onCreate
()
{
super
.
onCreate
();
...
...
@@ -57,6 +60,7 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
webSocketThreads
=
new
HashMap
<>();
}
@DebugLog
@Override
public
int
onStartCommand
(
Intent
intent
,
int
flags
,
int
startId
)
{
connectivityManager
.
ensureConnections
();
...
...
@@ -106,12 +110,17 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
@DebugLog
private
Single
<
RocketChatWebSocketThread
>
getOrCreateWebSocketThread
(
String
hostname
)
{
return
Single
.
defer
(()
->
{
webSocketThreadLock
.
acquire
();
if
(
webSocketThreads
.
containsKey
(
hostname
))
{
RocketChatWebSocketThread
thread
=
webSocketThreads
.
get
(
hostname
);
webSocketThreadLock
.
release
();
return
Single
.
just
(
thread
);
}
return
RocketChatWebSocketThread
.
getStarted
(
getApplicationContext
(),
hostname
)
.
doOnSuccess
(
thread
->
webSocketThreads
.
put
(
hostname
,
thread
));
.
doOnSuccess
(
thread
->
{
webSocketThreads
.
put
(
hostname
,
thread
);
webSocketThreadLock
.
release
();
});
});
}
...
...
app/src/main/java/chat/rocket/android/service/RocketChatWebSocketThread.java
View file @
f6ccb19b
...
...
@@ -3,24 +3,26 @@ package chat.rocket.android.service;
import
android.content.Context
;
import
android.os.Handler
;
import
android.os.HandlerThread
;
import
org.json.JSONObject
;
import
java.lang.reflect.Constructor
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.concurrent.TimeUnit
;
import
bolts.Task
;
import
chat.rocket.android.RocketChatCache
;
import
chat.rocket.android.api.DDPClientWrapper
;
import
chat.rocket.android.api.MethodCallHelper
;
import
chat.rocket.android.helper.LogIfError
;
import
chat.rocket.android.helper.RxHelper
;
import
chat.rocket.android.helper.TextUtils
;
import
chat.rocket.android.log.RCLog
;
import
chat.rocket.core.models.ServerInfo
;
import
chat.rocket.persistence.realm.models.internal.RealmSession
;
import
chat.rocket.persistence.realm.RealmHelper
;
import
chat.rocket.persistence.realm.RealmStore
;
import
chat.rocket.android.service.ddp.base.ActiveUsersSubscriber
;
import
chat.rocket.android.service.ddp.base.LoginServiceConfigurationSubscriber
;
import
chat.rocket.android.service.ddp.base.UserDataSubscriber
;
import
chat.rocket.android.service.ddp.stream.StreamRoomMessage
;
import
chat.rocket.android.service.observer.CurrentUserObserver
;
import
chat.rocket.android.service.observer.FileUploadingToUrlObserver
;
import
chat.rocket.android.service.observer.FileUploadingWithUfsObserver
;
...
...
@@ -32,8 +34,13 @@ import chat.rocket.android.service.observer.NewMessageObserver;
import
chat.rocket.android.service.observer.PushSettingsObserver
;
import
chat.rocket.android.service.observer.SessionObserver
;
import
chat.rocket.android.service.observer.TokenLoginObserver
;
import
chat.rocket.core.models.ServerInfo
;
import
chat.rocket.persistence.realm.RealmHelper
;
import
chat.rocket.persistence.realm.RealmStore
;
import
chat.rocket.persistence.realm.models.internal.RealmSession
;
import
hugo.weaving.DebugLog
;
import
rx.Single
;
import
rx.subscriptions.CompositeSubscription
;
/**
* Thread for handling WebSocket connection.
...
...
@@ -62,6 +69,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
private
final
ArrayList
<
Registrable
>
listeners
=
new
ArrayList
<>();
private
DDPClientWrapper
ddpClient
;
private
boolean
listenersRegistered
;
private
RocketChatCache
rocketChatCache
;
private
final
DDPClientRef
ddpClientRef
=
new
DDPClientRef
()
{
@Override
public
DDPClientWrapper
get
()
{
...
...
@@ -69,7 +77,6 @@ public class RocketChatWebSocketThread extends HandlerThread {
}
};
private
static
class
KeepAliveTimer
{
private
long
lastTime
;
private
final
long
thresholdMs
;
...
...
@@ -96,6 +103,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
this
.
hostname
=
hostname
;
this
.
realmHelper
=
RealmStore
.
getOrCreate
(
hostname
);
this
.
connectivityManager
=
ConnectivityManager
.
getInstanceForInternal
(
appContext
);
this
.
rocketChatCache
=
new
RocketChatCache
(
appContext
);
}
/**
...
...
@@ -147,7 +155,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
return
Single
.
fromEmitter
(
emitter
->
{
new
Handler
(
getLooper
()).
post
(()
->
{
RCLog
.
d
(
"thread %s: terminated()"
,
Thread
.
currentThread
().
getId
());
unregisterListeners
();
unregisterListeners
AndClose
();
connectivityManager
.
notifyConnectionLost
(
hostname
,
ConnectivityManagerInternal
.
REASON_CLOSED_BY_USER
);
RocketChatWebSocketThread
.
super
.
quit
();
...
...
@@ -196,9 +204,9 @@ public class RocketChatWebSocketThread extends HandlerThread {
public
void
run
()
{
ddpClient
.
ping
().
continueWith
(
task
->
{
if
(
task
.
isFaulted
())
{
RCLog
.
e
(
task
.
getError
());
Exception
error
=
task
.
getError
();
RCLog
.
e
(
error
);
emitter
.
onSuccess
(
false
);
ddpClient
.
close
();
}
else
{
keepAliveTimer
.
update
();
emitter
.
onSuccess
(
true
);
...
...
@@ -232,9 +240,26 @@ public class RocketChatWebSocketThread extends HandlerThread {
// handling WebSocket#onClose() callback.
task
.
getResult
().
client
.
getOnCloseCallback
().
onSuccess
(
_task
->
{
if
(
listenersRegistered
)
{
terminate
();
}
ddpClient
.
close
();
forceInvalidateTokens
();
connectivityManager
.
notifyConnecting
(
hostname
);
// Needed to use subscriptions because of legacy code.
// TODO: Should update to RxJava 2
final
CompositeSubscription
subscriptions
=
new
CompositeSubscription
();
subscriptions
.
add
(
connect
().
retryWhen
(
RxHelper
.
exponentialBackoff
(
3
,
500
,
TimeUnit
.
MILLISECONDS
))
.
subscribe
(
connected
->
{
if
(!
connected
)
{
connectivityManager
.
notifyConnectionLost
(
hostname
,
ConnectivityManagerInternal
.
REASON_NETWORK_ERROR
);
}
subscriptions
.
clear
();
},
err
->
logErrorAndUnsubscribe
(
subscriptions
,
err
)
)
);
return
null
;
});
...
...
@@ -265,6 +290,11 @@ public class RocketChatWebSocketThread extends HandlerThread {
}));
}
private
void
logErrorAndUnsubscribe
(
CompositeSubscription
subscriptions
,
Throwable
err
)
{
RCLog
.
e
(
err
);
subscriptions
.
clear
();
}
@DebugLog
private
Single
<
Boolean
>
connect
()
{
return
connectDDPClient
()
...
...
@@ -284,7 +314,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
return
new
MethodCallHelper
(
realmHelper
,
ddpClientRef
).
getPermissions
();
}
//
@DebugLog
@DebugLog
private
void
registerListeners
()
{
if
(!
Thread
.
currentThread
().
getName
().
equals
(
"RC_thread_"
+
hostname
))
{
// execute in Looper.
...
...
@@ -293,7 +323,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
}
if
(
listenersRegistered
)
{
return
;
unregisterListeners
()
;
}
listenersRegistered
=
true
;
...
...
@@ -308,12 +338,30 @@ public class RocketChatWebSocketThread extends HandlerThread {
registrable
.
register
();
listeners
.
add
(
registrable
);
}
// Register for room stream messages
String
roomId
=
rocketChatCache
.
getSelectedRoomId
();
if
(
roomId
!=
null
&&
!
roomId
.
isEmpty
())
{
StreamRoomMessage
streamRoomMessage
=
new
StreamRoomMessage
(
appContext
,
hostname
,
realmHelper
,
ddpClientRef
,
roomId
);
streamRoomMessage
.
register
();
listeners
.
add
(
streamRoomMessage
);
}
}
catch
(
Exception
exception
)
{
RCLog
.
w
(
exception
,
"Failed to register listeners!!"
);
}
}
}
@DebugLog
private
void
unregisterListenersAndClose
()
{
unregisterListeners
();
if
(
ddpClient
!=
null
)
{
ddpClient
.
close
();
ddpClient
=
null
;
}
}
@DebugLog
private
void
unregisterListeners
()
{
Iterator
<
Registrable
>
iterator
=
listeners
.
iterator
();
...
...
@@ -323,9 +371,5 @@ public class RocketChatWebSocketThread extends HandlerThread {
iterator
.
remove
();
}
listenersRegistered
=
false
;
if
(
ddpClient
!=
null
)
{
ddpClient
.
close
();
ddpClient
=
null
;
}
}
}
app/src/main/java/chat/rocket/android/service/ServerConnectivity.java
View file @
f6ccb19b
...
...
@@ -6,7 +6,7 @@ package chat.rocket.android.service;
public
class
ServerConnectivity
{
public
static
final
int
STATE_CONNECTED
=
1
;
public
static
final
int
STATE_DISCONNECTED
=
2
;
/*package*/
static
final
int
STATE_CONNECTING
=
3
;
public
static
final
int
STATE_CONNECTING
=
3
;
/*package*/
static
final
int
STATE_DISCONNECTING
=
4
;
public
final
String
hostname
;
...
...
app/src/main/java/chat/rocket/android/service/ddp/AbstractDDPDocEventSubscriber.java
View file @
f6ccb19b
...
...
@@ -185,7 +185,7 @@ public abstract class AbstractDDPDocEventSubscriber implements Registrable {
if
(
rxSubscription
!=
null
)
{
rxSubscription
.
dispose
();
}
if
(!
TextUtils
.
isEmpty
(
subscriptionId
))
{
if
(!
TextUtils
.
isEmpty
(
subscriptionId
)
&&
ddpClientRef
.
get
()
!=
null
)
{
ddpClientRef
.
get
().
unsubscribe
(
subscriptionId
).
continueWith
(
new
LogIfError
());
}
}
...
...
app/src/main/java/chat/rocket/android/service/internal/AbstractRocketChatCacheObserver.java
View file @
f6ccb19b
...
...
@@ -2,6 +2,7 @@ package chat.rocket.android.service.internal;
import
android.content.Context
;
import
chat.rocket.android.log.RCLog
;
import
io.reactivex.disposables.CompositeDisposable
;
import
chat.rocket.android.RocketChatCache
;
...
...
@@ -47,7 +48,7 @@ public abstract class AbstractRocketChatCacheObserver implements Registrable {
compositeDisposable
.
add
(
new
RocketChatCache
(
context
)
.
getSelectedRoomIdPublisher
()
.
subscribe
(
this
::
updateRoomIdWith
)
.
subscribe
(
this
::
updateRoomIdWith
,
RCLog:
:
e
)
);
}
...
...
app/src/main/java/chat/rocket/android/service/observer/MethodCallObserver.java
View file @
f6ccb19b
package
chat
.
rocket
.
android
.
service
.
observer
;
import
android.content.Context
;
import
io.realm.Realm
;
import
io.realm.RealmResults
;
import
org.json.JSONObject
;
import
java.util.List
;
import
chat.rocket.android.helper.CheckSum
;
import
chat.rocket.android.helper.LogIfError
;
import
chat.rocket.android_ddp.rx.RxWebSocketCallback
;
import
chat.rocket.core.SyncState
;
import
chat.rocket.persistence.realm.models.internal.MethodCall
;
import
chat.rocket.persistence.realm.RealmHelper
;
import
chat.rocket.android.service.DDPClientRef
;
import
chat.rocket.android_ddp.DDPClientCallback
;
import
chat.rocket.core.SyncState
;
import
chat.rocket.persistence.realm.RealmHelper
;
import
chat.rocket.persistence.realm.models.internal.MethodCall
;
import
io.realm.Realm
;
import
io.realm.RealmResults
;
/**
* Observing MethodCall record, executing RPC if needed.
...
...
@@ -117,9 +118,6 @@ public class MethodCallObserver extends AbstractModelObserver<MethodCall> {
}
else
if
(
exception
instanceof
DDPClientCallback
.
RPC
.
Timeout
)
{
// temp "fix"- we need to rewrite the connection layer a bit
errMessage
=
"{\"message\": \"Connection Timeout\"}"
;
}
else
if
(
exception
instanceof
RxWebSocketCallback
.
Failure
)
{
// temp "fix"- we need to rewrite the connection layer a bit
errMessage
=
"{\"message\": \"Connection Failure\"}"
;
}
else
{
errMessage
=
exception
.
getMessage
();
}
...
...
app/src/main/res/values/strings.xml
View file @
f6ccb19b
...
...
@@ -14,14 +14,20 @@
<string
name=
"start_of_conversation"
>
Start of conversation
</string>
<string
name=
"users_of_room_title"
>
Members List
</string>
<string
name=
"fmt_room_user_count"
>
Total: %,d users
</string>
<plurals
name=
"fmt_room_user_count"
>
<item
quantity=
"one"
>
Total: %,d user
</item>
<item
quantity=
"other"
>
Total: %,d users
</item>
</plurals>
<string
name=
"sending"
>
Sending…
</string>
<string
name=
"not_synced"
>
Not synced
</string>
<string
name=
"failed_to_sync"
>
Failed to sync
</string>
<string
name=
"resend"
>
Resend
</string>
<string
name=
"discard"
>
Discard
</string>
<string
name=
"fmt_dialog_view_latest_message_title"
>
New %d messages
</string>
<plurals
name=
"fmt_dialog_view_latest_message_title"
>
<item
quantity=
"one"
>
New %d message
</item>
<item
quantity=
"other"
>
New %d messages
</item>
</plurals>
<string
name=
"dialog_view_latest_message_action"
>
View
</string>
<string
name=
"file_uploading_title"
>
Uploading…
</string>
...
...
circle.yml
View file @
f6ccb19b
...
...
@@ -7,7 +7,7 @@
machine
:
environment
:
ANDROID_HOME
:
/usr/local/android-sdk-linux
GRADLE_OPTS
:
'
-Dorg.gradle.jvmargs="-Xmx
2048
m
-XX:+HeapDumpOnOutOfMemoryError"'
GRADLE_OPTS
:
'
-Dorg.gradle.jvmargs="-Xmx
1536m
-XX:MaxPermSize=512
m
-XX:+HeapDumpOnOutOfMemoryError"'
dependencies
:
pre
:
...
...
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/RocketChatWidgets.java
View file @
f6ccb19b
package
chat
.
rocket
.
android
.
widget
;
import
android.content.Context
;
import
chat.rocket.android.widget.fresco.CustomImageFormatConfigurator
;
import
com.facebook.common.logging.FLog
;
import
com.facebook.drawee.backends.pipeline.DraweeConfig
;
import
com.facebook.drawee.backends.pipeline.Fresco
;
...
...
@@ -9,8 +9,11 @@ import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFact
import
com.facebook.imagepipeline.core.ImagePipelineConfig
;
import
com.facebook.imagepipeline.listener.RequestListener
;
import
com.facebook.imagepipeline.listener.RequestLoggingListener
;
import
java.util.HashSet
;
import
java.util.Set
;
import
chat.rocket.android.widget.fresco.CustomImageFormatConfigurator
;
import
okhttp3.OkHttpClient
;
public
class
RocketChatWidgets
{
...
...
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