Android Repository - Structure Analysis¶
Repository: Psyter Android Client
Analysis Date: November 6, 2025
Version: 2.0.15 (Build 50)
Analyst: Development Team
Table of Contents¶
- Architecture Overview
- High-Level Component Diagram
- Package Structure
- Layer Architecture
- Key Components Analysis
- Data Flow Architecture
- Navigation Architecture
- Design Patterns
- Component Relationships
- Technical Architecture
Architecture Overview¶
Architecture Style¶
Hybrid MVC with Repository Pattern
The Android client uses a hybrid architecture combining:
- MVC (Model-View-Controller) - Primary pattern
- Activities/Fragments = View + Controller
- DataModels = Model
- Adapters = View helpers
- Repository Pattern - Data access abstraction (partial implementation)
- Observer Pattern - UI updates via callbacks and interfaces
- Singleton Pattern - Utility classes (Utils, GlobalData, MySharedPreferences)
Architectural Characteristics¶
- ✅ Modular Package Structure - Feature-based organization
- ✅ Separation of Concerns - UI, data, and business logic separated
- ⚠️ Tight Coupling - Heavy reliance on static Utils class
- ⚠️ God Objects - Some Activities exceed 1000 lines (e.g., SplashActivity ~850 lines)
- ⚠️ Mixed Responsibilities - CareProvider code in Client app
- ❌ No Dependency Injection - Manual object creation throughout
High-Level Component Diagram¶
┌────────────────────────────────────────────────────────────────┐
│ Psyter Android Client │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Presentation Layer │ │
│ │ ┌──────────────┬──────────────┬──────────────┐ │ │
│ │ │ Activities │ Fragments │ Adapters │ │ │
│ │ │ (44+) │ (44+) │ (60+) │ │ │
│ │ └──────────────┴──────────────┴──────────────┘ │ │
│ │ │ │
│ │ Package Groups: │ │
│ │ • Registration (Auth, Onboarding) │ │
│ │ • Client (Patient Features) │ │
│ │ • CareProvider (Provider Features - Legacy) │ │
│ │ • CommonUser (Shared Features) │ │
│ │ • Collaboration (Video Calls) │ │
│ │ • Scheduling (Appointments) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Business Logic Layer │ │
│ │ ┌──────────────┬──────────────┬──────────────┐ │ │
│ │ │ Interfaces │ Listeners │ Validators │ │ │
│ │ └──────────────┴──────────────┴──────────────┘ │ │
│ │ • UpdateProfileStatusListener │ │
│ │ • OnClickRecyclerView │ │
│ │ • MPInterfaceCollaboration │ │
│ │ • Observer (custom) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Data Layer │ │
│ │ ┌──────────────┬──────────────┬──────────────┐ │ │
│ │ │ DataModels │ Repositories │ Storage │ │ │
│ │ │ (150+) │ (Limited) │ │ │ │
│ │ └──────────────┴──────────────┴──────────────┘ │ │
│ │ • RegisterModel, CarePDataModel │ │
│ │ • BookingsDataModel, SlotsDataModel │ │
│ │ • ConversationListModel │ │
│ │ • MySharedPreferences (Local Storage) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Infrastructure Layer │ │
│ │ ┌──────────────┬──────────────┬──────────────┐ │ │
│ │ │ Networking │ Firebase │ WebRTC │ │ │
│ │ └──────────────┴──────────────┴──────────────┘ │ │
│ │ • AndroidNetworking (REST API) │ │
│ │ • WebSocket (Presence & Collaboration) │ │
│ │ • Firebase (Auth, FCM, Crashlytics) │ │
│ │ • PeerConnection (Video/Audio) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Utility & Helpers Layer │ │
│ │ ┌──────────────┬──────────────┬──────────────┐ │ │
│ │ │ Utils (God) │ Permissions │ Localization│ │ │
│ │ └──────────────┴──────────────┴──────────────┘ │ │
│ │ • Utils.java (2000+ lines) │ │
│ │ • LocaleUtils, LangHelper (i18n) │ │
│ │ • clsStoragePermission, clsCameraPermission │ │
│ │ • TransparentProgressDialog │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
External Dependencies:
┌──────────────┬──────────────┬──────────────┬──────────────┐
│ Backend APIs │ WebSocket │ Firebase │ Payment GW │
│ (REST) │ Server │ Services │ (WebView) │
└──────────────┴──────────────┴──────────────┴──────────────┘
Package Structure¶
Root Package: com.psyter.www¶
com.psyter.www/
├── Registration/ # Authentication & Onboarding
│ ├── Activities/
│ │ ├── SplashActivity # App entry point (~850 lines)
│ │ ├── LoginActivity # User login (~980 lines)
│ │ ├── UserSelectionActivity # Client vs Provider selection
│ │ ├── RegisterCareProviderActivity # Provider registration
│ │ ├── QuestionaireActivity # Screening questionnaire
│ │ └── VerifyAccountActivity # Email verification
│ ├── Adapters/
│ │ ├── ContriesDropDownAdapter # Country selector
│ │ ├── GenericDropDownAdapter # Generic dropdown
│ │ ├── SearchableAdapter # Searchable lists
│ │ ├── SlotsGridAdapter # Time slot grid
│ │ └── GridAdapter # Generic grid adapter
│ └── DataModel/
│ ├── CountriesDataModel # Country data
│ ├── ScreeningQusDataModel # Questionnaire questions
│ ├── ScreeningAnsDataModel # Questionnaire answers
│ ├── EventObjects # Event data
│ ├── HistoryDataModel # History data
│ └── attendanceDetailDataModel # Attendance tracking
│
├── Client/ # Patient/Client Features
│ ├── Activities/
│ │ ├── HomeWrokSubmitActivity # Submit homework assignments
│ │ ├── PaymentWebActivity # Payment gateway WebView
│ │ ├── PDFviewerActivity # View prescriptions/documents
│ │ ├── ViewDocWebActivity # Document viewer
│ │ ├── BlogsActivity # Educational content
│ │ ├── BlogDetailsActivity # Blog post details
│ │ ├── NotificationsActivity # Notification center
│ │ └── AddUpdateDiaryActivity # Diary entry CRUD
│ ├── Fragments/
│ │ ├── MainFragmentClient # Home dashboard
│ │ ├── FindCPFragment # Search providers (~800 lines)
│ │ ├── MyCPFragment # My providers list
│ │ ├── MyProfileFragmentClient # User profile
│ │ ├── MyDiaryFragment # Mental health diary
│ │ ├── MyHomeWorkFragment # Homework assignments
│ │ ├── MyQyestionaireFragment # Questionnaires (~1500 lines)
│ │ ├── QuestionnaireFragment # Questionnaire taking
│ │ ├── ReferralsFragment # Referrals management
│ │ └── BookSlotActivity # Appointment booking
│ ├── BookSlots/
│ │ ├── MonthViewClient # Calendar month view
│ │ ├── SelectSlotActivity # Time slot selection
│ │ └── SlotPaymentSuggestActivity # Payment suggestions
│ ├── Adapters/
│ │ ├── CarePListAdapter # Provider list adapter
│ │ ├── DiaryAdapter # Diary entries adapter
│ │ ├── HomeWorkAdapter # Homework adapter
│ │ ├── QuestionnaireAdapter # Questionnaire adapter
│ │ └── BlogAdapter # Blog posts adapter
│ └── DataModels/
│ ├── BlogModel # Blog post data
│ ├── HomeWorkListDataModel # Homework data
│ ├── DiaryDataModel # Diary entry data
│ └── NotificationDataModel # Notification data
│
├── CareProvider/ # Provider Features (Legacy in Client app)
│ ├── Activities/
│ │ ├── BaseClientActivityMain # Main navigation activity (~1400 lines)
│ │ ├── ChatMainActivity # Chat interface
│ │ ├── ConversationActivity # Conversation view
│ │ ├── ClientHistoryActivity # Client history
│ │ ├── CPHistoryActivity # Provider history
│ │ ├── PrescriptionActivity # Create prescriptions
│ │ ├── NewHomeWorkActivity # Assign homework
│ │ ├── HomeWorkCheckActivity # Review homework
│ │ ├── HomeworkFeedbackHistoryActivity # Homework feedback
│ │ ├── InitialAssessmentAcitivity # Initial assessment
│ │ ├── FilledAssessmentViewActivity # View assessment
│ │ ├── AddPromoCodeActivity # Promo code management
│ │ ├── ReferralActivity # Referral management
│ │ ├── PaymentsDetailActivity # Payment details
│ │ ├── ReserveSlotActivity # Reserve appointment slots
│ │ └── CarePListingFiltersActivity # Provider filters
│ ├── Fragments/
│ │ ├── MainFragment # Provider home
│ │ ├── MyProfileFragment # Provider profile
│ │ ├── MyAppointFragment # Appointments
│ │ ├── MyClientsFragment # Client list
│ │ ├── PersonalInfoFragment # Personal info editing
│ │ ├── ContactInfoFragment # Contact info
│ │ ├── EducationInfoFragment # Education details
│ │ ├── CurrentJobFragment # Job information
│ │ ├── VideoBioFragment # Video biography
│ │ ├── ManageServicesFragment # Service management
│ │ ├── ManageSessionDurationFragment # Session settings
│ │ ├── ManageAccessFragment # Access control
│ │ ├── MyPreferFragment # Preferences
│ │ ├── PaymentMethodFragment # Payment setup
│ │ ├── PaymentInfoFragment # Payment info
│ │ ├── PromoCodeFragment # Promo codes
│ │ ├── PrescriptionCPAddFragment # Add prescription
│ │ ├── PrescriptionListFragment # Prescription list
│ │ ├── SaudiCommesionFragment # Saudi commission info
│ │ ├── MedicalSourceFragment # Medical resources
│ │ ├── PrivacyPolicyFragment # Privacy policy
│ │ ├── WebviewFragment # WebView container
│ │ └── ReservationFragment # Reservations
│ ├── Schedule/
│ │ ├── MonthViewFragment # Calendar for providers
│ │ ├── MarkAvailabiltyActivity # Mark availability
│ │ ├── CalendarCareProviderView # Calendar view
│ │ ├── CustomTimePickerDialog # Time picker
│ │ ├── CustomTimePickerDialogClock # Clock picker
│ │ └── Adapter/
│ │ ├── GridAdapterMonthCP # Month grid adapter
│ │ └── MarkedSlotsRecyclerAdapter # Marked slots
│ ├── Adapters/
│ │ ├── MyAppointAdapter # Appointments adapter
│ │ ├── MyClientsAdapter # Clients adapter
│ │ ├── PrescriptionAdapter # Prescriptions adapter
│ │ └── PromoCodeAdapter # Promo codes adapter
│ ├── DataModels/
│ │ ├── WorkInfoDataModel # Work information
│ │ ├── ConversationListModel # Conversations
│ │ ├── FeedbackDataModel # Feedback data
│ │ ├── PromoCodeDataModel # Promo code data
│ │ └── DialogType # Dialog types
│ └── Interfaces/
│ ├── UpdateProfileStatusListener # Profile update callback
│ ├── OnShowPrescription # Prescription callback
│ ├── OnSelectMedicine # Medicine selection
│ ├── OnSelectMedicineDiagnose # Diagnosis selection
│ ├── OnClickRecyclerView # RecyclerView click handler
│ ├── OnAddPrescriptionValue # Add prescription callback
│ └── OnSelectDeleteAllergy # Allergy selection
│
├── CommonUser/ # Shared Client/Provider Features
│ ├── Activities/
│ │ ├── CarePListActivity # Provider search/list (~600 lines)
│ │ ├── CarePDetailActivity # Provider profile (~900 lines)
│ │ ├── LoginRegisterActivity # Login/Register choice
│ │ ├── ForgotPasswordActivity # Password recovery
│ │ ├── ResetPasswordActivity # Password reset
│ │ ├── VerifyEmailActivity # Email verification
│ │ ├── MedicalSourcesActivity # Medical resources
│ │ ├── ScheduleSessionActivity # Session scheduling
│ │ └── RateCareProviderActivity # Rate provider
│ ├── Adapters/
│ │ ├── CarePListAdapter # Provider list
│ │ ├── ScheduleAdapter # Schedule adapter
│ │ └── MedicalSourcesAdapter # Resources adapter
│ └── DataModel/
│ ├── CarePDataModel # Provider data (~50 fields)
│ ├── RegisterModel # Registration data
│ ├── ScheduleDataModel # Schedule data
│ └── MedicalSourceModel # Resource data
│
├── Collaboration/ # WebRTC Video Calls
│ ├── Presence/
│ │ ├── CollaborationMain # Video call activity (~3000 lines!)
│ │ ├── IncomingCall # Incoming call screen
│ │ ├── WebAPICall # ICE server config
│ │ └── ManagePresenceeClient # WebSocket presence manager (~1500 lines)
│ └── Common/
│ ├── GlobalData # Global state (singleton)
│ ├── MessagesListAdapter # Chat messages
│ ├── ReceivedMessage # Message model
│ ├── UserInfo # User info model
│ ├── WebRTCClient # WebRTC wrapper (if exists)
│ └── SignalingClient # Signaling logic
│
├── Scheduling/ # Appointment Scheduling
│ ├── WeeklySchedule/
│ │ └── WeeklyScheduleFragment # Weekly calendar (~2700 lines!)
│ └── DataModels/
│ ├── BookingsDataModel # Booking data
│ ├── SlotsDataModel # Time slot data
│ └── AvailabilityDataModel # Availability data
│
├── views/ # Custom Views & Registration Flow
│ ├── activity/
│ │ ├── OnboardingActivity # Onboarding flow
│ │ └── RegisterActivity # Registration flow
│ └── fragments/
│ ├── OnboardingFragmentA # Onboarding slide 1
│ ├── OnboardingFragmentB # Onboarding slide 2
│ ├── OnboardingFragmentC # Onboarding slide 3
│ └── register/
│ ├── RegisterNumberOrEmail # Registration step 1
│ ├── RegisterVerification # Registration step 2 (OTP)
│ ├── RegisterVerificationConfirm # Registration step 3
│ └── RegisterBasicInfo # Registration step 4
│
├── Stats/ # Utilities & Helpers (⚠️ God Package)
│ ├── Utils.java # Global utilities (~2031 lines!)
│ │ # - API endpoints (150+ constants)
│ │ # - Base URLs
│ │ # - Helper methods (date, validation, UI)
│ │ # - Static tokens and keys
│ ├── MySharedPreferences.java # Local storage wrapper (~550 lines)
│ ├── GlobalData.java # Global app state (singleton)
│ ├── LocaleUtils.java # Language/locale management
│ ├── LangHelper.java # RTL support
│ ├── TransparentProgressDialog.java # Loading dialogs
│ ├── ReasonsEnum.java # Error code enums
│ ├── CalendarCustomView.java # Custom calendar (~2200 lines!)
│ ├── clsStoragePermission.java # Storage permission handler
│ ├── clsCameraPermission.java # Camera permission handler
│ ├── clsRecordingPermission.java # Audio permission handler
│ └── WeekDisplayActivity.java # Week display (extends ListActivity)
│
└── workers/ # Background Tasks (WorkManager)
├── AlarmWorkManager.java # Alarm scheduling
├── clsShow_Alarm.java # Alarm display
└── Tags.java # Worker tags
TOTAL:
- 520+ Java files
- 88 Activities/Fragments
- 60+ Adapters
- 150+ Data Models
- ~50,000+ lines of code
Layer Architecture¶
1. Presentation Layer (UI)¶
Components:
- Activities (44+) - Screen controllers
- Fragments (44+) - Reusable UI components
- Adapters (60+) - RecyclerView/ListView data binding
- Custom Views - CalendarCustomView, CustomTimePickerDialog
Responsibilities:
- Display data to user
- Handle user interactions
- Navigate between screens
- Show loading/error states
Key Patterns:
- Fragment-based navigation
- ViewPager for tabs (Profile, Onboarding)
- RecyclerView for lists
- Material Design components
Notable Large Files:
CollaborationMain.java ~3000 lines # WebRTC video call logic
WeeklyScheduleFragment.java ~2700 lines # Weekly calendar
CalendarCustomView.java ~2200 lines # Custom calendar view
MyQyestionaireFragment.java ~1500 lines # Questionnaire UI
BaseClientActivityMain.java ~1400 lines # Main navigation
2. Business Logic Layer¶
Components:
- Interfaces - Callbacks and listeners
- Validators - Input validation (password strength, email format)
- Observers - Custom observer pattern for UI updates
Responsibilities:
- Validate user input
- Format data for display
- Handle business rules
- Coordinate between UI and data layers
Key Interfaces:
UpdateProfileStatusListener # Profile update callbacks
MPInterfaceCollaboration # Video call state callbacks
Observer # Generic observer (not java.util.Observer)
OnClickRecyclerView # RecyclerView item click handling
3. Data Layer¶
Components:
- DataModels (150+) - Plain Java objects (POJOs)
- MySharedPreferences - Local storage (key-value)
- Repository Pattern (Limited) - Not fully implemented
Responsibilities:
- Store and retrieve data
- Serialize/deserialize JSON
- Manage local cache
- Provide data to business logic
Storage Mechanisms:
SharedPreferences:
- User session (tokens, user ID)
- User preferences (language, settings)
- Passwords (⚠️ unencrypted)
- Cache data
No Local Database:
- No Room/SQLite
- No offline data persistence beyond SharedPreferences
Key Data Models:
RegisterModel # User registration data
CarePDataModel # Provider information (~50 fields)
BookingsDataModel # Appointment bookings
SlotsDataModel # Available time slots
ConversationListModel # Chat conversations
HomeWorkListDataModel # Homework assignments
DiaryDataModel # Diary entries
4. Infrastructure Layer¶
Components:
- AndroidNetworking - REST API calls
- WebSocket Client - Real-time communication
- Firebase Services - Auth, FCM, Crashlytics
- WebRTC - Peer-to-peer video/audio
Responsibilities:
- Network communication
- Authentication
- Push notifications
- Real-time video/audio
- Error tracking
Network Architecture:
// REST API (AndroidNetworking library)
AndroidNetworking.post(Utils.BaseURL + "endpoint")
.addHeaders("Authorization", "Bearer " + Utils.TokenPsyter)
.addJSONObjectBody(json)
.build()
.getAsJSONObject(listener);
// WebSocket (nv-websocket-client library)
WebSocket ws = new WebSocketFactory()
.createSocket(wsUrl)
.addListener(new WebSocketAdapter() {
@Override
public void onTextMessage(WebSocket ws, String text) {
// Handle message
}
})
.connect();
// WebRTC (google-webrtc library)
PeerConnectionFactory factory = PeerConnectionFactory.builder()
.createPeerConnectionFactory();
PeerConnection peerConnection = factory.createPeerConnection(
iceServers, constraints, observer);
5. Utility Layer¶
Components:
- Utils.java - God object with 2000+ lines
- Permission Handlers - Runtime permission wrappers
- Localization - Language switching
- UI Helpers - Dialogs, formatters
Responsibilities:
- Provide reusable functions
- Manage permissions
- Format dates/numbers
- Show common UI elements
Problems:
- ⚠️ God Object - Utils.java does too much
- ⚠️ Static Methods - Hard to test and mock
- ⚠️ Hardcoded Values - URLs, tokens in Utils.java
- ⚠️ Tight Coupling - Everything depends on Utils
Key Components Analysis¶
1. Authentication Flow¶
Entry Point: SplashActivity.java (~850 lines)
SplashActivity (Launch)
│
├─► Check if logged in (MySharedPreferences)
│ │
│ ├─► YES → BaseClientActivityMain (Home)
│ └─► NO → Continue
│
├─► Check first launch
│ │
│ ├─► YES → OnboardingActivity (3 slides)
│ └─► NO → Continue
│
└─► UserSelectionActivity (Client vs Provider)
│
└─► LoginActivity or RegisterActivity
│
├─► LoginActivity
│ ├─► Email/Phone + Password
│ ├─► Google Sign-In
│ ├─► Apple Sign-In
│ └─► Success → BaseClientActivityMain
│
└─► RegisterActivity (Multi-step)
├─► Step 1: RegisterNumberOrEmail
├─► Step 2: RegisterVerification (OTP)
├─► Step 3: RegisterVerificationConfirm
├─► Step 4: RegisterBasicInfo
├─► Step 5: QuestionaireActivity (Screening)
└─► Success → BaseClientActivityMain
Components:
- SplashActivity - Initial routing logic
- OnboardingActivity - First-time user experience
- LoginActivity - Authentication (email/phone/social)
- RegisterActivity - Registration coordinator
- RegisterNumberOrEmail - Step 1 fragment
- RegisterVerification - Step 2 OTP fragment
- RegisterVerificationConfirm - Step 3 confirmation
- RegisterBasicInfo - Step 4 user info
- QuestionaireActivity - Step 5 screening assessment
Authentication API Calls:
// Login
POST /Authenticate
Body: {
"Username": "user@email.com",
"Password": "password",
"DeviceId": "device123",
"DeviceType": 2, // Android
"FcmToken": "fcm_token"
}
// Register
POST /Patient/RegisterClient
Body: {
"Email": "user@email.com",
"PhoneNumber": "+1234567890",
"Password": "password",
"FirstName": "John",
"LastName": "Doe",
...
}
2. Main Navigation (BaseClientActivityMain)¶
Pattern: Bottom Navigation with Side Drawer
BaseClientActivityMain (~1400 lines)
│
├─► Bottom Navigation (5 tabs)
│ ├─► Home (MainFragmentClient)
│ ├─► Find Care Providers (FindCPFragment)
│ ├─► My Providers (MyCPFragment)
│ ├─► Diary (MyDiaryFragment)
│ └─► Profile (MyProfileFragmentClient)
│
├─► Side Drawer (DuoNavigationDrawer)
│ ├─► My Appointments (MyAppointFragment)
│ ├─► My Homework (MyHomeWorkFragment)
│ ├─► My Questionnaires (MyQyestionaireFragment)
│ ├─► Referrals (ReferralsFragment)
│ ├─► Medical Sources (MedicalSourcesActivity)
│ ├─► Settings
│ └─► Logout
│
└─► WebSocket Presence Connection
├─► Connects on activity start
├─► Manages online/offline status
└─► Handles incoming call notifications
Key Responsibilities:
- Fragment transaction management
- WebSocket lifecycle management
- Push notification handling
- Incoming call routing
- Menu item click handling
3. Video Call Architecture (CollaborationMain)¶
Pattern: WebRTC with WebSocket Signaling
CollaborationMain.java (~3000 lines)
│
├─► WebRTC Components
│ ├─► PeerConnectionFactory
│ ├─► PeerConnection
│ ├─► VideoCapturer (Camera)
│ ├─► AudioSource (Microphone)
│ ├─► VideoTrack & AudioTrack
│ ├─► SurfaceViewRenderer (Local & Remote)
│ └─► EglBase (OpenGL context)
│
├─► WebSocket Signaling (ManagePresenceeClient)
│ ├─► C_CREATE_COLLABORATION (Start call)
│ ├─► C_SDP (Offer/Answer)
│ ├─► C_ICECANDIDATE (ICE candidates)
│ ├─► C_END_COLLABORATION (End call)
│ └─► C_LEAVE_COLLABORATION (Leave call)
│
├─► Call Controls
│ ├─► Mute/Unmute Microphone
│ ├─► Enable/Disable Camera
│ ├─► Switch Camera (Front/Back)
│ ├─► Speaker On/Off
│ └─► End Call
│
└─► ICE Server Configuration (WebAPICall)
├─► STUN servers (Google)
└─► TURN servers (if configured)
Call Flow:
1. User A clicks "Call" → CollaborationMain Activity starts
2. Connect to WebSocket signaling server
3. Create PeerConnection with ICE servers
4. Add local media stream (camera + mic)
5. Create SDP Offer → Send via WebSocket
6. User B receives SDP Offer → Creates Answer
7. Exchange ICE candidates via WebSocket
8. Establish peer-to-peer connection
9. Display remote video stream
10. Call ends → Close PeerConnection → Disconnect WebSocket
Key Classes:
- CollaborationMain - Main video call UI and logic
- ManagePresenceeClient - WebSocket signaling handler
- IncomingCall - Incoming call notification screen
- WebAPICall - ICE server configuration API
4. Appointment Booking Flow¶
Pattern: Multi-step wizard
Appointment Booking Flow
│
├─► Step 1: CarePListActivity
│ └─► Search & filter care providers
│ └─► Click provider → CarePDetailActivity
│
├─► Step 2: CarePDetailActivity
│ └─► View provider profile & availability
│ └─► Click "Book" → MonthViewClient
│
├─► Step 3: MonthViewClient
│ └─► Select date from calendar
│ └─► Click date → SelectSlotActivity
│
├─► Step 4: SelectSlotActivity
│ └─► Select time slot
│ └─► Click slot → SlotPaymentSuggestActivity
│
├─► Step 5: SlotPaymentSuggestActivity
│ └─► Choose payment method (Wallet or Card)
│ ├─► Wallet → Direct booking
│ └─► Card → PaymentWebActivity (WebView)
│
└─► Step 6: PaymentWebActivity
└─► Payment gateway (STS Payment)
├─► Success → Return to app → Booking confirmed
└─► Failure → Return to app → Retry or cancel
API Calls:
// 1. Get provider list
GET /ServiceProvider/GetServiceProviderListByCatalogueFilter
// 2. Get provider details
GET /ServiceProvider/GetServiceProviderDetail/{id}
// 3. Get available dates
POST /ServiceProvider/GetServiceProviderAvailableDates
// 4. Get available slots
POST /Scheduling/GetAvailableSlots
// 5. Reserve slot
POST /Scheduling/ReserveSlot
// 6. Process payment
POST /Payment/InsertPayForData
// 7. Confirm booking
POST /Scheduling/ConfirmBooking
5. Data Persistence (MySharedPreferences)¶
Pattern: Wrapper around SharedPreferences
MySharedPreferences (~550 lines)
│
├─► User Session
│ ├─► UserLoginInfoId (int)
│ ├─► Username (string)
│ ├─► Password (string) ⚠️ Plain text!
│ ├─► TokenPsyter (Bearer token)
│ ├─► TokenScheduling (Bearer token)
│ ├─► AuthClaimToken (string)
│ └─► DeviceId (string)
│
├─► User Profile
│ ├─► FirstName, LastName
│ ├─► Email, PhoneNumber
│ ├─► ProfileImageUrl
│ └─► UserType (Client/Provider)
│
├─► App Preferences
│ ├─► AppLanguage ("0" = English, "1" = Arabic)
│ ├─► UserSelection ("0" = Client, "1" = Provider)
│ └─► FirstLaunch (boolean)
│
└─► Cache Data
├─► Countries list (JSON)
├─► Cities list (JSON)
└─► Last sync timestamp
Security Issues:
- ⚠️ Passwords stored in plain text
- ⚠️ Bearer tokens not encrypted
- ⚠️ No SecureSharedPreferences or EncryptedSharedPreferences
Recommended Fix:
// Use Android Security Crypto library
EncryptedSharedPreferences.create(
"secret_shared_prefs",
masterKey,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
Data Flow Architecture¶
Request Flow (REST API)¶
User Action
│
▼
Activity/Fragment
│
├─► Show Loading Dialog
│
▼
AndroidNetworking
│
├─► Add Headers (Authorization)
├─► Add Body (JSON)
├─► Set Priority
│
▼
HTTP Client (OkHttp)
│
▼
Backend API (ASP.NET)
│
▼
HTTP Response
│
▼
JSONObjectRequestListener
│
├─► onResponse(JSONObject)
│ ├─► Parse JSON
│ ├─► Update DataModel
│ ├─► Update UI
│ └─► Hide Loading Dialog
│
└─► onError(ANError)
├─► Parse Error
├─► Show Error Message
└─► Hide Loading Dialog
WebSocket Flow (Real-time)¶
App Start
│
▼
BaseClientActivityMain
│
├─► Initialize ManagePresenceeClient
│
▼
Connect to WebSocket Server
│
├─► wss://server:3333/
├─► ?connectionMode=1 (Presence)
├─► &communicationKey=XXX
├─► &deviceId=YYY
│
▼
WebSocket Connected
│
├─► Send P_AUTHENTICATE
│
▼
Server Authenticates
│
├─► Receive P_AUTHENTICATED
│
▼
Presence Active
│
├─► Send/Receive Messages
├─► Update Online Status
├─► Handle Incoming Calls
└─► Heartbeat (Ping/Pong)
Video Call Flow (WebRTC)¶
Initiate Call
│
▼
CollaborationMain Activity
│
├─► Initialize PeerConnectionFactory
├─► Create PeerConnection
├─► Add Local Media Stream
│ ├─► Camera (VideoCapturer)
│ └─► Microphone (AudioSource)
│
▼
Create SDP Offer
│
├─► peerConnection.createOffer()
│
▼
Set Local Description
│
├─► peerConnection.setLocalDescription(offer)
│
▼
Send SDP via WebSocket
│
├─► C_SDP command
│
▼
Receive SDP Answer
│
├─► Set Remote Description
│
▼
Exchange ICE Candidates
│
├─► onIceCandidate() → Send via WebSocket
├─► Receive ICE → addIceCandidate()
│
▼
P2P Connection Established
│
├─► onAddStream() → Display Remote Video
│
▼
Active Call
│
├─► Audio/Video Streaming
├─► Control Actions (Mute, Camera, etc.)
│
▼
End Call
│
├─► Send C_END_COLLABORATION
├─► Close PeerConnection
└─► Disconnect WebSocket
Navigation Architecture¶
Primary Navigation Pattern¶
Bottom Navigation + Side Drawer
BaseClientActivityMain
│
├─► Bottom Navigation (Primary)
│ ├─► Tab 1: Home (R.id.navigation_home)
│ ├─► Tab 2: Find Providers (R.id.navigation_find_cp)
│ ├─► Tab 3: My Providers (R.id.navigation_my_cp)
│ ├─► Tab 4: Diary (R.id.navigation_diary)
│ └─► Tab 5: Profile (R.id.navigation_profile)
│
└─► Side Drawer (Secondary)
├─► Appointments
├─► Homework
├─► Questionnaires
├─► Referrals
├─► Settings
└─► Logout
Fragment Transaction Management¶
// Replace fragment in container
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit();
Activity Launch Patterns¶
1. Standard Launch (Most Activities)
<activity android:name=".LoginActivity"
android:launchMode="standard" />
2. Single Top (Main Activity)
<activity android:name=".BaseClientActivityMain"
android:launchMode="singleTop" />
3. Activity Results (Payment)
// Launch for result
Intent intent = new Intent(this, PaymentWebActivity.class);
startActivityForResult(intent, REQUEST_CODE_PAYMENT);
// Handle result
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_PAYMENT) {
if (resultCode == RESULT_OK) {
// Payment successful
}
}
}
Deep Linking (Push Notifications)¶
// In MyFirebaseMessagingService
Intent intent = new Intent(this, BaseClientActivityMain.class);
intent.putExtra("notification_type", "appointment_reminder");
intent.putExtra("booking_id", bookingId);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, flags);
Design Patterns¶
1. Singleton Pattern¶
Usage: Global state and utility classes
// GlobalData - WebSocket connection state
public class GlobalData {
private static GlobalData instance;
public static GlobalData getInstance() {
if (instance == null) {
instance = new GlobalData();
}
return instance;
}
public ManagePresenceeClient presenceClient;
public boolean isCallActive;
// ... other global state
}
// MySharedPreferences - Local storage wrapper
public class MySharedPreferences {
private static MySharedPreferences instance;
private SharedPreferences prefs;
public MySharedPreferences(Context context) {
prefs = context.getSharedPreferences("PsyterPrefs", MODE_PRIVATE);
}
// Getter/setter methods
}
Problems:
- Hard to test (static instances)
- Tight coupling
- Hidden dependencies
- No lifecycle management
2. Observer Pattern¶
Usage: UI updates and callbacks
// Custom Observer interface
public interface Observer {
void onDataChanged();
}
// Fragment implements Observer
public class FindCPFragment extends Fragment implements Observer {
@Override
public void onDataChanged() {
// Refresh UI
}
}
// Notify observers
observer.onDataChanged();
Note: Not using java.util.Observable, custom implementation
3. Adapter Pattern¶
Usage: RecyclerView and ListView data binding
public class CarePListAdapter extends RecyclerView.Adapter<CarePListAdapter.ViewHolder> {
private List<CarePDataModel> providerList;
private OnClickRecyclerView clickListener;
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_provider, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
CarePDataModel provider = providerList.get(position);
holder.tvName.setText(provider.getFirstName() + " " + provider.getLastName());
holder.tvSpecialty.setText(provider.getSpecialty());
// ... bind other data
holder.itemView.setOnClickListener(v -> {
clickListener.onItemClick(position, provider);
});
}
}
4. ViewHolder Pattern¶
Usage: Efficient RecyclerView rendering
class ViewHolder extends RecyclerView.ViewHolder {
TextView tvName;
TextView tvSpecialty;
ImageView ivProfile;
ViewHolder(View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tvName);
tvSpecialty = itemView.findViewById(R.id.tvSpecialty);
ivProfile = itemView.findViewById(R.id.ivProfile);
}
}
5. Factory Pattern (Limited)¶
Usage: Object creation (PeerConnectionFactory for WebRTC)
PeerConnectionFactory factory = PeerConnectionFactory.builder()
.setOptions(options)
.setVideoDecoderFactory(decoderFactory)
.setVideoEncoderFactory(encoderFactory)
.createPeerConnectionFactory();
6. Builder Pattern¶
Usage: AndroidNetworking requests
AndroidNetworking.post(url)
.addHeaders("Authorization", "Bearer " + token)
.addHeaders("Content-Type", "application/json")
.addJSONObjectBody(jsonObject)
.setPriority(Priority.HIGH)
.build()
.getAsJSONObject(listener);
7. MVC Pattern (Primary Architecture)¶
Model:
- DataModels (CarePDataModel, BookingsDataModel, etc.)
- MySharedPreferences
View:
- Activities (inflated layouts)
- Fragments (inflated layouts)
- XML layouts (res/layout/*.xml)
Controller:
- Activities (handle user input, business logic)
- Fragments (handle user input, business logic)
- Adapters (bind data to views)
Problems:
- Massive Controllers - Activities with 1000+ lines
- Mixed Responsibilities - View logic in controller
- Tight Coupling - Hard to test
- No ViewModel - State management issues
Component Relationships¶
Dependency Graph (Simplified)¶
BaseClientActivityMain
├─── depends on ───┬─► ManagePresenceeClient (WebSocket)
│ ├─► MySharedPreferences (Storage)
│ ├─► Utils (Constants, Helpers)
│ ├─► GlobalData (Singleton state)
│ └─► Fragments (MainFragmentClient, FindCPFragment, etc.)
│
├─► MainFragmentClient
│ ├─── depends on ───┬─► AndroidNetworking (API calls)
│ │ ├─► Utils (API endpoints)
│ │ └─► MySharedPreferences
│ └─► launches Activities (CarePListActivity, BlogsActivity, etc.)
│
├─► FindCPFragment
│ ├─── depends on ───┬─► CarePListAdapter
│ │ ├─► CarePDataModel
│ │ ├─► AndroidNetworking
│ │ └─► Utils
│ └─► launches CarePDetailActivity
│
└─► CollaborationMain (Video calls)
├─── depends on ───┬─► ManagePresenceeClient
│ ├─► PeerConnectionFactory (WebRTC)
│ ├─── Utils
│ └─► GlobalData
└─► uses WebSocket for signaling
Everything depends on:
├─► Utils.java (God object)
├─► MySharedPreferences (Storage)
└─► GlobalData (Singleton)
Circular Dependencies¶
Problem Areas:
Utils.java
├─► Contains static references to Activities
└─► Activities depend on Utils
GlobalData
├─► Holds ManagePresenceeClient instance
└─► ManagePresenceeClient references GlobalData
Activities ↔ Fragments
├─► Activities create Fragments
└─► Fragments call Activity methods via casting
Recommended Fix:
- Use Dependency Injection (Dagger/Hilt)
- Implement ViewModel for shared state
- Use interfaces for communication (Fragment ↔ Activity)
Technical Architecture¶
Threading Model¶
Main Thread (UI Thread):
- All UI updates
- Activity/Fragment lifecycle methods
- View rendering
Background Threads:
// AndroidNetworking (uses OkHttp thread pool)
AndroidNetworking.post(url)
.build()
.getAsJSONObject(new JSONObjectRequestListener() {
@Override
public void onResponse(JSONObject response) {
// Called on Main Thread
runOnUiThread(() -> {
// Update UI
});
}
});
// WorkManager (background tasks)
public class AlarmWorkManager extends Worker {
@Override
public Result doWork() {
// Runs on background thread
return Result.success();
}
}
// Manual threading (limited use)
new Thread(() -> {
// Background work
runOnUiThread(() -> {
// UI update
});
}).start();
Memory Management¶
Potential Leak Sources:
1. Static references to Context
- Utils.java with Activity references
- GlobalData with Context
2. Anonymous inner classes
- NetworkListeners holding Activity reference
- Handler callbacks
3. WebSocket connections
- ManagePresenceeClient not properly closed
4. WebRTC resources
- PeerConnection not released
- VideoCapturer not disposed
Recommended Fixes:
- Use WeakReference for Context
- Use static inner classes with WeakReference
- Implement proper cleanup in onDestroy()
- Use LeakCanary for detection
Resource Management¶
Image Loading:
// Glide (used throughout app)
Glide.with(context)
.load(imageUrl)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.into(imageView);
// Picasso (also used)
Picasso.with(context)
.load(imageUrl)
.into(imageView);
Recommendation: Standardize on one library (Glide recommended)
Architecture Assessment¶
Strengths ✅¶
-
Modular Package Structure
- Features organized by domain
- Clear separation between Client and CommonUser -
Separation of Concerns
- DataModels separate from UI
- Adapters handle view binding -
Reusable Components
- Custom views (CalendarCustomView)
- Utility classes (Utils, MySharedPreferences) -
Fragment-based UI
- Reusable UI components
- Proper fragment lifecycle management
Weaknesses ⚠️¶
-
God Objects
- Utils.java (2000+ lines)
- BaseClientActivityMain (1400+ lines)
- CollaborationMain (3000+ lines) -
Tight Coupling
- Everything depends on Utils
- Static method overuse
- No dependency injection -
No Proper Architecture Pattern
- Not MVVM, MVP, or Clean Architecture
- Mixed MVC implementation
- Business logic in Activities/Fragments -
Security Issues
- Passwords in plain text (SharedPreferences)
- Hardcoded tokens and URLs
- No certificate pinning -
Limited Testability
- Static dependencies
- No interfaces for abstraction
- Tight coupling to Android framework -
Code Organization
- CareProvider code in Client app (confusing)
- Mixed responsibilities in packages
- Inconsistent naming (Qyestionnaire vs Questionnaire)
Recommendations 🎯¶
Immediate (Do Now)¶
- Extract hardcoded values - Move to BuildConfig or secure storage
- Implement EncryptedSharedPreferences - Secure password storage
- Add ProGuard rules - Obfuscate sensitive code
Short-term (Do Next)¶
- Refactor God objects - Break down Utils.java, large Activities
- Implement MVVM - Add ViewModels for state management
- Add Repository pattern - Abstract data sources
- Dependency Injection - Use Hilt or Koin
- Remove legacy code - Clean up CareProvider code in Client app
Long-term (Plan)¶
- Migrate to Kotlin - Modern language features
- Modularize by feature - Feature modules
- Clean Architecture - Domain, Data, Presentation layers
- Add comprehensive tests - Unit, Integration, UI tests
- Implement offline-first - Room database, proper caching
Conclusion¶
The Android client application demonstrates a functional but legacy architecture with significant technical debt. The codebase is operational but difficult to maintain, test, and scale.
Key Priorities:
Document Version: 1.0
Last Updated: November 6, 2025
Next Review: After refactoring Phase 1