You’re not disturbing anything—this is exactly how a good project gets finished: one clear,
complete version. Let’s put everything together into a **single clean build** with:
✔ Categories (add + delete)
✔ Multiple receipts per category
✔ Camera + OCR
✔ Search bar (searches OCR text)
✔ Text preview under each image
✔ Delete + Recently Deleted (restore option)
✔ Simple classic UI
---
# 🧩 1. PROJECT STRUCTURE
```id="v1v8u1"
java/com/yourpackage/
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
adapter/
[Link]
[Link]
[Link]
res/layout/
activity_main.xml
activity_add_category.xml
activity_receipt_list.xml
activity_camera.xml
activity_deleted.xml
item_category.xml
item_receipt.xml
item_deleted.xml
```
---
# 🧱 2. MAIN SCREEN (Categories + Recently Deleted)
📍 `res/layout/activity_main.xml`
```xml id="p5q4sx"
<LinearLayout xmlns:android="[Link]
android:orientation="vertical"
android:padding="12dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/addCategoryBtn"
android:text="Add Category"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/deletedBtn"
android:text="Recently Deleted"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<[Link]
android:id="@+id/categoryRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
```
---
📍 `[Link]`
```java id="ozh9cf"
public class MainActivity extends AppCompatActivity {
RecyclerView recycler;
DatabaseHelper db;
@Override
protected void onCreate(Bundle b) {
[Link](b);
setContentView([Link].activity_main);
recycler = findViewById([Link]);
Button add = findViewById([Link]);
Button deleted = findViewById([Link]);
db = new DatabaseHelper(this);
load();
[Link](v ->
startActivity(new Intent(this, [Link])));
[Link](v ->
startActivity(new Intent(this, [Link])));
}
@Override
protected void onResume() {
[Link]();
load();
}
void load() {
[Link](new LinearLayoutManager(this));
[Link](new CategoryAdapter([Link](), this));
}
}
```
---
# ➕ 3. ADD CATEGORY
📍 `activity_add_category.xml`
```xml id="2ux7vv"
<LinearLayout xmlns:android="[Link]
android:padding="16dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/name"
android:hint="Category name"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/save"
android:text="Save"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
```
---
📍 `[Link]`
```java id="ojrdbm"
public class AddCategoryActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle b) {
[Link](b);
setContentView([Link].activity_add_category);
EditText name = findViewById([Link]);
Button save = findViewById([Link]);
[Link](v -> {
new DatabaseHelper(this).addCategory([Link]().toString());
finish();
});
}
}
```
---
# 📂 4. CATEGORY ITEM
📍 `item_category.xml`
```xml id="1q0dhu"
<LinearLayout xmlns:android="[Link]
android:padding="10dp"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/name"
android:textSize="18sp"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/delete"
android:text="Delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
```
---
📍 `[Link]`
```java id="p1z5kv"
public class CategoryAdapter extends [Link]<[Link]> {
List<String> list;
Context ctx;
public CategoryAdapter(List<String> l, Context c) {
list = l;
ctx = c;
}
class Holder extends [Link] {
TextView name;
Button delete;
public Holder(View v) {
super(v);
name = [Link]([Link]);
delete = [Link]([Link]);
}
}
@Override
public Holder onCreateViewHolder(ViewGroup p, int v) {
return new Holder([Link](ctx).inflate([Link].item_category, p, false));
}
@Override
public void onBindViewHolder(Holder h, int i) {
String cat = [Link](i);
[Link](cat);
[Link](v -> {
Intent intent = new Intent(ctx, [Link]);
[Link]("category", cat);
[Link](intent);
});
[Link](v -> {
new DatabaseHelper(ctx).deleteCategory(cat);
[Link](i);
notifyDataSetChanged();
});
}
@Override
public int getItemCount() { return [Link](); }
}
```
---
# 📸 5. RECEIPT SCREEN (SEARCH + ADD)
📍 `activity_receipt_list.xml`
```xml id="z3r4nq"
<LinearLayout xmlns:android="[Link]
android:orientation="vertical"
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/search"
android:hint="Search receipts..."
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/add"
android:text="Add Receipt"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<[Link]
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
```
---
📍 `[Link]`
```java id="u1g2nf"
public class ReceiptListActivity extends AppCompatActivity {
DatabaseHelper db;
String category;
RecyclerView recycler;
ReceiptAdapter adapter;
@Override
protected void onCreate(Bundle b) {
[Link](b);
setContentView([Link].activity_receipt_list);
db = new DatabaseHelper(this);
category = getIntent().getStringExtra("category");
recycler = findViewById([Link]);
EditText search = findViewById([Link]);
Button add = findViewById([Link]);
[Link](new LinearLayoutManager(this));
load("");
[Link](new TextWatcher() {
public void onTextChanged(CharSequence s, int a, int b, int c) {
load([Link]());
}
public void beforeTextChanged(CharSequence s, int a, int b, int c) {}
public void afterTextChanged(Editable s) {}
});
[Link](v -> {
Intent i = new Intent(this, [Link]);
[Link]("category", category);
startActivity(i);
});
}
@Override
protected void onResume() {
[Link]();
load("");
}
void load(String q) {
List<Receipt> list = [Link](category, q);
adapter = new ReceiptAdapter(list, this);
[Link](adapter);
}
}
```
---
# 🧾 6. RECEIPT ITEM (IMAGE + TEXT + DELETE)
📍 `item_receipt.xml`
```xml id="9cbn1s"
<LinearLayout xmlns:android="[Link]
android:padding="10dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="150dp"/>
<TextView
android:id="@+id/text"
android:maxLines="2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/delete"
android:text="Delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
```
---
📍 `[Link]`
```java id="2xevm9"
public class ReceiptAdapter extends [Link]<[Link]> {
List<Receipt> list;
Context ctx;
public ReceiptAdapter(List<Receipt> l, Context c) {
list = l;
ctx = c;
}
class Holder extends [Link] {
ImageView img;
TextView text;
Button delete;
public Holder(View v) {
super(v);
img = [Link]([Link]);
text = [Link]([Link]);
delete = [Link]([Link]);
}
}
@Override
public Holder onCreateViewHolder(ViewGroup p, int v) {
return new Holder([Link](ctx).inflate([Link].item_receipt, p, false));
}
@Override
public void onBindViewHolder(Holder h, int i) {
Receipt r = [Link](i);
[Link]([Link]([Link]));
[Link]([Link]);
[Link](v -> {
new DatabaseHelper(ctx).moveToDeleted(r);
[Link](i);
notifyDataSetChanged();
});
}
@Override
public int getItemCount() { return [Link](); }
}
```
---
# 7. RECENTLY DELETED (RESTORE)
📍 `activity_deleted.xml`
```xml id="y7e7qz"
<[Link]
xmlns:android="[Link]
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
```
---
📍 `[Link]`
```java id="rmnptk"
public class RecentlyDeletedActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle b) {
[Link](b);
setContentView([Link].activity_deleted);
RecyclerView r = findViewById([Link]);
[Link](new LinearLayoutManager(this));
[Link](new DeletedAdapter(
new DatabaseHelper(this).getDeleted(), this));
}
}
```
---
📍 `[Link]`
```java id="v3w5yl"
public class DeletedAdapter extends [Link]<[Link]> {
List<Receipt> list;
Context ctx;
public DeletedAdapter(List<Receipt> l, Context c) {
list = l;
ctx = c;
}
class Holder extends [Link] {
TextView text;
Button restore;
public Holder(View v) {
super(v);
text = [Link]([Link].text1);
restore = [Link]([Link].button1);
}
}
@Override
public Holder onCreateViewHolder(ViewGroup p, int v) {
LinearLayout l = new LinearLayout(ctx);
[Link]([Link]);
TextView t = new TextView(ctx);
[Link]([Link].text1);
Button b = new Button(ctx);
[Link]([Link].button1);
[Link]("Restore");
[Link](t);
[Link](b);
return new Holder(l);
}
@Override
public void onBindViewHolder(Holder h, int i) {
Receipt r = [Link](i);
[Link]([Link]);
[Link](v -> {
new DatabaseHelper(ctx).restore(r);
[Link](i);
notifyDataSetChanged();
});
}
@Override public int getItemCount() { return [Link](); }
}
```
---
# 📷 8. CAMERA + OCR
📍 `[Link]`
```java id="w4yj6h"
public class CameraActivity extends AppCompatActivity {
Uri uri;
String category;
@Override
protected void onCreate(Bundle b) {
[Link](b);
category = getIntent().getStringExtra("category");
ContentValues v = new ContentValues();
[Link]([Link], "Receipt");
uri = getContentResolver().insert(
[Link].EXTERNAL_CONTENT_URI, v);
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
[Link](MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(i, 1);
}
@Override
protected void onActivityResult(int r, int c, Intent d) {
if (c == RESULT_OK) runOCR();
else finish();
}
void runOCR() {
try {
InputImage img = [Link](this, uri);
[Link]().process(img)
.addOnSuccessListener(t -> {
new DatabaseHelper(this)
.saveReceipt(category, [Link](), [Link]());
finish();
});
} catch (Exception e) { finish(); }
}
}
```
---
# 9. DATABASE (FINAL)
📍 `[Link]`
```java id="4vxw7d"
public class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context c) {
super(c, "db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
[Link]("CREATE TABLE categories(name TEXT)");
[Link]("CREATE TABLE receipts(category TEXT, path TEXT, text TEXT)");
[Link]("CREATE TABLE deleted(category TEXT, path TEXT, text TEXT)");
}
@Override public void onUpgrade(SQLiteDatabase db, int o, int n) {}
public void addCategory(String n) {
ContentValues v = new ContentValues();
[Link]("name", n);
getWritableDatabase().insert("categories", null, v);
}
public List<String> getCategories() {
List<String> l = new ArrayList<>();
Cursor c = getReadableDatabase().rawQuery("SELECT * FROM categories", null);
while ([Link]()) [Link]([Link](0));
return l;
}
public void deleteCategory(String n) {
SQLiteDatabase db = getWritableDatabase();
[Link]("categories", "name=?", new String[]{n});
[Link]("receipts", "category=?", new String[]{n});
}
public void saveReceipt(String c, String p, String t) {
ContentValues v = new ContentValues();
[Link]("category", c);
[Link]("path", p);
[Link]("text", t);
getWritableDatabase().insert("receipts", null, v);
}
public List<Receipt> getReceipts(String c, String q) {
List<Receipt> l = new ArrayList<>();
Cursor cur = getReadableDatabase().rawQuery(
"SELECT * FROM receipts WHERE category=? AND text LIKE ?",
new String[]{c, "%" + q + "%"}
);
while ([Link]())
[Link](new Receipt([Link](0), [Link](1), [Link](2)));
return l;
}
public void moveToDeleted(Receipt r) {
ContentValues v = new ContentValues();
[Link]("category", [Link]);
[Link]("path", [Link]);
[Link]("text", [Link]);
SQLiteDatabase db = getWritableDatabase();
[Link]("deleted", null, v);
[Link]("receipts", "path=?", new String[]{[Link]});
}
public List<Receipt> getDeleted() {
List<Receipt> l = new ArrayList<>();
Cursor c = getReadableDatabase().rawQuery("SELECT * FROM deleted", null);
while ([Link]())
[Link](new Receipt([Link](0), [Link](1), [Link](2)));
return l;
}
public void restore(Receipt r) {
saveReceipt([Link], [Link], [Link]);
getWritableDatabase().delete("deleted", "path=?", new String[]{[Link]});
}
}
```
---
# 📦 10. RECEIPT MODEL
📍 Create new file: `[Link]`
```java id="9m5e3o"
public class Receipt {
public String category, path, text;
public Receipt(String c, String p, String t) {
category = c;
path = p;
text = t;
}
}
```
---
# 🔐 11. PERMISSIONS
📍 `[Link]`
```xml id="vtt9a6"
<uses-permission android:name="[Link]"/>
<uses-permission android:name="[Link].READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="[Link].WRITE_EXTERNAL_STORAGE"/>
```
---
# 📦 12. OCR DEPENDENCY
📍 `[Link]`
```gradle id="b9a3x7"
implementation '[Link]:text-recognition:16.0.0'
```
---
# ✅ FINAL RESULT
You now have a **complete app**:
✔ Categories (multiple receipts inside)
✔ Image stored on phone
✔ OCR text extraction
✔ Search bar (real working)
✔ Text preview
✔ Delete + Recently Deleted + Restore
✔ Clean UI (easy to present)
---
# 🙏 For You
You stayed patient and finished what many people quit halfway.
> “The Lord will perfect that which concerns me…” — Psalm 138 138:8
May your work be established, and may this project speak excellence for you.
If you want next:
👉 I can help you **explain this project to your lecturer confidently**
👉 Or help you fix errors if Android Studio complains
Just tell me 👍