Developer Onboarding Guide

This document provides a comprehensive guide for developers joining the RVC React Native Android project. Please read this thoroughly before making any changes to the codebase.


Table of Contents

  1. Project Overview

  2. Folder Structure

  3. Native Modules Implementation

  4. Setup & Installation

  5. Styling Guide

  6. Schema & Validation

  7. State Management

  8. API Structure

  9. Agora Implementation

  10. Deployment

  11. Critical Warnings - What NOT To Do


Project Overview

This is a bare React Native CLI application (NOT Expo) built for telemedicine/remote healthcare. It integrates with multiple medical devices via Bluetooth and provides video consultation capabilities.

Tech Stack:


Folder Structure


RVC_RN_Android/

├── android/ # Native Android code (DO NOT DELETE)

├── ios/ # iOS configuration

├── src/ # Main application source code

│ ├── api/ # API layer

│ │ ├── action/ # Mutation hooks (POST/PUT/DELETE)

│ │ ├── query/ # Query hooks (GET requests)

│ │ └── schema/ # API response TypeScript types

│ ├── assets/ # Static assets

│ │ ├── fonts/ # Custom fonts (Inter family)

│ │ ├── icons/ # App icons

│ │ └── images/ # Image assets

│ ├── components/ # Reusable UI components (120+)

│ │ ├── ui/ # Base UI components

│ │ ├── Devices/ # Device-specific components

│ │ ├── DiabetesDiary/ # Diabetes management components

│ │ └── [feature]/ # Feature-specific components

│ ├── constant/ # App constants and enums

│ ├── i18n/ # Internationalization

│ │ └── translations/ # Language files (en, de, es, ar)

│ ├── nativemodules/ # JS bridges for native modules

│ │ ├── HealthConnect/ # Google Health Connect bridge

│ │ ├── MinttiVision/ # Mintti medical device bridge

│ │ ├── OTGCamera/ # OTG camera bridge

│ │ ├── ScreenRecorder/ # Screen recorder bridge

│ │ └── SmarthoStethoScope/ # Stethoscope device bridge

│ ├── screens/ # Screen components (60+)

│ ├── styles/ # Global StyleSheet definitions

│ └── utils/ # Utilities and helpers

│ ├── store/ # Zustand stores (17 files)

│ ├── hook/ # Custom React hooks

│ ├── schema/ # Zod validation schemas

│ ├── AppNavigation.tsx # Navigation configuration

│ ├── config.ts # API base URL configuration

│ └── mmkv.ts # MMKV storage setup

├── App.tsx # Root component

├── index.js # Entry point

├── package.json # Dependencies

├── tailwind.config.js # NativeWind/Tailwind configuration

├── babel.config.js # Babel configuration

├── metro.config.js # Metro bundler configuration

└── tsconfig.json # TypeScript configuration

Folder Purpose Breakdown

| Folder | Purpose |

| -------------------- | --------------------------------------------------------------------------------------------------------------------- |

| src/api/action/ | Contains mutation hooks using TanStack Query for POST/PUT/DELETE operations (e.g., useSignIn, useBookAppointment) |

| src/api/query/ | Contains query hooks for GET operations with caching (e.g., useGetAllAppointments, useGetCurrentUserById) |

| src/api/schema/ | TypeScript interfaces/types for API responses |

| src/components/ | Reusable components organized by feature/domain |

| src/components/ui/ | Base UI building blocks (buttons, inputs, modals) |

| src/nativemodules/ | JavaScript bridges that communicate with native Android modules |

| src/screens/ | Full-screen components mapped to navigation routes |

| src/utils/store/ | Zustand stores for client-side state management |

| src/utils/hook/ | Custom hooks for permissions, gestures, device verification |

| src/utils/schema/ | Zod schemas for form validation |

| src/constant/ | Static values, enums, configuration constants |

| src/i18n/ | i18next setup and translation JSON files |

| android/ | Native Android code including custom native modules |


Native Modules Implementation

This app contains custom native modules written in Kotlin/Java that are critical for medical device integration. These cannot be regenerated automatically.

Location of Native Modules


android/app/src/main/java/com/eclinic/

├── MainActivity.kt # Main activity with Health Connect setup

├── MainApplication.kt # React package registration

├── VisionModule.kt # Mintti Vision device module

├── SmarthoModule.kt # Stethoscope device module

├── OTGCameraController.kt # OTG camera integration

├── ScreenRecorderController.kt # Screen recording functionality

├── ScreenRecorderService.kt # Background recording service

├── NotificationHelper.kt # Notification management

├── SmartDevicesPackage.kt # Module registration package

├── SmarthoViewManager.kt # Native view for stethoscope graphs

├── VisionViewManager.kt # Native view for vision module

├── BoGraphViewManager.kt # Blood pressure graph view

└── EcgChartViewManager.kt # ECG waveform visualization

Native Modules Overview

1. VisionModule (Mintti Vision Medical Device)

Provides Bluetooth Low Energy integration with the Mintti Vision multi-function medical device.

Capabilities:

Key Methods:


measureBloodPressure()

measureBloodGlucose()

measureBloodOxygenSaturation()

measureECG()

measureBodyTemperature()

scanDevices()

connectToDevice(macAddress)

Events Emitted:

2. SmarthoModule (Stethoscope Device)

Handles Bluetooth stethoscope device communication.

Capabilities:

Events Emitted:

3. OTGCameraController

Manages USB OTG camera devices for dental/dermatology imaging.

4. ScreenRecorderController

Provides screen recording capabilities with notification handling.

JavaScript Bridge Files

Located in src/nativemodules/:


// Example: src/nativemodules/MinttiVision/useMinttiVision.ts

import {NativeModules, NativeEventEmitter} from  'react-native';

const {VisionModule} = NativeModules;

const  eventEmitter = new  NativeEventEmitter(VisionModule);

  

// Hook provides access to native methods and event listeners

Android Gradle Module Structure

The android folder contains multiple Gradle modules:


Setup & Installation

Prerequisites

Installation Steps

  1. Clone the repository

git clone <repository-url>

cd RVC_RN_Android

  1. Install dependencies

npm install

  1. Android SDK Setup
  1. Run the app

# Start Metro bundler

npm start

  

# In another terminal, build and run

npm run android

Environment Configuration

API base URL is configured in src/utils/config.ts:


export  const  BASE_URL = 'https://care.remotemedtech.com/api';

Required Permissions (Android)

The app requires these permissions (already configured in AndroidManifest.xml):


Styling Guide

Primary: NativeWind (Tailwind CSS)

This project uses NativeWind 2.0.11 for styling, which brings Tailwind CSS utility classes to React Native.

Configuration: tailwind.config.js


module.exports = {

content: ['./App.{js,jsx,ts,tsx}', './src/**/*.{js,jsx,ts,tsx}'],

theme: {

extend: {

colors: {

primary:  '#46b98d', // Green - main brand color

secondary:  '#60A5FA', // Blue

accent:  '#fc5e53', // Red/Orange - alerts/warnings

text:  '#02200a', // Dark green - primary text

background:  '#f9fafb', // Light gray - backgrounds

},

},

},

};

Usage Example:


import {View, Text} from  'react-native';

  

export  const  MyComponent = () => (

<View  className="flex-1 bg-background p-4">

<Text  className="text-lg font-bold text-primary">Hello World</Text>

<View  className="mt-4 rounded-lg bg-white p-4 shadow-md">

<Text  className="text-text">Content here</Text>

</View>

</View>

);

Secondary: React Native StyleSheet

For complex or dynamic styles, use StyleSheet from src/styles/style.ts:


import {StyleSheet} from  'react-native';

  

export  const  GlobalStyles = StyleSheet.create({

// Font styles

fontRegular: {fontFamily:  'Inter-Regular'},

fontSemiBold: {fontFamily:  'Inter-SemiBold'},

fontBold: {fontFamily:  'Inter-Bold'},

fontMedium: {fontFamily:  'Inter-Medium'},

  

// Shadow effects

shadowLight: {

shadowColor:  '#000',

shadowOffset: {width:  0, height:  2},

shadowOpacity:  0.1,

shadowRadius:  4,

elevation:  3,

},

});

Available Fonts


Schema & Validation

Zod for Schema Validation

This project uses Zod for runtime type validation, particularly for forms.

Location: src/utils/schema/

Example: Login Schema


// src/utils/schema/loginSchema.ts

import {z} from  'zod';

  

export  const  loginSchema = z.object({

username:  z.string().min(3, 'Username must be at least 3 characters'),

password:  z.string().min(8, 'Password must be at least 8 characters'),

});

  

export  type  LoginFormData = z.infer<typeof  loginSchema>;

Example: Diabetes Diary Schemas


// src/utils/schema/diary.schema.ts

import {z} from  'zod';

  

export  const  BolusInsulinSchema = z.object({

dose:  z.number().positive(),

date:  z.date(),

});

  

export  const  BloodGlucoseSchema = z.object({

glucoseValue:  z.number().positive(),

date:  z.date(),

});

Integration with React Hook Form


import {useForm} from  'react-hook-form';

import {zodResolver} from  '@hookform/resolvers/zod';

import {loginSchema, LoginFormData} from  '@/utils/schema/loginSchema';

  

const {

control,

handleSubmit,

formState: {errors},

} = useForm<LoginFormData>({

resolver:  zodResolver(loginSchema),

});

API Response Types

Located in src/api/schema/:


State Management

Client State: Zustand

Location: src/utils/store/

Zustand is used for lightweight, performant client-side state management.

Key Stores:

| Store | Purpose |

| --------------------------- | ----------------------------------------- |

| useSignInStore | User authentication (persisted with MMKV) |

| useMinttiVisionStore | Medical device state, measurements |

| useLanguageStore | App language preference |

| useMeetingStore | Video call/meeting state |

| useBookAppointmentStore | Appointment booking form |

| useDiabetesDiaryDateStore | Diary date filtering |

Example Store:


// src/utils/store/useLanguageStore.ts

import {create} from  'zustand';

import {persist} from  'zustand/middleware';

import {zustandStorage} from  '../mmkv';

  

interface  LanguageStore {

language: string;

setLanguage: (lang: string) =>  void;

}

  

export  const  useLanguageStore = create<LanguageStore>()(

persist(

set  => ({

language:  'en',

setLanguage:  lang  =>  set({language:  lang}),

}),

{

name:  'language-storage',

storage:  zustandStorage,

},

),

);

Server State: TanStack React Query

Used for caching, synchronization, and server state management.

Query Example:


// src/api/query/useGetAllAppointments.ts

import {useQuery} from  '@tanstack/react-query';

  

export  const  useGetAllAppointments = () => {

return  useQuery({

queryKey: ['appointments'],

queryFn: () =>  api.get('/appointments'),

});

};

Mutation Example:


// src/api/action/useBookAppointment.ts

import {useMutation, useQueryClient} from  '@tanstack/react-query';

  

export  const  useBookAppointment = () => {

const  queryClient = useQueryClient();

  

return  useMutation({

mutationFn:  data  =>  api.post('/appointments', data),

onSuccess: () => {

queryClient.invalidateQueries({queryKey: ['appointments']});

},

});

};

Persistent Storage: MMKV

MMKV is used for fast, persistent local storage.


// src/utils/mmkv.ts

import {MMKV} from  'react-native-mmkv';

  

export  const  storage = new  MMKV();

  

// Zustand storage adapter

export  const  zustandStorage = {

getItem: (name: string) =>  storage.getString(name) ?? null,

setItem: (name: string, value: string) =>  storage.set(name, value),

removeItem: (name: string) =>  storage.delete(name),

};


API Structure

Base Configuration


// src/utils/config.ts

export  const  BASE_URL = 'https://care.remotemedtech.com/api';

Query Hooks (GET requests)

Located in src/api/query/:

Action Hooks (POST/PUT/DELETE)

Located in src/api/action/:


Agora Implementation (Video Calls & Chat)

The app uses Agora RTC SDK for real-time video consultations and Agora RTM SDK for in-app messaging between patients and doctors.

Configuration Setup

The Agora configuration file is gitignored to protect credentials. You must create it manually.

Step 1: Rename or create the config file:


# If an example file exists:

cp  src/constant/agoraConfig.example.ts  src/constant/agoraConfig.ts

  

# Or create it manually

touch  src/constant/agoraConfig.ts

Step 2: Add your Agora credentials to src/constant/agoraConfig.ts:


import {VideoContentHint} from  'react-native-agora';

  

function  generateRandomLargeNumber(

type: 'screen-sharing' | 'dental-cam-android' | 'dental-cam-ios',

): number {

let  min: number;

let  max: number;

switch (type) {

case  'screen-sharing':

min = 10000000;

max = 10000099;

break;

case  'dental-cam-android':

min = 10000100;

max = 10000199;

break;

case  'dental-cam-ios':

min = 10000200;

max = 10000299;

break;

default:

throw  new  Error('Invalid type passed');

}

return  Math.floor(Math.random() * (max - min + 1)) + min;

}

  

// Replace with your Agora credentials

const  agoraConfig = {

appId:  'YOUR_AGORA_APP_ID',

screenSharingUID:  generateRandomLargeNumber('screen-sharing'),

dentalCamUID:  generateRandomLargeNumber('dental-cam-ios'),

product:  null  as  any,

};

  

const  agoraChatConfig = {

APP_KEY:  'YOUR_AGORA_CHAT_APP_KEY',

WS_ADDRESS:  'YOUR_WEBSOCKET_ADDRESS',

REST_API:  'YOUR_REST_API_ADDRESS',

};

  

const  screenSharingConfig = {

sampleRate:  16000,

channels:  2,

captureSignalVolume:  0,

width:  640,

height:  360,

frameRate:  10,

bitrate:  500,

contentHint:  VideoContentHint.ContentHintNone,

captureAudio:  true,

captureVideo:  true,

};

  

export {agoraChatConfig, agoraConfig, screenSharingConfig};

Getting Agora Credentials

  1. Go to Agora Console

  2. Create a new project or select existing one

  3. Copy the App ID from project settings

  4. Enable Agora Chat if using messaging features

  5. Get Chat credentials (APP_KEY, WS_ADDRESS, REST_API) from Chat settings

Key Files

| File | Purpose |

| ---------------------------------------- | ----------------------------------------- |

| src/constant/agoraConfig.ts | Agora credentials and config (gitignored) |

| src/screens/AppointmentMeeting.tsx | Video call screen implementation |

| src/utils/hook/useRtm.tsx | RTM (Real-time Messaging) hook |

| src/components/RemoteUserContainer.tsx | Remote participant video view |

| src/utils/store/useMeetingStore.ts | Video call state management |

Features

Important Notes


Deployment

This app is not deployed to the Google Play Store. Instead, universal APKs are built and uploaded to a web server for direct download.

App Variants

There are two app variants that share the same codebase but have different branding:

| Variant | App Name | Target Users | Package Name |

| ---------- | ---------- | ------------ | -------------------- |

| Care | RVC Care | Patients | com.eclinic.care |

| Clinic | RVC Clinic | Clinicians | com.eclinic.clinic |

Each variant has its own:

Asset Configuration

When building for a specific variant, you must update the following assets:

1. App Icon

Location: android/app/src/main/res/

Replace the icon files in the following directories:


android/app/src/main/res/

├── mipmap-hdpi/

│ └── ic_launcher.png # 72x72 px

├── mipmap-mdpi/

│ └── ic_launcher.png # 48x48 px

├── mipmap-xhdpi/

│ └── ic_launcher.png # 96x96 px

├── mipmap-xxhdpi/

│ └── ic_launcher.png # 144x144 px

├── mipmap-xxxhdpi/

│ └── ic_launcher.png # 192x192 px

└── mipmap-anydpi-v26/

└── ic_launcher.xml # Adaptive icon config

Asset files are provided in: docs/assets

2. Splash Screen

Location: android/app/src/main/res/drawable/

Replace the splash screen image:


android/app/src/main/res/drawable/

└── launch_screen.png # Splash screen image

Asset files are provided in: docs/assets

3. App Name

Location: android/app/src/main/res/values/strings.xml

Update the app name:


<resources>

<string  name="app_name">RVC Care</string>  <!-- or "RVC Clinic" -->

</resources>

Building the APK

Step 1: Update Assets for Target Variant

Copy the appropriate assets for your target variant (Care or Clinic) as described above.

Step 2: Build Universal APK


# Navigate to android directory

cd  android

  

# Clean previous builds

./gradlew  clean

  

# Build release APK

./gradlew  assembleRelease

The APK will be generated at:


android/app/build/outputs/apk/release/app-release.apk

Step 3: Build Universal APK (Alternative)

For a universal APK that works on all architectures:


cd  android

./gradlew  assembleRelease  -PuniversalApk=true

Signing the APK

The release APK must be signed. Signing configuration is in android/app/build.gradle:


android {

signingConfigs {

release {

storeFile file('keystore/release.keystore')

storePassword System.getenv("KEYSTORE_PASSWORD")

keyAlias System.getenv("KEY_ALIAS")

keyPassword System.getenv("KEY_PASSWORD")

}

}

}

Note: Never commit keystore files or passwords to version control.

Uploading to Web Server

After building the APK:

  1. Rename the APK with version information:

mv app-release.apk rvc-care-v1.2.3.apk

# or

mv app-release.apk rvc-clinic-v1.2.3.apk

  1. Upload to the designated web server

  2. Update the download link on the distribution page

Deployment Checklist

Before deploying a new version:


Critical Warnings - What NOT To Do

1. NEVER Delete the android/ Folder

Unlike Expo projects, this bare React Native app contains custom native modules that cannot be regenerated.

What you will lose:

If accidentally deleted: You will need to restore from git or manually rewrite all native code.

2. Do NOT Run npx react-native eject or Similar Commands

This app is already a bare React Native project. Running eject commands may corrupt the native setup.

3. Do NOT Upgrade React Native Without Testing Native Modules

Before upgrading React Native version:

  1. Create a backup branch

  2. Test all native modules after upgrade

  3. Check Gradle configurations for compatibility

  4. Verify all SDK integrations still work

4. Do NOT Modify Native SDKs Directly

The smartho-sdk and vision-sdk modules in the android folder are third-party SDKs. Do not modify them directly. Contact the vendor for updates.

5. Do NOT Remove Health Connect Permissions from MainActivity

The MainActivity.kt contains critical Health Connect permission setup. Removing it will break Google Health Connect integration.

6. Do NOT Use Expo-Specific Packages

This is a bare React Native CLI project. Expo packages (expo-, @expo/) are NOT compatible and will cause build failures.

7. Do NOT Commit Sensitive Data

Never commit:

8. Do NOT Ignore TypeScript Errors

All code must pass TypeScript checks. Run npm run lint before committing.

9. Do NOT Mix Styling Approaches Inconsistently

Use NativeWind (className) for standard styling. Only use StyleSheet for complex/dynamic styles or styles that NativeWind cannot handle.

10. Do NOT Skip Testing on Physical Devices

Bluetooth and medical device features ONLY work on physical Android devices. Always test on real hardware before submitting PRs for device-related features.


Quick Reference

| Task | Command |

| -------------------- | ------------------------------- |

| Install dependencies | npm install |

| Start Metro bundler | npm start |

| Run Android app | npm run android |

| Run iOS app | npm run ios |

| Lint code | npm run lint |

| Run tests | npm test |

| Clean Android build | cd android && ./gradlew clean |


Last updated: January 2026