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.
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:
React Native 0.73.4
TypeScript 5.0.4
NativeWind (Tailwind CSS) for styling
Zustand for state management
TanStack React Query for server state
Zod for schema validation
i18next for internationalization (4 languages)
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 |
| -------------------- | --------------------------------------------------------------------------------------------------------------------- |
| 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 |
This app contains custom native modules written in Kotlin/Java that are critical for medical device integration. These cannot be regenerated automatically.
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
Provides Bluetooth Low Energy integration with the Mintti Vision multi-function medical device.
Capabilities:
Blood pressure measurement
Blood glucose monitoring
SpO2 (blood oxygen saturation)
ECG measurements
Body temperature
Battery monitoring
Key Methods:
measureBloodPressure()
measureBloodGlucose()
measureBloodOxygenSaturation()
measureECG()
measureBodyTemperature()
scanDevices()
connectToDevice(macAddress)
Events Emitted:
onBp, onBpRaw - Blood pressure data
onSpo2, onSpo2Result - Oxygen saturation
onEcg - ECG waveform data
onBgEvent, onBgResult - Blood glucose
Handles Bluetooth stethoscope device communication.
Capabilities:
Device scanning and connection
Heart/lung sound recording
Real-time waveform data
Heart rate detection
PCM audio file export
Events Emitted:
onScanResult - Device discovery
onHeartRate - Heart rate data
onProcessData - Waveform data
onDisconnected - Connection lost
Manages USB OTG camera devices for dental/dermatology imaging.
Provides screen recording capabilities with notification handling.
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
The android folder contains multiple Gradle modules:
smartho-sdk - Stethoscope SDK library
vision-sdk - Medical device SDK library
smarthomodule - Stethoscope React Native module
visionmodule - Vision React Native module
otg-camera - OTG camera module
Node.js >= 18
JDK 17
Android Studio with Android SDK
React Native CLI (NOT Expo CLI)
git clone <repository-url>
cd RVC_RN_Android
npm install
Open Android Studio
Ensure Android SDK 34 is installed
Configure ANDROID_HOME environment variable
# Start Metro bundler
npm start
# In another terminal, build and run
npm run android
API base URL is configured in src/utils/config.ts:
export const BASE_URL = 'https://care.remotemedtech.com/api';
The app requires these permissions (already configured in AndroidManifest.xml):
Bluetooth (BLE scanning and connection)
Camera (for OTG camera and video calls)
Microphone (for video calls and stethoscope)
Location (required for BLE on Android)
Storage (for saving recordings and documents)
Health Connect (for health data sync)
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>
);
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,
},
});
Inter-Regular
Inter-SemiBold
Inter-Bold
Inter-Medium
Inter-Thin
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(),
});
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),
});
Located in src/api/schema/:
Appointment.ts - Appointment data structure
Doctor.ts - Doctor information
Documents.ts - Document management
Test.ts - Test information
TestPlan.ts - Test plan structure
TestPlanResult.ts - Test results
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,
},
),
);
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']});
},
});
};
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),
};
// src/utils/config.ts
export const BASE_URL = 'https://care.remotemedtech.com/api';
Located in src/api/query/:
useGetAllAppointments
useGetAppointmentDetails
useGetCurrentUserById
useGetAllDiaryResult
useGetDiabetesDiary
useGetNotifications
useGetPatientDoctors
useGetSelfTestResults
useGetDoctorTimingSlots
useGetTestPlanByDate
And 20+ more…
Located in src/api/action/:
useSignIn
useBookAppointment
useCancelAppointment
useRescheduleAppointment
useSaveTestResult
useUploadDocument
useUpdateProfile
useTalkToAiAssistant
And 40+ more…
The app uses Agora RTC SDK for real-time video consultations and Agora RTM SDK for in-app messaging between patients and doctors.
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};
Go to Agora Console
Create a new project or select existing one
Copy the App ID from project settings
Enable Agora Chat if using messaging features
Get Chat credentials (APP_KEY, WS_ADDRESS, REST_API) from Chat settings
| 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 |
Video Consultations: Real-time video calls between patients and doctors
Screen Sharing: Share device screen during consultations
Dental Camera Streaming: Stream from dental camera devices
In-app Chat: Text messaging via Agora RTM
Never commit agoraConfig.ts to version control
The file is listed in .gitignore
This app is not deployed to the Google Play Store. Instead, universal APKs are built and uploaded to a web server for direct download.
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:
App name (displayed on device)
App icon
Splash screen
When building for a specific variant, you must update the following assets:
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
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
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>
Copy the appropriate assets for your target variant (Care or Clinic) as described above.
# 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
For a universal APK that works on all architectures:
cd android
./gradlew assembleRelease -PuniversalApk=true
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.
After building the APK:
mv app-release.apk rvc-care-v1.2.3.apk
# or
mv app-release.apk rvc-clinic-v1.2.3.apk
Upload to the designated web server
Update the download link on the distribution page
Before deploying a new version:
Update version code and name in
android/app/build.gradle
Verify correct assets (icon, splash) for target variant
Verify correct app name in strings.xml
Run npm run lint and fix any issues
Test on physical device (especially Bluetooth features)
Build signed release APK
Test the signed APK on a clean device
Upload to web server
Verify download link works
android/ Folder
Unlike Expo projects, this bare React Native app contains custom native modules that cannot be regenerated.
What you will lose:
VisionModule (Mintti medical device integration)
SmarthoModule (Stethoscope device)
OTGCameraController
ScreenRecorderController
All native view managers (ECG charts, BP graphs)
Custom SDK integrations (smartho-sdk, vision-sdk)
Health Connect configuration in MainActivity
If accidentally deleted: You will need to restore from git or manually rewrite all native code.
npx react-native eject or Similar Commands
This app is already a bare React Native project. Running eject commands may corrupt the native setup.
Before upgrading React Native version:
Create a backup branch
Test all native modules after upgrade
Check Gradle configurations for compatibility
Verify all SDK integrations still work
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.
The MainActivity.kt contains critical Health Connect
permission setup. Removing it will break Google Health Connect
integration.
This is a bare React Native CLI project. Expo packages (expo-, @expo/) are NOT compatible and will cause build failures.
Never commit:
API keys or secrets
.env files with production credentials
User data or health information
Debug keystores with production credentials
All code must pass TypeScript checks. Run
npm run lint before committing.
Use NativeWind (className) for standard styling. Only use StyleSheet for complex/dynamic styles or styles that NativeWind cannot handle.
Bluetooth and medical device features ONLY work on physical Android devices. Always test on real hardware before submitting PRs for device-related features.
| 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