- 投稿日:2020-01-18T22:31:05+09:00
UnityでAndroidビルドエラーUnityEditor.BuildPlayerWindow+BuildMethodExceptionが出た時のライブラリ競合解決が辛過ぎて泣いた
概要
Unityでスマホゲーム作っててiOS向けのリリースがひと段落したのでAndroid向けビルドしたらめっちゃエラー出て泣いた。
つら…環境
- OS:Windows 10
- Unity:2019.1.0f2
Macでも同様のエラー出たので、OS依存のエラーではないことは検証済み。
エラー内容を確認する
ビルド失敗時に表示されるUnity Editorのダイアログには、何もメッセージが表示されず無事死亡。
Consoleを確認すると
UnityEditor.BuildPlayerWindow+BuildMethodException: 145 errors
という素敵なログが出ていた。UnityEditor.BuildPlayerWindow+BuildMethodException: 145 errors at UnityEditor.BuildPlayerWindow+DefaultBuildMethods.BuildPlayer (UnityEditor.BuildPlayerOptions options) [0x00242] in C:\buildslave\unity\build\Editor\Mono\BuildPlayerWindowBuildMethods.cs:194 at UnityEditor.BuildPlayerWindow.CallBuildMethods (System.Boolean askForBuildLocation, UnityEditor.BuildOptions defaultBuildOptions) [0x0007f] in C:\buildslave\unity\build\Editor\Mono\BuildPlayerWindowBuildMethods.cs:97 UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)エラー145個て。初代のポケモン図鑑ならもう少しでコンプやぞ。
UnityEditor.BuildPlayerWindow+BuildMethodException
でググると結構情報出てくるけど、PlayServicesResolver
だけで解決するパターンばかり。どれも今回のエラーとはちょっと違いそうな雰囲気だ。もう少し手前のログを見ると、Gradle buildでコケていることがわかった。
CommandInvokationFailure: Gradle build failed. C:\Program Files\Unity\Hub\Editor\2019.1.0f2\Editor\Data\PlaybackEngines\AndroidPlayer/Tools\OpenJDK\Windows\bin\java.exe -classpath "C:\Program Files\Unity\Hub\Editor\2019.1.0f2\Editor\Data\PlaybackEngines\AndroidPlayer\Tools\gradle\lib\gradle-launcher-4.6.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease" stderr[ D8: Program type already present: com.facebook.unity.FBDialogUtils FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':transformDexArchiveWithExternalLibsDexMergerForRelease'. > com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: ...以下、つらつらと導入ライブラリの一覧が羅列されていた。
stderrにはFacebookのFBDialogUtils
がすでに存在しているとのメッセージが。
D8: Program type already present: com.facebook.unity.FBDialogUtils
Facebook SDKで何か引っかかっているのかな?
正直これだけでは具体的な原因が特定できない。とりあえず現状得られたエラーメッセージでググってみると、SDKの重複に起因して発生するエラーっぽい情報がでてきた。
D8: Program type already present: com.facebook.unity.Constants - Unity Answers
Program type already present error when gradle build - Unity ForumそういえばAndroidアプリのビルドでいろんなSDK入れると、バージョン違いの重複ライブラリが存在してしまい「どっち見ればええねん」的なエラーが出るのを何度も経験していた…
ライブラリの依存関係を調査する
おおよその目星がついたので深掘ってみる。Androidプロジェクト吐いて
gradlew dependencies
コマンド叩くと、ライブラリの依存関係を確認できるらしい。
【Android】ライブラリの依存関係を調査する方法(gradle) - テクノモンキーのアプリ開発日記知らなかった。
Build Settingsで [Export Project] にチェックを付けてAndroidプロジェクトを出力。
Android Studioでプロジェクト開いてgradlew sync実行。エラー出てたら解消させとく。コマンドプロンプト(Macの場合はターミナル)でAndroidプロジェクトのフォルダに移動して
gradlew dependencies
コマンドを叩く。ライブラリ一覧や依存関係がズラリと表示される。細かい部分はスルーするが、同名のバージョン違いが存在したり
play-services
系で被っているものがいくつかあった。ライブラリの競合を解決する
おそらく以下3つのライブラリが重複対象として該当。
- play-services-ads-identifier
- play-services-basement
- facebook-android-wrapper
対応方法としては
- バージョンを合わせる
- 依存関係を無効化する
- 重複ライブラリを除外する
といった案が考えられるようだ。
重複ライブラリを除外する
Androidプロジェクト上では
build.gradle
のdependencies
から対象のimplementationを削除することで、ビルドエラーが解消されapkの生成ができた。build.gradledependencies { ... implementation(name: 'play-services-ads-identifier-16.0.0', ext:'aar') implementation(name: 'play-services-basement-16.0.1', ext:'aar') implementation(name: 'facebook-android-wrapper-7.16.1', ext:'aar') ... }とはいえ毎回UnityからAndroidプロジェクト吐いてAndroid Studioでビルドするのはダル過ぎる。そんなのはiOSだけで十分です。
軽く調べてみると、Unityプロジェクト上では
mainTemplate.gradle
を自前で用意して依存関係を書かなければならないらしい。ちょっと時間も無くて「なるほどわからん」って感じだったので、重複してるaarファイルのバージョン低い方を削除するという力技でUnity上でもビルドエラーを解決(^ω^)
その後、対象ライブラリが関係している広告まわりを実装。ひと通りの動作確認でも問題なさそうだったのでクローズとした。
Androidのビルドエラー解消しんどい
Androidのライブラリ競合問題、5年くらい前から悩まされてた気がするけど、未だにサクッと解消できなくてつらい。はやくAIに仕事奪われたい。
- 投稿日:2020-01-18T17:17:33+09:00
Android Studio 3.5でjava.lang.ClassNotFoundException
applicationのbuld.gradleに追加したら解消された
android { defaultConfig { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
- 投稿日:2020-01-18T11:35:10+09:00
Android で OpenCL の Image2D を使って画像変換する
Android で OpenCL を試す
の続きですOpenCL の Image2D
OpenCL では,基本的な1次元の配列の他に,
画像の2次元のデータを取り扱う Image2D というデータ型が用意されている。
使い方
clCreateImage2D を使って画像データから Image2D を作成する。
引数は、画像データが格納された1次元配列のアドレスを示すポインター。カーネルプログラムからは、
read_imagef と write_imagef を使って読み書きする。Image2D のサンプル
Image2D のサンプルコードとして、
github に公開されているものを試す。
パソコン向けのC++ 版なので、Android向けに変更する。このサンプルはガウシアンフィルタを使って画像のぼかしを行う。
重みは 3x3 の基本的なもの
ぼかしの効果は画像を拡大しないとわからない。|1|2|1|
|2|4|2|
|1|2|1|Android の画像から Image2D を作成する
当初は、Android の Bitmap から Image2D を作成しようとした。
先人の例があるだろと思ったが、全く見つからない。
結局、うまくいかなかった。OpenCV の Maから Image2D を作成する例が見つかったので、
Mat を仲介役にした。Java プログラム
画像を Bitmap 形式にする Bitmap bitmap = BitmapFactory.decodeFile(pathName); OpenCV の Mat 形式にする int width = bitmap.getWidth(); int height = bitmap.getHeight(); Mat mat = new Mat(height, width, CvType.CV_8UC4); Utils.bitmapToMat(bitmap, mat); native プログラムを呼ぶ ImageFilter( mat.getNativeObjAddr() ); public native void ImageFilter(long matAddr);native プログラム
JNIEXPORT void JNICALL Java_jp_ohwada_android_opencl5_MainActivity_ImageFilter( jlong addr ) { // 引数から Mat を復元する Mat& mat = *(Mat*)addr; char *buffer = reinterpret_cast<char *>(mat.data); Image2D を作成する cl_mem image = clCreateImage2D(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &clImageFormat, width, height, 0, buffer, &errNum);アプリを作成する
OpenCL と OpenCV の環境が必要です。
下記を読んでください。
_ AndroidStudio で OpenCV をインポートする
(1) プロジェクトを作成する
(2) OpenCV の Android 用 SDK を用意する
(3) OpenCL のライブラリを用意する
(4) app/src/main/Assets フォルダーにOPenCLのカーネルプログラムファイルを配置する
(5) レイアウトファイルに ImageView を配置する
activity_main.xml<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <ImageView android:id="@+id/outputImageView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:src="@drawable/picture" />(6) MainActivity を作成する
MainActivity.javapublic class MainActivity extends Activity private native void nativeStepOpenCL ( // 詳細 略(7) C++ のプログラムファイルを作成する
step.cppextern "C" void Java_com_intel_sample_androidbasicocl_MainActivity_nativeStepOpenCL ( // 詳細 略(8) CMakeLists.txt を作成する
CMakeLists.txtadd_library( # Sets the name of the library. ImageFilter2D # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). ImageFilter2D.cpp )(9) app/build.gradle を変更する
build.gradleexternalNativeBuild { cmake { path 'src/main/cpp/CMakeLists.txt' } }アプリを実行する
analyze apk により下記の4つが同封されていることが確認できる。
- libImageFilter2D.so
- libOpenCL.so
- libopencv_java4.so
- libc++_shared.so
スクリーンショット
ぱっと見では、変換前後で違いがわからない。
左が変換前、右が変換後画像を拡大すると、ぼかしが効いているのがわかる
左が変換前、右が変換後サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/OpenCL5