AppSeedのアプリ開発ブログ

アプリ開発会社AppSeed(アップシード)開発担当のブログです。iOS、Android、Unity、Cocos2d-xなどアプリ開発関連のTipsや備忘録、アプリ開発に役立つ情報を発信します。

【Unity】Androidアプリビルド時にライブラリの競合エラーが発生した際の対処法に関するメモ

D8: Program type already present: android.arch.core.internal.SafeIterableMap

Unityで作ったアプリに広告SDKをいれたらAndroidアプリビルド時に上記のようなエラーでビルド出来ない状態になってしまいました。

エラー内容や変更点から考えるとSDK追加時にライブラリの競合が発生していると思われます。

これまでネイティブのAndroidアプリでのライブラリ競合は経験していますが、Unityでは経験なかったので多少苦戦してしまいました。

今後のためにメモとして残しておきたいと思います。



環境:Unity version 2018.3.6f1 Personal



Unity でライブラリ同士の競合が発生した場合の対処法


まず、UnityではGooglePlayService関連のライブラリ競合問題を解決するための方法としては、
「Play Services Resolver」を使うのが一般的なようです。

「Play Services Resolver」はUnityのツールバーの「Assets」から使えます。

【Unity】Androidアプリビルド時にライブラリの競合エラーが発生した際の対処法に関するメモ

「Play Services Resolver」の「Force Resolve」を選択すると、ライブラリ同士の競合を解決してくれるらしいのですが、

複雑な構成になっている場合などは「Play Services Resolver」で解決できない場合もあるようです。

今回の場合、「Play Services Resolver」で解決できなかったので、別の手法を調べてみました。




Unity の「Play Services Resolver」で解決できない場合の対処法

qiita.com


上記の記事によると、「Play Services Resolver」で解決できない場合は、Gradleを使ってビルドする方法が有効らしいです。

Gradleを使ってビルドするためには、Unityが用意している「mainTemplate.gradle」のファイルを使います。

mainTemplate.gradleの場所は
「/Applications/Unity/PlaybackEngines/AndroidPlayer/Tools/GradleTemplates/mainTemplate.gradle」
あたりにありました。


環境によって多少違うかとは思いますが、僕のUnityの「mainTemplate.gradle」は下記のような感じでした。

// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN

buildscript {
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.0'
**BUILD_SCRIPT_DEPS**}
}

allprojects {
    repositories {
        google()
        jcenter()
        flatDir {
            dirs 'libs'
        }
    }
}

apply plugin: 'com.android.application'
**APPLY_PLUGINS**

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
**DEPS**}

android {
    compileSdkVersion **APIVERSION**
    buildToolsVersion '**BUILDTOOLS**'

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        minSdkVersion **MINSDKVERSION**
        targetSdkVersion **TARGETSDKVERSION**
        applicationId '**APPLICATIONID**'
        ndk {
            abiFilters **ABIFILTERS**
        }
        versionCode **VERSIONCODE**
        versionName '**VERSIONNAME**'
    }

    lintOptions {
        abortOnError false
    }

    aaptOptions {
        noCompress = ['.unity3d', '.ress', '.resource', '.obb'**STREAMING_ASSETS**]
    }**SIGN**

    buildTypes {
        debug {
            minifyEnabled **MINIFY_DEBUG**
            useProguard **PROGUARD_DEBUG**
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'**USER_PROGUARD**
            jniDebuggable true
        }
        release {
            minifyEnabled **MINIFY_RELEASE**
            useProguard **PROGUARD_RELEASE**
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'**USER_PROGUARD****SIGNCONFIG**
        }
    }**PACKAGING_OPTIONS****SPLITS**
**BUILT_APK_LOCATION**
    bundle {
        language {
            enableSplit = false
        }
        density {
            enableSplit = false
        }
        abi {
            enableSplit = true
        }
    }
}**SPLITS_VERSION_CODE****REPOSITORIES****SOURCE_BUILD_SETUP**

このテンプレートをUnityプロジェクトの「Assets/Plugins/Android/」の下にコピーして、競合しているライブラリの競合を解決できる設定を行います。




ライブラリの競合調査


どのライブラリが競合しているかの調査ですが、調査方法としてはUnityからAndroidプロジェクトを出力して、
「gradlew dependencies」で調査する感じになるかと思います。


UnityからAndroidプロジェクトを出力する方法は、
「Unity」>「Build Settings」>「PlatformをAndroidに設定」>
「Export Projectにチェック」>「画面下のBuildがExportに変わる」>
「Exportを選択」でAndroidプロジェクトが出力できます。



【Unity】Androidアプリビルド時にライブラリの競合エラーが発生した際の対処法に関するメモ




Android プロジェクトのライブラリ競合の調査方法については以前書いたので省略します。

develop.hateblo.jp

「gradlew dependencies」でライブラリの競合を調査して、Unityプロジェクトに配置した「mainTemplate.gradle」に除外するライブラリの指定等を書いていく感じになります。





ということでUnityで作ったAndroidアプリのライブラリ競合の調査・解決方法をまとめると、


  1. 「Play Services Resolver」で競合解決できるかチェック
  2. 「Play Services Resolver」で競合解決できない場合はAndroidプロジェクトを出力
  3. Androidプロジェクトで「gradlew dependencies」を使ってライブラリ競合調査
  4. 競合している部分を解決する設定を「Assets/Plugins/Android/mainTemplate.gradle」に書いて再度ビルド
  5. 全ての競合がなくなるまで繰り返す

という感じになるのかなと思います。

上記の手法で競合解決ができることはわかりましたが、これだとネイティブのAndroidに比べてライブラリの競合調査の手順が多少増えるので、
もっと効率的にできる方法がないか後で調べてみたいと思います。