Overview
Smart Tenant is the Android app for the Smart Tenant property management website. It gives tenants and maintainers (repair staff) everything they need on their phone, while property owners, managers and the owner keep using the website. The app talks only to your website, so all data stays on your server.
What is in the package
| Folder / file | What it is |
|---|---|
lib/ | The app's source code (Flutter / Dart). |
assets/ | logo.png (login screen), icon.png and icon_foreground.png (app icon), notification_icon/ (small notification icon). |
setup.sh | One command that creates the Android project folder with every setting already applied. |
pubspec.yaml | App version and the list of libraries. |
docs/API.md | Reference of the website API the app uses (for developers who want to extend it). |
documentation/ | This guide. |
Features
Tenant features
| Area | What the tenant can do |
|---|---|
| Home | Next payment and amount due (red when overdue) with Pay now; total paid this year; lease dates and rent (and any scheduled rent change); property, address, unit, rooms, household; security deposit; autopay status; open repairs; polls to answer; documents that expire soon; inspection report waiting for a signature; parking; upcoming events. Quick buttons: Report a problem, Ask the assistant, Visitor pass, Book a facility. |
| Invoices | Open / paid / all invoices; invoice details with items, payments, credit notes; online payment (Stripe / Razorpay — opens the website's secure payment page); PDF receipts downloaded and opened on the phone. The invoice refreshes by itself after paying. |
| Repairs | Report a problem with type, description, photo (camera or gallery) and preferred visit day and time slot; follow the status; see the assigned maintainer and "on the way" notice; message the maintainer and office; rate the job when it is completed. |
| Assistant | Chat assistant (AI when enabled on the website) that answers questions, can raise a repair request from the conversation, and shows replies from office staff. |
| Payment history | All payments grouped by year with totals per year and receipt downloads. |
| Security deposit | Amount held, received, deducted, refunded, the unit's required deposit and every entry. |
| My documents | Documents on file (ID, insurance, …) with type, expiry date and "expired" / "expires soon" labels; open the file. |
| Inspections | Move-in, move-out and routine inspection reports room by room with condition, notes and photos; sign the report in the app. |
| Utility readings | Meter readings for the unit: previous / current reading, usage, rate and amount. |
| Notice board | Notices from the property manager. |
| Facility bookings | Book shared facilities (hall, gym, …) by free time slot, see bookings and their approval, cancel. |
| Visitor passes | Create a pass with visitor name, date, phone, purpose and vehicle; share the pass code; cancel. |
| Polls | Vote in property polls and see results when the manager allows it. |
| Agreements | Read the lease agreement PDF and sign with a finger. |
| Profile | Name, phone, change password, phone notifications on/off, test notification, sign out. |
Maintainer features
| Area | What the maintainer can do |
|---|---|
| Home | Counts (urgent, pending, in progress, completed this month, hours, new today); today's visits; earnings this month; work queue (most urgent first); preventive maintenance tasks; recent ratings and feedback. |
| Schedule | The next 14 days by day (Today, Tomorrow, …): repair visits on the tenant's preferred day and time slot plus preventive tasks; jobs without a set day at the end. |
| Jobs | Open / pending / in progress / completed jobs. Job details: problem, AI summary and priority, photos, address with Directions (maps app), tenant name and Call, earlier repairs at the same unit, messages. |
| Updates | "I'm on my way" (the tenant gets a notification and SMS); change status; enter cost, hours worked and fixed date; add an after photo and an invoice file. Completing the job notifies the tenant. |
| Account | Trade, properties covered, jobs completed, total hours, total billed, rating, member since; profile, phone notifications, sign out. |
Common to both
- Login with email and password, "Remember me", forgot password, and the 6-digit code when the user has 2-factor login on the website.
- Notifications inbox: bell with unread count on the home screen; tap a notification to open the right screen; "Mark all read".
- Push notifications — see the Push notifications section for the full list of events.
- Dynamic branding: login screen shows the website's logo, name and colours; after sign-in the user's company branding.
- Money and dates are shown in the company's currency and date format (set on the website).
- Server messages (errors, confirmations) follow the user's language on the website. The app's own labels are English; translate them in
lib/if needed. - Works with large phone font sizes and dark mode.
- Offline-friendly start: remembers the session and branding; shows "No connection" with Retry when the server cannot be reached.
Requirements
Your computer (to build the app)
| What | Version / notes |
|---|---|
| Operating system | Windows 10/11 (64-bit), macOS, or Linux (64-bit) |
| Flutter SDK | Latest stable release (3.27 or newer; tested with 3.47). Includes Dart. |
| Android Studio | Latest version. Gives you the Android SDK, build tools, Java (JDK 17+, bundled) and the emulator. |
| Android SDK | Installed by Android Studio (SDK Platform, Build-Tools, Command-line Tools, Platform-Tools). |
| Disk / memory | About 10 GB free space, 8 GB RAM or more recommended. |
Shell for setup.sh | macOS / Linux: Terminal. Windows: Git Bash (comes with Git for Windows) or WSL. |
Phones that can run the app
Android 7.0 (API 24) or newer — about 98 % of active Android phones. (The exact minimum is Flutter's default; never lower than Android 6.0.)
Accounts
| Account | Cost | Needed for |
|---|---|---|
| Google Play Console | $25 one time | Publishing on Google Play |
| Firebase (Google) | Free (Spark plan is enough) | Push notifications |
Website
Smart Tenant v3.6 or newer on HTTPS — see Prepare the website.
Install Flutter & Android Studio
- Install Android Studio from developer.android.com/studio. Start it once and finish the setup wizard (Standard). Then open Settings → Languages & Frameworks → Android SDK → SDK Tools and tick Android SDK Command-line Tools and Android SDK Platform-Tools. In Plugins, install the Flutter plugin (it adds Dart).
- Install Flutter following docs.flutter.dev/get-started/install
(choose your operating system → Android). Unzip it to a folder without spaces (e.g.
C:\src\flutteror~/flutter) and add itsbinfolder to your PATH. - Accept the Android licences and check everything:
flutter doctor --android-licenses flutter doctorflutter doctormust show a tick for Flutter and Android toolchain. (Chrome, Xcode and Visual Studio are not needed for Android.)
flutter doctor cannot find Java, set JAVA_HOME to Android Studio's bundled JDK
(e.g. C:\Program Files\Android\Android Studio\jbr) or run flutter config --jdk-dir "<that folder>".Prepare the website
Do this once on the website before building the app.
- Website on HTTPS. Install Smart Tenant v3.6+ on your domain with an SSL certificate
(Let's Encrypt is free). Release builds of the app refuse plain
http://. - Run the update. If you upgraded an existing website, make sure the database update ran
(
php artisan migrate --force, or the website's update screen). It creates the tables for phones and notifications. - Find your API address. Sign in as the owner → Settings → Mobile App. The page shows the address the app
needs, which is your website address followed by
/api/v1, for examplehttps://app.yourdomain.com/api/v1. Openhttps://app.yourdomain.com/api/v1/app-configin a browser: you should see JSON with your logo and colours. - Branding. Settings → General (Application Name, logo, favicon) and the theme colour are used by the app's login screen. Each owner's own General settings and theme are used after their tenants sign in.
- Accounts to test with. Create (or use) one tenant account and one maintainer account on the website.
- Cron job. The website's cron (
php artisan schedule:runevery minute) sends the reminder notifications (rent due, lease and document expiry). - Upload size. Photos are sent from the phone; set PHP
upload_max_filesizeandpost_max_sizeto at least10M.
Set up the project
- Unzip the package. It contains the
android_appfolder; put it in a path without spaces, for example~/projects/android_app. - Choose your package name. It is your company's reversed domain, e.g.
com.acmehomes. The app's ID on Google Play becomescom.acmehomes.smart_tenant.The package name can never change after the app is published. Use lower case letters, numbers and dots only. - Run the setup script in the project folder (Git Bash on Windows):
It creates thecd ~/projects/android_app chmod +x setup.sh ./setup.sh com.acmehomes "Acme Homes"android/folder and applies everything the app needs:- Internet and notification permissions, links to the browser / phone dialer
- Minimum Android version and the libraries required by notifications
- Small notification icon and notification channel
- App name under the icon, app icon from
assets/icon.png - Downloads the Flutter libraries (
flutter pub get)
- Set your website address in
lib/config/app_config.dart:static const String appName = 'Acme Homes'; static const String apiBaseUrl = String.fromEnvironment('API_BASE_URL', defaultValue: 'https://app.yourdomain.com/api/v1'); static const String websiteUrl = 'https://app.yourdomain.com'; - Open the project in Android Studio (File → Open → the project folder) or VS Code.
flutter create . --org com.acmehomes --project-name smart_tenant --platforms android,
then apply the Android settings described in Manual Android settings.How the setup script works
The android/ folder is not included in the package on purpose: every app needs its own permanent package name, so the folder is created on your computer with yours. setup.sh does this in two steps.
Step 1 — Flutter creates the folder
The script runs Flutter's own command:
flutter create . --org com.acmehomes --project-name smart_tenant --platforms android
This builds a standard android/ folder from Flutter's official template with your ID (com.acmehomes.smart_tenant). The app's code in lib/ is not touched.
Step 2 — the script adds this app's settings
Flutter's template is generic, so the script then edits the new files:
| File | What is added |
|---|---|
android/app/src/main/AndroidManifest.xml | Internet and notification permissions, links to the browser and phone dialer, app name, notification icon and notification channel |
android/app/build.gradle.kts | Minimum Android version, and the library setting that phone notifications need |
android/app/src/main/res/drawable-*/ | The small white notification icon, copied from assets/notification_icon/ |
android/app/src/debug/AndroidManifest.xml | Allows http:// in test builds only (release builds need HTTPS) |
| All icon sizes | Generated from assets/icon.png (dart run flutter_launcher_icons) |
| Libraries | Downloaded with flutter pub get |
Result
android_app/
android/ <- created, with com.acmehomes.smart_tenant
lib/ (unchanged)
assets/
...
- Safe to run again: settings are never added twice. Run it again to change the app name.
- Different ID before publishing: delete the
android/folder and run the script again with the new ID. After publishing the ID cannot change. - Windows: run it in Git Bash (installed with Git for Windows).
Every change is also listed in Manual Android settings, for reference or to make them by hand.
Run on a phone or emulator
On a real phone
- On the phone: Settings → About phone, tap Build number 7 times to enable Developer options.
- Settings → Developer options → USB debugging: on. Connect the phone with USB and allow the computer.
- Check the phone is listed, then run:
flutter devices flutter run
On the emulator
Android Studio → Device Manager → Create device (e.g. Pixel 8, latest system image) → Start. Then flutter run.
Testing against a local website (http)
Debug builds allow plain http:// so you can test against a website on your computer or local network:
# phone on the same Wi-Fi as your computer (use your computer's IP address)
flutter run --dart-define=API_BASE_URL=http://192.168.1.10/smart-tenant/main_file/api/v1
# Android emulator: 10.0.2.2 is your computer
flutter run --dart-define=API_BASE_URL=http://10.0.2.2/smart-tenant/main_file/api/v1
Sign in with the tenant or maintainer account you created on the website.
A test APK to share
flutter build apk --debug --dart-define=API_BASE_URL=https://app.yourdomain.com/api/v1
# file: build/app/outputs/flutter-apk/app-debug.apkSend this file to testers; they install it after allowing "Install unknown apps". For the store, use a release build (next sections).
Branding & customisation
Changes that need no new build (from the website)
| What | Where on the website |
|---|---|
| Logo and name on the login screen | Owner → Settings → General (Application Name, Logo) |
| Colours | Owner → Settings → theme colour |
| Company logo, name, colours after sign-in | Each owner → Settings → General / theme |
| Push notification setup | Owner → Settings → Mobile App |
The app checks for changes every time it opens. The look is remembered, so it opens correctly even offline.
Changes in the code (then build again)
| What | How |
|---|---|
| App name under the icon | Second argument of setup.sh (run it again), e.g. ./setup.sh com.acmehomes "Acme Homes". Also set appName in lib/config/app_config.dart. |
| Website address | apiBaseUrl in lib/config/app_config.dart (or --dart-define=API_BASE_URL=… when building). |
| App icon | Replace assets/icon.png (1024×1024 px, your mark on a solid background, no transparency) and
assets/icon_foreground.png (1024×1024, same mark on transparent background, mark about 50–60 % of the square).
Then run dart run flutter_launcher_icons. The adaptive icon background colour is adaptive_icon_background in pubspec.yaml. |
| Fallback logo | Replace assets/logo.png (used only before the website has answered once). |
| Fallback colours | brandColor and brandDarkColor in lib/config/app_config.dart. |
| "Use the website" link on login | websiteUrl in lib/config/app_config.dart. |
| Texts / translation | Screen texts are in lib/screens/. Search for the English text and replace it. |
The settings file:
class AppConfig {
static const String appName = 'Acme Homes';
static const String apiBaseUrl = String.fromEnvironment('API_BASE_URL',
defaultValue: 'https://app.yourdomain.com/api/v1');
static const Color brandColor = Color(0xFF2CA58D); // buttons, links
static const Color brandDarkColor = Color(0xFF0A2342); // headings, accents
static const String logoAsset = 'assets/logo.png';
static const String websiteUrl = 'https://app.yourdomain.com';
}Small notification icon
Android shows a white silhouette in the status bar. Replace the five files in
assets/notification_icon/ (white shape on transparent background, 24/36/48/72/96 px for mdpi/hdpi/xhdpi/xxhdpi/xxxhdpi) and run
./setup.sh again.
Push notifications (Firebase)
Without this step the app works and shows updates in the bell inbox, but phones do not get pop-up notifications. Everything is configured on the website: no Firebase files inside the app and no new build.
- Go to console.firebase.google.com → Create a project (Google Analytics is not needed).
- In the project: Add app → Android. Android package name: exactly your app ID, e.g.
com.acmehomes.smart_tenant(seeapplicationIdinandroid/app/build.gradle.kts). App nickname: anything. SHA-1: not needed. Click Register app. - Download google-services.json. Do not put it in the app; skip the remaining Firebase SDK steps.
- Firebase → Project settings → Service accounts → Generate new private key. A JSON file downloads (keep it secret).
- On your website as the owner: Settings → Mobile App. Open each file in a text editor and paste:
- the service account key JSON → Firebase service account (lets the website send)
- the
google-services.jsoncontent → Android app (google-services.json) (lets the app connect)
- Close and reopen the app, sign in and allow notifications when Android asks (Android 13+).
- Test: tenant More → Send a test notification (maintainer: Account). A notification should arrive within seconds. If not, the message on screen tells you what is missing.
When users are notified
| Who | Event | Opens |
|---|---|---|
| Tenant | New invoice, rent reminder | Invoices |
| Tenant | Payment received, rent paid automatically (autopay), automatic payment failed, refund or credit issued | Invoices |
| Tenant | Repair status changed, maintainer "on the way" | Repairs |
| Tenant | Reply from the office in the assistant chat | Assistant |
| Tenant | Visitor has arrived | Visitor passes |
| Tenant | Facility booking approved / not approved | Facility bookings |
| Tenant | New notice, new poll | Notice board / Polls |
| Tenant | Rental agreement ready to sign | Agreements |
| Tenant | Inspection report ready to sign | Inspections |
| Tenant | Document expiring soon, lease ending soon, rent change notice | My documents / Home |
| Maintainer | New job assigned | Jobs |
Every notification is also saved in the in-app inbox (the bell), even when phone notifications are off. Each user can switch phone notifications off under More (tenant) or Account (maintainer).
Version numbers
The version is in pubspec.yaml:
version: 1.0.0+1
1.0.0is the version users see (versionName).+1is the build number (versionCode). Google Play requires a higher number for every upload: 1.0.0+1, 1.0.1+2, 1.1.0+3 …
Signing key (keystore)
Google Play only accepts apps signed with your own upload key. Create it once:
# macOS / Linux
keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
# Windows (PowerShell)
keytool -genkey -v -keystore $env:USERPROFILE\upload-keystore.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias upload
keytool comes with Java; if it is not found, use the one in Android Studio's jbr/bin folder. Choose a strong password and
answer the questions (name, organisation, country).
Tell the build where the key is
Create android/key.properties:
storePassword=your-store-password
keyPassword=your-key-password
keyAlias=upload
storeFile=/home/you/upload-keystore.jks(Windows: storeFile=C:\\Users\\you\\upload-keystore.jks.) Add android/key.properties to .gitignore.
Edit android/app/build.gradle.kts. At the top, after the plugins { … } block:
import java.util.Properties
import java.io.FileInputStream
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}Inside android { … }, before buildTypes, add a signing config, and use it for release:
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
storePassword = keystoreProperties["storePassword"] as String
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
}
}Replace the existing release { signingConfig = signingConfigs.getByName("debug") } block — do not keep both.
(Older projects with build.gradle instead of .kts: see
Flutter's guide.)
Build the release
Make sure apiBaseUrl points to your https website, then:
flutter clean
flutter pub get
# for Google Play (Android App Bundle)
flutter build appbundle --release
# file: build/app/outputs/bundle/release/app-release.aab
# optional: an installable APK (direct download, other stores)
flutter build apk --release
# file: build/app/outputs/flutter-apk/app-release.apk
You can also pass the address without editing the file: flutter build appbundle --release --dart-define=API_BASE_URL=https://app.yourdomain.com/api/v1.
Test the release APK on a real phone before uploading (flutter install or copy the APK): sign in as tenant and maintainer, open
each screen, take a photo, pay a test invoice, send a test notification.
Publish on Google Play
1. Developer account
Register at play.google.com/console ($25 one time, identity verification).
- Organisation account (needs a free D-U-N-S number for your company): can publish to production directly.
- Personal account: Google requires a closed test with at least 12 testers for 14 days in a row before you can apply for production. Plan for this.
2. Create the app
Play Console → Create app: app name, default language, App (not game), Free, accept the declarations.
3. Store listing (Grow → Store presence → Main store listing)
| Item | Requirement | Suggestion |
|---|---|---|
| App name | Max 30 characters | "Acme Homes – Tenant App" |
| Short description | Max 80 characters | "Pay rent, report repairs and stay in touch with your property manager." |
| Full description | Max 4000 characters | List the tenant and maintainer features from this guide. |
| App icon | 512×512 PNG, 32-bit | Same mark as assets/icon.png |
| Feature graphic | 1024×500 JPG/PNG | Logo + a short slogan on your brand colour |
| Phone screenshots | 2–8, 16:9 or 9:16, 320–3840 px | Login, tenant home, invoice, repair, maintainer jobs, schedule |
| Contact details | Email (website and phone optional) | Your support email |
| Category | House & Home or Business |
Tip: take screenshots on the emulator (camera button in the emulator toolbar) with demo data on your website.
4. App content (Policy → App content)
| Section | Answer |
|---|---|
| Privacy policy | URL of the privacy policy page on your website |
| App access | All or some functionality is restricted → add a tenant and a maintainer demo login with instructions ("Sign in with this email and password") |
| Ads | No, the app does not contain ads |
| Content rating | Fill in the questionnaire (category: Utility/Productivity; no violence etc.) → usually "Everyone" |
| Target audience | 18 and over |
| Data safety | See Privacy & data safety |
| Government / financial / health apps | Not applicable (rent is paid on your website's payment page) |
5. Upload and release
- Testing → Internal testing → Create release → accept Play App Signing → upload
app-release.aab→ release notes → Save → Review → Start rollout. Add your testers' emails and install through the opt-in link. - Closed testing (required for new personal accounts: 12+ testers, 14 days).
- Production → Create release → upload (or promote the tested release) → choose countries → Send for review.
- Review usually takes from a few hours to 7 days. You get an email when the app is live.
Updates
Raise the build number in pubspec.yaml, build a new .aab, and create a new release in Production (or a testing track first).
Use staged rollout (e.g. 20 %) for big changes.
Other distribution
The release APK (app-release.apk) can also be offered as a direct download from your website, through an MDM, or on other stores
(Amazon Appstore, Samsung Galaxy Store, Huawei AppGallery). Push notifications need Google Play services on the phone (not available on Huawei
phones without Google services).
Privacy & data safety
Both stores require a privacy policy URL and a description of the data the app handles. Publish a privacy policy page on your website and use these answers in Play Console → Data safety:
| Data | Collected | Purpose | Notes |
|---|---|---|---|
| Name, email, phone number | Yes | Account management, app functionality | Entered by the property manager or the user |
| Photos | Yes (optional) | App functionality | Repair photos, after photos |
| Signature image | Yes (optional) | App functionality | Agreement signing |
| Messages | Yes | App functionality, customer support | Repair messages, assistant chat |
| Payment info | No (in the app) | — | Payment happens on the website's payment page |
| Device / push token | Yes | App functionality | To send notifications |
| Location | No | — | Directions open the phone's maps app |
| Analytics, ads, tracking | No | — | No analytics or advertising libraries |
- Data is encrypted in transit (HTTPS).
- Data is not sold or shared with third parties for advertising.
- Users can ask the property manager to delete their account; mention this (with a contact email) in the privacy policy.
Android permissions used
| Permission | Why |
|---|---|
| INTERNET | Talk to your website |
| POST_NOTIFICATIONS | Show notifications (Android 13+ asks the user) |
| Camera / photos | Through the system picker only when the user adds a photo — no permission prompt on modern Android |
Manual Android settings
What setup.sh changes, for reference or for doing it by hand.
android/app/src/main/AndroidManifest.xml
<manifest ...>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application android:label="Acme Homes" ...>
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_notification"/>
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="smart_tenant_default"/>
...
</application>
<queries>
<intent><action android:name="android.intent.action.VIEW"/><data android:scheme="https"/></intent>
<intent><action android:name="android.intent.action.DIAL"/><data android:scheme="tel"/></intent>
...
</queries>
</manifest>
android/app/src/debug/AndroidManifest.xml (debug only)
<application android:usesCleartextTraffic="true"/>
android/app/build.gradle.kts
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
...
}
defaultConfig {
minSdk = maxOf(flutter.minSdkVersion, 23)
...
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
}
Notification icon
Copy assets/notification_icon/drawable-<size>.png to
android/app/src/main/res/drawable-<size>/ic_notification.png for mdpi, hdpi, xhdpi, xxhdpi and xxxhdpi.
App icon
dart run flutter_launcher_iconsCode structure
| Path | Contents |
|---|---|
lib/main.dart | Start-up, theme, chooses login / tenant / maintainer screens |
lib/config/app_config.dart | White-label settings |
lib/core/api_client.dart | HTTP client: token, JSON, errors, downloads |
lib/core/auth_store.dart | Sign-in state, restores the saved session |
lib/core/branding.dart | Logo, name and colours from the website |
lib/core/push_service.dart | Firebase notifications, unread badge, opening the right screen |
lib/core/json.dart | Helpers to read the API's JSON (money and dates come pre-formatted) |
lib/widgets/ | Shared widgets: loading/error/empty states, paged lists, status chips, brand logo |
lib/screens/auth/ | Login, forgot password, 2-factor code |
lib/screens/tenant/ | All tenant screens |
lib/screens/maintainer/ | All maintainer screens |
lib/screens/common/ | Profile, messages, notifications inbox and settings, in-app banner |
docs/API.md | Every API endpoint with parameters and responses |
Libraries used: dio (HTTP), provider (state), flutter_secure_storage (token), firebase_core / firebase_messaging / flutter_local_notifications (push), url_launcher, image_picker, path_provider, open_filex, signature, cached_network_image, flutter_launcher_icons.
To add a screen: create it in lib/screens/…, load data with context.read<ApiClient>().get('/your-endpoint'), and add the
endpoint on the website in routes/api.php (see docs/API.md for conventions).
Updating to a new version
When a new version of the app is released:
- Back up your project folder (especially
android/,lib/config/app_config.dartandassets/). - Update the website first if the release notes say the app needs a newer website version.
- Replace
lib/,pubspec.yaml,setup.sh,docs/anddocumentation/with the new files. Keep your ownandroid/folder, yourassets/images and put your values back intolib/config/app_config.dart. - Run
./setup.sh com.yourcompany "Your App Name"again (same values as before). It only adds missing settings and never changes your package name or signing. - Raise the version in
pubspec.yaml(see "Version numbers"), build and upload as usual.
Troubleshooting
| Problem | Solution |
|---|---|
./setup.sh: Permission denied | chmod +x setup.sh, or run bash setup.sh … |
| "Flutter is not installed" | Flutter's bin folder is not in PATH. Open a new terminal after changing PATH; check with flutter --version. |
flutter doctor: Android licences not accepted | flutter doctor --android-licenses and answer y. |
| "No connection" on every screen | Wrong apiBaseUrl, or the website is on http:// (release builds need HTTPS). Open …/api/v1/app-config in the phone's browser to check. |
| Emulator cannot reach a local website | Use 10.0.2.2 instead of localhost. |
| "The app is for tenants and maintainers" | The account is an owner/manager/admin; use the website or a tenant/maintainer account. |
| Gradle build fails: "Dependency requires core library desugaring" | Run ./setup.sh again (it adds desugaring) or apply the settings in Manual Android settings. |
| Gradle: "Unsupported class file major version" / Java errors | Use JDK 17 or newer: flutter config --jdk-dir "<Android Studio>/jbr". |
| Build very slow or out of memory | In android/gradle.properties set org.gradle.jvmargs=-Xmx4G; close other programs. |
| Play Console: "You uploaded an APK or Android App Bundle that was signed in debug mode" | Complete the signing steps, then build again. |
| Play Console: "Version code 1 has already been used" | Raise the +number in pubspec.yaml. |
| Play Console: package name already exists | Choose another package name (run setup.sh in a fresh copy with the new name). |
| No notifications | Settings → Mobile App shows three ticks? Package name in Firebase matches applicationId? App reopened after pasting? Notifications allowed in the phone's settings? Use "Send a test notification" — it shows the reason. |
| Notifications arrive late when the phone is idle | Battery optimisation on some brands (Xiaomi, Oppo, Huawei…). Users can set the app to "No restrictions" in battery settings. |
| Photos fail to upload | Raise PHP upload_max_filesize / post_max_size to 10M+ on the server. |
| Payment page does not open | Online payment must be enabled and configured for the owner on the website. |
| Old logo/colours shown | Close and reopen the app; it refreshes branding on start. |
FAQ
Do I need one app per property owner?
No. One app serves all companies on your website; after sign-in it shows the tenant's company branding.
Can owners or managers use the app?
Not in this version. They are directed to the website, which is fully mobile friendly.
Where is the data stored?
Only on your website/server. The phone keeps the login token (in secure storage) and the last branding.
Does the app work without the website?
No, every screen loads from your website's API.
Can I change the API without a new build?
The website address is built into the app. Branding and push settings are not — they come from the website.
How do payments work?
Pay now opens the website's secure payment page (Stripe/Razorpay) in the browser; card data never passes through the app. This is allowed by both stores because rent is a real-world service.
Can I publish the app under my own name?
Yes — your package name, app name, icon and Play developer account.
Do I need a Mac?
No, Android apps build on Windows, macOS and Linux.
Can I give testers the app before it is on Google Play?
Yes: Play Console internal testing, or share an APK.
Support & changelog
Before contacting support, please check the Troubleshooting section and run flutter doctor.
When you contact support, include:
- Your purchase code
- App version (
pubspec.yaml) and website version - Output of
flutter doctor -v - The exact error message or a screenshot
- What you did just before the problem
Support covers installation questions, bugs and help with the steps in this guide. Customisations (new features, design changes) are not included in support but can be ordered separately.
Changelog
| Version | Date | Changes |
|---|---|---|
| 1.0.0 | October 2026 | First release: tenant and maintainer apps, online payments, repairs with photos, assistant, agreements and inspections signing, deposit, documents, utility readings, notices, polls, bookings, visitor passes, schedule, push notifications and inbox, dynamic branding. |