diff --git a/app/build.gradle b/app/build.gradle
index cd02eece..64c5f1cf 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,8 +1,8 @@
plugins {
alias(libs.plugins.androidApplication)
+ alias(libs.plugins.ossLicenses)
alias(libs.plugins.googleServices)
alias(libs.plugins.firebaseCrashlytics)
- alias(libs.plugins.aboutLibraries)
alias(libs.plugins.hiltAndroid)
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8dd3e47f..f52666f4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -63,7 +63,11 @@
android:theme="@style/AppTheme" />
+
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpActivity.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpActivity.java
index 327e14a1..8b60c4cf 100644
--- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpActivity.java
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpActivity.java
@@ -1,7 +1,6 @@
package com.d4rk.androidtutorials.java.ui.screens.help;
import android.content.ActivityNotFoundException;
-import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -23,7 +22,6 @@
import com.d4rk.androidtutorials.java.utils.OpenSourceLicensesUtils;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.play.core.review.ReviewInfo;
-import com.mikepenz.aboutlibraries.LibsBuilder;
import dagger.hilt.android.AndroidEntryPoint;
@@ -82,37 +80,13 @@ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
openLink("https://mihaicristiancondrea.github.io/profile/#privacy-policy-end-user-software");
return true;
} else if (itemId == R.id.oss) {
- OpenSourceLicensesUtils.loadHtmlData(this, (changelogHtml, eulaHtml) -> openLicensesScreen(this, eulaHtml, changelogHtml));
+ OpenSourceLicensesUtils.openLicensesScreen(this);
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
- private void openLicensesScreen(Context context, String eulaHtmlString, String changelogHtmlString) {
- new LibsBuilder()
- .withActivityTitle(context.getString(R.string.open_source_licenses))
- .withEdgeToEdge(true)
- .withShowLoadingProgress(true)
- .withSearchEnabled(true)
- .withAboutIconShown(true)
- .withAboutAppName(context.getString(R.string.app_name))
- .withVersionShown(true)
- .withAboutVersionString(BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")")
- .withLicenseShown(true)
- .withAboutVersionShown(true)
- .withAboutSpecial1(context.getString(R.string.eula_title))
- .withAboutSpecial1Description(
- eulaHtmlString != null ? eulaHtmlString : context.getString(R.string.loading_eula)
- )
- .withAboutSpecial2(context.getString(R.string.changelog))
- .withAboutSpecial2Description(
- changelogHtmlString != null ? changelogHtmlString : context.getString(R.string.loading_changelog)
- )
- .withAboutDescription(context.getString(R.string.app_short_description))
- .start(context);
- }
-
private void showVersionInfoDialog() {
DialogVersionInfoBinding binding = DialogVersionInfoBinding.inflate(getLayoutInflater());
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@@ -131,7 +105,7 @@ private void openGooglePlayListing() {
final String appPackageName = getPackageName();
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
- } catch (android.content.ActivityNotFoundException anfe) {
+ } catch (ActivityNotFoundException anfe) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
}
}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/settings/SettingsFragment.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/settings/SettingsFragment.java
index e54b38ab..859147ad 100644
--- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/settings/SettingsFragment.java
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/settings/SettingsFragment.java
@@ -16,11 +16,9 @@
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreferenceCompat;
-import com.d4rk.androidtutorials.java.BuildConfig;
import com.d4rk.androidtutorials.java.R;
import com.d4rk.androidtutorials.java.ui.components.dialogs.RequireRestartDialog;
import com.d4rk.androidtutorials.java.utils.OpenSourceLicensesUtils;
-import com.mikepenz.aboutlibraries.LibsBuilder;
public class SettingsFragment extends PreferenceFragmentCompat {
@Override
@@ -57,7 +55,7 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
Preference ossPreference = findPreference(getString(R.string.key_open_source_licenses));
if (ossPreference != null) {
ossPreference.setOnPreferenceClickListener(preference -> {
- OpenSourceLicensesUtils.loadHtmlData(requireContext(), (changelogHtml, eulaHtml) -> openLicensesScreen(requireContext(), eulaHtml, changelogHtml));
+ OpenSourceLicensesUtils.openLicensesScreen(requireContext());
return true;
});
}
@@ -98,28 +96,4 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
});
}
}
-
- private void openLicensesScreen(Context context, String eulaHtmlString, String changelogHtmlString) {
- new LibsBuilder()
- .withActivityTitle(context.getString(R.string.open_source_licenses))
- .withEdgeToEdge(true)
- .withShowLoadingProgress(true)
- .withSearchEnabled(true)
- .withAboutIconShown(true)
- .withAboutAppName(context.getString(R.string.app_name))
- .withVersionShown(true)
- .withAboutVersionString(BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")")
- .withLicenseShown(true)
- .withAboutVersionShown(true)
- .withAboutSpecial1(context.getString(R.string.eula_title))
- .withAboutSpecial1Description(
- eulaHtmlString != null ? eulaHtmlString : context.getString(R.string.loading_eula)
- )
- .withAboutSpecial2(context.getString(R.string.changelog))
- .withAboutSpecial2Description(
- changelogHtmlString != null ? changelogHtmlString : context.getString(R.string.loading_changelog)
- )
- .withAboutDescription(context.getString(R.string.app_short_description))
- .start(context);
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/utils/OpenSourceLicensesUtils.java b/app/src/main/java/com/d4rk/androidtutorials/java/utils/OpenSourceLicensesUtils.java
index 3dc9d3c1..be290945 100644
--- a/app/src/main/java/com/d4rk/androidtutorials/java/utils/OpenSourceLicensesUtils.java
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/utils/OpenSourceLicensesUtils.java
@@ -1,123 +1,32 @@
package com.d4rk.androidtutorials.java.utils;
+import android.app.Activity;
import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
+import android.content.Intent;
-import com.d4rk.androidtutorials.java.R;
-
-import org.commonmark.node.Node;
-import org.commonmark.parser.Parser;
-import org.commonmark.renderer.html.HtmlRenderer;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.Objects;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class OpenSourceLicensesUtils {
- private static final String TAG = "OpenSourceLicensesUtils";
- private static final ExecutorService executor = Executors.newSingleThreadExecutor();
- private static final Handler mainHandler = new Handler(Looper.getMainLooper());
-
- public static void loadHtmlData(final Context context, final HtmlDataCallback callback) {
- executor.execute(() -> {
- String packageName = context.getPackageName();
- String currentVersion = getAppVersion(context);
- String changelogUrl = "https://raw.githubusercontent.com/MihaiCristianCondrea/" + packageName + "/refs/heads/main/CHANGELOG.md";
- String eulaUrl = "https://raw.githubusercontent.com/MihaiCristianCondrea/" + packageName + "/refs/heads/main/EULA.md";
-
- String changelogMarkdown = loadMarkdown(context, changelogUrl, R.string.error_loading_changelog);
- String extractedChangelog = extractLatestVersionChangelog(changelogMarkdown, currentVersion);
- String changelogHtml = markdownToHtml(extractedChangelog);
-
- String eulaMarkdown = loadMarkdown(context, eulaUrl, R.string.error_loading_eula);
- String eulaHtml = markdownToHtml(eulaMarkdown);
+import androidx.annotation.Nullable;
- mainHandler.post(() -> callback.onHtmlDataLoaded(changelogHtml, eulaHtml));
- });
- }
+import com.d4rk.androidtutorials.java.R;
+import com.google.android.gms.oss.licenses.OssLicensesMenuActivity;
- private static String loadMarkdown(Context context, String urlString, int errorStringId) {
- HttpURLConnection connection = null;
- BufferedReader reader = null;
- try {
- URL url = new URL(urlString);
- connection = (HttpURLConnection) url.openConnection();
- connection.setRequestMethod("GET");
- connection.setConnectTimeout(10000);
- connection.setReadTimeout(10000);
+public final class OpenSourceLicensesUtils {
- int responseCode = connection.getResponseCode();
- if (responseCode == HttpURLConnection.HTTP_OK) {
- reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- StringBuilder content = new StringBuilder();
- String line;
- while ((line = reader.readLine()) != null) {
- content.append(line).append("\n");
- }
- return content.toString();
- } else {
- Log.e(TAG, "Failed to load URL: " + urlString + " with response code: " + responseCode);
- return context.getString(errorStringId);
- }
- } catch (Exception e) {
- Log.e(TAG, "Error loading markdown from URL: " + urlString, e);
- return context.getString(errorStringId);
- } finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (Exception e) {
- Log.e(TAG, "Error closing reader", e);
- }
- }
- if (connection != null) {
- connection.disconnect();
- }
- }
+ private OpenSourceLicensesUtils() {
+ // Utility class
}
- private static String extractLatestVersionChangelog(String markdown, String currentVersion) {
- // Define the regex pattern to match the latest version section
- String regexPattern = "(?m)^#\\s+Version\\s+" + Pattern.quote(currentVersion) + ":\\s*(.*?)^(#\\s+Version\\s+|$)";
- Pattern pattern = Pattern.compile(regexPattern, Pattern.DOTALL | Pattern.MULTILINE);
- Matcher matcher = pattern.matcher(markdown);
-
- if (matcher.find()) {
- // Group 1 contains the changelog for the current version
- return Objects.requireNonNull(matcher.group(1)).trim();
- } else {
- Log.e(TAG, "No changelog available for version " + currentVersion);
- return "No changelog available for version " + currentVersion;
+ public static void openLicensesScreen(@Nullable Context context) {
+ if (context == null) {
+ return;
}
- }
- private static String markdownToHtml(String markdown) {
- Parser parser = Parser.builder().build();
- HtmlRenderer renderer = HtmlRenderer.builder().build();
- Node document = parser.parse(markdown);
- return renderer.render(document);
- }
+ OssLicensesMenuActivity.setActivityTitle(context.getString(R.string.open_source_licenses));
- private static String getAppVersion(Context context) {
- try {
- return context.getPackageManager()
- .getPackageInfo(context.getPackageName(), 0)
- .versionName;
- } catch (Exception e) {
- Log.e(TAG, "Error getting app version", e);
- return "1.0.0"; // Fallback version
+ Intent intent = new Intent(context, OssLicensesMenuActivity.class);
+ if (!(context instanceof Activity)) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
- }
- public interface HtmlDataCallback {
- void onHtmlDataLoaded(String changelogHtml, String eulaHtml);
+ context.startActivity(intent);
}
}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 7363c4db..fd67164d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,7 +1,19 @@
+buildscript {
+ repositories {
+ google()
+ mavenCentral()
+ }
+ dependencies {
+ // The oss-licenses Gradle plugin still relies on XmlSlurper from groovy-xml when
+ // running on recent Gradle versions, so we provide it explicitly on the classpath.
+ classpath 'org.codehaus.groovy:groovy-xml:3.0.19'
+ }
+}
+
plugins {
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.googleServices) apply false
alias(libs.plugins.firebaseCrashlytics) apply false
- alias(libs.plugins.aboutLibraries) apply true
+ alias(libs.plugins.ossLicenses) apply false
alias(libs.plugins.hiltAndroid) apply false
}
diff --git a/docs/core/core-module.md b/docs/core/core-module.md
index aa1db163..3e4819bc 100644
--- a/docs/core/core-module.md
+++ b/docs/core/core-module.md
@@ -11,7 +11,7 @@ Houses use case classes and other business logic that operate on repositories.
Contains Activities, Fragments and ViewModels such as `MainViewModel`.
### utils
-Provides helpers like `OpenSourceLicensesUtils`, `ReviewHelper` and `EdgeToEdgeDelegate`.
+Provides helpers like `OpenSourceLicensesUtils` for launching the open source license screen, `ReviewHelper` and `EdgeToEdgeDelegate`.
### di
Contains Hilt modules and qualifiers for dependency injection.
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 91b612e3..7740a22d 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -2,11 +2,11 @@
agp = "8.13.0"
firebaseCrashlyticsPlugin = "3.0.6"
googleServices = "4.4.3"
+ossLicensesPlugin = "0.10.6"
appcompat = "1.7.1"
appUpdate = "2.1.0"
billing = "8.0.0"
constraintlayout = "2.2.1"
-aboutlibraries = "11.3.0"
coreSplashscreen = "1.0.1"
core = "4.6.2"
coreTesting = "2.2.0"
@@ -27,6 +27,7 @@ coreKtx = "1.17.0"
material = "1.14.0-alpha04"
multidex = "2.0.1"
playServicesAds = "24.6.0"
+playServicesOssLicenses = "17.3.0"
codeview = "1.3.9"
hilt = "2.57.1"
room = "2.8.0"
@@ -63,6 +64,7 @@ firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "fir
firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics" }
google-firebase-perf = { module = "com.google.firebase:firebase-perf" }
play-services-ads = { module = "com.google.android.gms:play-services-ads", version.ref = "playServicesAds" }
+play-services-oss-licenses = { module = "com.google.android.gms:play-services-oss-licenses", version.ref = "playServicesOssLicenses" }
# Networking (Retrofit)
retrofit2 = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
@@ -73,7 +75,6 @@ hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt"
hilt-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" }
# Utility
-aboutlibraries = { module = "com.mikepenz:aboutlibraries", version.ref = "aboutlibraries" }
app-update = { module = "com.google.android.play:app-update", version.ref = "appUpdate" }
billing = { module = "com.android.billingclient:billing", version.ref = "billing" }
core = { module = "io.noties.markwon:core", version.ref = "core" }
@@ -94,14 +95,15 @@ mockito-inline = { module = "org.mockito:mockito-inline", version.ref = "mockito
androidApplication = { id = "com.android.application", version.ref = "agp" }
googleServices = { id = "com.google.gms.google-services", version.ref = "googleServices" }
firebaseCrashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebaseCrashlyticsPlugin" }
-aboutLibraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutlibraries" }
hiltAndroid = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
+ossLicenses = { id = "com.google.android.gms.oss-licenses-plugin", version.ref = "ossLicensesPlugin" }
[bundles]
# Google Play services and related UI components
google-core = [
"material",
"play-services-ads",
+ "play-services-oss-licenses",
"review",
"app-update",
"billing",
@@ -138,7 +140,6 @@ androidx-lifecycle = [
# Shared UI tooling and visuals
ui-toolkit = [
- "aboutlibraries",
"core",
"lottie",
"library",
diff --git a/settings.gradle b/settings.gradle
index e1bd2e89..77d4c0a7 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -8,7 +8,7 @@ pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == 'com.google.android.gms.oss-licenses-plugin') {
- useModule("com.google.android.gms:oss-licenses-plugin:${requested.version}")
+ useModule('com.google.android.gms:oss-licenses-plugin:0.10.6')
}
}
}