From 1dd61d650bd3c07c6c6dc4f03114618d5183adc6 Mon Sep 17 00:00:00 2001 From: Matthieu <61561059+Wv5twkFEKh54vo4tta9yu7dHa3@users.noreply.github.com> Date: Fri, 11 Jun 2021 10:21:44 +0200 Subject: [PATCH] Add custom Activity to show libraries licenses without proprietary dependency --- app/build.gradle | 2 - app/src/main/AndroidManifest.xml | 5 +- .../wallet/app/android/LicensesActivity.kt | 112 ++++++++++++++++++ .../wallet/app/android/SettingsFragment.kt | 5 +- app/src/main/res/layout/activity_licenses.xml | 32 +++++ buildSrc/src/main/java/Dependencies.kt | 2 - 6 files changed, 147 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/dgca/wallet/app/android/LicensesActivity.kt create mode 100644 app/src/main/res/layout/activity_licenses.xml diff --git a/app/build.gradle b/app/build.gradle index dc703baf..267d2dc0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -94,8 +94,6 @@ dependencies { implementation Deps.timber - implementation Deps.google_licenses - testImplementation Deps.test_junit androidTestImplementation Deps.android_test_junit diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f067932b..95716075 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,10 +24,7 @@ - + showLicenseDialog(libraries[position]) + } + } + + private fun parseLibraries(): List { + /* + The gradle plugin "oss-licenses-plugin" creates two "raw" resources: + - third_party_licenses which is the binary concatenation of all the licenses text for + all the libraries. License texts can either be an URL to a license file or just the + raw text of the license. + - third_party_licenses_metadata which contains one dependency per line formatted in + the following way: "[start_offset]:[length] [name]" + [start_offset] : first byte in third_party_licenses that contains the license + text for this library. + [length] : length of the license text for this library in + third_party_licenses. + [name] : either the name of the library, or its artifact name. + See https://github.com/google/play-services-plugins/tree/master/oss-licenses-plugin + */ + val licensesData = resources + .openRawResource(R.raw.third_party_licenses) + .readBytes() + val licensesMetadataReader = resources + .openRawResource(R.raw.third_party_license_metadata) + .bufferedReader() + + return licensesMetadataReader.use { reader -> reader.readLines() }.map { line -> + val (section, name) = line.split(" ", limit = 2) + val (startOffset, length) = section.split(":", limit = 2).map(String::toInt) + val licenseData = licensesData.sliceArray(startOffset until startOffset + length) + val licenseText = licenseData.toString(Charset.forName("UTF-8")) + LibraryItem(name, licenseText) + }.sortedBy { item -> item.name.toLowerCase(Locale.ROOT) } + } + + private fun showLicenseDialog(libraryItem: LibraryItem) { + val dialog: AlertDialog = AlertDialog.Builder(this).let { + it.setTitle(libraryItem.name) + it.setMessage(libraryItem.license) + it.show() + } + + dialog.findViewById(android.R.id.message)!!.let { + Linkify.addLinks(it, Linkify.ALL) + it.linksClickable = true + it.textSize = 10F + it.typeface = Typeface.MONOSPACE + } + } +} + +private class LibraryItem(val name: String, val license: String) { + override fun toString(): String { + return name + } +} \ No newline at end of file diff --git a/app/src/main/java/dgca/wallet/app/android/SettingsFragment.kt b/app/src/main/java/dgca/wallet/app/android/SettingsFragment.kt index 5c1ce412..11455ed6 100644 --- a/app/src/main/java/dgca/wallet/app/android/SettingsFragment.kt +++ b/app/src/main/java/dgca/wallet/app/android/SettingsFragment.kt @@ -30,7 +30,6 @@ import android.view.Menu import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import com.google.android.gms.oss.licenses.OssLicensesMenuActivity import dagger.hilt.android.AndroidEntryPoint import dgca.wallet.app.android.databinding.FragmentSettingsBinding @@ -72,9 +71,9 @@ class SettingsFragment : Fragment() { } private fun openLicenses() { - OssLicensesMenuActivity.setActivityTitle(getString(R.string.licenses)) + val intent = Intent(requireContext(), LicensesActivity::class.java) requireContext().apply { - startActivity(Intent(this, OssLicensesMenuActivity::class.java)) + startActivity(intent) } } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_licenses.xml b/app/src/main/res/layout/activity_licenses.xml new file mode 100644 index 00000000..ae481fec --- /dev/null +++ b/app/src/main/res/layout/activity_licenses.xml @@ -0,0 +1,32 @@ + + + + + + + \ No newline at end of file diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 063fb281..de69d1c6 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -62,8 +62,6 @@ object Deps { const val timber = "com.jakewharton.timber:timber:${Versions.timber}" - const val google_licenses = "com.google.android.gms:play-services-oss-licenses:${Versions.google_licenses}" - const val test_junit = "junit:junit:${Versions.junit}" const val test_junit_jupiter_api = "org.junit.jupiter:junit-jupiter-api:${Versions.junit_jupiter}" const val test_junit_jupiter_params = "org.junit.jupiter:junit-jupiter-params:${Versions.junit_jupiter}"