AndroidアプリでJetpack Composeを使って使用しているライブラリのライセンスを表示してみる
Androidアプリを開発していると直面するライセンス表示問題。
色々調べるとCookpadさんが公開しているプラグインにたどり着いた。だが、お察しのとおりすでにアーカイブされている。
代わりにおすすめされているのが、Googleが公開しているOSS Licenses Gradle Plugin。
play-services-plugins/oss-licenses-plugin at master · google/play-services-plugins · GitHub
残念ながらJetpack Composeには現時点で対応していない。僕はJetpack Composeを使ってライセンスを表示したい。
そこで、見つけたのがJumpei Matsudaさんが公開しているlicense-list-plugin。
このプラグインを使ってartifact-definition.ymlを生成し、そのデータをパースした内容をCompose可能な関数で表示してみる。
アプリのbuild.gradleにて、プラグインの設定を行う。
plugins {
id 'com.android.application'
id "io.github.jmatsu.license-list"
}
// Licensing
apply plugin: "com.android.application"
apply plugin: "io.github.jmatsu.license-list"
ルートディレクトリにあるプロジェクトのbuild.gradleにbuildscriptの設定を追加する。
buildscript {
ext {
license_list_gradle_version = '0.8.1'
}
dependencies {
classpath "io.github.jmatsu:license-list-gradle:$license_list_gradle_version"
}
}
追加が完了したら、実際にプラグインを実行する。
./gradlew initLicenseList
実行後、app/artifact-definition.ymlとapp/license-catalog.ymlが作成されているはず。
モジュールを右クリックして、New -> Folder -> Assets Folderの順番で選択していき、assetsフォルダを作成する。
そのassetsの中に先ほど生成されたartifact-definition.ymlとlicense-catalog.ymlを移動する。
artifact-definition.ymlの中身をパースするために、kamlライブラリを導入する。
build.gradleに次の設定と依存関係を追加する。
plugins {
id 'org.jetbrains.kotlin.plugin.serialization' version '1.4.20'
}
dependencies {
implementation "com.charleskorn.kaml:kaml:0.49.0" // Get the latest version number from https://github.com/charleskorn/kaml/releases/latest
}
assets/artifact-definition.ymlを実際に読み込むために、Contextのインスタンスを使用する。
@kotlinx.serialization.Serializable data class License( val release: Map<String, List<ArtifactDefinition>>, val test: Map<String, List<ArtifactDefinition>>, val androidTest: Map<String, List<ArtifactDefinition>>, ) @kotlinx.serialization.Serializable data class ArtifactDefinition( val key: String, val displayName: String, val url: String?, val copyrightHolders: List<String>, val licenses: List<String> ) fun parseLicense(context: Context) { val yamlStr = context.assets.open("artifact-definition.yml").bufferedReader().use { it.readText() } val result = Yaml.default.decodeFromString(License.serializer(), yamlStr) }
ひとつのライセンス要素を表示するためのCompose可能な関数を定義する。
@Composable fun LicenseItem( displayName: String, url: String?, copyrightHolders: List<String>, licenses: List<String>, ) { Column() { Text( text = displayName, style = MaterialTheme.typography.titleLarge ) Spacer(modifier = Modifier.height(8.dp)) if (url != null) { Text( text = url ?: "" ) Spacer(modifier = Modifier.height(8.dp)) } if (copyrightHolders.isNotEmpty()) { copyrightHolders.forEach { copyrightHolder -> Text( text = copyrightHolder ) } Spacer(modifier = Modifier.height(8.dp)) } licenses.forEach { license -> Text( text = license ) } } }
そして、先ほど読み取ったデータを使い、LazyColumnを呼び出してリスト形式で表示する。
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
) {
if (license != null) {
items(license.release.keys.toList()) { groupKey ->
val group = license.release[groupKey]
group?.forEach { groupItem ->
LicenseItem(
displayName = groupItem.displayName,
url = groupItem.url,
copyrightHolders = groupItem.copyrightHolders,
licenses = groupItem.licenses
)
Spacer(modifier = Modifier.height(24.dp))
}
}
items(license.test.keys.toList()) { groupKey ->
val group = license.release[groupKey]
group?.forEach { groupItem ->
LicenseItem(
displayName = groupItem.displayName,
url = groupItem.url,
copyrightHolders = groupItem.copyrightHolders,
licenses = groupItem.licenses
)
Spacer(modifier = Modifier.height(24.dp))
}
}
items(license.androidTest.keys.toList()) { groupKey ->
val group = license.release[groupKey]
group?.forEach { groupItem ->
LicenseItem(
displayName = groupItem.displayName,
url = groupItem.url,
copyrightHolders = groupItem.copyrightHolders,
licenses = groupItem.licenses
)
Spacer(modifier = Modifier.height(24.dp))
}
}
}
}
実際の画面。

参考
Read a Text asset(text file from assets folder) as a String in Kotlin (Android) - Stack Overflow