Projec R
Projec R
PROJECT REPORT
A
Project Report
on
Submitted By:
TEJPRATAP
MCA 4TH SEM
Roll. No: 036
This is to certify that the final year-project report entitled <EXPANSE MANAGER = submitted
By TEJPRATAP (Roll.No:36), to the IET Khandari ,Agra, Uttar Pradesh, is a bonafide record of
the project work carried out by them under my supervision during the year 2022-2023.
ACKNOWLEDGEMENT
I had taken efforts in this project. However, it would not have been possible without
the kind support and help of many individuals and organizations.
I extremely indebted to Dr. Rajkumar sir, professor of Computer Science and Engineering,
IET and Assitence prof. Hariram sir, Sumit pathak sir,Department of Computer Science
and EngineeringIET for their valuable suggestions and constant support throughout my
project tenure. I would also like to express our sincere thanks to all faculty and staff
members of the Department of Computer Science and Engineering, IET for their support
I also express gratitude towards our parents for their kind cooperation and
encouragement which helped me in completion of this project. My thanks and
appreciation also go to our friends in developing the project and all the people who
have willingly helped me out with their abilities.
lOMoAR cPSD| 29388234
ABSTRACT
This project is based on an expense and income tracking system. This project aims to
create an easy, faster and smooth tracking system between the expense and the income.
This project also offers some opportunities that will help the user to sustain all financial
activities like digital automated diary. So, for the better expense tracking system, we
developed our project that will help the users a lot. Most of the people cannot track
their expenses and income one way they face a money crisis, in this case daily expense
tracker can help the people to track income-expense day to day and making life tension
free. Money is the most valuable portion of our daily life and without money we will not
last one day on the earth. So using the daily expense tracker application is important to
load a happy family. Daily expense tracker helps the user to avoid unexpected expenses
and bad financial situations. This Project will save time and provide a responsible
lifestyle. This system is made and supervised by the experts and satisfying by the user.
XML, JAVA,data base, Android Studio are used to develop the system. The system is
tested by over 5 users, and 80% of them found the system useful.
lOMoAR cPSD| 29388234
CHAPTER 1: INTRODUCTION
A Daily Expense Tracker is a one kind of digital diary that helps to keep an eye on all
of our money related transitions and also provides all financial activities report daily,
weekly, monthly and yearly. Users get notification to record expenses and incomes that
are helpful to the tracking system of the application. All information is saved in offline
mode so users can easily access any time and any palaces. User interface of the Daily
Expense Tracker is very simple and attractive so it is easy to understand and the best
way to record our financial data.
1.1 MOTIVATION
The motivation to work in this project is actually our real-life experience. As a user We
face many difficulties in our daily file. In our daily life money is the most important
portion and without it we cannot last one day on earth but if we keep on track all financial
data then we can overcome this problem. Most of the people cannot track their expenses
and income one way they face the money crisis and depression. This situation motivates us
to make an android app to track all financial activities. Using the Daily Expense Tracker
user can be tracking expenses day to day and making life tension free.
The main objective of this project is support to the user to sustain all financial
activities like digital automated dairy. This application helps the user to avoid
unexpected expenses and bad financial situations.
➢ Using this application, users can manage all financial data and track all
expense and income category wise.
➢ Creating a category and recording all expenses and income under the category.
➢ Enable the notification system user get notification daily at a specific time
that can help the user insert expense and income.
➢ Backup and Restore all information.
➢ Report are generated in PDF format in category wise or time period.
lOMoAR cPSD| 29388234
*Literature Review- This chapter will contain data regarding introduction of our
app,theory behind the app making. It will also contain detailed analysis of how we
searched and collected ideas for the same. Then it will include the conclusion of a
arriving at the problem? And the problem statement and its depiction
- include the screenshots of our app to give you an overview of how it will look
*Project Relevance- It is the conclusion part, comparing the data analysis of our
LITERATURE REVIEW
INTRODUCTION
A writing audit is a study of insightful sources on a particular research.I found various
similar products that have already been developed in the market. Unlike all those
products, Personal Expense Tracker (PET) provides security and graphical results.I
provide the users to enter their wish-list before any purchase. It generates notifications
to notify users about their timely entry. In order to complete our task, we used the
Android platform to build a portable, handy product that can run on an Android phone.
We used Android studio to build our application. The major language we used for
scripting was Java and XML for producing better layout. I used SQLite to implement
the database.
2.CATEGORY MASTER
This module fundamentally relies upon the SQLite for putting away classification
details and expense subtleties and income. The class exchange is put away in a
SQLite database.
In this paper, After making this application we assure that this application will
help its users to manage the cost of their daily expenditure. It will guide them and
make them aware about their daily expenses. It will prove to be helpful for the
people who are frustrated with their daily budget management, irritated because
of the amount of expenses and wish to manage money and to preserve the record
of their daily cost which may be useful to change their way of spending money. In
short, this application will help its users to overcome the wastage of money.
lOMoAR cPSD| 29388234
PROBLEM FORMULATION
1. INTRODUCTION
Many organizations have their own system to record their income and expenses,
which they feel is the main key point of their business progress. It is a good habit for
a person to record daily expenses and earning but due to unawareness and lack of
proper applications to suit their privacy, lacking decision making capacity people are
using traditional note keeping methods to do so. Due to lack of a complete tracking
system, there is a constant overload to rely on the daily entry of the expenditure and
total estimation till the end of the month.
2.PROBLEMS FACED
After discussing my application functions and comparing them to other existing
applications, some features were found lacking. This is a new application that will
attract the public user through its features.
There are always some challenges. We have to face some challenges as well, since the
main purpose of our application is to track the user's expenses.
➢ This is an Android-based mobile application, so if a user does not have an
Android phone then this application will not help him.
➢ After getting notifications if a user doesn‟t check his phone for full information
then the main motto of this app will fail.
3.OBJECTIVES
Goal is to create an expense tracking system where user can be tracking all
❖ Users can easily review the reports daily, weekly, monthly or yearly.
❖ Users can update or delete records.
❖ Users can get notifications daily. Create Category and Change currency.
❖ Users can also change Notification time and modify some features.
❖ Add Expense and Income
lOMoAR cPSD| 29388234
4. CONCLUSIONS
After making this application i assure that this application will help its users to
manage the cost of their daily expenditure. It will guide them and make them aware
about their daily expenses. It will prove to be helpful for the people who are frustrated
with their daily budget management, irritated because of the amount of expenses and
wish to manage money and to preserve the record of their daily cost which may be
useful to change their way of spending money. In short, this application will help its
users to overcome the wastage of money.
lOMoAR cPSD| 29388234
METHODOLOGY
Css
Cascading Style Sheets (CSS) is a style sheet language used for describing the presentation of
a document written in a markup language like HTML.CSS is a cornerstone technology of the
World Wide Web, alongside HTML and JavaScript.CSS is designed to enable the separation
of presentation and content, including layout, colors, and fonts.This separation can improve
content accessibility, provide more flexibility and control in the specification of presentation
characteristics, enable multiple web pages to share formatting by specifying the relevant CSS
in a separate .css file, and reduce complexity and repetition in the structural content.
CSS information can be provided from various sources. These sources can be the web
browser, the user and the author. The information from the author can be further classified
into inline, media type, importance, selector specificity, rule order, inheritance and property
definition. CSS style information can be in a separate document or it can be embedded into
an HTML document. Multiple style sheets can be imported. Different styles can be applied
depending on the output device being used; for example, the screen version can be quite
different from the printed version, so that authors can tailor the presentation appropriately
for each medium.The style sheet with the highest priority controls the content display.
Declarations not set in the highest priority source are passed on to a source of lower priority,
such as the user agent style. The process is called cascading.
*JAVA
The core technologies of the World Wide Web.JavaScript enables interactive web
pages and is an essential part of web applications. The vast majority of websites use
it,and major web browsers have a dedicated JavaScript engine to execute it.As a
multi-paradigm language, JavaScript supports event-driven, functional, and
imperative (including object-oriented and prototype-based) programming styles. It
has APIs for working with text, arrays, dates, regular expressions, and the DOM, but
the language itself does not include any I/O, such as networking, storage, or graphics
facilities. It relies upon the host environment in which it is embedded to provide these
features.
Initially only implemented client-side in web browsers, JavaScript engines are now
embedded in many other types of host software, including server-side in web servers
and databases, and in non-web programs such as word processors and PDF software,
and in runtime environments that make JavaScript available for writing mobile and
desktop applications, including desktop widgets.
The terms Vanilla JavaScript and Vanilla JS refer to JavaScript not extended by any
frameworks or additional libraries. Scripts written in Vanilla JS are plain JavaScript
code.Google's Chrome extensions, Opera's extensions, Apple's Safari 5 extensions,
Apple's Dashboard Widgets, Microsoft's Gadgets, Yahoo! Widgets, Google Desktop
Gadgets, and Serene Klipfolio are implemented using JavaScript.
*SQLite
SQLite is a relational database management system (RDBMS) contained in a C
library. In contrast to many other database management systems, SQLite is not a
client–server database engine. Rather, it is embedded into the end program.
SQLite generally follows PostgreSQL syntax. SQLite uses a dynamically and weakly
typed SQL syntax that does not guarantee the domain integrity.This means that one
can, for example, insert a string into a column defined as an integer. SQLite will
attempt to convert data between formats where appropriate, the string "123" into
an integer in this case, but does not guarantee such conversions and will store the
data as-is if such a conversion is not possible.
SQLite is a popular choice as embedded database software for local/client storage in
application software such as web browsers. It is arguably the most widely deployed
database engine, as it is used today by several widespread browsers, operating
systems, and embedded systems (such as mobile phones), among others. SQLite has
bindings to many programming languages.
REALM DATABASE
There are several databases used in android for storing as well as retrieval of data such as
SQLite, Room DB, Realm Database and many more. Realm Database is also one of the
famous data storage services which uses SQLite to store the data within our android
application. In this article we will take a look at using Realm Database in Android.
All of these challenges present different obstacles. You can solve each in isolation with a
wide variety of libraries and frameworks. Deciding the right solution for each problem with
the right tradeoffs is a challenge mobile developers know all too well.
The combination of multiple environments creates even more challenges. For instance, you
can use a Java library on your Android client to serialize objects, but that library likely
wouldn't work on iOS. And this doesn't even take into account consistency across backend
services.
Realm
Many of these challenges arise due to particularities of the mobile environment. These
challenges include network reliability, local storage, and keeping UIs reactive
Local storage: Realm runs right on client devices. Access objects using the native
query language for each platform. Storing, accessing, and updating your data is simple
and lightweight.
Network reliability: Realm is offline-first. You always read from and write to the
local database, not over the network. When Device Sync is enabled, Realm
synchronizes data with App Services over the network in a background thread. The
sync protocol resolves conflicts consistently on each client and in the linked Atlas
cluster.
Reactive UI: Live objects always reflect the latest data stored in Realm. You can
subscribe to changes, letting you keep your UI consistently up to date.
The Realm SDKs connect to local realms for Android, iOS, Node.js, React Native, Flutter,
and UWP development.
The Realm SDKs use Atlas Device Sync to synchronize app data between clients and
MongoDB Atlas. Atlas Device Sync handles network access and conflict resolution in a
background thread of your application, so your application logic stays the same regardless of
network conditions.
Once your client data is in Atlas, you can leverage the full Atlas developer data platform.
Perform aggregations and other complex workloads with the full capabilities of MongoDB.
Or connect your Atlas instance to Charts to visualize your data in real time. Storing your data
in Atlas makes it easy to share data across users and platforms.
Query MongoDB Atlas directly from the Realm SDKs using built-in MongoDB
interfaces. You can also configure the Atlas Data API to query MongoDB using an
HTTP client in your app.
App Services Users and Authentication provide built-in user management. Integrate
with a JWT authentication service or directly with third-party authentication
providers, like Facebook, Google, and Apple.
Atlas Triggers automatically execute an Atlas Function at a scheduled time or when
an event occurs, such as a change to a MongoDB database in Atlas or a user logs in.
The Atlas GraphQL API accesses data stored in a linked MongoDB cluster with a
standard GraphQL client.
App Services Rules control who accesses what data.
App Services Values and Secrets define global variables and private credentials once
and use them across your entire App.
let's revise a few definitions related to databases.
*What is ANDROID?
Android is an open source and Linux-based Operating System for mobile devices such as
smartphones and tablet computers. Android was developed by the Open Handset Alliance, led
by Google, and other companies.
Android offers a unified approach to application development for mobile devices which
means developers need only develop for Android, and their applications should be able to run
on different devices powered by Android.
The first beta version of the Android Software Development Kit (SDK) was released by
Google in 2007 where as the first commercial version, Android 1.0, was released in
September 2008.
On June 27, 2012, at the Google I/O conference, Google announced the next Android version,
4.1 Jelly Bean. Jelly Bean is an incremental update, with the primary aim of improving the
user interface, both in terms of functionality and performance.
The source code for Android is available under free and open source software licenses.
Google publishes most of the code under the Apache License version 2.0 and the rest, Linux
kernel changes, under the GNU General Public License version 2.
Why Android ?
We can unserstand in these way too -
It all happens through your camera. With Android, when you point your lens at text, Google
Translate can automatically scan the words and convert them to the language you want. It
works in 25 languages so far, even if you're offline. Menus, street signs – if your camera can
take a picture of it, Android can translate it.
Security
Your phone stays safe with built-in security.
When you have Android, you have security that’s there right out of the box and never stops
working. Google Play Protect scans all your apps, the software gets regular security updates
and the platform is always improving. It’s like a security guard that never takes a break, a nap
or a holiday.
Wellbeing
The balance that’s right for you.
With Digital Wellbeing, you get the tools to understand how you use your phone and decide
what works for you. Whether that means unplugging, cutting down distractions or just
winding down before bed.
Features of Android
Android is a powerful operating system competing with Apple 4GS and supports great features.
Few of them are listed below −
Etc.
Android Studio is the official Integrated Development Environment (IDE) for Android app
development. Based on the powerful code editor and developer tools from IntelliJ IDEA ,
Android Studio offers even more features that enhance your productivity when building
Android apps, such as:
Project structure
Each project in Android Studio contains one or more modules with source code files and
resource files. The types of modules include:
By default, Android Studio displays your project files in the Android project view, as shown
in figure 1. This view is organized by modules to provide quick access to your project's key
source files. All the build files are visible at the top level, under Gradle Scripts.
The Android project structure on disk differs from this flattened representation. To see the
actual file structure of the project, select Project instead of Android from the Project menu.
Gradle build system
Android Studio uses Gradle as the foundation of the build system, with more Android-
specific capabilities provided by the Android Gradle plugin. This build system runs as an
integrated tool from the Android Studio menu and independently from the command line.
You can use the features of the build system to do the following:
By employing the flexibility of Gradle, you can achieve all of this without modifying your
app's core source files.
Android Studio build files are named build.gradle.kts if you use Kotlin (recommended)
or build.gradle if you use Groovy. They are plain text files that use the Kotlin or Groovy
syntax to configure the build with elements provided by the Android Gradle plugin. Each
project has one top-level build file for the entire project and separate module-level build files
for each module. When you import an existing project, Android Studio automatically
generates the necessary build files.
Build variants
The build system can help you create different versions of the same app from a single project.
This is useful when you have both a free version and a paid version of your app or if you
want to distribute multiple APKs for different device configurations on Google Play..
Multiple APK support lets you efficiently create multiple APKs based on screen density or
ABI. For example, you can create separate APKs of an app for the hdpi and mdpi screen
densities, while still considering them a single variant and letting them share test APK,
javac, dx, and ProGuard settings.
Manage dependencies
Dependencies for your project are specified by name in the module-level build script. Gradle
finds dependencies and makes them available in your build. You can declare module
dependencies, remote binary dependencies, and local binary dependencies in your
build.gradle.kts file.
Android Studio configures projects to use the Maven Central Repository by default. This
configuration is included in the top-level build file for the project.
For more information about configuring dependencies, read Add build dependencies.
Inline debugging
Use inline debugging to enhance your code walkthroughs in the debugger view with inline
verification of references, expressions, and variable values.
To enable inline debugging, in the Debug window, click Settings and select Show Variable
Values in Editor.
Performance profilers
Android Studio provides performance profilers so you can easily track your app's memory
and CPU usage, find deallocated objects, locate memory leaks, optimize graphics
performance, and analyze network requests.
To use performance profilers, with your app running on a device or emulator, open the
Android Profiler by selecting View > Tool Windows > Profiler.
Data file access
The Android SDK tools, such as Systrace and Logcat, generate performance and debugging
data for detailed app analysis.
Android Studio supports annotations for variables, parameters, and return values to help you
catch bugs, such as null pointer exceptions and resource type conflicts.
The Android SDK Manager packages the Jetpack Annotations library in the Android Support
Repository for use with Android Studio. Android Studio validates the configured annotations
during code inspection.
When you build and run your app with Android Studio, you can view adb output and device
log messages in the Logcat window
From the Android Studio Welcome screen, select More Actions > Virtual Device
Manager
After opening a project, select View > Tool Windows > Device Manager from the main menu bar,
and then click Create device.
lOMoAR cPSD| 29388234
AndroidMainfest.XML
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.EManager"
tools:targetApi="31">
<activity
android:name=".views.activites.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<meta-data
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts" />
</application>
</manifest>
*MainActivity.JAVA
package com.example.emanager.views.activites;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;
import com.example.emanager.adapters.TransactionsAdapter;
import com.example.emanager.models.Transaction;
import com.example.emanager.utils.Constants;
import com.example.emanager.utils.Helper;
import com.example.emanager.viewmodels.MainViewModel;
import com.example.emanager.views.fragments.AddTransactionFragment;
import com.example.emanager.R;
import com.example.emanager.databinding.ActivityMainBinding;
import com.google.android.material.tabs.TabLayout;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import io.realm.Realm;
import io.realm.RealmResults;
ActivityMainBinding binding;
Calendar calendar;
/*
0 = Daily
1 = Monthly
2 = Calendar
3 = Summary
4 = Notes
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolBar);
getSupportActionBar().setTitle("Transactions");
Constants.setCategories();
calendar = Calendar.getInstance();
updateDate();
binding.nextDateBtn.setOnClickListener(c-> {
if(Constants.SELECTED_TAB == Constants.DAILY) {
calendar.add(Calendar.DATE, 1);
} else if(Constants.SELECTED_TAB == Constants.MONTHLY) {
calendar.add(Calendar.MONTH, 1);
}
updateDate();
});
binding.previousDateBtn.setOnClickListener(c-> {
if(Constants.SELECTED_TAB == Constants.DAILY) {
calendar.add(Calendar.DATE, -1);
} else if(Constants.SELECTED_TAB == Constants.MONTHLY) {
calendar.add(Calendar.MONTH, -1);
}
updateDate();
});
binding.floatingActionButton.setOnClickListener(c -> {
new AddTransactionFragment().show(getSupportFragmentManager(),
null);
});
ArrayList<Transaction> transactions = new ArrayList<>();
transactions.add(new Transaction("Income","Bussiness","cash","some
note here",new Date(),500,2));
transactions.add(new
Transaction("Expense","Investment","Bank","some note here",new
Date(),900,4));
transactions.add(new Transaction("Income","Rent","cash","some note
here",new Date(),500,2));
transactions.add(new Transaction("Inccom","Bussiness","cash","some
note here",new Date(),500,2));
TransactionsAdapter transactionsAdapter = new
TransactionsAdapter(this, transactions);
binding.transactionsList.setLayoutManager(new
LinearLayoutManager(this));
binding.transactionsList.setAdapter(transactionsAdapter);
binding.tabLayout.addOnTabSelectedListener(new
TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
if(tab.getText().equals("Monthly")) {
Constants.SELECTED_TAB = 1;
updateDate();
} else if(tab.getText().equals("Daily")) {
Constants.SELECTED_TAB = 0;
updateDate();
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
binding.transactionsList.setLayoutManager(new
LinearLayoutManager(this));
viewModel.transactions.observe(this, new
Observer<RealmResults<Transaction>>() {
@Override
public void onChanged(RealmResults<Transaction> transactions) {
TransactionsAdapter transactionsAdapter = new
TransactionsAdapter(MainActivity.this, transactions);
binding.transactionsList.setAdapter(transactionsAdapter);
if(transactions.size() > 0) {
binding.emptyState.setVisibility(View.GONE);
} else {
binding.emptyState.setVisibility(View.VISIBLE);
}
}
});
binding.currentDate.setText(Helper.formatDate(calendar.getTime()));
} else if(Constants.SELECTED_TAB == Constants.MONTHLY) {
binding.currentDate.setText(Helper.formatDateByMonth(calendar.getTime()));
}
viewModel.getTransactions(calendar);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.top_menu,menu);
return super.onCreateOptionsMenu(menu);
}
}
*AccountAdapters.JAVA
package com.example.emanager.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.emanager.R;
import com.example.emanager.databinding.RowAccountBinding;
import com.example.emanager.models.Account;
import java.util.ArrayList;
Context context;
ArrayList<Account> accountArrayList;
AccountsClickListener accountsClickListener;
@NonNull
@Override
public AccountsViewHolder onCreateViewHolder(@NonNull ViewGroup parent,
int viewType) {
return new
AccountsViewHolder(LayoutInflater.from(context).inflate(R.layout.row_accoun
t, parent, false));
}
@Override
public void onBindViewHolder(@NonNull AccountsViewHolder holder, int
position) {
Account account = accountArrayList.get(position);
holder.binding.accountName.setText(account.getAccountName());
holder.itemView.setOnClickListener(c-> {
accountsClickListener.onAccountSelected(account);
});
}
@Override
public int getItemCount() {
return accountArrayList.size();
}
RowAccountBinding binding;
*CategoryAdapter.JAVA
package com.example.emanager.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.emanager.R;
import com.example.emanager.databinding.SampleCategoryItemBinding;
import com.example.emanager.models.Category;
import java.util.ArrayList;
Context context;
ArrayList<Category> categories;
CategoryClickListener categoryClickListener;
@NonNull
@Override
public CategoryViewHolder onCreateViewHolder(@NonNull ViewGroup parent,
int viewType) {
return new
CategoryViewHolder(LayoutInflater.from(context).inflate(R.layout.sample_cat
egory_item, parent,false));
}
@Override
public void onBindViewHolder(@NonNull CategoryViewHolder holder, int
position) {
Category category = categories.get(position);
holder.binding.categoryText.setText(category.getCategoryName());
holder.binding.categoryIcon.setImageResource(category.getCategoryImage());
holder.binding.categoryIcon.setBackgroundTintList(context.getColorStateList
(category.getCategoryColor()));
holder.itemView.setOnClickListener(c-> {
categoryClickListener.onCategoryClicked(category);
});
}
@Override
public int getItemCount() {
return categories.size();
}
SampleCategoryItemBinding binding;
TransactionAdapter.JAVA
package com.example.emanager.adapters;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.emanager.R;
import com.example.emanager.databinding.RowTransactionBinding;
import com.example.emanager.models.Category;
import com.example.emanager.models.Transaction;
import com.example.emanager.utils.Constants;
import com.example.emanager.utils.Helper;
import com.example.emanager.views.activites.MainActivity;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import io.realm.RealmResults;
Context context;
RealmResults<Transaction> transactions;
@NonNull
@Override
public TransactionViewHolder onCreateViewHolder(@NonNull ViewGroup
parent, int viewType) {
return new
TransactionViewHolder(LayoutInflater.from(context).inflate(R.layout.row_tra
nsaction, parent, false));
}
@Override
public void onBindViewHolder(@NonNull TransactionViewHolder holder, int
position) {
Transaction transaction = transactions.get(position);
holder.binding.transactionAmount.setText(String.valueOf(transaction.getAmou
nt()));
holder.binding.accountLbl.setText(transaction.getAccount());
holder.binding.transactionDate.setText(Helper.formatDate(transaction.getDat
e()));
holder.binding.transactionCategory.setText(transaction.getCategory());
Category transactionCategory =
Constants.getCategoryDetails(transaction.getCategory());
holder.binding.categoryIcon.setImageResource(transactionCategory.getCategor
yImage());
holder.binding.categoryIcon.setBackgroundTintList(context.getColorStateList
(transactionCategory.getCategoryColor()));
holder.binding.accountLbl.setBackgroundTintList(context.getColorStateList(C
onstants.getAccountsColor(transaction.getAccount())));
if(transaction.getType().equals(Constants.INCOME)) {
holder.binding.transactionAmount.setTextColor(context.getColor(R.color.gree
nColor));
} else if(transaction.getType().equals(Constants.EXPENSE)) {
holder.binding.transactionAmount.setTextColor(context.getColor(R.color.redC
olor));
}
holder.itemView.setOnLongClickListener(new
View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
AlertDialog deleteDialog = new
AlertDialog.Builder(context).create();
deleteDialog.setTitle("Delete Transaction");
deleteDialog.setMessage("Are you sure to delete this
transaction?");
deleteDialog.setButton(DialogInterface.BUTTON_POSITIVE,
"Yes", (dialogInterface, i) -> {
((MainActivity)context).viewModel.deleteTransaction(transaction);
});
deleteDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "No",
(dialogInterface, i) -> {
deleteDialog.dismiss();
});
deleteDialog.show();
return false;
}
});
@Override
public int getItemCount() {
return transactions.size();
}
RowTransactionBinding binding;
import android.annotation.TargetApi;
….
@SuppressWarnings("all")
public class com_example_emanager_models_TransactionRealmProxy extends
com.example.emanager.models.Transaction
implements RealmObjectProxy,
com_example_emanager_models_TransactionRealmProxyInterface {
TransactionColumnInfo(OsSchemaInfo schemaInfo) {
super(7);
OsObjectSchemaInfo objectSchemaInfo =
schemaInfo.getObjectSchemaInfo("Transaction");
this.typeColKey = addColumnDetails("type", "type",
objectSchemaInfo);
this.categoryColKey = addColumnDetails("category", "category",
objectSchemaInfo);
this.accountColKey = addColumnDetails("account", "account",
objectSchemaInfo);
this.noteColKey = addColumnDetails("note", "note",
objectSchemaInfo);
this.dateColKey = addColumnDetails("date", "date",
objectSchemaInfo);
this.amountColKey = addColumnDetails("amount", "amount",
objectSchemaInfo);
this.idColKey = addColumnDetails("id", "id", objectSchemaInfo);
}
@Override
protected final ColumnInfo copy(boolean mutable) {
return new TransactionColumnInfo(this, mutable);
}
@Override
protected final void copy(ColumnInfo rawSrc, ColumnInfo rawDst) {
final TransactionColumnInfo src = (TransactionColumnInfo)
rawSrc;
final TransactionColumnInfo dst = (TransactionColumnInfo)
rawDst;
dst.typeColKey = src.typeColKey;
dst.categoryColKey = src.categoryColKey;
dst.accountColKey = src.accountColKey;
dst.noteColKey = src.noteColKey;
dst.dateColKey = src.dateColKey;
dst.amountColKey = src.amountColKey;
dst.idColKey = src.idColKey;
}
}
com_example_emanager_models_TransactionRealmProxy() {
proxyState.setConstructionFinished();
}
@Override
public void realm$injectObjectContext() {
if (this.proxyState != null) {
return;
}
final BaseRealm.RealmObjectContext context =
BaseRealm.objectContext.get();
this.columnInfo = (TransactionColumnInfo) context.getColumnInfo();
this.proxyState = new
ProxyState<com.example.emanager.models.Transaction>(this);
proxyState.setRealm$realm(context.getRealm());
proxyState.setRow$realm(context.getRow());
proxyState.setAcceptDefaultValue$realm(context.getAcceptDefaultValue());
proxyState.setExcludeFields$realm(context.getExcludeFields());
}
@Override
@SuppressWarnings("cast")
public String realmGet$type() {
proxyState.getRealm$realm().checkIfValid();
return (java.lang.String)
proxyState.getRow$realm().getString(columnInfo.typeColKey);
}
@Override
public void realmSet$type(String value) {
if (proxyState.isUnderConstruction()) {
if (!proxyState.getAcceptDefaultValue$realm()) {
return;
}
final Row row = proxyState.getRow$realm();
if (value == null) {
proxyState.getRealm$realm().checkIfValid();
if (value == null) {
proxyState.getRow$realm().setNull(columnInfo.typeColKey);
return;
}
proxyState.getRow$realm().setString(columnInfo.typeColKey, value);
}
@Override
@SuppressWarnings("cast")
public String realmGet$category() {
proxyState.getRealm$realm().checkIfValid();
return (java.lang.String)
proxyState.getRow$realm().getString(columnInfo.categoryColKey);
}
@Override
public void realmSet$category(String value) {
if (proxyState.isUnderConstruction()) {
if (!proxyState.getAcceptDefaultValue$realm()) {
return;
}
final Row row = proxyState.getRow$realm();
if (value == null) {
row.getTable().setNull(columnInfo.categoryColKey,
row.getObjectKey(), true);
return;
}
row.getTable().setString(columnInfo.categoryColKey,
row.getObjectKey(), value, true);
return;
}
proxyState.getRealm$realm().checkIfValid();
if (value == null) {
proxyState.getRow$realm().setNull(columnInfo.categoryColKey);
return;
}
proxyState.getRow$realm().setString(columnInfo.categoryColKey,
value);
}
@Override
@SuppressWarnings("cast")
public String realmGet$account() {
proxyState.getRealm$realm().checkIfValid();
return (java.lang.String)
proxyState.getRow$realm().getString(columnInfo.accountColKey);
}
@Override
public void realmSet$account(String value) {
if (proxyState.isUnderConstruction()) {
if (!proxyState.getAcceptDefaultValue$realm()) {
return;
}
final Row row = proxyState.getRow$realm();
if (value == null) {
row.getTable().setNull(columnInfo.accountColKey,
row.getObjectKey(), true);
return;
}
row.getTable().setString(columnInfo.accountColKey, row.getObjectKey(),
value, true);
return;
}
proxyState.getRealm$realm().checkIfValid();
if (value == null) {
proxyState.getRow$realm().setNull(columnInfo.accountColKey);
return;
}
proxyState.getRow$realm().setString(columnInfo.accountColKey,
value);
}
@Override
@SuppressWarnings("cast")
public String realmGet$note() {
proxyState.getRealm$realm().checkIfValid();
return (java.lang.String)
proxyState.getRow$realm().getString(columnInfo.noteColKey);
}
@Override
public void realmSet$note(String value) {
if (proxyState.isUnderConstruction()) {
if (!proxyState.getAcceptDefaultValue$realm()) {
return;
}
final Row row = proxyState.getRow$realm();
if (value == null) {
row.getTable().setNull(columnInfo.noteColKey,
row.getObjectKey(), true);
return;
}
row.getTable().setString(columnInfo.noteColKey,
row.getObjectKey(), value, true);
return;
}
proxyState.getRealm$realm().checkIfValid();
if (value == null) {
proxyState.getRow$realm().setNull(columnInfo.noteColKey);
return;
}
proxyState.getRow$realm().setString(columnInfo.noteColKey, value);
}
@Override
@SuppressWarnings("cast")
public Date realmGet$date() {
proxyState.getRealm$realm().checkIfValid();
if (proxyState.getRow$realm().isNull(columnInfo.dateColKey)) {
return null;
}
return (java.util.Date)
proxyState.getRow$realm().getDate(columnInfo.dateColKey);
}
@Override
plugins {
id 'com.android.application'
}
apply plugin: "realm-android"
android {
namespace 'com.example.emanager'
compileSdk 33
buildFeatures {
viewBinding true
}
defaultConfig {
applicationId "com.example.emanager"
minSdk 24
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-
optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
BULID GRADLE (PROJECT E MANAGER)
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:10.15.1"
}
}
plugins {
id 'com.android.application' version '8.0.1' apply false
id 'com.android.library' version '8.0.1' apply false
}