Push test: better error handling

This commit is contained in:
Benoit Marty 2020-10-02 15:23:42 +02:00 committed by Benoit Marty
parent 7d53dfeca4
commit 02f1dab9b2
11 changed files with 92 additions and 8 deletions

View file

@ -71,12 +71,14 @@ interface PushersService {
* @param url the Sygnal url (full path)
* @param appId the application id
* @param pushkey the FCM token
* @param callback callback to know if Sygnal has accepted the request. In this case, the app should receive a Push with the provided data (TODO)
*
* @param eventId the eventId which will be sent in the Push message. Use a fake eventId.
* @param callback callback to know if Sygnal has accepted the request. In this case, the app should receive a Push with the provided eventId.
* In case of error, PusherRejected failure can happen. In this case it means that the pushkey is not valid.
*/
fun testPush(url: String,
appId: String,
pushkey: String,
eventId: String,
callback: MatrixCallback<Unit>)
/**

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2020 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 org.matrix.android.sdk.api.session.pushers
import org.matrix.android.sdk.api.failure.Failure
sealed class SygnalFailure : Failure.FeatureFailure() {
object PusherRejected : SygnalFailure()
}

View file

@ -50,9 +50,10 @@ internal class DefaultPushersService @Inject constructor(
override fun testPush(url: String,
appId: String,
pushkey: String,
eventId: String,
callback: MatrixCallback<Unit>) {
sygnalNotifyTask
.configureWith(SygnalNotifyTask.Params(url, appId, pushkey)) {
.configureWith(SygnalNotifyTask.Params(url, appId, pushkey, eventId)) {
this.callback = callback
}
.executeBy(taskExecutor)

View file

@ -21,6 +21,9 @@ import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
internal data class SygnalNotification(
@Json(name = "event_id")
val eventId: String,
/**
* Required. This is an array of devices that the notification should be sent to.
*/

View file

@ -16,6 +16,7 @@
package org.matrix.android.sdk.internal.session.pushers.sygnal
import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.session.pushers.SygnalFailure
import org.matrix.android.sdk.internal.di.Unauthenticated
import org.matrix.android.sdk.internal.network.NetworkConstants
import org.matrix.android.sdk.internal.network.RetrofitFactory
@ -27,7 +28,8 @@ internal interface SygnalNotifyTask : Task<SygnalNotifyTask.Params, Unit> {
data class Params(
val url: String,
val appId: String,
val pushKey: String
val pushKey: String,
val eventId: String
)
}
@ -47,6 +49,7 @@ internal class DefaultSygnalNotifyTask @Inject constructor(
apiCall = sygnalApi.notify(
SygnalNotifyBody(
SygnalNotification(
eventId = params.eventId,
devices = listOf(
SygnalDevice(
params.appId,
@ -59,7 +62,7 @@ internal class DefaultSygnalNotifyTask @Inject constructor(
}
if (response.rejectedPushKey.contains(params.pushKey)) {
throw IllegalStateException("Failure")
throw SygnalFailure.PusherRejected
}
}
}

View file

@ -17,11 +17,13 @@ package im.vector.app.gplay.features.settings.troubleshoot
import androidx.appcompat.app.AppCompatActivity
import im.vector.app.R
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.pushers.PushersManager
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.settings.troubleshoot.TroubleshootTest
import im.vector.app.push.fcm.FcmHelper
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.pushers.SygnalFailure
import javax.inject.Inject
/**
@ -29,6 +31,7 @@ import javax.inject.Inject
*/
class TestPushFromSygnal @Inject constructor(private val context: AppCompatActivity,
private val stringProvider: StringProvider,
private val errorFormatter: ErrorFormatter,
private val pushersManager: PushersManager)
: TroubleshootTest(R.string.settings_troubleshoot_test_push_loop_title) {
@ -39,7 +42,11 @@ class TestPushFromSygnal @Inject constructor(private val context: AppCompatActiv
}
pushersManager.testPush(fcmToken, object : MatrixCallback<Unit> {
override fun onFailure(failure: Throwable) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_failed)
description = if (failure is SygnalFailure.PusherRejected) {
stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_failed)
} else {
errorFormatter.toHumanReadable(failure)
}
status = TestStatus.FAILED
}

View file

@ -75,6 +75,13 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
* @param message the message
*/
override fun onMessageReceived(message: RemoteMessage) {
// Diagnostic Push
if (message.data["event_id"] == PushersManager.TEST_EVENT_ID) {
// Display the notification right now
notificationDrawerManager.displayDiagnosticNotification()
return
}
if (!vectorPreferences.areNotificationEnabledForDevice()) {
Timber.i("Notification are disabled for this device")
return

View file

@ -41,6 +41,7 @@ class PushersManager @Inject constructor(
stringProvider.getString(R.string.pusher_http_url),
stringProvider.getString(R.string.pusher_app_id),
pushKey,
TEST_EVENT_ID,
callback
)
}
@ -66,4 +67,8 @@ class PushersManager @Inject constructor(
val currentSession = activeSessionHolder.getSafeActiveSession() ?: return
currentSession.removeHttpPusher(pushKey, stringProvider.getString(R.string.pusher_app_id), callback)
}
companion object {
const val TEST_EVENT_ID = "\$THIS_IS_A_FAKE_EVENT_ID"
}
}

View file

@ -590,6 +590,10 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
}
}
fun displayDiagnosticNotification() {
notificationUtils.displayDiagnosticNotification()
}
companion object {
private const val SUMMARY_NOTIFICATION_ID = 0
private const val ROOM_MESSAGES_NOTIFICATION_ID = 1

View file

@ -27,8 +27,10 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.net.Uri
import android.os.Build
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
@ -36,6 +38,7 @@ import androidx.core.app.RemoteInput
import androidx.core.app.TaskStackBuilder
import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.fragment.app.Fragment
import im.vector.app.BuildConfig
@ -47,7 +50,6 @@ import im.vector.app.features.call.service.CallHeadsUpActionReceiver
import im.vector.app.features.home.HomeActivity
import im.vector.app.features.home.room.detail.RoomDetailActivity
import im.vector.app.features.home.room.detail.RoomDetailArgs
import im.vector.app.features.pin.PinLocker
import im.vector.app.features.settings.VectorPreferences
import timber.log.Timber
import javax.inject.Inject
@ -61,7 +63,6 @@ import kotlin.random.Random
@Singleton
class NotificationUtils @Inject constructor(private val context: Context,
private val stringProvider: StringProvider,
private val pinLocker: PinLocker,
private val vectorPreferences: VectorPreferences) {
companion object {
@ -845,6 +846,33 @@ class NotificationUtils @Inject constructor(private val context: Context,
}
}
fun displayDiagnosticNotification() {
notificationManager.notify(
"DIAGNOSTIC",
888,
NotificationCompat.Builder(context, NOISY_NOTIFICATION_CHANNEL_ID)
.setContentTitle(stringProvider.getString(R.string.app_name))
.setContentText(stringProvider.getString(R.string.settings_troubleshoot_test_push_notification_content))
.setSmallIcon(R.drawable.ic_status_bar)
.setLargeIcon(getBitmap(context, R.drawable.element_logo_green))
.setColor(ContextCompat.getColor(context, R.color.notification_accent_color))
.setPriority(NotificationCompat.PRIORITY_MAX)
.setCategory(NotificationCompat.CATEGORY_STATUS)
.setAutoCancel(true)
.build()
)
}
private fun getBitmap(context: Context, @DrawableRes drawableRes: Int): Bitmap? {
val drawable = ResourcesCompat.getDrawable(context.resources, drawableRes, null) ?: return null
val canvas = Canvas()
val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
canvas.setBitmap(bitmap)
drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
drawable.draw(canvas)
return bitmap
}
/**
* Return true it the user has enabled the do not disturb mode
*/

View file

@ -752,6 +752,7 @@
<string name="settings_troubleshoot_test_push_loop_title">Test Push</string>
<string name="settings_troubleshoot_test_push_loop_success">The application is receiving PUSH, you should see a notification.</string>
<string name="settings_troubleshoot_test_push_loop_failed">Failed to receive push. Solution could be to reinstall the application.</string>
<string name="settings_troubleshoot_test_push_notification_content">You are receiving PUSH!</string>
<string name="settings_troubleshoot_test_foreground_service_started_title">Notifications Service</string>
<string name="settings_troubleshoot_test_foreground_service_startedt_success">Notifications Service is running.</string>