├── app ├── src │ ├── internal │ │ ├── debug │ │ │ └── .gitkeep │ │ ├── release │ │ │ └── .gitkeep │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── twilio │ │ │ └── video │ │ │ └── app │ │ │ ├── ui │ │ │ └── ScreenSelectorModule.java │ │ │ └── auth │ │ │ └── AuthModule.java │ ├── test │ │ ├── resources │ │ │ ├── robolectric.properties │ │ │ └── mockito-extensions │ │ │ │ └── org.mockito.plugins.MockMaker │ │ └── java │ │ │ └── com │ │ │ └── twilio │ │ │ └── video │ │ │ └── app │ │ │ ├── BaseUnitTest.kt │ │ │ ├── data │ │ │ └── api │ │ │ │ └── AuthServiceErrorTest.kt │ │ │ └── ui │ │ │ └── room │ │ │ └── UriRoomParserTest.kt │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── twilio │ │ │ │ └── video │ │ │ │ └── app │ │ │ │ ├── auth │ │ │ │ ├── LoginResult.kt │ │ │ │ ├── AuthenticationException.kt │ │ │ │ ├── GoogleSignInOptionsWrapper.kt │ │ │ │ ├── FirebaseWrapper.kt │ │ │ │ ├── GoogleAuthProviderWrapper.kt │ │ │ │ ├── AuthenticationProvider.kt │ │ │ │ ├── GoogleAuthWrapper.kt │ │ │ │ ├── GoogleSignInWrapper.kt │ │ │ │ ├── LoginEvent.kt │ │ │ │ ├── InternalLoginResult.kt │ │ │ │ ├── Authenticator.kt │ │ │ │ └── FirebaseAuthenticator.kt │ │ │ │ ├── ui │ │ │ │ ├── ScreenSelector.kt │ │ │ │ ├── room │ │ │ │ │ ├── UriWrapper.kt │ │ │ │ │ ├── UriRoomParser.kt │ │ │ │ │ ├── RoomViewEffect.kt │ │ │ │ │ ├── RoomViewEvent.kt │ │ │ │ │ ├── RoomViewState.kt │ │ │ │ │ ├── RoomViewModelModule.kt │ │ │ │ │ ├── ParticipantAdapter.kt │ │ │ │ │ ├── ParticipantPrimaryView.kt │ │ │ │ │ └── RoomNotification.kt │ │ │ │ ├── ProductionScreenSelector.kt │ │ │ │ ├── settings │ │ │ │ │ ├── AudioSettingsFragment.kt │ │ │ │ │ ├── InternalSettingsFragment.kt │ │ │ │ │ ├── BandwidthProfileSettingsFragment.kt │ │ │ │ │ ├── SettingsFragment.kt │ │ │ │ │ ├── SettingsActivity.kt │ │ │ │ │ └── BaseSettingsFragment.kt │ │ │ │ └── splash │ │ │ │ │ └── SplashActivity.kt │ │ │ │ ├── sdk │ │ │ │ ├── VideoTrackViewState.kt │ │ │ │ ├── RoomStats.kt │ │ │ │ ├── VideoClient.kt │ │ │ │ ├── VideoSdkModule.kt │ │ │ │ ├── LocalParticipantListener.kt │ │ │ │ └── StatsScheduler.kt │ │ │ │ ├── data │ │ │ │ ├── api │ │ │ │ │ ├── AuthServiceException.kt │ │ │ │ │ ├── dto │ │ │ │ │ │ ├── AuthServiceErrorDTO.kt │ │ │ │ │ │ ├── AuthServiceResponseDTO.kt │ │ │ │ │ │ ├── AuthServiceRequestDTO.kt │ │ │ │ │ │ └── Topology.kt │ │ │ │ │ ├── AuthServiceError.kt │ │ │ │ │ ├── TwilioApiEnvironment.kt │ │ │ │ │ ├── InternalTokenApi.kt │ │ │ │ │ └── TokenService.kt │ │ │ │ └── DataModule.kt │ │ │ │ ├── util │ │ │ │ ├── CompositeDisposableExtensions.kt │ │ │ │ ├── PermissionUtil.kt │ │ │ │ ├── FragmentManagerExtensions.kt │ │ │ │ ├── TreeRanger.java │ │ │ │ ├── SharedPreferencesUtil.kt │ │ │ │ ├── BuildConfigUtils.kt │ │ │ │ ├── InputUtils.java │ │ │ │ ├── CrashlyticsTreeRanger.java │ │ │ │ ├── EnvUtil.java │ │ │ │ ├── ReleaseTree.java │ │ │ │ └── DebugTree.java │ │ │ │ ├── android │ │ │ │ └── SharedPreferencesWrapper.kt │ │ │ │ ├── ApplicationScope.java │ │ │ │ ├── VideoApplication.kt │ │ │ │ ├── TreeModule.java │ │ │ │ └── participant │ │ │ │ └── ParticipantViewState.kt │ │ ├── ic_launcher-web.png │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── drawable-nodpi │ │ │ ├── halfdome_720p.jpg │ │ │ └── mt_whitney_720p.jpg │ │ │ ├── drawable-hdpi │ │ │ ├── twilio_name_white.png │ │ │ └── video_logo_splash.png │ │ │ ├── drawable-mdpi │ │ │ ├── twilio_name_white.png │ │ │ ├── video_logo_splash.png │ │ │ ├── network_quality_level_0.png │ │ │ ├── network_quality_level_1.png │ │ │ ├── network_quality_level_2.png │ │ │ ├── network_quality_level_3.png │ │ │ ├── network_quality_level_4.png │ │ │ └── network_quality_level_5.png │ │ │ ├── drawable-xhdpi │ │ │ ├── twilio_name_white.png │ │ │ ├── video_logo_splash.png │ │ │ ├── network_quality_level_0.png │ │ │ ├── network_quality_level_1.png │ │ │ ├── network_quality_level_2.png │ │ │ ├── network_quality_level_3.png │ │ │ ├── network_quality_level_4.png │ │ │ └── network_quality_level_5.png │ │ │ ├── drawable-xxhdpi │ │ │ ├── twilio_name_white.png │ │ │ ├── video_logo_splash.png │ │ │ ├── network_quality_level_0.png │ │ │ ├── network_quality_level_1.png │ │ │ ├── network_quality_level_2.png │ │ │ ├── network_quality_level_3.png │ │ │ ├── network_quality_level_4.png │ │ │ └── network_quality_level_5.png │ │ │ ├── drawable-xxxhdpi │ │ │ ├── twilio_name_white.png │ │ │ └── video_logo_splash.png │ │ │ ├── drawable │ │ │ ├── edit_text_cursor.xml │ │ │ ├── badge_background.xml │ │ │ ├── participant_stroke.xml │ │ │ ├── join_button.xml │ │ │ ├── ic_recording.xml │ │ │ ├── participant_background.xml │ │ │ ├── participant_selected_background.xml │ │ │ ├── ic_close_white_24dp.xml │ │ │ ├── ic_play_white_24px.xml │ │ │ ├── ic_headset_mic_white_24dp.xml │ │ │ ├── ic_pause_green_24px.xml │ │ │ ├── ic_pause_red_24px.xml │ │ │ ├── ic_volume_down_gray_24px.xml │ │ │ ├── ic_volume_down_green_24px.xml │ │ │ ├── ic_volume_down_white_24px.xml │ │ │ ├── roundbutton.xml │ │ │ ├── ic_bluetooth_white_24dp.xml │ │ │ ├── ic_add_circle_white_24px.xml │ │ │ ├── ic_error_outline.xml │ │ │ ├── ic_more_vert_white_24dp.xml │ │ │ ├── ic_volume_up_white_24dp.xml │ │ │ ├── ic_switch_camera_white_24dp.xml │ │ │ ├── ic_videocam_green_24px.xml │ │ │ ├── ic_videocam_white_24px.xml │ │ │ ├── ic_screen_share_white_24dp.xml │ │ │ ├── ic_phonelink_ring_white_24dp.xml │ │ │ ├── splash_screen.xml │ │ │ ├── ic_exit_to_app_white_24px.xml │ │ │ ├── ic_call_white_24px.xml │ │ │ ├── ic_mic_green_24px.xml │ │ │ ├── ic_mic_red_24px.xml │ │ │ ├── ic_mic_white_24px.xml │ │ │ ├── ic_videocam_off_gray_24px.xml │ │ │ ├── ic_videocam_off_red_24px.xml │ │ │ ├── ic_call_black_24dp.xml │ │ │ ├── ic_switch_camera_512dp.xml │ │ │ ├── ic_account_circle_white_24dp.xml │ │ │ ├── ic_stop_screen_share_white_24dp.xml │ │ │ ├── ic_call_end_white_24px.xml │ │ │ ├── ic_mic_off_gray_24px.xml │ │ │ ├── ic_mic_off_red_24px.xml │ │ │ ├── ic_pin.xml │ │ │ ├── ic_stats_disabled_image.xml │ │ │ ├── ic_account_circle_white_48px.xml │ │ │ └── ic_thumbnail_no_audio.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── values │ │ │ ├── dimens.xml │ │ │ ├── attrs.xml │ │ │ └── colors.xml │ │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ │ ├── drawable-anydpi │ │ │ └── ic_videocam_notification.xml │ │ │ ├── layout │ │ │ ├── number_preference.xml │ │ │ ├── content_room.xml │ │ │ └── join_room.xml │ │ │ ├── xml │ │ │ ├── audio_preferences.xml │ │ │ ├── preferences.xml │ │ │ └── internal_preferences.xml │ │ │ └── menu │ │ │ └── room_menu.xml │ ├── androidTest │ │ ├── java │ │ │ └── com │ │ │ │ └── twilio │ │ │ │ └── video │ │ │ │ └── app │ │ │ │ ├── e2eTest │ │ │ │ ├── E2ETest.kt │ │ │ │ ├── LoginTest.kt │ │ │ │ ├── PermissionTest.kt │ │ │ │ ├── AppLinkRoomTest.kt │ │ │ │ ├── BackgroundSupportTest.kt │ │ │ │ └── BaseE2ETest.kt │ │ │ │ ├── integrationTest │ │ │ │ ├── IntegrationTest.kt │ │ │ │ ├── BaseIntegrationTest.kt │ │ │ │ └── CameraCapturerCompatTest.kt │ │ │ │ ├── TestCredentials.kt │ │ │ │ ├── espresso │ │ │ │ ├── HiddenView.kt │ │ │ │ └── DrawableMatcher.kt │ │ │ │ ├── util │ │ │ │ ├── UiAutomatorExtensions.kt │ │ │ │ ├── EspressoUtil.kt │ │ │ │ └── TestUtil.kt │ │ │ │ └── screen │ │ │ │ ├── LoginScreen.kt │ │ │ │ └── LobbyScreen.kt │ │ ├── assets │ │ │ └── Credentials │ │ │ │ └── TestCredentials.json.example │ │ └── AndroidManifest.xml │ ├── community │ │ ├── ic_launcher-web.png │ │ ├── java │ │ │ └── com │ │ │ │ └── twilio │ │ │ │ └── video │ │ │ │ └── app │ │ │ │ ├── data │ │ │ │ ├── CommunityPreferences.kt │ │ │ │ └── api │ │ │ │ │ └── AuthService.kt │ │ │ │ ├── security │ │ │ │ ├── SecurePreferences.kt │ │ │ │ ├── SecurityModule.kt │ │ │ │ └── SecurePreferencesImpl.kt │ │ │ │ ├── auth │ │ │ │ ├── CommunityLoginResult.kt │ │ │ │ └── CommunityAuthModule.kt │ │ │ │ └── ui │ │ │ │ ├── CommunityScreenSelector.kt │ │ │ │ └── CommunityScreenSelectorModule.java │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── values │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── styles.xml │ │ │ │ └── strings.xml │ │ │ └── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ └── AndroidManifest.xml │ ├── internalDebug │ │ ├── ic_launcher-web.png │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── values │ │ │ └── strings.xml │ │ │ └── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ ├── internalRelease │ │ ├── ic_launcher-web.png │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── values │ │ │ └── strings.xml │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ │ └── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ ├── release │ │ └── res │ │ │ └── values │ │ │ └── strings.xml │ └── testCommunity │ │ └── java │ │ └── com │ │ └── twilio │ │ └── video │ │ └── app │ │ ├── security │ │ └── SecurePreferencesFake.kt │ │ ├── util │ │ ├── TextInputLayoutMatcher.kt │ │ └── AuthServiceTestData.kt │ │ ├── fake │ │ ├── FakeSecurityModule.kt │ │ ├── MockCommunityAuthModule.kt │ │ └── MockCommunityAuthServiceModule.kt │ │ └── screen │ │ └── CommunityLoginScreen.kt ├── video-android-app.keystore ├── gradle.properties └── proguard-rules.pro ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── images ├── emulator │ ├── emulator_navigate.png │ ├── emulator_avd_settings.png │ ├── emulator_select_image.png │ ├── emulator_virtual_device.png │ └── emulator_select_hardware.png └── community-variant │ └── community-variant.png ├── gradle.properties ├── ACKNOWLEDGEMENTS.md ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── PULL_REQUEST_TEMPLATE.md ├── ui-test-args.yaml ├── .gitignore ├── Twilions.md └── gradlew.bat /app/src/internal/debug/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/internal/release/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /app/src/test/resources/robolectric.properties: -------------------------------------------------------------------------------- 1 | sdk=28 -------------------------------------------------------------------------------- /app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/LoginResult.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | interface LoginResult 4 | -------------------------------------------------------------------------------- /app/video-android-app.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/video-android-app.keystore -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/androidTest/java/com/twilio/video/app/e2eTest/E2ETest.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.e2eTest 2 | 3 | annotation class E2ETest 4 | -------------------------------------------------------------------------------- /app/src/community/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/ic_launcher-web.png -------------------------------------------------------------------------------- /images/emulator/emulator_navigate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/images/emulator/emulator_navigate.png -------------------------------------------------------------------------------- /app/src/internalDebug/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/internalRelease/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/ic_launcher-web.png -------------------------------------------------------------------------------- /images/emulator/emulator_avd_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/images/emulator/emulator_avd_settings.png -------------------------------------------------------------------------------- /images/emulator/emulator_select_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/images/emulator/emulator_select_image.png -------------------------------------------------------------------------------- /images/emulator/emulator_virtual_device.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/images/emulator/emulator_virtual_device.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /images/emulator/emulator_select_hardware.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/images/emulator/emulator_select_hardware.png -------------------------------------------------------------------------------- /app/src/community/java/com/twilio/video/app/data/CommunityPreferences.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.data 2 | 3 | const val PASSCODE: String = "passcode" 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/release/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Video 4 | 5 | -------------------------------------------------------------------------------- /images/community-variant/community-variant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/images/community-variant/community-variant.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/internal/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/halfdome_720p.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-nodpi/halfdome_720p.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/androidTest/java/com/twilio/video/app/integrationTest/IntegrationTest.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.integrationTest 2 | 3 | annotation class IntegrationTest 4 | -------------------------------------------------------------------------------- /app/src/community/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/community/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #80fffffe 4 | 5 | -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/twilio_name_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-hdpi/twilio_name_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/video_logo_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-hdpi/video_logo_splash.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/twilio_name_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-mdpi/twilio_name_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/video_logo_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-mdpi/video_logo_splash.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/mt_whitney_720p.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-nodpi/mt_whitney_720p.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/twilio_name_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xhdpi/twilio_name_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/video_logo_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xhdpi/video_logo_splash.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/androidTest/assets/Credentials/TestCredentials.json.example: -------------------------------------------------------------------------------- 1 | { 2 | "email_sign_in_user": { 3 | "email": null, 4 | "password": null 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /app/src/community/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Video Internal 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/twilio_name_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xxhdpi/twilio_name_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/video_logo_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xxhdpi/video_logo_splash.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/twilio_name_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xxxhdpi/twilio_name_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/video_logo_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xxxhdpi/video_logo_splash.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Video Internal Debug 4 | 5 | -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/network_quality_level_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-mdpi/network_quality_level_0.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/network_quality_level_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-mdpi/network_quality_level_1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/network_quality_level_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-mdpi/network_quality_level_2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/network_quality_level_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-mdpi/network_quality_level_3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/network_quality_level_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-mdpi/network_quality_level_4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/network_quality_level_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-mdpi/network_quality_level_5.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/network_quality_level_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xhdpi/network_quality_level_0.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/network_quality_level_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xhdpi/network_quality_level_1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/network_quality_level_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xhdpi/network_quality_level_2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/network_quality_level_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xhdpi/network_quality_level_3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/network_quality_level_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xhdpi/network_quality_level_4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/network_quality_level_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xhdpi/network_quality_level_5.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/network_quality_level_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xxhdpi/network_quality_level_0.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/network_quality_level_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xxhdpi/network_quality_level_1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/network_quality_level_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xxhdpi/network_quality_level_2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/network_quality_level_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xxhdpi/network_quality_level_3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/network_quality_level_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xxhdpi/network_quality_level_4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/network_quality_level_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/main/res/drawable-xxhdpi/network_quality_level_5.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/community/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/community/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalDebug/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/community/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 94.5dp 4 | 5 | -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twilio/twilio-video-app-android/HEAD/app/src/internalRelease/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/androidTest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | #Fri Dec 12 23:40:57 UTC 2025 2 | android.nonTransitiveRClass=false 3 | android.nonFinalResIds=false 4 | org.gradle.jvmargs=-Xmx2048m 5 | versionCode=171 6 | android.useAndroidX=true 7 | android.enableJetifier=true 8 | -------------------------------------------------------------------------------- /app/src/community/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/ui/ScreenSelector.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | 5 | interface ScreenSelector { 6 | 7 | val loginScreen: Class 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/ui/room/UriWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui.room 2 | 3 | import android.net.Uri 4 | 5 | class UriWrapper(uri: Uri?) { 6 | 7 | val pathSegments: MutableList? = uri?.pathSegments 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/AuthenticationException.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | // TODO Provide more detailed error handling as part of https://issues.corp.twilio.com/browse/AHOYAPPS-153 4 | class AuthenticationException : Exception() 5 | -------------------------------------------------------------------------------- /app/src/community/java/com/twilio/video/app/security/SecurePreferences.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.security 2 | 3 | interface SecurePreferences { 4 | 5 | fun putSecureString(key: String, value: String) 6 | 7 | fun getSecureString(key: String): String? 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/GoogleSignInOptionsWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | import com.google.android.gms.auth.api.signin.GoogleSignInOptions 4 | 5 | class GoogleSignInOptionsWrapper(val googleSignInOptions: GoogleSignInOptions) 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/sdk/VideoTrackViewState.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.sdk 2 | 3 | import com.twilio.video.VideoTrack 4 | 5 | data class VideoTrackViewState constructor( 6 | val videoTrack: VideoTrack, 7 | val isSwitchedOff: Boolean = false, 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/FirebaseWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | import com.google.firebase.auth.FirebaseAuth 4 | 5 | class FirebaseWrapper { 6 | 7 | val instance: FirebaseAuth 8 | get() = FirebaseAuth.getInstance() 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/edit_text_cursor.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jun 01 16:21:34 MDT 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip 7 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/twilio/video/app/TestCredentials.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app 2 | 3 | data class TestCredentials( 4 | val email_sign_in_user: EmailCredentials, 5 | ) 6 | 7 | data class EmailCredentials( 8 | val email: String, 9 | val password: String, 10 | ) 11 | -------------------------------------------------------------------------------- /app/src/test/java/com/twilio/video/app/BaseUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app 2 | 3 | import net.lachlanmckee.timberjunit.TimberTestRule 4 | import org.junit.Rule 5 | 6 | open class BaseUnitTest { 7 | @get:Rule 8 | var logAllAlwaysRule = TimberTestRule.logAllAlways() 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/badge_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/participant_stroke.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/data/api/AuthServiceException.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.data.api 2 | 3 | class AuthServiceException( 4 | throwable: Throwable? = null, 5 | val error: AuthServiceError? = null, 6 | message: String? = null, 7 | ) : RuntimeException(message, throwable) 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/GoogleAuthProviderWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | import com.google.firebase.auth.GoogleAuthProvider 4 | 5 | class GoogleAuthProviderWrapper { 6 | 7 | fun getCredential(idToken: String) = GoogleAuthProvider.getCredential(idToken, null) 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/util/CompositeDisposableExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.util 2 | 3 | import io.reactivex.disposables.CompositeDisposable 4 | import io.reactivex.disposables.Disposable 5 | 6 | operator fun CompositeDisposable.plus(newDisposable: Disposable) = add(newDisposable) 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/AuthenticationProvider.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | import io.reactivex.Observable 4 | 5 | interface AuthenticationProvider { 6 | 7 | fun login(loginEventObservable: Observable): Observable 8 | 9 | fun logout() 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/data/api/dto/AuthServiceErrorDTO.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.data.api 2 | 3 | data class AuthServiceErrorDTO( 4 | val error: ErrorDTO? = null, 5 | ) 6 | 7 | data class ErrorDTO( 8 | val message: String? = null, 9 | val explanation: String? = null, 10 | ) 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/join_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/community/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/community/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/internalDebug/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/internalRelease/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 90dp 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_recording.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/participant_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/participant_selected_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/data/api/dto/AuthServiceResponseDTO.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.data.api 2 | 3 | import com.google.gson.annotations.SerializedName 4 | import com.twilio.video.app.data.api.dto.Topology 5 | 6 | data class AuthServiceResponseDTO( 7 | val token: String? = null, 8 | @SerializedName("room_type") val topology: Topology? = null, 9 | ) 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/sdk/RoomStats.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.sdk 2 | 3 | import com.twilio.video.RemoteParticipant 4 | import com.twilio.video.StatsReport 5 | 6 | data class RoomStats( 7 | val remoteParticipants: List, 8 | val localVideoTrackNames: Map, 9 | val statsReports: List? = null, 10 | ) 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/ui/ProductionScreenSelector.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import com.twilio.video.app.ui.login.LoginActivity 5 | 6 | class ProductionScreenSelector : ScreenSelector { 7 | 8 | override val loginScreen: Class 9 | get() = LoginActivity::class.java 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/ui/room/UriRoomParser.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui.room 2 | 3 | class UriRoomParser(private val uri: UriWrapper) { 4 | 5 | fun parseRoom(): String? = 6 | uri.pathSegments?.let { 7 | if (it.size >= 2) { 8 | it[1] 9 | } else { 10 | null 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/community/java/com/twilio/video/app/auth/CommunityLoginResult.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | import com.twilio.video.app.data.api.AuthServiceError 4 | 5 | sealed class CommunityLoginResult : LoginResult { 6 | data class CommunityLoginFailureResult(val error: AuthServiceError? = null) : CommunityLoginResult() 7 | object CommunityLoginSuccessResult : CommunityLoginResult() 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/community/java/com/twilio/video/app/ui/CommunityScreenSelector.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import com.twilio.video.app.ui.login.CommunityLoginActivity 5 | 6 | class CommunityScreenSelector : ScreenSelector { 7 | 8 | override val loginScreen: Class 9 | get() = CommunityLoginActivity::class.java 10 | } 11 | -------------------------------------------------------------------------------- /app/src/community/java/com/twilio/video/app/data/api/AuthService.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.data.api 2 | 3 | import retrofit2.http.Body 4 | import retrofit2.http.POST 5 | import retrofit2.http.Url 6 | 7 | interface AuthService { 8 | 9 | @POST 10 | suspend fun getToken( 11 | @Url url: String, 12 | @Body authServiceRequestDTO: AuthServiceRequestDTO, 13 | ): AuthServiceResponseDTO 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/GoogleAuthWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | import android.content.Intent 4 | import com.google.android.gms.auth.api.Auth 5 | import com.google.android.gms.auth.api.signin.GoogleSignInResult 6 | 7 | class GoogleAuthWrapper { 8 | 9 | fun getSignInResultFromIntent(intent: Intent): GoogleSignInResult? = Auth.GoogleSignInApi.getSignInResultFromIntent(intent) 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/GoogleSignInWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | import android.content.Context 4 | import com.google.android.gms.auth.api.signin.GoogleSignIn 5 | 6 | class GoogleSignInWrapper { 7 | 8 | fun getClient(context: Context, googleSignInOptionsWrapper: GoogleSignInOptionsWrapper) = 9 | GoogleSignIn.getClient(context, googleSignInOptionsWrapper.googleSignInOptions) 10 | } 11 | -------------------------------------------------------------------------------- /app/src/testCommunity/java/com/twilio/video/app/security/SecurePreferencesFake.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.security 2 | 3 | class SecurePreferencesFake : SecurePreferences { 4 | 5 | private var preferences: MutableMap = mutableMapOf() 6 | 7 | override fun putSecureString(key: String, value: String) { 8 | preferences[key] = value 9 | } 10 | 11 | override fun getSecureString(key: String) = preferences[key] 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/ui/settings/AudioSettingsFragment.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui.settings 2 | 3 | import android.os.Bundle 4 | import com.twilio.video.app.R 5 | 6 | class AudioSettingsFragment : BaseSettingsFragment() { 7 | 8 | override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { 9 | addPreferencesFromResource(R.xml.audio_preferences) 10 | 11 | setHasOptionsMenu(true) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/util/PermissionUtil.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.util 2 | 3 | import android.content.Context 4 | import android.content.pm.PackageManager.PERMISSION_GRANTED 5 | import androidx.core.content.ContextCompat.checkSelfPermission 6 | 7 | class PermissionUtil(private val context: Context) { 8 | 9 | fun isPermissionGranted(permission: String) = 10 | checkSelfPermission(context, permission) == PERMISSION_GRANTED 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_close_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_play_white_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/android/SharedPreferencesWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.android 2 | 3 | import android.content.SharedPreferences 4 | import androidx.core.content.edit 5 | 6 | class SharedPreferencesWrapper(private val sharedPreferences: SharedPreferences) : 7 | SharedPreferences by sharedPreferences { 8 | 9 | fun edit(action: SharedPreferences.Editor.() -> Unit) { 10 | sharedPreferences.edit(action = action) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_headset_mic_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pause_green_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pause_red_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 13 | -------------------------------------------------------------------------------- /app/src/internal/java/com/twilio/video/app/ui/ScreenSelectorModule.java: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui; 2 | 3 | import dagger.Module; 4 | import dagger.Provides; 5 | import dagger.hilt.InstallIn; 6 | import dagger.hilt.android.components.ActivityComponent; 7 | 8 | @Module 9 | @InstallIn(ActivityComponent.class) 10 | public class ScreenSelectorModule { 11 | 12 | @Provides 13 | ScreenSelector providesScreenSelector() { 14 | return new ProductionScreenSelector(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/LoginEvent.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | import android.content.Intent 4 | 5 | sealed class LoginEvent { 6 | object GoogleLoginIntentRequestEvent : LoginEvent() 7 | data class EmailLoginEvent(val email: String, val password: String) : LoginEvent() 8 | data class GoogleLoginEvent(val signInResultIntent: Intent) : LoginEvent() 9 | data class CommunityLoginEvent(val identity: String, val passcode: String) : LoginEvent() 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/data/api/dto/AuthServiceRequestDTO.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.data.api 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | data class AuthServiceRequestDTO( 6 | @SerializedName("passcode") val passcode: String? = null, 7 | @SerializedName("user_identity") val user_identity: String? = null, 8 | @SerializedName("room_name") val room_name: String? = null, 9 | @SerializedName("create_room") val create_room: Boolean = false, 10 | ) 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_volume_down_gray_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_volume_down_green_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_volume_down_white_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/roundbutton.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bluetooth_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/community/java/com/twilio/video/app/ui/CommunityScreenSelectorModule.java: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui; 2 | 3 | import dagger.Module; 4 | import dagger.Provides; 5 | import dagger.hilt.InstallIn; 6 | import dagger.hilt.android.components.ActivityComponent; 7 | 8 | @Module 9 | @InstallIn(ActivityComponent.class) 10 | public class CommunityScreenSelectorModule { 11 | 12 | @Provides 13 | ScreenSelector providesScreenSelector() { 14 | return new CommunityScreenSelector(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_circle_white_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_error_outline.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/community/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_more_vert_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_volume_up_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/InternalLoginResult.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | import android.content.Intent 4 | import com.google.android.gms.auth.api.signin.GoogleSignInAccount 5 | 6 | sealed class InternalLoginResult : LoginResult { 7 | data class GoogleLoginIntentResult(val intent: Intent) : InternalLoginResult() 8 | data class GoogleLoginSuccessResult(val googleSignInAccount: GoogleSignInAccount) : InternalLoginResult() 9 | data class EmailLoginSuccessResult(val email: String) : InternalLoginResult() 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_switch_camera_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_videocam_green_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 10 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_videocam_white_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 10 | 14 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/twilio/video/app/integrationTest/BaseIntegrationTest.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.integrationTest 2 | 3 | import com.twilio.video.app.util.CameraCapturerCompat 4 | import com.twilio.video.app.util.getTargetContext 5 | import org.junit.Assume.assumeTrue 6 | import org.junit.Before 7 | 8 | open class BaseIntegrationTest { 9 | 10 | @Before 11 | fun setUp() { 12 | // Skip any devices that don't have a front or back camera 13 | assumeTrue(CameraCapturerCompat.newInstance(getTargetContext(), null) != null) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_screen_share_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_phonelink_ring_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/splash_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/testCommunity/java/com/twilio/video/app/util/TextInputLayoutMatcher.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.util 2 | 3 | import android.view.View 4 | import com.google.android.material.textfield.TextInputLayout 5 | import org.hamcrest.Description 6 | import org.hamcrest.Matcher 7 | import org.hamcrest.TypeSafeMatcher 8 | 9 | fun isTextInputLayoutError(): Matcher = object : TypeSafeMatcher() { 10 | 11 | override fun describeTo(description: Description?) { } 12 | 13 | override fun matchesSafely(item: View?): Boolean = 14 | if (item is TextInputLayout) item.isErrorEnabled else false 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_videocam_notification.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/twilio/video/app/espresso/HiddenView.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.espresso 2 | 3 | import android.view.View 4 | import androidx.test.espresso.NoMatchingViewException 5 | import androidx.test.espresso.ViewAssertion 6 | import java.lang.RuntimeException 7 | 8 | class HiddenView : ViewAssertion { 9 | 10 | override fun check(view: View?, noViewFoundException: NoMatchingViewException?) { 11 | noViewFoundException?.let { throw it } 12 | val isNotVisible = view?.let { it.visibility == View.GONE } ?: false 13 | if (isNotVisible) return else throw RuntimeException() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_exit_to_app_white_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 10 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_call_white_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_mic_green_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_mic_red_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_mic_white_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_videocam_off_gray_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 10 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_videocam_off_red_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 10 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_call_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /ACKNOWLEDGEMENTS.md: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | 3 | This software includes the following software dependencies under their corresponding licenses: 4 | 5 | - Twilio Video Android - https://www.twilio.com/legal/tos. 6 | 7 | - Generic [Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0.txt). 8 | 9 | - Timber 10 | - MaterialRangeBar 11 | - Butter Knife 12 | - Guava 13 | - Dagger 14 | - RxJava 15 | - Retrofit 16 | - Kotlin 17 | 18 | Android SDK and Google Libraries - https://developer.android.com/studio/terms.html. 19 | 20 | Firebase - https://cloud.google.com/terms/. 21 | 22 | Crashlytics - https://firebase.google.com/terms/crashlytics/. 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/sdk/VideoClient.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.sdk 2 | 3 | import android.content.Context 4 | import com.twilio.video.Room 5 | import com.twilio.video.Video 6 | 7 | class VideoClient( 8 | private val context: Context, 9 | private val connectOptionsFactory: ConnectOptionsFactory, 10 | ) { 11 | 12 | suspend fun connect( 13 | identity: String, 14 | roomName: String, 15 | roomListener: Room.Listener, 16 | ): Room { 17 | return Video.connect( 18 | context, 19 | connectOptionsFactory.newInstance(identity, roomName), 20 | roomListener, 21 | ) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: 5 | labels: "feature-request" 6 | assignees: 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_switch_camera_512dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | -------------------------------------------------------------------------------- /app/src/community/java/com/twilio/video/app/security/SecurityModule.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.security 2 | 3 | import android.app.Application 4 | import android.content.SharedPreferences 5 | import dagger.Module 6 | import dagger.Provides 7 | import dagger.hilt.InstallIn 8 | import dagger.hilt.components.SingletonComponent 9 | import javax.inject.Singleton 10 | 11 | @Module 12 | @InstallIn(SingletonComponent::class) 13 | class SecurityModule { 14 | 15 | @Provides 16 | @Singleton 17 | fun providesSecurePreferences(app: Application, preferences: SharedPreferences): SecurePreferences { 18 | return SecurePreferencesImpl(app.applicationContext, preferences) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/data/api/AuthServiceError.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.data.api 2 | 3 | import timber.log.Timber 4 | 5 | enum class AuthServiceError { 6 | INVALID_PASSCODE_ERROR, 7 | EXPIRED_PASSCODE_ERROR, 8 | ; 9 | 10 | companion object { 11 | fun value(value: String?): AuthServiceError? = 12 | when (value) { 13 | "passcode incorrect" -> INVALID_PASSCODE_ERROR 14 | "passcode expired" -> EXPIRED_PASSCODE_ERROR 15 | else -> { 16 | Timber.d("Unrecognized Auth Service error message: %s", value) 17 | null 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/util/FragmentManagerExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.util 2 | 3 | import androidx.annotation.IdRes 4 | import androidx.fragment.app.Fragment 5 | import androidx.fragment.app.FragmentManager 6 | import androidx.fragment.app.commit 7 | import kotlin.reflect.KClass 8 | 9 | fun FragmentManager.replaceFragment( 10 | fragment: Fragment, 11 | @IdRes fragmentContainer: Int, 12 | ) { 13 | commit { 14 | addToBackStack(null) 15 | replace(fragmentContainer, findFragment(fragment::class) ?: fragment) 16 | } 17 | } 18 | 19 | fun FragmentManager.findFragment(fragment: KClass): Fragment? = 20 | fragments.find { it::class == fragment } 21 | -------------------------------------------------------------------------------- /app/src/community/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Video Community 4 | 5 | 6 | Your name 7 | Passcode 8 | Log In Error 9 | Passcode incorrect. 10 | Passcode expired. 11 | There was an issue logging in. 12 | LOG IN 13 | Video Logo 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/ui/room/RoomViewEffect.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui.room 2 | 3 | import com.twilio.video.Room 4 | import com.twilio.video.app.data.api.AuthServiceError 5 | import io.uniflow.core.flow.data.UIEvent 6 | 7 | sealed class RoomViewEffect : UIEvent() { 8 | 9 | object PermissionsDenied : RoomViewEffect() 10 | data class Connected(val room: Room) : RoomViewEffect() 11 | object Disconnected : RoomViewEffect() 12 | 13 | object ShowConnectFailureDialog : RoomViewEffect() 14 | object ShowMaxParticipantFailureDialog : RoomViewEffect() 15 | data class ShowTokenErrorDialog(val serviceError: AuthServiceError? = null) : RoomViewEffect() 16 | data class Transcription(val text: String) : RoomViewEffect() 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_account_circle_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/testCommunity/java/com/twilio/video/app/fake/FakeSecurityModule.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.fake 2 | 3 | import com.twilio.video.app.security.SecurePreferences 4 | import com.twilio.video.app.security.SecurePreferencesFake 5 | import com.twilio.video.app.security.SecurityModule 6 | import dagger.Module 7 | import dagger.Provides 8 | import dagger.hilt.components.SingletonComponent 9 | import dagger.hilt.testing.TestInstallIn 10 | import javax.inject.Singleton 11 | 12 | @Module 13 | @TestInstallIn( 14 | components = [SingletonComponent::class], 15 | replaces = [SecurityModule::class], 16 | ) 17 | class FakeSecurityModule { 18 | 19 | @Provides 20 | @Singleton 21 | fun providesSecurePreferences(): SecurePreferences = SecurePreferencesFake() 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_stop_screen_share_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/data/api/TwilioApiEnvironment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.twilio.video.app.data.api 18 | 19 | const val TWILIO_API_DEV_ENV = "dev" 20 | const val TWILIO_API_STAGE_ENV = "stage" 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_call_end_white_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_mic_off_gray_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 10 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_mic_off_red_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 10 | 17 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | [Description of the Pull Request] 4 | 5 | ## Breakdown 6 | 7 | - [Bulleted summary of changes] 8 | - [eg. Add new public function to `Authenticator.kt` ] 9 | - [eg. Add new string resources to `strings.xml`] 10 | 11 | ## Validation 12 | 13 | - [Bulleted summary of validation steps] 14 | - [eg. Add new unit tests to validate changes] 15 | - [eg. Verified all CI checks pass on the feature branch] 16 | 17 | ## Additional Notes 18 | 19 | [Any additional comments, notes, or information relevant to reviewers.] 20 | 21 | **Contributing to Twilio** 22 | 23 | > All third-party contributors acknowledge that any contributions they provide will be made under the same open-source license that the open-source project is provided under. 24 | 25 | - [ ] I acknowledge that all my contributions will be made under the project's license. 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/util/TreeRanger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.twilio.video.app.util; 18 | 19 | interface TreeRanger { 20 | void inform(String message); 21 | 22 | void caution(String message); 23 | 24 | void alert(Throwable throwable); 25 | } 26 | -------------------------------------------------------------------------------- /ui-test-args.yaml: -------------------------------------------------------------------------------- 1 | e2e-tests: 2 | timeout: 30m 3 | type: instrumentation 4 | app: app/build/outputs/apk/internal/debug/app-internal-debug.apk 5 | test: app/build/outputs/apk/androidTest/internal/debug/app-internal-debug-androidTest.apk 6 | device: 7 | - {model: tokay, version: 35} 8 | - {model: redfin, version: 30} 9 | test-targets: 10 | - "annotation com.twilio.video.app.e2eTest.E2ETest" 11 | 12 | integration-tests: 13 | timeout: 30m 14 | type: instrumentation 15 | app: app/build/outputs/apk/internal/debug/app-internal-debug.apk 16 | test: app/build/outputs/apk/androidTest/internal/debug/app-internal-debug-androidTest.apk 17 | device: 18 | - {model: tokay, version: 34} 19 | - {model: shiba, version: 34} 20 | - {model: dm3q, version: 33} 21 | - {model: pettyl, version: 27} 22 | - {model: redfin, version: 30} 23 | test-targets: 24 | - "annotation com.twilio.video.app.integrationTest.IntegrationTest" -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/ApplicationScope.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.twilio.video.app; 18 | 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import javax.inject.Scope; 22 | 23 | @Scope 24 | @Retention(RetentionPolicy.RUNTIME) 25 | public @interface ApplicationScope {} 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/number_preference.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/data/api/InternalTokenApi.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.twilio.video.app.data.api 17 | 18 | import retrofit2.http.Body 19 | import retrofit2.http.POST 20 | 21 | interface InternalTokenApi { 22 | @POST("/token") 23 | suspend fun getToken(@Body request: AuthServiceRequestDTO): AuthServiceResponseDTO 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/sdk/VideoSdkModule.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.sdk 2 | 3 | import android.app.Application 4 | import android.content.SharedPreferences 5 | import com.twilio.video.app.data.api.TokenService 6 | import dagger.Module 7 | import dagger.Provides 8 | import dagger.hilt.InstallIn 9 | import dagger.hilt.components.SingletonComponent 10 | import javax.inject.Singleton 11 | 12 | @Module 13 | @InstallIn(SingletonComponent::class) 14 | class VideoSdkModule { 15 | 16 | @Provides 17 | @Singleton 18 | fun providesRoomManager( 19 | application: Application, 20 | sharedPreferences: SharedPreferences, 21 | tokenService: TokenService, 22 | ): RoomManager { 23 | val connectOptionsFactory = ConnectOptionsFactory(application, sharedPreferences, tokenService) 24 | val videoClient = VideoClient(application, connectOptionsFactory) 25 | return RoomManager(application, videoClient, sharedPreferences) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pin.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/util/SharedPreferencesUtil.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.util 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import android.preference.PreferenceManager 6 | 7 | /* 8 | * Utility method that allows getting a shared preference with a default value. The return value 9 | * type is inferred by the default value type. 10 | */ 11 | inline fun SharedPreferences.get(key: String, defaultValue: T): T { 12 | return when (defaultValue) { 13 | is Boolean -> getBoolean(key, defaultValue) as T 14 | is Float -> getFloat(key, defaultValue) as T 15 | is Int -> getInt(key, defaultValue) as T 16 | is Long -> getLong(key, defaultValue) as T 17 | is String -> getString(key, defaultValue) as T 18 | else -> throw IllegalArgumentException("Attempted to get preference with unsupported type") 19 | } 20 | } 21 | 22 | fun getSharedPreferences(context: Context) = PreferenceManager.getDefaultSharedPreferences(context) 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/util/BuildConfigUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.twilio.video.app.util 17 | 18 | import com.twilio.video.app.BuildConfig 19 | 20 | val isCommunityFlavor: Boolean get() = BuildConfig.FLAVOR == "community" 21 | 22 | val isInternalFlavor: Boolean get() = BuildConfig.FLAVOR == "internal" 23 | 24 | val isReleaseBuildType: Boolean get() = BuildConfig.BUILD_TYPE == "release" 25 | -------------------------------------------------------------------------------- /app/src/main/res/xml/audio_preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 17 | 18 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/Authenticator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.twilio.video.app.auth 18 | 19 | import io.reactivex.Observable 20 | 21 | interface Authenticator { 22 | 23 | fun login(loginEventObservable: Observable): Observable 24 | 25 | fun login(loginEvent: LoginEvent): Observable 26 | 27 | fun loggedIn(): Boolean 28 | 29 | fun logout() 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_room.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/data/api/TokenService.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.twilio.video.app.data.api 18 | 19 | interface TokenService { 20 | suspend fun getToken( 21 | identity: String? = null, 22 | roomName: String? = null, 23 | ): String 24 | 25 | suspend fun getToken( 26 | identity: String? = null, 27 | roomName: String? = null, 28 | passcode: String? = null, 29 | ): String { return "" } 30 | } 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | sdk/local.properties 2 | sdk/libs/armeabi-v7a 3 | sdk/obj 4 | sdk/gen 5 | sdk/.settings 6 | sdk/bin 7 | output 8 | 9 | dist/ 10 | target/ 11 | docs/ 12 | 13 | # Files for the Dalvik VM 14 | *.dex 15 | 16 | # Java class files 17 | *.class 18 | 19 | # Generated files 20 | bin/ 21 | gen/ 22 | 23 | # Gradle files 24 | .gradle/ 25 | build/ 26 | 27 | # Local configuration file (sdk path, etc) 28 | local.properties 29 | 30 | # Proguard folder generated by Eclipse 31 | proguard/ 32 | 33 | tags 34 | obj 35 | 36 | .vagrant 37 | depot_tools 38 | 39 | .gradle 40 | local.properties 41 | .idea 42 | *.iml 43 | build 44 | .DS_Store 45 | sdk/target/* 46 | sdk/libs/ 47 | *~ 48 | *.swp 49 | *.swo 50 | **/**/**/libs 51 | 52 | # Screenshots 53 | .gradletasknamecache 54 | 55 | # Cmake 56 | **/.externalNativeBuild 57 | 58 | # Google Play Services 59 | **/google-services.json 60 | !app/src/community/google-services.json 61 | 62 | # CI Secrets 63 | secrets.tar.gz 64 | secrets.tar 65 | secrets/ 66 | 67 | # CXX directories 68 | **/.cxx/ 69 | 70 | # Test files 71 | captures/ 72 | app/src/androidTest/assets/Credentials/TestCredentials.json -------------------------------------------------------------------------------- /app/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | org.gradle.jvmargs=-Xmx20496m 15 | 16 | # When configured, Gradle will run in incubating parallel mode. 17 | # This option should only be used with decoupled projects. More details, visit 18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 19 | # org.gradle.parallel=true 20 | 21 | VERSION_NAME=0.8.0 22 | VERSION_CODE=298 23 | android.useAndroidX=true 24 | android.enableJetifier=true 25 | android.useFullClasspathForDexingTransform = true -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/auth/FirebaseAuthenticator.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.auth 2 | 3 | import io.reactivex.Observable 4 | 5 | class FirebaseAuthenticator( 6 | private val firebaseWrapper: FirebaseWrapper, 7 | private val authenticationProviders: List, 8 | ) : Authenticator { 9 | 10 | override fun login(loginEventObservable: Observable): Observable { 11 | // TODO Figure out a better way to only subscribe to one authenticator at a time 12 | val observables: MutableList> = mutableListOf() 13 | authenticationProviders.forEach { 14 | observables.add(it.login(loginEventObservable)) 15 | } 16 | return Observable.merge(observables) 17 | } 18 | 19 | override fun login(loginEvent: LoginEvent): Observable { 20 | return login(Observable.just(loginEvent)) 21 | } 22 | 23 | override fun loggedIn() = firebaseWrapper.instance.currentUser != null 24 | 25 | override fun logout() { 26 | authenticationProviders.forEach { it.logout() } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/xml/preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 14 | 18 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/testCommunity/java/com/twilio/video/app/fake/MockCommunityAuthModule.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.fake 2 | 3 | import android.content.SharedPreferences 4 | import com.twilio.video.app.auth.Authenticator 5 | import com.twilio.video.app.auth.CommunityAuthModule 6 | import com.twilio.video.app.auth.CommunityAuthenticator 7 | import com.twilio.video.app.data.api.TokenService 8 | import com.twilio.video.app.security.SecurePreferences 9 | import dagger.Module 10 | import dagger.Provides 11 | import dagger.hilt.components.SingletonComponent 12 | import dagger.hilt.testing.TestInstallIn 13 | import kotlinx.coroutines.Dispatchers 14 | 15 | @Module 16 | @TestInstallIn( 17 | components = [SingletonComponent::class], 18 | replaces = [CommunityAuthModule::class], 19 | ) 20 | class MockCommunityAuthModule { 21 | @Provides 22 | fun providesCommunityAuthenticator( 23 | preferences: SharedPreferences, 24 | securePreferences: SecurePreferences, 25 | tokenService: TokenService, 26 | ): Authenticator { 27 | return CommunityAuthenticator(preferences, securePreferences, tokenService, Dispatchers.Main) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_stats_disabled_image.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -keep class tvi.webrtc.** { *; } 2 | -dontwarn tvi.webrtc.** 3 | -keep class com.twilio.video.** { *; } 4 | -keep class com.twilio.common.** { *; } 5 | -keepattributes InnerClasses 6 | 7 | # https://github.com/firebase/firebase-android-sdk/issues/4900#issuecomment-1520001376 8 | -keep class com.google.android.gms.internal.** { *; } 9 | 10 | # Facebook Conceal proguard config 11 | -keep class com.facebook.crypto.** { *; } 12 | -keep class com.facebook.jni.** { *; } 13 | -keepclassmembers class com.facebook.cipher.jni.** { *; } 14 | 15 | # Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items). 16 | -keep,allowobfuscation,allowshrinking interface retrofit2.Call 17 | -keep,allowobfuscation,allowshrinking class retrofit2.Response 18 | 19 | # With R8 full mode generic signatures are stripped for classes that are not 20 | # kept. Suspend functions are wrapped in continuations where the type argument 21 | # is used. 22 | -keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation 23 | 24 | # Needed when using the VirtualBackgroundProcessor 25 | -keep class com.google.mlkit.common.** { *; } 26 | -keep class com.google.mlkit.vision.** { *; } 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_account_circle_white_48px.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/test/java/com/twilio/video/app/data/api/AuthServiceErrorTest.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.data.api 2 | 3 | import com.twilio.video.app.BaseUnitTest 4 | import com.twilio.video.app.data.api.AuthServiceError.EXPIRED_PASSCODE_ERROR 5 | import com.twilio.video.app.data.api.AuthServiceError.INVALID_PASSCODE_ERROR 6 | import junitparams.JUnitParamsRunner 7 | import junitparams.Parameters 8 | import org.hamcrest.CoreMatchers.equalTo 9 | import org.hamcrest.MatcherAssert.assertThat 10 | import org.junit.Test 11 | import org.junit.runner.RunWith 12 | 13 | @RunWith(JUnitParamsRunner::class) 14 | class AuthServiceErrorTest : BaseUnitTest() { 15 | 16 | fun params() = 17 | arrayOf( 18 | arrayOf("passcode incorrect", INVALID_PASSCODE_ERROR), 19 | arrayOf("passcode expired", EXPIRED_PASSCODE_ERROR), 20 | arrayOf("bad input", null), 21 | arrayOf(null, null), 22 | ) 23 | 24 | @Parameters(method = "params") 25 | @Test 26 | fun `value should return the corresponding AuthServiceError enum`( 27 | input: String?, 28 | expectedValue: AuthServiceError?, 29 | ) { 30 | assertThat(AuthServiceError.value(input), equalTo(expectedValue)) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/twilio/video/app/util/UiAutomatorExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.util 2 | 3 | import android.os.Build 4 | import androidx.test.platform.app.InstrumentationRegistry 5 | import androidx.test.uiautomator.UiDevice 6 | import androidx.test.uiautomator.UiSelector 7 | import java.util.concurrent.TimeoutException 8 | 9 | fun uiDevice(): UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) 10 | 11 | fun UiDevice.allowAllPermissions() { 12 | clickThroughDialogs("Allow|ALLOW|While using the app") 13 | } 14 | 15 | fun UiDevice.denyAllPermissions() { 16 | clickThroughDialogs("Deny|DENY|Don\\p{Punct}t allow") 17 | } 18 | 19 | private fun UiDevice.clickThroughDialogs(text: String) { 20 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 21 | var allowPermissions = findObject(UiSelector().textMatches(text)) 22 | if (allowPermissions.waitForExists(5000)) { 23 | while (allowPermissions.exists()) { 24 | allowPermissions.click() 25 | allowPermissions = findObject(UiSelector().textMatches(text)) 26 | } 27 | } else { 28 | throw TimeoutException("Timed out while waiting for permission dialog.") 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/data/DataModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.twilio.video.app.data 18 | 19 | import android.app.Application 20 | import android.content.SharedPreferences 21 | import com.twilio.video.app.util.getSharedPreferences 22 | import dagger.Module 23 | import dagger.Provides 24 | import dagger.hilt.InstallIn 25 | import dagger.hilt.components.SingletonComponent 26 | 27 | @Module 28 | @InstallIn(SingletonComponent::class) 29 | class DataModule { 30 | @Provides 31 | internal fun provideSharedPreferences(app: Application): SharedPreferences { 32 | return getSharedPreferences(app) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/ui/settings/InternalSettingsFragment.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui.settings 2 | 3 | import android.os.Bundle 4 | import androidx.preference.ListPreference 5 | import com.twilio.video.app.R 6 | import com.twilio.video.app.data.Preferences 7 | import com.twilio.video.app.data.api.dto.Topology 8 | 9 | class InternalSettingsFragment : BaseSettingsFragment() { 10 | 11 | override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { 12 | addPreferencesFromResource(R.xml.internal_preferences) 13 | 14 | findPreference(Preferences.ENVIRONMENT)?.run { 15 | value = sharedPreferences.getString( 16 | Preferences.ENVIRONMENT, 17 | Preferences.ENVIRONMENT_DEFAULT, 18 | ) 19 | } 20 | 21 | findPreference(Preferences.TOPOLOGY)?.run { 22 | val roomTypes = Topology.values().map { it.value }.toTypedArray() 23 | entries = roomTypes 24 | entryValues = roomTypes 25 | value = sharedPreferences.getString( 26 | Preferences.TOPOLOGY, 27 | Preferences.TOPOLOGY_DEFAULT, 28 | ) 29 | } 30 | 31 | setHasOptionsMenu(true) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/res/xml/internal_preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 13 | 20 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/community/java/com/twilio/video/app/security/SecurePreferencesImpl.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.security 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import androidx.core.content.edit 6 | import androidx.security.crypto.EncryptedSharedPreferences 7 | import androidx.security.crypto.MasterKey 8 | 9 | class SecurePreferencesImpl( 10 | context: Context, 11 | preferences: SharedPreferences, 12 | ) : SecurePreferences { 13 | 14 | private val securePreferences: SharedPreferences 15 | 16 | init { 17 | val masterKey = MasterKey.Builder(context) 18 | .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) 19 | .build() 20 | 21 | securePreferences = EncryptedSharedPreferences.create( 22 | context, 23 | "secure_prefs", 24 | masterKey, 25 | EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, 26 | EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM, 27 | ) 28 | } 29 | 30 | override fun putSecureString(key: String, value: String) { 31 | securePreferences.edit { putString(key, value) } 32 | } 33 | 34 | override fun getSecureString(key: String): String? { 35 | return securePreferences.getString(key, null) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Twilions.md: -------------------------------------------------------------------------------- 1 | # Twilions 2 | 3 | Twilio employees should follow these instructions for building and testing the Twilio and Internal build variants. 4 | 5 | ## Build 6 | 7 | Download the google-services.json files here: 8 | * [Internal Debug (default)](https://console.firebase.google.com/project/video-app-79418/settings/general/android:com.twilio.video.app.internal.debug) - Download to `app/src/internal/debug` 9 | * [Internal Release](https://console.firebase.google.com/project/video-app-79418/settings/general/android:com.twilio.video.app.internal) - Download to `app/src/internal/release` 10 | 11 | After copying the above files the internal variant should build with no errors. However, when building the Twilio flavor, the app signing keystore is required. Please reach out to a developer on the team to get access to it. 12 | 13 | ## UI Tests 14 | 15 | ### Credentials 16 | 17 | 1. Make `Credentials` directory within the ```app/src/androidTest/assets``` directory. 18 | 1. Copy `TestCredentials.json.example` to `TestCredentials.json` within the ```Credentials``` directory and insert correct values for `email_sign_in_user`. 19 | 20 | ### Run 21 | 22 | * Android Studio - Right click and run unit tests on package ```app/src/androidTest/java/com/twilio/video/app``` 23 | * Terminal - ```./gradlew app:connectedInternalDebugAndroidTest``` 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/util/InputUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.twilio.video.app.util; 18 | 19 | import android.app.Activity; 20 | import android.content.Context; 21 | import android.view.View; 22 | import android.view.inputmethod.InputMethodManager; 23 | 24 | public final class InputUtils { 25 | 26 | public static void hideKeyboard(Activity activity) { 27 | View view = activity.getCurrentFocus(); 28 | if (view != null) { 29 | InputMethodManager imm = 30 | (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); 31 | imm.hideSoftInputFromWindow(view.getWindowToken(), 0); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/VideoApplication.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.twilio.video.app 18 | 19 | import android.app.Application 20 | import android.content.Context 21 | import androidx.multidex.MultiDex 22 | import dagger.hilt.android.HiltAndroidApp 23 | import timber.log.Timber 24 | import javax.inject.Inject 25 | 26 | @HiltAndroidApp 27 | class VideoApplication : Application() { 28 | @Inject 29 | lateinit var tree: Timber.Tree 30 | 31 | override fun attachBaseContext(base: Context) { 32 | super.attachBaseContext(base) 33 | MultiDex.install(this) 34 | } 35 | 36 | override fun onCreate() { 37 | super.onCreate() 38 | 39 | Timber.plant(tree) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/testCommunity/java/com/twilio/video/app/fake/MockCommunityAuthServiceModule.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.fake 2 | 3 | import android.content.SharedPreferences 4 | import com.twilio.video.app.android.SharedPreferencesWrapper 5 | import com.twilio.video.app.data.CommunityAuthServiceModule 6 | import com.twilio.video.app.data.api.AuthService 7 | import com.twilio.video.app.data.api.AuthServiceRepository 8 | import com.twilio.video.app.data.api.TokenService 9 | import com.twilio.video.app.security.SecurePreferences 10 | import dagger.Module 11 | import dagger.Provides 12 | import dagger.hilt.components.SingletonComponent 13 | import dagger.hilt.testing.TestInstallIn 14 | import org.mockito.kotlin.mock 15 | import javax.inject.Singleton 16 | 17 | @Module 18 | @TestInstallIn( 19 | components = [SingletonComponent::class], 20 | replaces = [CommunityAuthServiceModule::class], 21 | ) 22 | class MockCommunityAuthServiceModule { 23 | 24 | @Provides 25 | @Singleton 26 | fun providesAuthService(): AuthService = mock() 27 | 28 | @Provides 29 | fun providesTokenService( 30 | authService: AuthService, 31 | securePreferences: SecurePreferences, 32 | sharedPreferences: SharedPreferences, 33 | ): TokenService { 34 | return AuthServiceRepository(authService, securePreferences, SharedPreferencesWrapper(sharedPreferences)) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_thumbnail_no_audio.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/ui/room/RoomViewEvent.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui.room 2 | 3 | import android.content.Intent 4 | import com.twilio.audioswitch.AudioDevice 5 | 6 | sealed class RoomViewEvent { 7 | object OnResume : RoomViewEvent() 8 | object OnPause : RoomViewEvent() 9 | object ToggleLocalVideo : RoomViewEvent() 10 | object EnableLocalVideo : RoomViewEvent() 11 | object DisableLocalVideo : RoomViewEvent() 12 | object ToggleLocalAudio : RoomViewEvent() 13 | object EnableLocalAudio : RoomViewEvent() 14 | object DisableLocalAudio : RoomViewEvent() 15 | data class StartScreenCapture(val captureResultCode: Int, val captureIntent: Intent) : RoomViewEvent() 16 | object StopScreenCapture : RoomViewEvent() 17 | object SwitchCamera : RoomViewEvent() 18 | data class SelectAudioDevice(val device: AudioDevice) : RoomViewEvent() 19 | object ActivateAudioDevice : RoomViewEvent() 20 | object DeactivateAudioDevice : RoomViewEvent() 21 | data class Connect(val identity: String, val roomName: String) : RoomViewEvent() 22 | data class PinParticipant(val sid: String) : RoomViewEvent() 23 | data class VideoTrackRemoved(val sid: String) : RoomViewEvent() 24 | data class ScreenTrackRemoved(val sid: String) : RoomViewEvent() 25 | object Disconnect : RoomViewEvent() 26 | object ResumeVirtualBackground : RoomViewEvent() 27 | object PauseVirtualBackground : RoomViewEvent() 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #cc2b33 4 | #a52229 5 | #b0bec5 6 | #de000000 7 | #8a000000 8 | 9 | 10 | #80ffffff 11 | 12 | #757575 13 | #424242 14 | #9E9E9E 15 | 16 | #66000000 17 | #e0e0e0 18 | #80ffffff 19 | #1fffffff 20 | #80ffffff 21 | #CC9B9B9B 22 | #CC2B33 23 | 24 | #ccffffff 25 | #CC000000 26 | #cc2b33 27 | 28 | 29 | #66000000 30 | #cc000000 31 | #80000000 32 | 33 | -------------------------------------------------------------------------------- /app/src/testCommunity/java/com/twilio/video/app/util/AuthServiceTestData.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.util 2 | 3 | import com.twilio.video.app.data.api.AuthServiceResponseDTO 4 | import okhttp3.ResponseBody 5 | import org.mockito.kotlin.mock 6 | import org.mockito.kotlin.whenever 7 | import retrofit2.HttpException 8 | import retrofit2.Response 9 | 10 | const val INVALID_PASSCODE_ERROR = 11 | """{ 12 | "error": { 13 | "message": "passcode incorrect", 14 | "explanation": "The passcode used to validate application users is incorrect." 15 | } 16 | }""" 17 | 18 | const val EXPIRED_PASSCODE_ERROR = 19 | """{ 20 | "error": { 21 | "message": "passcode expired", 22 | "explanation": "The passcode used to validate application users has expired. Re-deploy the application to refresh the passcode." 23 | } 24 | }""" 25 | 26 | const val UNKNOWN_ERROR_MESSAGE = 27 | """{ 28 | "error": { 29 | "message": "Unknown", 30 | "explanation": "Something went wrong ¯\_(ツ)_/¯" 31 | } 32 | }""" 33 | 34 | fun getMockHttpException(errorBody: String?): HttpException { 35 | val responseBody: ResponseBody = mock { 36 | val errorString = errorBody 37 | whenever(mock.string()).thenReturn(errorString) 38 | } 39 | val response: Response = mock { 40 | whenever(mock.errorBody()).thenReturn(responseBody) 41 | } 42 | return HttpException(response) 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/util/CrashlyticsTreeRanger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.twilio.video.app.util; 18 | 19 | import com.google.firebase.crashlytics.FirebaseCrashlytics; 20 | import javax.inject.Inject; 21 | 22 | public class CrashlyticsTreeRanger implements TreeRanger { 23 | 24 | FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance(); 25 | 26 | @Inject 27 | public CrashlyticsTreeRanger() {} 28 | 29 | @Override 30 | public void inform(String message) { 31 | crashlytics.log(message); 32 | } 33 | 34 | @Override 35 | public void caution(String message) { 36 | crashlytics.log(message); 37 | } 38 | 39 | @Override 40 | public void alert(Throwable throwable) { 41 | crashlytics.recordException(throwable); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/data/api/dto/Topology.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.twilio.video.app.data.api.dto 17 | 18 | import com.google.gson.annotations.SerializedName 19 | 20 | private const val GROUP_ROOM_NAME = "group" 21 | private const val GROUP_SMALL_ROOM_NAME = "group-small" 22 | private const val PEER_TO_PEER_ROOM_NAME = "peer-to-peer" 23 | private const val GO_ROOM_NAME = "go" 24 | 25 | enum class Topology(val value: String) { 26 | @SerializedName(GROUP_ROOM_NAME) 27 | GROUP(GROUP_ROOM_NAME), 28 | 29 | @SerializedName(GROUP_SMALL_ROOM_NAME) 30 | GROUP_SMALL(GROUP_SMALL_ROOM_NAME), 31 | 32 | @SerializedName(PEER_TO_PEER_ROOM_NAME) 33 | PEER_TO_PEER(PEER_TO_PEER_ROOM_NAME), 34 | 35 | @SerializedName(GO_ROOM_NAME) 36 | GO(GO_ROOM_NAME), 37 | ; 38 | 39 | override fun toString() = value 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/ui/room/RoomViewState.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui.room 2 | 3 | import com.twilio.audioswitch.AudioDevice 4 | import com.twilio.video.app.participant.ParticipantViewState 5 | import com.twilio.video.app.sdk.RoomStats 6 | import com.twilio.video.app.sdk.VideoTrackViewState 7 | import com.twilio.video.app.ui.room.RoomViewConfiguration.Lobby 8 | import io.uniflow.core.flow.data.UIState 9 | 10 | data class RoomViewState( 11 | val primaryParticipant: ParticipantViewState, 12 | val title: String? = null, 13 | val participantThumbnails: List? = null, 14 | val selectedDevice: AudioDevice? = null, 15 | val availableAudioDevices: List? = null, 16 | val configuration: RoomViewConfiguration = Lobby, 17 | val isCameraEnabled: Boolean = false, 18 | val localVideoTrack: VideoTrackViewState? = null, 19 | val isMicEnabled: Boolean = false, 20 | val isAudioMuted: Boolean = false, 21 | val isAudioEnabled: Boolean = true, 22 | val isVideoEnabled: Boolean = true, 23 | val isVideoOff: Boolean = false, 24 | val isScreenCaptureOn: Boolean = false, 25 | val isRecording: Boolean = false, 26 | val roomStats: RoomStats? = null, 27 | val isVirtualBackgroundPaused: Boolean = false, 28 | ) : UIState() 29 | 30 | sealed class RoomViewConfiguration { 31 | object Connecting : RoomViewConfiguration() 32 | object Connected : RoomViewConfiguration() 33 | object Lobby : RoomViewConfiguration() 34 | } 35 | -------------------------------------------------------------------------------- /app/src/community/java/com/twilio/video/app/auth/CommunityAuthModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.twilio.video.app.auth 17 | 18 | import android.content.SharedPreferences 19 | import com.twilio.video.app.data.api.TokenService 20 | import com.twilio.video.app.security.SecurePreferences 21 | import dagger.Module 22 | import dagger.Provides 23 | import dagger.hilt.InstallIn 24 | import dagger.hilt.components.SingletonComponent 25 | import javax.inject.Singleton 26 | 27 | @Module 28 | @InstallIn(SingletonComponent::class) 29 | class CommunityAuthModule { 30 | @Provides 31 | @Singleton 32 | fun providesCommunityAuthenticator( 33 | preferences: SharedPreferences, 34 | securePreferences: SecurePreferences, 35 | tokenService: TokenService, 36 | ): Authenticator { 37 | return CommunityAuthenticator(preferences, securePreferences, tokenService) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/twilio/video/app/util/EspressoUtil.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.util 2 | 3 | import androidx.annotation.IdRes 4 | import androidx.recyclerview.widget.RecyclerView 5 | import androidx.test.espresso.Espresso.onView 6 | import androidx.test.espresso.action.ViewActions.click 7 | import androidx.test.espresso.assertion.ViewAssertions.matches 8 | import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItem 9 | import androidx.test.espresso.matcher.ViewMatchers.hasDescendant 10 | import androidx.test.espresso.matcher.ViewMatchers.isDisplayed 11 | import androidx.test.espresso.matcher.ViewMatchers.withId 12 | import androidx.test.espresso.matcher.ViewMatchers.withText 13 | import org.hamcrest.CoreMatchers.not 14 | 15 | fun clickView(viewText: String) { 16 | onView(withText(viewText)).perform(click()) 17 | } 18 | 19 | fun clickView(@IdRes id: Int) { 20 | onView(withId(id)).perform(click()) 21 | } 22 | 23 | fun scrollAndClickView(viewText: String, recyclerViewId: Int) { 24 | onView(withId(recyclerViewId)) 25 | .perform(actionOnItem(hasDescendant(withText(viewText)), click())) 26 | } 27 | 28 | fun assertTextIsDisplayed(text: String) { 29 | onView(withText(text)).check(matches(isDisplayed())) 30 | } 31 | 32 | fun assertTextIsDisplayedRetry(text: String) { 33 | retryEspressoAction { onView(withText(text)).check(matches(isDisplayed())) } 34 | } 35 | 36 | fun assertTextIsNotDisplayedRetry(text: String) { 37 | retryEspressoAction { onView(withText(text)).check(matches(not(isDisplayed()))) } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/res/menu/room_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 15 | 16 | 21 | 22 | 25 | 26 | 29 | 30 | 34 | 35 | 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: 5 | labels: "bug" 6 | assignees: 7 | 8 | --- 9 | 10 | 11 | > Before filing an issue please check that the issue is not already addressed by the following: 12 | > * [Video Guides](https://www.twilio.com/docs/api/video) 13 | > * [Github Issues](https://github.com/twilio/twilio-video-app-android/issues) 14 | > * [Changelog](https://github.com/twilio/twilio-video-app-android/blob/master/CHANGELOG.md) 15 | 16 | > Please ensure that you are not sharing any 17 | [Personally Identifiable Information(PII)](https://www.twilio.com/docs/glossary/what-is-personally-identifiable-information-pii) 18 | or sensitive account information (API keys, credentials, etc.) when reporting an issue. 19 | 20 | **Describe the bug** 21 | A clear and concise description of what the bug is. 22 | 23 | **To Reproduce** 24 | Steps to reproduce the behavior: 25 | 1. Go to '...' 26 | 2. Click on '....' 27 | 3. Scroll down to '....' 28 | 4. See error 29 | 30 | **Expected behavior** 31 | A clear and concise description of what you expected to happen. 32 | 33 | **Screenshots** 34 | If applicable, add screenshots to help explain your problem. 35 | 36 | **Android Device (please complete the following information):** 37 | - Device: (e.g. Pixel 4) 38 | - API Version: (e.g. API 29) 39 | 40 | **Video Android SDK (please complete the following information):** 41 | - Version: (e.g. 5.1.0) 42 | 43 | **Additional context** 44 | Add any other context about the problem here. 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/ui/room/RoomViewModelModule.kt: -------------------------------------------------------------------------------- 1 | package com.twilio.video.app.ui.room 2 | 3 | import android.app.Application 4 | import com.twilio.audioswitch.AudioDevice 5 | import com.twilio.audioswitch.AudioSwitch 6 | import com.twilio.video.app.participant.ParticipantManager 7 | import com.twilio.video.app.util.PermissionUtil 8 | import dagger.Module 9 | import dagger.Provides 10 | import dagger.hilt.InstallIn 11 | import dagger.hilt.android.components.ViewModelComponent 12 | import dagger.hilt.android.scopes.ViewModelScoped 13 | 14 | @Module 15 | @InstallIn(ViewModelComponent::class) 16 | class RoomViewModelModule { 17 | 18 | @Provides 19 | @ViewModelScoped 20 | fun providesPermissionUtil(application: Application) = PermissionUtil(application) 21 | 22 | @Provides 23 | @ViewModelScoped 24 | fun providesParticipantManager() = ParticipantManager() 25 | 26 | @Provides 27 | @ViewModelScoped 28 | fun providesInitialViewState(participantManager: ParticipantManager) = RoomViewState(participantManager.primaryParticipant) 29 | 30 | @Provides 31 | @ViewModelScoped 32 | fun providesAudioSwitch(application: Application): AudioSwitch = 33 | AudioSwitch( 34 | application, 35 | loggingEnabled = true, 36 | preferredDeviceList = listOf( 37 | AudioDevice.BluetoothHeadset::class.java, 38 | AudioDevice.WiredHeadset::class.java, 39 | AudioDevice.Speakerphone::class.java, 40 | AudioDevice.Earpiece::class.java, 41 | ), 42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/twilio/video/app/util/EnvUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Twilio, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.twilio.video.app.util; 18 | 19 | import static com.twilio.video.app.data.api.TwilioApiEnvironmentKt.TWILIO_API_DEV_ENV; 20 | import static com.twilio.video.app.data.api.TwilioApiEnvironmentKt.TWILIO_API_STAGE_ENV; 21 | 22 | public class EnvUtil { 23 | private static final String TWILIO_DEV_ENV = "Development"; 24 | private static final String TWILIO_STAGE_ENV = "Staging"; 25 | private static final String TWILIO_PROD_ENV = "Production"; 26 | public static final String TWILIO_ENV_KEY = "TWILIO_ENVIRONMENT"; 27 | 28 | public static String getNativeEnvironmentVariableValue(String environment) { 29 | if (environment != null) { 30 | if (environment.equals(TWILIO_API_DEV_ENV)) { 31 | return TWILIO_DEV_ENV; 32 | } else if (environment.equals(TWILIO_API_STAGE_ENV)) { 33 | return TWILIO_STAGE_ENV; 34 | } 35 | } 36 | 37 | return TWILIO_PROD_ENV; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/join_room.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 |