Merge branch 'develop' into feature/dagger

This commit is contained in:
ganfra
2019-06-27 18:56:23 +02:00
120 changed files with 3914 additions and 3977 deletions

View File

@ -9,7 +9,7 @@
android:name="firebase_analytics_collection_deactivated"
android:value="true" />
<service android:name=".push.fcm.VectorFirebaseMessagingService">
<service android:name=".gplay.push.fcm.VectorFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>

View File

@ -0,0 +1,74 @@
/*
* Copyright 2018 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.riotredesign.gplay.features.settings.troubleshoot
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.iid.FirebaseInstanceId
import im.vector.riotredesign.R
import im.vector.riotredesign.core.resources.StringProvider
import im.vector.riotredesign.core.utils.startAddGoogleAccountIntent
import im.vector.riotredesign.features.settings.troubleshoot.NotificationTroubleshootTestManager
import im.vector.riotredesign.features.settings.troubleshoot.TroubleshootTest
import im.vector.riotredesign.push.fcm.FcmHelper
import timber.log.Timber
import javax.inject.Inject
/*
* Test that app can successfully retrieve a token via firebase
*/
class TestFirebaseToken @Inject constructor(private val context: AppCompatActivity,
private val stringProvider: StringProvider) : TroubleshootTest(R.string.settings_troubleshoot_test_fcm_title) {
override fun perform() {
status = TestStatus.RUNNING
try {
FirebaseInstanceId.getInstance().instanceId
.addOnCompleteListener(context) { task ->
if (!task.isSuccessful) {
val errorMsg = if (task.exception == null) "Unknown" else task.exception!!.localizedMessage
//Can't find where this constant is (not documented -or deprecated in docs- and all obfuscated)
if ("SERVICE_NOT_AVAILABLE".equals(errorMsg)) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_service_not_available, errorMsg)
} else if ("TOO_MANY_REGISTRATIONS".equals(errorMsg)) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_too_many_registration, errorMsg)
} else if ("ACCOUNT_MISSING".equals(errorMsg)) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_account_missing, errorMsg)
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_fcm_failed_account_missing_quick_fix) {
override fun doFix() {
startAddGoogleAccountIntent(context, NotificationTroubleshootTestManager.REQ_CODE_FIX)
}
}
} else {
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed, errorMsg)
}
status = TestStatus.FAILED
} else {
task.result?.token?.let {
val tok = it.substring(0, Math.min(8, it.length)) + "********************"
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_success, tok)
Timber.e("Retrieved FCM token success [$it].")
FcmHelper.storeFcmToken(context, tok)
}
status = TestStatus.SUCCESS
}
}
} catch (e: Throwable) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed, e.localizedMessage)
status = TestStatus.FAILED
}
}
}

View File

@ -13,40 +13,41 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.riotredesign.push.fcm.troubleshoot
package im.vector.riotredesign.gplay.features.settings.troubleshoot
import androidx.fragment.app.Fragment
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import im.vector.riotredesign.R
import im.vector.riotredesign.core.resources.StringProvider
import im.vector.riotredesign.features.settings.troubleshoot.TroubleshootTest
import timber.log.Timber
import javax.inject.Inject
/*
* Check that the play services APK is available an up-to-date. If needed provide quick fix to install it.
*/
class TestPlayServices(val fragment: Fragment) : TroubleshootTest(R.string.settings_troubleshoot_test_play_services_title) {
class TestPlayServices @Inject constructor(private val context: AppCompatActivity,
private val stringProvider: StringProvider) : TroubleshootTest(R.string.settings_troubleshoot_test_play_services_title) {
override fun perform() {
val apiAvailability = GoogleApiAvailability.getInstance()
val resultCode = apiAvailability.isGooglePlayServicesAvailable(fragment.context)
val resultCode = apiAvailability.isGooglePlayServicesAvailable(context)
if (resultCode == ConnectionResult.SUCCESS) {
quickFix = null
description = fragment.getString(R.string.settings_troubleshoot_test_play_services_success)
description = stringProvider.getString(R.string.settings_troubleshoot_test_play_services_success)
status = TestStatus.SUCCESS
} else {
if (apiAvailability.isUserResolvableError(resultCode)) {
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_play_services_quickfix) {
override fun doFix() {
fragment.activity?.let {
apiAvailability.getErrorDialog(it, resultCode, 9000 /*hey does the magic number*/).show()
}
apiAvailability.getErrorDialog(context, resultCode, 9000 /*hey does the magic number*/).show()
}
}
Timber.e("Play Services apk error $resultCode -> ${apiAvailability.getErrorString(resultCode)}.")
}
description = fragment.getString(R.string.settings_troubleshoot_test_play_services_failed, apiAvailability.getErrorString(resultCode))
description = stringProvider.getString(R.string.settings_troubleshoot_test_play_services_failed, apiAvailability.getErrorString(resultCode))
status = TestStatus.FAILED
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright 2018 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.riotredesign.gplay.features.settings.troubleshoot
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.work.WorkInfo
import androidx.work.WorkManager
import im.vector.matrix.android.api.session.pushers.PusherState
import im.vector.riotredesign.R
import im.vector.riotredesign.core.di.ActiveSessionHolder
import im.vector.riotredesign.core.pushers.PushersManager
import im.vector.riotredesign.core.resources.StringProvider
import im.vector.riotredesign.features.settings.troubleshoot.TroubleshootTest
import im.vector.riotredesign.push.fcm.FcmHelper
import javax.inject.Inject
/**
* Force registration of the token to HomeServer
*/
class TestTokenRegistration @Inject constructor(private val context: AppCompatActivity,
private val stringProvider: StringProvider,
private val pushersManager: PushersManager,
private val activeSessionHolder: ActiveSessionHolder) : TroubleshootTest(R.string.settings_troubleshoot_test_token_registration_title) {
override fun perform() {
//Check if we have a registered pusher for this token
val fcmToken = FcmHelper.getFcmToken(context) ?: run {
status = TestStatus.FAILED
return
}
val session = activeSessionHolder.getSafeActiveSession() ?: run {
status = TestStatus.FAILED
return
}
val pusher = session.pushers().filter {
it.pushKey == fcmToken && it.state == PusherState.REGISTERED
}
if (pusher.isEmpty()) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_token_registration_failed, null)
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_token_registration_quick_fix) {
override fun doFix() {
val workId = pushersManager.registerPusherWithFcmKey(fcmToken)
WorkManager.getInstance().getWorkInfoByIdLiveData(workId).observe(context, Observer { workInfo ->
if (workInfo != null) {
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
manager?.retry()
} else if (workInfo.state == WorkInfo.State.FAILED) {
manager?.retry()
}
}
})
}
}
status = TestStatus.FAILED
} else {
description = stringProvider.getString(R.string.settings_troubleshoot_test_token_registration_success)
status = TestStatus.SUCCESS
}
}
}

View File

@ -0,0 +1,21 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Code exclusively used by the GPlay build and not referenced on the main source code
*/
package im.vector.riotredesign.gplay

View File

@ -17,7 +17,7 @@
* limitations under the License.
*/
package im.vector.riotredesign.push.fcm
package im.vector.riotredesign.gplay.push.fcm
import android.os.Handler
import android.os.Looper
@ -26,11 +26,12 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ProcessLifecycleOwner
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import im.vector.matrix.android.api.Matrix
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.riotredesign.BuildConfig
import im.vector.riotredesign.R
import im.vector.riotredesign.core.di.ActiveSessionHolder
import im.vector.riotredesign.core.extensions.vectorComponent
import im.vector.riotredesign.core.preference.BingRule
import im.vector.riotredesign.core.pushers.PushersManager
import im.vector.riotredesign.features.badge.BadgeProxy
@ -38,35 +39,31 @@ import im.vector.riotredesign.features.notifications.NotifiableEventResolver
import im.vector.riotredesign.features.notifications.NotifiableMessageEvent
import im.vector.riotredesign.features.notifications.NotificationDrawerManager
import im.vector.riotredesign.features.notifications.SimpleNotifiableEvent
<<<<<<< HEAD
=======
import im.vector.riotredesign.features.settings.PreferencesManager
import org.koin.android.ext.android.inject
>>>>>>> develop
import im.vector.riotredesign.push.fcm.FcmHelper
import timber.log.Timber
import javax.inject.Inject
/**
* Class extending FirebaseMessagingService.
*/
class VectorFirebaseMessagingService : FirebaseMessagingService() {
<<<<<<< HEAD
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
@Inject lateinit var notifiableEventResolver: NotifiableEventResolver
@Inject lateinit var pusherManager: PushersManager
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
private val notifiableEventResolver by lazy {
NotifiableEventResolver(this)
}
=======
private val notificationDrawerManager by inject<NotificationDrawerManager>()
private val pusherManager by inject<PushersManager>()
>>>>>>> develop
private val notifiableEventResolver by inject<NotifiableEventResolver>()
// UI handler
private val mUIHandler by lazy {
Handler(Looper.getMainLooper())
}
override fun onCreate() {
super.onCreate()
vectorComponent().inject(this)
}
/**
* Called when message is received.
*
@ -103,7 +100,6 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
* you retrieve the token.
*/
override fun onNewToken(refreshedToken: String?) {
if (Matrix.getInstance().currentSession == null) return
Timber.i("onNewToken: FCM Token has been updated")
FcmHelper.storeFcmToken(this, refreshedToken)
if (refreshedToken == null) {
@ -149,7 +145,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
val unreadCount = data.get("unread")?.let { Integer.parseInt(it) } ?: 0
BadgeProxy.updateBadgeCount(applicationContext, unreadCount)
val session = safeGetCurrentSession()
val session = activeSessionHolder.getSafeActiveSession()
if (session == null) {
Timber.w("## Can't sync from push, no current session")
@ -167,21 +163,12 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
}
}
fun safeGetCurrentSession(): Session? {
try {
return Matrix.getInstance().currentSession
} catch (e: Throwable) {
Timber.e(e, "## Failed to get current session")
return null
}
}
// check if the event was not yet received
// a previous catchup might have already retrieved the notified event
private fun isEventAlreadyKnown(eventId: String?, roomId: String?): Boolean {
if (null != eventId && null != roomId) {
try {
val session = safeGetCurrentSession() ?: return false
val session = activeSessionHolder.getSafeActiveSession() ?: return false
val room = session.getRoom(roomId) ?: return false
return room.getTimeLineEvent(eventId) != null
} catch (e: Exception) {
@ -241,7 +228,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
if (notifiableEvent is NotifiableMessageEvent) {
if (TextUtils.isEmpty(notifiableEvent.senderName)) {
notifiableEvent.senderName = data["sender_display_name"]
?: data["sender"] ?: ""
?: data["sender"] ?: ""
}
if (TextUtils.isEmpty(notifiableEvent.roomName)) {
notifiableEvent.roomName = findRoomNameBestEffort(data, session) ?: ""
@ -287,11 +274,11 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
try {
return Event(eventId = data["event_id"],
senderId = data["sender"],
roomId = data["room_id"],
type = data.getValue("type"),
senderId = data["sender"],
roomId = data["room_id"],
type = data.getValue("type"),
// TODO content = data.getValue("content"),
originServerTs = System.currentTimeMillis())
originServerTs = System.currentTimeMillis())
} catch (e: Exception) {
Timber.e(e, "buildEvent fails ")
}

View File

@ -25,6 +25,7 @@ import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.firebase.iid.FirebaseInstanceId
import im.vector.riotredesign.R
import im.vector.riotredesign.core.di.ActiveSessionHolder
import im.vector.riotredesign.core.pushers.PushersManager
import timber.log.Timber
@ -99,4 +100,12 @@ object FcmHelper {
val resultCode = apiAvailability.isGooglePlayServicesAvailable(activity)
return resultCode == ConnectionResult.SUCCESS
}
fun onEnterForeground(context: Context) {
// No op
}
fun onEnterBackground(context: Context, activeSessionHolder: ActiveSessionHolder) {
// TODO FCM fallback
}
}

View File

@ -16,30 +16,34 @@
package im.vector.riotredesign.push.fcm
import androidx.fragment.app.Fragment
import im.vector.matrix.android.api.session.Session
import im.vector.riotredesign.features.settings.troubleshoot.*
import im.vector.riotredesign.push.fcm.troubleshoot.TestFirebaseToken
import im.vector.riotredesign.push.fcm.troubleshoot.TestPlayServices
import im.vector.riotredesign.push.fcm.troubleshoot.TestTokenRegistration
import im.vector.riotredesign.features.settings.troubleshoot.NotificationTroubleshootTestManager
import im.vector.riotredesign.features.settings.troubleshoot.TestAccountSettings
import im.vector.riotredesign.features.settings.troubleshoot.TestBingRulesSettings
import im.vector.riotredesign.features.settings.troubleshoot.TestDeviceSettings
import im.vector.riotredesign.features.settings.troubleshoot.TestSystemSettings
import im.vector.riotredesign.gplay.features.settings.troubleshoot.TestFirebaseToken
import im.vector.riotredesign.gplay.features.settings.troubleshoot.TestPlayServices
import im.vector.riotredesign.gplay.features.settings.troubleshoot.TestTokenRegistration
import javax.inject.Inject
class NotificationTroubleshootTestManagerFactory {
class NotificationTroubleshootTestManagerFactory @Inject constructor(private val testSystemSettings: TestSystemSettings,
private val testAccountSettings: TestAccountSettings,
private val testDeviceSettings: TestDeviceSettings,
private val testBingRulesSettings: TestBingRulesSettings,
private val testPlayServices: TestPlayServices,
private val testFirebaseToken: TestFirebaseToken,
private val testTokenRegistration: TestTokenRegistration) {
companion object {
fun createTestManager(fragment: Fragment, session: Session?): NotificationTroubleshootTestManager {
val mgr = NotificationTroubleshootTestManager(fragment)
mgr.addTest(TestSystemSettings(fragment))
if (session != null) {
mgr.addTest(TestAccountSettings(fragment, session))
}
mgr.addTest(TestDeviceSettings(fragment))
if (session != null) {
mgr.addTest(TestBingRulesSettings(fragment, session))
}
mgr.addTest(TestPlayServices(fragment))
mgr.addTest(TestFirebaseToken(fragment))
mgr.addTest(TestTokenRegistration(fragment))
return mgr
}
fun create(fragment: Fragment): NotificationTroubleshootTestManager {
val mgr = NotificationTroubleshootTestManager(fragment)
mgr.addTest(testSystemSettings)
mgr.addTest(testAccountSettings)
mgr.addTest(testDeviceSettings)
mgr.addTest(testBingRulesSettings)
mgr.addTest(testPlayServices)
mgr.addTest(testFirebaseToken)
mgr.addTest(testTokenRegistration)
return mgr
}
}

View File

@ -1,74 +0,0 @@
/*
* Copyright 2018 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.riotredesign.push.fcm.troubleshoot
import androidx.fragment.app.Fragment
import com.google.firebase.iid.FirebaseInstanceId
import im.vector.riotredesign.R
import im.vector.riotredesign.core.utils.startAddGoogleAccountIntent
import im.vector.riotredesign.features.settings.troubleshoot.NotificationTroubleshootTestManager
import im.vector.riotredesign.features.settings.troubleshoot.TroubleshootTest
import timber.log.Timber
/*
* Test that app can successfully retrieve a token via firebase
*/
class TestFirebaseToken(val fragment: Fragment) : TroubleshootTest(R.string.settings_troubleshoot_test_fcm_title) {
override fun perform() {
status = TestStatus.RUNNING
val activity = fragment.activity
if (activity != null) {
try {
FirebaseInstanceId.getInstance().instanceId
.addOnCompleteListener(activity) { task ->
if (!task.isSuccessful) {
val errorMsg = if (task.exception == null) "Unknown" else task.exception!!.localizedMessage
//Can't find where this constant is (not documented -or deprecated in docs- and all obfuscated)
if ("SERVICE_NOT_AVAILABLE".equals(errorMsg)) {
description = fragment.getString(R.string.settings_troubleshoot_test_fcm_failed_service_not_available, errorMsg)
} else if ("TOO_MANY_REGISTRATIONS".equals(errorMsg)) {
description = fragment.getString(R.string.settings_troubleshoot_test_fcm_failed_too_many_registration, errorMsg)
} else if ("ACCOUNT_MISSING".equals(errorMsg)) {
description = fragment.getString(R.string.settings_troubleshoot_test_fcm_failed_account_missing, errorMsg)
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_fcm_failed_account_missing_quick_fix) {
override fun doFix() {
startAddGoogleAccountIntent(fragment, NotificationTroubleshootTestManager.REQ_CODE_FIX)
}
}
} else {
description = fragment.getString(R.string.settings_troubleshoot_test_fcm_failed, errorMsg)
}
status = TestStatus.FAILED
} else {
task.result?.token?.let {
val tok = it.substring(0, Math.min(8, it.length)) + "********************"
description = fragment.getString(R.string.settings_troubleshoot_test_fcm_success, tok)
Timber.e("Retrieved FCM token success [$it].")
}
status = TestStatus.SUCCESS
}
}
} catch (e: Throwable) {
description = fragment.getString(R.string.settings_troubleshoot_test_fcm_failed, e.localizedMessage)
status = TestStatus.FAILED
}
} else {
status = TestStatus.FAILED
}
}
}

View File

@ -1,57 +0,0 @@
/*
* Copyright 2018 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.riotredesign.push.fcm.troubleshoot
import androidx.fragment.app.Fragment
import im.vector.riotredesign.R
import im.vector.riotredesign.features.settings.troubleshoot.TroubleshootTest
/**
* Force registration of the token to HomeServer
*/
class TestTokenRegistration(val fragment: Fragment) : TroubleshootTest(R.string.settings_troubleshoot_test_token_registration_title) {
override fun perform() {
/*
TODO
Matrix.getInstance(VectorApp.getInstance().baseContext).pushManager.forceSessionsRegistration(object : MatrixCallback<Unit> {
override fun onSuccess(info: Void?) {
description = fragment.getString(R.string.settings_troubleshoot_test_token_registration_success)
status = TestStatus.SUCCESS
}
override fun onNetworkError(e: Exception?) {
description = fragment.getString(R.string.settings_troubleshoot_test_token_registration_failed, e?.localizedMessage)
status = TestStatus.FAILED
}
override fun onMatrixError(e: MatrixError?) {
description = fragment.getString(R.string.settings_troubleshoot_test_token_registration_failed, e?.localizedMessage)
status = TestStatus.FAILED
}
override fun onUnexpectedError(e: Exception?) {
description = fragment.getString(R.string.settings_troubleshoot_test_token_registration_failed, e?.localizedMessage)
status = TestStatus.FAILED
}
})
*/
status = TestStatus.FAILED
}
}