diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d4443457f280209f1fec5c38e25b0d8bf4acaf7d..f5e86c55731d3c9c6e2f943bc478d49712836e3a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -51,4 +51,6 @@ dependencies { testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + implementation ("androidx.navigation:navigation-fragment-ktx:2.4.0-alpha10") + implementation ("androidx.navigation:navigation-ui-ktx:2.4.0-alpha10") } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0a7a0050c4cf51c9ed9f51874fd7f77ac1c239ec..7406ad07aff983711cf0a36bc74b3af58af538fb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools"> + xmlns:tools="http://schemas.android.com/tools" + package="com.example.tubespbd"> + + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <application android:allowBackup="true" @@ -12,13 +16,13 @@ android:supportsRtl="true" android:theme="@style/Theme.Tubespbd" tools:targetApi="31"> + <activity - android:name=".SplashActivity" + android:name=".MainActivity" android:exported="true" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> @@ -27,5 +31,4 @@ android:name="preloaded_fonts" android:resource="@array/preloaded_fonts" /> </application> - -</manifest> \ No newline at end of file +</manifest> diff --git a/app/src/main/java/com/example/tubespbd/MainActivity.kt b/app/src/main/java/com/example/tubespbd/MainActivity.kt index 23d2a1c423608c40beae7ad2b6347d105a03f706..596c5d8b2189c18973f7bd11f973436a01773adb 100644 --- a/app/src/main/java/com/example/tubespbd/MainActivity.kt +++ b/app/src/main/java/com/example/tubespbd/MainActivity.kt @@ -1,19 +1,23 @@ package com.example.tubespbd +import android.Manifest +import android.content.pm.PackageManager import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.ActivityCompat +import com.example.tubespbd.databinding.ActivityMainBinding +import android.location.LocationManager import androidx.navigation.findNavController import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController -import com.example.tubespbd.database.MyDBHelper -import com.example.tubespbd.databinding.ActivityMainBinding import com.google.android.material.bottomnavigation.BottomNavigationView class MainActivity : AppCompatActivity() { - private lateinit var dbHelper: MyDBHelper private lateinit var binding: ActivityMainBinding + private lateinit var locationManager: LocationManager + private lateinit var transactionManager: TransactionManager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -22,11 +26,12 @@ class MainActivity : AppCompatActivity() { binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) + locationManager = getSystemService(LOCATION_SERVICE) as LocationManager + val navView: BottomNavigationView = binding.navView val navController = findNavController(R.id.nav_host_fragment_activity_main) - // Passing each menu ID as a set of Ids because each - // menu should be considered as top level destinations. + val appBarConfiguration = AppBarConfiguration( setOf( R.id.navigation_home, R.id.navigation_scan, R.id.navigation_dashboard, R.id.navigation_notifications @@ -34,39 +39,70 @@ class MainActivity : AppCompatActivity() { ) setupActionBarWithNavController(navController, appBarConfiguration) navView.setupWithNavController(navController) + checkAndRequestLocationPermissions() + } - // Database - dbHelper = MyDBHelper(this) + private fun initializeAfterPermissionsGranted() { + // Initialize TransactionManager after permissions are granted + transactionManager = TransactionManager(this, locationManager) + + performDatabaseOperations() + } + + private fun performDatabaseOperations() { + val locationString = if (hasLocationPermissions() && isLocationEnabled()) { + transactionManager.getLocationString() + } else { + "none" + } - // TEST DB Sementara - // Insert - val transactionId = dbHelper.insertTransaction("Mi Ayam", "Pembelian", 15000, "Bandung") + val transactionId = transactionManager.insertTransaction("Mi Ayam", "Pembelian", 15000, locationString) println("Inserted transaction with ID: $transactionId") - // Retrieve - val transactions = dbHelper.getAllTransactions() - println("All transactions:") - for (transaction in transactions) { - println("Transaction ID: ${transaction.id}, Title: ${transaction.title}, Amount: ${transaction.amount}") + // Retrieve all transactions + val transactions = transactionManager.getAllTransactions() + transactions.forEach { transaction -> + println("Transaction ID: ${transaction.id}, Title: ${transaction.title}, Amount: ${transaction.amount}, Location: ${transaction.location}, Date: ${transaction.tanggal}") } + } - // Update - val updatedRows = dbHelper.updateTransaction(transactionId.toInt(), "Mi Bakso", "Pengeluaran", 20000, "Jakarta") - println("Updated $updatedRows row(s)") + private fun isLocationEnabled(): Boolean { + return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) + } - // Retrieve yang sudah di update - val updatedTransaction = dbHelper.getAllTransactions().find { it.id == transactionId.toInt() } - println("Updated transaction: ${updatedTransaction?.id}, ${updatedTransaction?.title}, ${updatedTransaction?.amount}") + private fun hasLocationPermissions() = ActivityCompat.checkSelfPermission( + this, Manifest.permission.ACCESS_FINE_LOCATION + ) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( + this, Manifest.permission.ACCESS_COARSE_LOCATION + ) == PackageManager.PERMISSION_GRANTED - // Delete - val deletedRows = dbHelper.deleteTransaction(transactionId.toInt()) - println("Deleted $deletedRows row(s)") + private fun requestLocationPermissions() { + ActivityCompat.requestPermissions( + this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), + REQUEST_LOCATION_PERMISSION + ) + } - // Retrieve setelah delete - val remainingTransactions = dbHelper.getAllTransactions() - println("Transactions after deletion:") - for (transaction in remainingTransactions) { - println("Transaction ID: ${transaction.id}, Title: ${transaction.title}, Amount: ${transaction.amount}") + private fun checkAndRequestLocationPermissions() { + if (!hasLocationPermissions()) { + requestLocationPermissions() + } else { + initializeAfterPermissionsGranted() } } + + override fun onRequestPermissionsResult( + requestCode: Int, permissions: Array<String>, grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + if (requestCode == REQUEST_LOCATION_PERMISSION && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) { + initializeAfterPermissionsGranted() + } else { + println("Location permission was denied by the user.") + } + } + + companion object { + private const val REQUEST_LOCATION_PERMISSION = 100 + } } diff --git a/app/src/main/java/com/example/tubespbd/TransactionManager.kt b/app/src/main/java/com/example/tubespbd/TransactionManager.kt new file mode 100644 index 0000000000000000000000000000000000000000..94b495fdf3cb260d4219c030fabfcdc553424c7a --- /dev/null +++ b/app/src/main/java/com/example/tubespbd/TransactionManager.kt @@ -0,0 +1,45 @@ +package com.example.tubespbd + +import android.content.Context +import android.location.LocationManager +import androidx.core.app.ActivityCompat +import android.Manifest +import android.content.pm.PackageManager +import com.example.tubespbd.database.MyDBHelper +import com.example.tubespbd.database.MyDBHelper.Transaction + +class TransactionManager(private val context: Context, private val locationManager: LocationManager) { + + private val dbHelper = MyDBHelper(context) + + fun insertTransaction(title: String, type: String, amount: Int, locationString: String): Long { + val locationString = getLocationString() + return dbHelper.insertTransaction(title, type, amount, locationString) + } + + fun getAllTransactions(): List<Transaction> { + return dbHelper.getAllTransactions() + } + + fun updateTransaction(id: Int, title: String, type: String, amount: Int, location: String): Int { + return dbHelper.updateTransaction(id, title, type, amount, location) + } + + fun deleteTransaction(id: Int): Int { + return dbHelper.deleteTransaction(id) + } + + fun getLocationString(): String { + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && + ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + // Permission is not granted + return "Location Permissions not granted" + } + val location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) + return if (location != null) { + "${location.latitude}, ${location.longitude}" + } else { + "Location not available" + } + } +} diff --git a/app/src/main/java/com/example/tubespbd/database/MyDBHelper.kt b/app/src/main/java/com/example/tubespbd/database/MyDBHelper.kt index 473c3005ea44757433310909a77588b687b3ddde..fed31afbaf94659770fbb66807eb1d3d64f4cdac 100644 --- a/app/src/main/java/com/example/tubespbd/database/MyDBHelper.kt +++ b/app/src/main/java/com/example/tubespbd/database/MyDBHelper.kt @@ -1,88 +1,142 @@ -package com.example.tubespbd.database - -import android.content.ContentValues -import android.content.Context -import android.database.sqlite.SQLiteDatabase -import android.database.sqlite.SQLiteOpenHelper - -class MyDBHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { - - data class Transaction( - val id: Int, - val title: String, - val category: String, - val amount: Int, - val location: String - ) - - companion object { - private const val DATABASE_NAME = "transaction.db" - private const val DATABASE_VERSION = 1 - - private const val TABLE_NAME = "transactions" - private const val COLUMN_ID = "id" - private const val COLUMN_TITLE = "title" - private const val COLUMN_CATEGORY = "category" - private const val COLUMN_AMOUNT = "amount" - private const val COLUMN_LOCATION = "location" - } - - private val CREATE_TABLE = - "CREATE TABLE $TABLE_NAME ($COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT, " + - "$COLUMN_TITLE TEXT, $COLUMN_CATEGORY TEXT, $COLUMN_AMOUNT REAL, $COLUMN_LOCATION TEXT)" - - override fun onCreate(db: SQLiteDatabase) { - db.execSQL(CREATE_TABLE) - } - - override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { - db.execSQL("DROP TABLE IF EXISTS $TABLE_NAME") - onCreate(db) - } - - fun insertTransaction(title: String, category: String, amount: Int, location: String): Long { - val db = this.writableDatabase - val values = ContentValues().apply { - put(COLUMN_TITLE, title) - put(COLUMN_CATEGORY, category) - put(COLUMN_AMOUNT, amount) - put(COLUMN_LOCATION, location) + package com.example.tubespbd.database + + import android.content.ContentValues + import android.content.Context + import android.database.sqlite.SQLiteDatabase + import android.database.sqlite.SQLiteOpenHelper + import android.location.Location + import android.location.LocationManager + import android.Manifest + import androidx.core.app.ActivityCompat + + import android.content.pm.PackageManager + import java.text.SimpleDateFormat + import java.util.* + + class MyDBHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { + private val context: Context = context + data class Transaction( + val id: Int, + val title: String, + val category: String, + val amount: Int, + val location: String, + val tanggal: String // Add tanggal attribute + ) + + companion object { + private const val DATABASE_NAME = "transaction.db" + private const val DATABASE_VERSION = 1 + + private const val TABLE_NAME = "transactions" + private const val COLUMN_ID = "id" + private const val COLUMN_TITLE = "title" + private const val COLUMN_CATEGORY = "category" + private const val COLUMN_AMOUNT = "amount" + private const val COLUMN_LOCATION = "location" + private const val COLUMN_TANGGAL = "tanggal" // Define the column name for tanggal + } + + private val CREATE_TABLE = + "CREATE TABLE $TABLE_NAME ($COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT, " + + "$COLUMN_TITLE TEXT, $COLUMN_CATEGORY TEXT, $COLUMN_AMOUNT REAL, $COLUMN_LOCATION TEXT, $COLUMN_TANGGAL TEXT)" // Add COLUMN_TANGGAL to create table statement + + override fun onCreate(db: SQLiteDatabase) { + db.execSQL(CREATE_TABLE) + } + + override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + db.execSQL("DROP TABLE IF EXISTS $TABLE_NAME") + onCreate(db) + } + + fun insertTransaction(title: String, category: String, amount: Int, location: String): Long { + val db = this.writableDatabase + val tanggal = getCurrentDateTime() + val values = ContentValues().apply { + put(COLUMN_TITLE, title) + put(COLUMN_CATEGORY, category) + put(COLUMN_AMOUNT, amount) + put(COLUMN_LOCATION, location) + put(COLUMN_TANGGAL, tanggal) + } + return db.insert(TABLE_NAME, null, values) } - return db.insert(TABLE_NAME, null, values) - } - - fun getAllTransactions(): ArrayList<Transaction> { - val transactionList = ArrayList<Transaction>() - val selectQuery = "SELECT * FROM $TABLE_NAME" - val db = this.readableDatabase - val cursor = db.rawQuery(selectQuery, null) - cursor?.use { - while (cursor.moveToNext()) { - val id = cursor.getInt(cursor.getColumnIndex(COLUMN_ID)) - val title = cursor.getString(cursor.getColumnIndex(COLUMN_TITLE)) - val category = cursor.getString(cursor.getColumnIndex(COLUMN_CATEGORY)) - val amount = cursor.getInt(cursor.getColumnIndex(COLUMN_AMOUNT)) - val location = cursor.getString(cursor.getColumnIndex(COLUMN_LOCATION)) - val transaction = Transaction(id, title, category, amount, location) - transactionList.add(transaction) + + // Function to get current date and time in a specific format + private fun getCurrentDateTime(): String { + val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) + val date = Date() + return dateFormat.format(date) + } + private fun getUserLocation(locationManager: LocationManager): String { + // Check if the location permission is granted + if (ActivityCompat.checkSelfPermission( + context, + Manifest.permission.ACCESS_FINE_LOCATION + ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( + context, + Manifest.permission.ACCESS_COARSE_LOCATION + ) != PackageManager.PERMISSION_GRANTED + ) { + // Handle the case where location permission is not granted + return "Location permission not granted" + } + + // Location permission is granted, proceed with getting the location + val location: Location? = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) + return if (location != null) { + "${location.latitude}, ${location.longitude}" + } else { + "Location not available" } } - return transactionList - } - - fun updateTransaction(id: Int, title: String, category: String, amount: Int, location: String): Int { - val db = this.writableDatabase - val values = ContentValues().apply { - put(COLUMN_TITLE, title) - put(COLUMN_CATEGORY, category) - put(COLUMN_AMOUNT, amount) - put(COLUMN_LOCATION, location) + + + fun getAllTransactions(): ArrayList<Transaction> { + val transactionList = ArrayList<Transaction>() + val selectQuery = "SELECT * FROM $TABLE_NAME" + val db = this.readableDatabase + val cursor = db.rawQuery(selectQuery, null) + cursor?.use { + while (cursor.moveToNext()) { + val idIndex = cursor.getColumnIndex(COLUMN_ID) + val titleIndex = cursor.getColumnIndex(COLUMN_TITLE) + val categoryIndex = cursor.getColumnIndex(COLUMN_CATEGORY) + val amountIndex = cursor.getColumnIndex(COLUMN_AMOUNT) + val locationIndex = cursor.getColumnIndex(COLUMN_LOCATION) + val tanggalIndex = cursor.getColumnIndex(COLUMN_TANGGAL) + // Check if the column exists before accessing its index + if (idIndex != -1 && titleIndex != -1 && categoryIndex != -1 && amountIndex != -1 && locationIndex != -1) { + val id = cursor.getInt(idIndex) + val title = cursor.getString(titleIndex) + val category = cursor.getString(categoryIndex) + val amount = cursor.getInt(amountIndex) + val location = cursor.getString(locationIndex) + val tanggal = cursor.getString(tanggalIndex) + val transaction = Transaction(id, title, category, amount, location, tanggal) + transactionList.add(transaction) + } else { + + } + } + } + return transactionList + } + + fun updateTransaction(id: Int, title: String, category: String, amount: Int, location: String): Int { + val db = this.writableDatabase + val values = ContentValues().apply { + put(COLUMN_TITLE, title) + put(COLUMN_CATEGORY, category) + put(COLUMN_AMOUNT, amount) + put(COLUMN_LOCATION, location) + } + return db.update(TABLE_NAME, values, "$COLUMN_ID = ?", arrayOf(id.toString())) + } + + fun deleteTransaction(id: Int): Int { + val db = this.writableDatabase + return db.delete(TABLE_NAME, "$COLUMN_ID = ?", arrayOf(id.toString())) } - return db.update(TABLE_NAME, values, "$COLUMN_ID = ?", arrayOf(id.toString())) - } - - fun deleteTransaction(id: Int): Int { - val db = this.writableDatabase - return db.delete(TABLE_NAME, "$COLUMN_ID = ?", arrayOf(id.toString())) - } -} + } \ No newline at end of file