diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bfacbd1d614984c5ebe50aa134ff479140f54db6..4268f2ee25bb1ade5a1792c2218906851a9d5cf4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,10 @@ android:name="android.hardware.camera" android:required="false" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> @@ -15,8 +19,6 @@ <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <queries> <intent> @@ -55,7 +57,8 @@ android:name=".service.jwt.JwtService" android:enabled="true" android:exported="true" - android:permission="android.permission.INTERNET"></service> + android:permission="android.permission.INTERNET"> + </service> <receiver android:name=".ui.transactions.TransactionsBroadcastReceiver" @@ -76,7 +79,8 @@ <activity android:name=".MainActivity" - android:exported="true"></activity> + android:exported="true"> + </activity> </application> diff --git a/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt b/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt index ac2f699489d874c76d9f99703006c13ce544b1a7..dcf6420c546113097190383b0de42234c21a829c 100644 --- a/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt @@ -7,7 +7,10 @@ import android.content.DialogInterface import android.content.Intent import android.content.pm.PackageManager import android.net.Uri +import android.os.Build import android.os.Bundle +import android.os.Environment +import android.provider.Settings import android.util.Log import android.view.LayoutInflater import android.view.View @@ -29,6 +32,7 @@ import com.example.bondoyap.ui.transactions.TransactionsViewModel import com.example.bondoyap.ui.transactions.TransactionsViewModelFactory import java.io.File + class SettingsFragment : Fragment() { private var _binding: FragmentSettingsBinding? = null @@ -87,6 +91,16 @@ class SettingsFragment : Fragment() { } val appContext = context?.applicationContext + if (Build.VERSION.SDK_INT >= 30) { + if (!Environment.isExternalStorageManager()) { + Toast.makeText(appContext, "Perbolehkan Akses file ...", Toast.LENGTH_SHORT).show() + val getpermission = Intent() + getpermission.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION) + startActivity(getpermission) + } + } + + logoutButton.setOnClickListener { showConfirmationDialog("Logout", "Apakah Anda yakin logout dari aplikasi?") { settingsViewModel.getUser() @@ -113,8 +127,6 @@ class SettingsFragment : Fragment() { exporter = TransactionsExporter(transactionsViewModel, requireContext()) - // exporter = context?.let { TransactionsExporter(database, it) }!! - saveButton.setOnClickListener { if (ContextCompat.checkSelfPermission( requireContext(), @@ -133,11 +145,6 @@ class SettingsFragment : Fragment() { builder.setItems(formats) { dialog: DialogInterface, which: Int -> when (which) { 0 -> { - Toast.makeText( - appContext, - "Menyimpan transaksi ke xls...", - Toast.LENGTH_SHORT - ).show() exporter.exportToXLS() Toast.makeText( appContext, @@ -147,11 +154,6 @@ class SettingsFragment : Fragment() { } 1 -> { - Toast.makeText( - appContext, - "Menyimpan transaksi ke xlsx...", - Toast.LENGTH_SHORT - ).show() exporter.exportToXLSX() Toast.makeText( appContext, @@ -177,13 +179,6 @@ class SettingsFragment : Fragment() { val message = "Halo, Berikut adalah detail transaksi aplikasi Bondoman.\n " + "File Transaksi terlampir." - settingsViewModel.getUser()?.let { user -> - recipientEmail = user.email - val attachment = getAttachmentUri("transactions.xls") - Log.d("Attachment", "Attachment URI: $attachment") - context?.let { EmailHelper(it) } - ?.sendGmail(recipientEmail, subject, message, attachment) - } val formats = arrayOf("XLS", "XLSX") val builder = AlertDialog.Builder(requireContext()) @@ -208,7 +203,7 @@ class SettingsFragment : Fragment() { 1 -> { Toast.makeText( appContext, - "Menyimpan transaksi ke xlsx...", + "Mengirim file xlsx...", Toast.LENGTH_SHORT ).show() settingsViewModel.getUser()?.let { user -> @@ -263,15 +258,16 @@ class SettingsFragment : Fragment() { } private fun getAttachmentUri(fileName: String): Uri { - val cacheDir = context?.cacheDir - val fileCache = File(cacheDir, fileName) -// val documentsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) -// val file = File(documentsDir, fileName) +// val cacheDir = context?.cacheDir +// val fileCache = File(cacheDir, fileName) + val documentsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) + val file = File(documentsDir, fileName) - Log.d("Attachment", "File path: ${fileCache.absolutePath}") + Log.d("Attachment", "File path: ${file.absolutePath}") - if (!fileCache.exists()) { - Log.d("Attachment", "Creating file: ${fileCache.absolutePath}") + if (!file.exists()) { + Log.d("Attachment", "Creating file: ${file.absolutePath}") + Toast.makeText(requireContext(),"Menyimpan File di Documents ...", Toast.LENGTH_SHORT).show() if (fileName.endsWith(".xls")) { exporter.exportToXLS() } else if (fileName.endsWith(".xlsx")) { @@ -280,12 +276,12 @@ class SettingsFragment : Fragment() { // Toast.makeText(requireContext(),"File belum tersimpan! Simpan File terlebih dahulu!", Toast.LENGTH_SHORT).show() } - Log.d("Attachment", "File path: ${fileCache.absolutePath}") + Log.d("Attachment", "File path: ${file.absolutePath}") return FileProvider.getUriForFile( requireContext(), "${requireContext().packageName}.provider", - fileCache + file ) } diff --git a/app/src/main/java/com/example/bondoyap/ui/settings/TransactionsExporter.kt b/app/src/main/java/com/example/bondoyap/ui/settings/TransactionsExporter.kt index 96c9d5f7dfd12b36538971f2230b520251557e1e..4c8b5f4a2120633d869431d0fabd8289d0ac2f83 100644 --- a/app/src/main/java/com/example/bondoyap/ui/settings/TransactionsExporter.kt +++ b/app/src/main/java/com/example/bondoyap/ui/settings/TransactionsExporter.kt @@ -35,53 +35,73 @@ class TransactionsExporter(private val transactionsViewModel: TransactionsViewMo private fun writeToExcel(fileName: String, transactions: List<Transactions>) { val documentsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) - val file = File(documentsDir, fileName) + val file = createFile(fileName, "documents") + val path = File(documentsDir, fileName) + + Log.d("Save", path.absolutePath) val cacheDir = context.cacheDir - val fileCache = File(cacheDir, fileName) + val fileCache = createFile(fileName, "cache") + val pathCache = File(cacheDir, fileName) - workbook { - sheet("Transactions") { - transactionsHeader() - for (transaction in transactions) { - row { - cell(transaction.tanggal) - cell( - if (transaction.isPemasukan) { - "Pemasukan" - } else { - "Pengeluaran" - } - ) - cell(transaction.nominal) - cell(transaction.judul) - cell(if (transaction.longitude.isEmpty() || transaction.latitude.isEmpty()) { - "Unavailable" - } else { - val addresses: List<Address> = - Geocoder(context, Locale.getDefault()).getFromLocation( - transaction.latitude.toDouble(), - transaction.longitude.toDouble(), - 1 - ) ?: emptyList() - if (addresses.isNotEmpty()) { - val locationName = addresses[0].getAddressLine(0) - locationName - } else { + if (file != null) { + workbook { + sheet("Transactions") { + transactionsHeader() + + for (transaction in transactions) { + row { + cell(transaction.tanggal) + cell(if (transaction.isPemasukan) "Pemasukan" else "Pengeluaran") + cell(transaction.nominal) + cell(transaction.judul) + cell(if (transaction.longitude.isEmpty() || transaction.latitude.isEmpty()) { "Unavailable" - } - }) + } else { + val addresses: List<Address> = + Geocoder(context, Locale.getDefault()).getFromLocation( + transaction.latitude.toDouble(), + transaction.longitude.toDouble(), + 1 + ) ?: emptyList() + if (addresses.isNotEmpty()) { + addresses[0].getAddressLine(0) ?: "Unavailable" + } else { + "Unavailable" + } + }) + } } } - } - }.write(file.absolutePath) + }.write(path.absolutePath) + } else { + // Handle case where file creation failed + println("Failed to create file.") + } + } + fun createFile(fileName: String, directoryType: String): File? { + val targetDirectory = when (directoryType) { + "documents" -> Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) + "cache" -> context.cacheDir + else -> null + } - file.copyTo(fileCache, true) + if (targetDirectory != null) { + val file = File(targetDirectory, fileName) + try { + if (!file.exists()) { + file.createNewFile() + } + return file + } catch (e: Exception) { + e.printStackTrace() + } + } + return null } - private fun Sheet.transactionsHeader() { val headings = listOf("Tanggal", "Kategori Transaksi", "Nominal Transaksi", "Nama Transaksi", "Lokasi")