]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/commitdiff
Fix a rare crash in `onBackPresses()`. https://redmine.stoutner.com/issues/651
authorSoren Stoutner <soren@stoutner.com>
Tue, 22 Dec 2020 00:14:52 +0000 (17:14 -0700)
committerSoren Stoutner <soren@stoutner.com>
Tue, 22 Dec 2020 00:14:52 +0000 (17:14 -0700)
app/build.gradle
app/src/free/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.java
app/src/free/java/com/stoutner/privacybrowser/helpers/AdHelper.java
app/src/free/res/layout/adview.xml
app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
gradle.properties

index 30954025b2a20e4a74143270b7dd2fd1b5f698e1..be417985cde3e36889e037391f7531a98d53df3d 100644 (file)
@@ -94,6 +94,6 @@ dependencies {
     // Include the Google material library.
     implementation 'com.google.android.material:material:1.2.1'
 
-    // Only compile Firebase ads for the free flavor.
-    freeImplementation 'com.google.firebase:firebase-ads:19.6.0'
+    // Only compile AdMob ads for the free flavor.
+    freeImplementation 'com.google.android.gms:play-services-ads:19.6.0'
 }
\ No newline at end of file
index 60d507b0e8cd6bae2b18d4f387d908535825598d..d8d81e34f3e10c6679d1d7253ca2cd5e58b3a7bc 100644 (file)
@@ -87,8 +87,8 @@ public class AdConsentDialog extends DialogFragment {
             // Update the ad consent database.
             adConsentDatabaseHelper.updateAdConsent(true);
 
-            // Load an ad.  `getContext()` can be used instead of `getActivity.getApplicationContext()` on the minimum API >= 23.
-            AdHelper.loadAd(getActivity().findViewById(R.id.adview), getActivity().getApplicationContext(), getString(R.string.ad_unit_id));
+            // Load an ad.  `getContext()` can be used instead of `getActivity.getApplicationContext()` once the minimum API >= 23.
+            AdHelper.loadAd(getActivity().findViewById(R.id.adview), getActivity().getApplicationContext(), getActivity(), getString(R.string.ad_unit_id));
         });
 
         // Create an alert dialog from the alert dialog builder.
index 60f22aaccc91bd9e5d4d3402b4057a25ad7d6ed5..4d4575d5e78949f8736e56d6a9bbca25a078fc28 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2016-2019 Soren Stoutner <soren@stoutner.com>.
+ * Copyright © 2016-2020 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
  *
 
 package com.stoutner.privacybrowser.helpers;
 
+import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.view.Display;
 import android.view.View;
 import android.widget.RelativeLayout;
 
@@ -32,16 +35,17 @@ import com.google.android.gms.ads.AdRequest;
 import com.google.android.gms.ads.AdSize;
 import com.google.android.gms.ads.AdView;
 import com.google.android.gms.ads.MobileAds;
+
 import com.stoutner.privacybrowser.R;
 import com.stoutner.privacybrowser.dialogs.AdConsentDialog;
 
 public class AdHelper {
     private static boolean initialized;
 
-    public static void initializeAds(View view, Context applicationContext, FragmentManager fragmentManager, String googleAppId, String adUnitId) {
+    public static void initializeAds(View view, Context applicationContext, Activity activity, FragmentManager fragmentManager, String adUnitId) {
         if (!initialized) {  // This is the first run.
             // Initialize mobile ads.
-            MobileAds.initialize(applicationContext, googleAppId);
+            MobileAds.initialize(applicationContext);
 
             // Initialize the bookmarks database helper.  The `0` specifies a database version, but that is ignored and set instead using a constant in `AdConsentDatabaseHelper`.
             AdConsentDatabaseHelper adConsentDatabaseHelper = new AdConsentDatabaseHelper(applicationContext, null, null, 0);
@@ -51,45 +55,78 @@ public class AdHelper {
 
             // Display the ad consent dialog if needed.
             if (!adConsentGranted) {  // Ad consent has not been granted.
-                // Display the ad consent dialog.
+                // Instantiate the ad consent dialog.
                 DialogFragment adConsentDialogFragment = new AdConsentDialog();
+
+                // Display the ad consent dialog.
                 adConsentDialogFragment.show(fragmentManager, "Ad Consent");
             } else {  // Ad consent has been granted.
                 // Load an ad.
-                loadAd(view, applicationContext, adUnitId);
+                loadAd(view, applicationContext, activity, adUnitId);
             }
 
             // Set the initialized variable to true so this section doesn't run again.
             initialized = true;
         } else {  // Ads have previously been initialized.
             // Load an ad.
-            loadAd(view, applicationContext, adUnitId);
+            loadAd(view, applicationContext, activity, adUnitId);
         }
     }
 
-    public static void loadAd(View view, Context applicationContext, String adUnitId) {
+    public static void loadAd(View view, Context applicationContext, Activity activity, String adUnitId) {
         // Cast the generic view to an AdView.
         AdView adView = (AdView) view;
 
         // Save the layout parameters.  They are used when programatically recreating the ad below.
         RelativeLayout.LayoutParams adViewLayoutParameters = (RelativeLayout.LayoutParams) adView.getLayoutParams();
 
-        // Remove the AdView.
+        // Get a handle for the ad view parent.
         RelativeLayout adViewParentLayout = (RelativeLayout) adView.getParent();
+
+        // Remove the AdView.
         adViewParentLayout.removeView(adView);
 
-        // Setup the new AdView.  This is necessary because the size of the banner ad can change on rotate.
+        // Create a new AdView.  This is necessary because the size can change when the device is rotated.
         adView = new AdView(applicationContext);
-        adView.setAdSize(AdSize.SMART_BANNER);
+
+        // Set the ad unit ID.
         adView.setAdUnitId(adUnitId);
+
+        //  Set the view ID.
         adView.setId(R.id.adview);
+
+        // Set the layout parameters.
         adView.setLayoutParams(adViewLayoutParameters);
 
-        // Display the new AdView.
+        // Add the new ad view to the parent layout.
         adViewParentLayout.addView(adView);
 
-        // Only request non-personalized ads.  https://developers.google.com/ad-manager/mobile-ads-sdk/android/eu-consent#forward_consent_to_the_google_mobile_ads_sdk
+        // Get a handle for the display.
+        Display display = activity.getWindowManager().getDefaultDisplay();
+
+        // Initialize a display metrics.
+        DisplayMetrics displayMetrics = new DisplayMetrics();
+
+        // Get the display metrics from the display.
+        display.getMetrics(displayMetrics);
+
+        // Get the width pixels and the density.
+        float widthPixels = displayMetrics.widthPixels;
+        float density = displayMetrics.density;
+
+        // Calculate the ad width.
+        int adWidth = (int) (widthPixels / density);
+
+        // Get the ad size.  This line should be enabled once Firebase Ads is updated to 20.0.0.
+        AdSize adSize = AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(applicationContext, adWidth);
+
+        // Set the ad size on the adView.
+        adView.setAdSize(adSize);
+
+        // Create an ad settings bundle.
         Bundle adSettingsBundle = new Bundle();
+
+        // Only request non-personalized ads.  https://developers.google.com/ad-manager/mobile-ads-sdk/android/eu-consent#forward_consent_to_the_google_mobile_ads_sdk
         adSettingsBundle.putString("npa", "1");
 
         // Build the ad request.
@@ -99,6 +136,7 @@ public class AdHelper {
         adView.loadAd(adRequest);
     }
 
+    // This method exists here for the sake of consistency with the following two methods.
     public static void hideAd(View view) {
         // Cast the generic view to an AdView.
         AdView adView = (AdView) view;
@@ -107,6 +145,7 @@ public class AdHelper {
         adView.setVisibility(View.GONE);
     }
 
+    // This method exists here so that the main WebView activity doesn't need to import `com.google.android.gms.ads.AdView`.
     public static void pauseAd(View view) {
         // Cast The generic view to an AdView.
         AdView adView = (AdView) view;
@@ -115,6 +154,7 @@ public class AdHelper {
         adView.pause();
     }
 
+    // This method exists here so that the main WebView activity doesn't need to import `com.google.android.gms.ads.AdView`.
     public static void resumeAd(View view) {
         // Cast the generic view to an AdView.
         AdView adView = (AdView) view;
index 28d09acb5a529fc439be252c9f2d59b91bc23150..d573bda842e7db5d318a4d8c2b81566f0beaa5ff 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright © 2016-2017,2019 Soren Stoutner <soren@stoutner.com>.
+  Copyright © 2016-2017,2019-2020 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
 
@@ -25,5 +25,4 @@
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
     android:layout_alignParentBottom="true"
-    ads:adSize="SMART_BANNER"
     ads:adUnitId="@string/ad_unit_id" />
\ No newline at end of file
index 422bb5ef3e2da4df60e60bf0de128c19577bf222..5b39fdcba08cabd6fd0f3e9d2c1d4d07761fb4cc 100644 (file)
@@ -321,14 +321,18 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private String saveWebpageFilePath;
 
     // Declare the class views.
+    private FrameLayout rootFrameLayout;
     private DrawerLayout drawerLayout;
+    private RelativeLayout mainContentRelativeLayout;
     private AppBarLayout appBarLayout;
     private Toolbar toolbar;
+    private ActionBar actionBar;
     private LinearLayout findOnPageLinearLayout;
     private LinearLayout tabsLinearLayout;
     private TabLayout tabLayout;
     private SwipeRefreshLayout swipeRefreshLayout;
     private ViewPager webViewPager;
+    private FrameLayout fullScreenVideoFrameLayout;
 
     // Declare the class menus.
     private Menu optionsMenu;
@@ -445,7 +449,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         setContentView(R.layout.main_framelayout);
 
         // Get handles for the views.
+        rootFrameLayout = findViewById(R.id.root_framelayout);
         drawerLayout = findViewById(R.id.drawerlayout);
+        mainContentRelativeLayout = findViewById(R.id.main_content_relativelayout);
         appBarLayout = findViewById(R.id.appbar_layout);
         toolbar = findViewById(R.id.toolbar);
         findOnPageLinearLayout = findViewById(R.id.find_on_page_linearlayout);
@@ -453,6 +459,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         tabLayout = findViewById(R.id.tablayout);
         swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
         webViewPager = findViewById(R.id.webviewpager);
+        fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout);
 
         // Get a handle for the navigation view.
         NavigationView navigationView = findViewById(R.id.navigationview);
@@ -476,9 +483,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         appCompatDelegate.setSupportActionBar(toolbar);
 
         // Get a handle for the action bar.
-        ActionBar actionBar = appCompatDelegate.getSupportActionBar();
+        actionBar = appCompatDelegate.getSupportActionBar();
 
-        // This is needed to get rid of the Android Studio warning that the action bar might be null.
+        // Remove the incorrect lint warning below that the action bar might be null.
         assert actionBar != null;
 
         // Add the custom layout, which shows the URL text bar.
@@ -678,9 +685,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Reapply any system UI flags and the ad in the free flavor.
         if (displayingFullScreenVideo || inFullScreenBrowsingMode) {  // The system is displaying a website or a video in full screen mode.
-            // Get a handle for the root frame layouts.
-            FrameLayout rootFrameLayout = findViewById(R.id.root_framelayout);
-
             /* Hide the system bars.
              * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
              * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
@@ -690,8 +694,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             rootFrameLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
                     View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
         } else if (BuildConfig.FLAVOR.contentEquals("free")) {  // The system in not in full screen mode.
+            // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+            View adView = findViewById(R.id.adview);
+
             // Resume the ad.
-            AdHelper.resumeAd(findViewById(R.id.adview));
+            AdHelper.resumeAd(adView);
         }
     }
 
@@ -724,8 +731,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Pause the ad or it will continue to consume resources in the background on the free flavor.
         if (BuildConfig.FLAVOR.contentEquals("free")) {
+            // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+            View adView = findViewById(R.id.adview);
+
             // Pause the ad.
-            AdHelper.pauseAd(findViewById(R.id.adview));
+            AdHelper.pauseAd(adView);
         }
     }
 
@@ -807,9 +817,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Store a handle for the options menu so it can be used by `onOptionsItemSelected()` and `updatePrivacyIcons()`.
         optionsMenu = menu;
 
-        // Set the initial status of the privacy icons.  `false` does not call `invalidateOptionsMenu` as the last step.
-        updatePrivacyIcons(false);
-
         // Get handles for the class menu items.
         optionsPrivacyMenuItem = menu.findItem(R.id.javascript);
         optionsRefreshMenuItem = menu.findItem(R.id.refresh);
@@ -859,6 +866,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         MenuItem bookmarksMenuItem = menu.findItem(R.id.bookmarks);
         MenuItem adConsentMenuItem = menu.findItem(R.id.ad_consent);
 
+        // Set the initial status of the privacy icons.  `false` does not call `invalidateOptionsMenu` as the last step.
+        updatePrivacyIcons(false);
+
         // Only display third-party cookies if API >= 21
         optionsThirdPartyCookiesMenuItem.setVisible(Build.VERSION.SDK_INT >= 21);
 
@@ -2139,8 +2149,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Reload the ad for the free flavor if not in full screen mode.
         if (BuildConfig.FLAVOR.contentEquals("free") && !inFullScreenBrowsingMode) {
+            // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+            View adView = findViewById(R.id.adview);
+
             // Reload the ad.  The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
-            AdHelper.loadAd(findViewById(R.id.adview), getApplicationContext(), getString(R.string.ad_unit_id));
+            // `getContext()` can be used instead of `getActivity.getApplicationContext()` once the minimum API >= 23.
+            AdHelper.loadAd(adView, getApplicationContext(), this, getString(R.string.ad_unit_id));
         }
 
         // `invalidateOptionsMenu` should recalculate the number of action buttons from the menu to display on the app bar, but it doesn't because of the this bug:
@@ -2681,11 +2695,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // close the bookmarks drawer.
             drawerLayout.closeDrawer(GravityCompat.END);
         } else if (displayingFullScreenVideo) {  // A full screen video is shown.
-            // Get a handle for the layouts.
-            FrameLayout rootFrameLayout = findViewById(R.id.root_framelayout);
-            RelativeLayout mainContentRelativeLayout = findViewById(R.id.main_content_relativelayout);
-            FrameLayout fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout);
-
             // Re-enable the screen timeout.
             fullScreenVideoFrameLayout.setKeepScreenOn(false);
 
@@ -2708,7 +2717,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) {  // Privacy Browser is currently in full screen browsing mode.
                 // Hide the banner ad in the free flavor.
                 if (BuildConfig.FLAVOR.contentEquals("free")) {
-                    AdHelper.hideAd(findViewById(R.id.adview));
+                    // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+                    View adView = findViewById(R.id.adview);
+
+                    // Hide the banner ad.
+                    AdHelper.hideAd(adView);
                 }
 
                 /* Hide the system bars.
@@ -2732,8 +2745,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             // Reload the ad for the free flavor if not in full screen mode.
             if (BuildConfig.FLAVOR.contentEquals("free") && !inFullScreenBrowsingMode) {
-                // Reload the ad.
-                AdHelper.loadAd(findViewById(R.id.adview), getApplicationContext(), getString(R.string.ad_unit_id));
+                // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+                View adView = findViewById(R.id.adview);
+
+                // Reload the ad.  `getContext()` can be used instead of `getActivity.getApplicationContext()` once the minimum API >= 23.
+                AdHelper.loadAd(adView, getApplicationContext(), this, getString(R.string.ad_unit_id));
             }
         } else if (currentWebView.canGoBack()) {  // There is at least one item in the current WebView history.
             // Get the current web back forward list.
@@ -3654,16 +3670,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             searchURL = searchString;
         }
 
-        // Get a handle for the app compat delegate.
-        AppCompatDelegate appCompatDelegate = getDelegate();
-
-        // Get handles for the views that need to be modified.
-        FrameLayout rootFrameLayout = findViewById(R.id.root_framelayout);
-        ActionBar actionBar = appCompatDelegate.getSupportActionBar();
-
-        // Remove the incorrect lint warning below that the action bar might be null.
-        assert actionBar != null;
-
         // Apply the proxy.
         applyProxy(false);
 
@@ -3741,7 +3747,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             // Hide the banner ad in the free flavor.
             if (BuildConfig.FLAVOR.contentEquals("free")) {
-                AdHelper.hideAd(findViewById(R.id.adview));
+                // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+                View adView = findViewById(R.id.adview);
+
+                // Hide the banner ad.
+                AdHelper.hideAd(adView);
             }
 
             /* Hide the system bars.
@@ -3764,8 +3774,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             // Show the banner ad in the free flavor.
             if (BuildConfig.FLAVOR.contentEquals("free")) {
+                // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+                View adView = findViewById(R.id.adview);
+
                 // Initialize the ads.  If this isn't the first run, `loadAd()` will be automatically called instead.
-                AdHelper.initializeAds(findViewById(R.id.adview), getApplicationContext(), getSupportFragmentManager(), getString(R.string.google_app_id), getString(R.string.ad_unit_id));
+                // `getContext()` can be used instead of `getActivity.getApplicationContext()` once the minimum API >= 23.
+                AdHelper.initializeAds(adView, getApplicationContext(), this, getSupportFragmentManager(), getString(R.string.ad_unit_id));
             }
 
             // Remove the `SYSTEM_UI` flags from the root frame layout.
@@ -5260,19 +5274,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             }
         }
 
-        // Get a handle for the app compat delegate.
-        AppCompatDelegate appCompatDelegate = getDelegate();
-
         // Get handles for the activity views.
-        FrameLayout rootFrameLayout = findViewById(R.id.root_framelayout);
-        RelativeLayout mainContentRelativeLayout = findViewById(R.id.main_content_relativelayout);
-        ActionBar actionBar = appCompatDelegate.getSupportActionBar();
-        LinearLayout tabsLinearLayout = findViewById(R.id.tabs_linearlayout);
         EditText urlEditText = findViewById(R.id.url_edittext);
-        SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
-
-        // Remove the incorrect lint warning below that the action bar might be null.
-        assert actionBar != null;
 
         // Get a handle for the activity
         Activity activity = this;
@@ -5349,7 +5352,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // Hide the banner ad in the free flavor.
                         if (BuildConfig.FLAVOR.contentEquals("free")) {
-                            AdHelper.hideAd(findViewById(R.id.adview));
+                            // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+                            View adView = findViewById(R.id.adview);
+
+                            // Hide the banner ad.
+                            AdHelper.hideAd(adView);
                         }
 
                         /* Hide the system bars.
@@ -5387,8 +5394,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // Show the banner ad in the free flavor.
                         if (BuildConfig.FLAVOR.contentEquals("free")) {
-                            // Reload the ad.
-                            AdHelper.loadAd(findViewById(R.id.adview), getApplicationContext(), getString(R.string.ad_unit_id));
+                            // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+                            View adView = findViewById(R.id.adview);
+
+                            // Reload the ad.  `getContext()` can be used instead of `getActivity.getApplicationContext()` once the minimum API >= 23.
+                            AdHelper.loadAd(adView, getApplicationContext(), activity, getString(R.string.ad_unit_id));
                         }
 
                         // Remove the `SYSTEM_UI` flags from the root frame layout.
@@ -5603,16 +5613,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Enter full screen video.
             @Override
             public void onShowCustomView(View video, CustomViewCallback callback) {
-                // Get a handle for the full screen video frame layout.
-                FrameLayout fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout);
-
                 // Set the full screen video flag.
                 displayingFullScreenVideo = true;
 
                 // Pause the ad if this is the free flavor.
                 if (BuildConfig.FLAVOR.contentEquals("free")) {
+                    // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+                    View adView = findViewById(R.id.adview);
+
                     // The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
-                    AdHelper.pauseAd(findViewById(R.id.adview));
+                    AdHelper.pauseAd(adView);
                 }
 
                 // Hide the keyboard.
@@ -5646,9 +5656,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Exit full screen video.
             @Override
             public void onHideCustomView() {
-                // Get a handle for the full screen video frame layout.
-                FrameLayout fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout);
-
                 // Re-enable the screen timeout.
                 fullScreenVideoFrameLayout.setKeepScreenOn(false);
 
@@ -5680,7 +5687,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                     // Hide the banner ad in the free flavor.
                     if (BuildConfig.FLAVOR.contentEquals("free")) {
-                        AdHelper.hideAd(findViewById(R.id.adview));
+                        // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+                        View adView = findViewById(R.id.adview);
+
+                        // Hide the banner ad.
+                        AdHelper.hideAd(adView);
                     }
 
                     /* Hide the system bars.
@@ -5698,8 +5709,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // Reload the ad for the free flavor if not in full screen mode.
                 if (BuildConfig.FLAVOR.contentEquals("free") && !inFullScreenBrowsingMode) {
-                    // Reload the ad.
-                    AdHelper.loadAd(findViewById(R.id.adview), getApplicationContext(), getString(R.string.ad_unit_id));
+                    // Get a handle for the ad view.  This cannot be a class variable because it changes with each ad load.
+                    View adView = findViewById(R.id.adview);
+
+                    // Reload the ad.  `getContext()` can be used instead of `getActivity.getApplicationContext()` once the minimum API >= 23.
+                    AdHelper.loadAd(adView, getApplicationContext(), activity, getString(R.string.ad_unit_id));
                 }
             }
 
index eda7fe88d54b3f6dd16263c58b92837dd7fad2e9..e631854fc4353a20b07d635a06cb0988177e0d80 100644 (file)
@@ -34,5 +34,5 @@ org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
 # Use AndroidX.
 android.useAndroidX=true
 
-# Automatically convert third-party libraries to use AndroidX.  This is necessary for Firebase Ads in the free flavor.
+# Automatically convert third-party libraries to use AndroidX.  This is necessary for AdMob Ads in the free flavor.
 android.enableJetifier=true