From 734b64ce3bafbe49ba8daa99ae470d6a5cd8e33c Mon Sep 17 00:00:00 2001 From: raphael Date: Wed, 29 Dec 2021 19:42:43 +0100 Subject: [PATCH] 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 --- .../com/example/bump/MessageProcessorTest.kt | 11 ++ .../java/com/example/bump/RestCryptTest.kt | 3 +- .../java/com/example/bump/BumpProcessor.kt | 116 ++++++++++++++++++ .../java/com/example/bump/CameraFragment.kt | 7 +- .../java/com/example/bump/FirstFragment.kt | 23 ++-- .../main/java/com/example/bump/LocalData.kt | 24 ++++ .../java/com/example/bump/MainApplication.kt | 6 +- app/src/main/java/com/example/bump/Message.kt | 5 + .../java/com/example/bump/RestSingleton.kt | 6 +- app/src/main/res/values/strings.xml | 2 + 10 files changed, 187 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/com/example/bump/BumpProcessor.kt create mode 100644 app/src/main/java/com/example/bump/LocalData.kt create mode 100644 app/src/main/java/com/example/bump/Message.kt diff --git a/app/src/androidTest/java/com/example/bump/MessageProcessorTest.kt b/app/src/androidTest/java/com/example/bump/MessageProcessorTest.kt index 15f9e35..dedba27 100644 --- a/app/src/androidTest/java/com/example/bump/MessageProcessorTest.kt +++ b/app/src/androidTest/java/com/example/bump/MessageProcessorTest.kt @@ -1,6 +1,8 @@ package com.example.bump 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.Test import org.junit.runner.RunWith @@ -28,6 +30,15 @@ class MessageProcessorTest { 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 { @JvmStatic fun decryptMessage(code: String, messageData: String): String { diff --git a/app/src/androidTest/java/com/example/bump/RestCryptTest.kt b/app/src/androidTest/java/com/example/bump/RestCryptTest.kt index 72073d6..7b3f724 100644 --- a/app/src/androidTest/java/com/example/bump/RestCryptTest.kt +++ b/app/src/androidTest/java/com/example/bump/RestCryptTest.kt @@ -68,9 +68,8 @@ class RestCryptTest{ val lock = CountDownLatch(1) - fun listTester(resultList: JSONObject) { + fun listTester(messages: JSONArray) { val message = MessageProcessor(code) - val messages: JSONArray = resultList.get("messages") as JSONArray var messageEncoded = messages[0] as JSONObject var messageData = messageEncoded.get("data").toString() diff --git a/app/src/main/java/com/example/bump/BumpProcessor.kt b/app/src/main/java/com/example/bump/BumpProcessor.kt new file mode 100644 index 0000000..4ef5bf6 --- /dev/null +++ b/app/src/main/java/com/example/bump/BumpProcessor.kt @@ -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 + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bump/CameraFragment.kt b/app/src/main/java/com/example/bump/CameraFragment.kt index fd7aa54..913e3ba 100644 --- a/app/src/main/java/com/example/bump/CameraFragment.kt +++ b/app/src/main/java/com/example/bump/CameraFragment.kt @@ -31,9 +31,7 @@ import kotlin.math.min import android.view.WindowInsets import android.graphics.Insets - - - +import com.example.bump.BumpProcessor class CameraFragment: Fragment() { @@ -182,6 +180,9 @@ class CameraFragment: Fragment() { .addOnSuccessListener { barcodes -> barcodes.forEach { Log.d(TAG, it.rawValue!!) + val bump = BumpProcessor.getInstance(requireContext()) + bump.addSecret(requireContext(), it.rawValue!!) + fragmentManager?.popBackStack() } } .addOnFailureListener { diff --git a/app/src/main/java/com/example/bump/FirstFragment.kt b/app/src/main/java/com/example/bump/FirstFragment.kt index 8158923..fb91131 100644 --- a/app/src/main/java/com/example/bump/FirstFragment.kt +++ b/app/src/main/java/com/example/bump/FirstFragment.kt @@ -6,8 +6,13 @@ 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.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. @@ -20,6 +25,11 @@ class FirstFragment : Fragment() { // onDestroyView. private val binding get() = _binding!! + private lateinit var rest: RestSingleton + private lateinit var log: JSONArray + + private val bump = BumpProcessor(requireContext()) + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -27,21 +37,20 @@ class FirstFragment : Fragment() { _binding = FragmentFirstBinding.inflate(inflater, container, false) return binding.root - } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - - binding.buttonFirst.setOnClickListener { - findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment) + if(bump.hasSecret()){ + binding.buttonFirst.visibility = View.GONE + } else { + binding.buttonFirst.setOnClickListener { + findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment) + } } - testDecryption() } - fun testDecryption() { - } override fun onDestroyView() { super.onDestroyView() diff --git a/app/src/main/java/com/example/bump/LocalData.kt b/app/src/main/java/com/example/bump/LocalData.kt new file mode 100644 index 0000000..77bc40b --- /dev/null +++ b/app/src/main/java/com/example/bump/LocalData.kt @@ -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<> +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bump/MainApplication.kt b/app/src/main/java/com/example/bump/MainApplication.kt index 8fcb770..0309056 100644 --- a/app/src/main/java/com/example/bump/MainApplication.kt +++ b/app/src/main/java/com/example/bump/MainApplication.kt @@ -6,6 +6,7 @@ import android.content.Context // Not object class. AndroidManifest.xml error happen. class MainApplication : Application() { lateinit var rest : RestSingleton + lateinit var bump : BumpProcessor init { instance = this @@ -25,7 +26,10 @@ class MainApplication : Application() { // Use ApplicationContext. // example: SharedPreferences etc... - val context: Context = MainApplication.applicationContext() + val context: Context = applicationContext() rest = RestSingleton(context) + // bump = BumpProcessor(context) + + // bump.startUpdateHandler(context) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bump/Message.kt b/app/src/main/java/com/example/bump/Message.kt new file mode 100644 index 0000000..a5de05f --- /dev/null +++ b/app/src/main/java/com/example/bump/Message.kt @@ -0,0 +1,5 @@ +package com.example.bump + +class Message { + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bump/RestSingleton.kt b/app/src/main/java/com/example/bump/RestSingleton.kt index 53b39d1..a1930c5 100644 --- a/app/src/main/java/com/example/bump/RestSingleton.kt +++ b/app/src/main/java/com/example/bump/RestSingleton.kt @@ -29,7 +29,7 @@ class RestSingleton constructor(context: Context){ 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 data = JSONObject() data.put("sender", sender) @@ -38,10 +38,10 @@ class RestSingleton constructor(context: Context){ data, { response -> run { - callback(response) + callback(response.get("messages") as JSONArray) } } , - {callback(JSONObject())}) + {callback(JSONArray())}) requestQueue.add(jsonRequest) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 17943fa..75043a7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,4 +12,6 @@ No Sender Added Scan Camera Fragment + code_file_key + code_key \ No newline at end of file