エミュレーターでAndroidアプリケーションが実行されていることを検出するにはどうすればよいですか?


313

エミュレータで実行する場合とデバイスで実行する場合で、コードの実行方法を少し変えたいと思います。(たとえば、パブリックURLの代わりに10.0.2.2を使用して、開発サーバーに対して自動的に実行します。)Androidアプリケーションがエミュレーターで実行されていることを検出する最良の方法は何ですか?


2
見てくださいandroid.os.Build
yanchenko

11
私を驚かせてください... Googleはこれを行う標準的な方法を持っている必要がありますか?
powder366 14

@kreker問題は何ですか、既存のソリューションで直面していますか?
Khemraj 2018年

@Khemraj詐欺の問題。
悪者は

回答:


159

このソリューションはどうですか:

    fun isProbablyAnEmulator() = Build.FINGERPRINT.startsWith("generic")
            || Build.FINGERPRINT.startsWith("unknown")
            || Build.MODEL.contains("google_sdk")
            || Build.MODEL.contains("Emulator")
            || Build.MODEL.contains("Android SDK built for x86")
            || Build.BOARD == "QC_Reference_Phone" //bluestacks
            || Build.MANUFACTURER.contains("Genymotion")
            || Build.HOST.startsWith("Build") //MSI App Player
            || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
            || "google_sdk" == Build.PRODUCT

一部のエミュレータは実際のデバイスの正確な仕様を偽造しているため、それを検出できない場合があることに注意してください。

ここにAPKで作成できる小さなスニペットを使用して、さまざまなことを示し、独自のルールを追加できます。

        textView.text = "FINGERPRINT:${Build.FINGERPRINT}\n" +
                "MODEL:${Build.MODEL}\n" +
                "MANUFACTURER:${Build.MANUFACTURER}\n" +
                "BRAND:${Build.BRAND}\n" +
                "DEVICE:${Build.DEVICE}\n" +
                "BOARD:${Build.BOARD}\n" +
                "HOST:${Build.HOST}\n" +
                "PRODUCT:${Build.PRODUCT}\n"

9
FacebookがReact-Nativeでエミュレーターを検出する方法です
Vaiden

これは、@ Aleadamからの回答をしばらく使用した後に更新する必要があったものです(私にとっては機能しなくなりました)。
ckbhodge

@Sid何を追加する必要がありますか?
Android開発者

2
@Sidさまざまなビルドクラス変数を印刷しましたか?特別なことは何もありませんか?これを試しましたか:github.com/framgia/android-emulator-detector
Android開発者

1
@DrDeo BuildConfig.DEBUGを使用して現在のビルドのチェックを追加するか、独自のカスタム変数を使用して独自のビルドを作成できます。また、この関数は常にfalseを返すようにするためにProGuardのを使用することができ、または何かあるかもしれない(ここに示したように、あなたは、例えば、ログを削除することができます。medium.com/tixdo-labs/...、ので、多分あまりにものが可能)
Androidデベロッパー

118

ある共通のセム Build.FINGERPRINT.contains("generic")


これはGalaxy Tab Emulatorでも機能します。一番好きな答えはしませんでした。
BufferStack 2012年

10
「generic」を含むフィンガープリントがエミュレーターかデバイスかを明記してください。その情報は重要ですが、提供されていません。
James Cameron

2
エミュレーター-あなたの前のコメントで判断する:)
ドリ

8
これは、CyanogenModを実行しているデバイスでtrueを返すため、注意してください。
ardevd 2015

8
Androidのドキュメントは、あなたが解釈しようとするべきではないと言うFINGERPRINT値を。
gnuf

64

まあ、Android idは私には機能しません、私は現在使用しています:

"google_sdk".equals( Build.PRODUCT );

35
これを読んでいる人は誰でも、この文字列が「google_sdk」ではなく「sdk」に変更されているように見えることに興味があるかもしれません。
Daniel Sloof

15
@ダニエル:私はGoogle APIで2.3.3を使用していますが、「google_sdk」と表示されています。Google APIを使用したAVDの場合は「google_sdk」、通常の場合は「sdk」のようです。
Randy Sugianto 'Yuku'

3
Intelエミュレータは「full_x86」を返すので、このメソッドは当てになりません。
user462982 2012

3
@GlennMaynard逆の形式は醜いですが、実用的です。「google_sdk」はできませんが、Build.PRODUCTはnullである可能性があるため、この形式は潜在的なnull参照エラーを回避します。
Rupert Rawnsley 2013

4
さらにケースを含める: "google_sdk" .equals(Build.PRODUCT)|| "sdk" .equals(Build.PRODUCT)|| "sdk_x86" .equals(Build.PRODUCT)|| "vbox86p" .equals(Build.PRODUCT)
アルベルトアロンソルイバル

31

他の回答からのヒントに基づいて、これはおそらく最も堅牢な方法です:

isEmulator = "goldfish".equals(Build.HARDWARE)


はい。Build.PRODUCTとは異なり、Build.HARDWARE(金魚)は公式のSDKとAOSPで同じです。ただし、API 8より前は、リフレクションを使用してHARDWAREフィールドを取得する必要があります。
David Chandler

4
私は一緒に行きますisEmulator = Build.HARDWARE.contains("golfdish")
ホームズ2013年

7
@holmes:typo、s / b "金魚"
Noah

7
Android 5.1 x86_64イメージ(およびおそらく他の最近の64ビットイメージ)の場合、「金魚」ではなく「ranchu」になります。
warbi 2016

28

GoogleはFlutterのデバイス情報プラグインでこのコードを使用して、デバイスがエミュレータかどうかを判断します。

private boolean isEmulator() {
    return (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
        || Build.FINGERPRINT.startsWith("generic")
        || Build.FINGERPRINT.startsWith("unknown")
        || Build.HARDWARE.contains("goldfish")
        || Build.HARDWARE.contains("ranchu")
        || Build.MODEL.contains("google_sdk")
        || Build.MODEL.contains("Emulator")
        || Build.MODEL.contains("Android SDK built for x86")
        || Build.MANUFACTURER.contains("Genymotion")
        || Build.PRODUCT.contains("sdk_google")
        || Build.PRODUCT.contains("google_sdk")
        || Build.PRODUCT.contains("sdk")
        || Build.PRODUCT.contains("sdk_x86")
        || Build.PRODUCT.contains("vbox86p")
        || Build.PRODUCT.contains("emulator")
        || Build.PRODUCT.contains("simulator");
}

20

アプリがデバッグキーで署名されているかどうかを確認するには、以下のコードのようなものはどうですか?それはエミュレータを検出していませんが、あなたの目的のために働くかもしれませんか?

public void onCreate Bundle b ) {
   super.onCreate(savedInstanceState);
   if ( signedWithDebugKey(this,this.getClass()) ) {
     blah blah blah
   }

  blah 
    blah 
      blah

}

static final String DEBUGKEY = 
      "get the debug key from logcat after calling the function below once from the emulator";    


public static boolean signedWithDebugKey(Context context, Class<?> cls) 
{
    boolean result = false;
    try {
        ComponentName comp = new ComponentName(context, cls);
        PackageInfo pinfo = context.getPackageManager().getPackageInfo(comp.getPackageName(),PackageManager.GET_SIGNATURES);
        Signature sigs[] = pinfo.signatures;
        for ( int i = 0; i < sigs.length;i++)
        Log.d(TAG,sigs[i].toCharsString());
        if (DEBUGKEY.equals(sigs[0].toCharsString())) {
            result = true;
            Log.d(TAG,"package has been signed with the debug key");
        } else {
            Log.d(TAG,"package signed with a key other than the debug key");
        }

    } catch (android.content.pm.PackageManager.NameNotFoundException e) {
        return false;
    }

    return result;

} 

1
このコードをありがとう。私が確認し、それが機能していることを確認します。長いデバッグキーに対処するアルドは苦痛を伴う可能性がありますが、それは一度だけ行われます。他のすべての回答はOSビルド情報文字列の一部を静的文字列と比較するため、これが唯一の信頼できるソリューションです。これは、Android SDKバージョンで変更可能であり、変更されており、カスタムAndroidビルドによって偽造することもできます。
ZoltanF 2011

それが唯一の信頼できる解決策だと思います。ただし、デバッグキーは予想よりも早く変更される可能性があります。
RDS

2
これを行うより良い方法はBuildConfig.DEBUGです。
Mygod

13

このコードは私のために働きます

TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String networkOperator = tm.getNetworkOperatorName();
if("Android".equals(networkOperator)) {
    // Emulator
}
else {
    // Device
}

そのデバイスにsimカードがない場合、空の文字列を返します: ""

Androidエミュレーターは常に「Android」をネットワークオペレーターとして返却するため、上記のコードを使用します。


3
SIMカードのないデバイス(タブレットなど)は何を返しますか?
RDS

Android 2.1のエミュレータを実行しています。このコードは私にとってはうまくいきましたが、Cordovaを2.7.0にアップグレードしてから、Context変数が未定義または何かのように見えます。ADTで発生するエラーは次のとおりです。「コンテキストを変数に解決できません。」また、上記のコメントによると、これは信頼できる方法ではありません(実際に自分で失敗したことはありませんが)。
Rustavore 2013年

2
SIMカードを持たない@rdsデバイスが空の文字列( "")を返す
JJ Kim

エミュレータでこの値を得る方法はありませんか?SIMカードがない場合は、すべてのユーザーをブロックしたいからです。
c-an

12

いくつかのテクニックを試しましたが、以下のようにBuild.PRODUCTをチェックするわずかに改訂されたバージョンに落ち着きました。これはエミュレータによってかなり異なるようです。そのため、現在3つのチェックを行っています。product.contains( "sdk")かどうかを確認できたはずですが、以下のチェックの方が少し安全だと思いました。

public static boolean isAndroidEmulator() {
    String model = Build.MODEL;
    Log.d(TAG, "model=" + model);
    String product = Build.PRODUCT;
    Log.d(TAG, "product=" + product);
    boolean isEmulator = false;
    if (product != null) {
        isEmulator = product.equals("sdk") || product.contains("_sdk") || product.contains("sdk_");
    }
    Log.d(TAG, "isEmulator=" + isEmulator);
    return isEmulator;
}

参考までに-Kindle FireにはBuild.BRAND = "generic"があり、一部のエミュレータにはネットワークオペレータ用の "Android"がありませんでした。


11

次の両方が「google_sdk」に設定されています。

Build.PRODUCT
Build.MODEL

したがって、次のいずれかの行を使用すれば十分です。

"google_sdk".equals(Build.MODEL)

または

"google_sdk".equals(Build.PRODUCT)

Windowsでx86エミュレーターを実行している場合、Build.Productはsdk_x86です。
Edward Brey 2013年

PRODUCTを使用したチェックは、異なるエミュレーターからさまざまな値を返すため、良い選択ではありません
Beeing Jk

10

私はちょうど探し_sdk_sdk_またはsdk_、あるいは単にsdk一部でBuild.PRODUCT

if(Build.PRODUCT.matches(".*_?sdk_?.*")){
  //-- emulator --
}else{
  //-- other device --
}

3
なぜcontains("sdk")ですか?唯一の違い(高速化以外)は、matches(".*_?sdk_?.*")sdkの前または後に文字がある場合、アンダースコア '_'である必要があることです。これは、チェックすることはそれほど重要ではありません。
Nulano

9

私があなたがエミュレーターにいるかどうかを見分ける良い方法を見つけたことはありません。

しかし、開発環境にいる場合に検出する必要がある場合は、これを行うことができます:

     if(Debug.isDebuggerConnected() ) {
        // Things to do in debug environment...
    }

この助けを願っています...


8

この関数を使用します。

 public static final boolean isEmulator() {

    int rating = 0;

    if ((Build.PRODUCT.equals("sdk")) || (Build.PRODUCT.equals("google_sdk"))
            || (Build.PRODUCT.equals("sdk_x86")) || (Build.PRODUCT.equals("vbox86p"))) {
        rating++;
    }
    if ((Build.MANUFACTURER.equals("unknown")) || (Build.MANUFACTURER.equals("Genymotion"))) {
        rating++;
    }
    if ((Build.BRAND.equals("generic")) || (Build.BRAND.equals("generic_x86"))) {
        rating++;
    }
    if ((Build.DEVICE.equals("generic")) || (Build.DEVICE.equals("generic_x86")) || (Build.DEVICE.equals("vbox86p"))) {
        rating++;
    }
    if ((Build.MODEL.equals("sdk")) || (Build.MODEL.equals("google_sdk"))
            || (Build.MODEL.equals("Android SDK built for x86"))) {
        rating++;
    }
    if ((Build.HARDWARE.equals("goldfish")) || (Build.HARDWARE.equals("vbox86"))) {
        rating++;
    }
    if ((Build.FINGERPRINT.contains("generic/sdk/generic"))
            || (Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86"))
            || (Build.FINGERPRINT.contains("generic/google_sdk/generic"))
            || (Build.FINGERPRINT.contains("generic/vbox86p/vbox86p"))) {
        rating++;
    }

    return rating > 4;

    }

7

emuを検出するより良い方法があるかどうかはわかりませんが、エミュレーターはinit.goldfish.rcルートディレクトリにファイルを持っています。

これはエミュレータ固有の起動スクリプトであり、エミュレータ以外のビルドには存在しないはずです。


Androidシステムの起動時に、Linuxカーネルは最初にプロセスを「init」と呼びます。initは "/init.rc"および "init.device.rc"ファイルを読み取ります。「init.device.rc」はデバイス固有であり、仮想デバイスでは、このファイルは「init.goldfish.rc」と呼ばれます。
NET3 2018

7

これが私の解決策です(デバッグマシンでWebサーバーを実行する場合にのみ機能します):アプリケーションの起動時に開始するバックグラウンドタスクを作成しました。http://10.0.2.2を探し、存在する場合はグローバルパラメータ(IsDebug)をtrueに変更します。それはあなたが走っている場所を見つけるための静かな方法です。

public class CheckDebugModeTask extends AsyncTask<String, Void, String> {
public static boolean IsDebug = false;

public CheckDebugModeTask()
{

}

@Override
protected String doInBackground(String... params) {     
  try {
    HttpParams httpParameters = new BasicHttpParams();
    int timeoutConnection = 1000;
    HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
    int timeoutSocket = 2000;
    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

    String url2 = "http://10.0.2.2";        
          HttpGet httpGet = new HttpGet(url2);
    DefaultHttpClient client = new DefaultHttpClient(httpParameters);

    HttpResponse response2 = client.execute(httpGet);
    if (response2 == null || response2.getEntity() == null || response2.getEntity().getContent() == null)
    return "";

    return "Debug";

} catch (Exception e) {
    return "";
}
}

@Override
protected void onPostExecute (String result)
{       
if (result == "Debug")
{
    CheckDebugModeTask.IsDebug = true;
}
}

onCreateのメインアクティビティから:

CheckDebugModeTask checkDebugMode = new CheckDebugModeTask();
checkDebugMode.execute("");

7

バッテリーから、エミュレーター:電源は常にAC充電器です。温度は常に0です。

またBuild.HOST、ホスト値を記録するために使用できます。異なるエミュレータには異なるホスト値があります。


どのようにして電源と温度を取得しますか?
Android開発者、

6

新しいエミュレーターを見つけましたBuild.HARDWARE = "ranchu"

リファレンス:https : //groups.google.com/forum/#!topic / android-emulator-dev / dltBnUW_HzU

また、エミュレーターかどうかを確認するAndroid公式の方法を見つけました。これは、私たちにとって良い参考になると思います。

Android APIレベル23以降[Android 6.0]

package com.android.internal.util;

/**
 * @hide
 */
public class ScreenShapeHelper {
    private static final boolean IS_EMULATOR = Build.HARDWARE.contains("goldfish");
}

我々は持っているScreenShapeHelper.IS_EMULATORエミュレータかどうかを確認します。

Android APIレベル24以降[Android 7.0]

package android.os;

/**
 * Information about the current build, extracted from system properties.
 */
public class Build {


    /**
     * Whether this build was for an emulator device.
     * @hide
     */
    public static final boolean IS_EMULATOR = getString("ro.kernel.qemu").equals("1");

}

我々は持っているBuild.IS_EMULATORエミュレータかどうかを確認します。

エミュレータが新しいものではないかどうか、また十分でない可能性があるかどうかを確認するための公式の方法、上記の回答も述べられています。

しかし、これはおそらく、オフィシャルがエミュレータかどうかをチェックするオフィシャルの方法を提供することを示しています。

上記のすべての方法を使用しているので、現在、エミュレーターかどうかを確認するために2つの方法を使用することもできます。

com.android.internalパッケージへのアクセス方法と@hide

公式のオープンSDKを待ちます。


5

もう1つのオプションは、ro.hardwareプロパティを調べ、金魚に設定されているかどうかを確認することです。残念ながら、Javaからこれを行う簡単な方法はないようですが、property_get()を使用してCから簡単に行うことができます。


4
これはNDKから機能するようです。<sys / system_properties.h>をインクルードし、__ system_property_get( "ro.hardware"、buf)を使用して、bufが "goldfish"であることを確認します。
NuSkooler、2011年

5

上記の推奨ソリューションはANDROID_ID、Android 2.2でリリースされた最新のSDKツールに本日アップデートするまで、機能するかどうかを確認するために機能しました。

したがって、私は現在、次の解決策に切り替えましたが、これはこれまでのところ機能しませんが、PHONE_STATEの読み取り許可を設定する必要があります(<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

private void checkForDebugMode() {
    ISDEBUGMODE = false; //(Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID) == null);

    TelephonyManager man = (TelephonyManager) getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
    if(man != null){
        String devId = man.getDeviceSoftwareVersion();
        ISDEBUGMODE = (devId == null);
    }
} 

5

1つの方法ですべての回答

static boolean checkEmulator()
{
    try
    {
        String buildDetails = (Build.FINGERPRINT + Build.DEVICE + Build.MODEL + Build.BRAND + Build.PRODUCT + Build.MANUFACTURER + Build.HARDWARE).toLowerCase();

        if (buildDetails.contains("generic") 
        ||  buildDetails.contains("unknown") 
        ||  buildDetails.contains("emulator") 
        ||  buildDetails.contains("sdk") 
        ||  buildDetails.contains("genymotion") 
        ||  buildDetails.contains("x86") // this includes vbox86
        ||  buildDetails.contains("goldfish")
        ||  buildDetails.contains("test-keys"))
            return true;
    }   
    catch (Throwable t) {Logger.catchedError(t);}

    try
    {
        TelephonyManager    tm  = (TelephonyManager) App.context.getSystemService(Context.TELEPHONY_SERVICE);
        String              non = tm.getNetworkOperatorName().toLowerCase();
        if (non.equals("android"))
            return true;
    }
    catch (Throwable t) {Logger.catchedError(t);}

    try
    {
        if (new File ("/init.goldfish.rc").exists())
            return true;
    }
    catch (Throwable t) {Logger.catchedError(t);}

    return false;
}

良いですね。init.goldfish.rcエミュレータにのみ存在します。ビルドの詳細に加えて、これはさらに良いチェックです。
sud007 2016年

2
@ sud007そこには `/init.goldfish.rcを持つ多くのデバイスがあり、これは誤検知につながります。たとえば、多くのSamsung Galaxyシリーズデバイス。
laalto

@laaltoあなたは実際に正しかった。私は後でそれを見つけ、ここで更新するのを忘れたことをお詫びします。
sud007 2018年

test-keysは私に誤検知を引き起こしています。
Avi Parshan

どのデバイスで誤検知を生成していますか?
アマンバーマ2018

5

私の推薦:

githubからこれを試してください。

Androidエミュレータを簡単に検出

  • デバイスファーム(https://aws.amazon.com/device-farm/)で実際のデバイスを確認した
  • BlueStacks
  • Genymotion
  • Android Emulator
  • アンディ46.2.207.0
  • MEmuプレイ
  • Noxアプリプレーヤー
  • コプレーヤー
  • .....

例の使用方法:

EmulatorDetector.with(this)
                .setCheckTelephony(true)
                .addPackageName("com.bluestacks")
                .setDebug(true)
                .detect(new EmulatorDetector.OnEmulatorDetectorListener() {
                    @Override
                    public void onResult(boolean isEmulator) {

                    }
                });

4

IMEI#、http: //developer.android.com/reference/android/telephony/TelephonyManager.html#getDeviceId%28%29を確認でき ます

エミュレータで思い出すと、これは0を返します。ただし、それを保証するドキュメントはありません。エミュレーターが常に0を返すとは限りませんが、登録済みの電話が0を返さないことはかなり安全に思われます。電話以外のAndroidデバイス、またはSIMカードがインストールされていないデバイス、または現在登録されていないデバイスで何が起こるか通信網?

それに依存するのは悪い考えだと思います。

また、電話の状態を読み取るための許可を求める必要があることを意味します。これは、他の何かのためにまだ必要がない場合は悪いことです。

そうでない場合は、署名されたアプリを最終的に生成する前に、常にどこかを反転させる必要があります。


5
IMEIは0、AndroidタブレットやSIMカードのない電話でも戻る可能性があります。
Paul Lammertsma

エミュレータでIMEIを編集できます。これは目的を果たさないかもしれません。また、API 29以降では、IMEIにアクセスできません。
Ananth

4
Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")

アプリがエミュレーターで実行されている場合、これはtrueを返します。

いくつかの異なるエミュレータしかないため、注意が必要なのは、すべてのエミュレータを検出することではありません。確認も簡単です。実際のデバイスがエミュレータとして検出されないようにする必要があります。

Androidデバイス情報共有」というアプリで確認しました。

このアプリでは、多くのデバイスのさまざまな種類の情報を見ることができます(おそらく世界のほとんどのデバイス。使用しているデバイスがリストにない場合は、自動的に追加されます)。


Macで実行しているGenymotionでBuild.DEVICE = vbox86p
lxknvlk

4

回答を確認したところ、LeapDroid、Droid4x、Andyエミュレーターを使用した場合、どれも機能しませんでした。

すべてのケースで機能するのは次のとおりです。

 private static String getSystemProperty(String name) throws Exception {
    Class systemPropertyClazz = Class.forName("android.os.SystemProperties");
    return (String) systemPropertyClazz.getMethod("get", new Class[]{String.class}).invoke(systemPropertyClazz, new Object[]{name});
}

public boolean isEmulator() {
    boolean goldfish = getSystemProperty("ro.hardware").contains("goldfish");
    boolean emu = getSystemProperty("ro.kernel.qemu").length() > 0;
    boolean sdk = getSystemProperty("ro.product.model").equals("sdk");
    return goldfish || emu || sdk;
}


Andy_46.16_48はBuild.HARDWAREに対して「andy」を返します
Doug Voss

Samsung Jシリーズデバイスの誤検知をリードします。エミュレーターを検出するために以下を使用:github.com/gingo/android-emulator-detector
bluetoothfx

3

実際、2.2のANDROID_IDは常に9774D56D682E549Cに等しくなりますこのスレッド +私の実験によると)。

だから、あなたはこのようなものをチェックすることができます:

String androidID = ...;
if(androidID == null || androidID.equals("9774D56D682E549C"))
    do stuff;

きれいではありませんが、それは仕事をします。


8
この恐ろしいバグのため、私はそれに注意します:code.google.com/p/android/issues/detail?id
Brandon O'Rourke

3

これは私のために働く

public boolean isEmulator() {
    return Build.MANUFACTURER.equals("unknown");
}

3
社内のファームウェアエンジニアはこれを更新していません。ハードウェアでBuild.Manufacturerを取得すると、「不明」が返されました。指紋はより良い方法のようです。
誰かどこか

3

エミュレータのファイルシステムにファイルを置きます。ファイルは実際のデバイスには存在しないので、これは安定していて、信頼でき、壊れたときに簡単に修正できるはずです。


3

私はこの質問のすべての回答を収集し、Androidがvm /エミュレーターで実行されているかどうかを検出する機能を考え出しました:

public boolean isvm(){


        StringBuilder deviceInfo = new StringBuilder();
        deviceInfo.append("Build.PRODUCT " +Build.PRODUCT +"\n");
        deviceInfo.append("Build.FINGERPRINT " +Build.FINGERPRINT+"\n");
        deviceInfo.append("Build.MANUFACTURER " +Build.MANUFACTURER+"\n");
        deviceInfo.append("Build.MODEL " +Build.MODEL+"\n");
        deviceInfo.append("Build.BRAND " +Build.BRAND+"\n");
        deviceInfo.append("Build.DEVICE " +Build.DEVICE+"\n");
        String info = deviceInfo.toString();


        Log.i("LOB", info);


        Boolean isvm = false;
        if(
                "google_sdk".equals(Build.PRODUCT) ||
                "sdk_google_phone_x86".equals(Build.PRODUCT) ||
                "sdk".equals(Build.PRODUCT) ||
                "sdk_x86".equals(Build.PRODUCT) ||
                "vbox86p".equals(Build.PRODUCT) ||
                Build.FINGERPRINT.contains("generic") ||
                Build.MANUFACTURER.contains("Genymotion") ||
                Build.MODEL.contains("Emulator") ||
                Build.MODEL.contains("Android SDK built for x86")
                ){
            isvm =  true;
        }


        if(Build.BRAND.contains("generic")&&Build.DEVICE.contains("generic")){
            isvm =  true;
        }

        return isvm;
    }

Emulator、Genymotion、Bluestacksでテスト済み(2015年10月1日)。


3

あなたはエミュレータ検出を行うために使用どちらのコード、私は非常にすべてカバーするユニットテストの書き込みをお勧めしたいBuild.FINGERPRINTBuild.HARDWAREBuild.MANUFACTURERあなたが依存していることの値を。テストの例をいくつか示します。

@Test
public void testIsEmulatorGenymotion() throws Exception {
    assertThat(
            DeviceUtils.isRunningOnEmulator(
                    "generic/vbox86p/vbox86p:4.1.1/JRO03S/eng.buildbot.20150217.102902:userdebug/test-keys",
                    "vbox86", "Genymotion")).isTrue();

    assertThat(
            DeviceUtils.isRunningOnEmulator(
                    "generic/vbox86p/vbox86p:5.1/LMY47D/buildbot06092001:userdebug/test-keys", "vbox86",
                    "Genymotion")).isTrue();
}

@Test
public void testIsEmulatorDefaultAndroidEmulator() throws Exception {
    assertThat(
            DeviceUtils.isRunningOnEmulator(
                    "generic_x86/sdk_google_phone_x86/generic_x86:5.0.2/LSY66H/1960483:eng/test-keys", "goldfish",
                    "unknown")).isTrue();

    assertThat(
            DeviceUtils.isRunningOnEmulator(
                    "Android/sdk_google_phone_x86_64/generic_x86_64:6.0/MASTER/2469028:userdebug/test-keys",
                    "ranchu", "unknown")).isTrue();
}

@Test
public void testIsEmulatorRealNexus5() throws Exception {
    assertThat(
            DeviceUtils.isRunningOnEmulator("google/hammerhead/hammerhead:6.0.1/MMB29K/2419427:user/release-keys",
                    "hammerhead", "LGE")).isFalse();
}

...そしてここに私たちのコードがあります(簡潔にするためにデバッグログとコメントは削除されています):

public static boolean isRunningOnEmulator() {
    if (sIsRunningEmulator == null) {
        sIsRunningEmulator = isRunningOnEmulator(Build.FINGERPRINT, Build.HARDWARE, Build.MANUFACTURER);
    }

    return sIsRunningEmulator;
}

static boolean isRunningOnEmulator(String fingerprint, String hardware, String manufacturer) {
    boolean isEmulatorFingerprint = fingerprint.endsWith("test-keys");
    boolean isEmulatorManufacturer = manufacturer.equals("Genymotion")
            || manufacturer.equals("unknown");

    if (isEmulatorFingerprint && isEmulatorManufacturer) {
        return true;
    } else {
        return false;
    }
}

2

Genymotionの基盤となるエミュレーションエンジンはVirtualBoxであり、すぐには変更されないため、次のコードが最も信頼性が高いことがわかりました。

   public static boolean isGenymotion() {
        return Build.PRODUCT != null && Build.PRODUCT.contains("vbox");
}

2

別のオプションは、デバッグモードかプロダクションモードかを確認することです。

if (BuildConfig.DEBUG) { Log.i(TAG, "I am in debug mode"); }

シンプルで信頼できる。

完全に質問の答えではありませんが、ほとんどの場合、デバッグ/テストセッションとユーザーベースのライフセッションを区別する必要があります。

私の場合、デバッグモードのときにgoogle analyticsをdryRun()に設定したので、このアプローチはまったく問題なく機能します。


より上級者向けの別のオプションがあります。Gradleビルドバリアント:

アプリのgradleファイルに新しいバリアントを追加します:

buildTypes {
    release {
        // some already existing commands
    }
    debug {
        // some already existing commands
    }
    // the following is new
    test {
    }
}

コードでビルドタイプを確認します。

if ("test".equals(BuildConfig.BUILD_TYPE)) { Log.i(TAG, "I am in Test build type"); }
 else if ("debug".equals(BuildConfig.BUILD_TYPE)) { Log.i(TAG, "I am in Debug build type"); }

これで、3つの異なるタイプのアプリを作成する機会があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.