Full Code of Appboy/appboy-android-sdk for AI

master 6f35b6a032e6 cached
472 files
1.4 MB
350.3k tokens
301 symbols
1 requests
Download .txt
Showing preview only (1,586K chars total). Download the full file or copy to clipboard to get everything.
Repository: Appboy/appboy-android-sdk
Branch: master
Commit: 6f35b6a032e6
Files: 472
Total size: 1.4 MB

Directory structure:
gitextract_xod5pvye/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug.yml
│   │   ├── config.yml
│   │   └── feature.yml
│   └── ISSUE_TEMPLATE.md
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── android-sdk-location/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── braze/
│                       └── location/
│                           ├── BrazeActionReceiver.kt
│                           ├── BrazeInternalGeofenceApi.kt
│                           ├── BrazeInternalLocationApi.kt
│                           └── GooglePlayLocationUtils.kt
├── android-sdk-ui/
│   ├── braze-consumer-proguard-rules.pro
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── assets/
│           │   └── braze-html-in-app-message-bridge.js
│           ├── java/
│           │   └── com/
│           │       └── braze/
│           │           ├── BrazeActivityLifecycleCallbackListener.kt
│           │           ├── IBrazeDeeplinkHandler.kt
│           │           ├── push/
│           │           │   ├── BrazeAmazonDeviceMessagingReceiver.kt
│           │           │   ├── BrazeFirebaseMessagingService.kt
│           │           │   ├── BrazeHuaweiPushHandler.kt
│           │           │   ├── BrazeNotificationActionUtils.kt
│           │           │   ├── BrazeNotificationFactory.kt
│           │           │   ├── BrazeNotificationStyleFactory.kt
│           │           │   ├── BrazeNotificationUtils.kt
│           │           │   ├── BrazePushReceiver.kt
│           │           │   ├── NotificationTrampolineActivity.kt
│           │           │   └── support/
│           │           │       └── HtmlUtils.kt
│           │           └── ui/
│           │               ├── BrazeDeeplinkHandler.kt
│           │               ├── BrazeFeedFragment.java
│           │               ├── BrazeWebViewActivity.kt
│           │               ├── BrazeXamarinFormsFeedFragment.java
│           │               ├── actions/
│           │               │   ├── IAction.kt
│           │               │   ├── NewsfeedAction.kt
│           │               │   ├── UriAction.kt
│           │               │   └── brazeactions/
│           │               │       ├── BrazeActionParser.kt
│           │               │       ├── BrazeActionUtils.kt
│           │               │       └── steps/
│           │               │           ├── AddToCustomAttributeArrayStep.kt
│           │               │           ├── AddToSubscriptionGroupStep.kt
│           │               │           ├── BaseBrazeActionStep.kt
│           │               │           ├── ContainerStep.kt
│           │               │           ├── IBrazeActionStep.kt
│           │               │           ├── LogCustomEventStep.kt
│           │               │           ├── NoOpStep.kt
│           │               │           ├── OpenLinkExternallyStep.kt
│           │               │           ├── OpenLinkInWebViewStep.kt
│           │               │           ├── RemoveFromCustomAttributeArrayStep.kt
│           │               │           ├── RemoveFromSubscriptionGroupStep.kt
│           │               │           ├── RequestPushPermissionStep.kt
│           │               │           ├── SetCustomUserAttributeStep.kt
│           │               │           ├── SetEmailSubscriptionStep.kt
│           │               │           ├── SetPushNotificationSubscriptionStep.kt
│           │               │           └── StepData.kt
│           │               ├── activities/
│           │               │   ├── BrazeBaseFragmentActivity.kt
│           │               │   ├── BrazeFeedActivity.java
│           │               │   └── ContentCardsActivity.kt
│           │               ├── adapters/
│           │               │   └── BrazeListAdapter.java
│           │               ├── contentcards/
│           │               │   ├── ContentCardsFragment.kt
│           │               │   ├── adapters/
│           │               │   │   ├── ContentCardAdapter.kt
│           │               │   │   └── EmptyContentCardsAdapter.kt
│           │               │   ├── handlers/
│           │               │   │   ├── DefaultContentCardsUpdateHandler.kt
│           │               │   │   ├── DefaultContentCardsViewBindingHandler.kt
│           │               │   │   ├── IContentCardsUpdateHandler.kt
│           │               │   │   └── IContentCardsViewBindingHandler.kt
│           │               │   ├── listeners/
│           │               │   │   ├── DefaultContentCardsActionListener.kt
│           │               │   │   └── IContentCardsActionListener.kt
│           │               │   ├── managers/
│           │               │   │   └── BrazeContentCardsManager.kt
│           │               │   ├── recycler/
│           │               │   │   ├── ContentCardsDividerItemDecoration.kt
│           │               │   │   ├── ItemTouchHelperAdapter.kt
│           │               │   │   └── SimpleItemTouchHelperCallback.kt
│           │               │   └── view/
│           │               │       ├── BannerImageContentCardView.kt
│           │               │       ├── BaseContentCardView.kt
│           │               │       ├── CaptionedImageContentCardView.kt
│           │               │       ├── ContentCardViewHolder.kt
│           │               │       ├── DefaultContentCardView.kt
│           │               │       ├── ShortNewsContentCardView.kt
│           │               │       └── TextAnnouncementContentCardView.kt
│           │               ├── feed/
│           │               │   ├── BrazeFeedManager.java
│           │               │   ├── BrazeImageSwitcher.kt
│           │               │   ├── listeners/
│           │               │   │   ├── BrazeDefaultFeedClickActionListener.java
│           │               │   │   └── IFeedClickActionListener.java
│           │               │   └── view/
│           │               │       └── BaseFeedCardView.java
│           │               ├── inappmessage/
│           │               │   ├── BrazeInAppMessageManager.kt
│           │               │   ├── DefaultInAppMessageViewWrapper.kt
│           │               │   ├── IInAppMessageAnimationFactory.kt
│           │               │   ├── IInAppMessageViewFactory.kt
│           │               │   ├── IInAppMessageViewWrapper.kt
│           │               │   ├── IInAppMessageViewWrapperFactory.kt
│           │               │   ├── InAppMessageCloser.java
│           │               │   ├── InAppMessageManagerBase.kt
│           │               │   ├── InAppMessageOperation.kt
│           │               │   ├── config/
│           │               │   │   └── BrazeInAppMessageParams.kt
│           │               │   ├── factories/
│           │               │   │   ├── DefaultInAppMessageAnimationFactory.kt
│           │               │   │   ├── DefaultInAppMessageFullViewFactory.kt
│           │               │   │   ├── DefaultInAppMessageHtmlFullViewFactory.kt
│           │               │   │   ├── DefaultInAppMessageHtmlViewFactory.kt
│           │               │   │   ├── DefaultInAppMessageModalViewFactory.kt
│           │               │   │   ├── DefaultInAppMessageSlideupViewFactory.kt
│           │               │   │   └── DefaultInAppMessageViewWrapperFactory.kt
│           │               │   ├── jsinterface/
│           │               │   │   ├── InAppMessageJavascriptInterface.kt
│           │               │   │   └── InAppMessageUserJavascriptInterface.kt
│           │               │   ├── listeners/
│           │               │   │   ├── DefaultHtmlInAppMessageActionListener.kt
│           │               │   │   ├── DefaultInAppMessageManagerListener.kt
│           │               │   │   ├── DefaultInAppMessageViewLifecycleListener.kt
│           │               │   │   ├── DefaultInAppMessageWebViewClientListener.kt
│           │               │   │   ├── IHtmlInAppMessageActionListener.kt
│           │               │   │   ├── IInAppMessageManagerListener.kt
│           │               │   │   ├── IInAppMessageViewLifecycleListener.kt
│           │               │   │   ├── IInAppMessageWebViewClientListener.kt
│           │               │   │   ├── IWebViewClientStateListener.kt
│           │               │   │   ├── SwipeDismissTouchListener.java
│           │               │   │   └── TouchAwareSwipeDismissTouchListener.kt
│           │               │   ├── utils/
│           │               │   │   ├── BackgroundInAppMessagePreparer.kt
│           │               │   │   ├── InAppMessageButtonViewUtils.kt
│           │               │   │   ├── InAppMessageViewUtils.kt
│           │               │   │   └── InAppMessageWebViewClient.kt
│           │               │   └── views/
│           │               │       ├── IInAppMessageImageView.kt
│           │               │       ├── IInAppMessageImmersiveView.kt
│           │               │       ├── IInAppMessageView.kt
│           │               │       ├── InAppMessageBaseView.kt
│           │               │       ├── InAppMessageBoundedLayout.kt
│           │               │       ├── InAppMessageButton.kt
│           │               │       ├── InAppMessageFullView.kt
│           │               │       ├── InAppMessageHtmlBaseView.kt
│           │               │       ├── InAppMessageHtmlFullView.kt
│           │               │       ├── InAppMessageHtmlView.kt
│           │               │       ├── InAppMessageImageView.kt
│           │               │       ├── InAppMessageImmersiveBaseView.kt
│           │               │       ├── InAppMessageModalView.kt
│           │               │       ├── InAppMessageSlideupView.kt
│           │               │       └── InAppMessageWebView.kt
│           │               ├── support/
│           │               │   ├── AnimationUtils.kt
│           │               │   ├── UriUtils.kt
│           │               │   └── ViewUtils.kt
│           │               └── widget/
│           │                   ├── BannerImageCardView.java
│           │                   ├── BaseCardView.kt
│           │                   ├── CaptionedImageCardView.java
│           │                   ├── DefaultCardView.java
│           │                   ├── ShortNewsCardView.java
│           │                   └── TextAnnouncementCardView.java
│           └── res/
│               ├── drawable/
│               │   └── com_braze_inappmessage_close_button_selector.xml
│               ├── drawable-nodpi/
│               │   ├── com_braze_card_background.xml
│               │   ├── com_braze_content_card_background.xml
│               │   ├── com_braze_content_card_scrim.xml
│               │   ├── com_braze_content_card_scrim_focused.xml
│               │   ├── com_braze_content_cards_rounded_corner_background.xml
│               │   ├── com_braze_content_cards_unread_bar_background.xml
│               │   ├── com_braze_inappmessage_button_background.xml
│               │   ├── com_braze_inappmessage_icon_background.xml
│               │   ├── com_braze_inappmessage_modal_background.xml
│               │   └── com_braze_inappmessage_slideup_background.xml
│               ├── drawable-nodpi-v21/
│               │   └── com_braze_inappmessage_button_background.xml
│               ├── layout/
│               │   ├── com_braze_banner_image_card.xml
│               │   ├── com_braze_banner_image_content_card.xml
│               │   ├── com_braze_captioned_image_card.xml
│               │   ├── com_braze_captioned_image_content_card.xml
│               │   ├── com_braze_content_cards.xml
│               │   ├── com_braze_content_cards_activity.xml
│               │   ├── com_braze_content_cards_empty.xml
│               │   ├── com_braze_default_card.xml
│               │   ├── com_braze_default_content_card.xml
│               │   ├── com_braze_feed.xml
│               │   ├── com_braze_feed_activity.xml
│               │   ├── com_braze_feed_footer.xml
│               │   ├── com_braze_feed_header.xml
│               │   ├── com_braze_feed_read_indicator_holder.xml
│               │   ├── com_braze_inappmessage_full.xml
│               │   ├── com_braze_inappmessage_full_graphic.xml
│               │   ├── com_braze_inappmessage_html.xml
│               │   ├── com_braze_inappmessage_html_full.xml
│               │   ├── com_braze_inappmessage_modal.xml
│               │   ├── com_braze_inappmessage_modal_graphic.xml
│               │   ├── com_braze_inappmessage_slideup.xml
│               │   ├── com_braze_notification_inline_image.xml
│               │   ├── com_braze_push_inline_image_constrained.xml
│               │   ├── com_braze_push_story_one_image.xml
│               │   ├── com_braze_short_news_card.xml
│               │   ├── com_braze_short_news_content_card.xml
│               │   ├── com_braze_stubbed_feed_image_view.xml
│               │   ├── com_braze_text_announcement_card.xml
│               │   ├── com_braze_text_announcement_content_card.xml
│               │   └── com_braze_webview_activity.xml
│               ├── layout-land/
│               │   └── com_braze_inappmessage_html_full.xml
│               ├── values/
│               │   ├── attrs.xml
│               │   ├── colors.xml
│               │   ├── dimens.xml
│               │   ├── ids.xml
│               │   ├── strings.xml
│               │   └── styles.xml
│               ├── values-ar/
│               │   └── strings.xml
│               ├── values-cs/
│               │   └── strings.xml
│               ├── values-da/
│               │   └── strings.xml
│               ├── values-de/
│               │   └── strings.xml
│               ├── values-es/
│               │   └── strings.xml
│               ├── values-es-rES/
│               │   └── strings.xml
│               ├── values-et/
│               │   └── strings.xml
│               ├── values-fi/
│               │   └── strings.xml
│               ├── values-fr/
│               │   └── strings.xml
│               ├── values-hdpi/
│               │   └── dimens.xml
│               ├── values-hi/
│               │   └── strings.xml
│               ├── values-in/
│               │   └── strings.xml
│               ├── values-it/
│               │   └── strings.xml
│               ├── values-iw/
│               │   └── strings.xml
│               ├── values-ja/
│               │   └── strings.xml
│               ├── values-km/
│               │   └── strings.xml
│               ├── values-ko/
│               │   └── strings.xml
│               ├── values-lo/
│               │   └── strings.xml
│               ├── values-mdpi/
│               │   └── dimens.xml
│               ├── values-ms/
│               │   └── strings.xml
│               ├── values-my/
│               │   └── strings.xml
│               ├── values-nb/
│               │   └── strings.xml
│               ├── values-night/
│               │   ├── colors.xml
│               │   ├── dimens.xml
│               │   └── styles.xml
│               ├── values-nl/
│               │   └── strings.xml
│               ├── values-pl/
│               │   └── strings.xml
│               ├── values-pt/
│               │   └── strings.xml
│               ├── values-pt-rPT/
│               │   └── strings.xml
│               ├── values-ru/
│               │   └── strings.xml
│               ├── values-sv/
│               │   └── strings.xml
│               ├── values-sw600dp/
│               │   ├── dimens.xml
│               │   └── styles.xml
│               ├── values-th/
│               │   └── strings.xml
│               ├── values-tl/
│               │   └── strings.xml
│               ├── values-uk/
│               │   └── strings.xml
│               ├── values-v21/
│               │   └── styles.xml
│               ├── values-vi/
│               │   └── strings.xml
│               ├── values-xhdpi/
│               │   └── dimens.xml
│               ├── values-zh-rCN/
│               │   └── strings.xml
│               ├── values-zh-rHK/
│               │   └── strings.xml
│               ├── values-zh-rSG/
│               │   └── strings.xml
│               └── values-zh-rTW/
│                   └── strings.xml
├── android-sdk-unity/
│   ├── build.gradle
│   ├── libs/
│   │   ├── Prime31UnityActivity-1.0.jar
│   │   └── unity-2019.2.12f1.jar
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── braze/
│                       └── unity/
│                           ├── BrazeUnityActivityWrapper.kt
│                           ├── BrazeUnityPlayerActivity.kt
│                           ├── EventSubscriberFactory.kt
│                           ├── configuration/
│                           │   └── UnityConfigurationProvider.kt
│                           ├── enums/
│                           │   ├── UnityInAppMessageManagerAction.kt
│                           │   └── UnityMessageType.kt
│                           ├── prime31compatible/
│                           │   └── BrazeUnityPlayerActivity.kt
│                           └── utils/
│                               ├── InAppMessageUtils.kt
│                               └── MessagingUtils.kt
├── build.gradle
├── config/
│   ├── buildscript/
│   │   └── break-compile-on-deprecations.gradle
│   └── quality/
│       └── break-compile-on-deprecations.gradle
├── droidboy/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── assets/
│           │   ├── braze_actions/
│           │   │   └── show_push_prompt.txt
│           │   ├── html_in_app_message_bridge_tester.html
│           │   ├── html_in_app_message_unified_bootstrap_album.html
│           │   ├── html_inapp_message_body_external_js.html
│           │   ├── html_inapp_message_body_inline_js.html
│           │   ├── html_inapp_message_body_no_js.html
│           │   ├── html_inapp_message_body_star_wars.html
│           │   ├── html_inapp_message_body_youtube_iframe.html
│           │   ├── html_inapp_message_dark_mode.html
│           │   ├── html_inapp_message_delayed_open.html
│           │   ├── html_shark_unified.html
│           │   └── modal_inapp_message_with_dark_theme.json
│           ├── java/
│           │   └── com/
│           │       └── appboy/
│           │           └── sample/
│           │               ├── CustomBrazeDeeplinkHandler.java
│           │               ├── CustomFeedClickActionListener.java
│           │               ├── CustomHtmlInAppMessageActionListener.java
│           │               ├── CustomInAppMessage.java
│           │               ├── CustomInAppMessageAnimationFactory.java
│           │               ├── CustomInAppMessageManagerListener.java
│           │               ├── CustomInAppMessageView.java
│           │               ├── CustomInAppMessageViewFactory.java
│           │               ├── DroidboyApplication.kt
│           │               ├── DroidboyEndpointProvider.java
│           │               ├── DroidboyNotificationFactory.java
│           │               ├── FeedCategoriesFragment.java
│           │               ├── FullyCustomNotificationFactory.kt
│           │               ├── InAppMessageTesterFragment.kt
│           │               ├── MainFragment.kt
│           │               ├── PushTesterFragment.java
│           │               ├── SetEnvironmentPreference.java
│           │               ├── UserProfileDialog.java
│           │               ├── activity/
│           │               │   ├── DroidBoyActivity.kt
│           │               │   ├── FeedFragmentActivity.java
│           │               │   ├── GeofencesMapActivity.java
│           │               │   ├── InAppMessageSandboxActivity.kt
│           │               │   ├── SettingsActivity.kt
│           │               │   └── settings/
│           │               │       └── SettingsFragment.kt
│           │               ├── dialog/
│           │               │   └── CustomDialogBase.kt
│           │               ├── featureflag/
│           │               │   ├── controller/
│           │               │   │   └── FeatureFlagAdapter.kt
│           │               │   └── view/
│           │               │       └── FeatureFlagFragment.kt
│           │               ├── imageloading/
│           │               │   └── GlideImageLoader.kt
│           │               ├── logging/
│           │               │   ├── CustomEventDialog.java
│           │               │   ├── CustomLogger.java
│           │               │   ├── CustomPurchaseDialog.java
│           │               │   ├── CustomUserAttributeDialog.java
│           │               │   └── PropertyManager.java
│           │               ├── subscriptions/
│           │               │   ├── EmailSubscriptionStateDialog.java
│           │               │   ├── PushSubscriptionStateDialog.java
│           │               │   └── SubscriptionStateDialogBase.java
│           │               └── util/
│           │                   ├── BrazeActionTestingUtil.kt
│           │                   ├── ButtonUtils.java
│           │                   ├── ContentCardsTestingUtil.kt
│           │                   ├── EmulatorDetectionUtils.java
│           │                   ├── EnvironmentUtils.kt
│           │                   ├── LifecycleUtils.java
│           │                   ├── LogcatExportUtil.kt
│           │                   ├── RuntimePermissionUtils.kt
│           │                   ├── SpinnerUtils.java
│           │                   └── ViewUtils.java
│           └── res/
│               ├── drawable/
│               │   └── custom_inappmessage_background.xml
│               ├── font/
│               │   ├── bungee_font_family.xml
│               │   ├── sailec_font_family.xml
│               │   └── sailec_regular.otf
│               ├── layout/
│               │   ├── activity_in_app_message_sandbox.xml
│               │   ├── custom_attribute.xml
│               │   ├── custom_event.xml
│               │   ├── custom_inappmessage.xml
│               │   ├── custom_name.xml
│               │   ├── custom_properties.xml
│               │   ├── custom_purchase.xml
│               │   ├── data_dialog.xml
│               │   ├── dialog_footer_navigation.xml
│               │   ├── drawer_header.xml
│               │   ├── feature_flag_fragment.xml
│               │   ├── feature_flag_overview_item.xml
│               │   ├── geofences_map.xml
│               │   ├── inappmessage_tester.xml
│               │   ├── landing_page.xml
│               │   ├── log_level_dialog.xml
│               │   ├── main_fragment.xml
│               │   ├── preference_wrapper_view.xml
│               │   ├── property_list_item.xml
│               │   ├── push_tester.xml
│               │   ├── set_environment_preference.xml
│               │   ├── settings_page.xml
│               │   ├── spinner_dropdown_item.xml
│               │   ├── spinner_item.xml
│               │   ├── subscription_state_preferences.xml
│               │   └── user_preferences.xml
│               ├── menu/
│               │   └── actionbar_options.xml
│               ├── values/
│               │   ├── braze.xml
│               │   ├── colors.xml
│               │   ├── dimens.xml
│               │   ├── inapp_align_options.xml
│               │   ├── inapp_boolean_options.xml
│               │   ├── inapp_button_options.xml
│               │   ├── inapp_click_action_options.xml
│               │   ├── inapp_color_options.xml
│               │   ├── inapp_dismiss_type_options.xml
│               │   ├── inapp_frame_options.xml
│               │   ├── inapp_header_options.xml
│               │   ├── inapp_icon_options.xml
│               │   ├── inapp_image_options.xml
│               │   ├── inapp_message_options.xml
│               │   ├── inapp_message_type_options.xml
│               │   ├── inapp_orientation_options.xml
│               │   ├── inapp_slide_from_options.xml
│               │   ├── inapp_uri_options.xml
│               │   ├── push_accent_color_options.xml
│               │   ├── push_action_options.xml
│               │   ├── push_category_options.xml
│               │   ├── push_channel_options.xml
│               │   ├── push_click_action_options.xml
│               │   ├── push_image_number_spinner.xml
│               │   ├── push_image_options.xml
│               │   ├── push_large_icon_options.xml
│               │   ├── push_notification_factory_options.xml
│               │   ├── push_priority_options.xml
│               │   ├── push_story_subtitle_align_options.xml
│               │   ├── push_story_title_align_options.xml
│               │   ├── push_visibility_options.xml
│               │   ├── strings.xml
│               │   └── styles.xml
│               ├── values-sw600dp/
│               │   └── styles.xml
│               ├── values-v28/
│               │   └── styles.xml
│               ├── values-xlarge/
│               │   └── styles.xml
│               └── xml/
│                   ├── preferences.xml
│                   └── provider_filepaths.xml
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── samples/
│   ├── README.md
│   ├── custom-broadcast/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── custombroadcast/
│   │           │               ├── CustomBroadcastApplication.java
│   │           │               ├── CustomBroadcastReceiver.java
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── activity_main.xml
│   │               ├── values/
│   │               │   ├── braze.xml
│   │               │   ├── colors.xml
│   │               │   ├── dimens.xml
│   │               │   ├── strings.xml
│   │               │   └── styles.xml
│   │               └── values-w820dp/
│   │                   └── dimens.xml
│   ├── firebase-push/
│   │   ├── README.md
│   │   ├── build.gradle
│   │   ├── google-services.json
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── firebasepush/
│   │           │               ├── FirebaseApplication.java
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── activity_main.xml
│   │               └── values/
│   │                   ├── braze.xml
│   │                   ├── colors.xml
│   │                   ├── dimens.xml
│   │                   ├── strings.xml
│   │                   └── styles.xml
│   ├── glide-image-integration/
│   │   ├── README.md
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── glideimageintegration/
│   │           │               ├── GlideBrazeImageLoader.java
│   │           │               ├── GlideIntegrationApplication.java
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── main_activity.xml
│   │               └── values/
│   │                   ├── braze.xml
│   │                   ├── colors.xml
│   │                   ├── dimens.xml
│   │                   ├── strings.xml
│   │                   └── styles.xml
│   ├── google-tag-manager/
│   │   ├── README.md
│   │   ├── build.gradle
│   │   ├── google-services.json
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── assets/
│   │           │   └── containers/
│   │           │       └── GTM-5HM9ZRX.json
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── googletagmanager/
│   │           │               ├── BrazeGtmTagProvider.java
│   │           │               ├── GtmApplication.java
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── activity_main.xml
│   │               └── values/
│   │                   ├── braze.xml
│   │                   ├── colors.xml
│   │                   ├── dimens.xml
│   │                   ├── strings.xml
│   │                   └── styles.xml
│   ├── hello-braze/
│   │   ├── README.md
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── helloworld/
│   │           │               ├── CustomApplication.java
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── main_activity.xml
│   │               └── values/
│   │                   ├── braze.xml
│   │                   └── strings.xml
│   ├── hms-push-sample/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── hms_sample/
│   │           │               ├── CustomPushService.kt
│   │           │               ├── HmsApplication.kt
│   │           │               └── MainActivity.kt
│   │           └── res/
│   │               ├── drawable/
│   │               │   └── ic_launcher_background.xml
│   │               ├── drawable-v24/
│   │               │   └── ic_launcher_foreground.xml
│   │               ├── layout/
│   │               │   ├── activity_main.xml
│   │               │   └── content_main.xml
│   │               ├── mipmap-anydpi-v26/
│   │               │   ├── ic_launcher.xml
│   │               │   └── ic_launcher_round.xml
│   │               └── values/
│   │                   ├── braze.xml
│   │                   ├── colors.xml
│   │                   ├── dimens.xml
│   │                   ├── strings.xml
│   │                   └── styles.xml
│   └── manual-session-integration/
│       ├── README.md
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── java/
│               │   └── com/
│               │       └── braze/
│               │           └── manualsessionintegration/
│               │               └── MainActivity.java
│               └── res/
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── values/
│                   │   ├── braze.xml
│                   │   ├── colors.xml
│                   │   ├── dimens.xml
│                   │   ├── strings.xml
│                   │   └── styles.xml
│                   └── values-w820dp/
│                       └── dimens.xml
└── settings.gradle

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug.yml
================================================
name: 🐞 Bug report
description: File a Bug Report for unexpected or incorrect SDK Behavior
title: '[Bug]: '
labels: ["bug"]
body:
  - type: markdown
    attributes:
      value: |
        Thanks for taking the time to fill out this bug report! 
        
        :warning: Please consider contacting [Braze Support](https://www.braze.com/docs/support_contact) for in-depth troubleshooting and to avoid leaking private information to our public Github issues.
  - type: input
    id: sdk_version
    attributes:
      label: Braze Android SDK Version
      placeholder: ex. 15.0.1
    validations:
      required: true
  - type: textarea
    id: repro_steps
    attributes:
      label: Steps To Reproduce
      description: Please provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example)
      placeholder: |
        Example:
          ```
          
          ```
    validations:
      required: true
  - type: textarea
    id: expected_behavior
    attributes:
      label: Expected Behavior
      description: What did you expect to happen?
    validations:
      required: true
  - type: textarea
    id: actual_behavior
    attributes:
      label: Actual Incorrect Behavior
      description: What incorrect behavior happened instead?
    validations:
      required: true
  - type: textarea
    id: verbose_logs
    attributes:
      label: Verbose Logs
      description: Enable [Verbose Logging](https://www.braze.com/docs/developer_guide/platform_integration_guides/android/initial_sdk_setup/additional_customization_and_configuration/#android-verbose-logging). This will be automatically formatted into code, so no need for backticks.
      render: shell
  - type: textarea
    id: other_info
    attributes:
      label: Additional Information
      description: Anything else you'd like to share?


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Braze Support
    url: https://www.braze.com/docs/support_contact
    about: Contact Braze Support for company or campaign-specific troubleshooting
  - name: Security Issues
    url: https://www.braze.com/docs/developer_guide/disclosures/security_and_vulnerability_disclosure/
    about: Please report security vulnerabilities here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature.yml
================================================
name: ✅ Feature Request
description: Request New SDK Features
title: '[Feature]: '
labels: ["feature-request"]
body:
  - type: markdown
    attributes:
      value: |
        :point_right: You can also submit feature requests in our [Public Roadmap Portal](https://dashboard.braze.com/resources/roadmap)
  - type: textarea
    id: problem
    attributes:
      label: What problem are you facing?
      description: Help us understand what you're unable to accomplish, or what's difficult with your integration
      placeholder: |
        ex: I am unable to accomplish XYZ today, since the SDK does not allow me to...
    validations:
      required: true
  - type: textarea
    id: workarounds
    attributes:
      label: Workarounds
      description: Are there any workarounds you can use? How complicated are they?
    validations:
      required: true
  - type: textarea
    id: ideal_solution
    attributes:
      label: Ideal Solution
      description: What would your ideal solution look like?
    validations:
      required: false
  - type: textarea
    id: other_information
    attributes:
      label: Other Information
      description: Any additional information you'd like to share?
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
<!--
Thank you for opening an issue with Braze!

If you are experiencing issues with our product, please consider directing your issue to support@braze.com, as that is the best channel for solving integration issues. Please see the bottom for more explanation.

For other items, like requests for modifications to our SDK or bug reports, please use the following format:
-->

* [ ] I have checked [Braze's documentation](https://www.braze.com/docs/developer_guide/platform_integration_guides/android/initial_sdk_setup/android_sdk_integration/) and am still experiencing the issue.
* [ ] I have an ANR related issue and have filled out the "ANR Reporting" section below.

# Standard Reporting

## What version of the Braze Android SDK are you using?

<!--
Example: 3.0.1
-->

## What did you do?

<!--
Please replace this with how you've integrated and customized the Braze SDK.
Example: Integrated Braze with the lifecycle listener and used automatic push registration.
-->

## What did you expect to happen?

<!--
Please replace this with the expected behavior.
Example: The Braze SDK is integrated properly and creating sessions.
-->

## What happened instead?

<!--
Please replace this with the actual behavior.  
Example: The Braze SDK doesn't create any sessions for the test user.
-->

## Steps to reproduce

<!--
Please give us detailed steps so we can reproduce the issue on our end. This is very important and will help speed up the investigation.
Example:
- Start the app
- Change to new user
- Set a custom in-app message listener
- Log a custom event
- In-app message doesn't appear
-->

## Are you doing any feature customizations that may relate to the issue? Can you share the code snippet?

<!--
Please provide any information or code snippets that can help us understand or reproduce the issue.
-->

## Project that demonstrates the issue

<!--
Please link to a project we can download that reproduces the issue.
-->

<!--
Note: We recommend e-mailing support@braze.com with any integration issues, as our team actively optimizes this support channel to provide efficient and robust resolutions. Integration issues also often require logs and other information that may contain private data, and our main support channel ensures no risk of leaking sensitive data.
-->

# ANR Reporting
<!--
Please go over https://developer.android.com/topic/performance/vitals/anr for more information on ANR reports.
-->

## Entire ANR Report
<!--
Please provide your entire, unmodified ANR report here
-->

## Braze Related Threads In ANR
<!--
Please list all Thread IDs (or just Thread traces) in the above ANR report that contain Braze SDK code.

Code from the Braze SDK usually is in the `com.appboy` or `bo.app` package, depending on your Proguard configuration.
-->


================================================
FILE: .gitignore
================================================
# Created by http://www.gitignore.io

### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm

## Directory-based project format
.idea/

## File-based project format
*.iml

## Additional for IntelliJ
out/

### Android ###
*.keystore

# Files for the Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/

# built application files
*.apk
*.ap_

# Gradle files
.gradle/
build/

# Local configuration file (sdk path, etc)
local.properties

.DS_Store


================================================
FILE: CHANGELOG.md
================================================
# :warning: This repository has been permanently moved to [https://github.com/braze-inc/braze-android-sdk](https://github.com/braze-inc/braze-android-sdk/blob/master/CHANGELOG.md)

## 24.3.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v24.3.0)

##### Fixed
- Fixed an issue where the SDK would attempt to to access the visual service WindowManager from non-visual contexts, resulting in benign StrictMode errors.
- Added `@JvmStatic` to `com.braze.push.BrazeHuaweiPushHandler.handleHmsRemoteMessageData()`.
- Fixed an issue where notification extra data was not being passed along in Push Story main image clicks.
- Fixed an issue where ContentCardAdapter was not properly handling bad indexes being passed in.
- Fixed an issue where a user's push subscription state would not change to "opted in" upon accepting the Android 13+ push prompt.

##### Added
- Added the ability to configure dismissal of Push Stories on click by adding `BrazeConfig.setDoesPushStoryDismissOnClick()` or `<bool name="com_braze_does_push_story_dismiss_on_click">true</bool>` to your `braze.xml`. Defaults to true.

## 24.2.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v24.2.0)

##### Added
- Added support for the upcoming Braze Feature Flags product.

##### Changed
- Changed the default behavior for images to more aggressively sample large images.
  - Images will be sampled until their effective bitmap size (i.e. W x H x 4 bytes) is below 16 MB.
  - Images will be sampled until both (and not either) the half-width and half-height of the image is less than or equal to the image destination dimensions.
- Changed the behavior of failed Content Card requests to automatically retry on server 500 errors and SDK Authentication errors.

## 24.1.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v24.1.0)

##### Added
- Added `BrazeActivityLifecycleCallbackListener.registerOnApplication()` which allows for registering the lifecycle callback listener from any `Context`.

## 24.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v24.0.0)

#### Breaking
- Location and geofence functionality has moved to a new module called `com.braze:android-sdk-location`. Add this module to your `build.gradle` if you are using Braze location functionality.
- Deprecated classes starting with `Appboy` have now been removed.
- Moved `com.appboy` packages to `com.braze`.
- All xml classes and values in them have been changed from `appboy` to `braze`. All custom code should be updated accordingly.
- `BrazeNotificationUtils.isAppboyPushMessage()` removed. Please use instead:
  - Java: `BrazeNotificationUtils.isBrazePushMessage(Intent)`
  - Kotlin: `Intent.isBrazePushMessage()`
- `APPBOY_NOTIFICATION_OPENED_SUFFIX`, `APPBOY_NOTIFICATION_RECEIVED_SUFFIX`, and `APPBOY_NOTIFICATION_DELETED_SUFFIX` are removed.
  - Instead, please use `Braze.getInstance(context).subscribeToPushNotificationEvents()`
- Updated the minimum version of `com.google.android.gms:play-services-location` required for Braze Geofences to `20.0.0`.

##### Added
- Added the ability to optionally pipe Braze logcat from `BrazeLogger` to a custom callback via `BrazeLogger.onLoggedCallback`.
  ```kotlin
    BrazeLogger.onLoggedCallback = fun(priority: BrazeLogger.Priority, message: String, throwable: Throwable?) {
      // Custom callback logic here
    }
  ```
  ```java
    BrazeLogger.setOnLoggedCallback((priority, s, throwable) -> {
      // Custom logic here
      return null;
    });
  ```

##### Changed
- Removed `BrazeUser.setFacebookData()` and `BrazeUser.setTwitterData()`.
- Changed the default behavior of `DefaultContentCardsUpdateHandler` to use the creation time vs last update time when sorting Content Cards.

## 23.3.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v23.3.0)

##### Fixed
- Fixed the behavior of the Braze HTML In-App Message bridge method `requestPushPermission()` to not cause the in-app message to reload.
- Fixed `com.braze.ui.inappmessage.views.InAppMessageImageView` to guard against null values of `InAppMessageImageView.inAppRadii`.

##### Changed
- Removed `com.appboy.ui.inappmessage.IInAppMessageViewWrapperFactory`. Please use `com.braze.ui.inappmessage.IInAppMessageViewWrapperFactory`.
- Changed `com.braze.ui.inappmessage.views.InAppMessageFullView.getMessageClickableView` to be nullable.

## 23.2.1

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v23.2.1)

##### Fixed
- Fixed the fields of `DefaultInAppMessageViewWrapper` to be `open`, allowing them to be subclassed in Kotlin properly.

## 23.2.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v23.2.0)

##### Fixed
- Fixed the fields of `DefaultInAppMessageViewWrapper` to be `protected`, allowing them to be subclassed.
- Fixed `BrazeNotificationPayload` and `BrazePushReceiver` to not hold onto an Activity context for longer than needed.

##### Added
- Added a config field `BrazeConfig.setIsHtmlInAppMessageApplyWindowInsetsEnabled()` to configure the SDK to automatically apply window insets to HTML In-App messages.
  - By default, this value is false.
- Added [`subscribeToNoMatchingTriggerForEvent`](https://appboy.github.io/appboy-android-sdk/kdoc/braze-android-sdk/com.braze/-braze/subscribe-to-no-matching-trigger-for-event.html) which is called if no Braze in-app message was triggered for a given event.

##### Changed
- Removed `com.appboy.ui.inappmessage.listeners.IInAppMessageWebViewClientListener`. Please use `com.braze.ui.inappmessage.listeners.IInAppMessageWebViewClientListener`.
- Removed `AppboyInAppMessageHtmlBaseView.APPBOY_BRIDGE_PREFIX`. Please use `InAppMessageHtmlBaseView.BRAZE_BRIDGE_PREFIX`.

## 23.1.2

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v23.1.2)

##### Changed
- Removed the use of the Kotlin Coroutines method `limitedParallelism()`.

## 23.1.1

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v23.1.1)

##### Fixed
- Fixed the `DefaultInAppMessageViewWrapper` to be Kotlin open, allowing it to be subclassed.

## 23.1.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v23.1.0)

##### Added
- Added more reliable HTML In-App Message focusing specifically for TV environments. To use this behavior please set `com.braze.configuration.BrazeConfig.Builder.setIsTouchModeRequiredForHtmlInAppMessages` to `false`.
- Added `BrazeNotificationPayload.extras` as a `Map<String, String>` to easily retrieve dashboard provided KVPs for push notification data.
- Added support for Content Cards to evaluate Retry-After headers.

## 23.0.1

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v23.0.1)

##### Fixed
- Fixed an issue where `BaseCardView` would sometimes have the wrong size for a given image.

##### Changed
- Added proguard rules to keep `enum.values()` and `enum.valueOf(String)` for users who don't use the default Android proguard rules.

## 23.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v23.0.0)

#### Breaking
- `BaseContentCardView.bindViewHolder()` now takes `Card` instead of generic type.

##### Fixed
- Fixed an issue where apps with a target of Android 12 running on Android 13 devices would not automatically create a default notification channel upon a push notification being received.

##### Added
- Added ability to retrieve deeplinks from `BrazeNotificationPayload` objects via `BrazeNotificationPayload().deeplink`.

## 22.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v22.0.0)

#### Breaking
- `Appboy.java` is now `Braze.kt`. Kotlin clients will need to update their code to support the use of Kotlin properties on the Braze singleton where needed.
  - `Braze.registerPushToken()`/`Braze.getRegisteredPushToken()` is now `Braze.setRegisteredPushToken()`/`Braze.getRegisteredPushToken()`. If using Kotlin, use the property `Braze.registeredPushToken`.
  - `Braze.getDeviceId` is now just `Braze.deviceId` for Kotlin.
  - `Braze.enableMockNetworkAppboyRequestsAndDropEventsMode` is now `Braze.enableMockNetworkRequestsAndDropEventsMode()`.
  - `Appboy.java` has been removed. For example, calls like `Appboy.getInstance()` will need to be `Braze.getInstance()` moving forward.
  - Replaced `setCustomAppboyNotificationFactory()` with `setCustomBrazeNotificationFactory() / customBrazeNotificationFactory`.
  - Renamed `enableMockAppboyNetworkRequestsAndDropEventsMode` to `enableMockNetworkRequestsAndDropEventsMode`.
- Moved `com.appboy.IBrazeEndpointProvider` to `com.braze.IBrazeEndpointProvider`.
- Renamed `com.appboy.events.IEventSubscriber` to `com.braze.events.IEventSubscriber`.
- Removed `Appboy.registerAppboyPushMessages() / Appboy.getAppboyPushMessageRegistrationId()`. Replaced with `getRegisteredPushToken() / setRegisteredPushToken()`.
- Replaced `IAppboyNotificationFactory` with `IBrazeNotificationFactory`.

##### Fixed
- Fixed an issue in `BrazePushReceiver` where eager In-App Message test displays and Content Card serializations from push notifications wouldn't work unless notifications were enabled on the device.
- Fixed an issue where devices between the API 19 up to API 29 would not perform automatic data syncs in some cases.
- Fixed an issue where carryover in-app messages wouldn't display on subsequent Views on new Activities.
- Fixed an issue where some long running In-App Message HTML WebViews would call View methods on non UI threads.

##### Added
- Added `IBraze.subscribeToPushNotificationEvents()` to allow for subscriptions to push notification events without the use of a `BroadcastReceiver`.
  - Recommended to be placed in your `Application.onCreate()`.

##### Changed
- Changed `com.braze.models.outgoing.BrazeProperties.clone()` to return `BrazeProperties?`.

## 21.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v21.0.0)

##### Important
- This release includes support for Android 13 (Tiramisu / API 33).

#### Breaking
- Removed `IAppboy.logContentCardsDisplayed`. This method was not part of the recommended Content Cards integration and can be safely removed.

##### Changed
- Changed target API for the SDK to 33.

## 20.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v20.0.0)

#### Breaking
- Changed `BrazeNotificationStyleFactory` to remove deprecated functions.
  - Removed `BrazeNotificationStyleFactory.getBigNotificationStyle(Context, Bundle, Bundle, NotificationCompat.Builder)`. Use `BrazeNotificationStyleFactory.getNotificationStyle(NotificationCompat.Builder, BrazeNotificationPayload)` instead.
  - Removed `BrazeNotificationStyleFactory.getBigTextNotificationStyle(BrazeConfigurationProvider, Bundle)`. Use `BrazeNotificationStyleFactory.getBigTextNotificationStyle(BrazeNotificationPayload)` instead.
  - Removed `BrazeNotificationStyleFactory.getStoryStyle(Context, Bundle, Bundle, NotificationCompat.Builder)`. Use `BrazeNotificationStyleFactory.getStoryStyle(NotificationCompat.Builder, BrazeNotificationPayload)` instead.
- Changed `BrazeNotificationActionUtils` to remove deprecated functions.
  - Removed `BrazeNotificationActionUtils.addNotificationActions(Context, NotificationCompat.Builder, Bundle)`. Use `BrazeNotificationActionUtils.addNotificationActions(NotificationCompat.Builder, BrazeNotificationPayload)` instead.
  - Removed `BrazeNotificationActionUtils.addNotificationAction(Context, NotificationCompat.Builder, Bundle, Int)`. Use `BrazeNotificationActionUtils.addNotificationAction(BrazeNotificationPayload.ActionButton)` instead.
  - Removed `AppboyNotificationActionUtils`. Use `BrazeNotificationActionUtils` instead.
- Removed `AppboyHuaweiPushHandler`. Use `BrazeHuaweiPushHandler` instead.
- Removed `AppboyFirebaseMessagingService`. Use `BrazeFirebaseMessagingService` instead.
- Removed `AppboyAdmReceiver`. Use `BrazeAmazonDeviceMessagingReceiver` instead.
- `BrazeFirebaseMessagingService.handleBrazeRemoteMessage()` and `BrazeFirebaseMessagingService.isBrazePushNotification()` now require non-null parameters.
- `UriAction.channel` is now `Channel.CONTENT_CARD` for actions that originate from a Content Card instead of `Channel.NEWS_FEED`.

##### Fixed
-  Fixed an issue that would prevent SDK Authentication errors from being retried.

##### Added
- Modified `BrazeProperties.addProperties()` to allow adding nested properties via `JSONObject` or `Map<String, *>`.
- Added support for Braze Action Deeplink Click Actions.

##### Changed
- Slideup messages now have a maximum width of 450dp. This can be adjusted by modifying `@dimen/com_braze_inappmessage_slideup_max_width`.
- Added `com.braze.Constants` with constants starting with "BRAZE_" that replace the corresponding "APPBOY_" constants in `com.appboy.Constants`. The "APPBOY_" constants are deprecated and will be removed in a future release.

## 19.0.0

##### Important
- It is highly recommended to include the compiler flag `-Xjvm-default=all` in your Gradle build options due to the new use of default arguments in the SDK. Without this flag, you may see a compiler warning about "Inheritance from an interface with '@JvmDefault' members". An example is included below:

```groovy
  android {
    kotlinOptions {
      freeCompilerArgs = ['-Xjvm-default=all']
      jvmTarget = "1.8"
    }
  }
```

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v19.0.0)

##### ⚠ Breaking
- Modified behavior of `BrazeProperties(JSONObject)` when `Date` is part of JSONObject.
  - Previously, Date objects in the JSONObject would be converted with the `Date.toString()` (e.g. "Thu Jan 01 03:15:33 CST 1970").
  - Date objects in the JSONObject are now converted to `BrazeDateFormat.LONG` (e.g. "1970-01-01 09:15:33"). This behavior is consistent with `BrazeProperties.addProperty(Date)`.
- Converted `IInAppMessage` to Kotlin and changed several methods to no longer allow for null inputs or return boolean statuses on field setters.
  - `IInAppMessage.setClickAction()` is renamed to `setClickBehavior()` and now returns void.
  - `MessageButton.setClickAction()` is renamed to `setClickBehavior()` and now returns void.
  - `InAppMessageImmersiveBase.setMessageButtons()` no longer accepts null. Pass in an empty list to clear.
- Converted `Card` to Kotlin, so JVM signatures may have changed.
  - Removed `Card.isEqualToCard()`. Please use `card.equals(otherCard)` instead.
  - Removed `Card.isRead()` and `Card.setIsRead()`. Please use `Card.isIndicatorHighlighted` (Kotlin) or `Card.isIndicatorHighlighted()` and `Card.setIndicatorHighlighted()` (Java).
- Removed `com.appboy.AnimationUtils`, `com.appboy.ViewUtils`, `com.appboy.UriUtils`, `com.appboy.IAction`, `com.appboy.NewsfeedAction` and `com.appboy.UriAction` classes. The Braze namespaced classes remain.
- `BrazeDeeplinkHandler.createUriActionFromUrlString()` and `BrazeDeeplinkHandler.createUriActionFromUri()` now require non-null values for uri/url and channel.
  - `AppboyNavigator` has been removed in favor of `BrazeDeeplinkHandler`.
- Removed `AppboyNotificationUtils` in favor of `BrazeNotificationUtils`.
- Removed `AppboyLifecycleCallbackListener`. Please use `BrazeActivityLifecycleCallbackListener`.
  - Removed `BrazeLifecycleCallbackListener.setInAppMessagingRegistrationBlacklist()` in favor of `BrazeLifecycleCallbackListener.setInAppMessagingRegistrationBlocklist()`. Removed `BrazeLifecycleCallbackListener.setSessionHandlingBlacklist()` in favor of `BrazeLifecycleCallbackListener.setSessionHandlingBlocklist()`.
- Removed `AppboyContentCardsManager`. Please use `BrazeContentCardsManager` instead.
- Removed `AppboyEmptyContentCardsAdapter`. Please use `EmptyContentCardsAdapter` instead.
- Removed `BrazeUser.setAvatarImageUrl(String)`.

##### Fixed
- Fixed the startup behavior of the SDK to not perform caller thread blocking operations when setting up SharedPreferences and other disk reading I/O.
- Fixed a potential issue where the default implementation of `Webview.onRenderProcessGone()` could lead to app crashes. Thanks to @ankitsingh08 for finding the issue.

##### Changed
- Added `BrazeProperties(Map<String, *>)` constructor.
- Changed `Appboy.getConfiguredApiKey()` to accept a `BrazeConfigurationProvider` instead of a `Context` object.
- Deprecated `AppboyBootReceiver`. Please use `BrazeBootReceiver` instead.
- Deprecated `APPBOY_WEBVIEW_URL_EXTRA`. Please use `BRAZE_WEBVIEW_URL_EXTRA` instead.
- Changed the SDK to not wake the screens of `Configuration.UI_MODE_TYPE_TELEVISION` devices when receiving push notifications.
  - These screen types will not be awoken even if `isPushWakeScreenForNotificationEnabled()` is true and the permission `Manifest.permission.WAKE_LOCK` is granted.
  - Special thanks to @IanGClifton for https://github.com/Appboy/appboy-android-sdk/pull/213.

## 18.0.1

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v18.0.1)

##### Fixed
- Fixed an issue introduced in 17.0.0 where some HTML In-App Message zip asset files containing hidden `__MACOSX` folders without a corresponding entry for that folder would cause the in-app message to fail to display.

## 18.0.0

##### Important
- It is highly recommended to include the compiler flag `-Xjvm-default=all` in your Gradle build options due to the new use of default arguments in the SDK. Without this flag, you may see a compiler warning about "Inheritance from an interface with '@JvmDefault' members". An example is included below:

```groovy
  android {
    kotlinOptions {
      freeCompilerArgs = ['-Xjvm-default=all']
      jvmTarget = "1.8"
    }
  }
```

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v18.0.0)

> This version has a known issue with HTML In-App Message which was fixed in v18.0.1
 
##### ⚠ Breaking
- Removed `AppboyLruImageLoader` in favor of `DefaultBrazeImageLoader`.
  - `com.appboy.lrucache.AppboyLruImageLoader` -> `com.braze.images.DefaultBrazeImageLoader`.
  - `com.appboy.Appboy.getAppboyImageLoader` -> `com.appboy.Appboy.getImageLoader`.
  - `com.appboy.Appboy.setAppboyImageLoader` -> `com.appboy.Appboy.setImageLoader`.
- Removed `IAppboyEndpointProvider` in favor of `IBrazeEndpointProvider`.
    - If using `Braze.setAppboyEndpointProvider()` please use `Braze.setEndpointProvider()`.
   
##### Fixed
- Fixed an issue introduced in 15.0.0 where Full in-app messages on tablets may have had an incorrect background color.

##### Added
- Added the ability to change SDK authentication signature with `Braze.changeUser()` when the current user id and a new signature is passed in.
    - Previously, `Braze.changeUser()` would not change the SDK authentication signature if the current user id was used.

##### Changed
- `InAppMessageCloser` is deprecated.
  - Use `BrazeInAppMessageManager.hideCurrentlyDisplayingInAppMessage()` to hide currently displayed in-app messages.
  - Use `IInAppMessage.setAnimateOut()` to set whether your in-app message should animate on close.
  - New version of `IInAppMessageManagerListener.onInAppMessageClicked()` and `IInAppMessageManagerListener.onInAppMessageButtonClicked()` that don't use `InAppMessageCloser` have been added.
    - If you override the deprecated functions that use `InAppMessageCloser`, those will be called.
    - If you override the new functions and don't override the deprecated functions, the new functions will be called.
- Deprecated `ContentCardsUpdatedEvent.getLastUpdatedInSecondsFromEpoch`.
    - Use `getTimestampSeconds()` (Java) or `timestampSeconds` (Kotlin).

## 17.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v17.0.0)

> This version has a known issue with HTML In-App Message which was fixed in v18.0.1

##### ⚠ Breaking
- `BrazeLogger.setLogLevel()` replaced with direct property setter `BrazeLogger.logLevel` for Kotlin.
- Removed `AppboyLogger, com.appboy.IntentUtils, com.appboy.StringUtils` class. The Braze namespaced classes remain.
- Removed `com_braze_locale_api_key_map` as a configuration option and `BrazeConfig.setLocaleToApiMapping()`. If you need to change your API key based on locale, please use `BrazeConfig` at runtime instead.

##### Added
- Added `Braze.isDisabled()` to determine whether the SDK is disabled.
- Added `Braze.addSdkMetadata()` to allow self reporting of SDK Metadata fields via the `BrazeSdkMetadata` enum.
  - Fields may also be added via a `string-array` to your `braze.xml` with the key `com_braze_sdk_metadata`. The allowed items are the same as the keys found in the `BrazeSdkMetadata` enum. For example when using Branch:
  ```xml
    <string-array name="com_braze_sdk_metadata">
     <item>BRANCH</item>
    </string-array>
  ```
  - Fields are additive across all reporting methods.

## 16.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v16.0.0)

##### ⚠ Breaking
- Removed `AppboyConfigurationProvider` in favor of `BrazeConfigurationProvider`.
  - Any deprecated usages, such as in the `IBrazeNotificationFactory` have also been removed.

##### Fixed
- Fixed an issue introduced in 13.1.0 where session start location updates would fail to update on pre API 30 devices.
- Fixed an issue introduced in 13.1.0 where geofence update events would fail to update properly.

##### Added
- Added the ability to namespace all `braze.xml` configurations to be able to use `braze` in place of `appboy`. The Braze namespaced configuration keys will take precedence over the `appboy` keys.
  - For example, `com_appboy_api_key` can be replaced with `com_braze_api_key`.
  - Be sure to look for and update any API keys in your build variants as the `com_braze_api_key` from your default variant might take precedence unexpectedly.
  - All `com_appboy_*` configuration keys in XML will be removed in a future release so it is advised to migrate these configuration keys to their `com_braze_*` counterparts.

##### Changed
- Changed target API for the SDK to 31.

## 15.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v15.0.0)

##### Important
- It is highly recommended to do extensive QA after updating to this release, especially for clients doing any amount of Content Card or In-App Message customizations.

##### ⚠ Breaking
- All Content Cards layout/drawables/colors/dimens identifiers containing `com_appboy_content_cards`/`com_appboy_content_card` were replaced with `com_braze_content_cards`/`com_braze_content_card` respectively.
  - Content Card drawables `icon_pinned, icon_read, icon_unread` are now `com_braze_content_card_icon_pinned, com_braze_content_card_icon_read, com_braze_content_card_icon_unread`.
- All In-App Message layout/drawables/colors/dimens identifiers containing `com_appboy_inappmessage`/`com_appboy_in_app_message` replaced with `com_braze_inappmessage`.
- All styles under namespace `Appboy.*` moved to `Braze.*`.
  - Any `Appboy.*` style overrides must be migrated to `Braze.*` as there is no backwards compatibility.
  - For example, a style override for `Appboy.Cards.ImageSwitcher` must be renamed to `Braze.Cards.ImageSwitcher`.
- Several classes/interfaces have been moved to a Braze namespace/package.
  - In-App Messages
    - In-App Message classes under `com.appboy.models.*` moved to `com.braze.models.inappmessage`
    - Class `com.appboy.ui.inappmessage.InAppMessageCloser` -> `com.braze.ui.inappmessage.InAppMessageCloser`
    - Enum `com.appboy.ui.inappmessage.InAppMessageOperation` -> `com.braze.ui.inappmessage.InAppMessageOperation`
    - Enums in package `com.appboy.enums.inappmessage.*` moved to `com.braze.enums.inappmessage`
  - Content Cards
    - Interface `IContentCardsUpdateHandler` moved to `com.braze.ui.contentcards.handlers.IContentCardsUpdateHandler`
    - Interface `IContentCardsViewBindingHandler` moved to `com.braze.ui.contentcards.handlers.IContentCardsViewBindingHandler`
    - Interface `AppboyContentCardsActionListener` moved to `com.braze.ui.contentcards.listeners.DefaultContentCardsActionListener`
    - Classes in package `com.appboy.ui.contentcards.view.*` moved to `com.braze.ui.contentcards.view.*`
      - This is the package containing all Content Card default views.
    - Class `com.appboy.events.ContentCardsUpdatedEvent` -> `com.braze.events.ContentCardsUpdatedEvent`
  - Miscellaneous
    - Class `AppboyBaseFragmentActivity` moved to `com.braze.ui.activities.BrazeBaseFragmentActivity`
- Removed deprecated `IInAppMessageManagerListener#onInAppMessageReceived` from `IInAppMessageManagerListener`.
- Removed `AppboyUser` in favor of `BrazeUser`.
  - Note that for Kotlin consumers, `Appboy.currentUser?` and `Braze.currentUser?` are valid due to the removal of generics on the `Braze.getCurrentUser()` method.

##### Added
- Added support for Conversational Push.
- Added the ability for custom broadcast receivers to not require the host package name as a prefix when declaring intent filters in your app manifest.
  - `<action android:name="${applicationId}.intent.APPBOY_PUSH_RECEIVED" />` should be replaced with `<action android:name="com.braze.push.intent.NOTIFICATION_RECEIVED" />`
  - `<action android:name="${applicationId}.intent.APPBOY_NOTIFICATION_OPENED" />` should be replaced with `<action android:name="com.braze.push.intent.NOTIFICATION_OPENED" />`
  - `<action android:name="${applicationId}.intent.APPBOY_PUSH_DELETED" />` should be replaced with `<action android:name="com.braze.push.intent.NOTIFICATION_DELETED" />`
  - The `appboy` intents have been deprecated but are still available. They will be removed in a future release so migrating early is highly recommended.
  - Both the `appboy` and `braze` intents are sent for backwards compatibility so only one set should be registered at a time.
- Added `BrazeUser.addToSubscriptionGroup()` and `BrazeUser.removeFromSubscriptionGroup()` to add or remove a user from an email or SMS subscription group.
  - Added `brazeBridge.getUser().addToSubscriptionGroup()` and `brazeBridge.getUser().removeFromSubscriptionGroup()` to the javascript interface for HTML In-App Messages.

##### Changed
- Several classes in the android-sdk-ui artifact have been renamed to the Braze namespace/package. Whenever possible, the original classes are still available. However, they will be removed in a future release so migrating early is highly recommended.
  - Classes in package `com.appboy.push.*` moved to `com.braze.push.*`
  - Classes in package `com.appboy.ui.inappmessage.views` moved to `com.braze.ui.inappmessage.views`
  - Classes in package `com.appboy.ui.inappmessage.listeners` moved to `com.braze.ui.inappmessage.listeners`
  - Interfaces in `com.appboy.ui.inappmessage.*` moved to `com.braze.ui.inappmessage.*`
  - Class `com.appboy.AppboyFirebaseMessagingService` -> `com.braze.push.BrazeFirebaseMessagingService`
  - Class `com.appboy.AppboyAdmReceiver` -> `com.braze.push.BrazeAmazonDeviceMessagingReceiver`
  - Class `com.appboy.ui.AppboyContentCardsFragment` -> `com.braze.ui.contentcards.ContentCardsFragment`
  - Class `com.appboy.ui.activities.AppboyContentCardsActivity` -> `com.braze.ui.activities.ContentCardsActivity`
  - Class `com.appboy.ui.AppboyWebViewActivity` -> `com.braze.ui.BrazeWebViewActivity`
  - Class `com.appboy.ui.inappmessage.AppboyInAppMessageManager` -> `com.braze.ui.inappmessage.BrazeInAppMessageManager`
  - Class `com.appboy.ui.inappmessage.DefaultInAppMessageViewWrapper` -> `com.braze.ui.inappmessage.DefaultInAppMessageViewWrapper`
  - Class `com.appboy.AppboyLifecycleCallbackListener` -> `com.braze.BrazeActivityLifecycleCallbackListener`
- Changed the `ContentCardsFragment` and `BrazeInAppMessageManager` to clear their respective caches of messages after `wipeData()` is called.

## 14.0.1

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v14.0.1)

##### Fixed
- Fixed an issue with `BrazeProperties` not being kept via proguard rules.
- Fixed an issue on TV integrations where in app messages wouldn't properly be given focus when visible.

##### Added
- Added close icon highlighting for TV integrations when selecting the close button in In App Messages.

## 14.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v14.0.0)

##### ⚠ Breaking
- Interface `IInAppMessageViewWrapperFactory` changed to use `BrazeConfigurationProvider`.
- Interface `IAppboyImageLoader/IBrazeImageLoader` changed to use `com.braze.enums.BrazeViewBounds`.
- Class `com.appboy.configuration.AppboyConfig` is now `com.braze.configuration.BrazeConfig`. The original class has been removed and old usages should be updated.
- Class `com.appboy.enums.AppboyViewBounds` is now `com.braze.enums.BrazeViewBounds`. The original class has been removed and old usages should be updated.
- Removed `com.appboy.push.AppboyNotificationUtils#bundleOptString`.
- `Braze.logPurchase()` and `Braze.logEvent()` now impose a 50KB limit on event properties. If the supplied properties are too large, the event is not logged.
  - See `BrazeProperties.isInvalid()`.
- HTML In-App Messages rendered via the default `AppboyHtmlViewFactory` now require the device to be in touch mode to display.
  - See `getIsTouchModeRequiredForHtmlInAppMessages()` in the #added section for configuration on disabling this behavior.
- For Kotlin consumers, `Appboy.currentUser?` calls must be migrated to `Braze.getCurrentUser<BrazeUser>()` due to updated generics resolution.

##### Changed
- Several classes in the base artifact have been renamed to the Braze namespace/packages. Whenever possible, the original classes are still available. However, they will be removed in a future release so migrating early is highly recommended.
  - `com.appboy.Appboy` -> `com.braze.Braze`
  - `com.appboy.configuration.AppboyConfig` -> `com.braze.configuration.BrazeConfig`
  - `com.braze.AppboyUser` -> `com.braze.BrazeUser`
  - `com.appboy.lrucache.AppboyLruImageLoader` -> `com.braze.images.DefaultBrazeImageLoader`
  - `com.appboy.configuration.AppboyConfigurationProvider` -> `com.braze.configuration.BrazeConfigurationProvider`
  - `com.appboy.models.outgoing.AppboyProperties` -> `com.braze.models.outgoing.BrazeProperties`
  - `com.appboy.support.AppboyImageUtils` -> `com.braze.support.BrazeImageUtils`
  - `com.appboy.support.AppboyFileUtils` -> `com.braze.support.BrazeFileUtils`
- Changed the behavior of In-App Message Accessibility Exclusive mode to save and reset the accessibility flags of views after display.
- Changed the `AppboyInAppMessageWebViewClientListener` to use an Activity context when following a deeplink in `IInAppMessageWebViewClientListener.onOtherUrlAction`.
- Deprecated `AppboyInAppMessageHtmlBaseView.APPBOY_BRIDGE_PREFIX`.

##### Added
- Added `Braze.registerPushToken()` and `Braze.getRegisteredPushToken()`.
  - Note that these methods are the functional equivalents of `Appboy.registerAppboyPushMessages()` and `Appboy.getAppboyPushMessageRegistrationId()`.
- Exposed `brazeBridge` which replaces `appboyBridge` to be used as the javascript interface for HTML In-App Messages. `appboyBridge` is deprecated and will be removed in a future version of the SDK.
- Added `AppboyInAppMessageHtmlBaseView.BRAZE_BRIDGE_PREFIX`.
- Added the ability to configure whether `View#isInTouchMode()` is required to show HTML In-App Messages via `BrazeConfig.setIsTouchModeRequiredForHtmlInAppMessages()`.
  - Can also be configured via boolean `com_braze_require_touch_mode_for_html_in_app_messages` in your `braze.xml`.
  - Defaults to true.
- Added support for new SDK Authentication feature.

##### Fixed
- Fixed an issue with `setIsInAppMessageAccessibilityExclusiveModeEnabled()` not being respected if set via runtime configuration. Setting this value via XML was unaffected.
- Fixed an issue with the SDK repeatedly failing to initialize when not properly setting a Braze API key.

## 13.1.2

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v13.1.2)

##### Changed
- Changed the `NotificationTrampolineActivity` to always call `finish()` regardless of any eventual deeplink handling by the host app or SDK.

## 13.1.1

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v13.1.1)

##### Fixed
- Fixed an issue with the `NotificationTrampolineActivity` being opened on notification delete intents.

## 13.1.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v13.1.0)

##### Changed
- All notifications now route through `NotificationTrampolineActivity` to comply with Android 12 notification trampoline restrictions.
- Inline Image push is now compatible with the Android 12 notification area changes.
- Automatic Firebase Messaging registration will now use `FirebaseMessaging.getInstance().getToken()` directly if available.
- Removed usage of `Intent.ACTION_CLOSE_SYSTEM_DIALOGS` with push notifications.

##### Added
- Added `getInAppMessageStack()`, `getCarryoverInAppMessage()`, and `getUnregisteredInAppMessage()` to `AppboyInAppMessageManager`.

## 13.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v13.0.0)

##### ⚠ Breaking
- Moved all In-App Message buttons from `Button` to `com.appboy.ui.inappmessage.views.InAppMessageButton`.
  - This ensures that the `MaterialComponentsViewInflater` does not interfere with standard In-App Message display when using a `MaterialComponents` theme.
  - Apps extending a `Material` theme should test to ensure their In-App Messages appear as expected.
- Moved `com.appboy.ui.inappmessage.AppboyInAppMessageImageView` to `com.appboy.ui.inappmessage.views.InAppMessageImageView`.
- Removed all getter methods from `AppboyConfig`. Access to the underlying data is now directly possible via the variables of the object, e.g. `appboyConfig.getApiKey()` is now `appboyConfig.mApiKey`.

##### Added
- Added `getEmptyCardsAdapter(), getContentCardUpdateRunnable(), getNetworkUnavailableRunnable()` to protected methods in `AppboyContentCardsFragment` for easier customizability.
- Changed the max content line length to 2 lines for Inline Image Push.
  - This style can be found via `"Appboy.Push.InlineImage.TextArea.TitleContent.ContentText"`

##### Fixed
- Changed the `AppboyContentCardsFragment.ContentCardsUpdateRunnable` to determine network unavailability and feed emptiness based on the filtered list of cards and not the original input list of cards.
- Fixed an issue with IAM display where a deleted local image would result in a failed image display.

## 12.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v12.0.0)

##### ⚠ Breaking
- Added `getIntentFlags` to the `IAppboyNavigator` interface to more easily allow for customizing Activity launch behavior.
  - A default implementation is available below:
  ```
    @Override
    public int getIntentFlags(IntentFlagPurpose intentFlagPurpose) {
      return new AppboyNavigator().getIntentFlags(intentFlagPurpose);
    }
  ```
- Renamed `firebase_messaging_service_automatically_register_on_new_token` to `com_appboy_firebase_messaging_service_automatically_register_on_new_token` in `appboy.xml` configuration.

##### Fixed
- Fixed an issue with the default image loader not properly setting image bitmaps on API 23 and below devices.
- Fixed an issue where the `AppboyInAppMessageManager.ensureSubscribedToInAppMessageEvents()` method wouldn't properly resubscribe after disabling and re-enabling the SDK.

##### Changed
- Changed Push Stories in `AppboyNotificationStyleFactory` to use `BrazeNotificationPayload`.

## 11.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v11.0.0)

##### ⚠ Breaking
- Changed the behavior of new beta HTML In-App Messages with dashboard preview support (i.e. those with `MessageType.HTML` and not `MessageType.HTML_FULL`) to not automatically log analytics clicks on url follows in `IInAppMessageWebViewClientListener`.
  - Body click analytics will no longer automatically be collected. To continue to receive body click analytics, you must log body clicks explicitly from your message via Javascript using `appboyBridge.logClick()`.
- `IContentCardsUpdateHandler` and `IContentCardsViewBindingHandler` interfaces now extend `android.os.Parcelable`.
  - This ensures that these handlers properly transition across instance state saves and reads.
  - Examples on how to extend `Parcelable` can be found in `DefaultContentCardsUpdateHandler` and `DefaultContentCardsViewBindingHandler`.
- Renamed `AppboyFcmReceiver` to `BrazePushReceiver`.

##### Added
- Added `AppboyInAppMessageManager.getIsCurrentlyDisplayingInAppMessage()`.
- Added ability to configure whether the `AppboyFirebaseMessagingService` will automatically register tokens in its `onNewToken` method.
  - Defaults to whether FCM automatic registration is enabled. Note that FCM automatic registration is a separate configuration option and is not enabled by default.
  - Configured by changing the boolean value for `firebase_messaging_service_automatically_register_on_new_token` in your `appboy.xml`, or at runtime by setting `AppboyConfig.setIsFirebaseMessagingServiceOnNewTokenRegistrationEnabled()`.
  - Note that the Sender ID used to configure tokens received in `onNewToken()` is based on the app's default Firebase Project rather than the explicitly configured Sender ID on the Braze SDK. These should generally be the same value.

##### Changed
- Deprecated `AppboyLifecycleCallbackListener.setInAppMessagingRegistrationBlacklist()` in favor of `AppboyLifecycleCallbackListener.setInAppMessagingRegistrationBlocklist()`.
- Deprecated `AppboyConfig.Builder.setDeviceObjectWhitelist()` in favor of `AppboyConfig.Builder.setDeviceObjectAllowlist()`.
- Deprecated `AppboyConfig.Builder.setDeviceObjectWhitelistEnabled()` in favor of `AppboyConfig.Builder.setDeviceObjectAllowlistEnabled()`.

##### Fixed
- Fixed an issue where the `AppboyContentCardsFragment` would not transition a custom `IContentCardsUpdateHandler` or `IContentCardsViewBindingHandler` implementation in `onSaveInstanceState()`, which caused the defaults for both to be used instead.
- Fixed an issue with deeplink handling where push action button deeplinks would only work once throughout the lifetime of the application.

## 10.1.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v10.1.0)

##### Changed
- Changed `AppboyWebViewActivity` to extend `FragmentActivity` for better fragment management.
  - Note that `AppboyWebViewActivity` now no longer performs session and in-app message registration on its own.
  - Clients using `AppboyLifecycleCallbackListener` will see no effect.
  - Clients performing manual session integration should override `AppboyWebViewActivity` to add back this registration and set the new Activity via `AppboyConfig.Builder#setCustomWebViewActivityClass()` or `com_appboy_custom_html_webview_activity_class_name` in the `appboy.xml` file.

##### Added
- Added support for receiving messages via the Huawei Messaging Service.

##### Fixed
- Fixed minor display issues with Inline Image Push.

## 10.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v10.0.0)

##### ⚠ Breaking
- The Android SDK has now fully migrated to AndroidX dependencies. No backwards compatibility is possible with the no longer maintained Android Support Library.
  - See https://developer.android.com/jetpack/androidx for more information on AndroidX, including migration steps.
  - Braze Android 9.0.0 is the last SDK version compatible with the Android Support Library.
- Added a new interface method, `IAppboyNotificationFactory.createNotification(BrazeNotificationPayload)`.
  - The `BrazeNotificationPayload` is a data object that performs the task of extracting and surfacing values from the Braze push payload in a far more convenient way.
  - Integrations without a custom `IAppboyNotificationFactory` will have no breaking changes.
  - Integrations with a custom `IAppboyNotificationFactory` are recommended to switchover to their non-deprecated counterparts in `AppboyNotificationUtils.java`.

##### Added
- Added support for `com_appboy_inapp_show_inapp_messages_automatically` boolean configuration for Unity.

##### Fixed
- Fixed support for dark mode in HTML in-app messages and remote urls opened in `AppboyWebViewActivity` for deeplinks via the `prefers-color-scheme: dark` css style.
  - The decision to display content in dark mode will still be determined at display time based on the device's state.
- Fixed an issue where the card parameter in `com.appboy.IAppboyImageLoader.renderUrlIntoCardView()` was null for Content Cards.

##### Removed
- Removed `com.appboy.push.AppboyNotificationUtils.handleContentCardsSerializedCardIfPresent()`.

## 9.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v9.0.0)

##### ⚠ Breaking
- The Android SDK now has a source and target build compatibility set to Java 8.

##### Changed
- Simplified the email regex used in the SDK to centralize most validation on the server.
  - The original email validation used is reproduced below:
  ```
  (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])
  ```

##### Fixed
- Fixed an issue where in-app message icon TextViews could throw a `ClassCastException` on certain devices and prevent display.

##### Removed
- Removed `com.appboy.support.AppboyImageUtils.getBitmap(android.net.Uri)` in favor of `com.appboy.support.AppboyImageUtils.getBitmap(android.content.Context, android.net.Uri, com.appboy.enums.AppboyViewBounds)`.
- Removed `com.appboy.AppboyAdmReceiver.CAMPAIGN_ID_KEY`.
  - Use `Constants.APPBOY_PUSH_CAMPAIGN_ID_KEY` instead.
- Removed `com.appboy.push.AppboyNotificationUtils.isValidNotificationPriority()`.

## 8.1.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v8.1.0)

##### Added support for Android 11 R (API 30).
- Note that apps targeting API 30 should update to this SDK version.

##### Changed
- Changed Content Card subscriptions to automatically re-fire when silent push syncs or test send cards are received via push.
- Improved several accessibility features of In-App Messages and Content Cards as per [Principles for improving app accessibility](https://developer.android.com/guide/topics/ui/accessibility/principles).
  - Changed non-informative accessibility content descriptions for in-app message and Content Card images to `@null`.
  - Content Cards now have content descriptions on their views that incorporate the title and description.
- Changed the `AppboyFirebaseMessagingService` to override the `onNewToken()` method to register a Firebase push token when automatic Firebase registration enabled.

##### Added
- Added `appboyBridge.getUser().addAlias()` to the javascript interface for HTML In-App Messages.
- Added `Appboy.getConfiguredApiKey()` to aid in determining if the SDK has an API key properly configured.
- Added an overload for `IAppboy.getCurrentUser()` that adds an asynchronous callback for when the current user is available instead of blocking on the caller thread.
  - The following is an example of the full interface:
  - ```java
    Appboy.getInstance(mContext).getCurrentUser(new IValueCallback<AppboyUser>() {
      @Override
      public void onSuccess(@NonNull AppboyUser currentUser) {
        currentUser.setFirstName("Jared");
      }

      @Override
      public void onError() {}
    });
  ```
  - A convenience class is also provided with `SimpleValueCallback`:
  - ```java
    Appboy.getInstance(mContext).getCurrentUser(new SimpleValueCallback<AppboyUser>() {
      @Override
      public void onSuccess(@NonNull AppboyUser currentUser) {
        currentUser.setFirstName("Julian");
      }
    });
  ```
- Added `AppboyInAppMessageManager.setClickOutsideModalViewDismissInAppMessageView()` allow for the dismissal of a Modal In-App Message when tapping on the frame behind the message itself.
  - The default (and historical) value is false, meaning that clicks outside the modal do not close the modal.
  - To toggle the feature on, call: `AppboyInAppMessageManager.getInstance().setClickOutsideModalViewDismissInAppMessageView(true)`

##### Fixed
- Fixed behavior of the `com.appboy.ui.AppboyContentCardsFragment` to not assign margin of the first card in the feed from the top of the feed.
- Fixed an issue with Content Card test sends where the test send wouldn't be visible in some conditions.
- Fixed an issue with regex based event property triggers not working as expected. Previously they had to match the entire string, now they will search for matches as expected. The regex is now also case-insensitive.
- Fixed an issue with `resolveActivity()` in the default `UriAction` logic not returning a valid `Activity` to handle external deeplinks on Android 11 devices without the `QUERY_ALL_PACKAGES` permission.
- Fixed an issue introduced in 4.0.1 where upgrading the SDK could result in server configuration values getting removed until the next session start.

##### Removed
- Removed `AppboyConfig.Builder.setNotificationsEnabledTrackingOn()`.
- Removed `AppboyImageUtils.getPixelsFromDp()`.
- Removed `ViewUtils.getDisplayHeight()`.

## 8.0.1

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v8.0.1)

##### Fixed
- Fixed an Activity resolution issue in `com.appboy.ui.AppboyWebViewActivity` by removing a call to `setDownloadListener()`.
- Fixed an implementation issue in 8.0.0 related to setting runtime configuration after stopping the SDK.

## 8.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v8.0.0)

##### ⚠ Breaking
* Integrators note: most of the changes listed below are on lightly used interfaces that do no affect most clients.
- Moved `InAppMessageHtmlBase.getAssetsZipRemoteUrl(), InAppMessageHtmlBase.setAssetsZipRemoteUrl()` to `InAppMessageZippedAssetHtmlBase.java`.
- Moved `AppboyInAppMessageHtmlFullView.APPBOY_BRIDGE_PREFIX` to `AppboyInAppMessageHtmlBaseView.APPBOY_BRIDGE_PREFIX`
- Renamed `IInAppMessage.getRemoteAssetPathForPrefetch` to `IInAppMessage.getRemoteAssetPathsForPrefetch` and changed signature to List<String>.
- Renamed `IInAppMessage.setLocalAssetPathForPrefetch` to `IInAppMessage.setLocalAssetPathsForPrefetch` and changed signature to Map<String, String>.
- Created In-App Message interface `IInAppMessageWithImage` for slideup, modal, and fulls to hold image based methods. These methods have been refactored out of the `IInAppMessage` interface.
  - These methods are `getImageUrl(), getRemoteImageUrl(), getLocalImageUrl(), getBitmap(), getImageDownloadSuccessful(), setImageUrl(), setLocalImageUrl(), setImageDownloadSuccessful(), setRemoteImageUrl()`, and `setBitmap()`.
- Content Card backgrounds (in the default UI), now have their colors set via `/android-sdk-ui/src/main/res/drawable-nodpi/com_appboy_content_card_background.xml`.
- Several Content Cards related style values are now fully decoupled from News Feed values and are enumerated below.
 - The color `@color/com_appboy_card_background_border` is now `@color/com_appboy_content_card_background_border` for Content Cards.
 - The color `@color/com_appboy_card_background_shadow` is now `@color/com_appboy_content_card_background_shadow` for Content Cards.
 - The color `@color/com_appboy_card_background` is now `@color/com_appboy_content_card_background` for Content Cards.
 - The color used for the text in the empty `AppboyContentCardsFragment`, `@color/com_appboy_title` is now `@color/com_appboy_content_card_empty_text_color`.
- Several News Feed dimensions values also used in Content Card styles now have Content Card specific values, enumerated below. Note that if these values were overridden in your styles for use in Content Cards, they will have to be updated to the new keys.
 - The dimension `@dimen/com_appboy_card_background_border_left` is now `@dimen/com_appboy_content_card_background_border_left`.
 - The dimension `@dimen/com_appboy_card_background_border_right` is now `@dimen/com_appboy_content_card_background_border_right`.
 - The dimension `@dimen/com_appboy_card_background_border_top` is now `@dimen/com_appboy_content_card_background_border_top`.
 - The dimension `@dimen/com_appboy_card_background_border_bottom` is now `@dimen/com_appboy_content_card_background_border_bottom`.
 - The dimension `@dimen/com_appboy_card_background_shadow_bottom` is now `@dimen/com_appboy_content_card_background_shadow_bottom`.
 - The dimension `@dimen/com_appboy_card_background_corner_radius` is now `@dimen/com_appboy_content_card_background_corner_radius`.
 - The dimension `@dimen/com_appboy_card_background_shadow_radius` is now `@dimen/com_appboy_content_card_background_shadow_radius`.
- Removed `AppboyInAppMessageHtmlJavascriptInterface(Context)` in favor of `AppboyInAppMessageHtmlJavascriptInterface(Context, IInAppMessageHtml)`.
- Removed `IAppboy.logPushDeliveryEvent()` and `AppboyNotificationUtils.logPushDeliveryEvent()`.

##### Added
- Added support for upcoming HTML In-App Message templates.
- Added `appboyBridge.logClick(String), appboyBridge.logClick()` and `appboyBridge.getUser().setLanguage()` to the javascript interface for HTML In-App Messages.
- Added support for dark mode in HTML in-app messages and remote urls opened in `AppboyWebViewActivity` for deeplinks via the `prefers-color-scheme: dark` css style.
  - The decision to display content in dark mode will be determined at display time based on the device's state.
- Added support for dark mode in the default Content Cards UI.
  - This feature is enabled by default. To disable or change, override the values present in `android-sdk-ui/src/main/res/values-night/colors.xml` and `android-sdk-ui/src/main/res/values-night/dimens.xml`.
- Added `IAppboy.subscribeToSessionUpdates()` which allows for the host app to be notified when a session is started or ended.
- Added the ability to optionally set a custom list of location providers when obtaining a single location, such as on session start. See `AppboyConfig.Builder.setCustomLocationProviderNames()` for more information.
  - The following example showcases instructing the SDK to use `LocationManager.GPS_PROVIDER` and `LocationManager.NETWORK_PROVIDER`.
    ```
      new AppboyConfig.Builder()
          .setCustomLocationProviderNames(EnumSet.of(LocationProviderName.GPS, LocationProviderName.NETWORK));
    ```
  - In xml:
    ```
      <string-array translatable="false" name="com_appboy_custom_location_providers_list">
        <item>GPS</item>
        <item>NETWORK</item>
      </string-array>
    ```
  - By default, only the passive and network providers are used when obtaining a single location from the system.
  - This change does not affect Braze Geofences.

##### Fixed
- Fixed an issue where the pending intent flags on a push story only allowed for the main deeplink to be fired once.
- Fixed behavior of the `com.appboy.ui.AppboyContentCardsFragment` to not double the margin of the first card in the feed from the top of the feed.
- Fixed an issue where calling `wipeData()` or `disableSdk()` could result in not being able to set runtime configuration afterwards.

##### Changed
- Deprecated `com.appboy.models.IInAppMessageWithImage#setImageUrl()` in favor of `com.appboy.models.IInAppMessageWithImage#setRemoteImageUrl(String)`.

## 7.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v7.0.0)

##### ⚠ Breaking
- Made several changes to the default Content Card views to more easily customize and apply ImageView styling.
  - Changed `Appboy.ContentCards.BannerImage.ImageContainer.Image` to `Appboy.ContentCards.BannerImage.Image`.
- Removed `com.appboy.ui.contentcards.view.ContentCardViewHolder.createCardImageWithStyle()`.

##### Added
- Added Czech and Ukrainian language translations for Braze UI elements.
- Added `android-sdk-base-jetified` and `android-sdk-ui-jetified` to reference jetified SDK AAR artifacts from the artifact repository.
  - This is a direct replacement for `android-sdk-ui-x` and is a more complete integration path for using the Braze SDK with AndroidX.
  - Usage as follows:
  ```
  dependencies {
    implementation "com.appboy:android-sdk-ui-jetified:${BRAZE_SDK_VERSION}"
  }
  ```
  - If previously using the `android-sdk-ui-x` module, you must replace any imports under the `com.appboy.uix.push` package to be under `com.appboy.ui.push`.
  - The gradle properties `android.enableJetifier=true` and `android.useAndroidX=true` are no longer required when using androidX libraries with the Braze SDK.
- Added Material Design Button class names to exported consumer proguard rules.
  ```
  -keepnames class android.support.design.button.MaterialButton
  -keepnames class com.google.android.material.button.MaterialButton
  ```

##### Fixed
- Fixed issue in `AppboyCardAdapter` where a card index could be out of bounds when marking a card as seen.

##### Changed
- In-App Message "test sends" from the dashboard now display automatically if your app is in the foreground.
  - Backgrounded apps will continue to receive a push notification to display the message.
  - You can disable this feature by changing the boolean value for `com_appboy_in_app_message_push_test_eager_display_enabled` in your `appboy.xml`, or at runtime by setting `AppboyConfig.setInAppMessageTestPushEagerDisplayEnabled()` to false.
- Changed `UriAction` to be more easily customizable.

##### Removed
- Removed the `android-sdk-ui-x` module. See the `Added` section for more information.
- Removed the China Push Sample app.

## 6.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v6.0.0)

##### ⚠ Breaking
- Slideup and HTML Full In-App Messages now require the device to be in touch mode at the time of display. This is enforced in their respective `IInAppMessageViewFactory` default implementations.
  - See https://developer.android.com/reference/android/view/View.html#isInTouchMode().
- Removed `ViewUtils.setFocusableInTouchModeAndRequestFocus()`.
- `AppboyUnityPlayerNativeActivity`, `AppboyOverlayActivity`, `AppboyUnityNativeInAppMessageManagerListener`, `AppboyUnityPlayerNativeActivity`, `AppboyUnityPlayerNativeActivity`, and `IAppboyUnityInAppMessageListener` have been removed from the `android-sdk-unity` project.
  - `UnityPlayerNativeActivity` was deprecated in 2015. See https://unity3d.com/unity/beta/unity5.4.0b1.

##### Added
- Added proper support for navigating and closing Braze In-App Messages with directional-pads/TV remote input devices.
- Added the ability to customize the in-app message button border radius via `@dimen/com_appboy_in_app_message_button_corner_radius`.
- Added the ability to customize the in-app message button border color stroke width via `@dimen/com_appboy_in_app_message_button_border_stroke`.
  - The stroke width used when an in-app message button border is focused is set via `@dimen/com_appboy_in_app_message_button_border_stroke_focused`.

##### Fixed
- Fixed an issue where Content Cards syncs were suppressed too often.
- Fixed an issue where in-app messages could not be closed on TVs or other devices without touch interactions.

##### Changed
- Changed in-app messages to return focus back to the view that previously held focus before a message is displayed as given via `Activity#getCurrentFocus()`.

## 5.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v5.0.0)

##### ⚠ Breaking
- Added `IInAppMessageView.hasAppliedWindowInsets()`.

##### Added
- Added `appboyBridge.logClick()` and `appboyBridge.getUser().setLanguage()` to the javascript interface for HTML In-App Messages.
- Added `Appboy.requestGeofences()` to request a Braze Geofences update for a manually provided GPS coordinate. Automatic Braze Geofence requests must be disabled to properly use this method.
  - Braze Geofences can only be requested once per session, either automatically by the SDK or manually with the above method.
- Added the ability to disable Braze Geofences from being requested automatically at session start.
  - You can do this by configuring the boolean value for `com_appboy_automatic_geofence_requests_enabled` in your `appboy.xml`.
  - You can also configure this at runtime by setting `AppboyConfig.setAutomaticGeofenceRequestEnabled()`.

##### Fixed
- Fixed an issue where multiple calls to `ViewCompat.setOnApplyWindowInsetsListener()` could result in in-app messages margins getting applied multiple times instead of exactly once.
- Fixed an issue where pure white `#ffffffff` in a dark theme in-app message would not be used when the device was in dark mode.
  - In this case, the original non-dark theme color would be used by the in-app message instead.

## 4.0.2

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v4.0.2)

##### Fixed
- Fixed an issue introduced in 4.0.0 where Content Card clicks wouldn't get forwarded to the parent RecyclerView based on its View's `clickable` status.
  - This would result in clicks not being handled or logged for Content Cards.

## 4.0.1

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v4.0.1)

##### Fixed
- Fixed an issue where in-app messages could display behind translucent status and navigation bars.

## 4.0.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v4.0.0)

##### Known Issues with version 4.0.0
- Content Card clicks are not handled or logged for Content Cards due to the `"Appboy.ContentCards"` style containing the `"clickable=true"` style. This is fixed in SDK version 4.0.2.

##### ⚠ Breaking
- Added `beforeInAppMessageViewOpened(), afterInAppMessageViewOpened(), beforeInAppMessageViewClosed(), afterInAppMessageViewClosed()` to the `IInAppMessageManagerListener` interface.
  - These methods are intended to help instrument each stage of the In-App Message View gaining and losing visibility status.
- Renamed `Card.getIsDismissible()` to `Card.getIsDismissibleByUser()`.

##### Added
- Added the ability to more easily test In-App Messages from the dashboard when sending a test push by bypassing the need to click the test push notification and instead directly display the test In-App Message when the app is in the foreground.
  - A push notification will still display if a test In-App Message push is received and the app is in the background.
  - You can enable this feature by configuring the boolean value for `com_appboy_in_app_message_push_test_eager_display_enabled` in your `appboy.xml`. The default value is false.
  - You can also enable this feature at runtime by setting `AppboyConfig.setInAppMessageTestPushEagerDisplayEnabled()` to true. The default value is false.
- Added the ability to customize how In-App Messages views are added to the view hierarchy with a custom `IInAppMessageViewWrapperFactory`.
  - See `AppboyInAppMessageManager.setCustomInAppMessageViewWrapperFactory()`.
  - For lightweight customizations, consider extending `DefaultInAppMessageViewWrapper` and overriding `getParentViewGroup()`, `getLayoutParams()`, and `addInAppMessageViewToViewGroup()`.
  - Addresses https://github.com/Appboy/appboy-android-sdk/issues/138.
- Added `Card.setIsDismissibleByUser()` to allow for integrators to disable the default swipe-to-dismiss behavior on a per-card basis.
- Added the ability to set the initial `AppboyLogger` log level via `appboy.xml`.
  - In your `appboy.xml`, set an integer value for `com_appboy_logger_initial_log_level`. The integer should correspond to a constant in `Log`, such as `Log.VERBOSE` which is 2.
  - Values set via `AppboyLogger.setLogLevel()` take precedence over values set in `appboy.xml`.
- Added the ability to use a custom Activity when opening deeplinks inside the app via a WebView. This Activity will be used in place of the default `AppboyWebViewActivity`.
  - You can do this by configuring the string value for `com_appboy_custom_html_webview_activity_class_name` in your `appboy.xml`. Note that the class name used `appboy.xml` must be the exact class name string as returned from `YourClass.class.getName()`.
  - You can also configure this at runtime by setting `AppboyConfig.setCustomWebViewActivityClass()`.
  - To retrieve the url in your custom WebView:
  ```
  final Bundle extras = getIntent().getExtras();
  if (extras.containsKey(Constants.APPBOY_WEBVIEW_URL_EXTRA)) {
    String url = extras.getString(Constants.APPBOY_WEBVIEW_URL_EXTRA);
  }
  ```

##### Fixed
- Fixed the inability to scroll through Content Cards when not using standard input mechanisms, aiding accessibility.
  - All Content Card views now have `selectable` and `focusable` attributes set to true.
  - Amazon Fire TV integrators should update to this version.
- Changed `AppboyInAppMessageHtmlUserJavascriptInterface.setCustomAttribute()` in the HTML javascript bridge to not coerce `Double` into `Float`.
- Fixed default Content Card rendering on low screen density devices. Previously, Content Cards could render without a margin and overflow off screen.
  - `@dimens/com_appboy_content_cards_max_width` now accurately sets the maximum possible width of a Content Card.
  - `@dimens/com_appboy_content_cards_divider_left_margin` and `@dimens/com_appboy_content_cards_divider_right_margin` are now used to provide a margin for Content Cards when the width of the Content Card does not exceed the max width of `@dimens/com_appboy_content_cards_max_width`.
- Fixed an issue where images in Content Cards could be resized before they had finished a layout, resulting in an 0 width/height ImageView.

##### Changed
- `InAppMessageImmersiveBase.getMessageButtons()` is now guaranteed to be non-null. When buttons are not set on the message, this list will be non-null and empty.
  - Calling `InAppMessageImmersiveBase.setMessageButtons()` with null will instead clear the `MessageButton` list
- Changed the SDK to compile against the 18.0.0 version of the Firebase Cloud Messaging dependency.
- Updated the exported `android-sdk-ui` consumer proguard rules to keep javascript interface methods.
- Changed the WebView used in HTML In-App Messages to have DOM storage enabled via `setDomStorageEnabled(true)`.
- Changed Content Cards to allow for blank or empty values for the title or description. In these situations, the `TextView`'s visibility is changed to `GONE` in the view hierarchy.

##### Removed
- Removed `Constants.APPBOY_WEBVIEW_URL_KEY`.

## 3.8.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v3.8.0)

##### ⚠ Breaking
- Added `renderUrlIntoInAppMessageView()`, `renderUrlIntoCardView()`, `getPushBitmapFromUrl()`, and `getInAppMessageBitmapFromUrl()` to the `IAppboyImageLoader` interface. These methods provide more information about the rendered object. For example, `renderUrlIntoCardView()` provides the `Card` object being rendered in the feed.
  - `IAppboyImageLoader.renderUrlIntoView()` and `IAppboyImageLoader.getBitmapFromUrl()` have been removed.
  - For maintaining behavioral parity, `renderUrlIntoInAppMessageView()` and `renderUrlIntoCardView()` can reuse your previous `IAppboyImageLoader.renderUrlIntoView()` implementation while `getPushBitmapFromUrl()` and `getInAppMessageBitmapFromUrl()` can reuse your previous `IAppboyImageLoader.getBitmapFromUrl()` implementation.
  - The Glide `IAppboyImageLoader` implementation has been updated and can be found [here](https://github.com/Appboy/appboy-android-sdk/blob/master/samples/glide-image-integration/src/main/java/com/appboy/glideimageintegration/GlideAppboyImageLoader.java).
- Removed `MessageButton#getIsSecondaryButton()` and `MessageButton#setIsSecondaryButton()`.

##### Added
- Added support for the upcoming feature, In-App Messages in Dark Mode.
  - Dark Mode enabled messages must be created from the dashboard. Braze does not dynamically theme In-App Messages for Dark Mode.
  - Added `IInAppMessageThemeable` interface to In-App Messages, which adds `enableDarkTheme()` to In-App Messages.
  - To configure/disable Braze from automatically applying a Dark Theme (when available from Braze's servers), use a custom `IInAppMessageManagerListener`.
    - ```
        if (inAppMessage instanceof IInAppMessageThemeable && ViewUtils.isDeviceInNightMode(AppboyInAppMessageManager.getInstance().getApplicationContext())) {
          ((IInAppMessageThemeable) inAppMessage).enableDarkTheme();
        }
      ```
- Added `Card.isContentCard()`.
- Added the ability to use an existing color resource for `com_appboy_default_notification_accent_color` in your `appboy.xml`.
  - For example: `<color name="com_appboy_default_notification_accent_color">@color/my_color_here</color>`.

##### Fixed
- Fixed an edge case where the `AppboyInAppMessageManager` could throw an `NullPointerException` if an in-app message was in the process of animating out while `AppboyInAppMessageManager.unregisterInAppMessageManager()` was called.
- Fixed an issue where multiple subscribers to Content Cards updates could cause a `ConcurrentModificationException` if they simultaneously attempted to mutate the list returned in `ContentCardsUpdatedEvent.getAllCards()`.
  - `ContentCardsUpdatedEvent.getAllCards()` now returns a shallow copy of the list of Content Cards model objects.
- Fixed an issue (introduced in 3.7.0) where the background color for fullscreen in-app messages was not set.
- Fixed an issue (introduced in 3.7.0) were images for fullscreen in-app messages would not appear on API 21 and below devices.

## 3.7.1

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v3.7.1)

##### Added
- Added `IInAppMessage.setExtras()` to set extras on In-App Messages.

##### Fixed
- Fixed an issue where a slow loading HTML In-App Message could throw an exception if the Activity changed before `onPageFinished()` was called.
- Removed `FEATURE_INDETERMINATE_PROGRESS` and `FEATURE_PROGRESS` from `AppboyWebViewActivity`.

## 3.7.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v3.7.0)

##### Known Issues
- This release introduced issues with in-app message unregistration (`AppboyInAppMessageManager.unregisterInAppMessageManager()`) and fullscreen in-app messages. These issues have been fixed in version 3.8.0 of the SDK.

##### Breaking
- Added the `applyWindowInsets()` method to `IInAppMessageView` interface. This allows for granular customization at the in-app message view level with respect to device notches.
- The old configuration key used in `appboy.xml` for disabling location collection `com_appboy_disable_location_collection` is now deleted. This key is replaced by `com_appboy_enable_location_collection`. The default value of `com_appboy_disable_location_collection` is false. Braze location collection is disabled by default starting with Braze SDK version 3.6.0.
- Removes the Feedback feature from the SDK. All Feedback methods on the SDK, including `Appboy.submitFeedback()` and `Appboy.logFeedbackDisplayed()`, are removed.

##### Fixed
- Changed the behavior of In-App Messages to allow analytics to be logged again when the same In-App Message is displaying a new time.

##### Changed
- Improves support for in-app messages on “notched” devices (for example, iPhone X, Pixel 3XL). Full-screen messages now expand to fill the entire screen of any phone, while covering the status bar.
- Changed the behavior of HTML In-App Messages to not display until the content has finished loading as determined via `WebViewClient#onPageFinished()` on the in-app message's `WebView`.

## 3.6.0

[Release Date](https://github.com/Appboy/appboy-android-sdk/releases/tag/v3.6.0)

##### Breaking
- External user ids (provided via `Appboy.changeUser()`), are now limited to 997 bytes in UTF-8 encoding.
  - Existing user IDs will be truncated to 997 bytes in UTF-8 encoding.
  - New user IDs (via `Appboy.changeUser()`) will be rejected if too long.
  - This byte limit can be read in code via `Constants#USER_ID_MAX_LENGTH_BYTES`.
- Added `IInAppMessage.getMessageType()` to return the `MessageType` enum for easier in-app message type checking.
- Braze location collection is disabled by default. If you choose to use our location services, you must explicitly enable location services.
  - You can do this by configuring the boolean value for `com_appboy_enable_location_collection` in your `appboy.xml`. The default value is false.
  - You can also enable location collection at runtime by setting `AppboyConfig.setIsLocationCollectionEnabled()` to true.
  - The old configuration value `com_appboy_disable_location_collection` in appboy.xml is deprecated. It should be replaced with new configuration value of `com_appboy_enable_location_collection`.

##### Added
- Added `AppboyContentCardsFragment.getContentCardsRecyclerView()` to obtain the RecyclerView associated with the Content Cards fragment.
- Added `AppboyInAppMessageManager.getDefaultInAppMessageViewFactory()` to simplify most custom implementations of `IInAppMessageViewFactory`.

##### Changed
- Changed the click target area of in-app message close buttons to 48dp. The close button drawable was increased to `20dp` from `14dp`.
  - The width/height in dp of this click target can be configured with a `dimens` override for `com_appboy_in_app_message_close_button_click_area_width` and `com_appboy_in_app_message_close_button_click_area_height` respectively.
- Changed `UriUtils.getQueryParameters()` to handle the parsing of an opaque/non-hierarchical Uri such as `mailto:` or `tel:`.

## 3.5.0

##### Breaking
- Removed `IAppboyUnitySupport` interface from Appboy singleton object. Its methods have been added to the `IAppboy` interface.
- The `IAction` in `IContentCardsActionListener.onContentCardClicked()` is now annotated as `@Nullable`. Previously, this field was always non-null.
- Fixed an issue where `FLAG_ACTIVITY_NEW_TASK` was not added to configured back stack Activities when opening push. This resulted in push notifications failing to open deep links in that situation.
  - Custom push back stack Activities are set via `AppboyConfig.setPushDeepLinkBackStackActivityClass()`.

##### Added
- Added `Appboy.getCachedContentCards()` to provide an easier way to obtain the cached/offline list of Content Cards on the device.
- Added `Appboy.deserializeContentCard()` to allow for the deserialization of a Content Card. Useful for custom integrations that store the Content Cards data models in their own storage and recreate the Content Card afterwards.

##### Changed
- Deprecated `Card.isEqualTo()` in favor of using `Card.equals()`.

##### Fixed
- Fixed behavior in Content Cards and News Feed where cards without a click action wouldn't have their client click listeners called.

## 3.4.0

##### Added
- Added support for Android 10 Q (API 29).
  - With the addition of the `android.permission.ACCESS_BACKGROUND_LOCATION` permission in Android Q, this permission is now required for Braze Geofences to work on Android Q+ devices. Please see the documentation for more information.
  - The `AppboyNotificationRoutingActivity` class is now sent with the `Intent.FLAG_ACTIVITY_NO_HISTORY` Intent flag. This is not expected to be a user visible change nor will require any integration changes.
- Added the ability to enable Braze Geofences without enabling Braze location collection. Set `AppboyConfig.setGeofencesEnabled()` or `com_appboy_geofences_enabled` in your `appboy.xml` to enable Braze Geofences.
  - Note that Braze Geofences will continue to work on existing integrations if location collection is enabled and this new configuration is not present. This new configuration is intended for integrations that want Braze Geofences, but not location collection enabled as well.
- Added `Appboy.setGoogleAdvertisingId()` to pass a Google Advertising ID and Ad Tracking Limiting enabled flag back to Braze. Note that the SDK will not automatically collect either field.

##### Fixed
- Fixed in-app message buttons not properly respecting colors when using a Material Design style theme.

##### Breaking
- Geofences on Android Q+ devices will not work without the `android.permission.ACCESS_BACKGROUND_LOCATION` permission.
- Changed the signature of `IInAppMessageManagerListener.onInAppMessageButtonClicked()` to include the in-app message of the clicked button.
- Removed the deprecated `AppboyWebViewActivity.URL_EXTRA`. Please use `Constants.APPBOY_WEBVIEW_URL_EXTRA` instead.

## 3.3.0

##### Known Issues
- If using a defined back stack Activity (set via `AppboyConfig.setPushDeepLinkBackStackActivityClass()`), then push notifications containing deep links won't be opened. This behavior is fixed in 3.4.1.

##### Changed
- Changed the behavior of push deep links to not restart the launcher activity of the app when clicked.
- Changed the broadcast receiver responsible for sealing sessions after the session timeout to use `goAsync` to lower the occurrence of ANRs on certain devices.
  - This ANR would contain the constant `APPBOY_SESSION_SHOULD_SEAL` in the Google Play Console.
- Changed the default video poster (the large black & white play icon) used by default in HTML in-app messages to be transparent.

##### Added
- Added support for `long` type event properties.

##### Fixed
- Fixed fullscreen in-app messages on notched devices rendering with a gap at the top of the in-app message.
- Fixed behavior of in-app messages where modal display would take up the entire screen after successive rotations on older devices.

## 3.2.2

##### Changed
- Improved the reliability of the session start location logic when location collection is enabled.
- Changed the in-app message trigger behavior to not perform custom event triggering until any pending server trigger requests have finished.

##### Fixed
- Fixed a bug in `AppboyInAppMessageImageView` that made images loaded with Glide appear blurry or not appear when setting an aspect ratio.

## 3.2.1

##### Added
- Added `AppboyFirebaseMessagingService.handleBrazeRemoteMessage()` to facilitate forwarding a Firebase `RemoteMessage` from your `FirebaseMessagingService` to the `AppboyFirebaseMessagingService`.
  - `AppboyFirebaseMessagingService.handleBrazeRemoteMessage()` will return false if the argument `RemoteMessage` did not originate from Braze. In that case, the `AppboyFirebaseMessagingService` will do nothing.
  - A helper method `AppboyFirebaseMessagingService.isBrazePushNotification()` will also return true if the `RemoteMessage` originated from Braze.

#### Fixed
- Fixed an issue with `AppboyInAppMessageBoundedLayout` having a custom styleable attribute that collided with a preset Android attribute.

## 3.2.0

##### Important
- Please note the breaking push changes in release 3.1.1 regarding the `AppboyFirebaseMessagingService` before upgrading to this version.

##### Fixed
- Fixed an issue where a filename's canonical path was not validated during zip file extraction.
- Fixed an issue where the SDK setup verification would erroneously always log a warning that the `AppboyFcmReceiver` was registered using the old `com.google.android.c2dm.intent.RECEIVE` intent-filter.

##### Changed
- Improved the look and feel of in-app messages to adhere to the latest UX and UI best practices. Changes affect font sizes, padding, and responsiveness across all message types. Now supports button border styling.

##### Added
- Added collection of `ActivityManager.isBackgroundRestricted()` to device collection information.

## 3.1.1

##### Breaking
- Added `AppboyFirebaseMessagingService` to directly use the Firebase messaging event `com.google.firebase.MESSAGING_EVENT`. This is now the required way to integrate Firebase push with Braze. The `AppboyFcmReceiver` should be removed from your `AndroidManifest` and replaced with the following:
  - ```
    <service android:name="com.appboy.AppboyFirebaseMessagingService">
      <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
      </intent-filter>
    </service>
    ```
  - Also note that any `c2dm` related permissions should be removed from your manifest as Braze does not require any extra permissions for `AppboyFirebaseMessagingService` to work correctly.
- Changed signature of `Appboy.logPushNotificationActionClicked()`.

##### Added
- Added ability to render HTML elements in push notifications via `AppboyConfig.setPushHtmlRenderingEnabled()` and also `com_appboy_push_notification_html_rendering_enabled` in your `appboy.xml`.
  - This allows the ability to use "multicolor" text in your push notifications.
  - Note that html rendering be used on all push notification text fields when this feature is enabled.

##### Fixed
- Fixed behavior where the app would be reopened after clicking notification action buttons with a "close" button.
- Fixed behavior where in-app messages would not apply proper margins on devices with notched displays and would appear obscured by the notch.
- Fixed an issue that caused the enum `DeviceKey` to be unavailable in our public API.
- Fixed an issue in the `AppboyFcmReceiver` where the "is uninstall tracking push" method was looking for the extras bundle before its preprocessing into a bundle. This would result in uninstall tracking push being forwarded to your broadcast receiver as a silent push when it should not.
- Fixed an issue in the `AppboyLruImageLoader` where very large bitmaps stored in the cache could throw `OutOfMemoryError` when retrieving them from the cache.

##### Changed
- Changed behavior of the Feed and Content Cards image loader to always resize images to their true source aspect ratio after download.

## 3.1.0

##### Breaking
- Renamed `AppboyNotificationUtils.wakeScreenIfHasPermission()` to `AppboyNotificationUtils.wakeScreenIfAppropriate()`. Wakelocks can now be configured to not wake the device screen for push notifications.
  - This can be set via `AppboyConfig.setIsPushWakeScreenForNotificationEnabled()` and also `com_appboy_push_wake_screen_for_notification_enabled` in your `appboy.xml`.

##### Added
- A drop-in `AppboyContentCardsActivity` class has been added which can be used to display Braze Content Cards.
- Added an appboyBridge ready event to know precisely when the appboyBridge has finished loading in the context of an HTML in-app message.
  - Example below:
    ```javascript
     <script type="text/javascript">
       function logMyCustomEvent() {
         appboyBridge.logCustomEvent('My Custom Event');
       }
       window.addEventListener('ab.BridgeReady', logMyCustomEvent, false);
     </script>
    ```
- Added `Constants.TRAFFIC_STATS_THREAD_TAG` to identify the Braze network traffic with the `TrafficStats` API.
- Added the ability to configure a blacklist of Activity classes to disable automatic session handling and in-app message registration in the AppboyLifecycleCallbackListener. See `AppboyLifecycleCallbackListener.setActivityClassInAppMessagingRegistrationBlacklist()`, `AppboyLifecycleCallbackListener.setActivityClassSessionHandlingBlacklist()`, and constructor `AppboyLifecycleCallbackListener(boolean, boolean, Set<Class>, Set<Class>)`.

##### Changed
- Deprecated the Feedback feature. This feature is disabled for new accounts, and will be removed in a future SDK release.
- Changed the deprecated status of the `AppboyNotificationUtils.isUninstallTrackingPush()` method. Note that uninstall tracking notifications will not be forwarded to registered receivers.
- Improved in-app message triggering logic to fall back to lower priority messages when the Braze server aborts templating (e.g. from a Connected Content abort in the message body, or because the user is no longer in the correct segment for the message)

## 3.0.1

##### Changed
- Deprecated `Card.isRead()` and `Card.setIsRead()`. Please use `Card.isIndicatorHighlighted()` and `Card.setIndicatorHighlighted()` instead.

##### Added
- Added `Card.isClicked()`. Clicks made through `Card.logClick()` are now saved locally on the device for Content Cards.
- Added `AppboyConfig.setIsInAppMessageAccessibilityExclusiveModeEnabled()` which forces accessibility readers to only be able to read currently displaying in-app messages and no other screen contents.
  - This can also be set via `com_appboy_device_in_app_message_accessibility_exclusive_mode_enabled` in your `appboy.xml`.

## 3.0.0

##### Breaking
- From `AppboyConfig`, removed `getEnableBackgroundLocationCollection()`, `getLocationUpdateTimeIntervalSeconds()`, and `getLocationUpdateDistance()` and their respective setters in `AppboyConfig.Builder`.
- Removed `AppboyInAppMessageImmersiveBaseView.getMessageButtonsView()`.
- Removed the Fresco image library from the SDK. To displaying GIFs, you must use a custom image library. Please see `IAppboy#setAppboyImageLoader(IAppboyImageLoader)`.
  - We recommend the [Glide Image Library](https://bumptech.github.io/glide/) as a Fresco replacement.
  - `AppboyConfig.Builder.setFrescoLibraryEnabled()` has been removed.
  - `AppboyConfigurationProvider.getIsFrescoLibraryUseEnabled()` has been removed.

##### Fixed
- Fixed a NPE issue with the RecyclerView while saving the instance state in the `AppboyContentCardsFragment`.

##### Added
- Added the ability to set location custom attributes on the html in-app message javascript interface.
- Added compatibility with androidX dependencies.
    - This initial release adds direct compatibility for classes found under the `com.appboy.push` package. These classes are commonly used in conjunction with an `IAppboyNotificationFactory`. To use these compatible classes, add the following gradle import: `implementation 'com.appboy:android-sdk-ui-x:VERSION'` and replace your imports to fall under the `com.appboy.uix.push` package.
    - The gradle properties `android.enableJetifier=true` and `android.useAndroidX=true` are required when using androidX libraries with the Braze SDK.
- Added nullability annotation to `Appboy` and `AppboyUser` for better Kotlin interoperability.
- Added the ability to optionally whitelist keys in the device object. See `AppboyConfig.Builder.setDeviceObjectWhitelistEnabled()` and `AppboyConfig.Builder.setDeviceObjectWhitelist()` for more information.
  - The following example showcases whitelisting the device object to only include the Android OS version and device locale in the device object.
    ```
      new AppboyConfig.Builder()
          .setDeviceObjectWhitelistEnabled(true)
          .setDeviceObjectWhitelist(EnumSet.of(DeviceKey.ANDROID_VERSION, DeviceKey.LOCALE));
    ```

##### Removed
- Removed the ability to optionally track locations in the background.
- Removed Cross Promotion cards from the News Feed.
  - Cross Promotion cards have also been removed as a card model and will thus no longer be returned.

##### Changed
- Updated the Baidu China Push sample to use the version 2.9 Baidu JNI libraries and version 6.1.1.21 of the Baidu jar.

## 2.7.0

##### Breaking
- Renamed `AppboyGcmReceiver` to `AppboyFcmReceiver`. This receiver is intended to be used for Firebase integrations and thus the `com.google.android.c2dm.intent.REGISTRATION` intent-filter action in your `AndroidManifest` should be removed.
- Removed `AppboyConfigurationProvider.isGcmMessagingRegistrationEnabled()`, `AppboyConfigurationProvider.getGcmSenderId()`, `AppboyConfig.Builder.setGcmSenderId()`, and `AppboyConfig.Builder.setGcmMessagingRegistrationEnabled()`.

##### Changed
- Changed custom event property values validation to allow for empty strings.

## 2.6.0

##### Added
- Introduced support for the Content Cards feature, which will eventually replace the existing News Feed feature and adds significant capability.

##### Breaking
- Updated the minimum SDK version from 14 (Ice Cream Sandwich) to 16 (Jelly Bean).

##### Added
- Added `AppboyUser.setLocationCustomAttribute()` and `AppboyUser.unsetLocationCustomAttribute()`.

## 2.5.1

##### Changed
- Changed the behavior of push stories to ensure that after the story initially appears in the notification tray, subsequent page traversal clicks don't alert the user again.

##### Added
- The Braze SDK now automatically records when the user has disabled notifications at the app level.
  - The `appboy.xml` `com_appboy_notifications_enabled_tracking_on` boolean attribute and `AppboyConfig.Builder.setNotificationsEnabledTrackingOn()` have been deprecated and are no longer used.
  - This allows users to more effectively opt-out of push and leads to a more accurate push notification reachable audience.

##### Fixed
- Fixed an issue where, when the lock screen was present, notification action button and push story body clicks would not open the application immediately. Added `AppboyNotificationRoutingActivity` for handling notification action button and push story body clicks. 
- Fixed an issue where, for non fullscreen activities targeting API 27, requesting an orientation on activities would throw an exception.

## 2.5.0

##### Breaking
- Added `isControl()` to the `IInAppMessage` interface.
- Added `logDisplayFailure()` to the `IInAppMessage` interface. In-app message display failures may affect campaign statistics so care should be taken when logging display failures.
- Added the `InAppMessageControl` class to represent control in-app messages. Control in-app messages should not be displayed to users and should only call `logImpression()` at render time.
  - Requesting in-app message display, even if the stack is non-empty, may potentially lead to no in-app message displaying if the in-app message is a control in-app message.
- Added `AppboyInAppMessageManager.setCustomControlInAppMessageManagerListener()` to modify the lifecycle behavior for control in-app messages.
- Removed `logInAppMessageClick`, `logInAppMessageButtonClick`, and `logInAppMessageImpression` from Appboy Unity player subclasses and `AppboyUnityActivityWrapper`.
- Removed `AppboyConfigurationProvider.getIsUilImageCacheDisabled()` and `AppboyConfig.Builder.setDisableUilImageCache()`.

##### Fixed
- Fixed the issue where in-app messages triggered on session start could potentially be templated with the old user's attributes.
- Fixed a bug where calling `Appboy.wipeData()` or `Appboy.disableSdk()` could potentially lead to null instances being returned from `Appboy.getInstance()`.
- Fixed the issue where push deep links did not respect the back stack behavior when instructed to open inside the app's WebView.
- Fixed a bug where the push received broadcast action contained the host package name twice.

## 2.4.0

##### Fixed
- Fixed a bug where calling `Appboy.wipeData()` would throw an uncaught exception when the Google Play location services library was not present.

##### Added
- Added the ability to listen for notification deleted intents from the `AppboyGcmReceiver` via the action suffix `AppboyNotificationUtils.APPBOY_NOTIFICATION_DELETED_SUFFIX`.
- Added a notification creation timestamp to notifications built from the `AppboyGcmReceiver`. This allows for calculating the duration of a notification. Intents will contain `Constants.APPBOY_PUSH_RECEIVED_TIMESTAMP_MILLIS` in the intent extras bundle.

##### Changed
- Deprecated `AppboyNotificationUtils.isUninstallTrackingPush()` to always return false. Uninstall tracking no longer requires sending a silent push notification to devices.

## 2.3.0

##### Known Issues with version 2.3.0
- If the Google Play location services library is not present, calls to `Appboy.wipeData()` will throw an uncaught exception.

##### Breaking
- Removed the `appboyInAppMessageCustomFontFile` custom xml attribute. Custom font typefaces must now be located in the `res/font` directory.
  - To override a Braze style, both `android:fontFamily` and `fontFamily` style attributes must be set to maintain compatibility across all SDK versions. Example below:
  ```
  <item name="android:fontFamily">@font/YOUR_CUSTOM_FONT_FAMILY</item>
  <item name="fontFamily">@font/YOUR_CUSTOM_FONT_FAMILY</item>
  ```
  - See https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html for more information.
- Removed `AppboyInAppMessageButtonView.java` and `AppboyInAppMessageTextView.java`.
- Removed the `AppboyGeofenceService`. Geofence integration no longer requires a manifest registration. Any reference to `AppboyGeofenceService` can safely be removed from your manifest.
- Renamed `AppboyUnityPlayerNativeActivityWrapper` to `AppboyUnityActivityWrapper`.

##### Fixed
- Fixed a bug where sessions could be opened and closed with a null activity.

##### Added
- Added the ability to have the Braze SDK automatically register for Firebase Cloud Messaging.
  - Enabled via `com_appboy_firebase_cloud_messaging_registration_enabled` boolean attribute in XML or via `AppboyConfig.Builder.setIsFirebaseCloudMessagingRegistrationEnabled()`.
  - The Firebase Cloud Messaging Sender ID is set via `com_appboy_firebase_cloud_messaging_sender_id` string attribute in XML or via `AppboyConfig.Builder.setFirebaseCloudMessagingSenderIdKey()`.
  - The Firebase Cloud Messaging dependencies must still be compiled into your project. The Braze SDK does not compile any Firebase Cloud Messaging dependencies as part of this release.
- Added UnityPlayerActivity support to AppboyUnityActivityWrapper. Previously only UnityPlayerNativeActivity was supported.
- Added a AppboyUnityPlayerActivity class for the UnityPlayerActivity for both prime31 and non-prime31 integrations.

## 2.2.5

##### Added
- Added support for wiping all customer data created by the Braze SDK via `Appboy.wipeData()`.
- Added `Appboy.disableSdk()` to disable the Braze SDK. 
- Added `Appboy.enableSdk()` to re-enable the SDK after a call to `Appboy.disableSdk()`.

##### Changed
- Changed `AppboyInAppMessageWebViewClientListener` to call `onDismissed()` when `onCloseAction()` gets called for HTML in-app messages.

##### Fixed
- Fixed an issue where internal thread pool executors could get blocked on a long running task and throw `RejectedExecutionException`.

## 2.2.4

##### Added
- Added `AppboyConfig.Builder.setIsSessionStartBasedTimeoutEnabled()` which optionally sets the session timeout behavior to be either session-start or session-end based. The default behavior is to be session-end based.
  - The use of this flag is recommended for long (30 minutes or longer) session timeout values.
  - This value can also be configured via `appboy.xml` with the boolean `com_appboy_session_start_based_timeout_enabled` set to true.

## 2.2.3

##### Added
- Added support for any custom image library to work with in-app messages and the news feed, including the [Glide Image Library](https://bumptech.github.io/glide/). 
  - Please see `IAppboy#setAppboyImageLoader(IAppboyImageLoader)` for how to set a custom image library.
- Added the `Glide Image Integration` sample app, showcasing how to use the Glide Library.

#### Changed
- Updated the proguard rules for Fresco and Notification Enabled Tracking.

## 2.2.2

##### Added
- The Braze SDK may now optionally record when the user has disabled notifications at the app level.
  - Enabled via `appboy.xml` using the `com_appboy_notifications_enabled_tracking_on` boolean attribute or via `AppboyConfig.Builder.setNotificationsEnabledTrackingOn()`.
  - If using proguard in your app and Braze SDK v2.2.2 or below, please add `-keep class android.support.v4.app.NotificationManagerCompat { *; }` to your proguard rules.
  - (Update) Note that starting with Braze Android SDK Version [`2.5.1`](https://github.com/Appboy/appboy-android-sdk/blob/master/CHANGELOG.md#251), this feature is now automatically enabled.

## 2.2.1

##### Added
- Added `Other`, `Unknown`, `Not Applicable`, and `Prefer not to Say` options for user gender.

## 2.2.0

##### Breaking
- Removed `Appboy.requestInAppMessageRefresh()` and removed support for Original in-app messages. Note that all customers on version 2.2.0 and newer should use triggered in-app messages.
- Changed the signature of most methods on the `IAppboy` interface. Methods that logged values now return void instead of boolean. 
  - `IAppboy.openSession()` now returns void.   
  - `IAppboy.closeSession` now returns void.
  - `IAppboy.changeUser()` now returns void. To get the current user, please call `IAppboy.getCurrentUser()`.
  - `IAppboy.logCustomEvent()` and all method overloads now return void.
  - `IAppboy.logPurchase()` and all method overloads now return void.
  - `IAppboy.submitFeedback()` now returns void.
  - `IAppboy.logPushNotificationOpened()` now returns void.
  - `IAppboy.logPushNotificationActionClicked()` now returns void.
  - `IAppboy.logFeedDisplayed()` now returns void.
  - `IAppboy.logFeedbackDisplayed()` now returns void.
- Removed `AppboyFeedbackFragment.FeedbackResult.ERROR`.
- Changed `AppboyFeedbackFragment.FeedbackFinishedListener` to `AppboyFeedbackFragment.IFeedbackFinishedListener`.
- Changed `AppboyFeedbackFragment.FeedbackResult.SENT` to `AppboyFeedbackFragment.FeedbackResult.SUBMITTED`. 
- Removed `Appboy.fetchAndRenderImage()`. Please use `getAppboyImageLoader().renderUrlIntoView()` instead.
- Removed `AppboyFileUtils.getExternalStorage()`.

##### Added
- Added Push Stories, a new push type that uses `DecoratedCustomViewStyle` to display multiple images in a single notification. We recommend posting push stories to a notification channel with vibration disabled to avoid repeated vibrations as the user navigates through the story.

##### Changed
- The Braze singleton now internally performs most actions on a background thread, giving a very substantial performance boost to all actions on the `Appboy` singleton.

#### Fixed
- Reduced the number of connections made when the Braze SDK downloads files and images. Note that the amount of data downloaded has not changed.

## 2.1.4

##### Added
- Added a check on Braze initialization for the "Calypso AppCrawler" indexing bot that disables all Braze network requests when found. This prevents erroneous Braze data from being sent for Firebase app indexing crawlers.
- Added the ability to disable adding an activity to the back stack when automatically following push deep links. Previously, the app's main activity would automatically be added to the back stack.
  - Enabled via `appboy.xml` using the `com_appboy_push_deep_link_back_stack_activity_enabled` boolean attribute or via `AppboyConfig.Builder.setPushDeepLinkBackStackActivityEnabled()`.
- Added the ability to specify a custom activity to open on the back stack when automatically following push deep links. Previously, only the app's main activity could be used.
  - The custom activity is set via `appboy.xml` using the `com_appboy_push_deep_link_back_stack_activity_class_name` string attribute or via `AppboyConfig.Builder.setPushDeepLinkBackStackActivityClass()`. Note that the class name used in the `appboy.xml` must be the exact class name string as returned from `YourClass.class.getName()`.
- Added the `setLanguage()` method to `AppboyUser` to allow explicit control over the language you use in the Braze dashboard to localize your messaging content.

##### Changed
- Added support for acquiring wake locks on Android O using the notification channel importance instead of the individual notification's priority.

## 2.1.3

##### Fixed
- Fixed a bug where implicit intents for custom push broadcast receivers would be suppressed in devices running Android O.
- Updated the Braze ProGuard configuration to ensure Google Play Services classes required by Geofencing aren't renamed.

## 2.1.2

##### Fixed
- Fixed a bug where sealed session flushes would not be sent on apps with long session timeouts due to Android O background service limitations.

## 2.1.1

##### Added
- Added the ability to set a custom API endpoint via `appboy.xml` using the `com_appboy_custom_endpoint` string attribute or via `AppboyConfig.Builder.setCustomEndpoint()`.

##### Fixed
- Fixed a bug where date custom attributes were formatted in the device's locale, which could result in incorrectly formatted dates. Date custom attributes are now always formatted in `Locale.US`.

## 2.1.0

##### Breaking
- Updated the minimum SDK version from 9 (Gingerbread) to 14 (Ice Cream Sandwich). 
  - We recommend that session tracking and in-app messages registration be done via an `AppboyLifecycleCallbackListener` instance using [`Application.registerActivityLifecycleCallbacks()`](https://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks)).
- Removed the deprecated field: `AppboyLogger.LogLevel`. Please use `AppboyLogger.setLogLevel()` and `AppboyLogger.getLogLevel()` instead.
- Updated the v4 support library dependency to version 26.0.0. To download Android Support Libraries versions 26.0.0 and above, you must add the following line to your top-level `build.gradle` repositories block:
  ```
  maven {
    url "https://maven.google.com"
  }
  ```

##### Added
- Added support for Android O notification channels. In the case that a Braze notification does not contain the id for a notification channel, Braze will fallback to a default notification channel. Other than the default notification channel, Braze will not create any channels. All other channels must be programatically defined by the host app.
  - Note that default notification channel creation will occur even if your app does not target Android O. If you would like to avoid default channel creation until your app targets Android O, do not upgrade to this version.
  - To set the user facing name of the default Braze notification channel, please use `AppboyConfig.setDefaultNotificationChannelName()`.
  - To set the user facing description of the default Braze notification channel, please use `AppboyConfig.setDefaultNotificationChannelDescription()`.

##### Changed
- Updated the target SDK version to 26.

## 2.0.5

##### Fixed
- Fixed a bug where relative links in `href` tags in HTML in-app messages would get passed as file Uris to the `AppboyNavigator`.

##### Added
- Added `Double` as a valid value type on `AppboyUser.setCustomUserAttribute()`.
- Added user aliasing capability. Aliases can be used in the API and dashboard to identify users in addition to their ID.  See the `addAlias` method on [`AppboyUser`](https://appboy.github.io/appboy-android-sdk/javadocs/com/appboy/AppboyUser.html) for more information.

## 2.0.4

##### Changed
- Made further improvements to Braze singleton initialization performance.

## 2.0.3

##### Changed
- Enabled TLS 1.2 for Braze HTTPS connections running on API 16+ devices. Previously, for devices running on API 16-20, only TLS 1.0 was enabled by default.
- Improved Braze singleton initialization performance.

## 2.0.2

##### Fixed
- Fixed a bug where identifying a user while a request was in flight could cause newly written attributes on the old user to be orphaned in local storage.

## 2.0.1

##### Added
- Added support for displaying Youtube videos inside of HTML in-app messages and the Braze Webview. For HTML in-app messages, this requires hardware acceleration to be enabled in the Activity where the in-app message is being displayed, please see https://developer.android.com/guide/topics/graphics/hardware-accel.html#controlling. Please note that hardware acceleration is only available on API versions 11 and above.
- Added the ability to access Braze's default notification builder instance from custom `IAppboyNotificationFactory` instances. This simplifies making small changes to Appboy's default notification handling.
- Improved `AppboyImageUtils.getBitmap()` by adding the ability to sample images using preset view bounds.

## 2.0.0

##### Breaking
- Removed the following deprecated methods and fields:
  - Removed the unsupported method `Appboy.logShare()`.
  - Removed `Appboy.logPurchase(String, int)`.
  - Removed `Appboy.logFeedCardImpression()` and `Appboy.logFeedCardClick()`. Please use `Card.logClick()` and `Card.logImpression()` instead.
  - Removed the unsupported method `Appboy.getAppboyResourceEndpoint()`.
  - Removed `IAppboyEndpointProvider.getResourceEndpoint()`. Please update your interface implementation if applicable.
  - Removed `Appboy.registerAppboyGcmMessages()`. Please use `Appboy.registerAppboyPushMessages()` instead.
  - Removed `AppboyInAppMessageBaseView.resetMessageMargins()`. Please use `AppboyInAppMessageBaseView.resetMessageMargins(boolean)` instead.
  - Removed `com.appboy.unity.AppboyUnityGcmReceiver`. To open Braze push deep links automatically in Unity, set the boolean configuration parameter `com_appboy_inapp_show_inapp_messages_automatically` to true in your `appboy.xml`.
  - Removed the unsupported method `AppboyUser.setBio()`.
  - Removed `AppboyUser.setIsSubscribedToEmails()`. Please use `AppboyUser.setEmailNotificationSubscriptionType()` instead.
  - Removed `Constants.APPBOY_PUSH_CUSTOM_URI_KEY`. Please use `Constants.APPBOY_PUSH_DEEP_LINK_KEY` instead.
  - Removed `Constants.APPBOY_CANCEL_NOTIFICATION_TAG`.
  - Removed `com.appboy.ui.actions.ViewAction` and `com.appboy.ui.actions.WebAction`.
  - Removed `CardCategory.ALL_CATEGORIES`. Please use `CardCategory.getAllCategories()` instead.
  - Removed `AppboyImageUtils.storePushBitmapInExternalStorage()`.
  - Removed `AppboyFileUtils.canStoreAssetsLocally()` and `AppboyFileUtils.getApplicationCacheDir()`.
  - Removed `InAppMessageModal.getModalFrameColor()` and `InAppMessageModal.setModalFrameColor()`. Please use `InAppMessageModal.getFrameColor()` and `InAppMessageModal.setFrameColor()` instead.
  - Removed `com.appboy.enums.SocialNetwork`.
  - Removed `AppboyNotificationUtils.getAppboyExtras()`. Please use `AppboyNotificationUtils.getAppboyExtrasWithoutPreprocessing()` instead.
  - Removed `AppboyNotificationUtils.setLargeIconIfPresentAndSupported(Context, AppboyConfigurationProvider, NotificationCompat.Builder)`. Please use `AppboyNotificationUtils.setLargeIconIfPresentAndSupported(Context, AppboyConfigurationProvider, NotificationCompat.Builder, Bundle)` instead.
  - Removed `AppboyInAppMessageManager.hideCurrentInAppMessage()`. Please use `AppboyInAppMessageManager.hideCurrentlyDisplayingInAppMessage()` instead.
- Changed method signatures for `gotoNewsFeed()` and `gotoURI()` in `IAppboyNavigator`. Please update your interface implementation if applicable.
- Removed `Appboy.unregisterAppboyPushMessages()`. Please use `AppboyUser.setPushNotificationSubscriptionType()` instead.
- Moved `getAppboyNavigator()` and `setAppboyNavigator()` from `Appboy.java` to `AppboyNavigator.java`.
- The Braze Baidu China Push integration now uses the Baidu `channelId` as the push token. Please update your push token registration code to pass `channelId` instead of `userId` into `Appboy.registerAppboyPushMessages()`. The China Push sample has been updated.
- Removed the `wearboy` and `wear-library` modules. Android Wear 1.0 is no longer supported. Please remove `AppboyWearableListenerService` from your `AndroidManifest.xml` if applicable.

##### Added
- Added a javascript interface to HTML in-app messages	with ability to	log custom events, purchases, user attributes, navigate users, and close the messaage.
- Added the ability to set a single delegate object to custom handle all Uris opened by Braze across in-app messages, push, and the news feed. Your delegate object should implement the `IAppboyNavigator` interface and be set using `AppboyNavigator.setAppboyNavigator()`.
  - See https://github.com/Appboy/appboy-android-sdk/blob/master/droidboy/src/main/java/com/appboy/sample/CustomAppboyNavigator.java for an example implementation.
  - You must also provide instructions for Braze to navigate to your app's (optional) news feed implementation. To use Braze's default handling, call `AppboyNavigator.executeNewsFeedAction(context, uriAction);`.
  - Note: Previously, `AppboyNavigator` was only used when opening in-app messages.

##### Changed
- Removed the need to manually add declarations for Braze's news feed and in-app message activities (`AppboyFeedActivity` and `AppboyWebViewActivity`) to the app `AndroidManifest.xml`. If you have these declarations in your manifest, they can be safely removed.
- Push notifications with web url click actions now open in an in-app webview instead of the external mobile web browser when clicked.

## 1.19.0

##### Added
- Added support for registering geofences with Google Play Services and messaging on geofence events. Please reach out to success@braze.com for more information about this feature.

##### Removed
- Support for share type notification action buttons and custom notification action buttons was removed.

##### Changed
- Push deep links that can be handled by the current app are automatically opened using the current app. Previously, if another app could handle the deep link as well, a chooser dialog would open.
  - Thanks to [catacom](https://github.com/catacom)
  - See https://github.com/Appboy/appboy-android-sdk/pull/71
- `AppboyImageUtils.storePushBitmapInExternalStorage()` has been deprecated.

## 1.18.0

##### Breaking
- Renamed the `android-sdk-jar` artifact in the `gh-pages` branch to `android-sdk-base` and changed its format from `jar` to `aar`. Most integrations depend on `android-sdk-ui` and won't need to take any action.
  - Note: If you were compiling `android-sdk-jar` in your `build.gradle`, you must now compile `android-sdk-base`.

##### Added
- Added the ability to set custom read and unread icons for News Feed cards. To do so, override the `Appboy.Cards.ImageSwitcher` style in your `styles.xml` and add `appboyFeedCustomReadIcon` and `appboyFeedCustomUnReadIcon` drawable attributes.
- Added a sample app showcasing the FCM + Braze push integration. See `/samples/firebase-push`.
- Added a sample app for manual session integration. See `/samples/manual-session-integration`.

##### Removed
- Removed the `-dontoptimize` flag from Braze's UI consumer proguard rules. See https://github.com/Appboy/appboy-android-sdk/blob/master/android-sdk-ui/appboy-proguard-rules.pro for the latest Proguard config.
  - Thanks to [mnonnenmacher](https://github.com/mnonnenmacher)
  - See https://github.com/Appboy/appboy-android-sdk/pull/69

##### Changed
- Updated the Droidboy project to use the conventional Android Build System folder structure.

## 1.17.0

##### Breaking
- Added the ability to configure Braze completely at runtime using `Appboy.configure()`. Values set at runtime take precedence over their counterparts in `appboy.xml`. A complete example of Braze runtime configuration is available in our Hello Appboy sample app's [application class](https://github.com/Appboy/appboy-android-sdk/blob/master/hello-appboy/src/main/java/com/appboy/helloworld/HelloAppboyApplication.java).
  - Renamed `com.appboy.configuration.XmlAppConfigurationProvider` to `com.appboy.configuration.AppboyConfigurationProvider`.
  - `Appboy.configure(String)` changed to `Appboy.configure(Context, AppboyConfig)`.  To maintain parity, replace your current usage with the following equivalent snippit:
  ```
  AppboyConfig appboyConfig = new AppboyConfig.Builder()
          .setApiKey("your-api-key")
          .build();
  Appboy.configure(this, appboyConfig);
  ```

##### Fixed
- Fixed an issue where in-app messages triggered off of push clicks wouldn't fire because the push click happened before the in-app message configuration was synced to the device.

##### Changed
- Updated `Appboy.registerAppboyPushMessages()` to flush the subscription to the server immediately.
- Improved the accessibility-mode behavior of in-app messages.

## 1.16.0

##### Added
- Added the ability to toggle outbound network requests from the Braze SDK online/offline. See `Appboy.setOutboundNetworkRequestsOffline()` for more details.

##### Fixed
- Fixed a bug that caused session sealed automatic data flushes to not occur.

##### Removed
- Removed Braze notification action button icons and icon constants.

## 1.15.3

##### Fixed
- Fixed a bug where in-app messages triggered while no activity was registered with `AppboyInAppMessageManager` would be dropped.

## 1.15.2

##### Fixed
- Fixed a bug where in-app messages triggered while no activity was registered with `AppboyInAppMessageManager` would be displayed without assets.

## 1.15.1

##### Added
- Added Hebrew localization strings.

##### Changed
- Improved the initialization time of the Braze SDK.

##### Removed
- Removed fetching of the device hardware serial number as part of device metadata collection.

## 1.15.0

##### Breaking
- Deprecated `AppboyInAppMessageManager.hideCurrentInAppMessage()`. Please use `AppboyInAppMessageManager.hideCurrentlyDisplayingInAppMessage()` instead.

##### Added
- Added the option to handle session tracking and `InAppMessageManager` registration automatically on apps with a minimum supported SDK of API level 14 or above. This is done by registering an `AppboyLifecycleCallbackListener` instance using [`Application.registerActivityLifecycleCallbacks()`](https://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks)). See the Hello Appboy sample app's [application class](https://github.com/Appboy/appboy-android-sdk/blob/master/hello-appboy/src/main/java/com/appboy/helloworld/HelloAppboyApplication.java) for an example.
- Added support for upgraded in-app messages including image-only messages, improved image sizing/cropping, text scrolling, text alignment, configurable orientation, and configurable frame color.
- Added support for in-app messages triggered on custom event properties, purchase properties, and in-app message clicks.
- Added support for templating event properties within in-app messages.
- Added the ability to optionally open deep links and the main activity of the app automatically when a user clicks a push notification, eliminating the need to write a custom `BroadcastReceiver` for Braze push. To activate, set the boolean property `com_appboy_handle_push_deep_links_automatically` to `true` in your `appboy.xml`. Note that even when automatic deep link opening is enabled, Braze push opened and received intents will still be sent. To avoid double opening, remove your custom `BroadcastReceiver` or modify it to not open deep links.

## 1.14.1

##### Fixed
- Fixed a bug where images in short news and cross promotion News Feed cards would appear too small on high resolution devices. This bug did not affect Fresco users.

##### Changed
- Updated Baidu push service jar from v4.6.2.38 to v5.1.0.48.

## 1.14.0

##### Breaking
- Renamed `disableAllAppboyNetworkRequests()` to `enableMockAppboyNetworkRequestsAndDropEventsMode()` and fixes a bug where calling `Appboy.changeUser()` would cause a network request even in disabled/mocked mode. Note that `enableMockAppboyNetworkRequestsAndDropEventsMode` should only be used in testing environments.

##### Added
- Added the ability to log negatively-priced purchases.
- Added the option to sort News Feed cards based on read/unread status.
- Added a custom News Feed click delegate. To handle News Feed clicks manually, implement `IFeedClickActionListener` and register an instance using `AppboyFeedManager.getInstance().setFeedCardClickActionListener()`.  This enables use-cases such as selectively using the native browser to open web links.

##### Changed
- Added the ability to include file separators in User Ids.
- Changes Braze's default Log Level from VERBOSE to INFO. Previously disabled debug log statements are enabled and available for debugging. To change Braze's Log Level, update the value of `AppboyLogger.LogLevel`, e.g. `AppboyLogger.LogLevel = Log.VERBOSE`.

##### Removed
- Removed `keep` rules from `consumerProguardFiles` automatic Proguard configuration for potentially improved optimization for client apps. Note that client apps that Proguard Braze code must now store release mapping files for Braze to interpret stack traces. If you would like to continue to `keep` all Braze code, add `-keep class bo.app.** { *; }` and `-keep class com.appboy.** { *; }` to your Proguard configuration.
  - See https://github.com/Appboy/appboy-android-sdk/issues/54
- Removed `onRetainInstance()` from the Braze News Feed fragment. As a result, the News Feed may be used in nested fragments.

## 1.13.5

##### Added
- Defined `com_appboy_card_background` to provide simpler control of news feed card background color.
- Added a convenience method to `Month` to allow direct instantiation from a month integer.

##### Fixed
- Fixed a database access race condition in changeUser code.
  - See https://github.com/Appboy/appboy-android-sdk/issues/52 and https://github.com/Appboy/appboy-android-sdk/issues/39

##### Removed
- Removed optimizations from the private library's Proguard configuration to allow dexing Braze with Jack and Android Gradle Plugin 2.2.0+.

## 1.13.4

##### Added
- Added ability to set push and email subscription state from Droidboy.

##### Changed
- Open sourced Braze's Unity plugin library code.

## 1.13.3

##### Added
- Added the ability to set the large notification icon from within the GCM payload.
- Added `consumerProguardFiles` automatic Proguard configuration.

##### Fixed
- Fixed a bug where triggered HTML in-app messages would not always send button analytics.

##### Changed
- Updated Baidu push service jar from v4.3.0.4 to v4.6.2.38.
- Updated to log analytics for in-app messages and in-app message buttons with 'NONE' click actions.
- Updated the Droidboy sample app to use material design.
- Updated the Hello Appboy sample app to use Proguard.

## 1.13.2

##### Fixed
- Fixed bug where passing a `JSONObject` with multiple invalid keys or values to the `AppboyProperties` constructor would cause a `ConcurrentModificationException`.

## 1.13.1

##### Fixed
- Added handling to a case where certain devices were returning null Resources for GCM BroadcastReceiver onReceive contexts.

## 1.13.0

##### Added
- Added support for action-based, locally triggered in-app messages. In-app messages are now sent to the device at session start with associated trigger events. The SDK will display in-app messages in near real-time when the trigger event associated with a message occurs. Trigger events can be app opens, push opens, purchases, and custom events.

##### Changed
- Deprecated the old system of requesting in-app message display, now collectively known as 'original' in-app messaging, where messages were limited to displaying at app start.

##### Removed
- Removed Iab billing example code from Droidboy.

## 1.12.0

##### Breaking
- Removed the deprecated method `Appboy.requestSlideupRefresh()`.  Please use `Appboy.requestInAppMessageRefresh()` instead.
- Removed the deprecated class AppboySlideupManager.  Please use AppboyInAppMessageManager instead.

##### Changed
- HTML in-app message WebViews now use wide viewport mode and load pages in overview mode.
- Moved `AppboyImageUtils` to the private library with an updated api.
- Moved `WebContentUtils` to the private library.
- Renamed `IInAppMessageHtmlBase` to `InAppMessageHtmlBase`.
- Method count of the private Braze library has decreased by over 600 since version 1.11.0.

##### Removed
- Removed the partial duplicate of the private library's StringUtils from the ui project.

## 1.11.2

##### Fixed
- Fixed bug where large and small icons both rendered at full size in notification remoteviews for Honeycomb/ICS.  Now, if a large icon is available, only the large icon is shown.  Otherwise, the small icon is used.
- Fixed bug where push open logs were under-reported under certain device conditions.

## 1.11.1
- Placeholder for Unity release.

## 1.11.0

##### Added
- Creates Activity based Unity in-app messages (fixing an issue where touches on in-app messages were hitting the game behind the in-app message) and removes redundant Unity permissions.
- Added a method for setting modal frame color on in-app messages, no longer displays in-app messages on asset download failure and adds robustness.
- Added deep link support to `AppboyUnityGcmReceiver`.

##### Changed
- Makes the WebView background for HTML in-app messages transparent.  Ensure your HTML in-app messages expect a transparent background.
- Updated Google Play Services from to 7.5.0 to 8.3.0 and Play Services Support from 1.2.0 to 1.3.0.
  - See https://github.com/Appboy/appboy-android-sdk/issues/45
- Updated Braze WebView to support redirects to deep links and enables DOM storage.

## 1.10.3

##### Added
- Added Android M Support.  Under the runtime permissions model introduced in Android M, location permission must be explicitly obtained from the end user by the integrating app.  Once location permission is granted, Braze will resume location data collection on the subsequent session.

## 1.10.2

##### Added
- Added the ability to log a custom event from an HTML in-app message. To log a custom event from an HTML in-app message, navigate a user to a url of the form `appboy://customEvent?name=customEventName&p1=v2`, where the `name` URL parameter is the name of the event, and the remaining parameters are logged as String properties on the event.

## 1.10.1

##### Changed
- Enabled javascript in HTML in-app messages.
- Deprecated `logShare()` and `setBio()` in the public interface as support in the Braze dashboard has been removed.

## 1.10.0

##### Fixed
- Fixed an issue where applications in extremely resource starved environments were seeing ANRs from the periodic dispatch `BroadcastReceiver`.  This was not a bug in the Braze code, but a symptom of a failing application.  This updates our periodic dispatch mechanism so it won't have this symptomatic behavior, which in some cases should help developers track down the source of the actual issue (depending on the bug).  Apps that only use the Braze jar file will now have to register `<service android:name="com.appboy.services.AppboyDataSyncService"/>` in their `AndroidManifest.xml` to enable Braze to periodically flush data.
- Fixed a very rare issue where calling `Context.checkCallingOrSelfPermission()` would cause an exception to be thrown on certain custom Android builds.

##### Changed
- Updated the News Feed to not show cards in the local cache that have expired.

## 1.9.2

##### Fixed
- Fixed bug triggered when `AppboyWearableListenerService` was not registered.

## 1.9.0

##### Breaking
- All users must add the line `-dontwarn com.google.android.gms.**` to their proguard config file if using proguard.
  - See https://github.com/Appboy/appboy-android-sdk/issues/43

##### Added
- Added support for analytics from Android Wear devices.
- Added support for displaying notification action buttons sent from the Braze dashboard.  To allow image sharing on social networks, add the `<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />` permission to your `AndroidManifest.xml`.
- Added delegate to `FeedbackFinishedListener` enabling modification of feedback messages before they are sent to Appboy.  Also adds a disposition parameter to `onFeedbackFinished()`.
- Added support for GIF images in the News Feed and in in-app messages via the Facebook Fresco image library (version 0.6.1) as a provided library. If found in the parent app (your app), images and GIFs will be loaded using views from the Fresco library. In order to display GIFs, Fresco must be added as a dependency in the parent app. If not found in the parent app, News Feed cards and in-app messages will not display GIFs. To disable use of the Fresco library in the UI project, set the value of `com_appboy_enable_fresco_library_use` to false (or omit it) in your `appboy.xml`; to enable Fresco use set `com_appboy_enable_fresco_library_use` to true in your `appboy.xml`. ImageView specific attributes for News Feed cards and in-app messages, such as `scaleType`, must now be applied programmatically instead of being applied from `styles.xml`. If using Fresco and proguarding your app, please include http://frescolib.org/docs/proguard.html with your proguard config. If you are not using Fresco, add the `dontwarn com.appboy.ui.**` directive. Note: to use Fresco with Braze it must be initialized when your application launches.
- Added explicit top and bottom padding values for in-app message buttons to improve button rendering on some phones.  See the `Appboy.InAppMessage.Button` style in `styles.xml`.
- Added HTML in-app message types. HTML in-app messages consist of html along with an included zipped assets file to locally reference images, css, etc. See `CustomHtmlInAppMessageActionListener` in our Droidboy sample app for an example listener for the callbacks on the actions inside the WebView hosting the HTML in-app message.
- Added a `setAttributionData()` method to AppboyUser that sets an AttributionData object for the user. Use this method with attribution provider SDKs when attribution events are fired.

##### Changed
- Removed the need for integrating client apps to log push notifications inside their activity code.  **Please remove all calls to `Appboy.logPushNotificationOpened()` from your app as they are now all handled automatically by Braze.  Otherwise, push opens will be incorrectly logged twice.**
- In-app message views are now found in the `com.appboy.ui.inappmessage.views` package and in-app message listeners are now found in the `com.appboy.ui.inappmessage.listeners` package.

## 1.8.2

##### Added
- Added the ability to specify custom fonts for in-app message ui elements via the `appboyInAppMessageCustomFontFile` custom xml attribute.
- Increases the number of supported currency codes from 22 to 171.  All common currency codes are now supported. The full list of supported codes is available at our <a href="https://appboy.github.io/appboy-android-sdk/javadocs/com/appboy/IAppboy.html#logPurchase(java.lang.String,%20java.lang.String,%20java.math.BigDecimal,%20int,%20com.appboy.models.outgoing.AppboyProperties)">Javadoc</a>.
- Added the method `isUninstallTrackingPush()` to AppboyNotificationUtils to be able to detect background push sent for Braze uninstall tracking.

##### Changed
- Updated `BigPictureStyle` to show message in expanded view if summary is not present (after 1.7.0 a summary was required in expanded view to have text appear).

## 1.8.1
- Internal release for Xamarin, adds `AppboyXamarinFormsFeedFragment`.

## 1.8.0

##### Breaking
- Updated the minimum sdk version from 8 (froyo) to 9 (gingerbread).

##### Added
- Added an opt-in location service that logs background location events.

##### Fixed
- Fixed an in-app message lifecycle listener bug where certain lifecycle events could be fired twice.

## 1.7.3

##### Added
- Added Braze logging configurability by setting the AppboyLogger.LogLevel.  This is intended to be used in development environments and should not be set in a released application as logging statements are essential for debugging.
  - See https://github.com/Appboy/appboy-android-sdk/issues/38
- Added `getAppboyPushMessageRegistrationId()` to the Braze interface to enable retrieval of the GCM/ADM/Baidu registration ID Braze has set for the device.

##### Changed
- Updated our libraries to build against API level 22.
- Blacklisted custom attributes may no longer be incremented.

## 1.7.2

##### Added
- Introduced `AppboyNotificationUtils.getAppboyExtrasWithoutPreprocessing()` to parse Braze extras from GCM/ADM intent extras directly rather than requiring Braze extras to be parsed into a Bundle before being passed into `AppboyNotificationUtils.getAppboyExtras()`.
- Added the ability to send and retrieve extra key-value pairs via a News Feed card.
- Added the ability to define custom key-value properties on a custom event or purchase.  Property keys are strings and values may be strings, doubles, ints, booleans, or `java.util.Date` objects.

##### Removed
- Removed `DownloadUtils.java` from `com.appboy.ui.support`.  The `downloadImageBitmap()` function has been moved to `com.appboy.support.AppboyImageUtils`.

## 1.7.1

##### Added
- Upgrades Droidboy's custom user attributes and purchases capability and refactors the settings page.

##### Removed
- Removed requirement to manually integrate Font Awesome into the client app's /assets folder for in-app messages with icons.

## 1.7.0

##### Breaking
- Added summary subtext in `BigView` style notifications.  This is a breaking change in `BigView` style notification display.  Previously the summary text in `BigView` style notifications was set to the bundle/dashboard summary text if it was present, or the alert message otherwise.  Now the bundle/dashboard summary text is used to set the message subtext, which results in the bundle/dashboard summary text being shown in both the collapsed and expanded views.  See our updated push previews for a visualization of this change.

##### Added
- Added the ability to set a custom `IAppboyNotificationFactory` to customize push using `Appboy.setCustomAppboyNotificationFactory()`.
- Added the ability to override title and summary in `BigView` push notifications.
- Added the ability to set a default large icon for push messages by adding the `com_appboy_push_large_notification_icon` drawable resource to your `appboy.xml`.
- Added support for modal and full screen style in-app messages.  Also adds support for including fontawesome icons and images with in-app messages, changing colors on in-app message UI elements, expanded customization options, and message resizing for tablets.  Please visit our documentation for more information.
- Added a sample application (China Sample App) which integrates Baidu Cloud Push and Braze for sending push messages through Braze to devices without Google Services installed.
- Added `AppboyNotificationUtils.logBaiduNotificationClick()`, a utility method for logging push notification opens from push messages sent via Baidu Cloud Push by Braze.

##### Changed
- Refactors AppboyNotificationUtils into multiple classes in the com.appboy.push package and the AppboyImageUtils class in com.appboy.

## 1.6.2

##### Added
- Added a major performance upgrade that reduces CPU usage, memory footprint, and network traffic.
- Added 26 additional languages to localization support for Braze UI elements.
- Added local blocking for blacklisted custom attributes, events, and purchases.  However, blacklisted attributes may still be incremented (removed in release 1.7.3).
- Added the ability to set the accent color for notification in Android Lollipop and above.  This can be done by setting the `com_appboy_default_notification_accent_color` integer in your `appboy.xml`.
- Updated the News Feed to render wider on tablet screens.
- Added swipe handling for in-app messages on APIs <= 11.

##### Changed
- Updated our UI library to build against API level 21.

## 1.6.1

##### Fixed
- Fixed a timezone bug where short names were used for lookup, causing the default timezone (GMT) to be set in cases where the short name was not equal to the time zone Id.
- Fixed a bug where multiple pending push intents could override each other in the notification center.

## 1.6.0

##### Fixed
- Fixed News Feed swipe-refresh `CalledFromWrongThreadException`.

##### Changed
- Updated the android-L preview support from version 1.5.2 to support the public release of Android 5.0.  Updates the v4 support library dependency to version 21.0.0.
- `android.permission.GET_ACCOUNTS` is no longer required during initial GCM registration for devices running Jelly Bean and higher.  However, use of this permissions is recommended so that pre-Jelly Bean devices can register with GCM.
- `android.permission.WAKE_LOCK` is no longer required during initial GCM registration.  However, use of this permissions is recommended to allow notifications to wake the screen and engage users when the notification arrives.
- No longer overwrite messages in the notification center based on collapse key (GCM) or consolidation key (ADM).  Instead, overwrite based on message title and message alert, or, if specified, a custom notification id.
- Updated Droidboy to use the most recent Google IAB helper classes.

## 1.5.5

##### Added
- Added support for displaying Kindle notifications with images.

##### Changed
- Notifications with a minimum priority specified no longer trigger the device wakelock because Android does not display them in the status bar (they appear silently in the drawer).

##### Removed
- Removed styleable elements from the UI project. This should have no impact on consuming projects.

## 1.5.4

##### Added
- Incubates a feature to allow for runtime changes to be made to the API key. Please contact android@braze.com if you want to test this feature.
- Added support for Big View text summaries, allowing summary text to be displayed under the main text in a notification.
- Added support for custom URIs to open when a notification is clicked.
- Added support for notification duration control.  When specified, sets an alarm to remove a notification from the notification center after the specified duration.
- Added support for notification sounds.  Users can specify a notification sound URI to play with the notification.
- Added support for changing in-app message duration from the client app.  To do this, you can modify the slideup object passed to you in the `onReceive()` delegate using the new setter method `IInAppMessage.setDurationInMilliseconds()`.

##### Changed
- Updated `AppboyWebViewActivity` to always fill the parent view.  This forces some previously problematic websites to render at the correct size.

## 1.5.3

##### Added
- Added the ability to turn off Braze's automatic location collection using the `com_appboy_disable_location_collection` boolean in `appboy.xml`.
- Added the ability to send location tracking events to Braze manually using setLastKnownLocation on the AppboyUser.  This is intended to be used with `com_appboy_disable_location_collection` set to true so that locations are only being recorded from a single source.

## 1.5.2

##### Added
- Added support for GCM and ADM messages without collapse keys.
- Added support for GCM and ADM messages with notification priorities.
- Enabled setting a registration ID without a full push setup; `registerAppboyGcmMessages()` and `registerAppboyPushMessages()` no longer throw null pointer exceptions if Braze isn't correctly configured to display push messages.
- Enabled `AppboyWebViewActivity` to download items.
- Added support for apps built targeting android-L. Braze's process for registering push notifications had previously used an implicit service intent which caused a runtime error. Any apps built against android-L will need to upgrade to this version. However, apps with Braze that are/were built against any other versions of Android will run without issue on android-L. Thus, this is not an urgent upgrade unless you're working with android-L.

##### Removed
- Removed extraneous features from Droidboy so it's more easily digestible as a sample application.

## 1.5.1

##### Removed
- Removed obfuscation from parameter names on public models.

## 1.5.0

##### Added
- Added Kindle Fire support and ADM support.
- Added read/unread visual indicators to newsfeed cards. Use the configuration boolean com_appboy_newsfeed_unread_visual_indicator_on in appboy.xml to enabled the indicators.  Additionally, moved the `logFeedCardImpression()` and `logFeedCardClick()` methods to the card objects themselves.
- Added support to image loading in CaptionedImage and Banner cards for dynamic resizing after loading the image url; supports any aspect ratio.
- Added Hello Appboy sample project that shows a minimal use case of the Braze SDK.
- Added wake lock to `AppboyGcmReceiver` in the UI project. When the `WAKE_LOCK` permission is set, the screen will be turned on when a notification is received.

##### Changed
- Moved constants from `AppboyGcmReceiver` (ie: `APPBOY_GCM_NOTIFICATION_TITLE_ID`, etc.) into new `AppboyNotificationUtils` class.
- Restricted productId to 255 characters for `Appboy.logPurchase()`.

## 1.4.3

##### Removed
- Removed org.json classes from appboy.jar.

## 1.4.2

##### Added
- Added summary text for push image notifications.
- Added a new constant, `APPBOY_LOG_TAG_PREFIX`, for logging which includes the sdk version number.

## 1.4.1

##### Added
- Added automatic tests to verify that the sdk has integrated correctly.
- Added an optional quantity amount to in-app-purchases.

##### Changed
- Changed the device identifier from the device persistent `ANDROID_ID` to a non device persistent identifier for compliance with the new Google Play Terms of Service.

##### Removed
- Removed default max length and ellipsize properties in the `styles.xml`. The old defaults were set to 5 for maxLines for  newsfeed cards and ellipsize 'end'.

## 1.4.0

##### Added
- Added categories.
- Added swipe to refresh functionality to the newsfeed. The swipe to refresh colors are configurable in the colors xml file.
- Added configurable session timeout to the `appboy xml`.
- Added images to GCM push notifications.
- Added email and push notification subscription types for a user. Subscription types are explicitly opted in, subscribed, and unsubscribed. The old email boolean subscribe method has been deprecated.

##### Changed
- The feedback form now displays error popups to the user on invalid fields.

##### Removed
- Removed click logging on slideups when action is `None`.

## 1.3.4

##### Changed
- Minor changes to address some Lint issues in the UI project.
- Updated the open source AppboyGcmReceiver to use references to R.java for resource identifiers. This became possible when we moved AppboyGcmReceiver.java into the android-sdk-ui project (from the base library JAR).

## 1.3.3

##### Fixed
- Minor bug fix for a crash that occurred in certain conditions where the News Feed cards were replaced with a smaller set of cards.

## 1.3.2

##### Fixed
- Fixed a few minor style issues to be closer in line with Eclipse's preferences.
- Fixed a potential synchronization issue with the AppboyListAdapter.
- Added the ability to set the avatar image URL for your users.
- Fixed support for protocol URLs and adds an ActivityAction overload that streamlines the use of deep link and web link actions.

##### Changed
- Minor update to Chinese language translation.
- Moved com.appboy.AppboyGcmReceiver to the open source android-sdk-ui project. Also moves some of the constants previously available as AppboyGcmReceiver.* to com.appboy.constants.APPBOY_GCM_*. The CAMPAIGN_ID_KEY previously used in our sample app is still available in com.appboy.AppboyGcmReceiver, but if you were using other constants, you'll have to move the references.
- Removed input validation on custom attribute key names so that you can use foreign characters and spaces to your heart's desire. Just don't go over the max character limit.

## 1.3.1

##### Changed
- Updated to version 1.9.1 of Android-Universal-Image-Loader.
- Added Chinese language translations.
- Minor cleanup to imports.

## 1.3

Braze version 1.3 provides a substantial upgrade to the slideup code and reorganization for better flexibility moving forward, but at the expense of a number of breaking changes. We've detailed the changes in this changelog and hope that you'll love the added power, increased flexibility, and improved UI that the new Braze slideup provides. If you have any trouble with these changes, feel free to reach out to success@braze.com for help, but most migrations to the new code structure should be relatively painless.

##### Breaking
New AppboySlideupManager
- The AppboySlideupManager has moved to `com.appboy.ui.slideups.AppboySlideupManager.java`.
- An `ISlideupManagerListener` has been provided to allow the developer to control which slideups are displayed, when they are displayed, as well as what action(s) to perform when a slideup is clicked or dismissed.
  - The slideup `YOUR-APPLICATION-PACKAGE-NAME.intent.APPBOY_SLIDEUP_CLICKED` event has been replaced by the `ISlideupManagerListener.onSlideupClicked(Slideup slideup, SlideupCloser slideupCloser)` method.
- Added the ability to use a custom `android.view.View` class to display slideups by providing an `ISlideupViewFactory`.
- Default handling of actions assigned to the slideup from the Braze dashboard.
- Slideups can be dismissed by swiping away the view to either the left or the right. (Only on devices running Honeycomb Android 3.1 or higher).
  - Any slideups that are created to be dismissed by a swipe will automatically be converted to auto dismiss slideups on devices that are not running Android 3.1 or higher.

Slideup model
- A key value `extras` java.util.Map has been added to provide additional data to the slideup. `Extras` can be on defined on a per slideup basis via the dashboard.
- The `SlideFrom` field defines whether the slideup originates from the top or the bottom of the screen.
- The `DismissType` property controls whether the slideup will dismiss automatically after a period of time has lapsed, or if it will wait for interaction with the user before disappearing.
  - The slideup will be dismissed automatically after the number of milliseconds defined by the duration field have elapsed if the slideup's DismissType is set to AUTO_DISMISS.
- The ClickAction field defines the behavior after the slideup is clicked: display a news feed, redirect to a uri, or nothing but dismissing the slideup. This can be changed by calling any of the following methods: `setClickActionToNewsFeed()`, `setClickActionToUri(Uri uri)`, or `setClickActionToNone()`.
- The uri field defines the uri string that the slide up will open when the ClickAction is set to URI. To change this value, use the `setClickActionToUri(Uri uri)` method.
- Convenience methods to track slideup impression and click events have been added to the `com.appboy.models.Slideup` class.
  - Impression and click tracking methods have been removed from `IAppboy.java`.
- A static `createSlideup` method has been added to create custom slideups.

IAppboyNavigator
- A custom `IAppboyNavigator` can be set via `IAppboy.setAppboyNavigator(IAppboyNavigator appboyNavigator)` which can be used to direct your users to your integrated Braze news feed when certain slideups are clicked. This provides a more seamless experience for your users. Alternatively, you can choose not to provide an IAppboyNavigator, but instead register the new `AppboyFeedActivity` class in your `AndroidManifest.xml` which will open a new Braze news feed Activity when certain slideups are clicked.

Other
- A new base class, `AppboyBaseActivity`, has been added that extends `android.app.Activity` and integrates Braze session and slideup management.
- A drop-in `AppboyFeedActivity` class has been added which can be used to display the Braze News Feed.

## 1.2.1

##### Fixed
- Fixed a ProGuard issue.

## 1.2

##### Added
- Introduced two new card types (Banner card and Captioned Image card).
- Added support for sending down key/value pairs as part of a GCM message.

##### Fixed
- Minor bug fixes.

## 1.1

##### Added
- Added support for reporting purchases in multiple currencies.

##### Fixed
- Fixed a bug in caching custom events to a SQLite database.
- Fixed a validation bug when logging custom events.

##### Changed
- Deprecated `IAppboy.logPurchase(String, int)`.

## 1.0
- Initial release


================================================
FILE: LICENSE
================================================
Copyright (c) 2023 Braze, Inc.
All rights reserved.

* Use of source code or binaries contained within Braze’s SDKs is permitted only to enable use of the Braze platform by customers of Braze.
* Modification of source code and inclusion in mobile apps is explicitly allowed provided that all other conditions are met.
* Neither the name of Braze nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
* Redistribution of source code or binaries is disallowed except with specific prior written permission. Any such redistribution must retain the above copyright notice, this list of conditions and the following disclaimer.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: README.md
================================================
This repository has been permanently moved to https://github.com/braze-inc/braze-android-sdk.

-----


![Braze Logo](https://github.com/Appboy/appboy-android-sdk/blob/master/braze-logo.png)

# Android SDK

Successful marketing automation is essential to the future of your mobile app. Braze helps you engage your users beyond the download. Visit the following links for details and we'll have you up and running in no time!

- [Braze User Guide](https://www.braze.com/docs/user_guide/introduction/ "Braze User Guide")
- [Braze Developer Guide](https://www.braze.com/docs/developer_guide/platform_integration_guides/android/initial_sdk_setup/android_sdk_integration/ "Braze Developer Guide")
- [KDoc](https://appboy.github.io/appboy-android-sdk/kdoc/ "Braze Android SDK Class Documentation")
- [Javadoc(old)](https://appboy.github.io/appboy-android-sdk/javadocs/ "Braze Android SDK Class Documentation"). This Javadoc is discontinued. For up-to-date documentation, please visit the Kotlin Doc (KDoc) instead.

## Version Information

- The Braze Android SDK supports Android 4.1+ / API 16+ (Jelly Bean and up).
- Last Target SDK Version: 33
- Kotlin version: `org.jetbrains.kotlin:kotlin-stdlib:1.6.0`
- Last Compiled Firebase Cloud Messaging Version: 23.0.0
- Braze uses [Font Awesome](https://fortawesome.github.io/Font-Awesome/) 4.3.0 for in-app message icons. Check out the [cheat sheet](http://fortawesome.github.io/Font-Awesome/cheatsheet/) to browse available icons.

## Components

- `android-sdk-base` - the Braze SDK base analytics library.
- `android-sdk-ui` - the Braze SDK user interface library for in-app messages, push, and the news feed.
- `android-sdk-location` - the Braze SDK location library for location and geofences.
- `droidboy` - a sample app demonstrating how to use Braze in-depth.
- `android-sdk-unity` - a library that enables Braze SDK integrations on Unity.
- `samples` - a folder containing several sample apps for various integration options.

## Remote repository for gradle
The version should match the git version tag, or the most recent version noted in the changelog. An example dependency declaration is:

```
allprojects {
  repositories {
    maven { url "https://appboy.github.io/appboy-android-sdk/sdk" }
    ...
  }
}
```

```
dependencies {
  implementation 'com.appboy:android-sdk-ui:24.3.+'
  implementation 'com.appboy:android-sdk-location:24.3.+'
  ...
}
```

## Installing android-sdk-ui to Your Local Maven Repository
To install the UI library as an AAR file to your local maven repository, run the `install` task with
`./gradlew install`. You can reference it with groupId `com.appboy` and artifactId `android-sdk-ui`. The version should
match the git version tag, or the most recent version noted in the changelog. An example dependency declaration is:

```
repositories {
  mavenLocal()
  ...
}
```

```
dependencies {
  implementation 'com.appboy:android-sdk-ui:24.3.+'
}
```

## Questions?

If you have questions, please contact [support@braze.com](mailto:support@braze.com).


================================================
FILE: android-sdk-location/build.gradle
================================================
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

dependencies {
    api "com.appboy:android-sdk-base:${BRAZE_SDK_VERSION}"
    compileOnly "androidx.annotation:annotation:${ANDROIDX_ANNOTATIONS_VERSION}"
    implementation "org.jetbrains.kotlin:kotlin-stdlib:${KOTLIN_VERSION}"
    implementation "com.google.android.gms:play-services-location:${PLAY_SERVICES_LOCATION_VERSION}"
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${KOTLIN_COROUTINES_VERSION}")
    implementation "androidx.core:core:${ANDROIDX_CORE_VERSION}"
}

android {
  compileSdkVersion rootProject.ext.compileSdkVersion
  buildToolsVersion rootProject.ext.buildToolsVersion

  defaultConfig {
    minSdkVersion rootProject.ext.minSdkVersion
    targetSdkVersion rootProject.ext.targetSdkVersion
  }

  kotlinOptions {
    freeCompilerArgs = ['-Xjvm-default=all', '-Xopt-in=kotlin.RequiresOptIn']
    jvmTarget = "1.8"
  }

  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}


================================================
FILE: android-sdk-location/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.appboy.location">
     <application>
        <receiver
          android:name="com.braze.location.BrazeActionReceiver"
          android:exported="false">
        </receiver>
    </application>
</manifest>


================================================
FILE: android-sdk-location/src/main/java/com/braze/location/BrazeActionReceiver.kt
================================================
package com.braze.location

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.location.Location
import android.location.LocationManager
import android.os.Build
import androidx.annotation.Keep
import androidx.annotation.VisibleForTesting
import com.braze.BrazeInternal
import com.braze.Constants
import com.braze.enums.GeofenceTransitionType
import com.braze.models.outgoing.BrazeLocation
import com.braze.support.BrazeLogger.Priority.E
import com.braze.support.BrazeLogger.Priority.W
import com.braze.support.BrazeLogger.brazelog
import com.google.android.gms.location.Geofence
import com.google.android.gms.location.GeofencingEvent
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

@Keep
class BrazeActionReceiver : BroadcastReceiver() {
    @OptIn(DelicateCoroutinesApi::class)
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent == null) {
            brazelog(W) { "BrazeActionReceiver received null intent. Doing nothing." }
            return
        } else if (context == null) {
            brazelog(W) { "BrazeActionReceiver received null context. Doing nothing." }
            return
        }
        val applicationContext = context.applicationContext
        // This pending result allows us to perform work off the main thread and receive 10 seconds from the system
        // to finish processing. By default, a BroadcastReceiver is allowed 5 seconds (due to the ANR limit)
        // for processing.
        val pendingResult = goAsync()
        val actionReceiver = ActionReceiver(applicationContext, intent)

        GlobalScope.launch(Dispatchers.IO) {
            actionReceiver.run()
            pendingResult.finish()
        }
    }

    @VisibleForTesting
    internal class ActionReceiver(
        private val applicationContext: Context,
        private val intent: Intent
    ) {
        private val action: String? = intent.action
        fun run() {
            try {
                performWork()
            } catch (e: Exception) {
                // If the action receiver encounters an error, we still have to mark the broadcast receiver's work as finished.
                brazelog(E, e) {
                    "Caught exception while performing the BrazeActionReceiver work. Action: $action Intent: $intent"
                }
            }
        }

        /**
         * Performs the work as specified by the intent action.
         *
         * @return True iff the work was perform successfully.
         */
        @VisibleForTesting
        fun performWork() {
            brazelog { "Received intent with action $action" }
            when (action) {
                null -> {
                    brazelog { "Received intent with null action. Doing nothing." }
                }
                Constants.BRAZE_ACTION_RECEIVER_GEOFENCE_UPDATE_INTENT_ACTION -> {
                    brazelog { "BrazeActionReceiver received intent with geofence transition: $action" }
                    GeofencingEvent.fromIntent(intent)?.let { handleGeofenceEvent(applicationContext, it) }
                }
                Constants.BRAZE_ACTION_RECEIVER_SINGLE_LOCATION_UPDATE_INTENT_ACTION -> {
                    brazelog { "BrazeActionReceiver received intent with single location update: $action" }
                    val location = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                        intent.extras?.getParcelable(LocationManager.KEY_LOCATION_CHANGED, Location::class.java)
                    } else {
                        @Suppress("DEPRECATION")
                        intent.extras?.get(LocationManager.KEY_LOCATION_CHANGED) as Location?
                    }
                    location?.let { handleSingleLocationUpdate(applicationContext, it) }
                }
                else -> {
                    brazelog(W) { "Unknown intent received in BrazeActionReceiver with action: $action" }
                }
            }
        }

        companion object {
            private fun handleSingleLocationUpdate(applicationContext: Context, location: Location): Boolean {
                try {
                    BrazeInternal.logLocationRecordedEvent(applicationContext, BrazeLocation(location))
                } catch (e: Exception) {
                    brazelog(E, e) { "Exception while processing single location update" }
                    return false
                }
                return true
            }

            /**
             * Records all geofence transitions in the given geofence event.
             *
             * @param applicationContext The application context
             * @param geofenceEvent Google Play Services geofencing event
             * @return true if a geofence transition was recorded
             */
            @VisibleForTesting
            fun handleGeofenceEvent(applicationContext: Context, geofenceEvent: GeofencingEvent): Boolean {
                if (geofenceEvent.hasError()) {
                    val errorCode = geofenceEvent.errorCode
                    brazelog(W) { "Location Services error: $errorCode" }
                    return false
                }

                val transitionType = geofenceEvent.geofenceTransition
                val triggeringGeofences = geofenceEvent.triggeringGeofences
                return when {
                    Geofence.GEOFENCE_TRANSITION_ENTER == transitionType -> {
                        triggeringGeofences?.forEach { geofence ->
                            BrazeInternal.recordGeofenceTransition(
                                applicationContext,
                                geofence.requestId,
                                GeofenceTransitionType.ENTER
                            )
                        }
                        true
                    }
                    Geofence.GEOFENCE_TRANSITION_EXIT == transitionType -> {
                        triggeringGeofences?.forEach { geofence ->
                            BrazeInternal.recordGeofenceTransition(
                                applicationContext,
                                geofence.requestId,
                                GeofenceTransitionType.EXIT
                            )
                        }
                        true
                    }
                    else -> {
                        brazelog(W) { "Unsupported transition type received: $transitionType" }
                        false
                    }
                }
            }
        }
    }
}


================================================
FILE: android-sdk-location/src/main/java/com/braze/location/BrazeInternalGeofenceApi.kt
================================================
package com.braze.location

import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import com.braze.Constants
import com.braze.models.BrazeGeofence
import com.braze.support.IntentUtils
import com.google.android.gms.location.LocationServices

/**
 * An implementation of the geofence calls so that they are contained in a single, external
 * module that clients don't need to include if they don't want location services.
 */
class BrazeInternalGeofenceApi : IBrazeGeofenceApi {

    /**
     * @return the PendingIntent that should be fired when a geofence is triggered.
     */
    override fun getGeofenceTransitionPendingIntent(context: Context): PendingIntent {
        val geofenceIntent = Intent(Constants.BRAZE_ACTION_RECEIVER_GEOFENCE_UPDATE_INTENT_ACTION)
            .setClass(context, BrazeActionReceiver::class.java)
        val flags = PendingIntent.FLAG_UPDATE_CURRENT or IntentUtils.getMutablePendingIntentFlags()
        return PendingIntent.getBroadcast(context, 0, geofenceIntent, flags)
    }

    /**
     * Teardown all geofences associated with the given intent.
     */
    override fun teardownGeofences(applicationContext: Context, intent: PendingIntent) {
        LocationServices.getGeofencingClient(applicationContext)
            .removeGeofences(intent)
    }

    /**
     * Register a list of geofences.
     *
     * @param context Application context.
     * @param geofenceList List of [BrazeGeofence] to be registered.
     * @param geofenceRequestIntent The intent to fire when geofence is triggered.
     */
    override fun registerGeofences(
        context: Context,
        geofenceList: List<BrazeGeofence>,
        geofenceRequestIntent: PendingIntent
    ) {
        GooglePlayLocationUtils.registerGeofencesWithGooglePlayIfNecessary(context, geofenceList, geofenceRequestIntent)
    }

    /**
     * Deletes the geofence cache.
     */
    override fun deleteRegisteredGeofenceCache(context: Context) {
        GooglePlayLocationUtils.deleteRegisteredGeofenceCache(context)
    }
}


================================================
FILE: android-sdk-location/src/main/java/com/braze/location/BrazeInternalLocationApi.kt
================================================
package com.braze.location

import android.Manifest
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.location.Location
import android.location.LocationManager
import android.os.Build
import androidx.annotation.VisibleForTesting
import com.braze.Constants
import com.braze.configuration.BrazeConfigurationProvider
import com.braze.enums.LocationProviderName
import com.braze.models.IBrazeLocation
import com.braze.models.outgoing.BrazeLocation
import com.braze.support.BrazeLogger.Priority.E
import com.braze.support.BrazeLogger.Priority.I
import com.braze.support.BrazeLogger.Priority.V
import com.braze.support.BrazeLogger.brazelog
import com.braze.support.IntentUtils
import com.braze.support.hasPermission
import com.braze.support.nowInMilliseconds
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
import java.util.*

/**
 * An implementation of the location calls so that they are contained in a single, external
 * module that clients don't need to include if they don't want location services.
 */
class BrazeInternalLocationApi : IBrazeLocationApi {
    private lateinit var context: Context
    private lateinit var locationManager: LocationManager
    private lateinit var appConfigurationProvider: BrazeConfigurationProvider
    private lateinit var allowedLocationProviders: EnumSet<LocationProviderName>

    private val isLocationCollectionEnabled
        get() = if (appConfigurationProvider.isLocationCollectionEnabled) {
            brazelog(I) { "Location collection enabled via sdk configuration." }
            true
        } else {
            brazelog(I) { "Location collection disabled via sdk configuration." }
            false
        }

    /**
     * Initialize the object with some external variables. This function should be called immediately
     * after the object is created and should be called only once.
     */
    override fun initWithContext(
        context: Context,
        allowedProviders: EnumSet<LocationProviderName>,
        appConfigurationProvider: BrazeConfigurationProvider
    ) {
        this.context = context
        this.appConfigurationProvider = appConfigurationProvider
        this.allowedLocationProviders = allowedProviders
        locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
    }

    /**
     * Requests a location fix for the session on the device.
     */
    @Suppress("MissingPermission", "ReturnCount")
    override fun requestSingleLocationUpdate(manualLocationUpdateCallback: (location: IBrazeLocation) -> Unit): Boolean {
        if (!isLocationCollectionEnabled) {
            brazelog(I) { "Did not request single location update. Location collection is disabled." }
            return false
        }
        val hasFinePermission = context.hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)
        val hasCoarsePermission = context.hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
        if (!(hasCoarsePermission || hasFinePermission)) {
            // Nothing we can do here without any permissions
            brazelog(I) { "Did not request single location update. Neither fine nor coarse location permissions found." }
            return false
        }

        // Check for a GPS location
        if (hasFinePermission) {
            val lastKnownGpsLocationIfValid =
                getLastKnownGpsLocationIfValid(locationManager)
            if (lastKnownGpsLocationIfValid != null) {
                brazelog { "Setting user location to last known GPS location: $lastKnownGpsLocationIfValid" }
                manualLocationUpdateCallback.invoke(BrazeLocation(lastKnownGpsLocationIfValid))
                return true
            }
        }
        val provider = getSuitableLocationProvider(
            locationManager,
            allowedLocationProviders,
            hasFinePermission,
            hasCoarsePermission
        )
        if (provider == null) {
            brazelog { "Could not request single location update. Could not find suitable location provider." }
            return false
        }
        brazelog { "Requesting single location update with provider: $provider" }
        return try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                locationManager.getCurrentLocation(
                    provider,
                    null,
                    Dispatchers.IO.asExecutor()
                ) { location: Location? ->
                    brazelog { "Location manager getCurrentLocation got location: $location" }
                    if (location != null) {
                        manualLocationUpdateCallback.invoke(BrazeLocation(location))
                    }
                }
            } else {
                requestSingleUpdateFromLocationManager(provider)
            }
            true
        } catch (se: SecurityException) {
            brazelog(E, se) {
                "Failed to request single location update due to security exception from insufficient permissions."
            }
            false
        } catch (e: Exception) {
            brazelog(E, e) { "Failed to request single location update due to exception." }
            false
        }
    }

    /**
     * Determines the best location provider based on the permissions and list of providers allowed.
     */
    @Suppress("ComplexCondition")
    fun getSuitableLocationProvider(
        locationManager: LocationManager,
        allowedProviders: EnumSet<LocationProviderName>,
        hasFinePermission: Boolean,
        hasCoarsePermission: Boolean
    ): String? {
        var provider: String? = null
        // Check for our preferred providers in order.
        // Order set in accordance with https://stackoverflow.com/a/6775456/3745724
        if (hasFinePermission
            && allowedProviders.contains(LocationProviderName.GPS)
            && locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
        ) {
            provider = LocationManager.GPS_PROVIDER
        } else if ((hasCoarsePermission || hasFinePermission)
            && allowedProviders.contains(LocationProviderName.NETWORK)
            && locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
        ) {
            provider = LocationManager.NETWORK_PROVIDER
        } else if (hasFinePermission
            && allowedProviders.contains(LocationProviderName.PASSIVE)
            && locationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER)
        ) {
            provider = LocationManager.PASSIVE_PROVIDER
        }
        return provider
    }

    /**
     * Returns the last known location from the [LocationManager.GPS_PROVIDER], if
     * not older than [LAST_KNOWN_GPS_LOCATION_MAX_AGE_MS].
     * Assumes that the [Manifest.permission.ACCESS_FINE_LOCATION] permission is present.
     */
    @Suppress("MissingPermission")
    @VisibleForTesting
    fun getLastKnownGpsLocationIfValid(locationManager: LocationManager): Location? {
        if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            return null
        }
        val lastKnownGpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
            ?: return null

        val ageMs = nowInMilliseconds() - lastKnownGpsLocation.time
        if (ageMs > LAST_KNOWN_GPS_LOCATION_MAX_AGE_MS) {
            brazelog(V) { "Last known GPS location is too old and will not be used. Age ms: $ageMs" }
            return null
        }
        brazelog { "Using last known GPS location: $lastKnownGpsLocation" }
        return lastKnownGpsLocation
    }

    @Suppress("deprecation", "MissingPermission")
    private fun requestSingleUpdateFromLocationManager(provider: String) {
        val locationUpdateIntent =
            Intent(Constants.BRAZE_ACTION_RECEIVER_SINGLE_LOCATION_UPDATE_INTENT_ACTION)
                .setClass(context, BrazeActionReceiver::class.java)
        val flags = PendingIntent.FLAG_UPDATE_CURRENT or IntentUtils.getMutablePendingIntentFlags()
        val locationUpdatePendingIntent =
            PendingIntent.getBroadcast(context, 0, locationUpdateIntent, flags)
        // Using this deprecated method because new method only supports API 30+
        locationManager.requestSingleUpdate(provider, locationUpdatePendingIntent)
    }

    companion object {
        /**
         * The oldest a location from [LocationManager.getLastKnownLocation] using [LocationManager.GPS_PROVIDER]
         * can be used before requesting a new fix another provider.
         */
        const val LAST_KNOWN_GPS_LOCATION_MAX_AGE_MS = 10 * 60 * 1000 // 10 Minutes
    }
}


================================================
FILE: android-sdk-location/src/main/java/com/braze/location/GooglePlayLocationUtils.kt
================================================
package com.braze.location

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.Context
import android.content.SharedPreferences
import com.braze.managers.BrazeGeofenceManager
import com.braze.managers.IBrazeGeofenceLocationUpdateListener
import com.braze.models.BrazeGeofence
import com.braze.models.outgoing.BrazeLocation
import com.braze.support.BrazeLogger.Priority.E
import com.braze.support.BrazeLogger.Priority.V
import com.braze.support.BrazeLogger.Priority.W
import com.braze.support.BrazeLogger.brazelog
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.location.Geofence
import com.google.android.gms.location.GeofenceStatusCodes
import com.google.android.gms.location.GeofencingRequest
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority

@SuppressLint("MissingPermission")
object GooglePlayLocationUtils {
    private const val REGISTERED_GEOFENCE_SHARED_PREFS_LOCATION = "com.appboy.support.geofences"

    /**
     * Requests to register the given list of geofences with Google Play Location Services.
     *
     * If a given geofence is already registered with Google Play Location Services, it will not be
     * needlessly re-registered. Geofences that are registered with Google Play Location Services but
     * not included in the given list of geofences will be un-registered.
     *
     * If the given geofence list is empty, geofences will be un-registered and deleted from local
     * storage.
     * @param context used by shared preferences
     * @param geofenceList list of [BrazeGeofence] objects
     * @param geofenceRequestIntent pending intent to fire when geofences transition events occur
     */
    @JvmStatic
    fun registerGeofencesWithGooglePlayIfNecessary(
        context: Context,
        geofenceList: List<BrazeGeofence>,
        geofenceRequestIntent: PendingIntent
    ) {
        try {
            val prefs = getRegisteredGeofenceSharedPrefs(context)
            val registeredGeofences = BrazeGeofenceManager.retrieveBrazeGeofencesFromLocalStorage(prefs)

            val newGeofencesToRegister = geofenceList.filter { newGeofence ->
                registeredGeofences.none { registeredGeofence ->
                    registeredGeofence.id == newGeofence.id && registeredGeofence.equivalentServerData(newGeofence)
                }
            }
            val obsoleteGeofenceIds = registeredGeofences.filter { registeredGeofence ->
                newGeofencesToRegister.none { newGeofence ->
                    newGeofence.id == registeredGeofence.id
                }
            }.map { it.id }

            if (obsoleteGeofenceIds.isNotEmpty()) {
                brazelog { "Un-registering ${obsoleteGeofenceIds.size} obsolete geofences from Google Play Services." }
                removeGeofencesRegisteredWithGeofencingClient(context, obsoleteGeofenceIds)
            } else {
                brazelog { "No obsolete geofences need to be unregistered from Google Play Services." }
            }
            if (newGeofencesToRegister.isNotEmpty()) {
                brazelog { "Registering ${newGeofencesToRegister.size} new geofences with Google Play Services." }
                registerGeofencesWithGeofencingClient(context, newGeofencesToRegister, geofenceRequestIntent)
            } else {
                brazelog { "No new geofences need to be registered with Google Play Services." }
            }
        } catch (e: Exception) {
            brazelog(E, e) { "Exception while adding geofences." }
        }
    }

    /**
     * Requests a single location update from Google Play Location Services for the given pending intent.
     *
     * @param resultListener A callback of type [IBrazeGeofenceLocationUpdateListener]
     * which will be informed of the result of location update.
     */
    @JvmStatic
    fun requestSingleLocationUpdateFromGooglePlay(
        context: Context,
        resultListener: IBrazeGeofenceLocationUpdateListener
    ) {
        try {
            brazelog { "Requesting single location update from Google Play Services." }
            LocationServices.getFusedLocationProviderClient(context)
                .getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, null)
                .addOnSuccessListener {
                    brazelog(V) { "Single location request from Google Play services was successful." }
                    resultListener.onLocationRequestComplete(BrazeLocation(it))
                }
                .addOnFailureListener { error: Exception? ->
                    brazelog(E, error) { "Failed to get single location update from Google Play services." }
                    resultListener.onLocationRequestComplete(null)
                }
        } catch (e: Exception) {
            brazelog(W, e) { "Failed to request location update due to exception." }
        }
    }

    /**
     * Delete the cache of registered geofences. This will cause any geofences passed to
     * [.registerGeofencesWithGooglePlayIfNecessary]
     * on the next call to that method to be registered.
     */
    @JvmStatic
    fun deleteRegisteredGeofenceCache(context: Context) {
        brazelog { "Deleting registered geofence cache." }
        getRegisteredGeofenceSharedPrefs(context).edit().clear().apply()
    }

    /**
     * Registers a list of [Geofence] with a [com.google.android.gms.location.GeofencingClient].
     *
     * @param newGeofencesToRegister List of [BrazeGeofence]s to register
     * @param geofenceRequestIntent A pending intent to fire on completion of adding the [Geofence]s with
     * the [com.google.android.gms.location.GeofencingClient].
     */
    private fun registerGeofencesWithGeofencingClient(
        context: Context,
        newGeofencesToRegister: List<BrazeGeofence>,
        geofenceRequestIntent: PendingIntent
    ) {
        val newGooglePlayGeofencesToRegister = newGeofencesToRegister.map { it.toGeofence() }
        val geofencingRequest = GeofencingRequest.Builder()
            .addGeofences(newGooglePlayGeofencesToRegister) // no initial trigger
            .setInitialTrigger(0)
            .build()
        LocationServices.getGeofencingClient(context).addGeofences(geofencingRequest, geofenceRequestIntent)
            .addOnSuccessListener {
                brazelog { "Geofences successfully registered with Google Play Services." }
                storeGeofencesToSharedPrefs(context, newGeofencesToRegister)
            }
            .addOnFailureListener { geofenceError: Exception? ->
                if (geofenceError is ApiException) {
                    when (val statusCode = geofenceError.statusCode) {
                        GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES -> brazelog(W) {
                            "Geofences not registered with Google Play Services due to GEOFENCE_TOO_MANY_GEOFENCES: $statusCode"
                        }
                        GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS -> brazelog(W) {
                            "Geofences not registered with Google Play Services due to GEOFENCE_TOO_MANY_PENDING_INTENTS: $statusCode"
                        }
                        GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE -> brazelog(W) {
                            "Geofences not registered with Google Play Services due to GEOFENCE_NOT_AVAILABLE: $statusCode"
                        }
                        GeofenceStatusCodes.SUCCESS ->
                            // Since we're in the failure listener, we don't expect this status code to appear. Nonetheless, it would
                            // be good to not surface this status code as unknown
                            brazelog {
                                "Received Geofence registration success code in failure block with Google Play Services."
                            }
                        else -> brazelog(W) { "Geofence pending result returned unknown status code: $statusCode" }
                    }
                } else {
                    brazelog(E, geofenceError) { "Geofence exception encountered while adding geofences." }
                }
            }
    }

    /**
     * Un-registers a list of [Geofence] with a [com.google.android.gms.location.GeofencingClient].
     *
     * @param obsoleteGeofenceIds List of [String]s containing Geofence IDs that needs to be un-registered
     */
    private fun removeGeofencesRegisteredWithGeofencingClient(context: Context, obsoleteGeofenceIds: List<String>) {
        LocationServices.getGeofencingClient(context).removeGeofences(obsoleteGeofenceIds)
            .addOnSuccessListener {
                brazelog { "Geofences successfully un-registered with Google Play Services." }
                removeGeofencesFromSharedPrefs(context, obsoleteGeofenceIds)
            }
            .addOnFailureListener { geofenceError: Exception? ->
                if (geofenceError is ApiException) {
                    when (val statusCode = geofenceError.statusCode) {
                        GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES -> brazelog(W) {
                            "Geofences cannot be un-registered with Google Play Services due to GEOFENCE_TOO_MANY_GEOFENCES: $statusCode"
                        }
                        GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS -> brazelog(W) {
                            "Geofences cannot be un-registered with Google Play Services due to GEOFENCE_TOO_MANY_PENDING_INTENTS: $statusCode"
                        }
                        GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE -> brazelog(W) {
                            "Geofences cannot be un-registered with Google Play Services due to GEOFENCE_NOT_AVAILABLE: $statusCode"
                        }
                        GeofenceStatusCodes.SUCCESS ->
                            // Since we're in the failure listener, we don't expect this status code to appear. Nonetheless, it would
                            // be good to not surface this status code as unknown
                            brazelog {
                                "Received Geofence un-registration success code in failure block with Google Play Services."
                            }
                        else -> brazelog(W) { "Geofence pending result returned unknown status code: $statusCode" }
                    }
                } else {
                    brazelog(E, geofenceError) { "Geofence exception encountered while removing geofences." }
                }
            }
    }

    /**
     * Returns a [SharedPreferences] instance holding list of registered [BrazeGeofence]s.
     */
    private fun getRegisteredGeofenceSharedPrefs(context: Context): SharedPreferences =
        context.getSharedPreferences(REGISTERED_GEOFENCE_SHARED_PREFS_LOCATION, Context.MODE_PRIVATE)

    /**
     * Stores the list of [BrazeGeofence] which are successfully registered.
     *
     * @param newGeofencesToRegister List of [BrazeGeofence]s to store in SharedPreferences
     */
    private fun storeGeofencesToSharedPrefs(context: Context, newGeofencesToRegister: List<BrazeGeofence>) {
        val editor = getRegisteredGeofenceSharedPrefs(context).edit()
        for (brazeGeofence in newGeofencesToRegister) {
            editor.putString(brazeGeofence.id, brazeGeofence.forJsonPut().toString())
            brazelog(V) { "Geofence with id: ${brazeGeofence.id} added to shared preferences." }
        }
        editor.apply()
    }

    /**
     * Removes the list of [BrazeGeofence] which are now un-registered with Google Play Services.
     *
     * @param obsoleteGeofenceIds List of [String]s containing Geofence IDs that are un-registered
     */
    private fun removeGeofencesFromSharedPrefs(context: Context, obsoleteGeofenceIds: List<String>) {
        val editor = getRegisteredGeofenceSharedPrefs(context).edit()
        for (id in obsoleteGeofenceIds) {
            editor.remove(id)
            brazelog(V) { "Geofence with id: $id removed from shared preferences." }
        }
        editor.apply()
    }
}

/**
 * Creates a Google Play Location Services Geofence object from a BrazeGeofence.
 * @return A Geofence object.
 */
fun BrazeGeofence.toGeofence(): Geofence {
    val builder = Geofence.Builder()
    builder
        .setRequestId(id)
        .setCircularRegion(latitude, longitude, radiusMeter.toFloat())
        .setNotificationResponsiveness(notificationResponsivenessMs)
        .setExpirationDuration(Geofence.NEVER_EXPIRE)
    var transitionTypes = 0
    if (enterEvents) {
        transitionTypes = transitionTypes or Geofence.GEOFENCE_TRANSITION_ENTER
    }
    if (exitEvents) {
        transitionTypes = transitionTypes or Geofence.GEOFENCE_TRANSITION_EXIT
    }
    builder.setTransitionTypes(transitionTypes)
    return builder.build()
}


================================================
FILE: android-sdk-ui/braze-consumer-proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in android-sdk/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html
#
# See https://github.com/Appboy/appboy-android-sdk/issues/49
-keepnames class com.braze.ui.** { *; }
-keepnames class com.braze.** { *; }
-keepnames class bo.app.** { *; }

-dontwarn com.braze.ui.**
-dontwarn com.google.firebase.messaging.**

-keepclassmembers class * {
   @android.webkit.JavascriptInterface <methods>;
}


================================================
FILE: android-sdk-ui/build.gradle
================================================
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

dependencies {
  api "com.appboy:android-sdk-base:${BRAZE_SDK_VERSION}"
  compileOnly "com.google.android.material:material:${GOOGLE_MATERIAL_VERSION}"

  implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${KOTLIN_COROUTINES_VERSION}"
  implementation "androidx.core:core:${ANDROIDX_CORE_VERSION}"
  implementation "androidx.fragment:fragment:${ANDROIDX_FRAGMENT_VERSION}"
  implementation "androidx.recyclerview:recyclerview:${ANDROIDX_RECYCLERVIEW_VERSION}"
  implementation "androidx.swiperefreshlayout:swiperefreshlayout:${ANDROIDX_SWIPE_REFRESH_LAYOUT_VERSION}"
  implementation "androidx.webkit:webkit:${ANDROIDX_WEBKIT_VERSION}"

  // Required for the FirebaseMessagingService
  compileOnly "com.google.firebase:firebase-messaging:${FIREBASE_PUSH_MESSAGING_VERSION}"
}

android {
  compileSdkVersion rootProject.ext.compileSdkVersion
  buildToolsVersion rootProject.ext.buildToolsVersion

  defaultConfig {
    minSdkVersion rootProject.ext.minSdkVersion
    targetSdkVersion rootProject.ext.targetSdkVersion
    consumerProguardFiles 'braze-consumer-proguard-rules.pro'
  }

  kotlinOptions {
    freeCompilerArgs = ['-Xjvm-default=all']
    jvmTarget = "1.8"
  }

  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}


================================================
FILE: android-sdk-ui/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.braze.ui">
  <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
  <application>
    <activity
      android:name="com.braze.ui.BrazeWebViewActivity"
      android:exported="false" />
    <activity
      android:name=".activities.BrazeFeedActivity"
      android:exported="false" />
    <activity
      android:name="com.braze.ui.activities.ContentCardsActivity"
      android:exported="false" />
    <activity
      android:name="com.braze.push.NotificationTrampolineActivity"
      android:launchMode="singleInstance"
      android:exported="false"
      android:theme="@style/Braze.PushTrampoline.Transparent" />
    <receiver
      android:name="com.braze.push.BrazePushReceiver"
      android:exported="false" />
  </application>
</manifest>


================================================
FILE: android-sdk-ui/src/main/assets/braze-html-in-app-message-bridge.js
================================================
var brazeBridge = {
  logCustomEvent: function (name, properties) { brazeInternalBridge.logCustomEventWithJSON(name, JSON.stringify(properties)); },
  logPurchase: function (productId, price, currencyCode, quantity, purchaseProperties) {
    brazeInternalBridge.logPurchaseWithJSON(productId, price, currencyCode, quantity != null ? quantity : 1, JSON.stringify(purchaseProperties));
  },
  closeMessage: function () { window.location = 'appboy://close'; },
  requestImmediateDataFlush: function () { brazeInternalBridge.requestImmediateDataFlush(); },
  display: { showFeed: function () { window.open('appboy://feed'); } },
  logClick: function(buttonId) {
    if (buttonId != null) {
      brazeInternalBridge.logButtonClick(buttonId);
    } else {
      brazeInternalBridge.logClick();
    }
  },
  requestPushPermission: function () { brazeInternalBridge.requestPushPermission() },
  brazeBridgeUserObject: {
    setFirstName: function(firstName) { brazeInternalBridge.getUser().setFirstName(firstName); },
    setLastName: function(lastName) { brazeInternalBridge.getUser().setLastName(lastName); },
    setEmail: function(email) { brazeInternalBridge.getUser().setEmail(email); },
    setGender: function(gender) { brazeInternalBridge.getUser().setGender(gender); },
    setHomeCity: function(homeCity) { brazeInternalBridge.getUser().setHomeCity(homeCity); },
    setEmailNotificationSubscriptionType: function(subscriptionType) {
      brazeInternalBridge.getUser().setEmailNotificationSubscriptionType(subscriptionType);
    },
    setPushNotificationSubscriptionType: function(subscriptionType) {
      brazeInternalBridge.getUser().setPushNotificationSubscriptionType(subscriptionType);
    },
    addToCustomAttributeArray: function(key, value) { brazeInternalBridge.getUser().addToCustomAttributeArray(key, value); },
    removeFromCustomAttributeArray: function(key, value) { brazeInternalBridge.getUser().removeFromCustomAttributeArray(key, value); },
    incrementCustomUserAttribute: function(key) { brazeInternalBridge.getUser().incrementCustomUserAttribute(key); },
    setDateOfBirth: function(year, month, day) { brazeInternalBridge.getUser().setDateOfBirth(year, month, day); },
    setCountry: function(country) { brazeInternalBridge.getUser().setCountry(country); },
    setPhoneNumber: function(phone) { brazeInternalBridge.getUser().setPhoneNumber(phone); },
    setCustomUserAttribute: function(key, value) {
      var isArray = function(value) {
          if (Array.isArray) {
            return Array.isArray(value);
          }
          return Object.prototype.toString.call(value) === '[object Array]';
      };
      if (isArray(value)) {
        brazeInternalBridge.getUser().setCustomUserAttributeArray(key, JSON.stringify(value));
      } else {
        brazeInternalBridge.getUser().setCustomUserAttributeJSON(key, JSON.stringify({"value":value}));
      }
    },
    setLocationCustomUserAttribute: function(key, latitude, longitude) {
      console.log("setLocationCustomUserAttribute() is deprecated and only support on Android. Please use setCustomLocationAttribute() instead.");
      brazeInternalBridge.getUser().setCustomLocationAttribute(key, latitude, longitude);
    },
    setCustomLocationAttribute: function(key, latitude, longitude) { brazeInternalBridge.getUser().setCustomLocationAttribute(key, latitude, longitude); },
    setLanguage: function(language) { brazeInternalBridge.getUser().setLanguage(language); },
    addAlias: function(alias, label) { brazeInternalBridge.getUser().addAlias(alias, label); },
    addToSubscriptionGroup: function(subscriptionGroupId) { brazeInternalBridge.getUser().addToSubscriptionGroup(subscriptionGroupId); },
    removeFromSubscriptionGroup: function(subscriptionGroupId) { brazeInternalBridge.getUser().removeFromSubscriptionGroup(subscriptionGroupId); }
  },
  getUser: function() {
    return this.brazeBridgeUserObject;
  },
  changeUser: function(userId, sdkAuth = null) {
      brazeInternalBridge.changeUser(userId, sdkAuth);
  },
  web: {
    registerAppboyPushMessages: function(successCallback, deniedCallback) { console.log("This method is a no-op on Android."); },
    trackLocation: function() { console.log("This method is a no-op on Android."); },
  }
};
var appboyBridge = brazeBridge;
window.dispatchEvent(new Event("ab.BridgeReady"));


================================================
FILE: android-sdk-ui/src/main/java/com/braze/BrazeActivityLifecycleCallbackListener.kt
================================================
package com.braze

import android.app.Activity
import android.app.Application
import android.app.Application.ActivityLifecycleCallbacks
import android.content.Context
import android.os.Bundle
import androidx.annotation.VisibleForTesting
import com.braze.push.NotificationTrampolineActivity
import com.braze.support.BrazeLogger.Priority.E
import com.braze.support.BrazeLogger.Priority.V
import com.braze.support.BrazeLogger.brazelog
import com.braze.ui.inappmessage.BrazeInAppMessageManager

/**
 * Can be used to automatically handle Braze lifecycle methods.
 * Optionally, openSession() and closeSession() are called on onActivityStarted and onActivityStopped respectively.
 * The InAppMessageManager methods of registerInAppMessageManager() and unregisterInAppMessageManager() can be optionally
 * called here as well.
 * Note: This callback should not be set in any Activity. It must be set in the Application class of your app.
 *
 * @param sessionHandlingEnabled              When true, handles calling openSession and closeSession in onActivityStarted
 * and onActivityStopped respectively.
 * @param registerInAppMessageManager         When true, registers and unregisters the [BrazeInAppMessageManager] in
 * [Application.ActivityLifecycleCallbacks.onActivityResumed] and [Application.ActivityLifecycleCallbacks.onActivityPaused]
 * respectively.
 * @param inAppMessagingRegistrationBlocklist A set of [Activity]s for which in-app message registration will not occur.
 * Each class should be retrieved via [Activity.getClass]. If null, an empty set is used instead.
 * @param sessionHandlingBlocklist            A set of [Activity]s for which session handling
 * will not occur. Each class should be retrieved via [Activity.getClass].
 * If null, an empty set is used instead.
 */
@Suppress("TooManyFunctions")
open class BrazeActivityLifecycleCallbackListener @JvmOverloads constructor(
    private val sessionHandlingEnabled: Boolean = true,
    private val registerInAppMessageManager: Boolean = true,
    inAppMessagingRegistrationBlocklist: Set<Class<*>?>? = emptySet<Class<*>>(),
    sessionHandlingBlocklist: Set<Class<*>?>? = emptySet<Class<*>>()
) : ActivityLifecycleCallbacks {
    private var inAppMessagingRegistrationBlocklist: Set<Class<*>?>
    private var sessionHandlingBlocklist: Set<Class<*>?>

    init {
        this.inAppMessagingRegistrationBlocklist = inAppMessagingRegistrationBlocklist
            ?: emptySet<Class<*>>()
        this.sessionHandlingBlocklist = sessionHandlingBlocklist ?: emptySet<Class<*>>()
        brazelog(V) {
            "BrazeActivityLifecycleCallbackListener using in-app messaging blocklist: ${this.inAppMessagingRegistrationBlocklist}"
        }
        brazelog(V) {
            "BrazeActivityLifecycleCallbackListener using session handling blocklist: ${this.sessionHandlingBlocklist}"
        }
    }

    /**
     * Constructor that sets a blocklist for session handling and [BrazeInAppMessageManager] registration while also
     * enabling both features.
     *
     * @param inAppMessagingRegistrationBlocklist A set of [Activity]s for which in-app message registration will not
     * occur. Each class should be retrieved via [Activity.getClass].
     * @param sessionHandlingBlocklist            A set of [Activity]s for which session handling will not occur. Each
     * class should be retrieved via [Activity.getClass].
     */
    @JvmOverloads
    constructor(
        inAppMessagingRegistrationBlocklist: Set<Class<*>?>?,
        sessionHandlingBlocklist: Set<Class<*>?>? = emptySet<Class<*>>()
    ) : this(true, true, inAppMessagingRegistrationBlocklist, sessionHandlingBlocklist)

    /**
     * Sets the [Activity.getClass] blocklist for which in-app message registration will not occur.
     */
    fun setInAppMessagingRegistrationBlocklist(blocklist: Set<Class<*>?>) {
        brazelog(V) { "setInAppMessagingRegistrationBlocklist called with blocklist: $blocklist" }
        inAppMessagingRegistrationBlocklist = blocklist
    }

    /**
     * Sets the [Activity.getClass] blocklist for which session handling will not occur.
     */
    fun setSessionHandlingBlocklist(blocklist: Set<Class<*>?>) {
        brazelog(V) { "setSessionHandlingBlocklist called with blocklist: $blocklist" }
        sessionHandlingBlocklist = blocklist
    }

    override fun onActivityStarted(activity: Activity) {
        if (sessionHandlingEnabled && shouldHandleLifecycleMethodsInActivity(activity, true)) {
            brazelog(V) {
                "Automatically calling lifecycle method: openSession for class: ${activity.javaClass}"
            }
            Braze.getInstance(activity.applicationContext).openSession(activity)
        }
    }

    override fun onActivityStopped(activity: Activity) {
        if (sessionHandlingEnabled && shouldHandleLifecycleMethodsInActivity(activity, true)) {
            brazelog(V) {
                "Automatically calling lifecycle method: closeSession for class: ${activity.javaClass}"
            }
            Braze.getInstance(activity.applicationContext).closeSession(activity)
        }
    }

    override fun onActivityResumed(activity: Activity) {
        if (registerInAppMessageManager &&
            shouldHandleLifecycleMethodsInActivity(activity, false)
        ) {
            brazelog(V) {
                "Automatically calling lifecycle method: registerInAppMessageManager for class: ${activity.javaClass}"
            }
            BrazeInAppMessageManager.getInstance().registerInAppMessageManager(activity)
        }
    }

    override fun onActivityPaused(activity: Activity) {
        if (registerInAppMessageManager &&
            shouldHandleLifecycleMethodsInActivity(activity, false)
        ) {
            brazelog(V) {
                "Automatically calling lifecycle method: unregisterInAppMessageManager for class: ${activity.javaClass}"
            }
            BrazeInAppMessageManager.getInstance().unregisterInAppMessageManager(activity)
        }
    }

    override fun onActivityCreated(activity: Activity, bundle: Bundle?) {
        if (registerInAppMessageManager &&
            shouldHandleLifecycleMethodsInActivity(activity, false)
        ) {
            brazelog(V) {
                "Automatically calling lifecycle method: ensureSubscribedToInAppMessageEvents for class: ${activity.javaClass}"
            }
            BrazeInAppMessageManager.getInstance()
                .ensureSubscribedToInAppMessageEvents(activity.applicationContext)
        }
    }

    override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {}
    override fun onActivityDestroyed(activity: Activity) {}

    /**
     * Determines if this [Activity] should be ignored for the purposes of session tracking or in-app message registration.
     */
    @VisibleForTesting
    fun shouldHandleLifecycleMethodsInActivity(
        activity: Activity,
        forSessionHandling: Boolean
    ): Boolean {
        val activityClass: Class<out Activity> = activity.javaClass
       
Download .txt
gitextract_xod5pvye/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug.yml
│   │   ├── config.yml
│   │   └── feature.yml
│   └── ISSUE_TEMPLATE.md
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── android-sdk-location/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── braze/
│                       └── location/
│                           ├── BrazeActionReceiver.kt
│                           ├── BrazeInternalGeofenceApi.kt
│                           ├── BrazeInternalLocationApi.kt
│                           └── GooglePlayLocationUtils.kt
├── android-sdk-ui/
│   ├── braze-consumer-proguard-rules.pro
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── assets/
│           │   └── braze-html-in-app-message-bridge.js
│           ├── java/
│           │   └── com/
│           │       └── braze/
│           │           ├── BrazeActivityLifecycleCallbackListener.kt
│           │           ├── IBrazeDeeplinkHandler.kt
│           │           ├── push/
│           │           │   ├── BrazeAmazonDeviceMessagingReceiver.kt
│           │           │   ├── BrazeFirebaseMessagingService.kt
│           │           │   ├── BrazeHuaweiPushHandler.kt
│           │           │   ├── BrazeNotificationActionUtils.kt
│           │           │   ├── BrazeNotificationFactory.kt
│           │           │   ├── BrazeNotificationStyleFactory.kt
│           │           │   ├── BrazeNotificationUtils.kt
│           │           │   ├── BrazePushReceiver.kt
│           │           │   ├── NotificationTrampolineActivity.kt
│           │           │   └── support/
│           │           │       └── HtmlUtils.kt
│           │           └── ui/
│           │               ├── BrazeDeeplinkHandler.kt
│           │               ├── BrazeFeedFragment.java
│           │               ├── BrazeWebViewActivity.kt
│           │               ├── BrazeXamarinFormsFeedFragment.java
│           │               ├── actions/
│           │               │   ├── IAction.kt
│           │               │   ├── NewsfeedAction.kt
│           │               │   ├── UriAction.kt
│           │               │   └── brazeactions/
│           │               │       ├── BrazeActionParser.kt
│           │               │       ├── BrazeActionUtils.kt
│           │               │       └── steps/
│           │               │           ├── AddToCustomAttributeArrayStep.kt
│           │               │           ├── AddToSubscriptionGroupStep.kt
│           │               │           ├── BaseBrazeActionStep.kt
│           │               │           ├── ContainerStep.kt
│           │               │           ├── IBrazeActionStep.kt
│           │               │           ├── LogCustomEventStep.kt
│           │               │           ├── NoOpStep.kt
│           │               │           ├── OpenLinkExternallyStep.kt
│           │               │           ├── OpenLinkInWebViewStep.kt
│           │               │           ├── RemoveFromCustomAttributeArrayStep.kt
│           │               │           ├── RemoveFromSubscriptionGroupStep.kt
│           │               │           ├── RequestPushPermissionStep.kt
│           │               │           ├── SetCustomUserAttributeStep.kt
│           │               │           ├── SetEmailSubscriptionStep.kt
│           │               │           ├── SetPushNotificationSubscriptionStep.kt
│           │               │           └── StepData.kt
│           │               ├── activities/
│           │               │   ├── BrazeBaseFragmentActivity.kt
│           │               │   ├── BrazeFeedActivity.java
│           │               │   └── ContentCardsActivity.kt
│           │               ├── adapters/
│           │               │   └── BrazeListAdapter.java
│           │               ├── contentcards/
│           │               │   ├── ContentCardsFragment.kt
│           │               │   ├── adapters/
│           │               │   │   ├── ContentCardAdapter.kt
│           │               │   │   └── EmptyContentCardsAdapter.kt
│           │               │   ├── handlers/
│           │               │   │   ├── DefaultContentCardsUpdateHandler.kt
│           │               │   │   ├── DefaultContentCardsViewBindingHandler.kt
│           │               │   │   ├── IContentCardsUpdateHandler.kt
│           │               │   │   └── IContentCardsViewBindingHandler.kt
│           │               │   ├── listeners/
│           │               │   │   ├── DefaultContentCardsActionListener.kt
│           │               │   │   └── IContentCardsActionListener.kt
│           │               │   ├── managers/
│           │               │   │   └── BrazeContentCardsManager.kt
│           │               │   ├── recycler/
│           │               │   │   ├── ContentCardsDividerItemDecoration.kt
│           │               │   │   ├── ItemTouchHelperAdapter.kt
│           │               │   │   └── SimpleItemTouchHelperCallback.kt
│           │               │   └── view/
│           │               │       ├── BannerImageContentCardView.kt
│           │               │       ├── BaseContentCardView.kt
│           │               │       ├── CaptionedImageContentCardView.kt
│           │               │       ├── ContentCardViewHolder.kt
│           │               │       ├── DefaultContentCardView.kt
│           │               │       ├── ShortNewsContentCardView.kt
│           │               │       └── TextAnnouncementContentCardView.kt
│           │               ├── feed/
│           │               │   ├── BrazeFeedManager.java
│           │               │   ├── BrazeImageSwitcher.kt
│           │               │   ├── listeners/
│           │               │   │   ├── BrazeDefaultFeedClickActionListener.java
│           │               │   │   └── IFeedClickActionListener.java
│           │               │   └── view/
│           │               │       └── BaseFeedCardView.java
│           │               ├── inappmessage/
│           │               │   ├── BrazeInAppMessageManager.kt
│           │               │   ├── DefaultInAppMessageViewWrapper.kt
│           │               │   ├── IInAppMessageAnimationFactory.kt
│           │               │   ├── IInAppMessageViewFactory.kt
│           │               │   ├── IInAppMessageViewWrapper.kt
│           │               │   ├── IInAppMessageViewWrapperFactory.kt
│           │               │   ├── InAppMessageCloser.java
│           │               │   ├── InAppMessageManagerBase.kt
│           │               │   ├── InAppMessageOperation.kt
│           │               │   ├── config/
│           │               │   │   └── BrazeInAppMessageParams.kt
│           │               │   ├── factories/
│           │               │   │   ├── DefaultInAppMessageAnimationFactory.kt
│           │               │   │   ├── DefaultInAppMessageFullViewFactory.kt
│           │               │   │   ├── DefaultInAppMessageHtmlFullViewFactory.kt
│           │               │   │   ├── DefaultInAppMessageHtmlViewFactory.kt
│           │               │   │   ├── DefaultInAppMessageModalViewFactory.kt
│           │               │   │   ├── DefaultInAppMessageSlideupViewFactory.kt
│           │               │   │   └── DefaultInAppMessageViewWrapperFactory.kt
│           │               │   ├── jsinterface/
│           │               │   │   ├── InAppMessageJavascriptInterface.kt
│           │               │   │   └── InAppMessageUserJavascriptInterface.kt
│           │               │   ├── listeners/
│           │               │   │   ├── DefaultHtmlInAppMessageActionListener.kt
│           │               │   │   ├── DefaultInAppMessageManagerListener.kt
│           │               │   │   ├── DefaultInAppMessageViewLifecycleListener.kt
│           │               │   │   ├── DefaultInAppMessageWebViewClientListener.kt
│           │               │   │   ├── IHtmlInAppMessageActionListener.kt
│           │               │   │   ├── IInAppMessageManagerListener.kt
│           │               │   │   ├── IInAppMessageViewLifecycleListener.kt
│           │               │   │   ├── IInAppMessageWebViewClientListener.kt
│           │               │   │   ├── IWebViewClientStateListener.kt
│           │               │   │   ├── SwipeDismissTouchListener.java
│           │               │   │   └── TouchAwareSwipeDismissTouchListener.kt
│           │               │   ├── utils/
│           │               │   │   ├── BackgroundInAppMessagePreparer.kt
│           │               │   │   ├── InAppMessageButtonViewUtils.kt
│           │               │   │   ├── InAppMessageViewUtils.kt
│           │               │   │   └── InAppMessageWebViewClient.kt
│           │               │   └── views/
│           │               │       ├── IInAppMessageImageView.kt
│           │               │       ├── IInAppMessageImmersiveView.kt
│           │               │       ├── IInAppMessageView.kt
│           │               │       ├── InAppMessageBaseView.kt
│           │               │       ├── InAppMessageBoundedLayout.kt
│           │               │       ├── InAppMessageButton.kt
│           │               │       ├── InAppMessageFullView.kt
│           │               │       ├── InAppMessageHtmlBaseView.kt
│           │               │       ├── InAppMessageHtmlFullView.kt
│           │               │       ├── InAppMessageHtmlView.kt
│           │               │       ├── InAppMessageImageView.kt
│           │               │       ├── InAppMessageImmersiveBaseView.kt
│           │               │       ├── InAppMessageModalView.kt
│           │               │       ├── InAppMessageSlideupView.kt
│           │               │       └── InAppMessageWebView.kt
│           │               ├── support/
│           │               │   ├── AnimationUtils.kt
│           │               │   ├── UriUtils.kt
│           │               │   └── ViewUtils.kt
│           │               └── widget/
│           │                   ├── BannerImageCardView.java
│           │                   ├── BaseCardView.kt
│           │                   ├── CaptionedImageCardView.java
│           │                   ├── DefaultCardView.java
│           │                   ├── ShortNewsCardView.java
│           │                   └── TextAnnouncementCardView.java
│           └── res/
│               ├── drawable/
│               │   └── com_braze_inappmessage_close_button_selector.xml
│               ├── drawable-nodpi/
│               │   ├── com_braze_card_background.xml
│               │   ├── com_braze_content_card_background.xml
│               │   ├── com_braze_content_card_scrim.xml
│               │   ├── com_braze_content_card_scrim_focused.xml
│               │   ├── com_braze_content_cards_rounded_corner_background.xml
│               │   ├── com_braze_content_cards_unread_bar_background.xml
│               │   ├── com_braze_inappmessage_button_background.xml
│               │   ├── com_braze_inappmessage_icon_background.xml
│               │   ├── com_braze_inappmessage_modal_background.xml
│               │   └── com_braze_inappmessage_slideup_background.xml
│               ├── drawable-nodpi-v21/
│               │   └── com_braze_inappmessage_button_background.xml
│               ├── layout/
│               │   ├── com_braze_banner_image_card.xml
│               │   ├── com_braze_banner_image_content_card.xml
│               │   ├── com_braze_captioned_image_card.xml
│               │   ├── com_braze_captioned_image_content_card.xml
│               │   ├── com_braze_content_cards.xml
│               │   ├── com_braze_content_cards_activity.xml
│               │   ├── com_braze_content_cards_empty.xml
│               │   ├── com_braze_default_card.xml
│               │   ├── com_braze_default_content_card.xml
│               │   ├── com_braze_feed.xml
│               │   ├── com_braze_feed_activity.xml
│               │   ├── com_braze_feed_footer.xml
│               │   ├── com_braze_feed_header.xml
│               │   ├── com_braze_feed_read_indicator_holder.xml
│               │   ├── com_braze_inappmessage_full.xml
│               │   ├── com_braze_inappmessage_full_graphic.xml
│               │   ├── com_braze_inappmessage_html.xml
│               │   ├── com_braze_inappmessage_html_full.xml
│               │   ├── com_braze_inappmessage_modal.xml
│               │   ├── com_braze_inappmessage_modal_graphic.xml
│               │   ├── com_braze_inappmessage_slideup.xml
│               │   ├── com_braze_notification_inline_image.xml
│               │   ├── com_braze_push_inline_image_constrained.xml
│               │   ├── com_braze_push_story_one_image.xml
│               │   ├── com_braze_short_news_card.xml
│               │   ├── com_braze_short_news_content_card.xml
│               │   ├── com_braze_stubbed_feed_image_view.xml
│               │   ├── com_braze_text_announcement_card.xml
│               │   ├── com_braze_text_announcement_content_card.xml
│               │   └── com_braze_webview_activity.xml
│               ├── layout-land/
│               │   └── com_braze_inappmessage_html_full.xml
│               ├── values/
│               │   ├── attrs.xml
│               │   ├── colors.xml
│               │   ├── dimens.xml
│               │   ├── ids.xml
│               │   ├── strings.xml
│               │   └── styles.xml
│               ├── values-ar/
│               │   └── strings.xml
│               ├── values-cs/
│               │   └── strings.xml
│               ├── values-da/
│               │   └── strings.xml
│               ├── values-de/
│               │   └── strings.xml
│               ├── values-es/
│               │   └── strings.xml
│               ├── values-es-rES/
│               │   └── strings.xml
│               ├── values-et/
│               │   └── strings.xml
│               ├── values-fi/
│               │   └── strings.xml
│               ├── values-fr/
│               │   └── strings.xml
│               ├── values-hdpi/
│               │   └── dimens.xml
│               ├── values-hi/
│               │   └── strings.xml
│               ├── values-in/
│               │   └── strings.xml
│               ├── values-it/
│               │   └── strings.xml
│               ├── values-iw/
│               │   └── strings.xml
│               ├── values-ja/
│               │   └── strings.xml
│               ├── values-km/
│               │   └── strings.xml
│               ├── values-ko/
│               │   └── strings.xml
│               ├── values-lo/
│               │   └── strings.xml
│               ├── values-mdpi/
│               │   └── dimens.xml
│               ├── values-ms/
│               │   └── strings.xml
│               ├── values-my/
│               │   └── strings.xml
│               ├── values-nb/
│               │   └── strings.xml
│               ├── values-night/
│               │   ├── colors.xml
│               │   ├── dimens.xml
│               │   └── styles.xml
│               ├── values-nl/
│               │   └── strings.xml
│               ├── values-pl/
│               │   └── strings.xml
│               ├── values-pt/
│               │   └── strings.xml
│               ├── values-pt-rPT/
│               │   └── strings.xml
│               ├── values-ru/
│               │   └── strings.xml
│               ├── values-sv/
│               │   └── strings.xml
│               ├── values-sw600dp/
│               │   ├── dimens.xml
│               │   └── styles.xml
│               ├── values-th/
│               │   └── strings.xml
│               ├── values-tl/
│               │   └── strings.xml
│               ├── values-uk/
│               │   └── strings.xml
│               ├── values-v21/
│               │   └── styles.xml
│               ├── values-vi/
│               │   └── strings.xml
│               ├── values-xhdpi/
│               │   └── dimens.xml
│               ├── values-zh-rCN/
│               │   └── strings.xml
│               ├── values-zh-rHK/
│               │   └── strings.xml
│               ├── values-zh-rSG/
│               │   └── strings.xml
│               └── values-zh-rTW/
│                   └── strings.xml
├── android-sdk-unity/
│   ├── build.gradle
│   ├── libs/
│   │   ├── Prime31UnityActivity-1.0.jar
│   │   └── unity-2019.2.12f1.jar
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── braze/
│                       └── unity/
│                           ├── BrazeUnityActivityWrapper.kt
│                           ├── BrazeUnityPlayerActivity.kt
│                           ├── EventSubscriberFactory.kt
│                           ├── configuration/
│                           │   └── UnityConfigurationProvider.kt
│                           ├── enums/
│                           │   ├── UnityInAppMessageManagerAction.kt
│                           │   └── UnityMessageType.kt
│                           ├── prime31compatible/
│                           │   └── BrazeUnityPlayerActivity.kt
│                           └── utils/
│                               ├── InAppMessageUtils.kt
│                               └── MessagingUtils.kt
├── build.gradle
├── config/
│   ├── buildscript/
│   │   └── break-compile-on-deprecations.gradle
│   └── quality/
│       └── break-compile-on-deprecations.gradle
├── droidboy/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── assets/
│           │   ├── braze_actions/
│           │   │   └── show_push_prompt.txt
│           │   ├── html_in_app_message_bridge_tester.html
│           │   ├── html_in_app_message_unified_bootstrap_album.html
│           │   ├── html_inapp_message_body_external_js.html
│           │   ├── html_inapp_message_body_inline_js.html
│           │   ├── html_inapp_message_body_no_js.html
│           │   ├── html_inapp_message_body_star_wars.html
│           │   ├── html_inapp_message_body_youtube_iframe.html
│           │   ├── html_inapp_message_dark_mode.html
│           │   ├── html_inapp_message_delayed_open.html
│           │   ├── html_shark_unified.html
│           │   └── modal_inapp_message_with_dark_theme.json
│           ├── java/
│           │   └── com/
│           │       └── appboy/
│           │           └── sample/
│           │               ├── CustomBrazeDeeplinkHandler.java
│           │               ├── CustomFeedClickActionListener.java
│           │               ├── CustomHtmlInAppMessageActionListener.java
│           │               ├── CustomInAppMessage.java
│           │               ├── CustomInAppMessageAnimationFactory.java
│           │               ├── CustomInAppMessageManagerListener.java
│           │               ├── CustomInAppMessageView.java
│           │               ├── CustomInAppMessageViewFactory.java
│           │               ├── DroidboyApplication.kt
│           │               ├── DroidboyEndpointProvider.java
│           │               ├── DroidboyNotificationFactory.java
│           │               ├── FeedCategoriesFragment.java
│           │               ├── FullyCustomNotificationFactory.kt
│           │               ├── InAppMessageTesterFragment.kt
│           │               ├── MainFragment.kt
│           │               ├── PushTesterFragment.java
│           │               ├── SetEnvironmentPreference.java
│           │               ├── UserProfileDialog.java
│           │               ├── activity/
│           │               │   ├── DroidBoyActivity.kt
│           │               │   ├── FeedFragmentActivity.java
│           │               │   ├── GeofencesMapActivity.java
│           │               │   ├── InAppMessageSandboxActivity.kt
│           │               │   ├── SettingsActivity.kt
│           │               │   └── settings/
│           │               │       └── SettingsFragment.kt
│           │               ├── dialog/
│           │               │   └── CustomDialogBase.kt
│           │               ├── featureflag/
│           │               │   ├── controller/
│           │               │   │   └── FeatureFlagAdapter.kt
│           │               │   └── view/
│           │               │       └── FeatureFlagFragment.kt
│           │               ├── imageloading/
│           │               │   └── GlideImageLoader.kt
│           │               ├── logging/
│           │               │   ├── CustomEventDialog.java
│           │               │   ├── CustomLogger.java
│           │               │   ├── CustomPurchaseDialog.java
│           │               │   ├── CustomUserAttributeDialog.java
│           │               │   └── PropertyManager.java
│           │               ├── subscriptions/
│           │               │   ├── EmailSubscriptionStateDialog.java
│           │               │   ├── PushSubscriptionStateDialog.java
│           │               │   └── SubscriptionStateDialogBase.java
│           │               └── util/
│           │                   ├── BrazeActionTestingUtil.kt
│           │                   ├── ButtonUtils.java
│           │                   ├── ContentCardsTestingUtil.kt
│           │                   ├── EmulatorDetectionUtils.java
│           │                   ├── EnvironmentUtils.kt
│           │                   ├── LifecycleUtils.java
│           │                   ├── LogcatExportUtil.kt
│           │                   ├── RuntimePermissionUtils.kt
│           │                   ├── SpinnerUtils.java
│           │                   └── ViewUtils.java
│           └── res/
│               ├── drawable/
│               │   └── custom_inappmessage_background.xml
│               ├── font/
│               │   ├── bungee_font_family.xml
│               │   ├── sailec_font_family.xml
│               │   └── sailec_regular.otf
│               ├── layout/
│               │   ├── activity_in_app_message_sandbox.xml
│               │   ├── custom_attribute.xml
│               │   ├── custom_event.xml
│               │   ├── custom_inappmessage.xml
│               │   ├── custom_name.xml
│               │   ├── custom_properties.xml
│               │   ├── custom_purchase.xml
│               │   ├── data_dialog.xml
│               │   ├── dialog_footer_navigation.xml
│               │   ├── drawer_header.xml
│               │   ├── feature_flag_fragment.xml
│               │   ├── feature_flag_overview_item.xml
│               │   ├── geofences_map.xml
│               │   ├── inappmessage_tester.xml
│               │   ├── landing_page.xml
│               │   ├── log_level_dialog.xml
│               │   ├── main_fragment.xml
│               │   ├── preference_wrapper_view.xml
│               │   ├── property_list_item.xml
│               │   ├── push_tester.xml
│               │   ├── set_environment_preference.xml
│               │   ├── settings_page.xml
│               │   ├── spinner_dropdown_item.xml
│               │   ├── spinner_item.xml
│               │   ├── subscription_state_preferences.xml
│               │   └── user_preferences.xml
│               ├── menu/
│               │   └── actionbar_options.xml
│               ├── values/
│               │   ├── braze.xml
│               │   ├── colors.xml
│               │   ├── dimens.xml
│               │   ├── inapp_align_options.xml
│               │   ├── inapp_boolean_options.xml
│               │   ├── inapp_button_options.xml
│               │   ├── inapp_click_action_options.xml
│               │   ├── inapp_color_options.xml
│               │   ├── inapp_dismiss_type_options.xml
│               │   ├── inapp_frame_options.xml
│               │   ├── inapp_header_options.xml
│               │   ├── inapp_icon_options.xml
│               │   ├── inapp_image_options.xml
│               │   ├── inapp_message_options.xml
│               │   ├── inapp_message_type_options.xml
│               │   ├── inapp_orientation_options.xml
│               │   ├── inapp_slide_from_options.xml
│               │   ├── inapp_uri_options.xml
│               │   ├── push_accent_color_options.xml
│               │   ├── push_action_options.xml
│               │   ├── push_category_options.xml
│               │   ├── push_channel_options.xml
│               │   ├── push_click_action_options.xml
│               │   ├── push_image_number_spinner.xml
│               │   ├── push_image_options.xml
│               │   ├── push_large_icon_options.xml
│               │   ├── push_notification_factory_options.xml
│               │   ├── push_priority_options.xml
│               │   ├── push_story_subtitle_align_options.xml
│               │   ├── push_story_title_align_options.xml
│               │   ├── push_visibility_options.xml
│               │   ├── strings.xml
│               │   └── styles.xml
│               ├── values-sw600dp/
│               │   └── styles.xml
│               ├── values-v28/
│               │   └── styles.xml
│               ├── values-xlarge/
│               │   └── styles.xml
│               └── xml/
│                   ├── preferences.xml
│                   └── provider_filepaths.xml
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── samples/
│   ├── README.md
│   ├── custom-broadcast/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── custombroadcast/
│   │           │               ├── CustomBroadcastApplication.java
│   │           │               ├── CustomBroadcastReceiver.java
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── activity_main.xml
│   │               ├── values/
│   │               │   ├── braze.xml
│   │               │   ├── colors.xml
│   │               │   ├── dimens.xml
│   │               │   ├── strings.xml
│   │               │   └── styles.xml
│   │               └── values-w820dp/
│   │                   └── dimens.xml
│   ├── firebase-push/
│   │   ├── README.md
│   │   ├── build.gradle
│   │   ├── google-services.json
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── firebasepush/
│   │           │               ├── FirebaseApplication.java
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── activity_main.xml
│   │               └── values/
│   │                   ├── braze.xml
│   │                   ├── colors.xml
│   │                   ├── dimens.xml
│   │                   ├── strings.xml
│   │                   └── styles.xml
│   ├── glide-image-integration/
│   │   ├── README.md
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── glideimageintegration/
│   │           │               ├── GlideBrazeImageLoader.java
│   │           │               ├── GlideIntegrationApplication.java
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── main_activity.xml
│   │               └── values/
│   │                   ├── braze.xml
│   │                   ├── colors.xml
│   │                   ├── dimens.xml
│   │                   ├── strings.xml
│   │                   └── styles.xml
│   ├── google-tag-manager/
│   │   ├── README.md
│   │   ├── build.gradle
│   │   ├── google-services.json
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── assets/
│   │           │   └── containers/
│   │           │       └── GTM-5HM9ZRX.json
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── googletagmanager/
│   │           │               ├── BrazeGtmTagProvider.java
│   │           │               ├── GtmApplication.java
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── activity_main.xml
│   │               └── values/
│   │                   ├── braze.xml
│   │                   ├── colors.xml
│   │                   ├── dimens.xml
│   │                   ├── strings.xml
│   │                   └── styles.xml
│   ├── hello-braze/
│   │   ├── README.md
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── helloworld/
│   │           │               ├── CustomApplication.java
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── layout/
│   │               │   └── main_activity.xml
│   │               └── values/
│   │                   ├── braze.xml
│   │                   └── strings.xml
│   ├── hms-push-sample/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── braze/
│   │           │           └── hms_sample/
│   │           │               ├── CustomPushService.kt
│   │           │               ├── HmsApplication.kt
│   │           │               └── MainActivity.kt
│   │           └── res/
│   │               ├── drawable/
│   │               │   └── ic_launcher_background.xml
│   │               ├── drawable-v24/
│   │               │   └── ic_launcher_foreground.xml
│   │               ├── layout/
│   │               │   ├── activity_main.xml
│   │               │   └── content_main.xml
│   │               ├── mipmap-anydpi-v26/
│   │               │   ├── ic_launcher.xml
│   │               │   └── ic_launcher_round.xml
│   │               └── values/
│   │                   ├── braze.xml
│   │                   ├── colors.xml
│   │                   ├── dimens.xml
│   │                   ├── strings.xml
│   │                   └── styles.xml
│   └── manual-session-integration/
│       ├── README.md
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── java/
│               │   └── com/
│               │       └── braze/
│               │           └── manualsessionintegration/
│               │               └── MainActivity.java
│               └── res/
│                   ├── layout/
│                   │   └── activity_main.xml
│                   ├── values/
│                   │   ├── braze.xml
│                   │   ├── colors.xml
│                   │   ├── dimens.xml
│                   │   ├── strings.xml
│                   │   └── styles.xml
│                   └── values-w820dp/
│                       └── dimens.xml
└── settings.gradle
Download .txt
SYMBOL INDEX (301 symbols across 58 files)

FILE: android-sdk-ui/src/main/java/com/braze/ui/BrazeFeedFragment.java
  class BrazeFeedFragment (line 38) | public class BrazeFeedFragment extends ListFragment implements SwipeRefr...
    method run (line 55) | @Override
    method onAttach (line 90) | @Override
    method onCreateView (line 100) | @Override
    method onViewCreated (line 118) | @SuppressLint("InflateParams")
    method sortFeedCards (line 262) | public List<Card> sortFeedCards(List<Card> cards) {
    method onResume (line 267) | @Override
    method onDestroyView (line 273) | @Override
    method onPause (line 281) | @Override
    method setOnScreenCardsToRead (line 290) | private void setOnScreenCardsToRead() {
    method onDetach (line 295) | @Override
    method onSaveInstanceState (line 305) | @Override
    method loadFragmentStateFromSavedInstanceState (line 335) | @VisibleForTesting
    method getCategories (line 357) | public EnumSet<CardCategory> getCategories() {
    method getSortEnabled (line 361) | public boolean getSortEnabled() {
    method setSortEnabled (line 369) | public void setSortEnabled(boolean sortEnabled) {
    method setCategory (line 373) | public void setCategory(CardCategory category) {
    method setCategories (line 387) | public void setCategories(EnumSet<CardCategory> categories) {
    method onRefresh (line 407) | @Override
    class FeedGestureListener (line 417) | public class FeedGestureListener extends GestureDetector.SimpleOnGestu...
      method onDown (line 418) | @Override
      method onScroll (line 423) | @Override
      method onFling (line 429) | @Override

FILE: android-sdk-ui/src/main/java/com/braze/ui/BrazeXamarinFormsFeedFragment.java
  class BrazeXamarinFormsFeedFragment (line 34) | @SuppressWarnings({"PMD.UnnecessaryConstructor", "deprecation"})
    method run (line 44) | @Override
    method BrazeXamarinFormsFeedFragment (line 75) | public BrazeXamarinFormsFeedFragment() {
    method onAttach (line 78) | @Override
    method onCreateView (line 90) | @Override
    method onActivityCreated (line 108) | @SuppressLint("InflateParams")
    method onResume (line 238) | @Override
    method onDestroyView (line 244) | @Override
    method onPause (line 253) | @Override
    method setOnScreenCardsToRead (line 262) | private void setOnScreenCardsToRead() {
    method onDetach (line 267) | @Override
    method onSaveInstanceState (line 275) | @Override
    method getCategories (line 287) | public EnumSet<CardCategory> getCategories() {
    method setCategory (line 291) | public void setCategory(CardCategory category) {
    method setCategories (line 305) | public void setCategories(EnumSet<CardCategory> categories) {
    method onRefresh (line 323) | @Override
    class FeedGestureListener (line 331) | public class FeedGestureListener extends GestureDetector.SimpleOnGestu...
      method onDown (line 332) | @Override
      method onScroll (line 337) | @Override
      method onFling (line 343) | @Override

FILE: android-sdk-ui/src/main/java/com/braze/ui/activities/BrazeFeedActivity.java
  class BrazeFeedActivity (line 14) | public class BrazeFeedActivity extends BrazeBaseFragmentActivity {
    method onCreate (line 15) | @Override

FILE: android-sdk-ui/src/main/java/com/braze/ui/adapters/BrazeListAdapter.java
  class BrazeListAdapter (line 47) | public class BrazeListAdapter extends ArrayAdapter<Card> {
    method BrazeListAdapter (line 53) | public BrazeListAdapter(Context context, int layoutResourceId, List<Ca...
    method getViewTypeCount (line 63) | @Override
    method getItemViewType (line 68) | @Override
    method getView (line 88) | @NonNull
    method replaceFeed (line 117) | @SuppressWarnings("checkstyle:localvariablename")
    method add (line 159) | @Override
    method resetCardImpressionTracker (line 168) | public void resetCardImpressionTracker() {
    method logCardImpression (line 172) | private void logCardImpression(Card card) {
    method batchSetCardsToRead (line 195) | public void batchSetCardsToRead(int startIndex, int endIndex) {

FILE: android-sdk-ui/src/main/java/com/braze/ui/feed/BrazeFeedManager.java
  class BrazeFeedManager (line 6) | public class BrazeFeedManager {
    method getInstance (line 13) | public static BrazeFeedManager getInstance() {
    method setFeedCardClickActionListener (line 31) | public void setFeedCardClickActionListener(IFeedClickActionListener cu...
    method getFeedCardClickActionListener (line 38) | public IFeedClickActionListener getFeedCardClickActionListener() {

FILE: android-sdk-ui/src/main/java/com/braze/ui/feed/listeners/BrazeDefaultFeedClickActionListener.java
  class BrazeDefaultFeedClickActionListener (line 8) | public class BrazeDefaultFeedClickActionListener implements IFeedClickAc...
    method onFeedCardClicked (line 9) | @Override

FILE: android-sdk-ui/src/main/java/com/braze/ui/feed/listeners/IFeedClickActionListener.java
  type IFeedClickActionListener (line 15) | public interface IFeedClickActionListener {
    method onFeedCardClicked (line 26) | boolean onFeedCardClicked(Context context, Card card, IAction cardActi...

FILE: android-sdk-ui/src/main/java/com/braze/ui/feed/view/BaseFeedCardView.java
  class BaseFeedCardView (line 19) | public abstract class BaseFeedCardView<T extends Card> extends BaseCardV...
    method BaseFeedCardView (line 22) | public BaseFeedCardView(Context context) {
    method getProperViewFromInflatedStub (line 52) | public View getProperViewFromInflatedStub(int stubLayoutId) {
    method setCard (line 62) | public void setCard(final T newCard) {
    method getCard (line 69) | public Card getCard() {
    method isClickHandled (line 73) | @Override
    method getLayoutResource (line 78) | protected abstract int getLayoutResource();
    method onSetCard (line 80) | protected abstract void onSetCard(T card);

FILE: android-sdk-ui/src/main/java/com/braze/ui/inappmessage/InAppMessageCloser.java
  class InAppMessageCloser (line 10) | @Deprecated
    method InAppMessageCloser (line 14) | public InAppMessageCloser(IInAppMessageViewWrapper inAppMessageViewWra...
    method close (line 18) | public void close(boolean animate) {

FILE: android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/SwipeDismissTouchListener.java
  class SwipeDismissTouchListener (line 57) | @SuppressWarnings("checkstyle:missingswitchdefault")
    type DismissCallbacks (line 83) | public interface DismissCallbacks {
      method canDismiss (line 87) | boolean canDismiss(Object token);
      method onDismiss (line 95) | void onDismiss(View view, Object token);
    method SwipeDismissTouchListener (line 106) | public SwipeDismissTouchListener(View view, Object token, DismissCallb...
    method onTouch (line 118) | @Override
    method performDismiss (line 246) | @TargetApi(12)

FILE: android-sdk-ui/src/main/java/com/braze/ui/widget/BannerImageCardView.java
  class BannerImageCardView (line 12) | public class BannerImageCardView extends BaseFeedCardView<BannerImageCar...
    method BannerImageCardView (line 21) | public BannerImageCardView(Context context) {
    method BannerImageCardView (line 25) | @SuppressWarnings("deprecation") // getDrawable() until Build.VERSION_...
    method getLayoutResource (line 39) | @Override
    method onSetCard (line 44) | @Override

FILE: android-sdk-ui/src/main/java/com/braze/ui/widget/CaptionedImageCardView.java
  class CaptionedImageCardView (line 13) | public class CaptionedImageCardView extends BaseFeedCardView<CaptionedIm...
    method CaptionedImageCardView (line 25) | public CaptionedImageCardView(Context context) {
    method CaptionedImageCardView (line 29) | @SuppressWarnings("deprecation") // getDrawable() until Build.VERSION_...
    method getLayoutResource (line 47) | @Override
    method onSetCard (line 52) | @Override

FILE: android-sdk-ui/src/main/java/com/braze/ui/widget/DefaultCardView.java
  class DefaultCardView (line 10) | public class DefaultCardView extends BaseFeedCardView<Card> {
    method DefaultCardView (line 13) | public DefaultCardView(Context context) {
    method DefaultCardView (line 17) | public DefaultCardView(Context context, Card card) {
    method getLayoutResource (line 25) | @Override
    method onSetCard (line 30) | @Override public void onSetCard(Card card) {

FILE: android-sdk-ui/src/main/java/com/braze/ui/widget/ShortNewsCardView.java
  class ShortNewsCardView (line 13) | public class ShortNewsCardView extends BaseFeedCardView<ShortNewsCard> {
    method ShortNewsCardView (line 22) | public ShortNewsCardView(Context context) {
    method ShortNewsCardView (line 26) | @SuppressWarnings("deprecation") // getDrawable() until Build.VERSION_...
    method getLayoutResource (line 44) | @Override
    method onSetCard (line 49) | @Override

FILE: android-sdk-ui/src/main/java/com/braze/ui/widget/TextAnnouncementCardView.java
  class TextAnnouncementCardView (line 12) | public class TextAnnouncementCardView extends BaseFeedCardView<TextAnnou...
    method TextAnnouncementCardView (line 19) | public TextAnnouncementCardView(Context context) {
    method TextAnnouncementCardView (line 23) | @SuppressWarnings("deprecation") // getDrawable() until Build.VERSION_...
    method getLayoutResource (line 37) | @Override
    method onSetCard (line 42) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/CustomBrazeDeeplinkHandler.java
  class CustomBrazeDeeplinkHandler (line 21) | public class CustomBrazeDeeplinkHandler implements IBrazeDeeplinkHandler {
    method gotoNewsFeed (line 24) | @Override
    method gotoUri (line 34) | @Override
    method getIntentFlags (line 45) | @Override
    method createUriActionFromUrlString (line 50) | @Nullable
    method createUriActionFromUri (line 56) | @Nullable
    class CustomUriAction (line 62) | public static class CustomUriAction extends UriAction {
      method CustomUriAction (line 64) | public CustomUriAction(@NonNull UriAction uriAction) {
      method openUriWithActionView (line 68) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/CustomFeedClickActionListener.java
  class CustomFeedClickActionListener (line 12) | public class CustomFeedClickActionListener implements IFeedClickActionLi...
    method onFeedCardClicked (line 13) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/CustomHtmlInAppMessageActionListener.java
  class CustomHtmlInAppMessageActionListener (line 14) | public class CustomHtmlInAppMessageActionListener implements IHtmlInAppM...
    method CustomHtmlInAppMessageActionListener (line 18) | public CustomHtmlInAppMessageActionListener(Context context) {
    method onCloseClicked (line 22) | @Override
    method onCustomEventFired (line 28) | @Override
    method onNewsfeedClicked (line 34) | @Override
    method onOtherUrlAction (line 41) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/CustomInAppMessage.java
  class CustomInAppMessage (line 5) | public class CustomInAppMessage extends InAppMessageModal {

FILE: droidboy/src/main/java/com/appboy/sample/CustomInAppMessageAnimationFactory.java
  class CustomInAppMessageAnimationFactory (line 11) | public class CustomInAppMessageAnimationFactory implements IInAppMessage...
    method getOpeningAnimation (line 13) | @Override
    method getClosingAnimation (line 21) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/CustomInAppMessageManagerListener.java
  class CustomInAppMessageManagerListener (line 15) | public class CustomInAppMessageManagerListener implements IInAppMessageM...
    method CustomInAppMessageManagerListener (line 18) | public CustomInAppMessageManagerListener(Activity activity) {
    method beforeInAppMessageDisplayed (line 22) | @Override
    method onInAppMessageClicked (line 27) | @Override
    method onInAppMessageButtonClicked (line 37) | @Override
    method onInAppMessageDismissed (line 47) | @Override
    method beforeInAppMessageViewOpened (line 62) | @Override
    method afterInAppMessageViewOpened (line 65) | @Override
    method beforeInAppMessageViewClosed (line 68) | @Override
    method afterInAppMessageViewClosed (line 71) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/CustomInAppMessageView.java
  class CustomInAppMessageView (line 19) | public class CustomInAppMessageView extends RelativeLayout implements II...
    method CustomInAppMessageView (line 21) | public CustomInAppMessageView(Context context, AttributeSet attrs) {
    method setMessageBackgroundColor (line 25) | public void setMessageBackgroundColor(int color) {
    method setMessageTextColor (line 30) | public void setMessageTextColor(int color) {
    method setMessage (line 34) | public void setMessage(String text) {
    method setMessageImage (line 38) | public void setMessageImage(Bitmap bitmap) {
    method setMessageIcon (line 42) | public void setMessageIcon(String icon, int iconColor, int iconBackgro...
    method resetMessageMargins (line 46) | public void resetMessageMargins() {
    method getMessageClickableView (line 55) | public View getMessageClickableView() {
    method applyWindowInsets (line 59) | @Override
    method getMessageTextView (line 64) | public TextView getMessageTextView() {
    method getMessageImageView (line 68) | public ImageView getMessageImageView() {
    method getMessageIconView (line 72) | public TextView getMessageIconView() {
    method getHasAppliedWindowInsets (line 76) | @Override
    method setHasAppliedWindowInsets (line 81) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/CustomInAppMessageViewFactory.java
  class CustomInAppMessageViewFactory (line 13) | public class CustomInAppMessageViewFactory implements IInAppMessageViewF...
    method createInAppMessageView (line 14) | @SuppressLint("InflateParams")

FILE: droidboy/src/main/java/com/appboy/sample/DroidboyEndpointProvider.java
  class DroidboyEndpointProvider (line 12) | public class DroidboyEndpointProvider implements IBrazeEndpointProvider {
    method DroidboyEndpointProvider (line 16) | public DroidboyEndpointProvider(@NonNull String endpoint) {
    method getApiEndpoint (line 21) | public Uri getApiEndpoint(Uri brazeEndpoint) {

FILE: droidboy/src/main/java/com/appboy/sample/DroidboyNotificationFactory.java
  class DroidboyNotificationFactory (line 12) | public class DroidboyNotificationFactory implements IBrazeNotificationFa...
    method createNotification (line 14) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/FeedCategoriesFragment.java
  class FeedCategoriesFragment (line 21) | @SuppressWarnings({"PMD.FieldDeclarationsShouldBeAtStartOfClass", "depre...
    type NoticeDialogListener (line 31) | public interface NoticeDialogListener {
      method onDialogPositiveClick (line 32) | void onDialogPositiveClick(FeedCategoriesFragment dialog);
    method newInstance (line 43) | public static FeedCategoriesFragment newInstance(EnumSet<CardCategory>...
    method onAttach (line 54) | @Override
    method onCreateDialog (line 68) | @NonNull
    method getBooleansFromEnumSet (line 110) | @SuppressWarnings("checkstyle:localvariablename")
    method getEnumSetFromBooleans (line 135) | private EnumSet<CardCategory> getEnumSetFromBooleans(boolean[] isCheck...

FILE: droidboy/src/main/java/com/appboy/sample/PushTesterFragment.java
  class PushTesterFragment (line 32) | @SuppressWarnings("PMD.AvoidDuplicateLiterals")
    method onCreateView (line 96) | @Override
    method onCreate (line 266) | @Override
    method onItemSelected (line 271) | public void onItemSelected(AdapterView<?> parent, View view, int posit...
    method onNothingSelected (line 353) | public void onNothingSelected(AdapterView<?> parent) {
    method getPublicVersionNotificationString (line 357) | private String getPublicVersionNotificationString() throws JSONExcepti...
    method addPushStoryPages (line 371) | private Bundle addPushStoryPages(Bundle notificationExtras) {
    method addActionButtons (line 397) | private Bundle addActionButtons(Bundle notificationExtras) {
    method addConversationPush (line 439) | private void addConversationPush(Bundle bundle) {
    method generateDisplayValue (line 464) | private String generateDisplayValue(String field) {
    method setNotificationFactory (line 474) | private void setNotificationFactory() {

FILE: droidboy/src/main/java/com/appboy/sample/SetEnvironmentPreference.java
  class SetEnvironmentPreference (line 22) | public class SetEnvironmentPreference extends CustomDialogBase {
    method onCreateView (line 32) | @Nullable
    method onViewCreated (line 39) | @Override
    method getApiKeyButton (line 77) | private Button getApiKeyButton(final String alias, final String apiKey) {
    method onExitButtonPressed (line 89) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/UserProfileDialog.java
  class UserProfileDialog (line 30) | public class UserProfileDialog extends CustomDialogBase implements View....
    method onCreateView (line 69) | @Nullable
    method onViewCreated (line 82) | @Override
    method onClick (line 116) | @Override
    method clear (line 133) | private void clear() {
    method populate (line 142) | private void populate() {
    method onExitButtonPressed (line 164) | @Override
    method getBirthday (line 239) | private String getBirthday() {
    method parseGenderFromSharedPreferences (line 243) | private int parseGenderFromSharedPreferences() {
    method getSharedPreferences (line 265) | private SharedPreferences getSharedPreferences() {

FILE: droidboy/src/main/java/com/appboy/sample/activity/FeedFragmentActivity.java
  class FeedFragmentActivity (line 9) | public class FeedFragmentActivity extends AppCompatActivity {
    method onCreate (line 10) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/activity/GeofencesMapActivity.java
  class GeofencesMapActivity (line 32) | public class GeofencesMapActivity extends AppCompatActivity implements O...
    method onCreate (line 36) | @Override
    method onMapReady (line 45) | @Override
    method retrieveBrazeGeofencesFromLocalStorage (line 75) | private static List<BrazeGeofence> retrieveBrazeGeofencesFromLocalStor...

FILE: droidboy/src/main/java/com/appboy/sample/logging/CustomEventDialog.java
  class CustomEventDialog (line 15) | public class CustomEventDialog extends CustomLogger {
    method onCreateView (line 17) | @Nullable
    method customLog (line 23) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/logging/CustomLogger.java
  class CustomLogger (line 22) | public abstract class CustomLogger extends CustomDialogBase {
    method onViewCreated (line 27) | @Override
    method onExitButtonPressed (line 43) | @Override
    method notifyResult (line 62) | private void notifyResult(String input) {
    method customLog (line 66) | protected abstract void customLog(String name, BrazeProperties propert...

FILE: droidboy/src/main/java/com/appboy/sample/logging/CustomPurchaseDialog.java
  class CustomPurchaseDialog (line 20) | public class CustomPurchaseDialog extends CustomLogger {
    method onCreateView (line 27) | @Nullable
    method customLog (line 41) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/logging/CustomUserAttributeDialog.java
  class CustomUserAttributeDialog (line 21) | public class CustomUserAttributeDialog extends CustomDialogBase {
    method onCreateView (line 35) | @Nullable
    method onViewCreated (line 41) | @Override
    method onExitButtonPressed (line 65) | @Override
    method notifyResult (line 146) | private void notifyResult(boolean result, String input) {
    method stringToInteger (line 157) | private int stringToInteger(String num) {

FILE: droidboy/src/main/java/com/appboy/sample/logging/PropertyManager.java
  class PropertyManager (line 29) | public class PropertyManager implements AdapterView.OnItemSelectedListen...
    method PropertyManager (line 40) | public PropertyManager(Context context, LinearLayout linearLayout, Edi...
    method getBrazeProperties (line 82) | public BrazeProperties getBrazeProperties() {
    method addPropertyView (line 105) | private void addPropertyView(String key, Object value) {
    method getIntegerProperty (line 125) | private Object getIntegerProperty() {
    method getLongProperty (line 134) | private Object getLongProperty() {
    method getDoubleProperty (line 143) | private Object getDoubleProperty() {
    method getStringProperty (line 152) | private Object getStringProperty() {
    method getBooleanProperty (line 162) | private Object getBooleanProperty() {
    method onItemSelected (line 173) | @Override
    method onNothingSelected (line 208) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/subscriptions/EmailSubscriptionStateDialog.java
  class EmailSubscriptionStateDialog (line 11) | public class EmailSubscriptionStateDialog extends SubscriptionStateDialo...
    method onExitButtonPressed (line 14) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/subscriptions/PushSubscriptionStateDialog.java
  class PushSubscriptionStateDialog (line 11) | public class PushSubscriptionStateDialog extends SubscriptionStateDialog...
    method onExitButtonPressed (line 14) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/subscriptions/SubscriptionStateDialogBase.java
  class SubscriptionStateDialogBase (line 15) | public abstract class SubscriptionStateDialogBase extends CustomDialogBa...
    method onCreateView (line 22) | @Nullable
    method onViewCreated (line 28) | @Override

FILE: droidboy/src/main/java/com/appboy/sample/util/ButtonUtils.java
  class ButtonUtils (line 7) | public class ButtonUtils {
    method setUpPopulateButton (line 9) | public static void setUpPopulateButton(View view, int buttonId, final ...
    method setUpPopulateButton (line 13) | public static Button setUpPopulateButton(View view, int buttonId, fina...
    method handlePopulateButtonClick (line 24) | public static void handlePopulateButtonClick(EditText buttonEditText, ...

FILE: droidboy/src/main/java/com/appboy/sample/util/EmulatorDetectionUtils.java
  class EmulatorDetectionUtils (line 3) | public class EmulatorDetectionUtils {
    method getEmulatorModelsForAppboyDeactivation (line 7) | public static String[] getEmulatorModelsForAppboyDeactivation() {

FILE: droidboy/src/main/java/com/appboy/sample/util/LifecycleUtils.java
  class LifecycleUtils (line 13) | @SuppressWarnings("PMD.DoNotCallSystemExit")
    method restartApp (line 17) | public static void restartApp(Context context) {

FILE: droidboy/src/main/java/com/appboy/sample/util/SpinnerUtils.java
  class SpinnerUtils (line 12) | public class SpinnerUtils {
    method setUpSpinner (line 15) | public static void setUpSpinner(Spinner spinner, OnItemSelectedListene...
    method setUpSpinnerWithList (line 22) | public static void setUpSpinnerWithList(Spinner spinner, OnItemSelecte...
    method spinnerItemNotSet (line 29) | public static boolean spinnerItemNotSet(String spinnerItem) {
    method handleSpinnerItemSelected (line 33) | public static String handleSpinnerItemSelected(AdapterView<?> parent, ...

FILE: droidboy/src/main/java/com/appboy/sample/util/ViewUtils.java
  class ViewUtils (line 8) | @SuppressWarnings("deprecation")
    method enableImmersiveMode (line 14) | public static void enableImmersiveMode(final View decorView) {
    method enableNoLimitsMode (line 23) | public static void enableNoLimitsMode(Window window) {
    method setSystemUiVisibility (line 27) | private static int setSystemUiVisibility() {

FILE: samples/custom-broadcast/src/main/java/com/braze/custombroadcast/CustomBroadcastApplication.java
  class CustomBroadcastApplication (line 11) | public class CustomBroadcastApplication extends Application {
    method onCreate (line 12) | @Override

FILE: samples/custom-broadcast/src/main/java/com/braze/custombroadcast/CustomBroadcastReceiver.java
  class CustomBroadcastReceiver (line 15) | public class CustomBroadcastReceiver extends BroadcastReceiver {
    method onReceive (line 18) | @Override
    method logNotificationDuration (line 45) | private void logNotificationDuration(Intent intent) {

FILE: samples/custom-broadcast/src/main/java/com/braze/custombroadcast/MainActivity.java
  class MainActivity (line 13) | public class MainActivity extends AppCompatActivity {
    method onCreate (line 15) | @Override
    method showMessage (line 37) | private void showMessage(String message) {

FILE: samples/firebase-push/src/main/java/com/braze/firebasepush/FirebaseApplication.java
  class FirebaseApplication (line 13) | public class FirebaseApplication extends Application {
    method onCreate (line 16) | @Override

FILE: samples/firebase-push/src/main/java/com/braze/firebasepush/MainActivity.java
  class MainActivity (line 13) | public class MainActivity extends AppCompatActivity {
    method onCreate (line 15) | @Override
    method showMessage (line 38) | private void showMessage(String message) {

FILE: samples/glide-image-integration/src/main/java/com/braze/glideimageintegration/GlideBrazeImageLoader.java
  class GlideBrazeImageLoader (line 19) | public class GlideBrazeImageLoader implements IBrazeImageLoader {
    method renderUrlIntoCardView (line 24) | @Override
    method renderUrlIntoInAppMessageView (line 33) | @Override
    method getPushBitmapFromUrl (line 42) | @Override
    method getInAppMessageBitmapFromUrl (line 50) | @Override
    method renderUrlIntoView (line 58) | private void renderUrlIntoView(Context context,
    method getBitmapFromUrl (line 68) | private Bitmap getBitmapFromUrl(Context context,
    method setOffline (line 82) | @Override

FILE: samples/glide-image-integration/src/main/java/com/braze/glideimageintegration/GlideIntegrationApplication.java
  class GlideIntegrationApplication (line 10) | public class GlideIntegrationApplication extends Application {
    method onCreate (line 11) | @Override

FILE: samples/glide-image-integration/src/main/java/com/braze/glideimageintegration/MainActivity.java
  class MainActivity (line 19) | public class MainActivity extends AppCompatActivity {
    method onCreate (line 21) | @Override
    method showInAppMessage (line 61) | private void showInAppMessage(InAppMessageBase inAppMessage) {

FILE: samples/google-tag-manager/src/main/java/com/braze/googletagmanager/BrazeGtmTagProvider.java
  class BrazeGtmTagProvider (line 15) | public class BrazeGtmTagProvider implements CustomTagProvider {
    method setApplicationContext (line 40) | public static void setApplicationContext(Context applicationContext) {
    method execute (line 46) | @Override
    method logEvent (line 77) | private void logEvent(Map<String, Object> tagParameterMap) {
    method parseMapIntoProperties (line 82) | private BrazeProperties parseMapIntoProperties(Map<String, Object> map) {
    method setCustomAttribute (line 108) | private void setCustomAttribute(Map<String, Object> tagParameterMap) {
    method changeUser (line 135) | private void changeUser(Map<String, Object> tagParameterMap) {

FILE: samples/google-tag-manager/src/main/java/com/braze/googletagmanager/GtmApplication.java
  class GtmApplication (line 11) | public class GtmApplication extends Application {
    method onCreate (line 12) | @Override

FILE: samples/google-tag-manager/src/main/java/com/braze/googletagmanager/MainActivity.java
  class MainActivity (line 13) | public class MainActivity extends AppCompatActivity {
    method onCreate (line 16) | @Override
    method showMessage (line 63) | private void showMessage(String message) {

FILE: samples/hello-braze/src/main/java/com/braze/helloworld/CustomApplication.java
  class CustomApplication (line 16) | public class CustomApplication extends Application {
    method onCreate (line 18) | @Override
    method configureAppboyAtRuntime (line 26) | private void configureAppboyAtRuntime() {

FILE: samples/hello-braze/src/main/java/com/braze/helloworld/MainActivity.java
  class MainActivity (line 15) | public class MainActivity extends Activity {
    method onCreate (line 25) | @Override
    method displayToast (line 68) | private void displayToast(String message) {

FILE: samples/manual-session-integration/src/main/java/com/braze/manualsessionintegration/MainActivity.java
  class MainActivity (line 10) | public class MainActivity extends AppCompatActivity {
    method onCreate (line 12) | @Override
    method onStart (line 18) | @Override
    method onResume (line 27) | @Override
    method onPause (line 35) | @Override
    method onStop (line 42) | @Override
Condensed preview — 472 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,560K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug.yml",
    "chars": 1855,
    "preview": "name: 🐞 Bug report\ndescription: File a Bug Report for unexpected or incorrect SDK Behavior\ntitle: '[Bug]: '\nlabels: [\"bu"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 386,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Braze Support\n    url: https://www.braze.com/docs/support_contact\n "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature.yml",
    "chars": 1243,
    "preview": "name: ✅ Feature Request\ndescription: Request New SDK Features\ntitle: '[Feature]: '\nlabels: [\"feature-request\"]\nbody:\n  -"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 2773,
    "preview": "<!--\nThank you for opening an issue with Braze!\n\nIf you are experiencing issues with our product, please consider direct"
  },
  {
    "path": ".gitignore",
    "chars": 499,
    "preview": "# Created by http://www.gitignore.io\n\n### Intellij ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, P"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 139791,
    "preview": "# :warning: This repository has been permanently moved to [https://github.com/braze-inc/braze-android-sdk](https://githu"
  },
  {
    "path": "LICENSE",
    "chars": 1473,
    "preview": "Copyright (c) 2023 Braze, Inc.\nAll rights reserved.\n\n* Use of source code or binaries contained within Braze’s SDKs is p"
  },
  {
    "path": "README.md",
    "chars": 3032,
    "preview": "This repository has been permanently moved to https://github.com/braze-inc/braze-android-sdk.\n\n-----\n\n\n![Braze Logo](htt"
  },
  {
    "path": "android-sdk-location/build.gradle",
    "chars": 1054,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\n\ndependencies {\n    api \"com.appboy:android-sdk-base:"
  },
  {
    "path": "android-sdk-location/src/main/AndroidManifest.xml",
    "chars": 329,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  package=\"c"
  },
  {
    "path": "android-sdk-location/src/main/java/com/braze/location/BrazeActionReceiver.kt",
    "chars": 6690,
    "preview": "package com.braze.location\n\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.conte"
  },
  {
    "path": "android-sdk-location/src/main/java/com/braze/location/BrazeInternalGeofenceApi.kt",
    "chars": 2068,
    "preview": "package com.braze.location\n\nimport android.app.PendingIntent\nimport android.content.Context\nimport android.content.Inten"
  },
  {
    "path": "android-sdk-location/src/main/java/com/braze/location/BrazeInternalLocationApi.kt",
    "chars": 8702,
    "preview": "package com.braze.location\n\nimport android.Manifest\nimport android.app.PendingIntent\nimport android.content.Context\nimpo"
  },
  {
    "path": "android-sdk-location/src/main/java/com/braze/location/GooglePlayLocationUtils.kt",
    "chars": 12908,
    "preview": "package com.braze.location\n\nimport android.annotation.SuppressLint\nimport android.app.PendingIntent\nimport android.conte"
  },
  {
    "path": "android-sdk-ui/braze-consumer-proguard-rules.pro",
    "chars": 692,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in an"
  },
  {
    "path": "android-sdk-ui/build.gradle",
    "chars": 1377,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\n\ndependencies {\n  api \"com.appboy:android-sdk-base:${"
  },
  {
    "path": "android-sdk-ui/src/main/AndroidManifest.xml",
    "chars": 890,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  package=\"c"
  },
  {
    "path": "android-sdk-ui/src/main/assets/braze-html-in-app-message-bridge.js",
    "chars": 4346,
    "preview": "var brazeBridge = {\n  logCustomEvent: function (name, properties) { brazeInternalBridge.logCustomEventWithJSON(name, JSO"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/BrazeActivityLifecycleCallbackListener.kt",
    "chars": 8036,
    "preview": "package com.braze\n\nimport android.app.Activity\nimport android.app.Application\nimport android.app.Application.ActivityLif"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/IBrazeDeeplinkHandler.kt",
    "chars": 3284,
    "preview": "package com.braze\n\nimport android.content.Context\nimport android.net.Uri\nimport android.os.Bundle\nimport com.braze.enums"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/push/BrazeAmazonDeviceMessagingReceiver.kt",
    "chars": 87,
    "preview": "package com.braze.push\n\nclass BrazeAmazonDeviceMessagingReceiver : BrazePushReceiver()\n"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/push/BrazeFirebaseMessagingService.kt",
    "chars": 3891,
    "preview": "package com.braze.push\n\nimport android.content.Context\nimport android.content.Intent\nimport android.os.Bundle\nimport com"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/push/BrazeHuaweiPushHandler.kt",
    "chars": 2122,
    "preview": "package com.braze.push\n\nimport android.content.Context\nimport android.content.Intent\nimport android.os.Bundle\nimport com"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/push/BrazeNotificationActionUtils.kt",
    "chars": 8727,
    "preview": "package com.braze.push\n\nimport android.app.PendingIntent\nimport android.content.Context\nimport android.content.Intent\nim"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/push/BrazeNotificationFactory.kt",
    "chars": 7700,
    "preview": "package com.braze.push\n\nimport android.app.Notification\nimport android.content.Context\nimport android.os.Bundle\nimport a"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/push/BrazeNotificationStyleFactory.kt",
    "chars": 27362,
    "preview": "package com.braze.push\n\nimport android.app.PendingIntent\nimport android.content.Context\nimport android.content.Intent\nim"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/push/BrazeNotificationUtils.kt",
    "chars": 50251,
    "preview": "package com.braze.push\n\nimport android.Manifest\nimport android.annotation.SuppressLint\nimport android.annotation.TargetA"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/push/BrazePushReceiver.kt",
    "chars": 16230,
    "preview": "package com.braze.push\n\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.I"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/push/NotificationTrampolineActivity.kt",
    "chars": 2648,
    "preview": "package com.braze.push\n\nimport android.app.Activity\nimport android.content.Intent\nimport android.os.Bundle\nimport com.br"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/push/support/HtmlUtils.kt",
    "chars": 1125,
    "preview": "@file:JvmName(\"HtmlUtils\")\n\npackage com.braze.push.support\n\nimport android.os.Build\nimport android.text.Html\nimport com."
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/BrazeDeeplinkHandler.kt",
    "chars": 3331,
    "preview": "package com.braze.ui\n\nimport android.content.Context\nimport android.content.Intent\nimport android.net.Uri\nimport android"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/BrazeFeedFragment.java",
    "chars": 19783,
    "preview": "package com.braze.ui;\n\nimport android.annotation.SuppressLint;\nimport android.app.Activity;\nimport android.content.Conte"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/BrazeWebViewActivity.kt",
    "chars": 6821,
    "preview": "package com.braze.ui\n\nimport android.annotation.SuppressLint\nimport android.content.Context\nimport android.graphics.Bitm"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/BrazeXamarinFormsFeedFragment.java",
    "chars": 15580,
    "preview": "package com.braze.ui;\n\nimport android.annotation.SuppressLint;\nimport android.app.Activity;\nimport android.content.Conte"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/IAction.kt",
    "chars": 175,
    "preview": "package com.braze.ui.actions\n\nimport android.content.Context\nimport com.braze.enums.Channel\n\ninterface IAction {\n    val"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/NewsfeedAction.kt",
    "chars": 774,
    "preview": "package com.braze.ui.actions\n\nimport android.content.Context\nimport android.content.Intent\nimport android.os.Bundle\nimpo"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/UriAction.kt",
    "chars": 11789,
    "preview": "package com.braze.ui.actions\n\nimport android.annotation.SuppressLint\nimport android.content.ActivityNotFoundException\nim"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/BrazeActionParser.kt",
    "chars": 7485,
    "preview": "package com.braze.ui.actions.brazeactions\n\nimport android.content.Context\nimport android.net.Uri\nimport android.util.Bas"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/BrazeActionUtils.kt",
    "chars": 3132,
    "preview": "@file:JvmName(\"BrazeActionUtils\")\n\npackage com.braze.ui.actions.brazeactions\n\nimport android.net.Uri\nimport com.braze.mo"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/AddToCustomAttributeArrayStep.kt",
    "chars": 616,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.Braze\n\ninternal object "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/AddToSubscriptionGroupStep.kt",
    "chars": 559,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.Braze\n\ninternal object "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/BaseBrazeActionStep.kt",
    "chars": 677,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport com.braze.Braze\nimport com.braze.BrazeUser\nimport com.braze.even"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/ContainerStep.kt",
    "chars": 863,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.support.iterator\nimport"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/IBrazeActionStep.kt",
    "chars": 411,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\n\ninternal sealed interface IBrazeActionS"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/LogCustomEventStep.kt",
    "chars": 594,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.Braze\n\ninternal object "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/NoOpStep.kt",
    "chars": 246,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\n\ninternal object NoOpStep : IBrazeAction"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/OpenLinkExternallyStep.kt",
    "chars": 881,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.ui.BrazeDeeplinkHandler"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/OpenLinkInWebViewStep.kt",
    "chars": 730,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.ui.BrazeDeeplinkHandler"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/RemoveFromCustomAttributeArrayStep.kt",
    "chars": 638,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.Braze\n\ninternal object "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/RemoveFromSubscriptionGroupStep.kt",
    "chars": 569,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.Braze\n\ninternal object "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/RequestPushPermissionStep.kt",
    "chars": 534,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.support.requestPushPerm"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/SetCustomUserAttributeStep.kt",
    "chars": 823,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.Braze\nimport com.braze."
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/SetEmailSubscriptionStep.kt",
    "chars": 953,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.enums.NotificationSubsc"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/SetPushNotificationSubscriptionStep.kt",
    "chars": 973,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport android.content.Context\nimport com.braze.enums.NotificationSubsc"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/actions/brazeactions/steps/StepData.kt",
    "chars": 2782,
    "preview": "package com.braze.ui.actions.brazeactions.steps\n\nimport androidx.annotation.VisibleForTesting\nimport com.braze.enums.Cha"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/activities/BrazeBaseFragmentActivity.kt",
    "chars": 1553,
    "preview": "package com.braze.ui.activities\n\nimport androidx.fragment.app.FragmentActivity\nimport com.braze.Braze\nimport com.braze.u"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/activities/BrazeFeedActivity.java",
    "chars": 616,
    "preview": "package com.braze.ui.activities;\n\nimport android.os.Bundle;\n\nimport com.braze.ui.R;\n\n/**\n * The BrazeFeedActivity in an "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/activities/ContentCardsActivity.kt",
    "chars": 626,
    "preview": "package com.braze.ui.activities\n\nimport android.os.Bundle\nimport com.braze.ui.R\n\n/**\n * The [ContentCardsActivity] in an"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/adapters/BrazeListAdapter.java",
    "chars": 7716,
    "preview": "package com.braze.ui.adapters;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.view.ViewGroup;"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/ContentCardsFragment.kt",
    "chars": 17713,
    "preview": "package com.braze.ui.contentcards\n\nimport android.os.Build\nimport android.os.Bundle\nimport android.os.Parcelable\nimport "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/adapters/ContentCardAdapter.kt",
    "chars": 11550,
    "preview": "package com.braze.ui.contentcards.adapters\n\nimport android.content.Context\nimport android.os.Handler\nimport android.os.L"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/adapters/EmptyContentCardsAdapter.kt",
    "chars": 1090,
    "preview": "package com.braze.ui.contentcards.adapters\n\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.v"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/handlers/DefaultContentCardsUpdateHandler.kt",
    "chars": 2223,
    "preview": "package com.braze.ui.contentcards.handlers\n\nimport android.os.Parcel\nimport android.os.Parcelable\nimport com.braze.event"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/handlers/DefaultContentCardsViewBindingHandler.kt",
    "chars": 4311,
    "preview": "package com.braze.ui.contentcards.handlers\n\nimport android.content.Context\nimport android.os.Parcel\nimport android.os.Pa"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/handlers/IContentCardsUpdateHandler.kt",
    "chars": 838,
    "preview": "package com.braze.ui.contentcards.handlers\n\nimport android.os.Parcelable\nimport com.braze.models.cards.Card\nimport com.b"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/handlers/IContentCardsViewBindingHandler.kt",
    "chars": 2902,
    "preview": "package com.braze.ui.contentcards.handlers\n\nimport android.content.Context\nimport android.os.Parcelable\nimport android.v"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/listeners/DefaultContentCardsActionListener.kt",
    "chars": 169,
    "preview": "package com.braze.ui.contentcards.listeners\n\n// Use the default implementations from the interface\nclass DefaultContentC"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/listeners/IContentCardsActionListener.kt",
    "chars": 1265,
    "preview": "package com.braze.ui.contentcards.listeners\n\nimport android.content.Context\nimport com.braze.models.cards.Card\nimport co"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/managers/BrazeContentCardsManager.kt",
    "chars": 772,
    "preview": "package com.braze.ui.contentcards.managers\n\nimport com.braze.ui.contentcards.listeners.DefaultContentCardsActionListener"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/recycler/ContentCardsDividerItemDecoration.kt",
    "chars": 3095,
    "preview": "package com.braze.ui.contentcards.recycler\n\nimport android.content.Context\nimport android.graphics.Rect\nimport android.v"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/recycler/ItemTouchHelperAdapter.kt",
    "chars": 352,
    "preview": "package com.braze.ui.contentcards.recycler\n\ninterface ItemTouchHelperAdapter {\n    fun onItemDismiss(position: Int)\n\n   "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/recycler/SimpleItemTouchHelperCallback.kt",
    "chars": 1261,
    "preview": "package com.braze.ui.contentcards.recycler\n\nimport androidx.recyclerview.widget.ItemTouchHelper\nimport androidx.recycler"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/view/BannerImageContentCardView.kt",
    "chars": 1369,
    "preview": "package com.braze.ui.contentcards.view\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/view/BaseContentCardView.kt",
    "chars": 2784,
    "preview": "package com.braze.ui.contentcards.view\n\nimport android.annotation.TargetApi\nimport android.content.Context\nimport androi"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/view/CaptionedImageContentCardView.kt",
    "chars": 2125,
    "preview": "package com.braze.ui.contentcards.view\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/view/ContentCardViewHolder.kt",
    "chars": 2155,
    "preview": "package com.braze.ui.contentcards.view\n\nimport android.view.View\nimport android.widget.ImageView\nimport android.widget.T"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/view/DefaultContentCardView.kt",
    "chars": 818,
    "preview": "package com.braze.ui.contentcards.view\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/view/ShortNewsContentCardView.kt",
    "chars": 2393,
    "preview": "package com.braze.ui.contentcards.view\n\nimport android.content.Context\nimport android.os.Build\nimport android.view.Layou"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/contentcards/view/TextAnnouncementContentCardView.kt",
    "chars": 1905,
    "preview": "package com.braze.ui.contentcards.view\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/feed/BrazeFeedManager.java",
    "chars": 1449,
    "preview": "package com.braze.ui.feed;\n\nimport com.braze.ui.feed.listeners.BrazeDefaultFeedClickActionListener;\nimport com.braze.ui."
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/feed/BrazeImageSwitcher.kt",
    "chars": 2173,
    "preview": "package com.braze.ui.feed\n\nimport android.content.Context\nimport android.graphics.drawable.Drawable\nimport android.util."
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/feed/listeners/BrazeDefaultFeedClickActionListener.java",
    "chars": 353,
    "preview": "package com.braze.ui.feed.listeners;\n\nimport android.content.Context;\n\nimport com.braze.models.cards.Card;\nimport com.br"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/feed/listeners/IFeedClickActionListener.java",
    "chars": 1033,
    "preview": "package com.braze.ui.feed.listeners;\n\nimport android.content.Context;\n\nimport com.braze.models.cards.Card;\nimport com.br"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/feed/view/BaseFeedCardView.java",
    "chars": 2912,
    "preview": "package com.braze.ui.feed.view;\n\nimport android.content.Context;\nimport android.view.LayoutInflater;\nimport android.view"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/BrazeInAppMessageManager.kt",
    "chars": 32791,
    "preview": "package com.braze.ui.inappmessage\n\nimport android.annotation.SuppressLint\nimport android.app.Activity\nimport android.con"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/DefaultInAppMessageViewWrapper.kt",
    "chars": 23245,
    "preview": "package com.braze.ui.inappmessage\n\nimport android.app.Activity\nimport android.view.Gravity\nimport android.view.View\nimpo"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/IInAppMessageAnimationFactory.kt",
    "chars": 793,
    "preview": "package com.braze.ui.inappmessage\n\nimport android.view.animation.Animation\nimport com.braze.models.inappmessage.IInAppMe"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/IInAppMessageViewFactory.kt",
    "chars": 852,
    "preview": "package com.braze.ui.inappmessage\n\nimport android.app.Activity\nimport android.view.View\nimport com.braze.models.inappmes"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/IInAppMessageViewWrapper.kt",
    "chars": 1244,
    "preview": "package com.braze.ui.inappmessage\n\nimport android.app.Activity\nimport android.view.View\nimport com.braze.models.inappmes"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/IInAppMessageViewWrapperFactory.kt",
    "chars": 3657,
    "preview": "package com.braze.ui.inappmessage\n\nimport android.view.View\nimport android.view.animation.Animation\nimport com.braze.con"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/InAppMessageCloser.java",
    "chars": 737,
    "preview": "package com.braze.ui.inappmessage;\n\nimport com.braze.models.inappmessage.IInAppMessage;\n\n/**\n * @deprecated Please use {"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/InAppMessageManagerBase.kt",
    "chars": 12031,
    "preview": "package com.braze.ui.inappmessage\n\nimport android.app.Activity\nimport android.content.Context\nimport androidx.annotation"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/InAppMessageOperation.kt",
    "chars": 364,
    "preview": "package com.braze.ui.inappmessage\n\nimport androidx.annotation.Keep\nimport java.util.*\n\nenum class InAppMessageOperation "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/config/BrazeInAppMessageParams.kt",
    "chars": 436,
    "preview": "package com.braze.ui.inappmessage.config\n\nobject BrazeInAppMessageParams {\n    const val MODALIZED_IMAGE_RADIUS_DP = 9.0"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/factories/DefaultInAppMessageAnimationFactory.kt",
    "chars": 1735,
    "preview": "package com.braze.ui.inappmessage.factories\n\nimport android.content.res.Resources\nimport android.view.animation.AlphaAni"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/factories/DefaultInAppMessageFullViewFactory.kt",
    "chars": 7519,
    "preview": "package com.braze.ui.inappmessage.factories\n\nimport android.annotation.SuppressLint\nimport android.app.Activity\nimport a"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/factories/DefaultInAppMessageHtmlFullViewFactory.kt",
    "chars": 2598,
    "preview": "package com.braze.ui.inappmessage.factories\n\nimport android.annotation.SuppressLint\nimport android.app.Activity\nimport c"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/factories/DefaultInAppMessageHtmlViewFactory.kt",
    "chars": 2563,
    "preview": "package com.braze.ui.inappmessage.factories\n\nimport android.annotation.SuppressLint\nimport android.app.Activity\nimport c"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/factories/DefaultInAppMessageModalViewFactory.kt",
    "chars": 4252,
    "preview": "package com.braze.ui.inappmessage.factories\n\nimport android.annotation.SuppressLint\nimport android.app.Activity\nimport c"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/factories/DefaultInAppMessageSlideupViewFactory.kt",
    "chars": 2626,
    "preview": "package com.braze.ui.inappmessage.factories\n\nimport android.app.Activity\nimport com.braze.ui.R\nimport com.braze.Braze\nim"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/factories/DefaultInAppMessageViewWrapperFactory.kt",
    "chars": 2209,
    "preview": "package com.braze.ui.inappmessage.factories\n\nimport android.view.View\nimport android.view.animation.Animation\nimport com"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/jsinterface/InAppMessageJavascriptInterface.kt",
    "chars": 2829,
    "preview": "package com.braze.ui.inappmessage.jsinterface\n\nimport android.content.Context\nimport android.webkit.JavascriptInterface\n"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/jsinterface/InAppMessageUserJavascriptInterface.kt",
    "chars": 9337,
    "preview": "package com.braze.ui.inappmessage.jsinterface\n\nimport android.content.Context\nimport android.webkit.JavascriptInterface\n"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/DefaultHtmlInAppMessageActionListener.kt",
    "chars": 128,
    "preview": "package com.braze.ui.inappmessage.listeners\n\nopen class DefaultHtmlInAppMessageActionListener : IHtmlInAppMessageActionL"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/DefaultInAppMessageManagerListener.kt",
    "chars": 1056,
    "preview": "package com.braze.ui.inappmessage.listeners\n\nimport com.braze.models.inappmessage.IInAppMessage\nimport com.braze.models."
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/DefaultInAppMessageViewLifecycleListener.kt",
    "chars": 9131,
    "preview": "package com.braze.ui.inappmessage.listeners\n\nimport android.net.Uri\nimport android.view.View\nimport com.braze.enums.Chan"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/DefaultInAppMessageWebViewClientListener.kt",
    "chars": 8912,
    "preview": "package com.braze.ui.inappmessage.listeners\n\nimport android.os.Bundle\nimport androidx.annotation.VisibleForTesting\nimpor"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/IHtmlInAppMessageActionListener.kt",
    "chars": 2080,
    "preview": "package com.braze.ui.inappmessage.listeners\n\nimport android.os.Bundle\nimport com.braze.models.inappmessage.IInAppMessage"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/IInAppMessageManagerListener.kt",
    "chars": 5694,
    "preview": "@file:Suppress(\"DEPRECATION\")\npackage com.braze.ui.inappmessage.listeners\n\nimport android.view.View\nimport com.braze.mod"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/IInAppMessageViewLifecycleListener.kt",
    "chars": 2534,
    "preview": "@file:Suppress(\"DEPRECATION\")\n\npackage com.braze.ui.inappmessage.listeners\n\nimport android.view.View\nimport com.braze.mo"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/IInAppMessageWebViewClientListener.kt",
    "chars": 2111,
    "preview": "package com.braze.ui.inappmessage.listeners\n\nimport android.os.Bundle\nimport com.braze.models.inappmessage.IInAppMessage"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/IWebViewClientStateListener.kt",
    "chars": 213,
    "preview": "package com.braze.ui.inappmessage.listeners\n\nfun interface IWebViewClientStateListener {\n    /**\n     * Fired when [andr"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/SwipeDismissTouchListener.java",
    "chars": 9580,
    "preview": "package com.braze.ui.inappmessage.listeners;\n\n/*\n * Copyright 2013 Google Inc.\n *\n * Licensed under the Apache License, "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/listeners/TouchAwareSwipeDismissTouchListener.kt",
    "chars": 1054,
    "preview": "package com.braze.ui.inappmessage.listeners\n\nimport android.view.MotionEvent\nimport android.view.View\n\n/**\n * Adds touch"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/utils/BackgroundInAppMessagePreparer.kt",
    "chars": 11655,
    "preview": "package com.braze.ui.inappmessage.utils\n\nimport android.content.Context\nimport androidx.annotation.VisibleForTesting\nimp"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/utils/InAppMessageButtonViewUtils.kt",
    "chars": 4720,
    "preview": "package com.braze.ui.inappmessage.utils\n\nimport android.content.Context\nimport android.graphics.drawable.Drawable\nimport"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/utils/InAppMessageViewUtils.kt",
    "chars": 5094,
    "preview": "package com.braze.ui.inappmessage.utils\n\nimport android.content.Context\nimport android.graphics.Bitmap\nimport android.gr"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/utils/InAppMessageWebViewClient.kt",
    "chars": 8725,
    "preview": "package com.braze.ui.inappmessage.utils\n\nimport android.content.Context\nimport android.net.Uri\nimport android.os.Build\ni"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/IInAppMessageImageView.kt",
    "chars": 1212,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport com.braze.enums.inappmessage.CropType\n\n/**\n * IInAppMessageImageView is "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/IInAppMessageImmersiveView.kt",
    "chars": 1548,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.view.View\n\n/**\n * [IInAppMessageImmersiveView] is the base view "
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/IInAppMessageView.kt",
    "chars": 2033,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.view.View\nimport androidx.core.view.WindowInsetsCompat\n\n/**\n * ["
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageBaseView.kt",
    "chars": 3563,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.content.Context\nimport android.graphics.Bitmap\nimport android.ut"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageBoundedLayout.kt",
    "chars": 2904,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.content.Context\nimport android.util.AttributeSet\nimport android."
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageButton.kt",
    "chars": 455,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.content.Context\nimport android.util.AttributeSet\nimport android."
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageFullView.kt",
    "chars": 10775,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.app.Activity\nimport android.content.Context\nimport android.graph"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageHtmlBaseView.kt",
    "chars": 10584,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.annotation.SuppressLint\nimport android.content.Context\nimport an"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageHtmlFullView.kt",
    "chars": 346,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.content.Context\nimport android.util.AttributeSet\nimport com.braz"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageHtmlView.kt",
    "chars": 337,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.content.Context\nimport android.util.AttributeSet\nimport com.braz"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageImageView.kt",
    "chars": 4823,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.annotation.SuppressLint\nimport android.content.Context\nimport an"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageImmersiveBaseView.kt",
    "chars": 10669,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.content.Context\nimport android.graphics.Rect\nimport android.os.B"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageModalView.kt",
    "chars": 8010,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.content.Context\nimport android.graphics.drawable.Drawable\nimport"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageSlideupView.kt",
    "chars": 4515,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.content.Context\nimport android.graphics.drawable.GradientDrawabl"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/inappmessage/views/InAppMessageWebView.kt",
    "chars": 1884,
    "preview": "package com.braze.ui.inappmessage.views\n\nimport android.content.Context\nimport android.util.AttributeSet\nimport android."
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/support/AnimationUtils.kt",
    "chars": 2981,
    "preview": "@file:JvmName(\"AnimationUtils\")\n\npackage com.braze.ui.support\n\nimport android.view.animation.AccelerateInterpolator\nimpo"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/support/UriUtils.kt",
    "chars": 3552,
    "preview": "@file:JvmName(\"UriUtils\")\n\npackage com.braze.ui.support\n\nimport android.content.ComponentName\nimport android.content.Con"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/support/ViewUtils.kt",
    "chars": 4964,
    "preview": "@file:JvmName(\"ViewUtils\")\n@file:Suppress(\"TooManyFunctions\")\n\npackage com.braze.ui.support\n\nimport android.app.Activity"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/widget/BannerImageCardView.java",
    "chars": 1813,
    "preview": "package com.braze.ui.widget;\n\nimport android.content.Context;\nimport android.widget.ImageView;\n\nimport com.braze.models."
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/widget/BaseCardView.kt",
    "chars": 8104,
    "preview": "package com.braze.ui.widget\n\nimport android.content.Context\nimport android.os.Bundle\nimport android.view.ViewTreeObserve"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/widget/CaptionedImageCardView.java",
    "chars": 2291,
    "preview": "package com.braze.ui.widget;\n\nimport android.content.Context;\nimport android.widget.ImageView;\nimport android.widget.Tex"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/widget/DefaultCardView.java",
    "chars": 801,
    "preview": "package com.braze.ui.widget;\n\nimport android.content.Context;\n\nimport com.braze.models.cards.Card;\nimport com.braze.ui.R"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/widget/ShortNewsCardView.java",
    "chars": 2031,
    "preview": "package com.braze.ui.widget;\n\nimport android.content.Context;\nimport android.widget.ImageView;\nimport android.widget.Tex"
  },
  {
    "path": "android-sdk-ui/src/main/java/com/braze/ui/widget/TextAnnouncementCardView.java",
    "chars": 1722,
    "preview": "package com.braze.ui.widget;\n\nimport android.content.Context;\nimport android.widget.TextView;\n\nimport com.braze.models.c"
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable/com_braze_inappmessage_close_button_selector.xml",
    "chars": 314,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <item and"
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable-nodpi/com_braze_card_background.xml",
    "chars": 1129,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <!-- Sh"
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable-nodpi/com_braze_content_card_background.xml",
    "chars": 1217,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <!-- Sh"
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable-nodpi/com_braze_content_card_scrim.xml",
    "chars": 378,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <item and"
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable-nodpi/com_braze_content_card_scrim_focused.xml",
    "chars": 353,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <!-- Ba"
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable-nodpi/com_braze_content_cards_rounded_corner_background.xml",
    "chars": 222,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\" android:shape=\""
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable-nodpi/com_braze_content_cards_unread_bar_background.xml",
    "chars": 452,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <!-- Ba"
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable-nodpi/com_braze_inappmessage_button_background.xml",
    "chars": 307,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android"
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable-nodpi/com_braze_inappmessage_icon_background.xml",
    "chars": 262,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android"
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable-nodpi/com_braze_inappmessage_modal_background.xml",
    "chars": 265,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android"
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable-nodpi/com_braze_inappmessage_slideup_background.xml",
    "chars": 263,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android"
  },
  {
    "path": "android-sdk-ui/src/main/res/drawable-nodpi-v21/com_braze_inappmessage_button_background.xml",
    "chars": 606,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ripple xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:colo"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_banner_image_card.xml",
    "chars": 409,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <ViewStub\n"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_banner_image_content_card.xml",
    "chars": 612,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      "
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_captioned_image_card.xml",
    "chars": 2086,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <ViewStub\n"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_captioned_image_content_card.xml",
    "chars": 1680,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      "
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_content_cards.xml",
    "chars": 582,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.swiperefreshlayout.widget.SwipeRefreshLayout\n  xmlns:android=\"http://sc"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_content_cards_activity.xml",
    "chars": 421,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    and"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_content_cards_empty.xml",
    "chars": 323,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        "
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_default_card.xml",
    "chars": 334,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <include lay"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_default_content_card.xml",
    "chars": 108,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout style=\"@style/Braze.ContentCards\">\n</RelativeLayout>\n"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_feed.xml",
    "chars": 2495,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<androidx.swiperefreshlayout.widget.SwipeRefreshLayout\n  xmlns:android=\"http://s"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_feed_activity.xml",
    "chars": 396,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    and"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_feed_footer.xml",
    "chars": 204,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<View xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\""
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_feed_header.xml",
    "chars": 204,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<View xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\""
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_feed_read_indicator_holder.xml",
    "chars": 365,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\"\n       android:"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_inappmessage_full.xml",
    "chars": 4955,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.braze.ui.inappmessage.views.InAppMessageFullView\n    xmlns:android=\"http://s"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_inappmessage_full_graphic.xml",
    "chars": 2983,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.braze.ui.inappmessage.views.InAppMessageFullView\n    xmlns:android=\"http://s"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_inappmessage_html.xml",
    "chars": 483,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.braze.ui.inappmessage.views.InAppMessageHtmlView\n    xmlns:android=\"http://s"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_inappmessage_html_full.xml",
    "chars": 536,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.braze.ui.inappmessage.views.InAppMessageHtmlFullView\n    xmlns:android=\"http"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_inappmessage_modal.xml",
    "chars": 4685,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.braze.ui.inappmessage.views.InAppMessageModalView\n    xmlns:android=\"http://"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_inappmessage_modal_graphic.xml",
    "chars": 3980,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.braze.ui.inappmessage.views.InAppMessageModalView\n    xmlns:android=\"http://"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_inappmessage_slideup.xml",
    "chars": 1346,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.braze.ui.inappmessage.views.InAppMessageSlideupView\n    xmlns:android=\"http:"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_notification_inline_image.xml",
    "chars": 2402,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  xmlns:"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_push_inline_image_constrained.xml",
    "chars": 1210,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  xmlns:"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_push_story_one_image.xml",
    "chars": 1545,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n         "
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_short_news_card.xml",
    "chars": 2160,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\"\n       xmlns:to"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_short_news_content_card.xml",
    "chars": 1625,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      "
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_stubbed_feed_image_view.xml",
    "chars": 1007,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  "
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_text_announcement_card.xml",
    "chars": 1642,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\"\n       xmlns:to"
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_text_announcement_content_card.xml",
    "chars": 1279,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      "
  },
  {
    "path": "android-sdk-ui/src/main/res/layout/com_braze_webview_activity.xml",
    "chars": 475,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n     "
  },
  {
    "path": "android-sdk-ui/src/main/res/layout-land/com_braze_inappmessage_html_full.xml",
    "chars": 538,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.braze.ui.inappmessage.views.InAppMessageHtmlFullView\n    xmlns:android=\"http"
  },
  {
    "path": "android-sdk-ui/src/main/res/values/attrs.xml",
    "chars": 643,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <declare-styleable name=\"com.braze.ui.feed.BrazeImageSwitcher\">\n   "
  },
  {
    "path": "android-sdk-ui/src/main/res/values/colors.xml",
    "chars": 2848,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <color name=\"com_braze_inappmessage_icon\">@android:color/white</col"
  },
  {
    "path": "android-sdk-ui/src/main/res/values/dimens.xml",
    "chars": 3134,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <dimen name=\"com_braze_feed_max_width\">380.0dp</dimen>\n\n  <dimen na"
  },
  {
    "path": "android-sdk-ui/src/main/res/values/ids.xml",
    "chars": 396,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <!-- Application specific identifiers for View tagging, required fo"
  },
  {
    "path": "android-sdk-ui/src/main/res/values/strings.xml",
    "chars": 845,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <!-- News feed -->\n  <string name=\"com_braze_feed_empty\">We have no"
  },
  {
    "path": "android-sdk-ui/src/main/res/values/styles.xml",
    "chars": 46660,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <style name=\"Braze\"/>\n\n  <!-- In-app Message -->\n  <style name=\"Bra"
  },
  {
    "path": "android-sdk-ui/src/main/res/values-ar/strings.xml",
    "chars": 464,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <!-- News feed -->\n  <string name=\"com_braze_feed_empty\">ليس لدينا "
  },
  {
    "path": "android-sdk-ui/src/main/res/values-cs/strings.xml",
    "chars": 482,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <!-- News feed -->\n  <string name=\"com_braze_feed_empty\">Nemáme žád"
  },
  {
    "path": "android-sdk-ui/src/main/res/values-da/strings.xml",
    "chars": 461,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <!-- News feed -->\n  <string name=\"com_braze_feed_empty\">Vi har ing"
  },
  {
    "path": "android-sdk-ui/src/main/res/values-de/strings.xml",
    "chars": 520,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <!-- News feed -->\n  <string name=\"com_braze_feed_empty\">Derzeit si"
  },
  {
    "path": "android-sdk-ui/src/main/res/values-es/strings.xml",
    "chars": 509,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <!-- News feed -->\n  <string name=\"com_braze_feed_empty\">No tenemos"
  },
  {
    "path": "android-sdk-ui/src/main/res/values-es-rES/strings.xml",
    "chars": 491,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <!-- News feed -->\n  <string name=\"com_braze_feed_empty\">No tenemos"
  },
  {
    "path": "android-sdk-ui/src/main/res/values-et/strings.xml",
    "chars": 469,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <!-- News feed -->\n  <string name=\"com_braze_feed_empty\">Uuendusi p"
  },
  {
    "path": "android-sdk-ui/src/main/res/values-fi/strings.xml",
    "chars": 472,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <!-- News feed -->\n  <string name=\"com_braze_feed_empty\">Päivityksi"
  },
  {
    "path": "android-sdk-ui/src/main/res/values-fr/strings.xml",
    "chars": 505,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <!-- News feed -->\n  <string name=\"com_braze_feed_empty\">Aucune mis"
  }
]

// ... and 272 more files (download for full content)

About this extraction

This page contains the full source code of the Appboy/appboy-android-sdk GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 472 files (1.4 MB), approximately 350.3k tokens, and a symbol index with 301 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!