diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/distributor/Distributor.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/distributor/Distributor.kt index 5353467..d60495d 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/distributor/Distributor.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/distributor/Distributor.kt @@ -29,7 +29,6 @@ object Distributor { broadcastIntent.`package` = application broadcastIntent.action = ACTION_MESSAGE broadcastIntent.putExtra(EXTRA_TOKEN, connectorToken) - broadcastIntent.putExtra(EXTRA_MESSAGE, String(message)) broadcastIntent.putExtra(EXTRA_BYTES_MESSAGE, message) context.sendBroadcast(broadcastIntent) Log.d(TAG, "Message forwarded") @@ -53,7 +52,7 @@ object Distributor { context: Context, application: String, connectorToken: String, - message: String = "" + reason: FailedReason ) { application.ifBlank { return @@ -62,7 +61,7 @@ object Distributor { broadcastIntent.`package` = application broadcastIntent.action = ACTION_REGISTRATION_FAILED broadcastIntent.putExtra(EXTRA_TOKEN, connectorToken) - broadcastIntent.putExtra(EXTRA_MESSAGE, message) + broadcastIntent.putExtra(EXTRA_FAILED_REASON, reason.name) context.sendBroadcast(broadcastIntent) } @@ -115,12 +114,17 @@ object Distributor { Api(context).apiDeleteDevice(block) } - fun createApp(context: Context, appName: String, connectorToken: String, block: () -> Unit) { + /** + * Create an application on the server, runs [block] when it's done. + * + * [block]'s parameter is `true` if we have successfully created the registration. + */ + fun createApp(context: Context, appName: String, connectorToken: String, block: (Boolean) -> Unit) { Api(context).apiCreateApp(appName) { nextpushToken -> nextpushToken?.let { getDb(context).registerApp(appName, connectorToken, it) - } - block() + block(true) + } ?: block(false) } } diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/distributor/FailedReason.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/distributor/FailedReason.kt new file mode 100644 index 0000000..aff5c38 --- /dev/null +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/distributor/FailedReason.kt @@ -0,0 +1,23 @@ +package org.unifiedpush.distributor.nextpush.distributor + +/** + * A registration request may fail for different reasons. + */ +enum class FailedReason { +/** + * This is a generic error type, you can try to register again directly. + */ + INTERNAL_ERROR, +/** + * The registration failed because of missing network connection, try again when network is back. + */ + NETWORK, +/** + * The distributor requires a user action to work. For instance, the distributor may be log out of the push server and requires the user to log in. The user must interact with the distributor or sending a new registration will fail again. + */ + ACTION_REQUIRED, +/* + * The distributor requires a VAPID key and the app didn't provide one during registration. + VAPID_REQUIRED, + */ +} diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/distributor/UnifiedPushConstants.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/distributor/UnifiedPushConstants.kt index 4dfe2fa..e2f6a39 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/distributor/UnifiedPushConstants.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/distributor/UnifiedPushConstants.kt @@ -17,5 +17,5 @@ const val EXTRA_APPLICATION = "application" const val EXTRA_PI = "pi" const val EXTRA_TOKEN = "token" const val EXTRA_ENDPOINT = "endpoint" -const val EXTRA_MESSAGE = "message" +const val EXTRA_FAILED_REASON = "reason" const val EXTRA_BYTES_MESSAGE = "bytesMessage" diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt index 18d12fe..86b20f3 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt @@ -132,54 +132,102 @@ class RegisterBroadcastReceiver : BroadcastReceiver() { private fun onRegister(context: Context, connectorToken: String, application: String) { if (!AppCompanion.createQueue.containsTokenElseAdd(connectorToken)) { when (checkToken(context, connectorToken, application)) { - ConnectorTokenValidity.TOKEN_REGISTERED_OK -> { - sendEndpoint(context, connectorToken) - AppCompanion.createQueue.removeToken(connectorToken) - } - ConnectorTokenValidity.TOKEN_NOK -> { - sendRegistrationFailed( - context, - application, - connectorToken - ) - AppCompanion.createQueue.removeToken(connectorToken) - } - ConnectorTokenValidity.TOKEN_NEW -> { - val appName = context.getApplicationName(application) ?: application - if (!isConnected(context)) { - sendRegistrationFailed( - context, - application, - connectorToken, - message = "NextPush is not connected" - ) - Toast.makeText( - context, - "Cannot register $appName, NextPush is not connected.", - Toast.LENGTH_SHORT - ).show() - return - } - createApp( - context, - application, - connectorToken - ) { - sendEndpoint(context, connectorToken) - AppCompanion.createQueue.removeToken(connectorToken) - Toast.makeText( - context, - "$appName registered.", - Toast.LENGTH_SHORT - ).show() - } - } + ConnectorTokenValidity.TOKEN_REGISTERED_OK -> onRegisterKnownToken(context, connectorToken) + ConnectorTokenValidity.TOKEN_NOK -> onRegisterNokToken(context, connectorToken, application) + ConnectorTokenValidity.TOKEN_NEW ->onRegisterNewToken(context, connectorToken, application) } + AppCompanion.createQueue.removeToken(connectorToken) } else { Log.d(TAG, "Already registering this token") } } + /** + * The token is known, send the endpoint. + */ + private fun onRegisterKnownToken(context: Context, connectorToken: String) { + sendEndpoint(context, connectorToken) + } + + /** + * The token exists but don't match the application, we send a registration fail with INTERNAL_ERROR + * so the application can start again with a new token. + */ + private fun onRegisterNokToken(context: Context, connectorToken: String, application: String) { + sendRegistrationFailed( + context, + application, + connectorToken, + FailedReason.INTERNAL_ERROR + ) + } + + /** + * Registering a new token. + * + * If we are not connected to Nextcloud, we send registration failed with [FailedReason.ACTION_REQUIRED] + */ + private fun onRegisterNewToken(context: Context, connectorToken: String, application: String) { + val appName = context.getApplicationName(application) ?: application + when { + !isConnected(context) -> registrationFailedWithToast( + context, + connectorToken, + application, + FailedReason.ACTION_REQUIRED + ) + + !AppCompanion.hasInternet.get() -> registrationFailedWithToast( + context, + connectorToken, + application, + FailedReason.NETWORK + ) + + else -> createApp( + context, + application, + connectorToken + ) { success -> + when (success) { + true -> { + sendEndpoint(context, connectorToken) + Toast.makeText(context, "$appName registered.", Toast.LENGTH_SHORT) + .show() + } + + false -> registrationFailedWithToast( + context, + connectorToken, + application, + FailedReason.INTERNAL_ERROR + ) + } + } + } + } + + /** Send registration failed and toast */ + private fun registrationFailedWithToast(context: Context, connectorToken: String, application: String, failedReason: FailedReason) { + val appName = context.getApplicationName(application) ?: application + sendRegistrationFailed( + context, + application, + connectorToken, + failedReason + ) + val text = when (failedReason) { + FailedReason.NETWORK -> "Cannot register $appName, no internet." + FailedReason.ACTION_REQUIRED -> "Cannot register $appName, logged out." + FailedReason.INTERNAL_ERROR -> "Cannot register $appName, internal error." + } + Toast.makeText( + context, + text, + Toast.LENGTH_SHORT + ).show() + } + /** * Unregister the application from the server and remove from the local db */