adds rest list receiver, adds local code storage
- rest class now receives a list as well as single messages - adds support for threaded singleton which takes care of continuous checking of the bump server to get the most up-to-date list of messages - adds local data class with tests to get locally saved code in preferences
This commit is contained in:
parent
7e4cfceab4
commit
734b64ce3b
@ -1,6 +1,8 @@
|
|||||||
package com.example.bump
|
package com.example.bump
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import androidx.test.internal.runner.InstrumentationConnection
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
@ -28,6 +30,15 @@ class MessageProcessorTest {
|
|||||||
Assert.assertEquals(test, decrypted)
|
Assert.assertEquals(test, decrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setCode() {
|
||||||
|
val test = getRandomString(512)
|
||||||
|
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
val local = LocalData(appContext)
|
||||||
|
local.code = test
|
||||||
|
Assert.assertEquals(local.code, test)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun decryptMessage(code: String, messageData: String): String {
|
fun decryptMessage(code: String, messageData: String): String {
|
||||||
|
@ -68,9 +68,8 @@ class RestCryptTest{
|
|||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
|
|
||||||
|
|
||||||
fun listTester(resultList: JSONObject) {
|
fun listTester(messages: JSONArray) {
|
||||||
val message = MessageProcessor(code)
|
val message = MessageProcessor(code)
|
||||||
val messages: JSONArray = resultList.get("messages") as JSONArray
|
|
||||||
|
|
||||||
var messageEncoded = messages[0] as JSONObject
|
var messageEncoded = messages[0] as JSONObject
|
||||||
var messageData = messageEncoded.get("data").toString()
|
var messageData = messageEncoded.get("data").toString()
|
||||||
|
116
app/src/main/java/com/example/bump/BumpProcessor.kt
Normal file
116
app/src/main/java/com/example/bump/BumpProcessor.kt
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package com.example.bump
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
private var rest: RestSingleton = RestSingleton.getInstance(context)
|
||||||
|
private var secret: String? = null
|
||||||
|
private lateinit var log: JSONArray
|
||||||
|
private lateinit var messenger: MessageProcessor
|
||||||
|
|
||||||
|
init {
|
||||||
|
secret = getSecret(context)
|
||||||
|
log = getLog(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Volatile
|
||||||
|
private var INSTANCE: BumpProcessor? = null
|
||||||
|
fun getInstance(context: Context) =
|
||||||
|
INSTANCE ?: synchronized(this) {
|
||||||
|
INSTANCE ?: BumpProcessor(context).also {
|
||||||
|
INSTANCE = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateLog(context: Context, list: JSONArray) {
|
||||||
|
for(i in 0 until list.length()) {
|
||||||
|
var exists = false
|
||||||
|
for(j in 0 until log.length()) {
|
||||||
|
if (list[i] == log[j]) {
|
||||||
|
exists = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exists.let {
|
||||||
|
log.put(list[i])
|
||||||
|
addToLog(context, list[i] as JSONObject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasSecret(): Boolean {
|
||||||
|
secret?.let {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSecret(context: Context):String? {
|
||||||
|
val secretFile = File(context.filesDir, ".bump_secrets")
|
||||||
|
!secretFile.exists().let {
|
||||||
|
secretFile.createNewFile()
|
||||||
|
}
|
||||||
|
for(line in secretFile.readLines()) {
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startUpdateHandler(context: Context) {
|
||||||
|
|
||||||
|
val delay: Long = 30_000 //milliseconds
|
||||||
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
handler.postDelayed(object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
updateFromServer(context)
|
||||||
|
handler.postDelayed(this, delay)
|
||||||
|
}
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateFromServer(context: Context) {
|
||||||
|
rest.list(messenger.sender) {list -> updateLog(context, list)}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addToLog(context: Context, line: JSONObject) {
|
||||||
|
val logFile = File(context.filesDir, ".bump_log")
|
||||||
|
logFile.appendText(line.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addSecret(context: Context, newSecret: String) {
|
||||||
|
if(!hasSecret()) {
|
||||||
|
val secretFile = File(context.filesDir, ".bump_secrets")
|
||||||
|
!secretFile.exists().let {
|
||||||
|
secretFile.createNewFile()
|
||||||
|
}
|
||||||
|
secretFile.appendText(newSecret)
|
||||||
|
}
|
||||||
|
secret = getSecret(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLog(context: Context): JSONArray {
|
||||||
|
val logFile = File(context.filesDir, ".bump_log")
|
||||||
|
val log = JSONArray()
|
||||||
|
!logFile.exists().let {
|
||||||
|
logFile.createNewFile()
|
||||||
|
}
|
||||||
|
for(line in logFile.readLines()) {
|
||||||
|
log.put(JSONObject(line))
|
||||||
|
}
|
||||||
|
return log
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -31,9 +31,7 @@ import kotlin.math.min
|
|||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
|
|
||||||
import android.graphics.Insets
|
import android.graphics.Insets
|
||||||
|
import com.example.bump.BumpProcessor
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CameraFragment: Fragment() {
|
class CameraFragment: Fragment() {
|
||||||
@ -182,6 +180,9 @@ class CameraFragment: Fragment() {
|
|||||||
.addOnSuccessListener { barcodes ->
|
.addOnSuccessListener { barcodes ->
|
||||||
barcodes.forEach {
|
barcodes.forEach {
|
||||||
Log.d(TAG, it.rawValue!!)
|
Log.d(TAG, it.rawValue!!)
|
||||||
|
val bump = BumpProcessor.getInstance(requireContext())
|
||||||
|
bump.addSecret(requireContext(), it.rawValue!!)
|
||||||
|
fragmentManager?.popBackStack()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.addOnFailureListener {
|
.addOnFailureListener {
|
||||||
|
@ -6,8 +6,13 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import com.example.bump.BumpProcessor
|
||||||
import com.example.bump.MessageProcessor
|
import com.example.bump.MessageProcessor
|
||||||
|
import com.example.bump.RestSingleton
|
||||||
import com.maenle.bump.databinding.FragmentFirstBinding
|
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.
|
* A simple [Fragment] subclass as the default destination in the navigation.
|
||||||
@ -20,6 +25,11 @@ class FirstFragment : Fragment() {
|
|||||||
// onDestroyView.
|
// onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
private lateinit var rest: RestSingleton
|
||||||
|
private lateinit var log: JSONArray
|
||||||
|
|
||||||
|
private val bump = BumpProcessor(requireContext())
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
@ -27,21 +37,20 @@ class FirstFragment : Fragment() {
|
|||||||
|
|
||||||
_binding = FragmentFirstBinding.inflate(inflater, container, false)
|
_binding = FragmentFirstBinding.inflate(inflater, container, false)
|
||||||
return binding.root
|
return binding.root
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
if(bump.hasSecret()){
|
||||||
binding.buttonFirst.setOnClickListener {
|
binding.buttonFirst.visibility = View.GONE
|
||||||
findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
|
} else {
|
||||||
|
binding.buttonFirst.setOnClickListener {
|
||||||
|
findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testDecryption()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testDecryption() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
24
app/src/main/java/com/example/bump/LocalData.kt
Normal file
24
app/src/main/java/com/example/bump/LocalData.kt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package com.example.bump
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Context.MODE_PRIVATE
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import com.maenle.bump.R
|
||||||
|
|
||||||
|
class LocalData(context: Context) {
|
||||||
|
private val codeKey = context.getString(R.string.code_key)
|
||||||
|
private val preferenceKey = context.getString(R.string.preference_file_key)
|
||||||
|
|
||||||
|
private val preferences: SharedPreferences =
|
||||||
|
context.getSharedPreferences(preferenceKey, MODE_PRIVATE)
|
||||||
|
|
||||||
|
var code: String?
|
||||||
|
get() {
|
||||||
|
return preferences.getString(codeKey, null)
|
||||||
|
}
|
||||||
|
set(codeValue) {
|
||||||
|
preferences.edit().putString(codeKey, codeValue).apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
// var messages: List<>
|
||||||
|
}
|
@ -6,6 +6,7 @@ import android.content.Context
|
|||||||
// Not object class. AndroidManifest.xml error happen.
|
// Not object class. AndroidManifest.xml error happen.
|
||||||
class MainApplication : Application() {
|
class MainApplication : Application() {
|
||||||
lateinit var rest : RestSingleton
|
lateinit var rest : RestSingleton
|
||||||
|
lateinit var bump : BumpProcessor
|
||||||
|
|
||||||
init {
|
init {
|
||||||
instance = this
|
instance = this
|
||||||
@ -25,7 +26,10 @@ class MainApplication : Application() {
|
|||||||
|
|
||||||
// Use ApplicationContext.
|
// Use ApplicationContext.
|
||||||
// example: SharedPreferences etc...
|
// example: SharedPreferences etc...
|
||||||
val context: Context = MainApplication.applicationContext()
|
val context: Context = applicationContext()
|
||||||
rest = RestSingleton(context)
|
rest = RestSingleton(context)
|
||||||
|
// bump = BumpProcessor(context)
|
||||||
|
|
||||||
|
// bump.startUpdateHandler(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
5
app/src/main/java/com/example/bump/Message.kt
Normal file
5
app/src/main/java/com/example/bump/Message.kt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package com.example.bump
|
||||||
|
|
||||||
|
class Message {
|
||||||
|
|
||||||
|
}
|
@ -29,7 +29,7 @@ class RestSingleton constructor(context: Context){
|
|||||||
private const val URL = "http://192.168.68.127:4000/api/"
|
private const val URL = "http://192.168.68.127:4000/api/"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun list(sender: String, callback: (JSONObject) -> Unit){
|
fun list(sender: String, callback: (JSONArray) -> Unit){
|
||||||
val url = URL + "list/"
|
val url = URL + "list/"
|
||||||
val data = JSONObject()
|
val data = JSONObject()
|
||||||
data.put("sender", sender)
|
data.put("sender", sender)
|
||||||
@ -38,10 +38,10 @@ class RestSingleton constructor(context: Context){
|
|||||||
data,
|
data,
|
||||||
{ response ->
|
{ response ->
|
||||||
run {
|
run {
|
||||||
callback(response)
|
callback(response.get("messages") as JSONArray)
|
||||||
}
|
}
|
||||||
} ,
|
} ,
|
||||||
{callback(JSONObject())})
|
{callback(JSONArray())})
|
||||||
|
|
||||||
requestQueue.add(jsonRequest)
|
requestQueue.add(jsonRequest)
|
||||||
}
|
}
|
||||||
|
@ -12,4 +12,6 @@
|
|||||||
<string name="current_sender">No Sender Added</string>
|
<string name="current_sender">No Sender Added</string>
|
||||||
<string name="scan_sender">Scan</string>
|
<string name="scan_sender">Scan</string>
|
||||||
<string name="camera_fragment_label">Camera Fragment</string>
|
<string name="camera_fragment_label">Camera Fragment</string>
|
||||||
|
<string name="preference_file_key">code_file_key</string>
|
||||||
|
<string name="code_key">code_key</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue
Block a user