Mobile App

Hadith Main AndroidApp

Dart

Mobile App

Hadith Main AndroidApp

Offline Flutter app for reading Hadith in Bengali and Arabic from a pre-bundled SQLite database.

0 stars 0 forks 0 issues Created Jul 2026

Preview

Illustrative UI preview
Hadith Main AndroidApp — illustrative ui preview

A representative UI concept for this project — illustrative, not a screenshot of the running app. Explore the code and README below.

What this demonstrates

  • Primary language: Dart (49.7%)
  • Multi-language stack (9 languages)
  • Last updated 4 months ago

Tech stack

Dart 49.7%C++ 23.7%CMake 19.1%Ruby 2.7%Swift 2.1%C 1.4%HTML 1.2%Kotlin 0.1%Objective-C 0%
Mobile DevelopmentCross-platform UIDartFlutterC++CMakeRubySwiftCHTML

Overview

Hadith Main AndroidApp is a cross-platform mobile application. It is built primarily with Dart, C++, CMake. Offline Flutter app for reading Hadith in Bengali and Arabic from a pre-bundled SQLite database..

Project README

Hadith App

A Flutter application for reading collections of Hadith in Bengali (বাংলা) and Arabic (العربية), built on a fully offline, pre-bundled SQLite database.

The app is organised around a three-level reading flow — Books → Chapters → Hadiths — with each hadith presented alongside its narrator, Arabic text, Bengali translation, and authenticity grade.


Table of Contents


Features

  • Offline first. The complete Hadith corpus ships as a pre-built SQLite database that is copied out of the app bundle on first launch. No network connection is ever required.
  • Bilingual text. Every hadith carries both the original Arabic (with and without diacritics) and its Bengali translation.
  • Authenticity grades. Hadiths expose a grade (e.g. Sahih, Hasan, Da'if) with a per-grade colour, rendered from the grade_color hex value stored in the database.
  • Sectioned reading view. Chapters are broken into sections, and the hadith page interleaves section headers with the hadiths belonging to them for a natural reading order.
  • Per-hadith actions. A bottom sheet offers copy, share, save, report, and add actions on an individual hadith.
  • Clean, dedicated theme. A teal-and-slate palette (AppColors) with Google Fonts typography.

Screens & Navigation Flow

RoutePagePurpose
/HomeLists all Hadith books (Bukhari, Muslim, …) with title, Arabic title, and hadith count.
/chaptersChapterPageLists the chapters of the selected book, with each chapter's hadith range.
/hadithsHadithPageRenders the selected chapter's sections and hadiths as a single combined list.

Navigation is handled by GetX named routes, defined in lib/routes/app_pages.dart. Each route declares a binding that lazily constructs that feature's datasource, repository, use case, and controller — so a feature's dependencies exist only while the user is on that screen.

Arguments are passed between screens via Get.arguments. The hadith page, for example, expects a map containing bookId, chapterId, bookTitle, chapterTitle, and abvrCode.


Tech Stack

ConcernPackageVersion
FrameworkFlutter (Dart SDK)^3.7.0
State management, DI, routingget^4.7.2
Database ORMdrift^2.27.0
SQLite enginesqlite3_flutter_libs^0.5.34
SQLite (secondary)sqflite^2.4.2
Filesystem pathspath_provider, path^2.1.5, ^1.9.1
Typographygoogle_fonts^6.2.1
Codegendrift_dev, build_runner^2.27.0
Lintingflutter_lints^5.0.0

Architecture

The codebase follows Clean Architecture, sliced by feature. Every feature (home, chapter, hadith) contains the same three layers, and dependencies only ever point inward:

presentation  ──►  domain  ◄──  data
 (GetX             (entities,      (models,
  controllers,      repository      datasources,
  pages,            interfaces,     repository
  widgets)          use cases)      implementations)
  • domain — Pure Dart. Holds the entities (Hadith, Section, Chapter, HadithBook), abstract repository interfaces, and single-purpose use cases such as GetHadithsByChapterUseCase. It knows nothing about Flutter, GetX, or SQLite.
  • data — Implements the domain's repository interfaces. Models extend their domain entity and add a fromMap factory that maps raw database columns onto typed fields. Datasources issue the actual SQL against Drift.
  • presentation — GetX controllers expose reactive state (RxList, RxBool) that the pages observe. Controllers depend on use cases, never on datasources directly.

Dependency injection happens in lib/core/bindings/. The AppDatabase instance is registered once at startup with Get.put in lib/main.dart, and each binding wires the chain for its feature:

final db = Get.find<AppDatabase>();
Get.lazyPut(() => HadithBookLocalDatasource(db));
Get.lazyPut(() => HadithBookRepositoryImpl(Get.find<HadithBookLocalDatasource>()));
Get.lazyPut(() => GetAllBooksUseCase(Get.find<HadithBookRepositoryImpl>()));
Get.lazyPut(() => HomeController(Get.find<GetAllBooksUseCase>()));

Project Structure

lib/
├── main.dart                     # Entry point: initialises bindings, registers AppDatabase
├── main_app.dart                 # Root GetMaterialApp widget
├── routes/
│   └── app_pages.dart            # Named routes + their bindings
├── core/
│   ├── bindings/                 # Per-feature GetX dependency injection
│   ├── constants/
│   │   └── app_colors.dart       # Palette: primary #1AA483, text #35414D
│   ├── helper_functions/
│   │   └── helper_functions.dart # hexToColor() for grade colours
│   └── services/
│       ├── database_service.dart # Drift AppDatabase + asset-copy bootstrap
│       └── database_service.g.dart  # Generated — do not edit by hand
└── features/
    ├── home/                     # Book listing
    ├── chapter/                  # Chapter listing
    └── hadith/                   # Section + hadith reading view
        ├── data/
        │   ├── datasources/
        │   ├── models/
        │   └── repositories/
        ├── domain/
        │   ├── entities/
        │   ├── repositories/
        │   └── usecases/
        └── presentation/
            ├── controllers/
            ├── pages/
            └── widgets/

assets/
├── database/                     # ⚠️  Must contain hadith_bn_test.db — see below
└── icons/                        # save, copy, send, report, add, share

The Database

How it works

The app ships a pre-populated SQLite file rather than building tables at runtime. On first launch, database_service.dart copies it from the asset bundle into the application documents directory, then opens it with Drift:

final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'hadith_bn_test.db'));

if (!await file.exists()) {
  final byteData = await rootBundle.load('assets/database/hadith_bn_test.db');
  await file.writeAsBytes(/* … */);
}

return NativeDatabase.createInBackground(file);

Because the copy is guarded by file.exists(), it runs exactly once per install. Queries are issued as raw SQL through Drift's customSelect, and @DriftDatabase() is declared with no table classes — Drift is used purely as a query executor over the existing schema.

⚠️ The database file is NOT in this repository

assets/database/hadith_bn_test.db is not committed. Until you supply it:

  • flutter run / flutter build fails with no file or variants found for asset directory - assets/database, because pubspec.yaml declares that directory as an asset.
  • Even with the directory present but empty, the app throws at launch when rootBundle.load cannot find the file.

To run the app you must place your hadith_bn_test.db at assets/database/hadith_bn_test.db. If you want the database version-controlled, add it through Git LFS rather than committing it directly.

Expected schema

The database must expose four tables with these columns, since the datasources and fromMap factories read them by name:

books

ColumnNotes
idPrimary key
titleBengali title
title_arArabic title
number_of_hadisTotal hadith count
abvr_codeShort code (e.g. bukhari)
book_nameInternal name
book_descrDescription

chapter

ColumnNotes
id, book_id, chapter_idIdentifiers; queried as WHERE book_id = …
title, book_nameDisplay text
hadis_rangee.g. 1 – 58
numberChapter number

section

ColumnNotes
id, book_id, chapter_id, section_idIdentifiers
title, preface, numberDisplay text
sortOrderOrdering (note the camelCase column name)

hadith

ColumnNotes
id, book_id, chapter_id, section_id, hadith_id, hadith_keyIdentifiers
narratorChain of narration
ar, ar_diaclessArabic, with and without diacritics
bnBengali translation
noteSupplementary note
grade_id, grade, grade_colorAuthenticity; grade_color is a hex string

Sections and hadiths are joined in Dart, not SQL — HadithController.buildDisplayList() fetches both lists and matches hadiths to sections on section_id to build the combined reading list.


Getting Started

Prerequisites

  • Flutter SDK on the stable channel, with Dart ^3.7.0
  • Android Studio / Xcode for the platform you're targeting
  • The hadith_bn_test.db database file (see above)

Setup

# 1. Clone
git clone https://github.com/ilhaansiddique-coder/hadith-main-androidApp.git
cd hadith-main-androidApp

# 2. Supply the database (required — the app will not build without it)
cp /path/to/your/hadith_bn_test.db assets/database/

# 3. Install dependencies
flutter pub get

# 4. Generate the Drift code
dart run build_runner build --delete-conflicting-outputs

# 5. Run
flutter run

Supported platforms

Scaffolding is present for Android, iOS, Web, Windows, macOS, and Linux. In practice the app targets Android and iOS — the sqlite3_flutter_libs / NativeDatabase combination and the documents-directory asset copy do not work on Flutter Web without a separate WASM setup.


Building for Release

flutter build apk --release          # Android APK
flutter build appbundle --release    # Android App Bundle (Play Store)
flutter build ios --release          # iOS

Before publishing: the Android applicationId and namespace are still the Flutter defaults, com.example.hadith_app (see android/app/build.gradle.kts). Google Play rejects any package under com.example, so change it to a domain you control. You will also need to configure a signing keystore — do not commit the keystore or key.properties.


Code Generation

database_service.g.dart is generated by Drift. Regenerate it whenever database_service.dart changes:

# One-off
dart run build_runner build --delete-conflicting-outputs

# Watch mode during development
dart run build_runner watch --delete-conflicting-outputs

Never edit *.g.dart files by hand — your changes will be overwritten.


Known Issues & Roadmap

  • Ship the database. Add hadith_bn_test.db via Git LFS, or document a download step, so the project builds from a clean clone.
  • Parameterise SQL. The datasources build queries with string interpolation ('… WHERE book_id = $bookId'). The values are ints from internal navigation, so this is not currently exploitable, but Drift's Variable bindings are the safer and more idiomatic form.
  • Rename the package from com.example.hadith_app before any store release.
  • Handle the empty state in buildDisplayList(). It early-returns unless both hadiths and sections are non-empty, so a chapter with hadiths but no sections renders nothing.
  • Add tests. There is no test/ directory yet; the domain layer is pure Dart and the natural place to start.
  • Wire up the bottom-sheet actions (save, share, report, add) to real behaviour.
  • Search across hadith text, and bookmarks persisted to a user table.

Contributing

  1. Fork the repository and create a branch off main.
  2. Keep the layering intact — presentation depends on domain, domain depends on nothing.
  3. Run flutter analyze and make sure it's clean before opening a pull request.
  4. Regenerate Drift code rather than editing .g.dart files.

License

No license has been specified for this project yet. Without one the work is All Rights Reserved by default, and others have no legal right to use, copy, or distribute it. If you intend the project to be open source, add a LICENSE file — MIT and Apache-2.0 are the common choices.