adds log update function and log list
- log updates in background automatically from server data - log list in main screen of app is updated showing the title of each notification
This commit is contained in:
@ -2,7 +2,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.maenle.bump"
|
package="com.maenle.bump"
|
||||||
android:versionName="initial">
|
android:versionName="0.1_alpha">
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.camera.any" />
|
<uses-feature android:name="android.hardware.camera.any" />
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
@ -23,13 +23,13 @@
|
|||||||
android:exported="false">
|
android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
|
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
|
||||||
|
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||||
android:resource="@drawable/ic_stat_name"/>
|
android:resource="@drawable/ic_stat_name"/>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.firebase.messaging.default_notification_color"
|
android:name="com.google.firebase.messaging.default_notification_color"
|
||||||
android:resource="@color/black"/> <!-- [END fcm_default_icon] -->
|
android:resource="@color/black"/> <!-- [END fcm_default_icon] -->
|
||||||
@ -50,6 +50,10 @@
|
|||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name=".ui.MainActivity" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package com.maenle.bump
|
|||||||
|
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.maenle.bump.util.sendNotification
|
import com.maenle.bump.util.sendNotification
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService
|
import com.google.firebase.messaging.FirebaseMessagingService
|
||||||
@ -16,27 +17,32 @@ class MyFirebaseMessagingService : FirebaseMessagingService() {
|
|||||||
*
|
*
|
||||||
* @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
|
* @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
|
||||||
*/
|
*/
|
||||||
// [START receive_message]
|
|
||||||
override fun onMessageReceived(remoteMessage: RemoteMessage) {
|
override fun onMessageReceived(remoteMessage: RemoteMessage) {
|
||||||
// Not getting messages here? See why this may be: https://goo.gl/39bRNJ
|
// Not getting messages here? See why this may be: https://goo.gl/39bRNJ
|
||||||
// Log.d(TAG, "From: ${remoteMessage.from}")
|
// Log.d(TAG, "From: ${remoteMessage.from}")
|
||||||
|
|
||||||
// TODO Step 3.5 check messages for data
|
|
||||||
// Check if message contains a data payload.
|
// Check if message contains a data payload.
|
||||||
|
var body: String? = null;
|
||||||
|
var header: String? = null;
|
||||||
remoteMessage.data.let {
|
remoteMessage.data.let {
|
||||||
// Log.d(TAG, "Message data payload: " + remoteMessage.data)
|
val bump = BumpProcessor.getInstance(applicationContext)
|
||||||
|
Log.d(TAG, "Message data payload: " + remoteMessage.data)
|
||||||
|
val a = remoteMessage.data.keys
|
||||||
|
val value = remoteMessage.data["data"]
|
||||||
|
value?.let {
|
||||||
|
body = bump.decryptMessage(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Step 3.6 check messages for notification and call sendNotification
|
|
||||||
// Check if message contains a notification payload.
|
|
||||||
remoteMessage.notification?.let {
|
remoteMessage.notification?.let {
|
||||||
// Log.d(TAG, "Message Notification Body: ${it.body}")
|
header = it.body
|
||||||
sendNotification(it.body!!)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// [END receive_message]
|
|
||||||
|
|
||||||
//TODO Step 3.2 log registration token
|
sendNotification(header, body)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// log registration token
|
||||||
// [START on_new_token]
|
// [START on_new_token]
|
||||||
/**
|
/**
|
||||||
* Called if InstanceID token is updated. This may occur if the security of
|
* Called if InstanceID token is updated. This may occur if the security of
|
||||||
@ -63,14 +69,11 @@ class MyFirebaseMessagingService : FirebaseMessagingService() {
|
|||||||
bump.setFirebaseToken(baseContext)
|
bump.setFirebaseToken(baseContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private fun sendNotification(messageHeader: String?, messageBody: String?) {
|
||||||
* Create and show a simple notification containing the received FCM message.
|
|
||||||
*
|
|
||||||
* @param messageBody FCM message body received.
|
|
||||||
*/
|
|
||||||
private fun sendNotification(messageBody: String) {
|
|
||||||
val notificationManager = ContextCompat.getSystemService(applicationContext, NotificationManager::class.java) as NotificationManager
|
val notificationManager = ContextCompat.getSystemService(applicationContext, NotificationManager::class.java) as NotificationManager
|
||||||
notificationManager.sendNotification(messageBody, applicationContext)
|
notificationManager.sendNotification(messageHeader, messageBody, applicationContext)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -16,15 +16,14 @@ import com.google.zxing.WriterException
|
|||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.*
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
import androidmads.library.qrgenearator.QRGContents
|
import androidmads.library.qrgenearator.QRGContents
|
||||||
import androidmads.library.qrgenearator.QRGEncoder
|
import androidmads.library.qrgenearator.QRGEncoder
|
||||||
|
|
||||||
import com.maenle.bump.util.Display
|
import com.maenle.bump.util.Display
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple [Fragment] subclass as the default destination in the navigation.
|
|
||||||
*/
|
|
||||||
class FirstFragment : Fragment() {
|
class FirstFragment : Fragment() {
|
||||||
|
|
||||||
private var _binding: FragmentFirstBinding? = null
|
private var _binding: FragmentFirstBinding? = null
|
||||||
@ -53,16 +52,9 @@ class FirstFragment : Fragment() {
|
|||||||
getString(R.string.bump_notification_channel_name)
|
getString(R.string.bump_notification_channel_name)
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
|
||||||
val notificationManager = ContextCompat.getSystemService(
|
|
||||||
requireContext(),
|
|
||||||
NotificationManager::class.java
|
|
||||||
) as NotificationManager
|
|
||||||
notificationManager.sendNotification(getString(R.string.notification), requireContext())
|
|
||||||
*/
|
|
||||||
|
|
||||||
subscribeTopic()
|
subscribeTopic()
|
||||||
|
|
||||||
|
bump.callback = { log -> updateLogCallback(log) }
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,8 +144,23 @@ class FirstFragment : Fragment() {
|
|||||||
return newBitmap
|
return newBitmap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateLogCallback(log: JSONArray) {
|
||||||
|
val messages: MutableList<MessageItem> = mutableListOf()
|
||||||
|
val texts: MutableList<String> = mutableListOf()
|
||||||
|
binding.nrMessages.text = log.length().toString()
|
||||||
|
for(l in 0 until log.length()) {
|
||||||
|
val m = log[l] as JSONObject
|
||||||
|
messages.add(MessageItem(m.get("title") as String,
|
||||||
|
m.get("data") as String))
|
||||||
|
texts.add(m.get("title") as String)
|
||||||
|
}
|
||||||
|
val adapter = ArrayAdapter(requireContext(),
|
||||||
|
R.layout.support_simple_spinner_dropdown_item,
|
||||||
|
texts)
|
||||||
|
binding.notificationList.adapter = adapter
|
||||||
|
}
|
||||||
|
|
||||||
private fun subscribeTopic() {
|
private fun subscribeTopic() {
|
||||||
// [START subscribe_topic]
|
|
||||||
FirebaseMessaging.getInstance().subscribeToTopic(TOPIC)
|
FirebaseMessaging.getInstance().subscribeToTopic(TOPIC)
|
||||||
.addOnCompleteListener { task ->
|
.addOnCompleteListener { task ->
|
||||||
var curmessage = getString(R.string.message_subscribed)
|
var curmessage = getString(R.string.message_subscribed)
|
||||||
@ -176,4 +183,6 @@ class FirstFragment : Fragment() {
|
|||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MessageItem(var header: String, var body: String) {}
|
@ -1,6 +1,7 @@
|
|||||||
package com.maenle.bump.ui
|
package com.maenle.bump.ui
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
@ -29,6 +30,11 @@ class MainActivity : AppCompatActivity() {
|
|||||||
appBarConfiguration = AppBarConfiguration(navController.graph)
|
appBarConfiguration = AppBarConfiguration(navController.graph)
|
||||||
setupActionBarWithNavController(navController, appBarConfiguration)
|
setupActionBarWithNavController(navController, appBarConfiguration)
|
||||||
|
|
||||||
|
val bundle = intent.extras
|
||||||
|
if (bundle != null) {
|
||||||
|
Log.d("MainActivity", bundle.toString())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
@ -4,7 +4,6 @@ import android.content.Context
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.google.firebase.ktx.Firebase
|
|
||||||
import com.google.firebase.messaging.FirebaseMessaging
|
import com.google.firebase.messaging.FirebaseMessaging
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
@ -12,12 +11,16 @@ import java.io.File
|
|||||||
|
|
||||||
class BumpProcessor constructor(context: Context) {
|
class BumpProcessor constructor(context: Context) {
|
||||||
|
|
||||||
private var rest: RestSingleton = RestSingleton.getInstance(context)
|
private val rest: RestSingleton = RestSingleton.getInstance(context)
|
||||||
private lateinit var log: JSONArray
|
private val local = LocalData(context)
|
||||||
|
private var log: JSONArray
|
||||||
|
private val messenger = local.code?.let { MessageProcessor(it) }
|
||||||
|
|
||||||
|
var callback: ((JSONArray)->Unit)? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
log = getLog(context)
|
log = getLog(context)
|
||||||
|
startUpdateHandler(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -31,20 +34,26 @@ class BumpProcessor constructor(context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun decryptMessage(message: String): String {
|
||||||
|
return messenger!!.decrypt(message)
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateLog(context: Context, list: JSONArray) {
|
private fun updateLog(context: Context, list: JSONArray) {
|
||||||
for(i in 0 until list.length()) {
|
for(i in 0 until list.length()) {
|
||||||
var exists = false
|
var exists = false
|
||||||
for(j in 0 until log.length()) {
|
for(j in 0 until log.length()) {
|
||||||
if (list[i] == log[j]) {
|
if (list[i].toString() == log[j].toString()) {
|
||||||
exists = true
|
exists = true
|
||||||
continue
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exists.let {
|
if(!exists) {
|
||||||
log.put(list[i])
|
log.put(list[i])
|
||||||
addToLog(context, list[i] as JSONObject)
|
addToLog(context, list[i] as JSONObject)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callback?.invoke(log)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSecret(context: Context):String? {
|
private fun getSecret(context: Context):String? {
|
||||||
@ -52,11 +61,11 @@ class BumpProcessor constructor(context: Context) {
|
|||||||
return local.code
|
return local.code
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startUpdateHandler(context: Context) {
|
private fun startUpdateHandler(context: Context) {
|
||||||
|
val delay: Long = 10_000 //milliseconds
|
||||||
val delay: Long = 30_000 //milliseconds
|
|
||||||
val handler = Handler(Looper.getMainLooper())
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
updateFromServer(context)
|
||||||
handler.postDelayed(object : Runnable {
|
handler.postDelayed(object : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
updateFromServer(context)
|
updateFromServer(context)
|
||||||
@ -65,7 +74,7 @@ class BumpProcessor constructor(context: Context) {
|
|||||||
}, delay)
|
}, delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateFromServer(context: Context) {
|
fun updateFromServer(context: Context) {
|
||||||
LocalData(context).code?.let {
|
LocalData(context).code?.let {
|
||||||
val messenger = MessageProcessor(it)
|
val messenger = MessageProcessor(it)
|
||||||
rest.list(messenger.sender) { list -> updateLog(context, list) }
|
rest.list(messenger.sender) { list -> updateLog(context, list) }
|
||||||
@ -74,7 +83,13 @@ class BumpProcessor constructor(context: Context) {
|
|||||||
|
|
||||||
private fun addToLog(context: Context, line: JSONObject) {
|
private fun addToLog(context: Context, line: JSONObject) {
|
||||||
val logFile = File(context.filesDir, ".bump_log")
|
val logFile = File(context.filesDir, ".bump_log")
|
||||||
logFile.appendText(line.toString())
|
logFile.appendText(line.toString() + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clearLog(context: Context) {
|
||||||
|
val logFile = File(context.filesDir, ".bump_log")
|
||||||
|
logFile.writeText("")
|
||||||
|
log = JSONArray("[]")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addSecret(context: Context, newCode: String): Boolean {
|
fun addSecret(context: Context, newCode: String): Boolean {
|
||||||
@ -94,7 +109,7 @@ class BumpProcessor constructor(context: Context) {
|
|||||||
return newCode.length == validChars && newCode.length >= 32
|
return newCode.length == validChars && newCode.length >= 32
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLog(context: Context): JSONArray {
|
fun getLog(context: Context): JSONArray {
|
||||||
val logFile = File(context.filesDir, ".bump_log")
|
val logFile = File(context.filesDir, ".bump_log")
|
||||||
val log = JSONArray()
|
val log = JSONArray()
|
||||||
!logFile.exists().let {
|
!logFile.exists().let {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.maenle.bump.util
|
package com.maenle.bump.util
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import java.util.Base64
|
import java.util.Base64
|
||||||
import javax.crypto.spec.PBEKeySpec
|
import javax.crypto.spec.PBEKeySpec
|
||||||
import javax.crypto.SecretKeyFactory
|
import javax.crypto.SecretKeyFactory
|
||||||
@ -77,13 +78,19 @@ class MessageProcessor(code: String, private val salt: ByteArray? = null) {
|
|||||||
super.splitMessage(messageRaw)
|
super.splitMessage(messageRaw)
|
||||||
}
|
}
|
||||||
fun validateAndDecryptWith(password: String, timeToLive: Long = TIME_TO_LIVE): String {
|
fun validateAndDecryptWith(password: String, timeToLive: Long = TIME_TO_LIVE): String {
|
||||||
val fernetKey = deriveMessageKeyFromPassword(password)
|
try {
|
||||||
val validator: Validator<String> = object : StringValidator {
|
val fernetKey = deriveMessageKeyFromPassword(password)
|
||||||
override fun getTimeToLive(): TemporalAmount {
|
val validator: Validator<String> = object : StringValidator {
|
||||||
return Duration.ofHours(timeToLive)
|
override fun getTimeToLive(): TemporalAmount {
|
||||||
|
return Duration.ofHours(timeToLive)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return token.validateAndDecrypt(fernetKey, validator)
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
e.message?.let { Log.d(TAG, it) }
|
||||||
}
|
}
|
||||||
return token.validateAndDecrypt(fernetKey, validator)
|
return ""
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.maenle.bump.util
|
package com.maenle.bump.util
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@ -10,16 +9,32 @@ import androidx.core.app.NotificationCompat
|
|||||||
import com.maenle.bump.ui.MainActivity
|
import com.maenle.bump.ui.MainActivity
|
||||||
import com.maenle.bump.R
|
import com.maenle.bump.R
|
||||||
|
|
||||||
// Notification ID.
|
|
||||||
private val NOTIFICATION_ID = 0
|
|
||||||
|
|
||||||
@SuppressLint("WrongConstant")
|
|
||||||
fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
|
|
||||||
|
// Notification ID.
|
||||||
|
private const val NOTIFICATION_ID = 0
|
||||||
|
|
||||||
|
fun NotificationManager.sendNotification(messageHeader: String?, messageBody: String?, applicationContext: Context) {
|
||||||
|
var title = applicationContext.getString(R.string.notification_title)
|
||||||
|
var body = ""
|
||||||
|
|
||||||
|
if(messageBody != null) {
|
||||||
|
if(messageHeader != null) {
|
||||||
|
title = messageHeader
|
||||||
|
}
|
||||||
|
body = messageBody
|
||||||
|
} else if(messageHeader != null) {
|
||||||
|
body = messageHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
sendParsedNotification(title, body, applicationContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun NotificationManager.sendParsedNotification(messageHeader: String, messageBody: String, applicationContext: Context) {
|
||||||
// Create the content intent for the notification, which launches
|
// Create the content intent for the notification, which launches
|
||||||
// this activity
|
// this activity
|
||||||
// TODO: Step 1.11 create intent
|
|
||||||
val contentIntent = Intent(applicationContext, MainActivity::class.java)
|
val contentIntent = Intent(applicationContext, MainActivity::class.java)
|
||||||
// TODO: Step 1.12 create PendingIntent
|
|
||||||
val contentPendingIntent = PendingIntent.getActivity(
|
val contentPendingIntent = PendingIntent.getActivity(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
NOTIFICATION_ID,
|
NOTIFICATION_ID,
|
||||||
@ -27,43 +42,39 @@ fun NotificationManager.sendNotification(messageBody: String, applicationContext
|
|||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Step 2.0 add style
|
|
||||||
val eggImage = BitmapFactory.decodeResource(
|
val eggImage = BitmapFactory.decodeResource(
|
||||||
applicationContext.resources,
|
applicationContext.resources,
|
||||||
R.drawable.ic_stat_name
|
R.drawable.ic_stat_name
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Step 1.2 get an instance of NotificationCompat.Builder
|
val intent = Intent(applicationContext, this.javaClass)
|
||||||
|
val action =
|
||||||
|
PendingIntent.getBroadcast(applicationContext, 0, intent, 0)
|
||||||
// Build the notification
|
// Build the notification
|
||||||
val builder = NotificationCompat.Builder(
|
val builder = NotificationCompat.Builder(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
applicationContext.getString(R.string.bump_notification_channel_id)
|
applicationContext.getString(R.string.bump_notification_channel_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Step 1.3 set title, text and icon to builder
|
|
||||||
.setSmallIcon(R.drawable.ic_stat_name)
|
.setSmallIcon(R.drawable.ic_stat_name)
|
||||||
.setContentTitle(applicationContext
|
.setContentTitle(messageHeader)
|
||||||
.getString(R.string.notification_title))
|
|
||||||
.setContentText(messageBody)
|
.setContentText(messageBody)
|
||||||
|
|
||||||
// TODO: Step 1.13 set content intent
|
// set content intent
|
||||||
.setContentIntent(contentPendingIntent)
|
.setContentIntent(contentPendingIntent)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
|
|
||||||
// TODO: Step 2.1 add style to builder
|
// add style to builder
|
||||||
.setLargeIcon(eggImage)
|
.setLargeIcon(eggImage)
|
||||||
|
|
||||||
// TODO: Step 2.5 set priority
|
// set priority
|
||||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||||
// TODO: Step 1.4 call notify
|
.addAction(0, "Action", action)
|
||||||
|
|
||||||
|
// notify
|
||||||
notify(NOTIFICATION_ID, builder.build())
|
notify(NOTIFICATION_ID, builder.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Step 1.14 Cancel all notifications
|
|
||||||
/**
|
|
||||||
* Cancels all notifications.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
fun NotificationManager.cancelNotifications() {
|
fun NotificationManager.cancelNotifications() {
|
||||||
cancelAll()
|
cancelAll()
|
||||||
}
|
}
|
@ -33,7 +33,7 @@ class RestSingleton constructor(context: Context){
|
|||||||
val url = URL + "list/"
|
val url = URL + "list/"
|
||||||
val data = JSONObject()
|
val data = JSONObject()
|
||||||
data.put("sender", sender)
|
data.put("sender", sender)
|
||||||
data.put("minutes", (60*24*365*100).toString())
|
data.put("minutes", (60*24*2).toString())
|
||||||
val jsonRequest = JsonObjectRequest(Request.Method.POST, url,
|
val jsonRequest = JsonObjectRequest(Request.Method.POST, url,
|
||||||
data,
|
data,
|
||||||
{ response ->
|
{ response ->
|
||||||
@ -100,7 +100,6 @@ class RestSingleton constructor(context: Context){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private val requestQueue: RequestQueue by lazy {
|
private val requestQueue: RequestQueue by lazy {
|
||||||
// applicationContext is key, it keeps you from leaking the
|
// applicationContext is key, it keeps you from leaking the
|
||||||
// Activity or BroadcastReceiver if someone passes one in.
|
// Activity or BroadcastReceiver if someone passes one in.
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"/>
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/buttons"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
@ -68,4 +69,35 @@
|
|||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:text="@string/view_sender" />
|
android:text="@string/view_sender" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/header"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/buttons"
|
||||||
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/nr_messages"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/default_nr_messages"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:textSize="20sp"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/message_header"
|
||||||
|
android:textSize="20sp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/notification_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_margin="20sp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/header">
|
||||||
|
</ListView>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
10
app/src/main/res/layout/notification_item.xml
Normal file
10
app/src/main/res/layout/notification_item.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="10dp" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -13,6 +13,8 @@
|
|||||||
<string name="scan_sender">Scan</string>
|
<string name="scan_sender">Scan</string>
|
||||||
<string name="camera_fragment_label">Scan Sender QR</string>
|
<string name="camera_fragment_label">Scan Sender QR</string>
|
||||||
<string name="preference_file_key">code_file_key</string>
|
<string name="preference_file_key">code_file_key</string>
|
||||||
|
<string name="message_header">messages received:</string>
|
||||||
|
<string name="default_nr_messages">0</string>
|
||||||
<string name="code_key">code_key</string>
|
<string name="code_key">code_key</string>
|
||||||
<string name="notification_title">Bump</string>
|
<string name="notification_title">Bump</string>
|
||||||
<string name="bump_notification_channel_id">bump_id</string>
|
<string name="bump_notification_channel_id">bump_id</string>
|
||||||
|
Reference in New Issue
Block a user