【Android】 OssLicensesMenuActivityに表示されるライセンス情報を手動で追加する

By | 2019年1月27日

概要

Google Play ServicesのIncluding Open Source Noticesにあるツールを使うと、プロジェクトで使用しているオープンソースライブラリのライセンスリストを自動生成し、OssLicensesMenuActivityから表示させることができる。

 しかし、このツールはgradleに記載したライブラリしかリストアップしてくれない。 例えば、material iconなどのような、gradleの依存関係に記載できないプロダクトのライセンスはリストアップの対象外である。そこで、何とかこのツールを使いつつ、ライセンス項目を追加する方法を考えてみた。

今回作成したコードの完成版はこちら

環境

Android Studio 3.2.1

手順

まずは、空のAndroidプロジェクトを作り、OssLicensesMenuActivityを表示するところまでをやってみる。ここまでの手順は以下のサイトを参考にした。

まずルートレベルのbuild.gradleにプラグインのクラスパスを追加する。

build.gradle (root-level)

buildscript {
  repositories {
    // ...
    google()
  }
  dependencies {
    // ...
    // 追加
    classpath 'com.google.android.gms:oss-licenses-plugin:0.9.3'
  }
}

アプリケーションレベルのbuild.gradleの冒頭にプラグインを適用させる旨を追記する。

build.gradle (app-level)

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'
// 追加
apply plugin: 'com.google.android.gms.oss-licenses-plugin'

同じくアプリケーションレベルのbuild.gradleのdependenciesブロックの中に、oss-licensesライブラリーを追加する。

implementation 'com.google.android.gms:play-services-oss-licenses:16.0.2'

デフォルトのActivityに適当なButtonを追加し、ボタンをクリックするとライセンス画面を表示するようにしてみる。

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // OssLicensesMenuActivityにインテントを投げる
        findViewById<Button>(R.id.button).setOnClickListener{
            startActivity(Intent(this, OssLicensesMenuActivity::class.java))
        }
    }
}

ここまでの手順で、gradleのdependenciesに記述されたライブラリのライセンスを表示させることができた。

ライセンス情報の追加

さて、本題はここからである。gradleの依存関係に無いプロダクトのライセンス情報を手動で追加するにはどうすればよいだろうか?GitHubに公開されているプラグインのソースを眺めながらビルド時に何が行われるかを確認していこう。処理の大まかな流れとしては、

  • preBuild前に下記のタスクが実行されるように登録
    (OssLicensesPlugin.groovy)
  • gradleの依存情報を走査し、
    app/build/generated/third_party_licenses/res/dependencies.jsonに書き込む(DependencyTask.groovy)
  • 上記のjsonファイルの内容を元に
    app/build/generated/third_party_licenses/res/raw以下にthird_party_license_metadatathird_party_licensesを生成(LicensesTask.groovy)

ここまでの流れで、app/build/generated/third_party_licenses/resの構成は以下のように自動生成される。

├── dependencies.json
└── res
    └── raw
        ├── third_party_license_metadata
        └── third_party_licenses

third_party_licensesには依存情報から取得された全てのライセンスの具体的な内容が、そしてthird_party_license_metadataには以下の形式でコンテンツのメタ情報が書かれている。

コンテンツの開始位置:コンテンツの文字数 ライセンス名

その後、OssLicensesMenuActivityは起動時に上記の2つのファイルの内容を読み込み、リストビューに表示させているのである。

さて、ということはビルドプロセス中に、これらのファイルに任意の文字列を書き込んでしまえばライセンス情報を追加できそうである。そこで、アプリレベルのbuild.gradleに以下のコードを追加した。

build.gradle (app-level)

// ライセンス情報を追加するタスク
task addMyLicenseTask {
    final String UTF_8 = "UTF-8"
    final byte[] LINE_SEPARATOR = System.getProperty("line.separator").getBytes(UTF_8)

    // generateLicensesタスクの直後に起動
    mustRunAfter tasks.findByName('generateLicenses')

    // 手動でライセンス情報を追加する
    doLast {
        def dependencyOutput = new File(project.buildDir, "generated/third_party_licenses")

        def resourceOutput = new File(dependencyOutput, "/res")
        def outputDir = new File(resourceOutput, "/raw")

        // ライセンスファイル
        def licensesFile = new File(outputDir, "third_party_licenses")
        // ライセンスファイルへの書き込み前に現在の位置を保持
        def start = licensesFile.length()

        // ライセンスファイルへ書き込み
        def licenseContent = 'This is my library license!!'
        licensesFile << licenseContent
        licensesFile << (LINE_SEPARATOR)

        // ライセンスメタデータファイルに書き込み
        def licensesMetadataFile = new File(outputDir, "third_party_license_metadata")
        // "開始位置:文字数 ライセンス名"の形式で書き込む
        licensesMetadataFile << ("${start}:${licenseContent.length()} my_library")
        licensesMetadataFile << (LINE_SEPARATOR)
    }
}

// preBuild前にライセンス情報を追加する
tasks.findByPath(':app:preBuild').dependsOn addMyLicenseTask

とりあえず今回はmy_libraryという適当な文字列を追加している。
これをビルドして実行すると、意図通りライセンス情報が追加された。

※表示の順番はコンテンツファイルに書かれていた順番ではなく、ソートされている。

あとは、必要に応じて表示する内容を調整していけばいいだろう。
ここまでの完全なコードはGitHubにプッシュしたので参考にしてほしい。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です