読者です 読者をやめる 読者になる 読者になる

虚苦心観察ブログ

ブログ管理者である虚苦心が私利私欲に基づいて書いているブログです。主にガジェットのレビューだったり、画像処理のことだったりを記事にしています。

CMake + OpenCV "3.0" + Visual Studio

OpenCV3.0をVisualStudioで使おうとするとこんなエラーが出ます。

error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in main.obj

これはビルド済みのOpenCVが使っているライブラリとビルドしようとしているプログラムのライブラリが同じ必要があるのに違うために起こっているようです。

これはVisualStudioのプロジェクトの設定から「C/C++」→「コード生成」と移動し、「ランタイムライブラリ」の項目をMT→MDに変更すればコンパイルでき、実行可能です。

ただCMakeを使っている場合はCMakeLists.txtを変更するたびにこの変更が毎回元に戻ってしまうので面倒です。
なのでCMakeにMD→MTに変更するための設定を追記します。

stackoverflow.com

重要なのはこちら
set(CompilerFlags
CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE
CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE
)
foreach(CompilerFlag ${CompilerFlags})
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
endforeach()

これを書くことで設定中に存在しているMDをすべてMTに変更してくれます。
めでたしめでたし

Fatal Exception: java.lang.NoClassDefFoundError android.support.v7.appcompat.R$layout

前回の続き。
前回の問題はエディター上では解決されるが、端末上では解決されていなかった。

どういうわけかインポートした外部ライブラリがロードできないでいた。
その一つがSupport Library。今までロードできていたものが使えなくなっていたのだ。

FATAL EXCEPTION: java.lang.NoClassDefFoundError: android.support.v7.appcompat.R$layout

こんなエラーが出ていて、同じ問題に直面している人がいた。stackoverflow.com

どういうわけかMultidexに対応すると解決できるらしい。
ただ、これらの問題が発生するのはAndroid4系から前のバージョン。5系では発生していない。

んー、つらい。

Error:Execution failed for task ':app:transformClassesWithDexForDebug'.

公開中のアプリのメンテナンスでSDKをアップデートしたところ、端末へのインストール時にタイトルのようなエラーが発生した。

エラーの詳細は以下の通り

Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
> com.android.build.transform.api.TransformException: com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'C:\Program Files\Java\jdk1.8.0_51\bin\java.exe'' finished with non-zero exit value 2

上記はStackoverflowで引っかかったエラーの内容をそのまま掲載しているが、私のアプリで発生していたエラーも全く同じ。stackoverflow.com

どうもAndroidStudio、つまりはAndroidのビルドシステムのアップデートにより仕様が変更された様子(詳細はしらない)。
リンク先に解決方法が書かれているが、ちょっと工程が多すぎ。
実際にはbuild.configにmultiDexEnableの項目を加えればよいみたい

stackoverflow.com

とりあえずアプリは動くようになったので解決した。
ここまで書いてなんとなく理解がすすんだのだけど、build.configのdefaultConfigに書かなければいけない項目が変更されたのだろう。おそらく。


Androidは昔に比べれば安定しているとはいえアップデートが早く、仕様が固定されるとも限らないのは辛いですね。
それに比べWindowsLinuxのような開発環境だと仕様が変わることはまずないし、開発手段もたくさんあるので気に入らなければ乗り換えれば良いから精神的に楽なんですよね。Windowsのデスクトップアプリを作ってて最近そういうことを実感してきました。

今回はここまで。

Android Studio + Microsoft Android Emulator

ちょっと手間取ったのでメモ

Microsoft製のAndroidEmulatorをインストール&起動してみたのだがadbに認識されずデバッグに使えないという現象が発生。
公式のサポートに解決方法が載っていた。

Troubleshooting the Visual Studio Emulator for Android

が、そもそもレジストリキーが存在しなかった。
ならキーを新しく作ればいいのか?と思い、

  1. HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node の下に「Android SDK Tools」という名前でキーを作成するとフォルダができる。
  2. そのフォルダを選択し、「Path」という名前で文字列値を追加
  3. 追加する文字列はAndroidSDKのルートフォルダのフルパス。add-onsとかbuild-toolsなどSDKが全部詰まっているフォルダ

以上をしたらエミュレータを起動。起動済みなら再起動。これで動いた。

AndroidStudio単体なら以上で問題なかったのだが、AndroidStudioからAndroidMonitor(Eclipseで動くやつ)を起動するとADBが再起動してしまうためかエミュレータを認識しなかった。

AndroidStudioを起動せずにAndroidMonitorを起動した場合は問題なくエミュレータが認識されることは確認できたが、AndroidStudio↔AndroidMonitorの切り替えは未解決。結構問題なんだよなー・・・

Windows に ipython notebook インストール

基本的にはこちらを参考にした
Python for Windows インストールメモ

ただし、ipythonそのもののインストールはGithubからWindows用のバイナリをダウンロード・インストールする必要があるgithub.com

pipでのインストール時にバージョンを指定する必要がある様子
pip install ipython==3.2.1

FragmentのレイアウトでViewPagerを使い、PagerAdapterにFragment(State)PagerAdapterを使う場合の注意点

題名のままですが、実際にはFragmentの中でFragmentを管理する場合の注意点です。

どういった状況で発生するかというと(私の場合)、
1. Parent1Fragmentの中でViewPagerを使ってChildAFragmentとChildBFragmentを表示します。
2. このParent1Fragmentから別のParent2Fragmentへ遷移します。
3. 戻るボタンでParent1Fragmentへ戻ります。

このような流れをとるとFragment(State)PagerAdapterへ与えたFragmentManagerがgetFragmentManager()メソッドから得たものだと、1.の状態が正常に復元されません。
Parent1Fragmentの状態だけが復元され、ChildAFragmentとChildBFragmentは復元されないという気持ち悪い状態に陥ります。

これはFragmentの中でFragmentを管理している場合に起こります。
またFragmentの状態の復元はFragmentの遷移が発生し、戻るボタンで元のFragmentへ戻った場合に発生します(他の場合もあるかも)。
FragmentA→FragmentB→(戻るボタン)→FragmentA というような移動の時に発生し、Homeボタンでアプリを終了したときには発生しないようです。

解決方法はgetChildFragmentManager()メソッドで別のFragmentManagerを用意すること。
これによりFragmentの管理が階層化され正常に復元がされるようになります。


getFragmentManagerを使おうがgetChildFragmentManagerを使おうがプログラム上は正常に動いてしまい何が原因だかわからず半日つぶしてしまいました。。。。
誰かの助けになれば幸いです。


参考
Fragmentをネストする際の注意点 - Just for Fun
Y.A.M の 雑記帳: Fragment in Fragment 時の注意点

AndroidStudioでdebug.keystoreを共有する

GitなどのVCSを使って複数のPCで作業しているとDebugで使うdebug.keystoreを共有して使いたいときがあります。
なぜかというと、デフォルトで使用されるdebug.keystoreはPC毎に異なるもののため、PC1でデバッグ後、PC2でデバッグしようとするとインストール時にAndroid端末側でエラーが発生し、PCを変えるごとにアプリをアンインストール・インストールを繰り返さなくてはなるからです。
これは同じアプリの開発者間でAndroid端末を共有している場合にもいえることです。

アプリ内にデータを保存していないものであればアンインストールしても特に問題ありませんが、ほとんどのアプリはデータを保存していると思うのでアンインストールしたくない、という問題は多いと思います。

このような問題はdebug.keystoreを共有することで解決します。
解決策はこちら

What is the equivalent of Eclipse "Custom debug Keystore" in Android studio? - Stack Overflow

アプリとして起動可能なモジュールのgradle.buildを修正します。
修正箇所は以下。

android {
    signingConfigs {
        debug {
            storeFile file("your.keystore")
        }
    }
}

your.keystoreには相対パスも指定可能です。パスの表記は(WindowsPCでも)Unix方式。
たとえば以下のようなプロジェクトのディレクトリ構造だったとしたら(だいぶ省いてます)、

Project
├── build.gradle
├── debug.keystore <-デバッグ用キーストア
├── settings.gradle
└── AppModule
    ├── build
    ├── build.gradle <-開発中アプリのgradle設定ファイル(これを修正)
    └── src

"your.keystore"には"../debug.keystore"と指定することが可能です。
プロジェクトのリポジトリ内にdebug.keystoreを含め、デバッグ用キーストアの位置を相対パスで指定することでどのPCでも設定を変更せずに開発が行えます。