KDP(電子出版)のメモ 急急如律令

Amazon Kindleダイレクト・パブリッシングでの電子出版や電子書籍の作成販売について、文章やイラストの作成や編集方法について書いています。

AndroidのOSSライブラリ表示

 アンドロイドアプリでライブラリを使っているとライセンス表記をする必要がある。githubのリポジトリへのリンクに貼れば良いのかな。 qiita.com

zenn.dev

あなた:

androidにoss-licenses-pluginを追加する手順

ChatGPT:

Android プロジェクトに oss-licenses-plugin(Google OSS Licenses Plugin)を追加する手順は以下の通りです。これにより、プロジェクトに含まれるライブラリのライセンス情報を自動的に収集・表示できます。

// プロジェクトレベルの build.gradle
buildscript {
    dependencies {
        classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6'
    }
}

⚠️ Android Gradle Plugin 8.0 以降では build.gradle.kts を使用している場合もあります。その場合は build.gradle.kts に classpath を書いてください。

// アプリレベルの build.gradle
plugins {
    id 'com.android.application'
    id 'com.google.android.gms.oss-licenses-plugin'
}
dependencies {
    implementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
}
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity;

Intent intent = new Intent(this, OssLicensesMenuActivity.class);
// 任意でタイトルをカスタマイズ(オプション)
intent.putExtra("title", "オープンソースライセンス");
startActivity(intent);

ライブラリによっては META-INF にあるライセンスファイルが必要なので、以下を追加することがあります。

android {
    packagingOptions {
        resources {
            excludes += ['META-INF/DEPENDENCIES', 'META-INF/LICENSE', 'META-INF/LICENSE.txt', 'META-INF/NOTICE']
        }
    }
}

ビルドして、先ほどの OssLicensesMenuActivity を起動することでライセンス一覧が表示されます。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.menu_licenses) {
        Intent intent = new Intent(this, OssLicensesMenuActivity.class);
        startActivity(intent);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

何か一部が Kotlin だったり、Jetpack Compose だったりしますか?その場合の例も出せます!

あなた:

preference.xmlからOssLicensesMenuActivityを開きたい

ChatGPT:

preference.xml から OssLicensesMenuActivity を開くには、PreferenceFragmentCompat を使って、特定の Preference(例えば PreferenceScreen や Preference)がタップされたときに OssLicensesMenuActivity を起動するように処理を追加します。

以下に手順とコード例を示します。

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 他の設定 -->

    <Preference
        android:key="oss_licenses"
        android:title="オープンソースライセンス"
        android:summary="使用しているOSSライブラリのライセンス情報を表示します" />

</PreferenceScreen>
public class SettingsFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.preference, rootKey);

        Preference licensePref = findPreference("oss_licenses");
        if (licensePref != null) {
            licensePref.setOnPreferenceClickListener(preference -> {
                Intent intent = new Intent(requireContext(), OssLicensesMenuActivity.class);
                intent.putExtra("title", "オープンソースライセンス"); // 任意でタイトル設定
                startActivity(intent);
                return true;
            });
        }
    }
}
public class SettingsActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportFragmentManager()
            .beginTransaction()
            .replace(android.R.id.content, new SettingsFragment())
            .commit();
    }
}

Kotlin でも必要なら例を出せます!Jetpack Compose ベースでも対応可能です。

他に「戻るボタン付きにしたい」などのUIカスタマイズや、Compose版も必要ですか?

あなた:

  • What went wrong: Plugin with id 'com.android.application' was already requested at line 1

ChatGPT:

そのエラー:

* What went wrong:
Plugin with id 'com.android.application' was already requested at line 1

は、build.gradle に同じプラグイン(com.android.application)を2回読み込もうとしていることが原因です。

plugins {
    id 'com.android.application'    // ← ここが既にあるのに…
    id 'com.google.android.gms.oss-licenses-plugin'
}

// ↓ 下にまたある(古い記述パターン)
apply plugin: 'com.android.application'  // ← これが原因でエラーになる

または:

plugins {
    id 'com.android.application'  // すでにここで指定してるのに
    id 'com.android.application'  // ← 重複
}

Gradle の plugins ブロックで一度だけ記述すればOK:

plugins {
    id 'com.android.application'
    id 'com.google.android.gms.oss-licenses-plugin'
}

💡 apply plugin: の書き方は plugins {} ブロックと一緒に使わないでください。

  • build.gradle の 上の方(1行目付近) にすでに apply plugin: 'com.android.application' がある場合、それを削除してください。
  • 複数モジュールがある場合、com.android.application はアプリモジュールだけに使ってください。ライブラリモジュールでは com.android.library にしてください。

build.gradle の 上の方(1行目付近) にすでに apply plugin: 'com.android.application' がある場合、それを削除してください。

複数モジュールがある場合、com.android.application はアプリモジュールだけに使ってください。ライブラリモジュールでは com.android.library にしてください。

もしエラーが出ている build.gradle ファイルを貼ってくれれば、どこを直せばよいか具体的に教えられますよ!

あなた:

Plugin [id: 'com.google.android.gms.oss-licenses-plugin'] was not found in any of the following sources:

ChatGPT:

このエラー:

Plugin [id: 'com.google.android.gms.oss-licenses-plugin'] was not found in any of the following sources:

は、Gradle が oss-licenses-plugin を見つけられない という意味です。これは、主に以下の理由で発生します:

まず、プロジェクトレベルの build.gradle に以下が あるかどうか 確認してください:

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6'
    }
}

💡 repositories に google() を忘れると、Gradle がプラグインを見つけられません。

oss-licenses-plugin は plugins {} ブロックでは読み込めない(pluginManagement を使わないとだめ)ため、次のように書いてください:

// アプリモジュールの build.gradle
apply plugin: 'com.android.application'
apply plugin: 'com.google.android.gms.oss-licenses-plugin'

android {
    // ...
}

dependencies {
    implementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
}
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6'
    }
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.android.gms.oss-licenses-plugin'

android {
    // your android config
}

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

Gradle 7 以降で plugins {} を使いたい場合は、settings.gradle または settings.gradle.kts に以下を追加する必要があります:

pluginManagement {
    repositories {
        google()
        gradlePluginPortal()
        mavenCentral()
    }
}

よければ build.gradle の該当部分を貼ってもらえれば、修正箇所をピンポイントで教えられます!

どうします?コード貼ってくれたら見ますよ。

あなた:

Could not compile build file 'C:\Users\Owner\AndroidStudioProjects\AozoraEpub3\build.gradle'.

startup failed: build file 'C:\Users\Owner\AndroidStudioProjects\AozoraEpub3\build.gradle': 5: all buildscript {} blocks must appear before any plugins {} blocks in the script

ChatGPT:

このエラー:

all buildscript {} blocks must appear before any plugins {} blocks in the script

は、build.gradle ファイルの中で plugins {} の前に buildscript {} を書かないといけないというGradleのルールに違反しているためです。

plugins {
    id 'com.android.application'
    id 'com.google.android.gms.oss-licenses-plugin'
}

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6'
    }
}
// ✅ buildscript ブロックを plugins より前に配置する

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6'
    }
}

plugins {
    id 'com.android.application'
    id 'com.google.android.gms.oss-licenses-plugin'
}

oss-licenses-plugin のような古いタイプの Gradle プラグインは plugins {} ブロックではなく、apply plugin: を使うのが推奨されています。

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6'
    }
}

apply plugin: 'com.android.application'
apply plugin: 'com.google.android.gms.oss-licenses-plugin'
  • oss-licenses-plugin は Gradle Plugin Portal ではなく Google の Maven リポジトリにある
  • plugins {} では classpath の指定が効かない

oss-licenses-plugin は Gradle Plugin Portal ではなく Google の Maven リポジトリにある

plugins {} では classpath の指定が効かない

そのため、apply plugin: のほうが確実に動作します。

必要であれば、全体の build.gradle を整え直してあげることもできますよ!コード貼ってもらっても大丈夫です!

あなた:

debug lisence infoと表示される

ChatGPT:

「debug license info」とだけ表示されて、ライセンス一覧が表示されない場合、以下の原因が考えられます。

oss-licenses-plugin はビルド時に licenses.json を生成しますが、以下が 正しく動いていないと中身が空になることがあります。

一度クリーン & リビルドを行う:

./gradlew clean :app:assembleDebug

または Android Studio で:

  • メニューから Build > Clean Project
  • その後、Build > Rebuild Project

メニューから Build > Clean Project

その後、Build > Rebuild Project

play-services-oss-licenses が正しく導入されていても、他の依存ライブラリが含まれていない場合があります。

  • build.gradle に次の依存関係があることを確認:

build.gradle に次の依存関係があることを確認:

dependencies {
    implementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
}
  • ライブラリが api や implementation で追加されているかチェック
  • ライブラリの aar などに license 情報が含まれているかを確認(古いライブラリだと含まれていないことも)

ライブラリが api や implementation で追加されているかチェック

ライブラリの aar などに license 情報が含まれているかを確認(古いライブラリだと含まれていないことも)

Proguard が有効な場合、ライセンス情報が削除されることがあります。

proguard-rules.pro に以下を追加:

-keep class com.google.android.gms.oss.licenses.** { *; }

ライセンス情報が読み込まれていない場合、「debug license info」などの プレースホルダー UI だけが表示されます。

ライセンス Activity の呼び出しコードが正しいことを確認してください:

Intent intent = new Intent(this, OssLicensesMenuActivity.class);
intent.putExtra("title", "オープンソースライセンス"); // ← 任意のタイトル
startActivity(intent);

app/build/generated/oss_licenses に licenses.json が存在するか確認してください。

ファイルが存在していない場合は、oss-licenses-plugin がビルド中にライセンス収集に失敗しています。

  • gradle.properties に android.enableR8=false を一時的に設定して試す
  • ライブラリを追加してもライセンスが出ない場合 → そのライブラリが POM にライセンス情報を含んでいない可能性あり

gradle.properties に android.enableR8=false を一時的に設定して試す

ライブラリを追加してもライセンスが出ない場合 → そのライブラリが POM にライセンス情報を含んでいない可能性あり

よければライセンス一覧が表示されない際の画面キャプチャや、使ってる依存関係のリストも教えてもらえれば、もう一歩深く一緒に見れますよ!

あなた:

preferenceにOSSのgithubのリポジトリへのリンク

ChatGPT:

Preference 画面に「このアプリで使っているOSSの GitHub リポジトリへのリンク」を追加するには、以下のように Preference に intent を設定して、タップ時にブラウザで GitHub を開くようにすればOKです!

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 他の設定項目 -->

    <Preference
        android:key="oss_github"
        android:title="オープンソースリポジトリ"
        android:summary="GitHub 上のライセンス情報を見る"
        android:icon="@android:drawable/ic_menu_info_details"
        android:intent="@android:intent/action/VIEW"
        android:data="https://github.com/your-org/your-repo" />

</PreferenceScreen>

✅ android:intent + android:data を使えば、ブラウザでそのURLを開くことができます。

この方法だと、コード側で findPreference() などの処理を追加しなくても タップで自動的にブラウザが起動します。

Javaなら:

Preference githubPref = findPreference("oss_github");
if (githubPref != null) {
    githubPref.setOnPreferenceClickListener(preference -> {
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/your-org/your-repo"));
        startActivity(intent);
        return true;
    });
}
  • 複数のOSSリポジトリがある場合は、リンクを複数の Preference に分けて作ってもOK。
  • または、1つのHTMLにまとめてそれを WebView で表示するのもアリ。

複数のOSSリポジトリがある場合は、リンクを複数の Preference に分けて作ってもOK。

または、1つのHTMLにまとめてそれを WebView で表示するのもアリ。

必要なら、GitHubの複数リポジトリ一覧を動的にPreferenceに並べる方法や、WebViewで表示するスタイルもお手伝いできますよ!やってみたい方向ある?

あなた:

AAPT: error: attribute android:intent not found.

ChatGPT:

そのエラー:

AAPT: error: attribute android:intent not found.

は、preference.xml に書いた android:intent が 無効な属性であるために発生しています。

<Preference
    android:key="oss_github"
    android:title="オープンソースリポジトリ"
    android:intent="@android:intent/action/VIEW"
    android:data="https://github.com/your-org/your-repo" />

android:intent や android:data という属性は Preference XMLでは使えません。

<Preference
    android:key="oss_github"
    android:title="オープンソースリポジトリ"
    android:summary="GitHub 上のライセンス情報を見る" />
Preference githubPref = findPreference("oss_github");
if (githubPref != null) {
    githubPref.setOnPreferenceClickListener(preference -> {
        Intent browserIntent = new Intent(Intent.ACTION_VIEW,
                Uri.parse("https://github.com/your-org/your-repo"));
        startActivity(browserIntent);
        return true;
    });
}
findPreference<Preference>("oss_github")?.setOnPreferenceClickListener {
    val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/your-org/your-repo"))
    startActivity(intent)
    true
}
<Preference
    android:key="oss_github"
    android:title="オープンソースリポジトリ"
    android:summary="GitHub 上のライセンス情報を見る"
    android:icon="@drawable/ic_github" />

ic_github というアイコンを res/drawable に用意しておけば、見栄えも良くなります!

必要なら、リポジトリを複数並べたり、ライセンス種別ごとにまとめたりする方法も教えますよ!どうしましょう?