oss-licenses-plugin 사용해보기

최근 개인 프로젝트를 진행하면서, 사용한 오픈소스 라이센스 라이브러리들에 대해 표시할 메뉴를 만들 일이 있었다.

기존에는 하나하나 조사했던 반면, 최근에 Google이 ‘oss-service-plugin’ 라는 플러그인을 만든 것을 알아내서 사용해보기로 했다.

사용

최상단의 build.gradle에 아래 의존성을 추가한다.

dependencies {
   ...
   classpath 'com.google.android.gms:oss-licenses-plugin:0.10.2'
   ...
}

(버전 참조: https://maven.google.com/web/index.html?q=oss-licenses-plugin#com.google.android.gms:oss-licenses-plugin:0.10.2)

그 다음, 앱 모듈의 build.gradle에 아래 의존성을 추가한다.

...
apply plugin: 'com.google.android.gms.oss-licenses-plugin'

...

dependencies {
   implementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
}

(버전 참조: https://maven.google.com/web/index.html?q=play-services-oss-licenses#com.google.android.gms:play-services-oss-licenses:17.0.0)

마지막으로, Setting 등의 공간에 메뉴를 추가하고 클릭했을 때 아래의 코드를 실행한다.

startActivity(Intent(requireContext(), OssLicensesMenuActivity::class.java))

적용 사진

OssLicensesMenuActivity 를 실행하면 위와 같이 사용한 라이브러리의 목록이 나오고, 각 목록을 클릭하면 해당 라이브러리의 라이센스 문서가 나온다.

위 처럼 의존성을 적어주고 startActivity를 해주는 것 만으로도 쉽게 구현할 수 있었다.

내부 살펴보기

기재한 플러그인인 ‘com.google.android.gms.oss-licenses-plugin’ 은 아래와 같은 작업을 가지고 있다.

getDependencies

코드: https://github.com/google/play-services-plugins/blob/master/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/DependencyTask.groovy

configuration 에서 의존성의 목록(ResolvedDependency, https://gradle.github.io/gradle-script-kotlin-docs/api/org.gradle.api.artifacts/-resolved-dependency/) 과 그의 child dependency 를 재귀로 통해 가져와, build/generated/dependencies.json 를 구성한다.

...
{
       "group": "com.google.dagger",
       "version": "2.28",
       "fileLocation": "C:\\Users\\winds\\.gradle\\caches\\modules-2\\files-2.1\\com.google.dagger\\dagger\\2.28\\3c1b86e40d4957297d6fde6bdce74b3f48aac49d\\dagger-2.28.jar",
       "name": "dagger"
},
...

generateLicenses

코드: https://github.com/google/play-services-plugins/blob/master/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/LicensesTask.groovy

getDependencies에서 생성한 dependencies.json를 가지고 한 개씩 순회하면서 아래 작업을 진행한다.

  • 만일, 라이브러리의 그룹이 구글 라이브러리면, (com.google.android.gms 또는 com.google.firebase) addLicensesFromPom() 를 실행하고 그의 transitive licenses(전이된 라이센스) 를 추가한다.
    • 구글 라이브러리 이면, 각자의 라이브러리 파일에 “third_party_licenses.json”, “third_party_licenses.txt” 가 있으므로 Zip 파일에서 해당 파일을 얻어 appendLicense() 를 실행한다.
  • 아니라면, addLicensesFromPom() 를 실행한다.

addLicensesFromPom() 는 아래와 같은 작업을 진행한다.

  1. 아키텍트 파일에서 .pom 파일을 가져온다.
  2. .pom 파일에서 라이센스 정보를 가져와 third_party_licenses 파일에 작성한다.
  3. “${start}:${content.length} ${group}:${name}” 처럼 각 라이브러리에 대해 정보를 third_party_license_metadata 에 추가한다.

즉, third_party_licenses 파일은 표시할 모든 라이브러리 라이센스에 대한 내용을 가지고 있고, third_party_license_metadata 는 특정 라이브러리의 라이센스를 표시할 메타데이터를 가지고 있다.

third_party_license_metadata 에는 아래의 데이터들을 볼 수 있다.

0:46 androidx.databinding:databinding-runtime
48:46 androidx.lifecycle:lifecycle-common
96:46 androidx.annotation:annotation
144:46 androidx.arch.core:core-common
192:46 androidx.databinding:databinding-common
240:46 androidx.collection:collection
288:46 androidx.lifecycle:lifecycle-runtime
336:46 androidx.databinding:viewbinding
384:46 androidx.databinding:databinding-adapters
432:46 com.google.firebase:firebase-installations
480:46 androidx.localbroadcastmanager:localbroadcastmanager
528:47 com.google.android.gms:play-services-measurement-impl

그리고, third_pary_licenses에는 아래의 데이터들을 볼 수 있다.

http://www.apache.org/licenses/LICENSE-2.0.txt
http://www.apache.org/licenses/LICENSE-2.0.txt
http://www.apache.org/licenses/LICENSE-2.0.txt
http://www.apache.org/licenses/LICENSE-2.0.txt
http://www.apache.org/licenses/LICENSE-2.0.txt
http://www.apache.org/licenses/LICENSE-2.0.txt
http://www.apache.org/licenses/LICENSE-2.0.txt
http://www.apache.org/licenses/LICENSE-2.0.txt
http://www.apache.org/licenses/LICENSE-2.0.txt
http://www.apache.org/licenses/LICENSE-2.0.txt
http://www.apache.org/licenses/LICENSE-2.0.txt
https://developer.android.com/studio/terms.html

  Copyright (c) 2005-2011, The Android Open Source Project

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.

  Unless required by applicable law or agreed to in writing, software

이 데이터들을 가지고, OssLicensesMenuActivity 를 실행시키면 내부 코드에서 third_pary_licenses와 third_party_license_metadata 를 가지고 목록을 표시하거나, 내용을 표시하는 것을 알 수 있다.

for(int var6 = 0; var6 < var5; ++var6) {
  String var7;
  int var8 = (var7 = var4[var6]).indexOf(32);
  String[] var9;
  boolean var14 = (var9 = var7.substring(0, var8).split(":")).length == 2 && var8 > 0;
  String var10002 = String.valueOf(var7);
  String var10001;
  if (var10002.length() != 0) {
      var10001 = "Invalid license meta-data line:\n".concat(var10002);
  } else {
      String var10003 = new String;
      var10001 = var10003;
      var10003.<init>("Invalid license meta-data line:\n");
  }

  String var13 = var10001;
  if (!var14) {
      throw new IllegalStateException(String.valueOf(var13));
  }

  long var10 = Long.parseLong(var9[0]);
  int var12 = Integer.parseInt(var9[1]);
  var3.add(zzc.zza(var7.substring(var8 + 1), var10, var12, var1));
}