From 568ac6354411aa26c42077d2b80f8770f6e64695 Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Mon, 31 May 2021 12:22:56 -0700 Subject: [PATCH] Convert the flavor specific Java classes to Kotlin. https://redmine.stoutner.com/issues/719 --- .../dialogs/AdConsentDialog.java | 139 -------------- .../privacybrowser/dialogs/AdConsentDialog.kt | 116 ++++++++++++ .../helpers/AdConsentDatabaseHelper.java | 110 ----------- .../helpers/AdConsentDatabaseHelper.kt | 92 +++++++++ .../privacybrowser/helpers/AdHelper.java | 165 ---------------- .../privacybrowser/helpers/AdHelper.kt | 176 ++++++++++++++++++ app/src/main/assets/de/about_changelog.html | 2 +- app/src/main/assets/en/about_changelog.html | 2 +- app/src/main/assets/es/about_changelog.html | 2 +- app/src/main/assets/fr/about_changelog.html | 2 +- app/src/main/assets/it/about_changelog.html | 2 +- .../main/assets/pt-rBR/about_changelog.html | 2 +- .../assets/pt-rBR/about_contributors.html | 2 + .../main/assets/pt-rBR/about_licenses.html | 2 + app/src/main/assets/pt-rBR/about_links.html | 2 + .../main/assets/pt-rBR/about_permissions.html | 2 + .../assets/pt-rBR/about_privacy_policy.html | 2 + app/src/main/assets/ru/about_changelog.html | 2 +- app/src/main/assets/tr/about_changelog.html | 2 +- .../dialogs/MoveToFolderDialog.kt | 6 +- .../privacybrowser/dialogs/OpenDialog.kt | 6 +- .../dialogs/PinnedMismatchDialog.kt | 6 +- .../dialogs/ProxyNotInstalledDialog.kt | 6 +- .../privacybrowser/dialogs/SaveDialog.kt | 18 +- .../dialogs/SaveWebpageDialog.kt | 18 +- .../dialogs/ViewRequestDialog.kt | 6 +- app/src/main/res/values-night-v23/styles.xml | 23 ++- app/src/main/res/values-night-v27/styles.xml | 23 ++- app/src/main/res/values-night/styles.xml | 23 ++- app/src/main/res/values-v23/styles.xml | 23 ++- app/src/main/res/values-v27/styles.xml | 23 ++- app/src/main/res/values/attrs.xml | 10 +- app/src/main/res/values/styles.xml | 23 ++- ...dConsentDialog.java => AdConsentDialog.kt} | 9 +- .../helpers/{AdHelper.java => AdHelper.kt} | 33 ++-- 35 files changed, 542 insertions(+), 538 deletions(-) delete mode 100644 app/src/free/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.java create mode 100644 app/src/free/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.kt delete mode 100644 app/src/free/java/com/stoutner/privacybrowser/helpers/AdConsentDatabaseHelper.java create mode 100644 app/src/free/java/com/stoutner/privacybrowser/helpers/AdConsentDatabaseHelper.kt delete mode 100644 app/src/free/java/com/stoutner/privacybrowser/helpers/AdHelper.java create mode 100644 app/src/free/java/com/stoutner/privacybrowser/helpers/AdHelper.kt rename app/src/standard/java/com/stoutner/privacybrowser/dialogs/{AdConsentDialog.java => AdConsentDialog.kt} (73%) rename app/src/standard/java/com/stoutner/privacybrowser/helpers/{AdHelper.java => AdHelper.kt} (58%) diff --git a/app/src/free/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.java b/app/src/free/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.java deleted file mode 100644 index d8d81e34..00000000 --- a/app/src/free/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright © 2018-2020 Soren Stoutner . - * - * This file is part of Privacy Browser . - * - * Privacy Browser is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Privacy Browser is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Privacy Browser. If not, see . - */ - -package com.stoutner.privacybrowser.dialogs; - -import android.app.Dialog; -import android.content.DialogInterface; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.view.WindowManager; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; -import androidx.fragment.app.DialogFragment; - -import com.stoutner.privacybrowser.R; -import com.stoutner.privacybrowser.helpers.AdConsentDatabaseHelper; -import com.stoutner.privacybrowser.helpers.AdHelper; - -public class AdConsentDialog extends DialogFragment { - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - // Use a builder to create the alert dialog. - AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(requireContext(), R.style.PrivacyBrowserAlertDialog); - - // Get the current theme status. - int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; - - // Set the icon according to the theme. - if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) { - dialogBuilder.setIcon(R.drawable.block_ads_enabled_night); - } else { - dialogBuilder.setIcon(R.drawable.block_ads_enabled_day); - } - - // Remove the incorrect lint warning below that `getApplicationContext()` might be null. - assert getActivity() != null; - - // Initialize the bookmarks database helper. The `0` specifies a database version, but that is ignored and set instead using a constant in `AdConsentDatabaseHelper`. - // `getContext()` can be used instead of `getActivity.getApplicationContext()` when the minimum API >= 23. - AdConsentDatabaseHelper adConsentDatabaseHelper = new AdConsentDatabaseHelper(getActivity().getApplicationContext(), null, null, 0); - - // Set the title. - dialogBuilder.setTitle(R.string.ad_consent); - - // Set the text. - dialogBuilder.setMessage(R.string.ad_consent_text); - - // Configure the close button. - dialogBuilder.setNegativeButton(R.string.close_browser, (DialogInterface dialog, int which) -> { - // Update the ad consent database. - adConsentDatabaseHelper.updateAdConsent(false); - - // Close the browser. `finishAndRemoveTask` also removes Privacy Browser from the recent app list. - if (Build.VERSION.SDK_INT >= 21) { - getActivity().finishAndRemoveTask(); - } else { - getActivity().finish(); - } - - // Remove the terminated program from RAM. The status code is `0`. - System.exit(0); - }); - - // Configure the accept button. - dialogBuilder.setPositiveButton(R.string.accept_ads, (DialogInterface dialog, int which) -> { - // Update the ad consent database. - adConsentDatabaseHelper.updateAdConsent(true); - - // 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. - AlertDialog alertDialog = dialogBuilder.create(); - - // Get a handle for the shared preferences. - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext()); - - // Get the screenshot preference. - boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false); - - // Disable screenshots if not allowed. - if (!allowScreenshots) { - // Remove the warning below that `getWindow()` might be null. - assert alertDialog.getWindow() != null; - - // Disable screenshots. - alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); - } - - // Return the alert dialog. - return alertDialog; - } - - // Close Privacy Browser Free if the dialog is cancelled without selecting a button (by tapping on the background). - @Override - public void onCancel(@NonNull DialogInterface dialogInterface) { - // Remove the incorrect lint warning below that `getApplicationContext()` might be null. - assert getActivity() != null; - - // Initialize the bookmarks database helper. The `0` specifies a database version, but that is ignored and set instead using a constant in `AdConsentDatabaseHelper`. - // `getContext()` can be used instead of `getActivity.getApplicationContext()` when the minimum API >= 23. - AdConsentDatabaseHelper adConsentDatabaseHelper = new AdConsentDatabaseHelper(getActivity().getApplicationContext(), null, null, 0); - - // Update the ad consent database. - adConsentDatabaseHelper.updateAdConsent(false); - - // Close the browser. `finishAndRemoveTask()` also removes Privacy Browser from the recent app list. - if (Build.VERSION.SDK_INT >= 21) { - getActivity().finishAndRemoveTask(); - } else { - getActivity().finish(); - } - - // Remove the terminated program from RAM. The status code is `0`. - System.exit(0); - } -} \ No newline at end of file diff --git a/app/src/free/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.kt b/app/src/free/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.kt new file mode 100644 index 00000000..f22367cf --- /dev/null +++ b/app/src/free/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.kt @@ -0,0 +1,116 @@ +/* + * Copyright © 2018-2021 Soren Stoutner . + * + * This file is part of Privacy Browser . + * + * Privacy Browser is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Browser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Browser. If not, see . + */ + +package com.stoutner.privacybrowser.dialogs + +import android.app.Dialog +import android.content.DialogInterface +import android.os.Build +import android.os.Bundle +import android.view.WindowManager + +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.DialogFragment +import androidx.preference.PreferenceManager + +import com.stoutner.privacybrowser.R +import com.stoutner.privacybrowser.helpers.AdConsentDatabaseHelper +import com.stoutner.privacybrowser.helpers.AdHelper +import kotlin.system.exitProcess + +class AdConsentDialog : DialogFragment() { + // Declare the class variables. + private lateinit var adConsentDatabaseHelper: AdConsentDatabaseHelper + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + // Use a builder to create the alert dialog. + val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.PrivacyBrowserAlertDialog) + + // Set the icon according to the theme. + dialogBuilder.setIconAttribute(R.attr.blockAdsBlueIcon) + + // Initialize the bookmarks database helper. + adConsentDatabaseHelper = AdConsentDatabaseHelper(requireContext()) + + // Set the title. + dialogBuilder.setTitle(R.string.ad_consent) + + // Set the text. + dialogBuilder.setMessage(R.string.ad_consent_text) + + // Set the close browser button. + dialogBuilder.setNegativeButton(R.string.close_browser) { _: DialogInterface?, _: Int -> + // Update the ad consent database. + adConsentDatabaseHelper.updateAdConsent(false) + + // Close the browser. `finishAndRemoveTask` also removes Privacy Browser from the recent app list. + if (Build.VERSION.SDK_INT >= 21) { + requireActivity().finishAndRemoveTask() + } else { + requireActivity().finish() + } + + // Remove the terminated program from RAM. The status code is `0`. + exitProcess(0) + } + + // Set the accept ads button. + dialogBuilder.setPositiveButton(R.string.accept_ads) { _: DialogInterface?, _: Int -> + // Update the ad consent database. + adConsentDatabaseHelper.updateAdConsent(true) + + // Load an ad. + AdHelper.loadAd(requireActivity().findViewById(R.id.adview), requireContext(), requireActivity(), getString(R.string.ad_unit_id)) + } + + // Create an alert dialog from the alert dialog builder. + val alertDialog = dialogBuilder.create() + + // Get a handle for the shared preferences. + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + + // Get the screenshot preference. + val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false) + + // Disable screenshots if not allowed. + if (!allowScreenshots) { + // Disable screenshots. + alertDialog.window!!.addFlags(WindowManager.LayoutParams.FLAG_SECURE) + } + + // Return the alert dialog. + return alertDialog + } + + // Close Privacy Browser Free if the dialog is cancelled without selecting a button (by tapping on the background). + override fun onCancel(dialogInterface: DialogInterface) { + // Update the ad consent database. + adConsentDatabaseHelper.updateAdConsent(false) + + // Close the browser. `finishAndRemoveTask()` also removes Privacy Browser from the recent app list. + if (Build.VERSION.SDK_INT >= 21) { + requireActivity().finishAndRemoveTask() + } else { + requireActivity().finish() + } + + // Remove the terminated program from RAM. The status code is `0`. + exitProcess(0) + } +} \ No newline at end of file diff --git a/app/src/free/java/com/stoutner/privacybrowser/helpers/AdConsentDatabaseHelper.java b/app/src/free/java/com/stoutner/privacybrowser/helpers/AdConsentDatabaseHelper.java deleted file mode 100644 index bbe480c1..00000000 --- a/app/src/free/java/com/stoutner/privacybrowser/helpers/AdConsentDatabaseHelper.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright © 2018 Soren Stoutner . - * - * This file is part of Privacy Browser . - * - * Privacy Browser is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Privacy Browser is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Privacy Browser. If not, see . - */ - -package com.stoutner.privacybrowser.helpers; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; - -public class AdConsentDatabaseHelper extends SQLiteOpenHelper { - private static final int SCHEMA_VERSION = 1; - private static final String AD_CONSENT_DATABASE = "ad_consent.db"; - private static final String AD_CONSENT_TABLE = "ad_consent"; - - private static final String _ID = "_id"; - private static final String AD_CONSENT = "ad_consent"; - - private static final String CREATE_AD_CONSENT_TABLE = "CREATE TABLE " + AD_CONSENT_TABLE + " (" + - _ID + " INTEGER PRIMARY KEY, " + - AD_CONSENT + " BOOLEAN)"; - - // Initialize the database. The lint warnings for the unused parameters are suppressed. - public AdConsentDatabaseHelper(Context context, @SuppressWarnings("UnusedParameters") String name, SQLiteDatabase.CursorFactory cursorFactory, @SuppressWarnings("UnusedParameters") int version) { - super(context, AD_CONSENT_DATABASE, cursorFactory, SCHEMA_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase adConsentDatabase) { - // Create the ad consent database. - adConsentDatabase.execSQL(CREATE_AD_CONSENT_TABLE); - - // Create an ad consent ContentValues. - ContentValues adConsentContentValues = new ContentValues(); - - // Populate the ad consent content values. - adConsentContentValues.put(AD_CONSENT, false); - - // Insert a new row. The second argument is `null`, which makes it so that a completely null row cannot be created. - adConsentDatabase.insert(AD_CONSENT_TABLE, null, adConsentContentValues); - } - - @Override - public void onUpgrade(SQLiteDatabase adConsentDatabase, int oldVersion, int newVersion) { - // Code for upgrading the database will be added here if the schema version ever increases above 1. - } - - // Check to see if ad consent has been granted. - public boolean isGranted() { - // Get a readable database handle. - SQLiteDatabase adConsentDatabase = this.getReadableDatabase(); - - // Get the ad consent cursor. - Cursor adConsentCursor = adConsentDatabase.rawQuery("SELECT * FROM " + AD_CONSENT_TABLE, null); - - // Move to the first entry. - adConsentCursor.moveToFirst(); - - // Get the ad consent boolean. - boolean adConsent = (adConsentCursor.getInt(adConsentCursor.getColumnIndex(AD_CONSENT)) == 1); - - // Close the cursor. - adConsentCursor.close(); - - // Close the database. - adConsentDatabase.close(); - - // Return the ad consent boolean. - return adConsent; - } - - // Update the ad consent. - public void updateAdConsent(boolean adConsent) { - // Get a writable database handle. - SQLiteDatabase adConsentDatabase = this.getWritableDatabase(); - - // Create an ad consent integer. - int adConsentInt; - - // Set the ad consent integer according to the boolean. - if (adConsent) { - adConsentInt = 1; - } else { - adConsentInt = 0; - } - - // Update the ad consent in the database. - adConsentDatabase.execSQL("UPDATE " + AD_CONSENT_TABLE + " SET " + AD_CONSENT + " = " + adConsentInt); - - // Close the database. - adConsentDatabase.close(); - } -} \ No newline at end of file diff --git a/app/src/free/java/com/stoutner/privacybrowser/helpers/AdConsentDatabaseHelper.kt b/app/src/free/java/com/stoutner/privacybrowser/helpers/AdConsentDatabaseHelper.kt new file mode 100644 index 00000000..8499d553 --- /dev/null +++ b/app/src/free/java/com/stoutner/privacybrowser/helpers/AdConsentDatabaseHelper.kt @@ -0,0 +1,92 @@ +/* + * Copyright © 2018,2021 Soren Stoutner . + * + * This file is part of Privacy Browser . + * + * Privacy Browser is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Browser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Browser. If not, see . + */ + +package com.stoutner.privacybrowser.helpers + +import android.content.ContentValues +import android.content.Context +import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteOpenHelper + +// Define the class constants. +private const val SCHEMA_VERSION = 1 +private const val AD_CONSENT_DATABASE = "ad_consent.db" +private const val AD_CONSENT_TABLE = "ad_consent" +private const val ID = "_id" +private const val AD_CONSENT = "ad_consent" +private const val CREATE_AD_CONSENT_TABLE = "CREATE TABLE $AD_CONSENT_TABLE ($ID INTEGER PRIMARY KEY, $AD_CONSENT BOOLEAN)" + +class AdConsentDatabaseHelper (context: Context) : SQLiteOpenHelper(context, AD_CONSENT_DATABASE, null, SCHEMA_VERSION) { + override fun onCreate(adConsentDatabase: SQLiteDatabase) { + // Create the ad consent table. + adConsentDatabase.execSQL(CREATE_AD_CONSENT_TABLE) + + // Create an ad consent content values. + val adConsentContentValues = ContentValues() + + // Populate the ad consent content values with the default data. + adConsentContentValues.put(AD_CONSENT, false) + + // Insert a new row. The second argument is `null`, which makes it so that a completely null row cannot be created. + adConsentDatabase.insert(AD_CONSENT_TABLE, null, adConsentContentValues) + } + + override fun onUpgrade(adConsentDatabase: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + // Code for upgrading the database will be added here if the schema version ever increases above 1. + } + + // Check to see if ad consent has been granted. + val isGranted: Boolean get() { + // Get a readable database handle. + val adConsentDatabase = this.readableDatabase + + // Get the ad consent cursor. + val adConsentCursor = adConsentDatabase.rawQuery("SELECT * FROM $AD_CONSENT_TABLE", null) + + // Move the cursor to the first entry. + adConsentCursor.moveToFirst() + + // Get the ad consent boolean. + val adConsent = adConsentCursor.getInt(adConsentCursor.getColumnIndex(AD_CONSENT)) == 1 + + // Close the cursor. + adConsentCursor.close() + + // Close the database. + adConsentDatabase.close() + + // Return the ad consent boolean. + return adConsent + } + + // Update the ad consent. + fun updateAdConsent(adConsent: Boolean) { + // Get a writable database handle. + val adConsentDatabase = this.writableDatabase + + // Set the ad consent integer according to the boolean. + val adConsentInt = if (adConsent) 1 else 0 + + // Update the ad consent in the database. + adConsentDatabase.execSQL("UPDATE $AD_CONSENT_TABLE SET $AD_CONSENT = $adConsentInt") + + // Close the database. + adConsentDatabase.close() + } +} \ No newline at end of file diff --git a/app/src/free/java/com/stoutner/privacybrowser/helpers/AdHelper.java b/app/src/free/java/com/stoutner/privacybrowser/helpers/AdHelper.java deleted file mode 100644 index 4d4575d5..00000000 --- a/app/src/free/java/com/stoutner/privacybrowser/helpers/AdHelper.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright © 2016-2020 Soren Stoutner . - * - * This file is part of Privacy Browser . - * - * Privacy Browser is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Privacy Browser is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Privacy Browser. If not, see . - */ - -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; - -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.FragmentManager; - -import com.google.ads.mediation.admob.AdMobAdapter; -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, Activity activity, FragmentManager fragmentManager, String adUnitId) { - if (!initialized) { // This is the first run. - // Initialize mobile ads. - 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); - - // Check to see if consent has been granted. - boolean adConsentGranted = adConsentDatabaseHelper.isGranted(); - - // Display the ad consent dialog if needed. - if (!adConsentGranted) { // Ad consent has not been granted. - // 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, 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, activity, 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(); - - // Get a handle for the ad view parent. - RelativeLayout adViewParentLayout = (RelativeLayout) adView.getParent(); - - // Remove the AdView. - adViewParentLayout.removeView(adView); - - // Create a new AdView. This is necessary because the size can change when the device is rotated. - adView = new AdView(applicationContext); - - // Set the ad unit ID. - adView.setAdUnitId(adUnitId); - - // Set the view ID. - adView.setId(R.id.adview); - - // Set the layout parameters. - adView.setLayoutParams(adViewLayoutParameters); - - // Add the new ad view to the parent layout. - adViewParentLayout.addView(adView); - - // 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. - AdRequest adRequest = new AdRequest.Builder().addNetworkExtrasBundle(AdMobAdapter.class, adSettingsBundle).build(); - - // Make it so. - 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; - - // Hide the ad. - 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; - - // Pause the AdView. - 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; - - // Resume the AdView. - adView.resume(); - } -} \ No newline at end of file diff --git a/app/src/free/java/com/stoutner/privacybrowser/helpers/AdHelper.kt b/app/src/free/java/com/stoutner/privacybrowser/helpers/AdHelper.kt new file mode 100644 index 00000000..a572e938 --- /dev/null +++ b/app/src/free/java/com/stoutner/privacybrowser/helpers/AdHelper.kt @@ -0,0 +1,176 @@ +/* + * Copyright © 2016-2021 Soren Stoutner . + * + * This file is part of Privacy Browser . + * + * Privacy Browser is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Browser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Browser. If not, see . + */ + +package com.stoutner.privacybrowser.helpers + +import android.app.Activity +import android.content.Context +import android.os.Bundle +import android.util.DisplayMetrics +import android.view.View +import android.widget.RelativeLayout + +import androidx.fragment.app.FragmentManager + +import com.google.ads.mediation.admob.AdMobAdapter +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 + +object AdHelper { + // Define the class variables. + private var initialized = false + + // The `@JvmStatic` notation can be removed once all the code has migrated to Kotlin. + @JvmStatic + fun initializeAds(view: View, context: Context, activity: Activity, fragmentManager: FragmentManager, adUnitId: String) { + // Check to see if the ads have been initialized. + if (!initialized) { // This is the first run; the ads have not yet been initialized. + // Initialize mobile ads. + MobileAds.initialize(context) + + // Initialize the bookmarks database helper. + val adConsentDatabaseHelper = AdConsentDatabaseHelper(context) + + // Check to see if consent has been granted. + val adConsentGranted = adConsentDatabaseHelper.isGranted + + // Display the ad consent dialog if needed. + if (!adConsentGranted) { // Ad consent has not been granted. + // Instantiate the ad consent dialog. + val adConsentDialogFragment = AdConsentDialog() + + // Display the ad consent dialog. + adConsentDialogFragment.show(fragmentManager,"Ad Consent") + } else { // Ad consent has already been granted. + // Load an ad. + loadAd(view, context, 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, context, activity, adUnitId) + } + } + + // The `@JvmStatic` notation can be removed once all the code has migrated to Kotlin. + @JvmStatic + fun loadAd(view: View, context: Context, activity: Activity, adUnitId: String) { + // Cast the generic view to an AdView. + var adView = view as AdView + + // Save the layout parameters. They are used when programatically recreating the ad below. + val adViewLayoutParameters = adView.layoutParams as RelativeLayout.LayoutParams + + // Get a handle for the ad view parent. + val adViewParentLayout = adView.parent as RelativeLayout + + // Remove the AdView. + adViewParentLayout.removeView(adView) + + // Create a new AdView. This is necessary because the size can change when the device is rotated. + adView = AdView(context) + + // Set the ad unit ID. + adView.adUnitId = adUnitId + + // Set the view ID. + adView.id = R.id.adview + + // Set the layout parameters. + adView.layoutParams = adViewLayoutParameters + + // Add the new ad view to the parent layout. + adViewParentLayout.addView(adView) + + // Get a handle for the display. Once the minimum API >= 30, this should be changed to `context.getDisplay()`. + @Suppress("DEPRECATION") val display = activity.windowManager.defaultDisplay + + // Initialize a display metrics. + val displayMetrics = DisplayMetrics() + + // Get the display metrics from the display. Once the minimum APO >= 30, this should be replaced with `WindowMetrics.getBounds()` and `Configuration.densityDpi`. + @Suppress("DEPRECATION") + display.getMetrics(displayMetrics) + + // Get the width pixels and the density. + val widthPixels = displayMetrics.widthPixels.toFloat() + val density = displayMetrics.density + + // Calculate the ad width. + val adWidth = (widthPixels / density).toInt() + + // Get the ad size. + val adSize = AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, adWidth) + + // Set the ad size on the adView. + adView.adSize = adSize + + // Create an ad settings bundle. + val adSettingsBundle = Bundle() + + // Only request non-personalized ads. + adSettingsBundle.putString("npa", "1") + + // Build the ad request. + val adRequest = AdRequest.Builder().addNetworkExtrasBundle(AdMobAdapter::class.java, adSettingsBundle).build() + + // Make it so. + adView.loadAd(adRequest) + } + + // The `@JvmStatic` notation can be removed once all the code has migrated to Kotlin. + // This method exists here for the sake of consistency with the following two methods. + @JvmStatic + fun hideAd(view: View) { + // Cast the generic view to an AdView. + val adView = view as AdView + + // Hide the ad. + adView.visibility = View.GONE + } + + // The `@JvmStatic` notation can be removed once all the code has migrated to Kotlin. + // This method exists here so that the main WebView activity doesn't need to import `com.google.android.gms.ads.AdView`. + @JvmStatic + fun pauseAd(view: View) { + // Cast The generic view to an AdView. + val adView = view as AdView + + // Pause the AdView. + adView.pause() + } + + // The `@JvmStatic` notation can be removed once all the code has migrated to Kotlin. + // This method exists here so that the main WebView activity doesn't need to import `com.google.android.gms.ads.AdView`. + @JvmStatic + fun resumeAd(view: View) { + // Cast the generic view to an AdView. + val adView = view as AdView + + // Resume the AdView. + adView.resume() + } +} \ No newline at end of file diff --git a/app/src/main/assets/de/about_changelog.html b/app/src/main/assets/de/about_changelog.html index 74d4feff..5e0754c6 100644 --- a/app/src/main/assets/de/about_changelog.html +++ b/app/src/main/assets/de/about_changelog.html @@ -34,7 +34,7 @@

3.8 (version code 55)

-

24. Mai 2021 - Mindest-API 19, Ziel-API 30

+

24. Mai 2021 - Mindest-API 19, Ziel-API 30

  • Option hinzugefügt, um die App-Leiste unten anzuzeigen.
  • Option zum Speichern von Web-Archiven wieder integriert.
  • diff --git a/app/src/main/assets/en/about_changelog.html b/app/src/main/assets/en/about_changelog.html index 0da332c0..b4e2865b 100644 --- a/app/src/main/assets/en/about_changelog.html +++ b/app/src/main/assets/en/about_changelog.html @@ -28,7 +28,7 @@

    3.8 (version code 55)

    -

    24 May 2021 - minimum API 19, target API 30

    +

    24 May 2021 - minimum API 19, target API 30

    • Add an option to move the app bar to the bottom.
    • Reimplement the saving of web archives.
    • diff --git a/app/src/main/assets/es/about_changelog.html b/app/src/main/assets/es/about_changelog.html index 9e341f33..e476e7cf 100644 --- a/app/src/main/assets/es/about_changelog.html +++ b/app/src/main/assets/es/about_changelog.html @@ -30,7 +30,7 @@

      3.8 (código de versión 55)

      -

      24 de mayo de 2021 - API mínimo 19, API dirigido 30

      +

      24 de mayo de 2021 - API mínimo 19, API dirigido 30

      • Añadir una opción para mover la barra de aplicaciones a la parte inferior.
      • Reimplementar el guardar archivos web.
      • diff --git a/app/src/main/assets/fr/about_changelog.html b/app/src/main/assets/fr/about_changelog.html index c3b3dfb3..ab3249ea 100644 --- a/app/src/main/assets/fr/about_changelog.html +++ b/app/src/main/assets/fr/about_changelog.html @@ -30,7 +30,7 @@

        3.8 (version du code 55)

        -

        24 Mai 2021 - API minimale : 19, API optimale : 30

        +

        24 Mai 2021 - API minimale : 19, API optimale : 30

        • Add an option to move the app bar to the bottom.
        • Reimplement the saving of web archives.
        • diff --git a/app/src/main/assets/it/about_changelog.html b/app/src/main/assets/it/about_changelog.html index 56fcfff4..879dc94d 100644 --- a/app/src/main/assets/it/about_changelog.html +++ b/app/src/main/assets/it/about_changelog.html @@ -30,7 +30,7 @@

          3.8 (versione codice 55)

          -

          24 Maggio 2021 - minima API 19, target API 30

          +

          24 Maggio 2021 - minima API 19, target API 30

          • Aggiunta l'opzione per spostare in basso la barra dell'app.
          • Nuova implementazione del salvataggio degli archivi web.
          • diff --git a/app/src/main/assets/pt-rBR/about_changelog.html b/app/src/main/assets/pt-rBR/about_changelog.html index 09a3c48a..a6c8c9de 100644 --- a/app/src/main/assets/pt-rBR/about_changelog.html +++ b/app/src/main/assets/pt-rBR/about_changelog.html @@ -30,7 +30,7 @@

            3.8 (código da versão 55)

            -

            24 May 2021 - minimum API 19, target API 30

            +

            24 May 2021 - minimum API 19, target API 30

            • Adicionado uma opção para mover a barra de aplicativos para a parte inferior.
            • Reimplementado o salvamento de arquivos da web.
            • diff --git a/app/src/main/assets/pt-rBR/about_contributors.html b/app/src/main/assets/pt-rBR/about_contributors.html index 910456ad..8b99a0f8 100644 --- a/app/src/main/assets/pt-rBR/about_contributors.html +++ b/app/src/main/assets/pt-rBR/about_contributors.html @@ -1,6 +1,8 @@ - @drawable/about_blue_night - @drawable/domains_night - @drawable/font_size_night - @drawable/lock_night - @drawable/ssl_certificate_enabled_night \ No newline at end of file diff --git a/app/src/main/res/values-night-v27/styles.xml b/app/src/main/res/values-night-v27/styles.xml index a11d6371..1f147492 100644 --- a/app/src/main/res/values-night-v27/styles.xml +++ b/app/src/main/res/values-night-v27/styles.xml @@ -63,13 +63,6 @@ @drawable/select_all_night @drawable/share_night @drawable/sort_night - - - @drawable/about_blue_night - @drawable/domains_night - @drawable/font_size_night - @drawable/lock_night - @drawable/ssl_certificate_enabled_night \ No newline at end of file diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml index d940112d..51a456e8 100644 --- a/app/src/main/res/values-night/styles.xml +++ b/app/src/main/res/values-night/styles.xml @@ -57,13 +57,6 @@ @drawable/select_all_night @drawable/share_night @drawable/sort_night - - - @drawable/about_blue_night - @drawable/domains_night - @drawable/font_size_night - @drawable/lock_night - @drawable/ssl_certificate_enabled_night \ No newline at end of file diff --git a/app/src/main/res/values-v23/styles.xml b/app/src/main/res/values-v23/styles.xml index 94734222..266d5b7a 100644 --- a/app/src/main/res/values-v23/styles.xml +++ b/app/src/main/res/values-v23/styles.xml @@ -61,13 +61,6 @@ @drawable/select_all_day @drawable/share_day @drawable/sort_day - - - @drawable/about_blue_day - @drawable/domains_day - @drawable/font_size_day - @drawable/lock_day - @drawable/ssl_certificate_enabled_day \ No newline at end of file diff --git a/app/src/main/res/values-v27/styles.xml b/app/src/main/res/values-v27/styles.xml index 34da5360..2cfe87ee 100644 --- a/app/src/main/res/values-v27/styles.xml +++ b/app/src/main/res/values-v27/styles.xml @@ -63,13 +63,6 @@ @drawable/select_all_day @drawable/share_day @drawable/sort_day - - - @drawable/about_blue_day - @drawable/domains_day - @drawable/font_size_day - @drawable/lock_day - @drawable/ssl_certificate_enabled_day \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 920e3bcd..02e1b506 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -1,7 +1,7 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 28ab21d2..4f5e9a2e 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -57,13 +57,6 @@ @drawable/select_all_day @drawable/share_day @drawable/sort_day - - - @drawable/about_blue_day - @drawable/domains_day - @drawable/font_size_day - @drawable/lock_day - @drawable/ssl_certificate_enabled_day \ No newline at end of file diff --git a/app/src/standard/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.java b/app/src/standard/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.kt similarity index 73% rename from app/src/standard/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.java rename to app/src/standard/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.kt index 82238996..03a2765b 100644 --- a/app/src/standard/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.java +++ b/app/src/standard/java/com/stoutner/privacybrowser/dialogs/AdConsentDialog.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2018-2019 Soren Stoutner . + * Copyright © 2018-2019,2021 Soren Stoutner . * * This file is part of Privacy Browser . * @@ -17,11 +17,10 @@ * along with Privacy Browser. If not, see . */ -package com.stoutner.privacybrowser.dialogs; +package com.stoutner.privacybrowser.dialogs -// The AndroidX dialog fragment must be used or an error is produced on API <=22. -import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.DialogFragment -public class AdConsentDialog extends DialogFragment { +class AdConsentDialog : DialogFragment() { // Do nothing because this is the standard flavor. } \ No newline at end of file diff --git a/app/src/standard/java/com/stoutner/privacybrowser/helpers/AdHelper.java b/app/src/standard/java/com/stoutner/privacybrowser/helpers/AdHelper.kt similarity index 58% rename from app/src/standard/java/com/stoutner/privacybrowser/helpers/AdHelper.java rename to app/src/standard/java/com/stoutner/privacybrowser/helpers/AdHelper.kt index d60bf091..50d1db27 100644 --- a/app/src/standard/java/com/stoutner/privacybrowser/helpers/AdHelper.java +++ b/app/src/standard/java/com/stoutner/privacybrowser/helpers/AdHelper.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2018,2020 Soren Stoutner . + * Copyright © 2016-2018,2020-2021 Soren Stoutner . * * This file is part of Privacy Browser . * @@ -17,32 +17,39 @@ * along with Privacy Browser. If not, see . */ -package com.stoutner.privacybrowser.helpers; -import android.app.Activity; -import android.content.Context; -import android.view.View; +package com.stoutner.privacybrowser.helpers -import androidx.fragment.app.FragmentManager; +import android.app.Activity +import android.content.Context +import android.view.View -@SuppressWarnings("unused") -public class AdHelper { - public static void initializeAds(View view, Context applicationContext, Activity activity, FragmentManager fragmentManager, String adUnitId) { +import androidx.fragment.app.FragmentManager + +// The `@JvmStatic` notation can be removed once all the code has migrated to Kotlin. +@Suppress("UNUSED_PARAMETER") +object AdHelper { + @JvmStatic + fun initializeAds(view: View, context: Context, activity: Activity, fragmentManager: FragmentManager, adUnitId: String) { // Do nothing because this is the standard flavor. } - public static void loadAd(View view, Context applicationContext, Activity activity, String adUnitId) { + @JvmStatic + fun loadAd(view: View, context: Context, activity: Activity, adUnitId: String) { // Do nothing because this is the standard flavor. } - public static void hideAd(View view) { + @JvmStatic + fun hideAd(view: View) { // Do nothing because this is the standard flavor. } - public static void pauseAd(View view) { + @JvmStatic + fun pauseAd(view: View) { // Do nothing because this is the standard flavor. } - public static void resumeAd(View view) { + @JvmStatic + fun resumeAd(view: View) { // Do nothing because this is the standard flavor. } } \ No newline at end of file -- 2.45.2