adds stub for notifications
This commit is contained in:
parent
734b64ce3b
commit
6e3f3c44af
@ -1,8 +1,9 @@
|
||||
package com.example.bump
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.internal.runner.InstrumentationConnection
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.example.bump.util.LocalData
|
||||
import com.example.bump.util.MessageProcessor
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@ -15,8 +16,9 @@ class MessageProcessorTest {
|
||||
val code = "dydoes-unknowledgeable-indiscretion-househusbands-pot-walloper-indiscretion-discophorous-transcriptions-dydoes-poodle-faker-transcriptions-budlike"
|
||||
// val messageRaw = "M1dEAxKZ5HUHCJoRkgGOvAABhqCAAAAAAGG2eKTSlKXWLDQx5B_wssZsNwsanzQID2UyUm4KKuKYKgfwH5MG2N-qzt6K4mg3pfZmWPaiDB9PiqlX236k6zo9Yvvq"
|
||||
val messageRaw = "M1dEAxKZ5HUHCJoRkgGOvAABhqCAAAAAAGG8afPPk380EzwcbGzNoTr_I4y6YT8hnUYcToinlgsVkaUx5K-JicdS5epZenOX4u8vVhhMvR0ebeWm_mgp6LZvTw8S"
|
||||
val data = decryptMessage(code, messageRaw)
|
||||
Assert.assertEquals(data, "hello")
|
||||
val processor = MessageProcessor(code)
|
||||
val decrypted = processor.decrypt(messageRaw)
|
||||
Assert.assertEquals(decrypted, "hello")
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -26,7 +28,9 @@ class MessageProcessorTest {
|
||||
|
||||
val test = getRandomString(32)
|
||||
val encrypted = message.encrypt(test)
|
||||
val decrypted = decryptMessage(code, encrypted)
|
||||
|
||||
val processor = MessageProcessor(code)
|
||||
val decrypted = processor.decrypt(encrypted)
|
||||
Assert.assertEquals(test, decrypted)
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,9 @@ package com.example.bump
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.example.bump.util.Message
|
||||
import com.example.bump.util.MessageProcessor
|
||||
import com.example.bump.util.RestSingleton
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
@ -27,6 +30,13 @@ class ExampleInstrumentedTest {
|
||||
}
|
||||
}
|
||||
|
||||
class NotificationTest {
|
||||
@Test
|
||||
fun showNotification() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class RestCryptTest{
|
||||
@Test
|
||||
@ -46,6 +56,8 @@ class RestCryptTest{
|
||||
assertEquals(messageData, encrypted)
|
||||
val data = message.decrypt(messageData)
|
||||
assertEquals(data, testMessage)
|
||||
|
||||
val m = Message(code, data, messageEncrypted.get("timestamp").toString())
|
||||
lock.countDown()
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name="com.example.bump.MainApplication"
|
||||
android:name="com.example.bump.ui.MainApplication"
|
||||
android:allowBackup="true"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
@ -17,7 +17,7 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.BumpForAndroid">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:name="com.example.bump.ui.MainActivity"
|
||||
tools:node="merge"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
|
@ -1,5 +0,0 @@
|
||||
package com.example.bump
|
||||
|
||||
class Message {
|
||||
|
||||
}
|
28
app/src/main/java/com/example/bump/receiver/AlarmReceiver.kt
Normal file
28
app/src/main/java/com/example/bump/receiver/AlarmReceiver.kt
Normal file
@ -0,0 +1,28 @@
|
||||
package com.example.bump.receiver
|
||||
|
||||
import android.app.NotificationManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.example.bump.util.sendNotification
|
||||
import com.maenle.bump.R
|
||||
|
||||
class AlarmReceiver: BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
|
||||
val notificationManager = ContextCompat.getSystemService(
|
||||
context,
|
||||
NotificationManager::class.java
|
||||
) as NotificationManager
|
||||
|
||||
notificationManager.sendNotification(
|
||||
"Hello",
|
||||
context
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.example.bump.receiver
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.SystemClock
|
||||
import android.text.format.DateUtils
|
||||
import androidx.core.app.AlarmManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
|
||||
class SnoozeReceiver: BroadcastReceiver() {
|
||||
private val REQUEST_CODE = 0
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val triggerTime = SystemClock.elapsedRealtime() + DateUtils.MINUTE_IN_MILLIS
|
||||
|
||||
val notifyIntent = Intent(context, AlarmReceiver::class.java)
|
||||
val notifyPendingIntent = PendingIntent.getBroadcast(
|
||||
context,
|
||||
REQUEST_CODE,
|
||||
notifyIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
AlarmManagerCompat.setExactAndAllowWhileIdle(
|
||||
alarmManager,
|
||||
AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||
triggerTime,
|
||||
notifyPendingIntent
|
||||
)
|
||||
|
||||
val notificationManager = ContextCompat.getSystemService(
|
||||
context,
|
||||
NotificationManager::class.java
|
||||
) as NotificationManager
|
||||
notificationManager.cancelAll()
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.maenle.bump
|
||||
package com.example.bump.ui
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
@ -31,7 +31,8 @@ import kotlin.math.min
|
||||
import android.view.WindowInsets
|
||||
|
||||
import android.graphics.Insets
|
||||
import com.example.bump.BumpProcessor
|
||||
import com.example.bump.util.BumpProcessor
|
||||
import com.example.bump.util.CameraXViewModel
|
||||
|
||||
|
||||
class CameraFragment: Fragment() {
|
||||
@ -181,7 +182,7 @@ class CameraFragment: Fragment() {
|
||||
barcodes.forEach {
|
||||
Log.d(TAG, it.rawValue!!)
|
||||
val bump = BumpProcessor.getInstance(requireContext())
|
||||
bump.addSecret(requireContext(), it.rawValue!!)
|
||||
bump.addSecret(requireContext(), it.rawValue!!)
|
||||
fragmentManager?.popBackStack()
|
||||
}
|
||||
}
|
@ -1,18 +1,20 @@
|
||||
package com.maenle.bump
|
||||
package com.example.bump.ui
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.example.bump.BumpProcessor
|
||||
import com.example.bump.MessageProcessor
|
||||
import com.example.bump.RestSingleton
|
||||
import com.example.bump.util.BumpProcessor
|
||||
import com.example.bump.util.RestSingleton
|
||||
import com.maenle.bump.R
|
||||
import com.maenle.bump.databinding.FragmentFirstBinding
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass as the default destination in the navigation.
|
||||
@ -36,6 +38,13 @@ class FirstFragment : Fragment() {
|
||||
): View? {
|
||||
|
||||
_binding = FragmentFirstBinding.inflate(inflater, container, false)
|
||||
|
||||
// TODO: Step 1.7 call create channel
|
||||
createChannel(
|
||||
getString(R.string.bump_notification_channel_id),
|
||||
getString(R.string.bump_notification_channel_name)
|
||||
)
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
@ -51,6 +60,35 @@ class FirstFragment : Fragment() {
|
||||
|
||||
}
|
||||
|
||||
private fun createChannel(channelId: String, channelName: String) {
|
||||
// TODO: Step 1.6 START create a channel
|
||||
val notificationChannel = NotificationChannel(
|
||||
channelId,
|
||||
channelName,
|
||||
// TODO: Step 2.4 change importance
|
||||
NotificationManager.IMPORTANCE_HIGH
|
||||
)// TODO: Step 2.6 disable badges for this channel
|
||||
.apply {
|
||||
setShowBadge(false)
|
||||
}
|
||||
|
||||
notificationChannel.enableLights(true)
|
||||
notificationChannel.lightColor = Color.RED
|
||||
notificationChannel.enableVibration(true)
|
||||
notificationChannel.description = getString(R.string.bump_notification_channel_id)
|
||||
|
||||
val notificationManager = requireActivity().getSystemService(
|
||||
NotificationManager::class.java
|
||||
)
|
||||
notificationManager.createNotificationChannel(notificationChannel)
|
||||
|
||||
// TODO: Step 1.6 END create a channel
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance() = FirstFragment()
|
||||
}
|
||||
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
@ -1,4 +1,4 @@
|
||||
package com.maenle.bump
|
||||
package com.example.bump.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
@ -9,6 +9,7 @@ import androidx.navigation.ui.navigateUp
|
||||
import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.maenle.bump.R
|
||||
import com.maenle.bump.databinding.ActivityMainBinding
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
@ -1,7 +1,9 @@
|
||||
package com.example.bump
|
||||
package com.example.bump.ui
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import com.example.bump.util.BumpProcessor
|
||||
import com.example.bump.util.RestSingleton
|
||||
|
||||
// Not object class. AndroidManifest.xml error happen.
|
||||
class MainApplication : Application() {
|
@ -1,4 +1,4 @@
|
||||
package com.maenle.bump
|
||||
package com.example.bump.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
@ -1,15 +1,11 @@
|
||||
package com.example.bump
|
||||
package com.example.bump.util
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.android.volley.toolbox.JsonObjectRequest
|
||||
import com.maenle.bump.MainActivity
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import javax.inject.Inject
|
||||
|
||||
class BumpProcessor constructor(context: Context) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.maenle.bump
|
||||
package com.example.bump.util
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log
|
@ -1,4 +1,4 @@
|
||||
package com.example.bump
|
||||
package com.example.bump.util
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Context.MODE_PRIVATE
|
10
app/src/main/java/com/example/bump/util/Message.kt
Normal file
10
app/src/main/java/com/example/bump/util/Message.kt
Normal file
@ -0,0 +1,10 @@
|
||||
package com.example.bump.util
|
||||
|
||||
import java.time.LocalDate
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
|
||||
class Message(var sender: String, var data: String, timestamp: String) {
|
||||
val timestamp = LocalDate.parse(timestamp, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSS"))
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.example.bump
|
||||
package com.example.bump.util
|
||||
|
||||
import java.util.Base64
|
||||
import javax.crypto.spec.PBEKeySpec
|
||||
@ -7,7 +7,7 @@ import com.macasaet.fernet.Key
|
||||
import com.macasaet.fernet.Token
|
||||
import com.macasaet.fernet.StringValidator
|
||||
import com.macasaet.fernet.Validator
|
||||
import com.maenle.bump.MainActivity
|
||||
import com.example.bump.ui.MainActivity
|
||||
import java.math.BigInteger
|
||||
import java.security.SecureRandom
|
||||
import java.time.Duration
|
||||
@ -80,7 +80,7 @@ class MessageProcessor(code: String, private val salt: ByteArray? = null) {
|
||||
val decodedMessage : ByteArray = Base64.getUrlDecoder().decode(message)
|
||||
|
||||
salt = decodedMessage.copyOfRange(0, SALT_LENGTH)
|
||||
val iterationsDecoded = decodedMessage.copyOfRange(SALT_LENGTH, SALT_LENGTH+ ITERATIONS_LENGTH)
|
||||
val iterationsDecoded = decodedMessage.copyOfRange(SALT_LENGTH, SALT_LENGTH + ITERATIONS_LENGTH)
|
||||
val tokenString = String(Base64.getUrlEncoder().encode(decodedMessage.copyOfRange(20, decodedMessage.size)))
|
||||
|
||||
iterations = BigInteger(iterationsDecoded).toInt()
|
91
app/src/main/java/com/example/bump/util/NotificationUtil.kt
Normal file
91
app/src/main/java/com/example/bump/util/NotificationUtil.kt
Normal file
@ -0,0 +1,91 @@
|
||||
package com.example.bump.util
|
||||
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.example.bump.receiver.SnoozeReceiver
|
||||
import com.example.bump.ui.MainActivity
|
||||
import com.maenle.bump.R
|
||||
|
||||
// Notification ID.
|
||||
private val NOTIFICATION_ID = 0
|
||||
private val REQUEST_CODE = 0
|
||||
private val FLAGS = 0
|
||||
|
||||
fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
|
||||
// Create the content intent for the notification, which launches
|
||||
// this activity
|
||||
// TODO: Step 1.11 create intent
|
||||
val contentIntent = Intent(applicationContext, MainActivity::class.java)
|
||||
// TODO: Step 1.12 create PendingIntent
|
||||
val contentPendingIntent = PendingIntent.getActivity(
|
||||
applicationContext,
|
||||
NOTIFICATION_ID,
|
||||
contentIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
||||
// TODO: Step 2.0 add style
|
||||
val eggImage = BitmapFactory.decodeResource(
|
||||
applicationContext.resources,
|
||||
R.drawable.ic_launcher_foreground
|
||||
)
|
||||
val bigPicStyle = NotificationCompat.BigPictureStyle()
|
||||
.bigPicture(eggImage)
|
||||
.bigLargeIcon(null)
|
||||
|
||||
// TODO: Step 2.2 add snooze action
|
||||
val snoozeIntent = Intent(applicationContext, SnoozeReceiver::class.java)
|
||||
val snoozePendingIntent: PendingIntent = PendingIntent.getBroadcast(
|
||||
applicationContext,
|
||||
REQUEST_CODE,
|
||||
snoozeIntent,
|
||||
FLAGS)
|
||||
|
||||
// TODO: Step 1.2 get an instance of NotificationCompat.Builder
|
||||
// Build the notification
|
||||
val builder = NotificationCompat.Builder(
|
||||
applicationContext,
|
||||
applicationContext.getString(R.string.bump_notification_channel_id)
|
||||
)
|
||||
|
||||
// TODO: Step 1.8 use the new 'breakfast' notification channel
|
||||
|
||||
// TODO: Step 1.3 set title, text and icon to builder
|
||||
.setSmallIcon(R.drawable.ic_launcher_foreground)
|
||||
.setContentTitle(applicationContext
|
||||
.getString(R.string.notification_title))
|
||||
.setContentText(messageBody)
|
||||
|
||||
// TODO: Step 1.13 set content intent
|
||||
.setContentIntent(contentPendingIntent)
|
||||
.setAutoCancel(true)
|
||||
|
||||
// TODO: Step 2.1 add style to builder
|
||||
.setStyle(bigPicStyle)
|
||||
.setLargeIcon(eggImage)
|
||||
|
||||
// TODO: Step 2.3 add snooze action
|
||||
.addAction(
|
||||
R.drawable.ic_launcher_foreground,
|
||||
applicationContext.getString(R.string.snooze),
|
||||
snoozePendingIntent
|
||||
)
|
||||
|
||||
// TODO: Step 2.5 set priority
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
// TODO: Step 1.4 call notify
|
||||
notify(NOTIFICATION_ID, builder.build())
|
||||
}
|
||||
|
||||
// TODO: Step 1.14 Cancel all notifications
|
||||
/**
|
||||
* Cancels all notifications.
|
||||
*
|
||||
*/
|
||||
fun NotificationManager.cancelNotifications() {
|
||||
cancelAll()
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
package com.example.bump
|
||||
package com.example.bump.util
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.android.volley.Request
|
||||
import com.android.volley.RequestQueue
|
||||
import com.android.volley.toolbox.*
|
||||
import com.maenle.bump.MainActivity
|
||||
import com.example.bump.ui.MainActivity
|
||||
import org.json.JSONArray
|
||||
|
||||
import org.json.JSONObject
|
@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
tools:context="com.example.bump.ui.MainActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".SecondFragment">
|
||||
tools:context="com.example.bump.ui.SecondFragment">
|
||||
|
||||
<!--androidx.camera.view.PreviewView
|
||||
android:id="@+id/viewFinder"
|
||||
|
@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".FirstFragment">
|
||||
tools:context="com.example.bump.ui.FirstFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview_first"
|
||||
|
@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".SecondFragment">
|
||||
tools:context="com.example.bump.ui.SecondFragment">
|
||||
|
||||
<androidx.camera.view.PreviewView
|
||||
android:id="@+id/viewFinder"
|
||||
|
@ -1,7 +1,7 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="com.maenle.bump.MainActivity">
|
||||
tools:context="com.maenle.bump.com.example.bump.ui.MainActivity">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
<fragment
|
||||
android:id="@+id/FirstFragment"
|
||||
android:name="com.maenle.bump.FirstFragment"
|
||||
android:name="com.example.bump.ui.FirstFragment"
|
||||
android:label="@string/first_fragment_label"
|
||||
tools:layout="@layout/fragment_first">
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/SecondFragment"
|
||||
android:name="com.maenle.bump.SecondFragment"
|
||||
android:name="com.example.bump.ui.SecondFragment"
|
||||
android:label="@string/second_fragment_label"
|
||||
tools:layout="@layout/fragment_second">
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/CameraFragment"
|
||||
android:name="com.maenle.bump.CameraFragment"
|
||||
android:name="com.example.bump.ui.CameraFragment"
|
||||
android:label="@string/camera_fragment_label"
|
||||
tools:layout="@layout/fragment_camera">
|
||||
|
||||
|
@ -14,4 +14,8 @@
|
||||
<string name="camera_fragment_label">Camera Fragment</string>
|
||||
<string name="preference_file_key">code_file_key</string>
|
||||
<string name="code_key">code_key</string>
|
||||
<string name="notification_title">Bump</string>
|
||||
<string name="bump_notification_channel_id">bump_id</string>
|
||||
<string name="snooze">Snooze</string>
|
||||
<string name="bump_notification_channel_name">Bump</string>
|
||||
</resources>
|
Loading…
Reference in New Issue
Block a user