A versatile and user-friendly EPUB reader/viewer for Windows, Android, iOS, and macOS
Enjoy your favorite ebooks with extensive customization options and robust support for various EPUB formats
- ✨ Features
- 📸 Screenshots
- 🚀 Get Started
- 🛠️ Building from Source
- 🔥 Firebase Setup
- 📸 Screenshots
- 🛠️ Development
- 🤝 Contributing
- 📄 License
Available on Windows, Android, iOS, and macOS with native performance on each platform.
- 📑 Chapter & Page Navigation: Navigate seamlessly through chapters and pages
- 🎨 Font Customization: Adjust font family and font size to your preference
- 📍 Reading Position: Automatic tracking of reading position when switching between books
- 🎨 Color Themes: Various color themes with automatic dark/light mode switching
- 📊 Library Sorting: Sort by title, author, or date (on Calibre Server)
-
🔐 Google Authentication: Sign in with your Google account for cloud features
-
📱 Cross-Device Sync: Reading progress and settings sync across devices in real-time
-
🔄 Automatic Backup: Reading progress is automatically backed up to Firebase
-
📍 Position Tracking: Resume reading exactly where you left off on any device
-
🔁 Offline Queueing: Progress updates queue locally and reconcile on reconnect
-
🔒 Local-Only Mode: Use the app without authentication for complete privacy
-
🔐 Privacy: An in-app privacy policy is available under Settings → Privacy Policy. Cloud sync is optional and must be enabled by the user.
- 🔍 Discovery: Connect to Calibre Server using Bonjour auto-discovery
- 🌐 Manual Connection: Set Calibre Server URL directly
- 📚 Library Access: Navigate your entire Calibre library
- ⬇️ Download: Download EPUB books directly from your server
- 📖 Format Support: Full support for EPUB 2 and EPUB 3.x versions
- 🔧 Compatibility: Enhanced compatibility for out-of-spec and broken EPUBs
- 🎯 Reliability: Most ebooks work seamlessly (minor issues only with extremely malformed files)
- 🖼️ Images: Full support for embedded images
- 💄 CSS Styling: Complete CSS styles support within books
- 🔤 Fonts: Full support for fonts embedded within ebooks
- Audio Playback: Plays synchronized audio tracks embedded via MediaOverlays
- SMIL Highlighting: Highlights text in sync with audio using SMIL files
- Read-Along Support: Provides a seamless read-along experience with word/phrase highlighting
- Granular Controls: Play/pause and navigation work across chapters with overlays
Before building the project, ensure you have:
- Visual Studio 2026 (version 17.13 or later) with .NET MAUI workload installed
- .NET 10.0 SDK or later
- Platform-specific SDKs:
- For Android: Android SDK (API 34 or higher)
- For Windows: Windows App SDK
- For iOS/macOS: Xcode 16.0 or later
The .NET MAUI workload is required to build cross-platform applications. Install it using one of these methods:
- Open Visual Studio Installer
- Click Modify on your Visual Studio 2026 installation
- Go to the Workloads tab
- Check .NET Multi-platform App UI development
- Under Installation details, ensure the following are selected:
- .NET MAUI SDK
- Android SDK setup (API 34+)
- Android Emulator
- For iOS/Mac development: Xcode integration tools
- Click Modify to install
# Install .NET MAUI workload
dotnet workload install maui
# Verify installation
dotnet workload listDepending on your target platforms, you may need to install additional workloads:
# For Android development
dotnet workload install android
# For iOS development (macOS only)
dotnet workload install ios
# For macOS development (macOS only)
dotnet workload install maccatalyst
# For Windows development
dotnet workload install windows- Android SDK: API level 34 (Android 14) or higher
- Android Emulator: Recommended for testing
- Java Development Kit (JDK): Version 21 or later (automatically installed with Visual Studio)
- Android build tools: Installed automatically with Android SDK
To verify Android setup:
# Check Android SDK location
dotnet build EpubReader/EpubReader.csproj -t:GetAndroidSdkInfo
# List available Android emulators
adb devices- Windows 10 SDK: Version 19041 or later (automatically installed with Visual Studio)
- Windows App SDK: Included with .NET MAUI workload
- Developer Mode: Must be enabled in Windows Settings
- Go to Settings > Privacy & Security > For developers
- Enable Developer Mode
- Xcode: Version 16.0 or later
- Xcode Command Line Tools: Installed automatically with Xcode
- Apple Developer Account: Required for device deployment (free account available)
- CocoaPods: May be required for some dependencies
To install Xcode Command Line Tools:
xcode-select --installTo verify iOS setup:
# Check Xcode installation
xcodebuild -version
# List available iOS simulators
xcrun simctl list devicesAfter installing all prerequisites, verify your setup:
# Check .NET version
dotnet --version
# List installed workloads
dotnet workload list
# Restore project dependencies
dotnet restore EpubReader/EpubReader.csproj
# Verify project can build (replace target framework as needed)
dotnet build EpubReader/EpubReader.csproj -f net10.0-androidCommon Issues:
-
Workload installation fails
# Clean workload cache and reinstall dotnet workload clean dotnet workload install maui -
Android SDK not found
- Set
ANDROID_HOMEenvironment variable to your Android SDK location - Default locations:
- Windows:
%LOCALAPPDATA%\Android\Sdk - macOS:
~/Library/Android/sdk - Linux:
~/Android/Sdk
- Windows:
- Set
-
Missing Visual Studio components
- Re-run Visual Studio Installer and ensure all .NET MAUI components are selected
- Install optional components like Android Emulator if missing
-
iOS build fails on Windows
- iOS and macOS builds require a macOS machine
- Consider using Remote iOS Simulator for Windows (deprecated in .NET 9+)
- Alternative: Use a Mac for iOS/macOS development
git clone https://github.com/ne0rrmatrix/EpubReader.git
cd EpubReaderThe project includes several PowerShell scripts to simplify building and running the application with Firebase configuration.
Working directory: unless noted otherwise, run these PowerShell commands from the repository root (the folder that contains build.ps1, README.md, and EpubReader/).
Set-Location "C:\path\to\your\EpubReader-clone"If you are not in the repository root, prefer invoking scripts with pwsh -File and the full script path.
The main build script handles Firebase secrets without committing them to source control. It supports multiple ways to provide Firebase configuration:
For Android forks, also verify the Android signing property groups in EpubReader/EpubReader.csproj. The current Debug|net10.0-android|AnyCPU and Release|net10.0-android|AnyCPU blocks must point to a valid keystore file, alias, and passwords on your machine or Android builds can fail. See docs/firebase-fork-setup.md for the full signing-path guidance.
Basic Usage:
# Build all platforms (Debug)
.\build.ps1
# Build specific platform
.\build.ps1 -Android -Configuration Debug
.\build.ps1 -Windows -Configuration Release
# Using switches for configuration
.\build.ps1 -Android -DebugBuild
.\build.ps1 -Windows -ReleaseBuildThese examples assume your current directory is the repository root.
Providing Firebase Secrets:
-
Via Parameters (highest priority):
.\build.ps1 -Android -ApiKey "your-api-key" ` -AuthDomain "your-app.firebaseapp.com" ` -DatabaseUrl "https://your-db.firebaseio.com"
-
Via Google Services JSON:
.\build.ps1 -Android -GoogleJsonPath "path\to\google-services.json"
If you keep
google-services.jsonunder the repo, a repository-root example is:.\build.ps1 -Android -GoogleJsonPath ".\build-secrets\google-services.json"
-
Via Environment Variables:
$env:FIREBASE_API_KEY = "your-api-key" $env:FIREBASE_AUTH_DOMAIN = "your-app.firebaseapp.com" $env:FIREBASE_DATABASE_URL = "https://your-db.firebaseio.com" .\build.ps1 -Android
-
Via build-secrets Folder (auto-detected):
- Place
google-services.jsonin any of these locations:build-secrets/google-services.jsonbuild-secrets/android/google-services.jsonEpubReader/build-secrets/google-services.jsonEpubReader/build-secrets/android/google-services.json
- Run:
.\build.ps1 -Android
- Place
Important: Secrets are never printed to console or written to committed C# files.
Load Firebase secrets from .env or .env.local files:
Setup:
-
Create a
.envfile in the repository root:FIREBASE_API_KEY=your-api-key FIREBASE_AUTH_DOMAIN=your-app.firebaseapp.com FIREBASE_DATABASE_URL=https://your-db.firebaseio.com
-
(Optional) Create
.env.localfor local overrides (this file is gitignored) -
Run the build:
.\.vscode\build-from-env.ps1
Run that command from the repository root.
Priority Order:
.env.localoverrides.env- Environment variables already set take precedence
Launch the Windows debug build after building:
# Build and run
.\build.ps1 -Windows -DebugBuild
.\.vscode\run-app.ps1Run both commands from the repository root.
This script looks for the executable at:
EpubReader\bin\Debug\net10.0-windows10.0.19041.0\win-x64\EpubReader.exe
Convert google-services.json to Android XML resource strings:
Usage:
# Default paths
.\scripts\gen-android-strings.ps1
# Custom paths
.\scripts\gen-android-strings.ps1 `
-GoogleServicesJson "path\to\google-services.json" `
-OutFile "path\to\output\strings.secrets.xml"What it does:
- Reads
google-services.json - Extracts Firebase configuration values
- Generates
strings.secrets.xmlwith proper XML escaping - Places file in
build-secrets/android/by default
Generated format:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="google_api_key">your-api-key</string>
<string name="firebase_auth_domain">your-app.firebaseapp.com</string>
<string name="firebase_database_url">https://your-db.firebaseio.com</string>
<string name="google_app_id">your-app-id</string>
<string name="default_web_client_id">your-web-client-id</string>
</resources>-
Never commit secrets:
- Add
build-secrets/to.gitignore - Add
.env.localto.gitignore - Use environment variables in CI/CD
- Add
-
Use .env.local for sensitive data:
# Create local secrets file (gitignored) Copy-Item .env .env.local # Edit .env.local with your actual secrets
-
Verify secrets aren't leaked:
# Check what's staged for commit git status git diff --cached
-
For team development:
- Share
.env.exampletemplate with placeholder values - Each developer creates their own
.env.local - Use Azure Key Vault or similar for CI/CD secrets
- Share
For local development, you need to set up your Firebase credentials. Here's the recommended approach:
Step 1: Download Your Configuration File
- Go to Firebase Console
- Select your project
- Go to Project Settings (gear icon)
- Under "Your apps", find your Android app
- Click "Download google-services.json"
Step 2: Create build-secrets Directory
# Create the directory structure (already gitignored)
New-Item -ItemType Directory -Path "build-secrets" -Force
New-Item -ItemType Directory -Path "build-secrets/android" -ForceStep 3: Place Configuration File
# Copy your downloaded file to build-secrets
Copy-Item "Downloads/google-services.json" "build-secrets/google-services.json"
# Or copy to android-specific folder
Copy-Item "Downloads/google-services.json" "build-secrets/android/google-services.json"Step 4: Verify File Placement
# Check file exists and is valid JSON
Test-Path "build-secrets/google-services.json"
Get-Content "build-secrets/google-services.json" | ConvertFrom-JsonStep 5: Build with Your Credentials
# Build will automatically detect and use the file
.\build.ps1 -Android -DebugBuild
# Or explicitly specify the path
.\build.ps1 -Android -GoogleJsonPath "build-secrets/google-services.json"File Structure Reference:
EpubReader/
├── build-secrets/ # Your local credentials (gitignored)
│ ├── google-services.json # Android Firebase config
│ ├── android/
│ │ └── google-services.json
│ └── ios/
│ └── GoogleService-Info.plist
├── .env.local # Environment variables (gitignored)
├── build.ps1 # Main build script
└── EpubReader/
└── Platforms/
├── Android/
│ └── google-services.json # Optional: for direct builds
└── iOS/
└── GoogleService-Info.plist
What's in google-services.json?
The file contains essential Firebase configuration:
- project_info: Firebase project ID and database URL
- client_info: Your app's package name and app ID
To produce signed Android artifacts (APK/AAB) for release, set up your keystore and provide signing credentials via environment variables or a local .env.local (gitignored). The build scripts will never print secret values.
Required environment variables (local or CI):
ANDROID_KEYSTORE— absolute path to your keystore file (e.g.C:\Users\you\keys\release.keystore)ANDROID_KEYSTORE_PASSWORD— keystore store passwordANDROID_KEYSTORE_ALIAS— key alias inside the keystoreANDROID_KEY_PASSWORD— password for the key alias
Local development (recommended): add these to .env.local in the repo root (this file is gitignored). Example:
ANDROID_KEYSTORE=C:\Users\james\source\repos\EpubReader\EpubReader\epubreader.keystore
ANDROID_KEYSTORE_PASSWORD=your-store-pass
ANDROID_KEYSTORE_ALIAS=YourAlias
ANDROID_KEY_PASSWORD=your-key-passCI / GitHub Actions: store the keystore as a secret (base64 encoded) and the passwords as secrets. Use the included script scripts/export-keystore-base64.ps1 to create a base64 string suitable for a GitHub secret. In your workflow expose the secrets as environment variables with the same names (or decode the base64 into a file and set ANDROID_KEYSTORE to the file path).
Usage with the repository build scripts:
-
Build and sign (local):
# Ensures env vars (or .env.local) are present .\build.ps1 -Android -ReleaseBuild
-
The
build.ps1script will publish an Android artifact toartifacts\android. IfANDROID_KEYSTOREpoints to a valid file the artifact will be signed with the provided credentials; otherwise an unsigned artifact is produced. -
A convenience publish script
EpubReader\publishAndroid.ps1also reads the same environment variables and will sign when the keystore exists. It purposely avoids printing secret values.
Security notes:
-
Never commit your keystore or
.env.localto the repository. -
Add your keystore pattern to
.gitignore(the repo already ignores**/epubreader.keystore). -
Use CI secrets in GitHub Actions or an external secret manager for team builds.
-
api_key: API key for Firebase services
-
oauth_client: Web client ID for Google Sign-In
Important Security Notes:
build-secrets/is already in.gitignore- Double-check before committing:
git status - If accidentally committed, revoke keys in Firebase Console
✅ Safe practices:
- Keep files in
build-secrets/directory - Use different projects for dev/staging/production
- Rotate keys if ever exposed
- Use environment variables in CI/CD pipelines
Alternative: Using Environment Variables
Instead of files, you can extract and set environment variables:
# Extract from google-services.json and set environment variables
$json = Get-Content "build-secrets/google-services.json" | ConvertFrom-Json
$env:FIREBASE_API_KEY = $json.client[0].api_key[0].current_key
$env:FIREBASE_AUTH_DOMAIN = "$($json.project_info.project_id).firebaseapp.com"
$env:FIREBASE_DATABASE_URL = $json.project_info.firebase_url
# Then build
.\build.ps1 -AndroidFor Team Development:
Create a .env.example template for your team:
# .env.example - Template for team members
FIREBASE_API_KEY=get-from-firebase-console
FIREBASE_AUTH_DOMAIN=your-app.firebaseapp.com
FIREBASE_DATABASE_URL=https://your-project.firebaseio.comEach developer copies this to .env.local and fills in their values:
Copy-Item .env.example .env.local
# Edit .env.local with your actual values
notepad .env.localEpubReader uses Firebase for authentication and real-time synchronization of reading progress across devices. Follow these steps to configure Firebase for your build:
If you forked this repository and want to use your own Firebase project, see the full step-by-step guide in
docs/firebase-fork-setup.md. It now includes theGoogleServicesJsonproject-item behavior and separate instructions forbuild.ps1, Visual Studio, and Visual Studio Code.
Default Configuration:
- Android Package Name:
com.companyname.epubreader - iOS Bundle ID:
com.companyname.epubreader - App Display Name: "EpubReader"
For Your Own Firebase Project:
If you want to use your own Firebase project with custom naming, you'll need to:
-
Choose Your Package Name/Bundle ID (should be unique):
- Format:
com.yourcompany.yourappname - Example:
com.mycompany.bookviewer - Must be lowercase, no spaces or special characters except dots
- Format:
-
Update Project Files (if changing from default):
- Android: Edit
EpubReader/Platforms/Android/AndroidManifest.xml<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yourcompany.yourappname">
- iOS: Edit
EpubReader/Platforms/iOS/Info.plist<key>CFBundleIdentifier</key> <string>com.yourcompany.yourappname</string>
- Project File: Edit
EpubReader/EpubReader.csproj<ApplicationId>com.yourcompany.yourappname</ApplicationId> <ApplicationTitle>Your App Name</ApplicationTitle> <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
- Android: Edit
-
Match in Firebase Console:
- Use the exact same package name/bundle ID when registering your app in Firebase
- Case-sensitive matching is required
Quick Start with Default Settings:
If you want to quickly test with the default settings:
- Use package name:
com.companyname.epubreader - Download
google-services.jsonconfigured for this package name - No code changes needed - everything works out of the box
- If you want a full from-scratch walkthrough for your own fork, follow
docs/firebase-fork-setup.md
- Go to the Firebase Console
- Click "Add project" or select an existing project
- Enter a project name (e.g., "EpubReader" or "Your App Name")
- Note: Project name is for your reference only, doesn't affect app configuration
- Enable Google Analytics if desired
- Click "Create project"
- In Firebase Console, click the Android icon to add an Android app
- Enter your Android package name:
- Using default:
com.companyname.epubreader - Using custom:
com.yourcompany.yourappname(must match AndroidManifest.xml) ⚠️ Important: This cannot be changed later without creating a new app in Firebase
- Using default:
- Enter an app nickname (optional): "EpubReader Android" or your preferred name
- This is just for display in Firebase Console
- Enter your debug signing certificate SHA-1 (for development)
- To get SHA-1, run:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android- Windows users: Use
%USERPROFILE%\.android\debug.keystoreinstead of~/.android/
- Click "Register app"
- Download the
google-services.jsonfile - Verify the package name in the downloaded file:
# Check the package name matches your app $json = Get-Content "Downloads/google-services.json" | ConvertFrom-Json $packageName = $json.client[0].client_info.android_client_info.package_name Write-Host "Package name in google-services.json: $packageName"
- Place the file in one of these locations (for automatic detection by build scripts):
- Recommended:
build-secrets/google-services.json(project root) - Alternative:
build-secrets/android/google-services.json - Alternative:
EpubReader/build-secrets/google-services.json - For direct Visual Studio / Visual Studio Code Android builds, copy it to
EpubReader/Resources/Raw/google-services.json
- Recommended:
Package Name Troubleshooting:
- If you see "Package name mismatch" errors, ensure:
- AndroidManifest.xml
packageattribute matches Firebase - EpubReader.csproj
<ApplicationId>matches Firebase - google-services.json was downloaded for the correct package name
- AndroidManifest.xml
- Use this command to verify all locations match:
# Check AndroidManifest.xml Select-String -Path "EpubReader/Platforms/Android/AndroidManifest.xml" -Pattern 'package="([^"]*)"' # Check google-services.json $json = Get-Content "build-secrets/google-services.json" | ConvertFrom-Json $json.client[0].client_info.android_client_info.package_name
Important Notes:
- The
build-secrets/directory is gitignored to prevent committing your credentials - The build scripts will automatically detect and use files in
build-secrets/ - For direct IDE builds without
build.ps1, place the file inEpubReader/Resources/Raw/google-services.json - Ensure the file is named exactly
google-services.json(case-sensitive) - See
docs/firebase-fork-setup.mdfor the full direct Visual Studio and Visual Studio Code workflow
- In Firebase Console, click the iOS icon to add an iOS app
- Enter your iOS bundle ID:
- Using default:
com.companyname.epubreader - Using custom:
com.yourcompany.yourappname(must match Info.plist CFBundleIdentifier) ⚠️ Important: This cannot be changed later without creating a new app in Firebase
- Using default:
- Enter an app nickname (optional): "EpubReader iOS" or your preferred name
- Click "Register app"
- Download the
GoogleService-Info.plistfile - Verify the bundle ID in the downloaded file:
# Check the bundle ID matches your app (macOS) /usr/libexec/PlistBuddy -c "Print :BUNDLE_ID" Downloads/GoogleService-Info.plist
- Place the file in one of these locations:
- Recommended:
build-secrets/ios/GoogleService-Info.plist - Alternative:
EpubReader/Platforms/iOS/GoogleService-Info.plist(for direct builds)
- Recommended:
Bundle ID Troubleshooting:
- If you see bundle ID errors, ensure:
- Info.plist
CFBundleIdentifiermatches Firebase - EpubReader.csproj
<ApplicationId>matches Firebase - GoogleService-Info.plist was downloaded for the correct bundle ID
- Info.plist
After setting up Firebase:
- For Debug builds: Firebase will use the downloaded config files automatically
- For Release builds: Ensure config files are included or environment variables are set
- CI/CD: Store Firebase config as secrets and inject during build
If you want to publish your own version of EpubReader or customize it for your organization:
<!-- Example custom values -->
Package Name: com.mycompany.ebookreader
App Name: "MyBook Reader"
Display Version: 1.0.0File: EpubReader/Platforms/Android/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mycompany.ebookreader"> <!-- Change this -->
<application
android:label="MyBook Reader" <!-- Change this -->
android:icon="@mipmap/appicon">
<!-- ... rest of manifest ... -->
</application>
</manifest>File: EpubReader/Platforms/iOS/Info.plist
<dict>
<key>CFBundleIdentifier</key>
<string>com.mycompany.ebookreader</string> <!-- Change this -->
<key>CFBundleDisplayName</key>
<string>MyBook Reader</string> <!-- Change this -->
<key>CFBundleName</key>
<string>MyBook Reader</string> <!-- Change this -->
<!-- ... rest of plist ... -->
</dict>File: EpubReader/EpubReader.csproj
<PropertyGroup>
<ApplicationId>com.mycompany.ebookreader</ApplicationId> <!-- Change this -->
<ApplicationTitle>MyBook Reader</ApplicationTitle> <!-- Change this -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion> <!-- Your version -->
<ApplicationVersion>1</ApplicationVersion>
<!-- Optional: Customize icons -->
<ApplicationIcon>Resources\AppIcon\appicon.svg</ApplicationIcon>
</PropertyGroup>- In Firebase Console, register your app with your custom package name/bundle ID
- Download new
google-services.jsonandGoogleService-Info.plist - Place them in
build-secrets/directory - Verify package names match:
# Verify Android
$json = Get-Content "build-secrets/google-services.json" | ConvertFrom-Json
Write-Host "Firebase Package: $($json.client[0].client_info.android_client_info.package_name)"
$manifest = Get-Content "EpubReader/Platforms/Android/AndroidManifest.xml" -Raw
if ($manifest -match 'package="([^"]*)"') {
Write-Host "Manifest Package: $($Matches[1])"
}
# Verify iOS (macOS only)
$plist = /usr/libexec/PlistBuddy -c "Print :BUNDLE_ID" build-secrets/ios/GoogleService-Info.plist
Write-Host "Firebase Bundle ID: $plist"For Android, add your debug and release certificates to Firebase:
# Debug certificate
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
# Release certificate (if you have one)
keytool -list -v -keystore /path/to/your-release.keystore -alias your-aliasCopy the SHA-1 fingerprints and add them in Firebase Console:
- Project Settings → Your Android App → Add Fingerprint
# Build with your custom configuration
.\build.ps1 -Android -GoogleJsonPath "build-secrets/google-services.json"
# Verify the app installs with your custom package name
adb shell pm list packages | Select-String "com.mycompany"- Updated package name in AndroidManifest.xml
- Updated bundle ID in Info.plist
- Updated ApplicationId in EpubReader.csproj
- Updated ApplicationTitle in EpubReader.csproj
- Created Firebase project with custom app registrations
- Downloaded google-services.json with matching package name
- Downloaded GoogleService-Info.plist with matching bundle ID
- Added SHA-1 certificates to Firebase Console
- Verified package names match across all files
- Tested build and run with custom configuration
- (Optional) Updated app icons and splash screens
- (Optional) Updated app display name in XAML files
If you just want to use the app as-is for testing:
- Keep default package name:
com.companyname.epubreader - Create Firebase project and register with default names
- Download config files for
com.companyname.epubreader - Place in
build-secrets/directory - Build and run - no code changes needed!
Advantages of keeping defaults:
- Faster setup for testing
- No risk of typos in multiple files
- Easy to follow tutorials and documentation
- Can change later when ready to publish
When to customize:
- Publishing to Google Play Store or Apple App Store
- Creating a fork for your organization
- Adding custom branding
- Deploying to production
- Build and run the app
- Navigate to the login page
- Sign in with a Google account
- Open a book and read a few pages
- Sign in on another device with the same account
- Verify that reading progress syncs automatically
Users can also use the app without Firebase authentication:
- On the login page, select "Continue without signing in"
- All data will be stored locally only
- Cloud sync features will be disabled
1. "google-services.json not found" or "Missing google-services.json"
Cause: The build process cannot locate your Firebase configuration file.
Solutions:
- Verify the file exists in one of these locations:
build-secrets/google-services.json build-secrets/android/google-services.json EpubReader/Platforms/Android/google-services.json - Check the filename is exactly
google-services.json(case-sensitive, no extra extensions) - Ensure you downloaded the Android version (not iOS version)
- If using PowerShell scripts, check environment variables are set:
$env:FIREBASE_API_KEY $env:FIREBASE_AUTH_DOMAIN $env:FIREBASE_DATABASE_URL
2. "FirebaseApp with name [DEFAULT] doesn't exist"
Cause: Firebase configuration values are missing or incorrect.
Solutions:
- Re-download
google-services.jsonfrom Firebase Console - Verify the file contains valid JSON (open in text editor)
- Check that the package name matches:
com.companyname.epubreader - If using environment variables, ensure all required variables are set:
# Check variables are set (values will be hidden) echo $env:FIREBASE_API_KEY -ne $null echo $env:FIREBASE_AUTH_DOMAIN -ne $null echo $env:FIREBASE_DATABASE_URL -ne $null
- Clean and rebuild:
dotnet clean dotnet build -f net10.0-android
3. "Failed to parse google-services.json"
Cause: The JSON file is corrupted or has invalid formatting.
Solutions:
- Re-download the file from Firebase Console
- Open the file in a text editor and verify it's valid JSON
- Check for extra characters or byte-order marks (BOM) at the start
- Use a JSON validator online to check structure
- Ensure the file wasn't modified during download (check file size)
4. "Package name mismatch" or "SHA-1 certificate fingerprint mismatch"
Cause: The app's package name or signing certificate doesn't match Firebase configuration.
Solutions:
- Verify package name in Firebase Console matches your app
- For debug builds, add debug keystore SHA-1 to Firebase Console:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android - For release builds, add your release keystore SHA-1
- In Firebase Console, go to Project Settings → Your Android App → Add Fingerprint
5. "FIREBASE_API_KEY environment variable not set"
Cause: Build script requires Firebase secrets but they weren't provided.
Solutions:
- Use PowerShell build script with secrets:
.\build.ps1 -Android -GoogleJsonPath "path\to\google-services.json"
- Or set environment variables:
$env:FIREBASE_API_KEY = "your-key-here" $env:FIREBASE_AUTH_DOMAIN = "your-app.firebaseapp.com" $env:FIREBASE_DATABASE_URL = "https://your-db.firebaseio.com"
- Or place
google-services.jsoninbuild-secrets/folder
1. "Google Sign-In failed" or "Error code: 10"
Cause: Google authentication is not properly configured or credentials are incorrect.
Solutions:
- Verify Google Sign-In is enabled in Firebase Console:
- Go to Authentication → Sign-in method
- Ensure Google provider is enabled
- Check SHA-1 fingerprint is added in Firebase Console
- Ensure
default_web_client_idis correct ingoogle-services.json - For Android, verify the OAuth client ID is configured:
- Go to Google Cloud Console
- APIs & Services → Credentials
- Ensure Android OAuth client exists with correct package name and SHA-1
2. "Permission denied" when accessing Firebase Realtime Database
Cause: Firebase security rules are too restrictive or user is not authenticated.
Solutions:
- Check Firebase Realtime Database security rules
- For development, temporarily use test mode rules:
{ "rules": { ".read": "auth != null", ".write": "auth != null" } } - Ensure user is successfully signed in before accessing database
- Check Firebase Console → Realtime Database → Rules tab
- Verify database URL matches in configuration
3. "FirebaseException: Invalid API key"
Cause: The API key in your configuration is incorrect or has been regenerated.
Solutions:
- Re-download fresh
google-services.jsonfrom Firebase Console - Check for typos if setting API key manually
- Verify API key restrictions in Google Cloud Console:
- Go to APIs & Services → Credentials
- Click on your API key
- Check Android restrictions match your app
- Clear app data/cache and rebuild:
dotnet clean rm -rf EpubReader/bin EpubReader/obj dotnet build -f net10.0-android
4. "Network error" or "Unable to resolve host"
Cause: Network connectivity issues or incorrect Firebase database URL.
Solutions:
- Verify device/emulator has internet connection
- Check Firebase database URL format:
- Should be:
https://your-project-id.firebaseio.com - Not:
https://your-project-id.web.app
- Should be:
- Test Firebase connection in browser
- Check firewall/proxy settings aren't blocking Firebase domains
- Ensure Firebase project is active (not deleted or suspended)
5. "App crashes immediately on launch with Firebase error"
Cause: Critical Firebase configuration error or missing required fields.
Solutions:
- Check Android Logcat for detailed error:
adb logcat | grep -i firebase - Verify all required fields in
google-services.json:project_info.project_idproject_info.firebase_urlclient[0].client_info.mobilesdk_app_idclient[0].api_key[0].current_key
- Ensure FirebaseConfigLoader is working correctly
- Try running in local-only mode to isolate Firebase issues
- Check Visual Studio Output window for detailed error messages
Enable Detailed Logging:
For Android, add to your debug session:
adb logcat | Select-String -Pattern "Firebase|Auth|Database"Verify Configuration at Runtime:
Add temporary logging in your code:
// In FirebaseConfigLoader or MauiProgram.cs
System.Diagnostics.Trace.WriteLine($"Firebase API Key set: {!string.IsNullOrEmpty(apiKey)}");
System.Diagnostics.Trace.WriteLine($"Firebase Auth Domain: {authDomain}");
System.Diagnostics.Trace.WriteLine($"Firebase Database URL: {databaseUrl}");Test Firebase Connection:
Use Firebase Console to test:
- Go to Authentication → Users
- Try signing in with a test Google account
- Go to Realtime Database → Data
- Verify data structure and permissions
Common Checklist:
-
google-services.jsonis in the correct location - Package name matches:
com.companyname.epubreader - SHA-1 fingerprint is added to Firebase Console
- Google Sign-In is enabled in Firebase Console
- Realtime Database is created and has proper security rules
- API key is valid and not restricted incorrectly
- Database URL format is correct
- Device/emulator has internet connectivity
- Firebase project is active and billing is enabled (if required)
If you're still experiencing issues:
- Check build output logs in Visual Studio Output window
- Review Firebase Console for any project warnings or quota issues
- Test with a fresh Firebase project to rule out account issues
- Try local-only mode to verify the app works without Firebase
- Check GitHub Issues for similar problems and solutions
Useful Commands for Diagnostics:
# Check if file exists
Test-Path "build-secrets/google-services.json"
# Validate JSON file
Get-Content "build-secrets/google-services.json" | ConvertFrom-Json
# Check environment variables
Get-ChildItem Env: | Where-Object { $_.Name -like "*FIREBASE*" }
# Clean build artifacts
dotnet clean
Remove-Item -Recurse -Force EpubReader/bin, EpubReader/obj -ErrorAction SilentlyContinue
# Rebuild with verbose logging
dotnet build EpubReader/EpubReader.csproj -f net10.0-android -v detailed






























