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
d4f4c5b4
Unverified
Commit
d4f4c5b4
authored
Nov 01, 2017
by
Leonardo Aramaki
Committed by
GitHub
Nov 01, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #541 from RocketChat/fix/notifications
[WIP] New rewritten push notification handler
parents
9613b461
0846097e
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
846 additions
and
27 deletions
+846
-27
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+30
-1
RocketChatCache.java
app/src/main/java/chat/rocket/android/RocketChatCache.java
+69
-0
AbstractAuthedActivity.java
.../chat/rocket/android/activity/AbstractAuthedActivity.java
+32
-13
MainActivity.java
.../main/java/chat/rocket/android/activity/MainActivity.java
+13
-3
MainContract.java
.../main/java/chat/rocket/android/activity/MainContract.java
+2
-0
MainPresenter.java
...main/java/chat/rocket/android/activity/MainPresenter.java
+1
-0
MethodCallHelper.java
...c/main/java/chat/rocket/android/api/MethodCallHelper.java
+33
-2
RoomFragment.java
...a/chat/rocket/android/fragment/chatroom/RoomFragment.java
+4
-0
PushManager.kt
app/src/main/java/chat/rocket/android/push/PushManager.kt
+640
-0
GCMIntentService.java
...n/java/chat/rocket/android/push/gcm/GCMIntentService.java
+6
-6
ConnectivityManagerApi.java
...a/chat/rocket/android/service/ConnectivityManagerApi.java
+3
-0
RealmBasedConnectivityManager.java
...rocket/android/service/RealmBasedConnectivityManager.java
+6
-0
RocketChatService.java
...n/java/chat/rocket/android/service/RocketChatService.java
+4
-1
RocketChatWebSocketThread.java
...hat/rocket/android/service/RocketChatWebSocketThread.java
+3
-1
No files found.
app/src/main/AndroidManifest.xml
View file @
d4f4c5b4
...
...
@@ -5,6 +5,7 @@
<uses-permission
android:name=
"android.permission.ACCESS_NETWORK_STATE"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.WAKE_LOCK"
/>
<uses-permission
android:name=
"android.permission.VIBRATE"
/>
<permission
android:name=
"chat.rocket.android.permission.C2D_MESSAGE"
...
...
@@ -56,10 +57,32 @@
android:permission=
"com.google.android.c2dm.permission.SEND"
>
<intent-filter>
<action
android:name=
"com.google.android.c2dm.intent.RECEIVE"
/>
<category
android:name=
"com.example.gcm"
/>
<action
android:name=
"com.google.android.c2dm.intent.REGISTRATION"
/>
<category
android:name=
"chat.rocket.android"
/>
</intent-filter>
</receiver>
<receiver
android:name=
"com.google.firebase.iid.FirebaseInstanceIdReceiver"
android:exported=
"true"
android:permission=
"com.google.android.c2dm.permission.SEND"
>
<intent-filter>
<action
android:name=
"com.google.android.c2dm.intent.RECEIVE"
/>
<category
android:name=
"chat.rocket.android"
/>
</intent-filter>
</receiver>
<receiver
android:name=
"com.google.firebase.iid.FirebaseInstanceIdInternalReceiver"
android:exported=
"false"
/>
<service
android:name=
"com.google.firebase.iid.FirebaseInstanceIdService"
android:exported=
"true"
>
<intent-filter
android:priority=
"-500"
>
<action
android:name=
"com.google.firebase.INSTANCE_ID_EVENT"
/>
</intent-filter>
</service>
<service
android:name=
".push.gcm.GCMIntentService"
android:exported=
"false"
>
...
...
@@ -76,6 +99,12 @@
</intent-filter>
</service>
<receiver
android:name=
".push.PushManager$DeleteReceiver"
android:exported=
"false"
/>
<receiver
android:name=
".push.PushManager$ReplyReceiver"
android:exported=
"false"
/>
<meta-data
android:name=
"io.fabric.ApiKey"
android:value=
"12ac6e94f850aaffcdff52001af77ca415d06a43"
/>
...
...
app/src/main/java/chat/rocket/android/RocketChatCache.java
View file @
d4f4c5b4
...
...
@@ -22,12 +22,15 @@ import io.reactivex.BackpressureStrategy;
import
io.reactivex.Flowable
;
import
io.reactivex.annotations.NonNull
;
import
io.reactivex.annotations.Nullable
;
import
okhttp3.HttpUrl
;
/**
* sharedpreference-based cache.
*/
public
class
RocketChatCache
{
private
static
final
String
KEY_SELECTED_SERVER_HOSTNAME
=
"KEY_SELECTED_SERVER_HOSTNAME"
;
private
static
final
String
KEY_SELECTED_SITE_URL
=
"KEY_SELECTED_SITE_URL"
;
private
static
final
String
KEY_SELECTED_SITE_NAME
=
"KEY_SELECTED_SITE_NAME"
;
private
static
final
String
KEY_SELECTED_ROOM_ID
=
"KEY_SELECTED_ROOM_ID"
;
private
static
final
String
KEY_PUSH_ID
=
"KEY_PUSH_ID"
;
private
static
final
String
KEY_HOSTNAME_LIST
=
"KEY_HOSTNAME_LIST"
;
...
...
@@ -50,6 +53,72 @@ public class RocketChatCache {
setString
(
KEY_SELECTED_SERVER_HOSTNAME
,
newHostname
);
}
public
void
addHostSiteName
(
@NonNull
String
currentHostname
,
@NonNull
String
siteName
)
{
try
{
String
hostSiteNamesJson
=
getHostSiteNamesJson
();
JSONObject
jsonObject
=
(
hostSiteNamesJson
==
null
)
?
new
JSONObject
()
:
new
JSONObject
(
hostSiteNamesJson
);
jsonObject
.
put
(
currentHostname
,
siteName
);
setString
(
KEY_SELECTED_SITE_NAME
,
jsonObject
.
toString
());
}
catch
(
JSONException
e
)
{
RCLog
.
e
(
e
);
}
}
public
@NonNull
String
getHostSiteName
(
@NonNull
String
host
)
{
if
(
host
.
startsWith
(
"http"
))
{
HttpUrl
url
=
HttpUrl
.
parse
(
host
);
if
(
url
!=
null
)
{
host
=
url
.
host
();
}
}
try
{
String
hostSiteNamesJson
=
getHostSiteNamesJson
();
JSONObject
jsonObject
=
(
hostSiteNamesJson
==
null
)
?
new
JSONObject
()
:
new
JSONObject
(
hostSiteNamesJson
);
host
=
getSiteUrlFor
(
host
);
return
jsonObject
.
optString
(
host
);
}
catch
(
JSONException
e
)
{
RCLog
.
e
(
e
);
}
return
""
;
}
private
@Nullable
String
getHostSiteNamesJson
()
{
return
getString
(
KEY_SELECTED_SITE_NAME
,
null
);
}
public
void
addHostnameSiteUrl
(
@Nullable
String
hostnameAlias
,
@NonNull
String
currentHostname
)
{
String
alias
=
null
;
if
(
hostnameAlias
!=
null
)
{
alias
=
hostnameAlias
.
toLowerCase
();
}
try
{
String
selectedHostnameAliasJson
=
getLoginHostnamesJson
();
JSONObject
jsonObject
=
selectedHostnameAliasJson
==
null
?
new
JSONObject
()
:
new
JSONObject
(
selectedHostnameAliasJson
);
jsonObject
.
put
(
alias
,
currentHostname
);
setString
(
KEY_SELECTED_SITE_URL
,
jsonObject
.
toString
());
}
catch
(
JSONException
e
)
{
RCLog
.
e
(
e
);
}
}
public
@NonNull
String
getSiteUrlFor
(
String
hostname
)
{
try
{
String
selectedServerHostname
=
getSelectedServerHostname
();
return
new
JSONObject
(
getLoginHostnamesJson
())
.
optString
(
hostname
,
selectedServerHostname
);
}
catch
(
JSONException
e
)
{
RCLog
.
e
(
e
);
}
return
null
;
}
private
@Nullable
String
getLoginHostnamesJson
()
{
return
getString
(
KEY_SELECTED_SITE_URL
,
null
);
}
public
void
addHostname
(
@NonNull
String
hostname
,
@Nullable
String
hostnameAvatarUri
,
String
siteName
)
{
String
hostnameList
=
getString
(
KEY_HOSTNAME_LIST
,
null
);
try
{
...
...
app/src/main/java/chat/rocket/android/activity/AbstractAuthedActivity.java
View file @
d4f4c5b4
...
...
@@ -3,21 +3,24 @@ package chat.rocket.android.activity;
import
android.content.Intent
;
import
android.os.Bundle
;
import
android.support.annotation.Nullable
;
import
com.hadisatrio.optional.Optional
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.disposables.CompositeDisposable
;
import
io.reactivex.schedulers.Schedulers
;
import
java.util.List
;
import
chat.rocket.android.LaunchUtil
;
import
chat.rocket.android.RocketChatCache
;
import
chat.rocket.android.helper.Logger
;
import
chat.rocket.android.push.PushConstants
;
import
chat.rocket.android.push.PushNotificationHandler
;
import
chat.rocket.android.push.PushManager
;
import
chat.rocket.android.service.ConnectivityManager
;
import
chat.rocket.core.models.ServerInfo
;
import
chat.rocket.persistence.realm.RealmStore
;
import
chat.rocket.persistence.realm.models.ddp.RealmRoom
;
import
icepick.State
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.disposables.CompositeDisposable
;
import
io.reactivex.schedulers.Schedulers
;
import
okhttp3.HttpUrl
;
abstract
class
AbstractAuthedActivity
extends
AbstractFragmentActivity
{
@State
protected
String
hostname
;
...
...
@@ -53,20 +56,36 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
return
;
}
if
(
intent
.
hasExtra
(
PushConstants
.
HOSTNAME
))
{
rocketChatCache
.
setSelectedServerHostname
(
intent
.
getStringExtra
(
PushConstants
.
HOSTNAME
));
if
(
intent
.
hasExtra
(
PushConstants
.
ROOM_ID
))
{
rocketChatCache
.
setSelectedRoomId
(
intent
.
getStringExtra
(
PushConstants
.
ROOM_ID
));
if
(
intent
.
hasExtra
(
PushManager
.
EXTRA_HOSTNAME
))
{
String
hostname
=
intent
.
getStringExtra
(
PushManager
.
EXTRA_HOSTNAME
);
HttpUrl
url
=
HttpUrl
.
parse
(
hostname
);
if
(
url
!=
null
)
{
String
hostnameFromPush
=
url
.
host
();
String
loginHostname
=
rocketChatCache
.
getSiteUrlFor
(
hostnameFromPush
);
rocketChatCache
.
setSelectedServerHostname
(
loginHostname
);
if
(
intent
.
hasExtra
(
PushManager
.
EXTRA_ROOM_ID
))
{
rocketChatCache
.
setSelectedRoomId
(
intent
.
getStringExtra
(
PushManager
.
EXTRA_ROOM_ID
));
}
}
PushManager
.
INSTANCE
.
clearNotificationsByHost
(
hostname
);
}
else
{
updateHostnameIfNeeded
(
rocketChatCache
.
getSelectedServerHostname
());
}
if
(
intent
.
hasExtra
(
Push
Constants
.
NOT_ID
))
{
if
(
intent
.
hasExtra
(
Push
Manager
.
EXTRA_NOT_ID
)
&&
intent
.
hasExtra
(
PushManager
.
EXTRA_HOSTNAME
))
{
isNotification
=
true
;
PushNotificationHandler
.
cleanUpNotificationStack
(
intent
.
getIntExtra
(
PushConstants
.
NOT_ID
,
0
));
int
notificationId
=
intent
.
getIntExtra
(
PushManager
.
EXTRA_NOT_ID
,
0
);
String
hostname
=
intent
.
getStringExtra
(
PushManager
.
EXTRA_HOSTNAME
);
HttpUrl
url
=
HttpUrl
.
parse
(
hostname
);
if
(
url
!=
null
)
{
String
hostnameFromPush
=
url
.
host
();
String
loginHostname
=
rocketChatCache
.
getSiteUrlFor
(
hostnameFromPush
);
PushManager
.
INSTANCE
.
clearNotificationsByHostAndNotificationId
(
loginHostname
,
notificationId
);
}
else
{
PushManager
.
INSTANCE
.
clearNotificationsByNotificationId
(
notificationId
);
}
}
}
...
...
app/src/main/java/chat/rocket/android/activity/MainActivity.java
View file @
d4f4c5b4
...
...
@@ -74,8 +74,10 @@ public class MainActivity extends AbstractAuthedActivity implements MainContract
onHostnameUpdated
();
}
}
else
{
presenter
.
bindViewOnly
(
this
);
ConnectivityManager
.
getInstance
(
getApplicationContext
()).
keepAliveServer
();
presenter
.
bindView
(
this
);
presenter
.
loadSignedInServers
(
hostname
);
roomId
=
new
RocketChatCache
(
getApplicationContext
()).
getSelectedRoomId
();
}
}
...
...
@@ -172,7 +174,7 @@ public class MainActivity extends AbstractAuthedActivity implements MainContract
sessionInteractor
,
new
MethodCallHelper
(
this
,
hostname
),
ConnectivityManager
.
getInstance
(
getApplicationContext
()),
rocketChatCache
,
rocketChatCache
,
publicSettingRepository
);
...
...
@@ -302,6 +304,15 @@ public class MainActivity extends AbstractAuthedActivity implements MainContract
}
}
@Override
public
void
refreshRoom
()
{
Fragment
fragment
=
getSupportFragmentManager
().
findFragmentById
(
getLayoutContainerForFragment
());
if
(
fragment
!=
null
&&
fragment
instanceof
RoomFragment
)
{
RoomFragment
roomFragment
=
(
RoomFragment
)
fragment
;
roomFragment
.
loadMessages
();
}
}
private
void
changeServerIfNeeded
(
String
serverHostname
)
{
if
(!
hostname
.
equalsIgnoreCase
(
serverHostname
))
{
RocketChatCache
rocketChatCache
=
new
RocketChatCache
(
getApplicationContext
());
...
...
@@ -328,7 +339,6 @@ public class MainActivity extends AbstractAuthedActivity implements MainContract
public
static
final
int
STATUS_DISMISS
=
0
;
public
static
final
int
STATUS_CONNECTION_ERROR
=
1
;
public
static
final
int
STATUS_TOKEN_LOGIN
=
2
;
public
static
final
int
STATUS_LOGGING_OUT
=
3
;
private
int
status
;
private
Snackbar
snackbar
;
...
...
app/src/main/java/chat/rocket/android/activity/MainContract.java
View file @
d4f4c5b4
...
...
@@ -26,6 +26,8 @@ public interface MainContract {
void
showConnectionOk
();
void
showSignedInServers
(
List
<
Pair
<
String
,
Pair
<
String
,
String
>>>
serverList
);
void
refreshRoom
();
}
interface
Presenter
extends
BaseContract
.
Presenter
<
View
>
{
...
...
app/src/main/java/chat/rocket/android/activity/MainPresenter.java
View file @
d4f4c5b4
...
...
@@ -225,6 +225,7 @@ public class MainPresenter extends BasePresenter<MainContract.View>
connectivity
->
{
if
(
connectivity
.
state
==
ServerConnectivity
.
STATE_CONNECTED
)
{
view
.
showConnectionOk
();
view
.
refreshRoom
();
return
;
}
view
.
showConnecting
();
...
...
app/src/main/java/chat/rocket/android/api/MethodCallHelper.java
View file @
d4f4c5b4
...
...
@@ -11,11 +11,13 @@ import java.util.UUID;
import
bolts.Continuation
;
import
bolts.Task
;
import
chat.rocket.android.RocketChatCache
;
import
chat.rocket.android.helper.CheckSum
;
import
chat.rocket.android.helper.TextUtils
;
import
chat.rocket.android.service.ConnectivityManager
;
import
chat.rocket.android.service.DDPClientRef
;
import
chat.rocket.android_ddp.DDPClientCallback
;
import
chat.rocket.core.PublicSettingsConstants
;
import
chat.rocket.core.SyncState
;
import
chat.rocket.persistence.realm.RealmHelper
;
import
chat.rocket.persistence.realm.RealmStore
;
...
...
@@ -30,6 +32,7 @@ import chat.rocket.persistence.realm.models.ddp.RealmSpotlightUser;
import
chat.rocket.persistence.realm.models.internal.MethodCall
;
import
chat.rocket.persistence.realm.models.internal.RealmSession
;
import
hugo.weaving.DebugLog
;
import
okhttp3.HttpUrl
;
/**
* Utility class for creating/handling MethodCall or RPC.
...
...
@@ -65,6 +68,12 @@ public class MethodCallHelper {
this
.
ddpClientRef
=
ddpClientRef
;
}
public
MethodCallHelper
(
Context
context
,
RealmHelper
realmHelper
,
DDPClientRef
ddpClientRef
)
{
this
.
context
=
context
.
getApplicationContext
();
this
.
realmHelper
=
realmHelper
;
this
.
ddpClientRef
=
ddpClientRef
;
}
@DebugLog
private
Task
<
String
>
executeMethodCall
(
String
methodName
,
String
param
,
long
timeout
)
{
if
(
ddpClientRef
!=
null
)
{
...
...
@@ -422,13 +431,31 @@ public class MethodCallHelper {
.
onSuccessTask
(
task
->
Task
.
forResult
(
null
));
}
public
Task
<
Void
>
getPublicSettings
()
{
public
Task
<
Void
>
getPublicSettings
(
String
currentHostname
)
{
return
call
(
"public-settings/get"
,
TIMEOUT_MS
)
.
onSuccessTask
(
CONVERT_TO_JSON_ARRAY
)
.
onSuccessTask
(
task
->
{
final
JSONArray
settings
=
task
.
getResult
();
String
siteUrl
=
null
;
String
siteName
=
null
;
for
(
int
i
=
0
;
i
<
settings
.
length
();
i
++)
{
RealmPublicSetting
.
customizeJson
(
settings
.
getJSONObject
(
i
));
JSONObject
jsonObject
=
settings
.
getJSONObject
(
i
);
RealmPublicSetting
.
customizeJson
(
jsonObject
);
if
(
isPublicSetting
(
jsonObject
,
PublicSettingsConstants
.
General
.
SITE_URL
))
{
siteUrl
=
jsonObject
.
getString
(
RealmPublicSetting
.
VALUE
);
}
else
if
(
isPublicSetting
(
jsonObject
,
PublicSettingsConstants
.
General
.
SITE_NAME
))
{
siteName
=
jsonObject
.
getString
(
RealmPublicSetting
.
VALUE
);
}
}
if
(
siteName
!=
null
&&
siteUrl
!=
null
)
{
HttpUrl
httpSiteUrl
=
HttpUrl
.
parse
(
siteUrl
);
if
(
httpSiteUrl
!=
null
)
{
String
host
=
httpSiteUrl
.
host
();
RocketChatCache
rocketChatCache
=
new
RocketChatCache
(
context
);
rocketChatCache
.
addHostnameSiteUrl
(
host
,
currentHostname
);
rocketChatCache
.
addHostSiteName
(
currentHostname
,
siteName
);
}
}
return
realmHelper
.
executeTransaction
(
realm
->
{
...
...
@@ -439,6 +466,10 @@ public class MethodCallHelper {
});
}
private
boolean
isPublicSetting
(
JSONObject
jsonObject
,
String
id
)
{
return
jsonObject
.
optString
(
RealmPublicSetting
.
ID
).
equalsIgnoreCase
(
id
);
}
public
Task
<
Void
>
getPermissions
()
{
return
call
(
"permissions/get"
,
TIMEOUT_MS
)
.
onSuccessTask
(
CONVERT_TO_JSON_ARRAY
)
...
...
app/src/main/java/chat/rocket/android/fragment/chatroom/RoomFragment.java
View file @
d4f4c5b4
...
...
@@ -715,4 +715,8 @@ public class RoomFragment extends AbstractChatRoomFragment implements
startActivity
(
intent
);
}
}
public
void
loadMessages
()
{
presenter
.
loadMessages
();
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/push/PushManager.kt
0 → 100644
View file @
d4f4c5b4
package
chat.rocket.android.push
import
android.app.Notification
import
android.app.NotificationChannel
import
android.app.NotificationManager
import
android.app.PendingIntent
import
android.content.BroadcastReceiver
import
android.content.Context
import
android.content.Intent
import
android.graphics.drawable.Icon
import
android.os.Build
import
android.os.Bundle
import
android.support.annotation.RequiresApi
import
android.support.v4.app.NotificationCompat
import
android.support.v4.app.NotificationManagerCompat
import
android.support.v4.app.RemoteInput
import
android.text.Html
import
android.text.Spanned
import
android.util.Log
import
chat.rocket.android.BackgroundLooper
import
chat.rocket.android.BuildConfig
import
chat.rocket.android.R
import
chat.rocket.android.RocketChatCache
import
chat.rocket.android.activity.MainActivity
import
chat.rocket.android.helper.Logger
import
chat.rocket.core.interactors.MessageInteractor
import
chat.rocket.core.models.Room
import
chat.rocket.core.models.User
import
chat.rocket.persistence.realm.repositories.RealmMessageRepository
import
chat.rocket.persistence.realm.repositories.RealmRoomRepository
import
chat.rocket.persistence.realm.repositories.RealmUserRepository
import
io.reactivex.Single
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.functions.BiFunction
import
okhttp3.HttpUrl
import
org.json.JSONObject
import
java.io.Serializable
import
java.util.*
import
java.util.concurrent.atomic.AtomicInteger
import
kotlin.collections.HashMap
typealias
TupleRoomUser
=
Pair
<
Room
,
User
>
typealias
TupleGroupIdMessageCount
=
Pair
<
Int
,
AtomicInteger
>
object
PushManager
{
const
val
EXTRA_NOT_ID
=
"chat.rocket.android.EXTRA_NOT_ID"
const
val
EXTRA_HOSTNAME
=
"chat.rocket.android.EXTRA_HOSTNAME"
const
val
EXTRA_PUSH_MESSAGE
=
"chat.rocket.android.EXTRA_PUSH_MESSAGE"
const
val
EXTRA_ROOM_ID
=
"chat.rocket.android.EXTRA_ROOM_ID"
private
const
val
REPLY_LABEL
=
"REPLY"
private
const
val
REMOTE_INPUT_REPLY
=
"REMOTE_INPUT_REPLY"
// Notifications received from the same server are grouped in a single bundled notification.
// This map associates a host to a group id.
private
val
groupMap
=
HashMap
<
String
,
TupleGroupIdMessageCount
>()
// Map a hostname to a list of push messages that pertain to it.
private
val
hostToPushMessageList
=
HashMap
<
String
,
MutableList
<
PushMessage
>>()
private
val
randomizer
=
Random
()
/**
* Handles a receiving push by creating and displaying an appropriate notification based
* on the *data* param bundle received.
*/
@Synchronized
fun
handle
(
context
:
Context
,
data
:
Bundle
)
{
val
appContext
=
context
.
applicationContext
val
message
=
data
[
"message"
]
as
String
val
image
=
data
[
"image"
]
as
String
val
ejson
=
data
[
"ejson"
]
as
String
val
notId
=
data
[
"notId"
]
as
String
val
style
=
data
[
"style"
]
as
String
val
summaryText
=
data
[
"summaryText"
]
as
String
val
count
=
data
[
"count"
]
as
String
val
title
=
data
[
"title"
]
as
String
val
lastPushMessage
=
PushMessage
(
title
,
message
,
image
,
ejson
,
count
,
notId
,
summaryText
,
style
)
// We should use Timber here
if
(
BuildConfig
.
DEBUG
)
{
Log
.
d
(
PushMessage
::
class
.
java
.
simpleName
,
lastPushMessage
.
toString
())
}
showNotification
(
appContext
,
lastPushMessage
)
}
/**
* Clear all messages received to a given host the user is signed-in.
*/
fun
clearNotificationsByHost
(
host
:
String
)
{
hostToPushMessageList
.
remove
(
host
)
}
fun
clearNotificationsByNotificationId
(
notificationId
:
Int
)
{
if
(
hostToPushMessageList
.
isNotEmpty
())
{
for
(
entry
in
hostToPushMessageList
.
entries
)
{
entry
.
value
.
removeAll
{
it
.
notificationId
.
toInt
()
==
notificationId
}
}
}
}
fun
clearNotificationsByHostAndNotificationId
(
host
:
String
,
notificationId
:
Int
)
{
if
(
hostToPushMessageList
.
isNotEmpty
())
{
val
notifications
=
hostToPushMessageList
[
host
]
notifications
?.
let
{
notifications
.
removeAll
{
it
.
notificationId
.
toInt
()
==
notificationId
}
}
}
}
private
fun
isAndroidVersionAtLeast
(
minVersion
:
Int
)
=
Build
.
VERSION
.
SDK_INT
>=
minVersion
private
fun
getGroupForHost
(
host
:
String
):
TupleGroupIdMessageCount
{
val
size
=
groupMap
.
size
var
group
=
groupMap
.
get
(
host
)
if
(
group
==
null
)
{
group
=
TupleGroupIdMessageCount
(
size
+
1
,
AtomicInteger
(
0
))
groupMap
.
put
(
host
,
group
)
}
return
group
}
private
fun
showNotification
(
context
:
Context
,
lastPushMessage
:
PushMessage
)
{
val
manager
:
NotificationManager
=
context
.
getSystemService
(
Context
.
NOTIFICATION_SERVICE
)
as
NotificationManager
val
notId
=
lastPushMessage
.
notificationId
.
toInt
()
val
host
=
lastPushMessage
.
host
val
groupTuple
=
getGroupForHost
(
host
)
groupTuple
.
second
.
incrementAndGet
()
val
notIdListForHostname
:
MutableList
<
PushMessage
>?
=
hostToPushMessageList
.
get
(
host
)
if
(
notIdListForHostname
==
null
)
{
hostToPushMessageList
.
put
(
host
,
arrayListOf
(
lastPushMessage
))
}
else
{
notIdListForHostname
.
add
(
0
,
lastPushMessage
)
}
if
(
isAndroidVersionAtLeast
(
Build
.
VERSION_CODES
.
N
))
{
val
notification
=
createSingleNotificationForNougatAndAbove
(
context
,
lastPushMessage
)
val
groupNotification
=
createGroupNotificationForNougatAndAbove
(
context
,
lastPushMessage
)
manager
.
notify
(
notId
,
notification
)
manager
.
notify
(
groupTuple
.
first
,
groupNotification
)
}
else
{
val
notification
=
createSingleNotification
(
context
,
lastPushMessage
)
val
pushMessageList
=
hostToPushMessageList
.
get
(
host
)
NotificationManagerCompat
.
from
(
context
).
notify
(
notId
,
notification
)
pushMessageList
?.
let
{
if
(
pushMessageList
.
size
>
1
)
{
val
groupNotification
=
createGroupNotification
(
context
,
lastPushMessage
)
NotificationManagerCompat
.
from
(
context
).
notify
(
groupTuple
.
first
,
groupNotification
)
}
}
}
}
private
fun
createGroupNotification
(
context
:
Context
,
lastPushMessage
:
PushMessage
):
Notification
{
with
(
lastPushMessage
)
{
val
id
=
lastPushMessage
.
notificationId
.
toInt
()
val
contentIntent
=
getContentIntent
(
context
,
id
,
lastPushMessage
)
val
deleteIntent
=
getDismissIntent
(
context
,
lastPushMessage
)
val
builder
=
NotificationCompat
.
Builder
(
context
)
.
setWhen
(
createdAt
)
.
setContentTitle
(
title
.
fromHtml
())
.
setContentText
(
message
.
fromHtml
())
.
setGroup
(
host
)
.
setGroupSummary
(
true
)
.
setContentIntent
(
contentIntent
)
.
setDeleteIntent
(
deleteIntent
)
.
setMessageNotification
()
val
subText
=
RocketChatCache
(
context
).
getHostSiteName
(
host
)
if
(
subText
.
isNotEmpty
())
{
builder
.
setSubText
(
subText
)
}
if
(
style
==
"inbox"
)
{
val
pushMessageList
=
hostToPushMessageList
.
get
(
host
)
pushMessageList
?.
let
{
val
messageCount
=
pushMessageList
.
size
val
summary
=
summaryText
.
replace
(
"%n%"
,
messageCount
.
toString
())
.
fromHtml
()
builder
.
setNumber
(
messageCount
)
if
(
messageCount
>
1
)
{
val
firstPush
=
pushMessageList
[
0
]
val
singleConversation
=
pushMessageList
.
filter
{
firstPush
.
sender
.
username
!=
it
.
sender
.
username
}.
isEmpty
()
val
inbox
=
NotificationCompat
.
InboxStyle
()
.
setBigContentTitle
(
if
(
singleConversation
)
title
else
summary
)
for
(
push
in
pushMessageList
)
{
if
(
singleConversation
)
{
inbox
.
addLine
(
push
.
message
)
}
else
{
inbox
.
addLine
(
"<font color='black'>${push.title}</font> <font color='gray'>${push.message}</font>"
.
fromHtml
())
}
}
builder
.
setStyle
(
inbox
)
}
else
{
val
bigText
=
NotificationCompat
.
BigTextStyle
()
.
bigText
(
pushMessageList
[
0
].
message
.
fromHtml
())
.
setBigContentTitle
(
pushMessageList
[
0
].
title
.
fromHtml
())
builder
.
setStyle
(
bigText
)
}
}
}
else
{
val
bigText
=
NotificationCompat
.
BigTextStyle
()
.
bigText
(
message
.
fromHtml
())
.
setBigContentTitle
(
title
.
fromHtml
())
builder
.
setStyle
(
bigText
)
}
return
builder
.
build
()
}
}
@RequiresApi
(
Build
.
VERSION_CODES
.
N
)
private
fun
createGroupNotificationForNougatAndAbove
(
context
:
Context
,
lastPushMessage
:
PushMessage
):
Notification
{
with
(
lastPushMessage
)
{
val
manager
:
NotificationManager
=
context
.
getSystemService
(
Context
.
NOTIFICATION_SERVICE
)
as
NotificationManager
val
id
=
notificationId
.
toInt
()
val
contentIntent
=
getContentIntent
(
context
,
id
,
lastPushMessage
,
grouped
=
true
)
val
deleteIntent
=
getDismissIntent
(
context
,
lastPushMessage
)
val
builder
=
Notification
.
Builder
(
context
)
.
setWhen
(
createdAt
)
.
setContentTitle
(
title
.
fromHtml
())
.
setContentText
(
message
.
fromHtml
())
.
setGroup
(
host
)
.
setGroupSummary
(
true
)
.
setContentIntent
(
contentIntent
)
.
setDeleteIntent
(
deleteIntent
)
.
setMessageNotification
(
context
)
if
(
isAndroidVersionAtLeast
(
Build
.
VERSION_CODES
.
O
))
{
builder
.
setChannelId
(
host
)
val
groupChannel
=
NotificationChannel
(
host
,
host
,
NotificationManager
.
IMPORTANCE_HIGH
)
groupChannel
.
lockscreenVisibility
=
Notification
.
VISIBILITY_PUBLIC
groupChannel
.
enableLights
(
false
)
groupChannel
.
enableVibration
(
true
)
groupChannel
.
setShowBadge
(
true
)
manager
.
createNotificationChannel
(
groupChannel
)
}
val
subText
=
RocketChatCache
(
context
).
getHostSiteName
(
host
)
if
(
subText
.
isNotEmpty
())
{
builder
.
setSubText
(
subText
)
}
if
(
style
==
"inbox"
)
{
val
pushMessageList
=
hostToPushMessageList
.
get
(
host
)
pushMessageList
?.
let
{
val
count
=
pushMessageList
.
filter
{
it
.
title
==
title
}.
size
builder
.
setContentTitle
(
getTitle
(
count
,
title
))
val
inbox
=
Notification
.
InboxStyle
()
.
setBigContentTitle
(
getTitle
(
count
,
title
))
for
(
push
in
pushMessageList
)
{
inbox
.
addLine
(
push
.
message
)
}
builder
.
setStyle
(
inbox
)
}
}
else
{
val
bigText
=
Notification
.
BigTextStyle
()
.
bigText
(
message
.
fromHtml
())
.
setBigContentTitle
(
title
.
fromHtml
())
builder
.
setStyle
(
bigText
)
}
return
builder
.
build
()
}
}
private
fun
createSingleNotification
(
context
:
Context
,
lastPushMessage
:
PushMessage
):
Notification
{
with
(
lastPushMessage
)
{
val
id
=
notificationId
.
toInt
()
val
contentIntent
=
getContentIntent
(
context
,
id
,
lastPushMessage
)
val
deleteIntent
=
getDismissIntent
(
context
,
lastPushMessage
)
val
builder
=
NotificationCompat
.
Builder
(
context
)
.
setWhen
(
createdAt
)
.
setContentTitle
(
title
.
fromHtml
())
.
setContentText
(
message
.
fromHtml
())
.
setGroupSummary
(
false
)
.
setGroup
(
host
)
.
setDeleteIntent
(
deleteIntent
)
.
setContentIntent
(
contentIntent
)
.
setMessageNotification
()
val
subText
=
RocketChatCache
(
context
).
getHostSiteName
(
lastPushMessage
.
host
)
if
(
subText
.
isNotEmpty
())
{
builder
.
setSubText
(
subText
)
}
val
pushMessageList
=
hostToPushMessageList
.
get
(
host
)
pushMessageList
?.
let
{
if
(
pushMessageList
.
isNotEmpty
())
{
val
messageCount
=
pushMessageList
.
size
val
bigText
=
NotificationCompat
.
BigTextStyle
()
.
bigText
(
pushMessageList
.
last
().
message
.
fromHtml
())
.
setBigContentTitle
(
pushMessageList
.
last
().
title
.
fromHtml
())
builder
.
setStyle
(
bigText
).
setNumber
(
messageCount
)
}
}
return
builder
.
build
()
}
}
@RequiresApi
(
Build
.
VERSION_CODES
.
N
)
private
fun
createSingleNotificationForNougatAndAbove
(
context
:
Context
,
lastPushMessage
:
PushMessage
):
Notification
{
val
manager
:
NotificationManager
=
context
.
getSystemService
(
Context
.
NOTIFICATION_SERVICE
)
as
NotificationManager
with
(
lastPushMessage
)
{
val
id
=
notificationId
.
toInt
()
val
contentIntent
=
getContentIntent
(
context
,
id
,
lastPushMessage
)
val
deleteIntent
=
getDismissIntent
(
context
,
lastPushMessage
)
val
builder
=
Notification
.
Builder
(
context
)
.
setWhen
(
createdAt
)
.
setContentTitle
(
title
.
fromHtml
())
.
setContentText
(
message
.
fromHtml
())
.
setGroup
(
host
)
.
setGroupSummary
(
false
)
.
setDeleteIntent
(
deleteIntent
)
.
setContentIntent
(
contentIntent
)
.
setMessageNotification
(
context
)
.
addReplyAction
(
context
,
lastPushMessage
)
if
(
isAndroidVersionAtLeast
(
android
.
os
.
Build
.
VERSION_CODES
.
O
))
{
builder
.
setChannelId
(
host
)
val
channel
=
NotificationChannel
(
host
,
host
,
NotificationManager
.
IMPORTANCE_HIGH
)
channel
.
lockscreenVisibility
=
Notification
.
VISIBILITY_PUBLIC
channel
.
enableLights
(
false
)
channel
.
enableVibration
(
true
)
channel
.
setShowBadge
(
true
)
manager
.
createNotificationChannel
(
channel
)
}
val
subText
=
RocketChatCache
(
context
).
getHostSiteName
(
lastPushMessage
.
host
)
if
(
subText
.
isNotEmpty
())
{
builder
.
setSubText
(
subText
)
}
if
(
"inbox"
==
style
)
{
val
pushMessageList
=
hostToPushMessageList
.
get
(
host
)
pushMessageList
?.
let
{
val
userMessages
=
pushMessageList
.
filter
{
it
.
notificationId
==
lastPushMessage
.
notificationId
}
val
count
=
pushMessageList
.
filter
{
it
.
title
==
title
}.
size
builder
.
setContentTitle
(
getTitle
(
count
,
title
))
if
(
count
>
1
)
{
val
inbox
=
Notification
.
InboxStyle
()
inbox
.
setBigContentTitle
(
getTitle
(
count
,
title
))
for
(
push
in
userMessages
)
{
inbox
.
addLine
(
push
.
message
)
}
builder
.
setStyle
(
inbox
)
}
else
{
val
bigTextStyle
=
Notification
.
BigTextStyle
()
.
bigText
(
message
.
fromHtml
())
builder
.
setStyle
(
bigTextStyle
)
}
}
}
else
{
val
bigTextStyle
=
Notification
.
BigTextStyle
()
.
bigText
(
message
.
fromHtml
())
builder
.
setStyle
(
bigTextStyle
)
}
return
builder
.
build
()
}
}
private
fun
getTitle
(
messageCount
:
Int
,
title
:
String
):
CharSequence
{
return
if
(
messageCount
>
1
)
"($messageCount) ${title.fromHtml()}"
else
title
.
fromHtml
()
}
private
fun
getDismissIntent
(
context
:
Context
,
pushMessage
:
PushMessage
):
PendingIntent
{
val
deleteIntent
=
Intent
(
context
,
DeleteReceiver
::
class
.
java
)
.
putExtra
(
EXTRA_NOT_ID
,
pushMessage
.
notificationId
.
toInt
())
.
putExtra
(
EXTRA_HOSTNAME
,
pushMessage
.
host
)
return
PendingIntent
.
getBroadcast
(
context
,
pushMessage
.
notificationId
.
toInt
(),
deleteIntent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
)
}
private
fun
getContentIntent
(
context
:
Context
,
notificationId
:
Int
,
pushMessage
:
PushMessage
,
grouped
:
Boolean
=
false
):
PendingIntent
{
val
notificationIntent
=
Intent
(
context
,
MainActivity
::
class
.
java
)
.
addFlags
(
Intent
.
FLAG_ACTIVITY_SINGLE_TOP
or
Intent
.
FLAG_ACTIVITY_CLEAR_TOP
)
.
putExtra
(
EXTRA_NOT_ID
,
notificationId
)
.
putExtra
(
EXTRA_HOSTNAME
,
pushMessage
.
host
)
if
(!
grouped
)
{
notificationIntent
.
putExtra
(
EXTRA_ROOM_ID
,
pushMessage
.
rid
)
}
return
PendingIntent
.
getActivity
(
context
,
randomizer
.
nextInt
(),
notificationIntent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
)
}
// CharSequence extensions
private
fun
CharSequence
.
fromHtml
():
Spanned
{
return
Html
.
fromHtml
(
this
as
String
)
}
//Notification.Builder extensions
@RequiresApi
(
Build
.
VERSION_CODES
.
N
)
private
fun
Notification
.
Builder
.
addReplyAction
(
ctx
:
Context
,
pushMessage
:
PushMessage
):
Notification
.
Builder
{
val
replyRemoteInput
=
android
.
app
.
RemoteInput
.
Builder
(
REMOTE_INPUT_REPLY
)
.
setLabel
(
REPLY_LABEL
)
.
build
()
val
replyIntent
=
Intent
(
ctx
,
ReplyReceiver
::
class
.
java
)
replyIntent
.
putExtra
(
EXTRA_PUSH_MESSAGE
,
pushMessage
as
Serializable
)
val
pendingIntent
=
PendingIntent
.
getBroadcast
(
ctx
,
randomizer
.
nextInt
(),
replyIntent
,
0
)
val
replyAction
=
Notification
.
Action
.
Builder
(
Icon
.
createWithResource
(
ctx
,
R
.
drawable
.
ic_reply
),
REPLY_LABEL
,
pendingIntent
)
.
addRemoteInput
(
replyRemoteInput
)
.
setAllowGeneratedReplies
(
true
)
.
build
()
this
.
addAction
(
replyAction
)
return
this
}
@RequiresApi
(
Build
.
VERSION_CODES
.
N
)
private
fun
Notification
.
Builder
.
setMessageNotification
(
ctx
:
Context
):
Notification
.
Builder
{
val
res
=
ctx
.
resources
val
smallIcon
=
res
.
getIdentifier
(
"rocket_chat_notification"
,
"drawable"
,
ctx
.
packageName
)
with
(
this
,
{
setAutoCancel
(
true
)
setShowWhen
(
true
)
setColor
(
res
.
getColor
(
R
.
color
.
colorRed400
,
ctx
.
theme
))
setSmallIcon
(
smallIcon
)
})
return
this
}
// NotificationCompat.Builder extensions
private
fun
NotificationCompat
.
Builder
.
addReplyAction
(
pushMessage
:
PushMessage
):
NotificationCompat
.
Builder
{
val
context
=
this
.
mContext
val
replyRemoteInput
=
RemoteInput
.
Builder
(
REMOTE_INPUT_REPLY
)
.
setLabel
(
REPLY_LABEL
)
.
build
()
val
replyIntent
=
Intent
(
context
,
ReplyReceiver
::
class
.
java
)
replyIntent
.
putExtra
(
EXTRA_PUSH_MESSAGE
,
pushMessage
as
Serializable
)
val
pendingIntent
=
PendingIntent
.
getBroadcast
(
context
,
randomizer
.
nextInt
(),
replyIntent
,
0
)
val
replyAction
=
NotificationCompat
.
Action
.
Builder
(
R
.
drawable
.
ic_reply
,
REPLY_LABEL
,
pendingIntent
)
.
addRemoteInput
(
replyRemoteInput
)
.
setAllowGeneratedReplies
(
true
)
.
build
()
this
.
addAction
(
replyAction
)
return
this
}
private
fun
NotificationCompat
.
Builder
.
setMessageNotification
():
NotificationCompat
.
Builder
{
val
ctx
=
this
.
mContext
val
res
=
ctx
.
resources
val
smallIcon
=
res
.
getIdentifier
(
"rocket_chat_notification"
,
"drawable"
,
ctx
.
packageName
)
with
(
this
,
{
setAutoCancel
(
true
)
setShowWhen
(
true
)
setColor
(
ctx
.
resources
.
getColor
(
R
.
color
.
colorRed400
))
setDefaults
(
Notification
.
DEFAULT_ALL
)
setSmallIcon
(
smallIcon
)
})
return
this
}
private
data class
PushMessage
(
val
title
:
String
,
val
message
:
String
,
val
image
:
String
?,
val
ejson
:
String
,
val
count
:
String
,
val
notificationId
:
String
,
val
summaryText
:
String
,
val
style
:
String
)
:
Serializable
{
val
host
:
String
val
rid
:
String
val
type
:
String
val
name
:
String
?
val
sender
:
Sender
val
createdAt
:
Long
init
{
val
json
=
JSONObject
(
ejson
)
host
=
json
.
getString
(
"host"
)
rid
=
json
.
getString
(
"rid"
)
type
=
json
.
getString
(
"type"
)
name
=
json
.
optString
(
"name"
)
sender
=
Sender
(
json
.
getString
(
"sender"
))
createdAt
=
System
.
currentTimeMillis
()
}
data class
Sender
(
val
sender
:
String
)
:
Serializable
{
val
_id
:
String
val
username
:
String
val
name
:
String
init
{
val
json
=
JSONObject
(
sender
)
_id
=
json
.
getString
(
"_id"
)
username
=
json
.
getString
(
"username"
)
name
=
json
.
getString
(
"name"
)
}
}
}
/**
* BroadcastReceiver for dismissed notifications.
*/
class
DeleteReceiver
:
BroadcastReceiver
()
{
override
fun
onReceive
(
context
:
Context
?,
intent
:
Intent
?)
{
val
notId
=
intent
?.
extras
?.
getInt
(
EXTRA_NOT_ID
)
val
host
=
intent
?.
extras
?.
getString
(
EXTRA_HOSTNAME
)
if
(
host
!=
null
&&
notId
!=
null
)
{
clearNotificationsByHostAndNotificationId
(
host
,
notId
)
}
}
}
/**
* *EXPERIMENTAL*
*
* BroadcastReceiver for notifications' replies using Direct Reply feature (Android >= 7).
*/
class
ReplyReceiver
:
BroadcastReceiver
()
{
override
fun
onReceive
(
context
:
Context
?,
intent
:
Intent
?)
{
if
(
context
==
null
)
{
return
}
synchronized
(
this
)
{
val
manager
=
context
.
getSystemService
(
Context
.
NOTIFICATION_SERVICE
)
as
NotificationManager
val
message
:
CharSequence
?
=
extractMessage
(
intent
)
val
pushMessage
=
intent
?.
extras
?.
getSerializable
(
EXTRA_PUSH_MESSAGE
)
as
PushMessage
?
pushMessage
?.
let
{
val
userNotId
=
pushMessage
.
notificationId
.
toInt
()
val
groupTuple
=
groupMap
.
get
(
pushMessage
.
host
)
val
pushes
=
hostToPushMessageList
.
get
(
pushMessage
.
host
)
pushes
?.
let
{
val
allMessagesFromSameUser
=
pushes
.
filter
{
it
.
sender
.
_id
==
pushMessage
.
sender
.
_id
}
for
(
msg
in
allMessagesFromSameUser
)
{
manager
.
cancel
(
msg
.
notificationId
.
toInt
())
groupTuple
?.
second
?.
decrementAndGet
()
}
groupTuple
?.
let
{
val
groupNotId
=
groupTuple
.
first
val
totalNot
=
groupTuple
.
second
.
get
()
if
(
totalNot
==
0
)
{
manager
.
cancel
(
groupNotId
)
}
}
message
?.
let
{
val
httpUrl
=
HttpUrl
.
parse
(
pushMessage
.
host
)
httpUrl
?.
let
{
sendMessage
(
RocketChatCache
(
context
).
getSiteUrlFor
(
httpUrl
.
host
()),
message
,
pushMessage
.
rid
)
}
}
}
}
}
}
private
fun
extractMessage
(
intent
:
Intent
?):
CharSequence
?
{
val
remoteInput
:
Bundle
?
=
RemoteInput
.
getResultsFromIntent
(
intent
)
return
remoteInput
?.
getCharSequence
(
REMOTE_INPUT_REPLY
)
}
// Just kept for reference. We should use this on rewrite with job schedulers
private
fun
sendMessage
(
hostname
:
String
,
message
:
CharSequence
,
roomId
:
String
)
{
val
roomRepository
=
RealmRoomRepository
(
hostname
)
val
userRepository
=
RealmUserRepository
(
hostname
)
val
messageRepository
=
RealmMessageRepository
(
hostname
)
val
messageInteractor
=
MessageInteractor
(
messageRepository
,
roomRepository
)
val
singleRoom
:
Single
<
Room
>
=
roomRepository
.
getById
(
roomId
)
.
filter
({
it
.
isPresent
})
.
map
({
it
.
get
()
})
.
firstElement
()
.
toSingle
()
val
singleUser
:
Single
<
User
>
=
userRepository
.
getCurrent
()
.
filter
({
it
.
isPresent
})
.
map
({
it
.
get
()
})
.
firstElement
()
.
toSingle
()
val
roomUserTuple
:
Single
<
TupleRoomUser
>
=
Single
.
zip
(
singleRoom
,
singleUser
,
BiFunction
{
room
,
user
->
TupleRoomUser
(
room
,
user
)
})
roomUserTuple
.
flatMap
{
tuple
->
messageInteractor
.
send
(
tuple
.
first
,
tuple
.
second
,
message
as
String
)
}
.
subscribeOn
(
AndroidSchedulers
.
from
(
BackgroundLooper
.
get
()))
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
subscribe
({
success
->
// Empty
},
{
throwable
->
throwable
.
printStackTrace
()
Logger
.
report
(
throwable
)
})
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/push/gcm/GCMIntentService.java
View file @
d4f4c5b4
package
chat
.
rocket
.
android
.
push
.
gcm
;
import
com.google.android.gms.gcm.GcmListenerService
;
import
android.annotation.SuppressLint
;
import
android.content.Context
;
import
android.content.res.Resources
;
import
android.os.Bundle
;
import
android.util.Log
;
import
com.google.android.gms.gcm.GcmListenerService
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
chat.rocket.android.push.PushConstants
;
import
chat.rocket.android.push.Push
NotificationHandl
er
;
import
chat.rocket.android.push.Push
Manag
er
;
@SuppressLint
(
"NewApi"
)
public
class
GCMIntentService
extends
GcmListenerService
implements
PushConstants
{
...
...
@@ -33,9 +35,7 @@ public class GCMIntentService extends GcmListenerService implements PushConstant
extras
=
normalizeExtras
(
applicationContext
,
extras
);
PushNotificationHandler
pushNotificationHandler
=
new
PushNotificationHandler
();
pushNotificationHandler
.
showNotificationIfPossible
(
applicationContext
,
extras
);
PushManager
.
INSTANCE
.
handle
(
applicationContext
,
extras
);
}
/*
...
...
app/src/main/java/chat/rocket/android/service/ConnectivityManagerApi.java
View file @
d4f4c5b4
package
chat
.
rocket
.
android
.
service
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
java.util.List
;
...
...
@@ -22,4 +23,6 @@ public interface ConnectivityManagerApi {
List
<
ServerInfo
>
getServerList
();
Observable
<
ServerConnectivity
>
getServerConnectivityAsObservable
();
int
getConnectivityState
(
@NonNull
String
hostname
);
}
app/src/main/java/chat/rocket/android/service/RealmBasedConnectivityManager.java
View file @
d4f4c5b4
...
...
@@ -4,6 +4,7 @@ import android.content.ComponentName;
import
android.content.Context
;
import
android.content.ServiceConnection
;
import
android.os.IBinder
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
java.util.ArrayList
;
...
...
@@ -148,6 +149,11 @@ import rx.subjects.PublishSubject;
return
Observable
.
concat
(
Observable
.
from
(
getCurrentConnectivityList
()),
connectivitySubject
);
}
@Override
public
int
getConnectivityState
(
@NonNull
String
hostname
)
{
return
serverConnectivityList
.
get
(
hostname
);
}
@DebugLog
private
Single
<
Boolean
>
connectToServerIfNeeded
(
String
hostname
,
boolean
forceConnect
)
{
return
Single
.
defer
(()
->
{
...
...
app/src/main/java/chat/rocket/android/service/RocketChatService.java
View file @
d4f4c5b4
...
...
@@ -105,11 +105,14 @@ public class RocketChatService extends Service implements ConnectivityServiceInt
private
Single
<
RocketChatWebSocketThread
>
getOrCreateWebSocketThread
(
String
hostname
)
{
return
Single
.
defer
(()
->
{
webSocketThreadLock
.
acquire
();
if
(
webSocketThreads
.
containsKey
(
hostname
))
{
int
connectivityState
=
ConnectivityManager
.
getInstance
(
getApplicationContext
()).
getConnectivityState
(
hostname
);
boolean
isConnected
=
connectivityState
==
ServerConnectivity
.
STATE_CONNECTED
;
if
(
webSocketThreads
.
containsKey
(
hostname
)
&&
isConnected
)
{
RocketChatWebSocketThread
thread
=
webSocketThreads
.
get
(
hostname
);
webSocketThreadLock
.
release
();
return
Single
.
just
(
thread
);
}
connectivityManager
.
notifyConnecting
(
hostname
);
return
RocketChatWebSocketThread
.
getStarted
(
getApplicationContext
(),
hostname
)
.
doOnSuccess
(
thread
->
{
webSocketThreads
.
put
(
hostname
,
thread
);
...
...
app/src/main/java/chat/rocket/android/service/RocketChatWebSocketThread.java
View file @
d4f4c5b4
...
...
@@ -211,6 +211,8 @@ public class RocketChatWebSocketThread extends HandlerThread {
if
(
task
.
isFaulted
())
{
Exception
error
=
task
.
getError
();
RCLog
.
e
(
error
);
connectivityManager
.
notifyConnectionLost
(
hostname
,
ConnectivityManagerInternal
.
REASON_NETWORK_ERROR
);
emitter
.
onError
(
error
);
}
else
{
keepAliveTimer
.
update
();
...
...
@@ -345,7 +347,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
}
private
Task
<
Void
>
fetchPublicSettings
()
{
return
new
MethodCallHelper
(
realmHelper
,
ddpClientRef
).
getPublicSettings
(
);
return
new
MethodCallHelper
(
appContext
,
realmHelper
,
ddpClientRef
).
getPublicSettings
(
hostname
);
}
private
Task
<
Void
>
fetchPermissions
()
{
...
...
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