├── .gitignore ├── ActivityEmbeddingSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── activityembeddingsample │ │ │ ├── ActivityEmbeddingSampleApplication.kt │ │ │ ├── FABSplitListener.kt │ │ │ ├── details │ │ │ ├── DetailsActivity.kt │ │ │ └── DetailsPlaceholderActivity.kt │ │ │ ├── list │ │ │ ├── LettersAdapter.kt │ │ │ ├── ListActivity.kt │ │ │ └── ListViewModel.kt │ │ │ └── share │ │ │ └── ShareActivity.kt │ │ └── res │ │ ├── drawable │ │ └── ic_fab.xml │ │ ├── layout │ │ ├── activity_details.xml │ │ ├── activity_details_placeholder.xml │ │ ├── activity_list.xml │ │ ├── activity_share.xml │ │ └── item_list.xml │ │ ├── values-night │ │ └── themes.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ ├── data_extraction_rules.xml │ │ └── split_configuration.xml ├── art │ └── activity-embedding-demo.gif ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── BasicCoroutinesSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── basiccoroutinessample │ │ │ └── MainActivity.kt │ │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── themes.xml ├── art │ ├── cancel_jobs.png │ └── start_jobs.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── BiometricSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── biometricsample │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── husaynhakeem │ │ │ │ └── biometricsample │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── biometric │ │ │ │ ├── BiometricAuthenticator.kt │ │ │ │ ├── BiometricAuthenticatorApi23.kt │ │ │ │ ├── BiometricAuthenticatorApi30.kt │ │ │ │ ├── BiometricAuthenticatorLegacy.kt │ │ │ │ └── BiometricCodeConversions.kt │ │ │ │ └── crypto │ │ │ │ ├── CryptographyManager.kt │ │ │ │ ├── CryptographyManagerApi23.kt │ │ │ │ ├── CryptographyManagerApi30.kt │ │ │ │ ├── CryptographyManagerCommon.kt │ │ │ │ ├── CryptographyManagerLegacy.kt │ │ │ │ ├── EncryptedData.kt │ │ │ │ └── EncryptionMode.kt │ │ └── res │ │ │ ├── layout │ │ │ ├── activity_main.xml │ │ │ ├── layout_authenticate.xml │ │ │ ├── layout_authentication_confirmation.xml │ │ │ ├── layout_authenticator_types.xml │ │ │ ├── layout_configuration_change.xml │ │ │ ├── layout_logging.xml │ │ │ └── layout_negative_button.xml │ │ │ ├── values-night │ │ │ └── themes.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── themes.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── husaynhakeem │ │ └── biometricsample │ │ └── ExampleUnitTest.kt ├── art │ ├── biometric_main_screen.png │ ├── biometric_pin_authentication.png │ ├── biometric_prompt.png │ └── biometric_sample.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── Camera2Sample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── camera2sample │ │ │ ├── CameraFragment.kt │ │ │ ├── DeviceRotationListener.kt │ │ │ ├── ExifOrientationSetter.kt │ │ │ ├── ImageSaver.kt │ │ │ ├── LensFacing.kt │ │ │ ├── Logger.kt │ │ │ ├── MainActivity.kt │ │ │ ├── PermissionsFragment.kt │ │ │ └── PreviewView.kt │ │ └── res │ │ ├── drawable │ │ └── icon_take_picture.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ └── fragment_camera.xml │ │ ├── navigation │ │ └── navigation_graph.xml │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml ├── art │ └── camera2.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── ComposePlayground ├── BarberSample │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── .gitignore │ │ ├── build.gradle │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── husaynhakeem │ │ │ │ └── barberapp │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── data │ │ │ │ ├── Barbers.kt │ │ │ │ └── Services.kt │ │ │ │ ├── screen │ │ │ │ ├── home │ │ │ │ │ ├── Barbers.kt │ │ │ │ │ ├── BarbersPreviews.kt │ │ │ │ │ ├── HomeScreen.kt │ │ │ │ │ ├── HomeScreenPreviews.kt │ │ │ │ │ ├── HomeSection.kt │ │ │ │ │ ├── HomeSectionPreviews.kt │ │ │ │ │ ├── PromoCard.kt │ │ │ │ │ ├── PromoCardPreviews.kt │ │ │ │ │ ├── Services.kt │ │ │ │ │ └── ServicesPreviews.kt │ │ │ │ ├── landing │ │ │ │ │ ├── AutoFitText.kt │ │ │ │ │ ├── LandingScreen.kt │ │ │ │ │ └── LandingScreenPreviews.kt │ │ │ │ └── shared │ │ │ │ │ ├── ActionButton.kt │ │ │ │ │ └── ActionButtonPreviews.kt │ │ │ │ └── ui │ │ │ │ └── theme │ │ │ │ ├── Color.kt │ │ │ │ ├── Shape.kt │ │ │ │ ├── Theme.kt │ │ │ │ └── Type.kt │ │ │ └── res │ │ │ ├── drawable │ │ │ ├── barber_landing_background.png │ │ │ └── barber_landing_logo.png │ │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── themes.xml │ │ │ └── xml │ │ │ ├── backup_rules.xml │ │ │ └── data_extraction_rules.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── README.md └── SideEffectsSample │ ├── .gitignore │ ├── README.md │ ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── sideeffectssample │ │ │ ├── Logger.kt │ │ │ ├── MainActivity.kt │ │ │ ├── screen │ │ │ ├── DerivedStateOfScreen.kt │ │ │ ├── DisposableEffectScreen.kt │ │ │ ├── HomeScreen.kt │ │ │ ├── LaunchedEffectScreen.kt │ │ │ ├── ProduceStateScreen.kt │ │ │ ├── RememberCoroutineScopeScreen.kt │ │ │ ├── RememberUpdatedStateScreen.kt │ │ │ └── SideEffectScreen.kt │ │ │ └── ui │ │ │ └── theme │ │ │ ├── Color.kt │ │ │ ├── Shape.kt │ │ │ ├── Theme.kt │ │ │ └── Type.kt │ │ └── res │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── ComposeSettingsSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── composesettingssample │ │ │ ├── SettingsTest.kt │ │ │ └── ui │ │ │ ├── AppVersionSettingTest.kt │ │ │ ├── HintsSettingTest.kt │ │ │ ├── ManageSubscriptionSettingTest.kt │ │ │ ├── MarketingOptionsSettingTest.kt │ │ │ ├── NotificationsSettingTest.kt │ │ │ └── ThemeSettingTest.kt │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── composesettingssample │ │ │ ├── MainActivity.kt │ │ │ ├── SettingsState.kt │ │ │ ├── SettingsViewModel.kt │ │ │ └── ui │ │ │ ├── AppVersionSetting.kt │ │ │ ├── HintsSetting.kt │ │ │ ├── ManageSubscriptionSetting.kt │ │ │ ├── MarketingOptionsSetting.kt │ │ │ ├── NotificationsSetting.kt │ │ │ ├── SectionSpacer.kt │ │ │ ├── SettingItem.kt │ │ │ ├── Settings.kt │ │ │ ├── SettingsList.kt │ │ │ ├── Tags.kt │ │ │ ├── ThemeSetting.kt │ │ │ └── theme │ │ │ ├── Color.kt │ │ │ ├── Shape.kt │ │ │ ├── Theme.kt │ │ │ └── Type.kt │ │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── ComposeStateSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── husaynhakeem │ │ │ │ └── composestatesample │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── MainViewModel.kt │ │ │ │ ├── PokemonList.kt │ │ │ │ ├── data │ │ │ │ ├── Models.kt │ │ │ │ ├── PokemonContainer.kt │ │ │ │ ├── PokemonRepository.kt │ │ │ │ ├── fake │ │ │ │ │ └── FakePokemonContainer.kt │ │ │ │ └── impl │ │ │ │ │ ├── InMemoryPokemonContainer.kt │ │ │ │ │ └── InternalPokemonRepository.kt │ │ │ │ ├── ui │ │ │ │ ├── Color.kt │ │ │ │ ├── Shape.kt │ │ │ │ ├── Theme.kt │ │ │ │ └── Type.kt │ │ │ │ └── widget │ │ │ │ ├── LazyGridForIndexed.kt │ │ │ │ ├── PokemonHolder.kt │ │ │ │ ├── PokemonId.kt │ │ │ │ ├── PokemonSprite.kt │ │ │ │ └── PokemonsGrid.kt │ │ └── res │ │ │ ├── drawable │ │ │ └── ic_error.xml │ │ │ ├── values-night │ │ │ └── themes.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── themes.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── husaynhakeem │ │ └── composestatesample │ │ ├── MainDispatcherRule.kt │ │ ├── MainViewModelTest.kt │ │ └── data │ │ └── impl │ │ └── InternalPokemonRepositoryTest.kt ├── art │ └── android-jetpack-compose-state-sample.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties └── settings.gradle ├── DaggerSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── daggersample │ │ │ ├── DaggerApp.kt │ │ │ ├── MainActivity.kt │ │ │ ├── base │ │ │ ├── Presenter.kt │ │ │ └── View.kt │ │ │ ├── di │ │ │ ├── AppComponent.kt │ │ │ ├── AppModule.kt │ │ │ ├── FeatureComponent.kt │ │ │ ├── FeatureModule.kt │ │ │ ├── FeatureScope.kt │ │ │ ├── StatsModule.kt │ │ │ └── ThirdPartyStatsModule.kt │ │ │ ├── model │ │ │ └── News.kt │ │ │ ├── presenter │ │ │ ├── AllNewsPresenter.kt │ │ │ ├── NewsItemPresenter.kt │ │ │ └── impl │ │ │ │ ├── AllNewsPresenterImpl.kt │ │ │ │ └── NewsItemPresenterImpl.kt │ │ │ ├── repository │ │ │ ├── NewsRepository.kt │ │ │ └── impl │ │ │ │ └── InMemoryNewsRepository.kt │ │ │ ├── stats │ │ │ ├── NewsStats.kt │ │ │ └── impl │ │ │ │ ├── LengthNewsStats.kt │ │ │ │ └── WordCountNewsStats.kt │ │ │ └── view │ │ │ ├── AllNewsView.kt │ │ │ ├── NewsItemView.kt │ │ │ └── impl │ │ │ ├── AllNewsAdapter.kt │ │ │ ├── AllNewsFragment.kt │ │ │ └── NewsItemFragment.kt │ │ └── res │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── fragment_all_news.xml │ │ ├── fragment_news_item.xml │ │ └── list_item_all_news.xml │ │ ├── values-night │ │ └── styles.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── art │ ├── all_news_screen.png │ └── news_item_screen.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── DataStoreSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── datastoresample │ │ │ ├── MainActivity.kt │ │ │ ├── MainViewModel.kt │ │ │ ├── ServiceLocator.kt │ │ │ ├── data │ │ │ ├── NightModePreference.kt │ │ │ ├── UserDataStore.kt │ │ │ └── UserSerializer.kt │ │ │ ├── home │ │ │ ├── HomeFragment.kt │ │ │ └── HomeViewModel.kt │ │ │ └── login │ │ │ ├── LoginFragment.kt │ │ │ └── LoginViewModel.kt │ │ ├── proto │ │ └── person_proto.proto │ │ └── res │ │ ├── drawable │ │ ├── ic_dark_mode.xml │ │ └── ic_light_mode.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── fragment_home.xml │ │ └── fragment_login.xml │ │ ├── menu │ │ └── main_menu.xml │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml ├── art │ ├── data-store-sample.png │ ├── log-in-day.png │ ├── log-in-night.png │ ├── logged-in-day.png │ └── logged-in-night.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── FaceDetectorSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── facedetectorsample │ │ │ ├── AnalysisFaceDetector.kt │ │ │ ├── CameraViewModel.kt │ │ │ ├── FaceBoundsOverlay.kt │ │ │ └── MainActivity.kt │ │ └── res │ │ ├── layout-land │ │ └── activity_main.xml │ │ ├── layout │ │ └── activity_main.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── art │ ├── art_landscape.png │ └── art_portrait.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── FragmentResultSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── fragmentresultsample │ │ │ ├── FragmentScenarioExtensions.kt │ │ │ ├── child_to_parent │ │ │ ├── ChildFragmentTest.kt │ │ │ └── ParentFragmentTest.kt │ │ │ └── fragment_to_fragment │ │ │ ├── ResultFragmentTest.kt │ │ │ └── ResultListenerFragmentTest.kt │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── fragmentresultsample │ │ │ ├── MainActivity.kt │ │ │ ├── child_to_parent │ │ │ ├── ChildFragment.kt │ │ │ └── ParentFragment.kt │ │ │ └── fragment_to_fragment │ │ │ ├── ResultFragment.kt │ │ │ └── ResultListenerFragment.kt │ │ └── res │ │ ├── layout-land │ │ └── fragment_parent.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── fragment_child.xml │ │ ├── fragment_parent.xml │ │ ├── fragment_result.xml │ │ └── fragment_result_listener.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── GesturesSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── gesturessample │ │ │ ├── DrawingCanvas.kt │ │ │ ├── MainActivity.kt │ │ │ └── extension │ │ │ ├── MotionEventExtensions.kt │ │ │ ├── ScaleGestureExtensions.kt │ │ │ └── TextViewExtensions.kt │ │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── GlanceSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── glancesample │ │ │ ├── MainActivity.kt │ │ │ ├── MainViewModel.kt │ │ │ ├── ui │ │ │ └── theme │ │ │ │ ├── Color.kt │ │ │ │ ├── Shape.kt │ │ │ │ ├── Theme.kt │ │ │ │ └── Type.kt │ │ │ ├── util │ │ │ ├── LoggingUtils.kt │ │ │ ├── SizeUtils.kt │ │ │ └── ToastUtils.kt │ │ │ └── widget │ │ │ ├── ErrorUIWidget.kt │ │ │ ├── HelloWorldWidget.kt │ │ │ ├── ListWidget.kt │ │ │ ├── StatefulWidget.kt │ │ │ ├── action │ │ │ ├── ActionWidget.kt │ │ │ ├── DummyActivity.kt │ │ │ ├── DummyBroadcastReceiver.kt │ │ │ └── DummyService.kt │ │ │ ├── interop │ │ │ ├── RemoteViewInteropWidget.kt │ │ │ └── RemoteViewWidget.kt │ │ │ └── size │ │ │ ├── SizeExactWidget.kt │ │ │ ├── SizeResponsiveWidget.kt │ │ │ └── SizeSingleWidget.kt │ │ └── res │ │ ├── drawable │ │ ├── ic_action.xml │ │ ├── ic_error_ui.xml │ │ ├── ic_hello_world.xml │ │ ├── ic_interop.xml │ │ ├── ic_list.xml │ │ ├── ic_size_mode.xml │ │ └── ic_stateful.xml │ │ ├── layout │ │ ├── layout_widget_custom_error.xml │ │ ├── layout_widget_initial.xml │ │ └── widget_remote_view.xml │ │ ├── values-night │ │ └── themes.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── widget_action_info.xml │ │ ├── widget_error_ui_info.xml │ │ ├── widget_hello_world_info.xml │ │ ├── widget_interop_info.xml │ │ ├── widget_list_info.xml │ │ ├── widget_size_exact_info.xml │ │ ├── widget_size_responsive_info.xml │ │ ├── widget_size_single_info.xml │ │ └── widget_stateful_info.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshot │ ├── widget-action.png │ ├── widget-error-ui.png │ ├── widget-hello-world.png │ ├── widget-interop.png │ ├── widget-list.png │ ├── widget-size-exact.png │ ├── widget-size-responsive.png │ ├── widget-size-single.png │ ├── widget-stateful.png │ └── widgets-glance.png └── settings.gradle ├── GradleDependencyConfigsSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── gradledependencyconfigssample │ │ │ ├── LoggerImplementationNotFoundException.kt │ │ │ ├── LoggerProvider.kt │ │ │ └── MainActivity.kt │ │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml ├── build.gradle ├── compileonly │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── husaynhakeem │ │ └── compileonly │ │ └── Logger.kt ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── otherruntimeonly │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── husaynhakeem │ │ └── otherruntimeonly │ │ └── OtherRuntimeOnlyLogger.kt ├── runtimeonly │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── husaynhakeem │ │ └── runtimeonly │ │ └── RuntimeOnlyLogger.kt └── settings.gradle ├── HiltSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── hiltsample │ │ │ ├── HiltSampleApplication.kt │ │ │ ├── MainActivity.kt │ │ │ ├── data │ │ │ ├── Post.kt │ │ │ ├── PostsDataSource.kt │ │ │ ├── PostsFakeDataSource.kt │ │ │ └── PostsRemoteDataSource.kt │ │ │ ├── di │ │ │ ├── ConcurrencyModule.kt │ │ │ ├── NetworkModule.kt │ │ │ └── PostsDataSourceModule.kt │ │ │ ├── network │ │ │ └── PostsService.kt │ │ │ └── ui │ │ │ ├── PostsAdapter.kt │ │ │ ├── PostsFragment.kt │ │ │ └── PostsViewModel.kt │ │ └── res │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── fragment_posts.xml │ │ └── item_post.xml │ │ ├── values-night │ │ └── styles.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── art │ └── art.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── InstrumentationSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── instrumentationsample │ │ │ ├── ActivityLifecycleTest.kt │ │ │ ├── ActivityMonitorTest.kt │ │ │ ├── LogAssert.kt │ │ │ └── NewActivityTest.kt │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── instrumentationsample │ │ │ ├── Logger.kt │ │ │ └── MainActivity.kt │ │ └── res │ │ ├── values-night │ │ └── styles.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── MapsSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── res │ │ │ └── values │ │ │ └── google_maps_api.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── husaynhakeem │ │ │ │ └── mapssample │ │ │ │ ├── LocationProvider.kt │ │ │ │ └── MapsActivity.kt │ │ └── res │ │ │ ├── layout │ │ │ └── activity_maps.xml │ │ │ ├── menu │ │ │ └── menu_maps.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── release │ │ └── res │ │ └── values │ │ └── google_maps_api.xml ├── art │ └── art.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── MenuHostSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── menuhostsample │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── husaynhakeem │ │ │ │ └── menuhostsample │ │ │ │ ├── ActivityExtensions.kt │ │ │ │ ├── ActivityOwnedAppBarProfileFragment.kt │ │ │ │ ├── FragmentOwnedAppBarProfileFragment.kt │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── MenuHostProfileFragment.kt │ │ │ │ └── MenuHostViewPagerActivity.kt │ │ └── res │ │ │ ├── drawable │ │ │ ├── ic_back.xml │ │ │ └── ic_save_profile.xml │ │ │ ├── layout │ │ │ ├── activity_main.xml │ │ │ ├── activity_menu_host_view_pager.xml │ │ │ ├── fragment_menu_host_view_pager.xml │ │ │ ├── fragment_profile_activity_owned_appbar.xml │ │ │ ├── fragment_profile_fragment_owned_appbar.xml │ │ │ └── fragment_profile_menu_host.xml │ │ │ ├── menu │ │ │ ├── menu_main.xml │ │ │ ├── menu_profile.xml │ │ │ └── menu_view_pager.xml │ │ │ ├── navigation │ │ │ └── nav_graph.xml │ │ │ ├── values-night │ │ │ └── themes.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── themes.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── husaynhakeem │ │ └── menuhostsample │ │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── README.md ├── RenderEffectSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── rendereffectsample │ │ │ ├── BlurEffectFragment.kt │ │ │ ├── ColorFilterEffectFragment.kt │ │ │ ├── MainActivity.kt │ │ │ ├── MainFragment.kt │ │ │ └── OffsetEffectFragment.kt │ │ └── res │ │ ├── drawable │ │ └── test_image.jpg │ │ ├── layout │ │ ├── choice_chip.xml │ │ ├── fragment_blur_effect.xml │ │ ├── fragment_color_filter_effect.xml │ │ ├── fragment_main.xml │ │ ├── fragment_offset_effect.xml │ │ └── main_activity.xml │ │ ├── navigation │ │ └── nav_graph.xml │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml ├── art │ ├── blur-effect.gif │ ├── color-filter-effect.gif │ └── offset-effect.gif ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── StartupSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── startupsample │ │ │ └── MainActivity.kt │ │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ └── values │ │ └── strings.xml ├── build.gradle ├── first-dependency │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── husaynhakeem │ │ └── first_dependency │ │ ├── Initializer1A.kt │ │ └── Initializer1B.kt ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── second-dependency │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── husaynhakeem │ │ └── second_dependency │ │ ├── Initializer2A.kt │ │ ├── Initializer2B.kt │ │ └── Initializer2C.kt └── settings.gradle ├── ThermalSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── thermalsample │ │ │ ├── MainActivity.kt │ │ │ ├── MainViewModel.kt │ │ │ ├── ThermalNotification.kt │ │ │ ├── ThermalService.kt │ │ │ └── ThermalStatus.kt │ │ └── res │ │ ├── drawable │ │ └── ic_notification.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── values-night │ │ └── styles.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── art │ ├── start-thermal-service.png │ ├── stop-thermal-service.png │ ├── thermal-api-not-supported.png │ ├── thermal-sample.png │ └── thermal-status-update.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── ViewBindingSample ├── .gitignore ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── viewbindingsample │ │ │ ├── FragmentBindTest.kt │ │ │ ├── FragmentInflateTest.kt │ │ │ └── MainActivityTest.kt │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── husaynhakeem │ │ │ └── viewbindingsample │ │ │ ├── FragmentBind.kt │ │ │ ├── FragmentInflate.kt │ │ │ └── MainActivity.kt │ │ └── res │ │ ├── layout-land │ │ └── fragment_bind.xml │ │ ├── layout-v23 │ │ └── fragment_inflate.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── fragment_bind.xml │ │ └── fragment_inflate.xml │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml ├── art │ ├── view_binding_landscape.png │ └── view_binding_portrait.png ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle └── WebSocketSample ├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── husaynhakeem │ │ └── websocketsample │ │ ├── MainActivity.kt │ │ ├── MainViewModel.kt │ │ └── network │ │ ├── BtcWebSocket.kt │ │ └── model │ │ ├── Channel.kt │ │ └── Subscription.kt │ └── res │ ├── layout │ └── activity_main.xml │ ├── values-night │ └── themes.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── themes.xml ├── art └── web-socket-android.gif ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | /**/.gradle 4 | /**/.idea 5 | /**/build -------------------------------------------------------------------------------- /ActivityEmbeddingSample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/ 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | local.properties 11 | -------------------------------------------------------------------------------- /ActivityEmbeddingSample/README.md: -------------------------------------------------------------------------------- 1 | # Activity Embedding 2 | 3 | Android sample app to learn about the recently added `Activity` embedding APIs in Jetpack `WindowManager`. I wrote about the topic in [this blog post](https://medium.com/proandroiddev/activity-embedding-in-android-b07da14b715). 4 | 5 | ![Activity embedding demo](https://github.com/husaynhakeem/android-playground/blob/master/ActivityEmbeddingSample/art/activity-embedding-demo.gif) 6 | -------------------------------------------------------------------------------- /ActivityEmbeddingSample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /ActivityEmbeddingSample/app/src/main/java/com/husaynhakeem/activityembeddingsample/ActivityEmbeddingSampleApplication.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.activityembeddingsample 2 | 3 | import android.app.Application 4 | import android.widget.Toast 5 | import androidx.window.core.ExperimentalWindowApi 6 | import androidx.window.embedding.SplitController 7 | 8 | class ActivityEmbeddingSampleApplication : Application() { 9 | 10 | @OptIn(ExperimentalWindowApi::class) 11 | override fun onCreate() { 12 | super.onCreate() 13 | SplitController.initialize(this, R.xml.split_configuration) 14 | 15 | val splitController = SplitController.getInstance() 16 | if (!splitController.isSplitSupported()) { 17 | Toast.makeText(this, R.string.split_not_supported, Toast.LENGTH_LONG).show() 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /ActivityEmbeddingSample/app/src/main/java/com/husaynhakeem/activityembeddingsample/details/DetailsPlaceholderActivity.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.activityembeddingsample.details 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import com.husaynhakeem.activityembeddingsample.databinding.ActivityDetailsPlaceholderBinding 6 | 7 | class DetailsPlaceholderActivity : AppCompatActivity() { 8 | 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | 12 | val binding = ActivityDetailsPlaceholderBinding.inflate(layoutInflater) 13 | setContentView(binding.root) 14 | } 15 | } -------------------------------------------------------------------------------- /ActivityEmbeddingSample/app/src/main/java/com/husaynhakeem/activityembeddingsample/list/ListViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.activityembeddingsample.list 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.ViewModel 6 | 7 | class ListViewModel : ViewModel() { 8 | 9 | val letters: LiveData> = MutableLiveData(allUppercaseLetters()) 10 | 11 | private fun allUppercaseLetters(): List { 12 | return ('A'..'Z').map { it.toString() } 13 | } 14 | } -------------------------------------------------------------------------------- /ActivityEmbeddingSample/app/src/main/res/drawable/ic_fab.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /ActivityEmbeddingSample/app/src/main/res/layout/item_list.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ActivityEmbeddingSample/app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /ActivityEmbeddingSample/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF000000 4 | #FFFFFFFF 5 | -------------------------------------------------------------------------------- /ActivityEmbeddingSample/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Activity Embedding 3 | Settings 4 | Just the letter 5 | Letters 6 | Select a letter 7 | Share 8 | Sending the letter %s to people nearby by telepathy 9 | Random button 10 | Split is not supported on this device 11 | -------------------------------------------------------------------------------- /ActivityEmbeddingSample/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 7 | -------------------------------------------------------------------------------- /ComposePlayground/BarberSample/app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /ComposePlayground/BarberSample/app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /ComposePlayground/BarberSample/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | compose_ui_version = '1.1.1' 4 | } 5 | }// Top-level build file where you can add configuration options common to all sub-projects/modules. 6 | plugins { 7 | id 'com.android.application' version '7.3.0-rc01' apply false 8 | id 'com.android.library' version '7.3.0-rc01' apply false 9 | id 'org.jetbrains.kotlin.android' version '1.6.10' apply false 10 | } -------------------------------------------------------------------------------- /ComposePlayground/BarberSample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposePlayground/BarberSample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /ComposePlayground/BarberSample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Sep 12 22:33:09 PDT 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /ComposePlayground/BarberSample/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | rootProject.name = "BarberApp" 16 | include ':app' 17 | -------------------------------------------------------------------------------- /ComposePlayground/README.md: -------------------------------------------------------------------------------- 1 | # Jetpack Compose playground 2 | 3 | Collection of Android sample apps built to learn Jetpack compose. 4 | -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/app/src/main/java/com/husaynhakeem/sideeffectssample/Logger.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.sideeffectssample 2 | 3 | import android.util.Log 4 | 5 | fun log(message: String) { 6 | Log.d("SideEffectSample", message) 7 | } -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/app/src/main/java/com/husaynhakeem/sideeffectssample/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.sideeffectssample.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple200 = Color(0xFFBB86FC) 6 | val Purple500 = Color(0xFF6200EE) 7 | val Purple700 = Color(0xFF3700B3) 8 | val Teal200 = Color(0xFF03DAC5) -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/app/src/main/java/com/husaynhakeem/sideeffectssample/ui/theme/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.sideeffectssample.ui.theme 2 | 3 | import androidx.compose.foundation.shape.RoundedCornerShape 4 | import androidx.compose.material.Shapes 5 | import androidx.compose.ui.unit.dp 6 | 7 | val Shapes = Shapes( 8 | small = RoundedCornerShape(4.dp), 9 | medium = RoundedCornerShape(4.dp), 10 | large = RoundedCornerShape(0.dp) 11 | ) -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SideEffectsSample 3 | -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | }// Top-level build file where you can add configuration options common to all sub-projects/modules. 3 | plugins { 4 | id 'com.android.application' version '7.3.0-rc01' apply false 5 | id 'com.android.library' version '7.3.0-rc01' apply false 6 | id 'org.jetbrains.kotlin.android' version '1.6.10' apply false 7 | } -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposePlayground/SideEffectsSample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Oct 17 20:35:04 PDT 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /ComposePlayground/SideEffectsSample/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | rootProject.name = "SideEffectsSample" 16 | include ':app' 17 | -------------------------------------------------------------------------------- /ComposeSettingsSample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /ComposeSettingsSample/README.md: -------------------------------------------------------------------------------- 1 | # Jetpack Compose Settings 2 | 3 | Android sample app to learn about a couple of things in Jetpack compose: 4 | - Using basic composables, including radio buttons, dropdown menus, checkboxes, etc. 5 | - Building reusable composables. 6 | - State hoisting. 7 | - Writing instrumentation tests for composables. 8 | 9 | compose-settings-screenshot 10 | -------------------------------------------------------------------------------- /ComposeSettingsSample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/java/com/husaynhakeem/composesettingssample/SettingsState.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composesettingssample 2 | 3 | import androidx.annotation.StringRes 4 | 5 | data class SettingsState( 6 | val notificationsEnabled: Boolean = false, 7 | val hintsEnabled: Boolean = false, 8 | val marketingOption: MarketingOption = MarketingOption.ALLOWED, 9 | val themeOption: Theme = Theme.SYSTEM, 10 | ) 11 | 12 | enum class MarketingOption(val id: Int) { 13 | ALLOWED(0), 14 | NOT_ALLOWED(1), 15 | } 16 | 17 | enum class Theme(@StringRes val label: Int) { 18 | LIGHT(R.string.theme_light), 19 | DARK(R.string.theme_dark), 20 | SYSTEM(R.string.theme_system), 21 | } -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/java/com/husaynhakeem/composesettingssample/ui/SettingItem.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composesettingssample.ui 2 | 3 | import androidx.compose.foundation.layout.heightIn 4 | import androidx.compose.material.Surface 5 | import androidx.compose.runtime.Composable 6 | import androidx.compose.ui.Modifier 7 | import androidx.compose.ui.unit.dp 8 | 9 | 10 | @Composable 11 | fun SettingItem( 12 | modifier: Modifier = Modifier, 13 | content: @Composable () -> Unit, 14 | ) { 15 | Surface( 16 | modifier = modifier 17 | .heightIn(min = 56.dp), 18 | ) { 19 | content() 20 | } 21 | } -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/java/com/husaynhakeem/composesettingssample/ui/Settings.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composesettingssample.ui 2 | 3 | import androidx.compose.material.MaterialTheme 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.runtime.collectAsState 6 | import androidx.compose.ui.Modifier 7 | import androidx.lifecycle.viewmodel.compose.viewModel 8 | import com.husaynhakeem.composesettingssample.SettingsViewModel 9 | 10 | 11 | @Composable 12 | fun Settings() { 13 | val viewModel: SettingsViewModel = viewModel() 14 | MaterialTheme { 15 | val state = viewModel.uiState.collectAsState() 16 | SettingsList( 17 | modifier = Modifier, 18 | state = state.value, 19 | viewModel = viewModel 20 | ) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/java/com/husaynhakeem/composesettingssample/ui/Tags.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composesettingssample.ui 2 | 3 | object Tags { 4 | 5 | const val TAG_TOGGLE_ITEM = "toggle_item" 6 | const val TAG_CHECK_ITEM = "check_item" 7 | const val TAG_MARKETING_OPTION = "marketing_option_" 8 | const val TAG_THEME = "theme" 9 | const val TAG_SELECT_THEME = "select_theme" 10 | const val TAG_THEME_OPTION = "theme_" 11 | } -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/java/com/husaynhakeem/composesettingssample/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composesettingssample.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple200 = Color(0xFFBB86FC) 6 | val Purple500 = Color(0xFF6200EE) 7 | val Purple700 = Color(0xFF3700B3) 8 | val Teal200 = Color(0xFF03DAC5) -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/java/com/husaynhakeem/composesettingssample/ui/theme/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composesettingssample.ui.theme 2 | 3 | import androidx.compose.foundation.shape.RoundedCornerShape 4 | import androidx.compose.material.Shapes 5 | import androidx.compose.ui.unit.dp 6 | 7 | val Shapes = Shapes( 8 | small = RoundedCornerShape(4.dp), 9 | medium = RoundedCornerShape(4.dp), 10 | large = RoundedCornerShape(0.dp) 11 | ) -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeSettingsSample/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeSettingsSample/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeSettingsSample/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeSettingsSample/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeSettingsSample/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeSettingsSample/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeSettingsSample/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeSettingsSample/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeSettingsSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeSettingsSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /ComposeSettingsSample/app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /ComposeSettingsSample/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | compose_version = '1.1.0' 4 | } 5 | }// Top-level build file where you can add configuration options common to all sub-projects/modules. 6 | plugins { 7 | id 'com.android.application' version '7.2.0-beta04' apply false 8 | id 'com.android.library' version '7.2.0-beta04' apply false 9 | id 'org.jetbrains.kotlin.android' version '1.6.10' apply false 10 | } 11 | 12 | task clean(type: Delete) { 13 | delete rootProject.buildDir 14 | } -------------------------------------------------------------------------------- /ComposeSettingsSample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeSettingsSample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /ComposeSettingsSample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Aug 06 21:36:39 PDT 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /ComposeSettingsSample/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | rootProject.name = "ComposeSettingsSample" 16 | include ':app' 17 | -------------------------------------------------------------------------------- /ComposeStateSample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | local.properties 11 | -------------------------------------------------------------------------------- /ComposeStateSample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /ComposeStateSample/app/src/main/java/com/husaynhakeem/composestatesample/data/Models.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composestatesample.data 2 | 3 | data class PokemonResult( 4 | val currentPage: Int, 5 | val totalPages: Int, 6 | val items: List 7 | ) 8 | 9 | data class Pokemon( 10 | val id: Int, 11 | val name: String, 12 | val spriteUrl: String 13 | ) -------------------------------------------------------------------------------- /ComposeStateSample/app/src/main/java/com/husaynhakeem/composestatesample/data/PokemonContainer.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composestatesample.data 2 | 3 | interface PokemonContainer { 4 | 5 | fun get(): List 6 | } -------------------------------------------------------------------------------- /ComposeStateSample/app/src/main/java/com/husaynhakeem/composestatesample/data/PokemonRepository.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composestatesample.data 2 | 3 | interface PokemonRepository { 4 | 5 | suspend fun getPokemonResultFor(page: Int, pageSize: Int): PokemonResult 6 | } -------------------------------------------------------------------------------- /ComposeStateSample/app/src/main/java/com/husaynhakeem/composestatesample/data/fake/FakePokemonContainer.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composestatesample.data.fake 2 | 3 | import com.husaynhakeem.composestatesample.data.Pokemon 4 | import com.husaynhakeem.composestatesample.data.PokemonContainer 5 | 6 | class FakePokemonContainer : PokemonContainer { 7 | 8 | private val allPokemon: MutableList = mutableListOf() 9 | 10 | override fun get(): List { 11 | return allPokemon.toList() 12 | } 13 | 14 | fun setAllPokemon(allPokemon: List) { 15 | this.allPokemon.clear() 16 | this.allPokemon.addAll(allPokemon) 17 | } 18 | } -------------------------------------------------------------------------------- /ComposeStateSample/app/src/main/java/com/husaynhakeem/composestatesample/ui/Color.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composestatesample.ui 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val purple200 = Color(0xFFBB86FC) 6 | val purple500 = Color(0xFF6200EE) 7 | val purple700 = Color(0xFF3700B3) 8 | val teal200 = Color(0xFF03DAC5) -------------------------------------------------------------------------------- /ComposeStateSample/app/src/main/java/com/husaynhakeem/composestatesample/ui/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.composestatesample.ui 2 | 3 | import androidx.compose.foundation.shape.RoundedCornerShape 4 | import androidx.compose.material.Shapes 5 | import androidx.compose.ui.unit.dp 6 | 7 | val shapes = Shapes( 8 | small = RoundedCornerShape(4.dp), 9 | medium = RoundedCornerShape(4.dp), 10 | large = RoundedCornerShape(0.dp) 11 | ) -------------------------------------------------------------------------------- /ComposeStateSample/app/src/main/res/drawable/ic_error.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /ComposeStateSample/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /ComposeStateSample/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ComposeStateSample 3 | -------------------------------------------------------------------------------- /ComposeStateSample/art/android-jetpack-compose-state-sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeStateSample/art/android-jetpack-compose-state-sample.png -------------------------------------------------------------------------------- /ComposeStateSample/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | ext { 4 | compose_version = '1.0.0-alpha06' 5 | } 6 | ext.kotlin_version = "1.4.10" 7 | repositories { 8 | google() 9 | jcenter() 10 | } 11 | dependencies { 12 | classpath "com.android.tools.build:gradle:4.2.0-alpha15" 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | jcenter() 21 | mavenCentral() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } -------------------------------------------------------------------------------- /ComposeStateSample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/ComposeStateSample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /ComposeStateSample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Nov 03 21:52:36 PST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /ComposeStateSample/local.properties: -------------------------------------------------------------------------------- 1 | ## This file is automatically generated by Android Studio. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file should *NOT* be checked into Version Control Systems, 5 | # as it contains information specific to your local configuration. 6 | # 7 | # Location of the SDK. This is only used by Gradle. 8 | # For customization when using a Version Control System, please read the 9 | # header note. 10 | sdk.dir=/Users/husaynhakeem/Library/Android/sdk -------------------------------------------------------------------------------- /ComposeStateSample/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = "ComposeStateSample" 2 | include ':app' 3 | -------------------------------------------------------------------------------- /DaggerSample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/* 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | local.properties 11 | -------------------------------------------------------------------------------- /DaggerSample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /DaggerSample/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/DaggerApp.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample 2 | 3 | import android.app.Application 4 | import com.husaynhakeem.daggersample.di.AppComponent 5 | import com.husaynhakeem.daggersample.di.DaggerAppComponent 6 | 7 | class DaggerApp : Application() { 8 | 9 | private lateinit var appComponent: AppComponent 10 | 11 | override fun onCreate() { 12 | super.onCreate() 13 | appComponent = DaggerAppComponent.builder().build() 14 | } 15 | 16 | fun appComponent() = appComponent 17 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/base/Presenter.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.base 2 | 3 | abstract class Presenter { 4 | 5 | protected var view: V? = null 6 | 7 | fun bind(view: V) { 8 | this.view = view 9 | } 10 | 11 | fun unbind() { 12 | this.view = null 13 | } 14 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/base/View.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.base 2 | 3 | interface View -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/di/AppComponent.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.di 2 | 3 | import dagger.Component 4 | import javax.inject.Singleton 5 | 6 | @Component(modules = [AppModule::class, FeatureModule::class]) 7 | @Singleton 8 | interface AppComponent { 9 | 10 | fun featureComponent(): FeatureComponent 11 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/di/AppModule.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.di 2 | 3 | import com.husaynhakeem.daggersample.repository.NewsRepository 4 | import com.husaynhakeem.daggersample.repository.impl.InMemoryNewsRepository 5 | import dagger.Binds 6 | import dagger.Module 7 | import javax.inject.Singleton 8 | 9 | @Module 10 | interface AppModule { 11 | 12 | @Binds 13 | @Singleton 14 | fun provideNewsRepository(inMemoryRepository: InMemoryNewsRepository): NewsRepository 15 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/di/FeatureComponent.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.di 2 | 3 | import com.husaynhakeem.daggersample.view.impl.AllNewsFragment 4 | import com.husaynhakeem.daggersample.view.impl.NewsItemFragment 5 | import dagger.Subcomponent 6 | 7 | @FeatureScope 8 | @Subcomponent(modules = [FeatureModule::class, StatsModule::class, ThirdPartyStatsModule::class]) 9 | interface FeatureComponent { 10 | 11 | fun inject(allNewsFragment: AllNewsFragment) 12 | fun inject(newsItemFragment: NewsItemFragment) 13 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/di/FeatureModule.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.di 2 | 3 | import com.husaynhakeem.daggersample.presenter.AllNewsPresenter 4 | import com.husaynhakeem.daggersample.presenter.NewsItemPresenter 5 | import com.husaynhakeem.daggersample.presenter.impl.AllNewsPresenterImpl 6 | import com.husaynhakeem.daggersample.presenter.impl.NewsItemPresenterImpl 7 | import dagger.Binds 8 | import dagger.Module 9 | 10 | @Module 11 | interface FeatureModule { 12 | 13 | @Binds 14 | fun provideAllNewsPresenter(allNewsPresenterImpl: AllNewsPresenterImpl): AllNewsPresenter 15 | 16 | @Binds 17 | fun provideNewsItemPresenter(newsItemPresenterImpl: NewsItemPresenterImpl): NewsItemPresenter 18 | } 19 | -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/di/FeatureScope.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.di 2 | 3 | import javax.inject.Scope 4 | 5 | @Scope 6 | @MustBeDocumented 7 | @Retention(AnnotationRetention.RUNTIME) 8 | annotation class FeatureScope -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/di/StatsModule.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.di 2 | 3 | import com.husaynhakeem.daggersample.stats.NewsStats 4 | import com.husaynhakeem.daggersample.stats.impl.LengthNewsStats 5 | import dagger.Module 6 | import dagger.Provides 7 | import dagger.multibindings.IntoSet 8 | 9 | @Module 10 | class StatsModule { 11 | 12 | @Provides 13 | @IntoSet 14 | fun provideNewsStats(): NewsStats { 15 | return LengthNewsStats() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/di/ThirdPartyStatsModule.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.di 2 | 3 | import com.husaynhakeem.daggersample.stats.NewsStats 4 | import com.husaynhakeem.daggersample.stats.impl.WordCountNewsStats 5 | import dagger.Module 6 | import dagger.Provides 7 | import dagger.multibindings.IntoSet 8 | 9 | @Module 10 | class ThirdPartyStatsModule { 11 | 12 | @Provides 13 | @IntoSet 14 | fun providesWordsLengthNewsStats(): NewsStats { 15 | return WordCountNewsStats() 16 | } 17 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/model/News.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.model 2 | 3 | data class News(val id: Long, val title: String, val text: String) -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/presenter/AllNewsPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.presenter 2 | 3 | import com.husaynhakeem.daggersample.base.Presenter 4 | import com.husaynhakeem.daggersample.view.AllNewsView 5 | 6 | abstract class AllNewsPresenter : Presenter() { 7 | 8 | abstract fun getAllNews() 9 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/presenter/NewsItemPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.presenter 2 | 3 | import com.husaynhakeem.daggersample.base.Presenter 4 | import com.husaynhakeem.daggersample.view.NewsItemView 5 | 6 | abstract class NewsItemPresenter : Presenter() { 7 | 8 | abstract fun getNewsItem(id: Long) 9 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/presenter/impl/AllNewsPresenterImpl.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.presenter.impl 2 | 3 | import com.husaynhakeem.daggersample.di.FeatureScope 4 | import com.husaynhakeem.daggersample.presenter.AllNewsPresenter 5 | import com.husaynhakeem.daggersample.repository.NewsRepository 6 | import javax.inject.Inject 7 | 8 | @FeatureScope 9 | class AllNewsPresenterImpl @Inject constructor(private val repository: NewsRepository) : 10 | AllNewsPresenter() { 11 | 12 | override fun getAllNews() { 13 | val allNews = repository.all() 14 | view?.displayAllNews(allNews) 15 | } 16 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/repository/NewsRepository.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.repository 2 | 3 | import com.husaynhakeem.daggersample.model.News 4 | 5 | interface NewsRepository { 6 | 7 | fun all(): List 8 | 9 | fun findBy(id: Long): News? 10 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/stats/NewsStats.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.stats 2 | 3 | import com.husaynhakeem.daggersample.model.News 4 | 5 | const val STATS_LOG = "news-stats" 6 | 7 | interface NewsStats { 8 | 9 | fun printStats(news: News) 10 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/stats/impl/LengthNewsStats.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.stats.impl 2 | 3 | import android.util.Log 4 | import com.husaynhakeem.daggersample.model.News 5 | import com.husaynhakeem.daggersample.stats.NewsStats 6 | import com.husaynhakeem.daggersample.stats.STATS_LOG 7 | 8 | class LengthNewsStats : NewsStats { 9 | 10 | override fun printStats(news: News) { 11 | val length = news.text.length 12 | Log.i(STATS_LOG, "News Length: $length") 13 | } 14 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/stats/impl/WordCountNewsStats.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.stats.impl 2 | 3 | import android.util.Log 4 | import com.husaynhakeem.daggersample.model.News 5 | import com.husaynhakeem.daggersample.stats.NewsStats 6 | import com.husaynhakeem.daggersample.stats.STATS_LOG 7 | 8 | class WordCountNewsStats : NewsStats { 9 | 10 | override fun printStats(news: News) { 11 | val wordsCount = news.text.splitToSequence(" ").count() 12 | Log.i(STATS_LOG, "News Word count: $wordsCount") 13 | } 14 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/view/AllNewsView.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.view 2 | 3 | import com.husaynhakeem.daggersample.base.View 4 | import com.husaynhakeem.daggersample.model.News 5 | 6 | interface AllNewsView : View { 7 | 8 | fun displayAllNews(news: List) 9 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/java/com/husaynhakeem/daggersample/view/NewsItemView.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.daggersample.view 2 | 3 | import com.husaynhakeem.daggersample.base.View 4 | import com.husaynhakeem.daggersample.model.News 5 | 6 | interface NewsItemView : View { 7 | 8 | fun displayNewsItem(news: News) 9 | 10 | fun onNewsItemNotFound(id: Long) 11 | } -------------------------------------------------------------------------------- /DaggerSample/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DaggerSample/app/src/main/res/layout/fragment_all_news.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DaggerSample/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /DaggerSample/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #BB86FC 4 | #6200EE 5 | #3700B3 6 | #03DAC5 7 | -------------------------------------------------------------------------------- /DaggerSample/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Dagger Sample 3 | -------------------------------------------------------------------------------- /DaggerSample/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /DaggerSample/art/all_news_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/DaggerSample/art/all_news_screen.png -------------------------------------------------------------------------------- /DaggerSample/art/news_item_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/DaggerSample/art/news_item_screen.png -------------------------------------------------------------------------------- /DaggerSample/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | ext.kotlin_version = "1.3.70" 4 | repositories { 5 | google() 6 | jcenter() 7 | } 8 | dependencies { 9 | classpath "com.android.tools.build:gradle:4.1.0-alpha07" 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } -------------------------------------------------------------------------------- /DaggerSample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/DaggerSample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /DaggerSample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Aug 04 20:45:50 PDT 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-6.3-bin.zip 7 | -------------------------------------------------------------------------------- /DaggerSample/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name = "DaggerSample" -------------------------------------------------------------------------------- /DataStoreSample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | local.properties 11 | -------------------------------------------------------------------------------- /DataStoreSample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /DataStoreSample/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /DataStoreSample/app/src/main/proto/person_proto.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "com.husaynhakeem.datastoresample"; 4 | option java_multiple_files = true; 5 | 6 | message User { 7 | uint64 id = 1; 8 | string token = 2; 9 | } 10 | -------------------------------------------------------------------------------- /DataStoreSample/app/src/main/res/drawable/ic_dark_mode.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /DataStoreSample/app/src/main/res/drawable/ic_light_mode.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /DataStoreSample/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DataStoreSample/app/src/main/res/menu/main_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /DataStoreSample/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /DataStoreSample/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | DataStore Sample 3 | Day/Night mode 4 | 5 | 6 | Username 7 | Password 8 | Login 9 | 10 | 11 | Logout 12 | Hello user#%d!\nYour secret token is %s 13 | -------------------------------------------------------------------------------- /DataStoreSample/art/data-store-sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/DataStoreSample/art/data-store-sample.png -------------------------------------------------------------------------------- /DataStoreSample/art/log-in-day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/DataStoreSample/art/log-in-day.png -------------------------------------------------------------------------------- /DataStoreSample/art/log-in-night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/DataStoreSample/art/log-in-night.png -------------------------------------------------------------------------------- /DataStoreSample/art/logged-in-day.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/DataStoreSample/art/logged-in-day.png -------------------------------------------------------------------------------- /DataStoreSample/art/logged-in-night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/DataStoreSample/art/logged-in-night.png -------------------------------------------------------------------------------- /DataStoreSample/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | ext.kotlin_version = "1.4.20" 4 | repositories { 5 | google() 6 | jcenter() 7 | } 8 | dependencies { 9 | classpath "com.android.tools.build:gradle:4.2.0-alpha15" 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.12' 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | task clean(type: Delete) { 23 | delete rootProject.buildDir 24 | } -------------------------------------------------------------------------------- /DataStoreSample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/DataStoreSample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /DataStoreSample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Feb 16 19:54:18 PST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /DataStoreSample/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = "DataStoreSample" 2 | include ':app' 3 | -------------------------------------------------------------------------------- /FaceDetectorSample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/* 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | -------------------------------------------------------------------------------- /FaceDetectorSample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /FaceDetectorSample/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #03DAC5 6 | -------------------------------------------------------------------------------- /FaceDetectorSample/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | FaceDetector Sample 3 | Required permissions not granted by user. 4 | No available cameras for usage. 5 | An error occurred while choosing a camera lens facing. 6 | -------------------------------------------------------------------------------- /FaceDetectorSample/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | -------------------------------------------------------------------------------- /FaceDetectorSample/art/art_landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/FaceDetectorSample/art/art_landscape.png -------------------------------------------------------------------------------- /FaceDetectorSample/art/art_portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/FaceDetectorSample/art/art_portrait.png -------------------------------------------------------------------------------- /FaceDetectorSample/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | ext.kotlin_version = "1.3.70" 4 | repositories { 5 | google() 6 | jcenter() 7 | } 8 | dependencies { 9 | classpath "com.android.tools.build:gradle:4.0.0-beta02" 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } -------------------------------------------------------------------------------- /FaceDetectorSample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/FaceDetectorSample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /FaceDetectorSample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jun 29 19:46:06 PDT 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-6.1.1-all.zip 7 | -------------------------------------------------------------------------------- /FaceDetectorSample/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name = "FaceDetectorSample" -------------------------------------------------------------------------------- /FragmentResultSample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | -------------------------------------------------------------------------------- /FragmentResultSample/README.md: -------------------------------------------------------------------------------- 1 | # Passing data between Fragments 2 | 3 | Android sample app to learn about passing data between fragments using the new [FragmentResultOwner](https://developer.android.com/reference/androidx/fragment/app/FragmentResultOwner) APIs. It mainly showcases: 4 | - Passing data between 2 distinct Fragments. 5 | - Passing data between a child fragment and its parent. 6 | - Testing that data is correctly passed between fragments using [FragmentScenario](https://developer.android.com/reference/androidx/fragment/app/testing/FragmentScenario). 7 | 8 | This sample was used in this [article](https://proandroiddev.com/android-fragments-fragment-result-805a6b2522ea). 9 | -------------------------------------------------------------------------------- /FragmentResultSample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /FragmentResultSample/app/src/androidTest/java/com/husaynhakeem/fragmentresultsample/FragmentScenarioExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.fragmentresultsample 2 | 3 | import android.content.Context 4 | import androidx.fragment.app.Fragment 5 | import androidx.fragment.app.testing.FragmentScenario 6 | 7 | 8 | fun FragmentScenario.context(): Context { 9 | var context: Context? = null 10 | onFragment { fragment -> 11 | context = fragment.requireContext() 12 | } 13 | if (context == null) { 14 | throw IllegalStateException("Cannot get context from FragmentScenario") 15 | } 16 | return context!! 17 | } -------------------------------------------------------------------------------- /FragmentResultSample/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /FragmentResultSample/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /FragmentResultSample/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #03DAC5 6 | -------------------------------------------------------------------------------- /FragmentResultSample/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | FragmentResult Sample 3 | Enter a number 4 | You entered the number %d 5 | Done 6 | Enter a number 7 | Enter a valid number 8 | -------------------------------------------------------------------------------- /FragmentResultSample/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /FragmentResultSample/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | ext.kotlin_version = "1.3.70" 4 | repositories { 5 | google() 6 | jcenter() 7 | } 8 | dependencies { 9 | classpath "com.android.tools.build:gradle:4.0.0-beta02" 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | jcenter() 21 | } 22 | } 23 | 24 | task clean(type: Delete) { 25 | delete rootProject.buildDir 26 | } -------------------------------------------------------------------------------- /FragmentResultSample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/FragmentResultSample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /FragmentResultSample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Apr 30 22:21:51 PDT 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-6.1.1-all.zip 7 | -------------------------------------------------------------------------------- /FragmentResultSample/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name = "FragmentResultSample" -------------------------------------------------------------------------------- /GesturesSample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | -------------------------------------------------------------------------------- /GesturesSample/README.md: -------------------------------------------------------------------------------- 1 | # Android touch gestures 2 | 3 | Android sample app to learn about touch gestures APIs in Android. It mainly showcases: 4 | - Handling single touch gestures. 5 | - Handling multi-touch gestures. 6 | - Detecting common gestures (e.g. Single and double tap, scroll, fling) 7 | - Detecting scaling gestures. 8 | 9 | This sample was used in this [article](https://proandroiddev.com/detecting-touch-gestures-in-android-f8eb4a4faf98). 10 | -------------------------------------------------------------------------------- /GesturesSample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /GesturesSample/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 29 7 | buildToolsVersion "29.0.3" 8 | defaultConfig { 9 | applicationId "com.husaynhakeem.gesturessample" 10 | minSdkVersion 21 11 | targetSdkVersion 29 12 | } 13 | } 14 | 15 | dependencies { 16 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 17 | implementation 'androidx.core:core-ktx:1.2.0' 18 | implementation 'androidx.appcompat:appcompat:1.1.0' 19 | implementation "androidx.cardview:cardview:1.0.0" 20 | implementation "com.google.android.material:material:1.1.0" 21 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 22 | } -------------------------------------------------------------------------------- /GesturesSample/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /GesturesSample/app/src/main/java/com/husaynhakeem/gesturessample/extension/ScaleGestureExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.gesturessample.extension 2 | 3 | import android.view.ScaleGestureDetector 4 | 5 | 6 | fun ScaleGestureDetector?.description(type: String): String { 7 | return when { 8 | this == null -> "Null scale gesture detector" 9 | type.isEmpty() -> "Scale event with factor ${this.scaleFactor}" 10 | else -> "$type Scale event with factor ${this.scaleFactor}" 11 | } 12 | } -------------------------------------------------------------------------------- /GesturesSample/app/src/main/java/com/husaynhakeem/gesturessample/extension/TextViewExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.gesturessample.extension 2 | 3 | import android.annotation.SuppressLint 4 | import android.widget.TextView 5 | 6 | 7 | @SuppressLint("SetTextI18n") 8 | fun TextView.addText(text: String) { 9 | setText("$text\n${this.text}") 10 | } 11 | 12 | fun TextView.overrideWithText(text: String) { 13 | setText(text) 14 | } 15 | 16 | fun TextView.clear() { 17 | text = "" 18 | } -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/GesturesSample/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/GesturesSample/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/GesturesSample/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/GesturesSample/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/GesturesSample/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/GesturesSample/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/GesturesSample/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/GesturesSample/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/GesturesSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/GesturesSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #03DAC5 6 | -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Touch Gestures Sample 3 | Single Touch 4 | Multi Touch 5 | Gesture Detector 6 | Scale Gesture Detector 7 | Default 8 | -------------------------------------------------------------------------------- /GesturesSample/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /GesturesSample/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | ext.kotlin_version = "1.3.70" 4 | repositories { 5 | google() 6 | jcenter() 7 | } 8 | dependencies { 9 | classpath "com.android.tools.build:gradle:4.0.0-beta02" 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } -------------------------------------------------------------------------------- /GesturesSample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husaynhakeem/android-playground/30967fe49a3970734b5eba0fc9a7897cecc61cc7/GesturesSample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /GesturesSample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Apr 12 15:07:35 PDT 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-6.1.1-all.zip 7 | -------------------------------------------------------------------------------- /GesturesSample/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name = "GesturesSample" -------------------------------------------------------------------------------- /GlanceSample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | local.properties 11 | -------------------------------------------------------------------------------- /GlanceSample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /GlanceSample/app/src/main/java/com/husaynhakeem/glancesample/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.glancesample.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple200 = Color(0xFFBB86FC) 6 | val Purple500 = Color(0xFF6200EE) 7 | val Purple700 = Color(0xFF3700B3) 8 | val Teal200 = Color(0xFF03DAC5) -------------------------------------------------------------------------------- /GlanceSample/app/src/main/java/com/husaynhakeem/glancesample/ui/theme/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.glancesample.ui.theme 2 | 3 | import androidx.compose.foundation.shape.RoundedCornerShape 4 | import androidx.compose.material.Shapes 5 | import androidx.compose.ui.unit.dp 6 | 7 | val Shapes = Shapes( 8 | small = RoundedCornerShape(4.dp), 9 | medium = RoundedCornerShape(4.dp), 10 | large = RoundedCornerShape(0.dp) 11 | ) -------------------------------------------------------------------------------- /GlanceSample/app/src/main/java/com/husaynhakeem/glancesample/util/LoggingUtils.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.glancesample.util 2 | 3 | import android.util.Log 4 | 5 | const val TAG_PREFIX = "GLANCE-" 6 | 7 | inline fun T.log(message: String) { 8 | Log.d("${TAG_PREFIX}${T::class.java.simpleName}", message) 9 | } -------------------------------------------------------------------------------- /GlanceSample/app/src/main/java/com/husaynhakeem/glancesample/util/SizeUtils.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.glancesample.util 2 | 3 | import androidx.compose.ui.unit.Dp 4 | import androidx.compose.ui.unit.DpSize 5 | import kotlin.math.roundToInt 6 | 7 | fun Dp.readable(): String { 8 | return "${value.roundToInt()}dp" 9 | } 10 | 11 | fun DpSize.isSmallerThan(other: DpSize): Boolean { 12 | return this.width <= other.width && this.height <= other.height 13 | } -------------------------------------------------------------------------------- /GlanceSample/app/src/main/java/com/husaynhakeem/glancesample/util/ToastUtils.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.glancesample.util 2 | 3 | import android.content.Context 4 | import android.widget.Toast 5 | import androidx.annotation.StringRes 6 | 7 | 8 | fun toast(context: Context, message: String) { 9 | Toast.makeText( 10 | context, 11 | message, 12 | Toast.LENGTH_SHORT 13 | ).show() 14 | } 15 | 16 | fun toast(context: Context, @StringRes messageResId: Int) { 17 | toast(context, context.getString(messageResId)) 18 | } -------------------------------------------------------------------------------- /GlanceSample/app/src/main/java/com/husaynhakeem/glancesample/widget/action/DummyBroadcastReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.glancesample.widget.action 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import com.husaynhakeem.glancesample.util.toast 7 | 8 | class DummyBroadcastReceiver : BroadcastReceiver() { 9 | override fun onReceive(context: Context?, intent: Intent?) { 10 | context?.let { 11 | toast(context, "Received broadcast with intent $intent") 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /GlanceSample/app/src/main/java/com/husaynhakeem/glancesample/widget/action/DummyService.kt: -------------------------------------------------------------------------------- 1 | package com.husaynhakeem.glancesample.widget.action 2 | 3 | import android.app.Service 4 | import android.content.Intent 5 | import android.os.IBinder 6 | import com.husaynhakeem.glancesample.util.toast 7 | 8 | class DummyService : Service() { 9 | 10 | override fun onBind(intent: Intent?): IBinder? = null 11 | 12 | override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { 13 | toast( 14 | applicationContext, 15 | "Service called with intent $intent, flags $flags and start id $startId" 16 | ) 17 | return super.onStartCommand(intent, flags, startId) 18 | } 19 | } -------------------------------------------------------------------------------- /GlanceSample/app/src/main/res/drawable/ic_action.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /GlanceSample/app/src/main/res/drawable/ic_error_ui.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /GlanceSample/app/src/main/res/drawable/ic_interop.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /GlanceSample/app/src/main/res/drawable/ic_list.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /GlanceSample/app/src/main/res/drawable/ic_size_mode.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /GlanceSample/app/src/main/res/drawable/ic_stateful.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /GlanceSample/app/src/main/res/layout/layout_widget_custom_error.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | -------------------------------------------------------------------------------- /GlanceSample/app/src/main/res/layout/layout_widget_initial.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /GlanceSample/app/src/main/res/layout/widget_remote_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 |