From d3a260f0a8a80559169980fa65881c7e08513d49 Mon Sep 17 00:00:00 2001 From: Ghazi Akmal Fauzan <13521058@std.stei.itb.ac.id> Date: Sun, 31 Mar 2024 23:13:09 +0700 Subject: [PATCH] feat: received scan response from server --- app/build.gradle.kts | 1 + .../nerbos/fragments/scan/ScanFragment.kt | 62 ++++++++++++++++++- .../example/nerbos/service/Authentication.kt | 2 +- app/src/main/res/values/strings.xml | 1 + 4 files changed, 64 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 81b18cb..852a074 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -58,6 +58,7 @@ dependencies { implementation("androidx.camera:camera-lifecycle:1.3.2") implementation("androidx.camera:camera-view:1.3.2") implementation("androidx.exifinterface:exifinterface:1.3.7") + implementation("com.squareup.okhttp3:okhttp:4.9.3") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") diff --git a/app/src/main/java/com/example/nerbos/fragments/scan/ScanFragment.kt b/app/src/main/java/com/example/nerbos/fragments/scan/ScanFragment.kt index cdf2eef..44a497a 100644 --- a/app/src/main/java/com/example/nerbos/fragments/scan/ScanFragment.kt +++ b/app/src/main/java/com/example/nerbos/fragments/scan/ScanFragment.kt @@ -8,6 +8,8 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Matrix import android.os.Bundle +import android.os.Handler +import android.os.Looper import android.provider.MediaStore import android.view.LayoutInflater import android.view.View @@ -28,9 +30,14 @@ import androidx.core.net.toUri import androidx.exifinterface.media.ExifInterface import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.example.nerbos.R +import com.example.nerbos.service.Authentication import java.io.File +import java.io.IOException import java.util.concurrent.ExecutorService import java.util.concurrent.Executors +import okhttp3.* +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.RequestBody.Companion.asRequestBody class ScanFragment : Fragment() { @@ -40,6 +47,10 @@ class ScanFragment : Fragment() { private val requestCameraPermissionCode = Manifest.permission.CAMERA + private val uploadURL: String by lazy { + requireContext().getString(R.string.backend_api_scan) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -160,7 +171,15 @@ class ScanFragment : Fragment() { MaterialAlertDialogBuilder(requireContext()) .setTitle("Use this picture?") .setPositiveButton("Yes") { dialog, _ -> - // Handle using the picture here + val imageFile = File.createTempFile("image", ".jpg", requireContext().cacheDir) + imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageFile.outputStream()) + uploadImageToServer(imageFile) { success, message -> + if (success) { + showToastOnUIThread("Image uploaded successfully") + } else { + showToastOnUIThread(message ?: "Failed to upload image. Please try again later.") + } + } dialog.dismiss() } .setNegativeButton("No") { dialog, _ -> @@ -176,6 +195,47 @@ class ScanFragment : Fragment() { } } + private fun uploadImageToServer(imageFile: File, callback: (Boolean, String?) -> Unit) { + val client = OkHttpClient() + + val requestBody = MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart("file", imageFile.name, imageFile.asRequestBody("image/*".toMediaTypeOrNull())) + .build() + + val authentication = Authentication(requireContext()) + val token = authentication.getToken() + + val request = Request.Builder() + .url(uploadURL) + .header("Authorization", "Bearer $token") + .post(requestBody) + .build() + + client.newCall(request).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful) { + showToastOnUIThread("Image uploaded successfully") + callback(true, "Image uploaded successfully") + } else { + showToastOnUIThread("Failed to upload image. Please try again later.") + callback(false, "Failed to upload image. Please try again later.") + } + } + + override fun onFailure(call: Call, e: IOException) { + showToastOnUIThread("Failed to upload image: ${e.message}") + callback(false, e.message) + } + }) + } + + private fun showToastOnUIThread(message: String) { + Handler(Looper.getMainLooper()).post { + Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() + } + } + private val requestCameraPermission = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (isGranted) { diff --git a/app/src/main/java/com/example/nerbos/service/Authentication.kt b/app/src/main/java/com/example/nerbos/service/Authentication.kt index 62cde48..ca362b7 100644 --- a/app/src/main/java/com/example/nerbos/service/Authentication.kt +++ b/app/src/main/java/com/example/nerbos/service/Authentication.kt @@ -84,7 +84,7 @@ class Authentication(private val context: Context) { return email.toInt() } - private fun getToken(): String { + internal fun getToken(): String { val sharedPreferences : SharedPreferences = context.getSharedPreferences(context.getString(R.string.preferences), Context.MODE_PRIVATE) return sharedPreferences.getString(context.getString(R.string.token), "") ?: "" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f22dee3..a0ce034 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -23,6 +23,7 @@ <string name="backend_api_login">https://pbd-backend-2024.vercel.app/api/auth/login</string> <string name="backend_api_token">https://pbd-backend-2024.vercel.app/api/auth/token</string> + <string name="backend_api_scan">https://pbd-backend-2024.vercel.app/api/bill/upload</string> <string name="ok">OK</string> <string name="welcome">Welcome!</string> -- GitLab