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

clock-up-blog

go-mi-tech

VS Xamarin.Android で「A numeric comparison was attempted on "$(_DeviceSdkVersion)" that evaluates to "" instead of a number」って出るときの対処

Xamarin Android Visual Studio トラブルシューティング

(If you prefer English than Japanese, you can see English article.)

筆者の環境

  • Visual Studio Enterprise 2015 Version 14.0.25123.00 Update 2
  • Xamarin 4.1.0.530 (2e39740)
  • Xamarin.Android 6.1.0.71 (4e27558)
  • Genymotion Version 2.7.2 Revision 20160613-d7856fb

エラー内容

Visual Studio の Xamarin のビルド時に以下のようなエラーが出ることがある。

1>C:\android-sdk-windows\build-tools\23.0.1\zipalign.exe 4 "C:\Users\kobake\Gorilla\Player\Droid\bin\Debug\uxdivers.gorilla-Signed-Unaligned.apk" "bin\Debug\\uxdivers.gorilla-Signed.apk" 
1>C:\android-sdk-windows\platform-tools\adb.exe -s 192.168.32.101:5555  shell getprop ro.build.version.sdk 
1>"adb.exe" はコード 1 を伴って終了しました。
1>条件 "$(_DeviceSdkVersion) >= 21" で、数字ではなく "" と評価された "$(_DeviceSdkVersion)" に対して、数値比較を実行しようとしました。
1>ビルドに失敗しました。

「条件 "$(_DeviceSdkVersion) >= 21" で、数字ではなく "" と評価された "$(_DeviceSdkVersion)" に対して、数値比較を実行しようとしました。」っていうエラー。

英語版の場合は「A numeric comparison was attempted on "$(_DeviceSdkVersion)" that evaluates to "" instead of a number, in condition "$(_DeviceSdkVersion) >= 21".」っていうエラー。

検証

「$(_DeviceSdkVersion)」というキーワードは実はエンジン内部の変数(と憶測した)なので、ここに囚われてはいけない。

このエラーが出る直前に「...\adb.exe -s ... shell getprop ro.build.version.sdk」という行があることに注目。このエラーの本質はこの adb コマンドの失敗である。

試しにコマンドプロンプトで該当の adb コマンドを実行してみる。(これは環境により違うので、個々にエラーログからコピる必要がある)

> C:\android-sdk-windows\platform-tools\adb.exe -s 192.168.44.101:5555  shell getprop ro.build.version.sdk
adb server version (32) doesn't match this client (36); killing...
error: could not install *smartsocket* listener: cannot bind to 127.0.0.1:5037: 通常、各ソケット アドレスに対してプロトコル、ネットワーク アドレス、またはポートのどれか 1 つのみを使用できます。 (10048)
could not read ok from ADB Server
* failed to start daemon *
error: cannot connect to daemon

「adb server version (32) doesn't match this client」というエラーログが表示された。
adb プロトコルの不一致により Androidバイスとの通信が失敗していることがわかる。

今回の対策(環境依存です。いつでもこの対策が通じるとは限りません)

前項の検証により adb のプロトコル不一致が生じていることが分かったので、これに対する対策を行う。
※「"$(_DeviceSdkVersion)"」に関連したエラーが出たからといってこれと同じ原因とは限らない。これについては各自、前項の検証を行い原因を突き止めること。

adb の検索

まずコンピュータ内のファイル検索により adb.exe がどこにあるかを探す。
今回は以下のファイルが見つかった。

  • C:\android-sdk-windows\platform-tools\adb.exe
  • C:\Program Files\Genymobile\Genymotion\tools\adb.exe

adb バージョンの確認

コマンドプロンプトにて、それぞれの adb のバージョンを確認する。

> C:\android-sdk-windows\platform-tools\adb.exe version
Android Debug Bridge version 1.0.36
Revision fd9e4d07b0f5-android

> "C:\Program Files\Genymobile\Genymotion\tools\adb.exe" version
Android Debug Bridge version 1.0.32
Revision 3de313b5b3b4-android

前者のほうが新しいバージョンであることが確認できた。
ちなみに後者の Genymotion というのは Androidエミュレータである。公式エミュレータより高速なので愛用している。

Genymotion が参照する adb を新しいほうに切り替える

f:id:kobake:20160621111405p:plain:w500
Genymotion の Settings ボタンから Settings 画面を開き、


f:id:kobake:20160621105306p:plain:w500
Settings 画面内の ADB タブを開き、Use custom Android SDK tools の設定を行う。
設定内容は前項で見つけた新しい Android SDK の場所。(※実際にはこれは Visual Studio メニューの [ツール] - [オプション] - [Xamarin] - [Android Settings] - [Android SDK Location] からも確認できる)

以上、対応おしまい。(一応 Genymotion も最新のものを使っているのですが、内部に含まれている adb がちょっと古いようでした)

Genymotion の設定項目については以下のフォーラムにて Christopher Amos さんから教わりました。


ちなみに Amos さんから教わった情報を知る前には、以下のような強引な対策をしていました。一応以下に残しておきますが非推奨です。

お勧めしない対策:adb のバージョンを無理やり一致させる

かなり強引ですが、古いほうの adb を新しい adb で上書いちゃえば一応問題は解決します。
adb.exe, AdbWinApi.dll, AdbWinUsbApi.dll あたりを上書きコピーしちゃいます。
(コピー前にタスクマネージャから adb を強制終了させておくと良いです)

おしまい

海外含め、とにかく情報を発信してみると何かしらのレスポンスがあり、時にそれが糧となり、ありがたいことです。

Thank you very much for the good information, Christopher Amos.

});