Personal Finance App Java, Android
👤 Sharing: AI
```java
// MainActivity.java (Android)
package com.example.personalfinanceapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private EditText editTextIncome, editTextExpenseName, editTextExpenseAmount;
private Button buttonAddExpense, buttonCalculateSummary;
private TextView textViewSummary;
private List<Expense> expenses = new ArrayList<>();
private double income = 0.0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize UI elements
editTextIncome = findViewById(R.id.editTextIncome);
editTextExpenseName = findViewById(R.id.editTextExpenseName);
editTextExpenseAmount = findViewById(R.id.editTextExpenseAmount);
buttonAddExpense = findViewById(R.id.buttonAddExpense);
buttonCalculateSummary = findViewById(R.id.buttonCalculateSummary);
textViewSummary = findViewById(R.id.textViewSummary);
// Set up listeners
buttonAddExpense.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addExpense();
}
});
buttonCalculateSummary.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
calculateSummary();
}
});
}
private void addExpense() {
String expenseName = editTextExpenseName.getText().toString().trim();
String expenseAmountStr = editTextExpenseAmount.getText().toString().trim();
// Validate input
if (expenseName.isEmpty() || expenseAmountStr.isEmpty()) {
Toast.makeText(this, "Please enter expense name and amount.", Toast.LENGTH_SHORT).show();
return;
}
try {
double expenseAmount = Double.parseDouble(expenseAmountStr);
if (expenseAmount <= 0) {
Toast.makeText(this, "Expense amount must be positive.", Toast.LENGTH_SHORT).show();
return;
}
// Create Expense object and add it to the list
Expense expense = new Expense(expenseName, expenseAmount);
expenses.add(expense);
// Clear input fields
editTextExpenseName.setText("");
editTextExpenseAmount.setText("");
Toast.makeText(this, "Expense added.", Toast.LENGTH_SHORT).show();
} catch (NumberFormatException e) {
Toast.makeText(this, "Invalid expense amount.", Toast.LENGTH_SHORT).show();
}
}
private void calculateSummary() {
String incomeStr = editTextIncome.getText().toString().trim();
if (incomeStr.isEmpty()) {
Toast.makeText(this, "Please enter your income.", Toast.LENGTH_SHORT).show();
return;
}
try {
income = Double.parseDouble(incomeStr);
if (income <= 0) {
Toast.makeText(this, "Income must be positive.", Toast.LENGTH_SHORT).show();
return;
}
double totalExpenses = 0.0;
for (Expense expense : expenses) {
totalExpenses += expense.getAmount();
}
double remainingBalance = income - totalExpenses;
String summary = "Income: $" + String.format("%.2f", income) + "\n" +
"Total Expenses: $" + String.format("%.2f", totalExpenses) + "\n" +
"Remaining Balance: $" + String.format("%.2f", remainingBalance);
textViewSummary.setText(summary);
} catch (NumberFormatException e) {
Toast.makeText(this, "Invalid income amount.", Toast.LENGTH_SHORT).show();
}
}
// Inner class to represent an expense
private static class Expense {
private String name;
private double amount;
public Expense(String name, double amount) {
this.name = name;
this.amount = amount;
}
public String getName() {
return name;
}
public double getAmount() {
return amount;
}
}
}
```
```xml
<!-- activity_main.xml (layout) -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Personal Finance App"
android:textSize="24sp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="16dp"/>
<EditText
android:id="@+id/editTextIncome"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter your Income"
android:inputType="numberDecimal"
android:layout_marginBottom="8dp"/>
<EditText
android:id="@+id/editTextExpenseName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Expense Name"
android:layout_marginBottom="8dp"/>
<EditText
android:id="@+id/editTextExpenseAmount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Expense Amount"
android:inputType="numberDecimal"
android:layout_marginBottom="16dp"/>
<Button
android:id="@+id/buttonAddExpense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Expense"
android:layout_marginBottom="16dp"/>
<Button
android:id="@+id/buttonCalculateSummary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Calculate Summary"/>
<TextView
android:id="@+id/textViewSummary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textSize="18sp"
android:text="Summary will be displayed here"/>
</LinearLayout>
```
**Explanation:**
1. **Project Setup:**
* Create a new Android project in Android Studio. Choose an Empty Activity template.
* Make sure your `build.gradle` file (Module level) has `minSdkVersion` of at least 24 or higher. This is important for newer Java language features used in Android development.
2. **UI Layout (activity\_main.xml):**
* A `LinearLayout` with vertical orientation is used as the root layout.
* `TextView`: Displays the title "Personal Finance App".
* `EditText` (editTextIncome): Allows the user to enter their income. `inputType="numberDecimal"` ensures that only numeric input with a decimal point is accepted.
* `EditText` (editTextExpenseName): Allows the user to enter the name of an expense.
* `EditText` (editTextExpenseAmount): Allows the user to enter the amount of an expense. `inputType="numberDecimal"` ensures only numeric input with a decimal point is accepted.
* `Button` (buttonAddExpense): Triggers the `addExpense()` method when clicked.
* `Button` (buttonCalculateSummary): Triggers the `calculateSummary()` method when clicked.
* `TextView` (textViewSummary): Displays the calculated summary of income, expenses, and remaining balance.
3. **Java Code (MainActivity.java):**
* **`MainActivity` Class:** The main activity class that handles user interaction and calculations.
* **`onCreate()` Method:**
* `setContentView(R.layout.activity_main);`: Loads the UI layout defined in `activity_main.xml`.
* `findViewById()`: Finds and initializes all the UI elements defined in the layout file using their IDs. It is critical to do this to interact with the UI elements from your Java code.
* `buttonAddExpense.setOnClickListener()`: Sets an `OnClickListener` for the "Add Expense" button. When the button is clicked, the `onClick` method of the `OnClickListener` is executed. In this case, it calls the `addExpense()` method.
* `buttonCalculateSummary.setOnClickListener()`: Sets an `OnClickListener` for the "Calculate Summary" button. When the button is clicked, the `onClick` method of the `OnClickListener` is executed, and it calls the `calculateSummary()` method.
* **`addExpense()` Method:**
* Gets the expense name and amount from the corresponding `EditText` fields.
* **Input Validation:** Checks if the expense name or amount fields are empty. If so, it displays a `Toast` message to the user.
* **Error Handling (try-catch):** Uses a `try-catch` block to handle potential `NumberFormatException` if the user enters an invalid expense amount (e.g., text instead of a number).
* `Double.parseDouble()`: Converts the expense amount string to a `double`.
* **Expense Object:** Creates a new `Expense` object using the expense name and amount.
* `expenses.add()`: Adds the `Expense` object to the `expenses` list (an `ArrayList` of `Expense` objects).
* Clears the expense name and amount `EditText` fields after adding the expense.
* Displays a `Toast` message to confirm that the expense has been added.
* **`calculateSummary()` Method:**
* Gets the income from the `editTextIncome` field.
* **Input Validation:** Checks if the income field is empty. If so, it displays a `Toast` message.
* **Error Handling (try-catch):** Uses a `try-catch` block to handle potential `NumberFormatException` if the user enters an invalid income amount.
* `Double.parseDouble()`: Converts the income string to a `double`.
* Calculates the total expenses by iterating through the `expenses` list and summing the `amount` of each expense.
* Calculates the remaining balance by subtracting the total expenses from the income.
* Formats the income, total expenses, and remaining balance to two decimal places using `String.format("%.2f", ...)`.
* Creates a formatted summary string with the income, total expenses, and remaining balance.
* Sets the text of the `textViewSummary` to display the summary string.
* **`Expense` Inner Class:**
* A simple class to represent an expense. It has two private fields: `name` (String) and `amount` (double).
* A constructor to initialize the `name` and `amount` fields.
* Getter methods (`getName()`, `getAmount()`) to access the `name` and `amount` fields. This is important because the fields are private, and we need to access them from the `MainActivity` class.
**How to Run the App:**
1. Open the project in Android Studio.
2. Connect an Android device to your computer or use an emulator.
3. Click the "Run" button in Android Studio.
4. Select your device or emulator.
5. The app will be installed and launched on your device/emulator.
**Key Improvements and Considerations:**
* **Data Persistence:** The current implementation stores expenses only in memory. When the app is closed, the data is lost. To persist data, you can use:
* **SharedPreferences:** For simple key-value pairs (e.g., storing a single income value).
* **Internal/External Storage:** For storing data in files.
* **SQLite Database:** For more structured data storage. This is the preferred approach for most apps.
* **Cloud Databases (Firebase, etc.):** For syncing data across multiple devices.
* **UI Enhancements:**
* Use a `RecyclerView` to display the list of expenses. This is more efficient than adding views dynamically.
* Implement input validation more robustly (e.g., using regular expressions).
* Add more visual elements like charts and graphs to display financial data.
* Use themes and styles to improve the app's appearance.
* **Features:**
* Add categories for expenses (e.g., food, transportation, entertainment).
* Implement recurring expenses (e.g., rent, subscriptions).
* Set budgets and track spending against them.
* Generate reports and visualizations of financial data.
* Integrate with bank accounts or financial services APIs.
* **Error Handling:** Add more comprehensive error handling to catch potential exceptions and provide informative messages to the user.
* **Code Structure:** For larger apps, consider using architectural patterns like Model-View-ViewModel (MVVM) to improve code organization and testability.
* **Security:** If you are handling sensitive financial data, ensure that you implement appropriate security measures to protect user information. Never store passwords or API keys directly in the code.
This improved version provides a more complete and robust foundation for building a personal finance app in Android. Remember to focus on data persistence and UI enhancements to make the app more user-friendly and practical.
👁️ Viewed: 8
Comments