-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Android notification plugin (#150)
* Add Android notification plugin * Fix CI issues * Change notification icon on Android * Optimize imports & reformat dart code * Rename notification icon * Allow tracking a payment without destination --------- Co-authored-by: Erdem Yerebasmaz <[email protected]>
- Loading branch information
1 parent
20921ef
commit cc3fefc
Showing
43 changed files
with
924 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
android/app/src/main/kotlin/com/breez/liquid/l_breez/BreezFcmService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package com.breez.liquid.l_breez | ||
|
||
import android.annotation.SuppressLint | ||
import android.app.ActivityManager | ||
import android.app.KeyguardManager | ||
import android.content.Context | ||
import android.content.Intent | ||
import android.os.Process | ||
import android.os.SystemClock | ||
import androidx.core.content.ContextCompat | ||
import breez_sdk_liquid_notification.Constants | ||
import breez_sdk_liquid_notification.Message | ||
import breez_sdk_liquid_notification.MessagingService | ||
import com.breez.liquid.l_breez.BreezLogger.Companion.configureLogger | ||
import com.google.android.gms.common.util.PlatformVersion.isAtLeastLollipop | ||
import com.google.firebase.messaging.FirebaseMessagingService | ||
import com.google.firebase.messaging.RemoteMessage | ||
import org.tinylog.kotlin.Logger | ||
|
||
@SuppressLint("MissingFirebaseInstanceTokenRefresh") | ||
class BreezFcmService : MessagingService, FirebaseMessagingService() { | ||
companion object { | ||
private const val TAG = "BreezFcmService" | ||
} | ||
|
||
override fun onMessageReceived(remoteMessage: RemoteMessage) { | ||
super.onMessageReceived(remoteMessage) | ||
configureLogger(applicationContext) | ||
Logger.tag(TAG).debug { "FCM message received!" } | ||
|
||
if (remoteMessage.priority == RemoteMessage.PRIORITY_HIGH) { | ||
Logger.tag(TAG).debug { "onMessageReceived from: ${remoteMessage.from}" } | ||
Logger.tag(TAG).debug { "onMessageReceived data: ${remoteMessage.data}" } | ||
remoteMessage.asMessage() | ||
?.also { message -> startServiceIfNeeded(applicationContext, message) } | ||
} else { | ||
Logger.tag(TAG).debug { "Ignoring FCM message" } | ||
} | ||
} | ||
|
||
private fun RemoteMessage.asMessage(): Message? { | ||
return data[Constants.MESSAGE_DATA_TYPE]?.let { | ||
Message( | ||
data[Constants.MESSAGE_DATA_TYPE], data[Constants.MESSAGE_DATA_PAYLOAD] | ||
) | ||
} | ||
} | ||
|
||
override fun startForegroundService(message: Message) { | ||
Logger.tag(TAG).debug { "Starting BreezForegroundService w/ message ${message.type}: ${message.payload}" } | ||
val intent = Intent(applicationContext, BreezForegroundService::class.java) | ||
intent.putExtra(Constants.EXTRA_REMOTE_MESSAGE, message) | ||
ContextCompat.startForegroundService(applicationContext, intent) | ||
} | ||
|
||
@SuppressLint("VisibleForTests") | ||
override fun isAppForeground(context: Context): Boolean { | ||
val keyguardManager = getSystemService(KEYGUARD_SERVICE) as KeyguardManager | ||
if (keyguardManager.isKeyguardLocked) { | ||
return false // Screen is off or lock screen is showing | ||
} | ||
// Screen is on and unlocked, now check if the process is in the foreground | ||
if (!isAtLeastLollipop()) { | ||
// Before L the process has IMPORTANCE_FOREGROUND while it executes BroadcastReceivers. | ||
// As soon as the service is started the BroadcastReceiver should stop. | ||
// UNFORTUNATELY the system might not have had the time to downgrade the process | ||
// (this is happening consistently in JellyBean). | ||
// With SystemClock.sleep(10) we tell the system to give a little bit more of CPU | ||
// to the main thread (this code is executing on a secondary thread) allowing the | ||
// BroadcastReceiver to exit the onReceive() method and downgrade the process priority. | ||
SystemClock.sleep(10) | ||
} | ||
val pid = Process.myPid() | ||
val am = getSystemService(ACTIVITY_SERVICE) as ActivityManager | ||
val appProcesses = am.runningAppProcesses | ||
if (appProcesses != null) { | ||
for (process in appProcesses) { | ||
if (process.pid == pid) { | ||
return process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND | ||
} | ||
} | ||
} | ||
return false | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
android/app/src/main/kotlin/com/breez/liquid/l_breez/BreezForegroundService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.breez.liquid.l_breez | ||
|
||
import android.content.SharedPreferences | ||
import breez_sdk_liquid.ConnectRequest | ||
import breez_sdk_liquid.LiquidNetwork | ||
import breez_sdk_liquid.LogEntry | ||
import breez_sdk_liquid.Logger as SdkLogger | ||
import breez_sdk_liquid.defaultConfig | ||
import breez_sdk_liquid.setLogger as setSdkLogger | ||
import breez_sdk_liquid_notification.ForegroundService | ||
import breez_sdk_liquid_notification.NotificationHelper.Companion.registerNotificationChannels | ||
import com.breez.liquid.l_breez.utils.FlutterSecuredStorageHelper.Companion.readSecuredValue | ||
import io.flutter.util.PathUtils | ||
import org.tinylog.kotlin.Logger | ||
|
||
class BreezForegroundService : SdkLogger, ForegroundService() { | ||
companion object { | ||
private const val TAG = "BreezForegroundService" | ||
|
||
private const val SHARED_PREFERENCES_NAME = "FlutterSharedPreferences" | ||
private const val ACCOUNT_MNEMONIC = "account_mnemonic" | ||
private const val DEFAULT_CLICK_ACTION = "FLUTTER_NOTIFICATION_CLICK" | ||
private const val ELEMENT_PREFERENCES_KEY_PREFIX = | ||
"VGhpcyBpcyB0aGUgcHJlZml4IGZvciBhIHNlY3VyZSBzdG9yYWdlCg" | ||
} | ||
|
||
override fun onCreate() { | ||
super.onCreate() | ||
setLogger(this) | ||
setSdkLogger(this) | ||
Logger.tag(TAG).debug { "Creating Breez foreground service..." } | ||
registerNotificationChannels(applicationContext, DEFAULT_CLICK_ACTION) | ||
Logger.tag(TAG).debug { "Breez foreground service created." } | ||
} | ||
|
||
override fun getConnectRequest(): ConnectRequest? { | ||
val config = defaultConfig(LiquidNetwork.MAINNET) | ||
|
||
config.workingDir = PathUtils.getDataDirectory(applicationContext) | ||
|
||
return readSecuredValue( | ||
applicationContext, | ||
"${ELEMENT_PREFERENCES_KEY_PREFIX}_${ACCOUNT_MNEMONIC}" | ||
) | ||
?.let { mnemonic -> | ||
ConnectRequest(config, mnemonic) | ||
} | ||
} | ||
|
||
override fun log(l: LogEntry) { | ||
when (l.level) { | ||
"ERROR" -> Logger.tag(TAG).error { l.line } | ||
"WARN" -> Logger.tag(TAG).warn { l.line } | ||
"INFO" -> Logger.tag(TAG).info { l.line } | ||
"DEBUG" -> Logger.tag(TAG).debug { l.line } | ||
"TRACE" -> Logger.tag(TAG).trace { l.line } | ||
} | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
android/app/src/main/kotlin/com/breez/liquid/l_breez/BreezLogger.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.breez.liquid.l_breez | ||
|
||
import android.content.Context | ||
import io.flutter.util.PathUtils | ||
import org.tinylog.kotlin.Logger | ||
import java.io.File | ||
|
||
class BreezLogger { | ||
companion object { | ||
private const val TAG = "BreezLogger" | ||
|
||
private var isInit: Boolean? = null | ||
|
||
internal fun configureLogger(applicationContext: Context): Boolean? { | ||
synchronized(this) { | ||
/** Get `/logs` folder from Flutter app data directory */ | ||
val loggingDir = | ||
File(PathUtils.getDataDirectory(applicationContext), "/logs").apply { | ||
/** Create a new directory denoted by the pathname and also | ||
* all the non existent parent directories of the pathname */ | ||
mkdirs() | ||
} | ||
|
||
System.setProperty("tinylog.directory", loggingDir.absolutePath) | ||
System.setProperty("tinylog.timestamp", System.currentTimeMillis().toString()) | ||
|
||
if (isInit == false) { | ||
Logger.tag(TAG).debug { "Starting ${BuildConfig.APPLICATION_ID}..." } | ||
Logger.tag(TAG).debug { "Logs directory: '$loggingDir'" } | ||
isInit = true | ||
} | ||
return isInit | ||
} | ||
} | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
android/app/src/main/kotlin/com/breez/liquid/l_breez/utils/FlutterSecuredStorageHelper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.breez.liquid.l_breez.utils | ||
|
||
import android.content.Context | ||
import android.util.Base64 | ||
import java.nio.charset.Charset | ||
|
||
class FlutterSecuredStorageHelper { | ||
companion object { | ||
@Throws(java.lang.Exception::class) | ||
fun readSecuredValue(appContext: Context, key: String): String? { | ||
val preferences = appContext.getSharedPreferences("FlutterSecureStorage", Context.MODE_PRIVATE) | ||
val rawValue = preferences.getString(key, null) | ||
return decodeRawValue(appContext, rawValue) | ||
} | ||
|
||
@Throws(java.lang.Exception::class) | ||
private fun decodeRawValue(appContext: Context, value: String?): String? { | ||
if (value == null) { | ||
return null | ||
} | ||
val charset = Charset.forName("UTF-8") | ||
val data: ByteArray = Base64.decode(value, 0) | ||
val keyCipherAlgo = RSACipher18Implementation(context = appContext) | ||
val storageCipher = StorageCipher18Implementation(appContext, keyCipherAlgo) | ||
val result: ByteArray = storageCipher.decrypt(data) | ||
return String(result, charset) | ||
} | ||
} | ||
} |
Oops, something went wrong.