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