Froyo(Android 2.2)でもANDROID_IDでエミュレータを判定する
先日のコード
String android_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID); if (android_id == null) { //エミュレータ } else { //実機 }
Froyoのエミュレータはnullを返さなくなったのでエミュレータの判定には使えないと書いたが、何時どの環境から実行しても同じ値を返すのであれば、単にその値をエミュレータであることの証にすれば良いだけなのではないか。
final String ANDROID_ID_EMULATOR = "9774d56d682e549c"; boolean isInEmulator; String android_id = Secure.getString(this.getApplicationContext().getContentResolver(), Secure.ANDROID_ID); if ( VERSION.SDK_INT < 8 ) { isInEmulator = (android_id == null); } else { isInEmulator = (android_id.equals(ANDROID_ID_EMULATOR)); } //isInEmulatorが真ならばエミュレータ
このANDROID_IDだが、実際にどこで設定されているのかを調べてみた。
-
- com.android.providers.settings.SettingsProvider#ensureAndroidIdIsSet
〜 final SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); String serial = SystemProperties.get("ro.serialno"); if (serial != null) { try { random.setSeed(serial.getBytes("UTF-8")); } catch (UnsupportedEncodingException ignore) { // stick with default seed } } final String newAndroidIdValue = Long.toHexString(random.nextLong()); Log.d(TAG, "Generated and saved new ANDROID_ID"); final ContentValues values = new ContentValues(); values.put(Settings.NameValueTable.NAME, Settings.Secure.ANDROID_ID); values.put(Settings.NameValueTable.VALUE, newAndroidIdValue); final Uri uri = insert(Settings.Secure.CONTENT_URI, values); 〜
システムプロパティro.serialnoの値をシードにして、セキュアランダムから疑似乱数を生成している訳で、シードになっているro.serialno(製品のシリアルNo.か?)が同じならば結果も同じになるので間違いなさそうだ。
アドホックだしAndroidのバージョンが変わった際にまた条件が変わる可能性があるが、それでも必要の無いパーミションを要求してユーザの不審を買うよりは良いだろう。