Android
Genymotion

Genymotionと実機をみわける話

More than 3 years have passed since last update.

Genymotion

Genymobile社が開発しているAndroidのエミュレータです。

https://www.genymotion.com/

無料版と有料版がありますが、特に有料版だと至れり尽くせりで、開発目的だけでなく、パソコン上でAndroidアプリを動かすのにまぁ不自由はないって感じです。ゴニョれば、Play Sroreアプリも入れられるし。

と言っても有料版は結構高いですが。

見分ける必要がでてきたので考えた

最初に考えたのは、加速度センサの挙動を使うというものでした。
普通に考えて、加速度は検知しないだろうと。

だがしかし、Genymotionの有料版では、Accelerometerが使えたりします。orz

  • マイクで音を拾ったらどうか → 実機でもマイクのない機種がありそう
  • CPUクロックを実測したらどうか → どうやって?
  • MACアドレスのベンダー調べたらどうか → MACアドレスを取得すること自体好ましくない

と、いろいろ考えたあげく、なんか弱点はないものか、FAQをあさったところ、ようやく見つけました。

Why doesn't the battery level chart visible in the system settings reflect the charge level?

The battery level chart is only updated when the battery is in discharging state. Other states of charge do not affect the battery chart, whatever mode is used (host or manual).

バッテリー情報が実機と違う

そりゃ当然、バッテリーの情報は実機とは異なってくるよね。
ということで、こことかこことかを参考に、バッテリー情報を取得してみます。

@Override
protected void onResume() {
    super.onResume();

    IntentFilter filter = new IntentFilter();        
    filter.addAction(Intent.ACTION_BATTERY_CHANGED);
    registerReceiver(mBroadcastReceiver, filter);
}

@Override
protected void onPause() {
    super.onPause();

    unregisterReceiver(mBroadcastReceiver);
}

private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
            //ここで、intent.get???Extra("???")で、各種情報が得られる
        }
    }
};

Genymotionの場合、onReceive()メソッドのところで得られる情報のなかに、実機じゃまずこれはないだろーというようなものがあるので、それを使って判別することになります(詳細は、実際に試してみてください)。

もし、間違えて実機をエミュレータだと判別してしまうと困るので、いくつかの情報を組み合わせるのがよいでしょう。

問題点

レシーバーへのコールバックで判別するので、処理としては非同期になります。また、onReceive()が呼ばれるタイミングは、特に決まっているわけではないので、そのあたりは何らかの割り切りをして実装する必要があります。

余談

この方法は、Bluestacksでも有効です。