Skip to content

Commit

Permalink
Add custom Activity to show libraries licenses without proprietary de…
Browse files Browse the repository at this point in the history
…pendency (#55)
  • Loading branch information
Wv5twkFEKh54vo4tta9yu7dHa3 authored Jul 23, 2021
1 parent fbb2ffc commit 9403481
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 11 deletions.
2 changes: 0 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ dependencies {

implementation Deps.timber

implementation Deps.google_licenses

testImplementation Deps.test_junit

androidTestImplementation Deps.test_ext
Expand Down
5 changes: 1 addition & 4 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@
</activity>

<activity
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
android:theme="@style/Theme.DgcaVerifierAppAndroid.Licensing" />
<activity
android:name="com.google.android.gms.oss.licenses.OssLicensesActivity"
android:name=".LicensesActivity"
android:theme="@style/Theme.DgcaVerifierAppAndroid.Licensing" />

<provider
Expand Down
112 changes: 112 additions & 0 deletions app/src/main/java/dgca/wallet/app/android/LicensesActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* ---license-start
* eu-digital-green-certificates / dgca-verifier-app-android
* ---
* Copyright (C) 2021 T-Systems International GmbH and all other contributors
* ---
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ---license-end
*
* Created by Matthieu De Beule on 11/06/2021, 08:39
*/

package dgca.wallet.app.android;

import android.graphics.Typeface
import android.os.Bundle
import android.text.util.Linkify
import android.widget.ArrayAdapter
import android.widget.ListView
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import dgca.wallet.app.android.databinding.ActivityLicensesBinding
import dgca.wallet.app.android.databinding.FragmentSettingsBinding
import java.nio.charset.Charset
import java.util.*

//Largely inspired by https://github.com/mozilla-mobile/fenix/pull/13767/
class LicensesActivity : AppCompatActivity() {
private lateinit var binding: ActivityLicensesBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityLicensesBinding.inflate(layoutInflater)

setTitle(R.string.licenses)
setContentView(binding.root)

supportActionBar?.setDisplayHomeAsUpEnabled(true)

setupLibrariesListView()
}

override fun onSupportNavigateUp(): Boolean {
onBackPressed()
return true
}

private fun setupLibrariesListView() {
val libraries = parseLibraries()
val listView = binding.licensesListview
listView.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, libraries)
listView.setOnItemClickListener { _, _, position, _ ->
showLicenseDialog(libraries[position])
}
}

private fun parseLibraries(): List<LibraryItem> {
/*
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<TextView>(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
}
}
5 changes: 2 additions & 3 deletions app/src/main/java/dgca/wallet/app/android/SettingsFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
}
}
}
32 changes: 32 additions & 0 deletions app/src/main/res/layout/activity_licenses.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ license-start
~ eu-digital-green-certificates / dgca-verifier-app-android
~
~ Copyright (C) 2021 T-Systems International GmbH and all other contributors
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~ license-end
~
~ Created by Matthieu De Beule on 11/06/2021, 08:43
-->

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/licenses_listview" />

</androidx.constraintlayout.widget.ConstraintLayout>
2 changes: 0 additions & 2 deletions buildSrc/src/main/java/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,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}"
Expand Down

0 comments on commit 9403481

Please sign in to comment.