Bagaimana saya bisa mendeteksi ketika aplikasi Android berjalan di emulator?

313

Saya ingin kode saya berjalan sedikit berbeda ketika berjalan di emulator daripada ketika berjalan di perangkat. ( Misalnya , menggunakan 10.0.2.2 alih-alih URL publik untuk berjalan melawan server pengembangan secara otomatis.) Apa cara terbaik untuk mendeteksi ketika aplikasi Android berjalan di emulator?

Joe Ludwig
sumber
2
Mungkin kita lihat android.os.Build.
yanchenko
11
Buat saya kagum ... Google harus memiliki cara standar untuk melakukan ini?
powder366
@ Kreker apa masalah, Anda hadapi dalam solusi yang ada?
Khemraj
@Khemraj masalah penipuan. Pria jahat dapat mengejek beberapa sensor dan mengubah beberapa string untuk berpura-pura perangkat nyata
kreker

Jawaban:

159

Bagaimana dengan solusi ini:

    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

Perhatikan bahwa beberapa emulator memalsukan spesifikasi pasti dari perangkat nyata, jadi mungkin tidak mungkin untuk mendeteksinya.

Berikut cuplikan kecil yang dapat Anda buat di APK untuk menunjukkan berbagai hal tentangnya, sehingga Anda dapat menambahkan aturan Anda sendiri:

        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"
pengembang android
sumber
9
Itulah cara Facebook mendeteksi emulator di React-Native
Vaiden
Inilah yang harus saya perbarui setelah menggunakan jawaban dari @Aleadam untuk sementara waktu (itu berhenti bekerja untuk saya).
ckbhodge
@ Id Apa yang harus ditambahkan untuk itu?
pengembang android
2
@ Id Sudahkah Anda mencetak berbagai variabel kelas Build di sana? Sepertinya tidak ada yang istimewa? Sudahkah Anda mencoba ini: github.com/framgia/android-emulator-detector ?
pengembang android
1
@DrDeo Anda dapat menambahkan tanda centang pada build saat ini menggunakan BuildConfig.DEBUG, atau buat build Anda sendiri dengan variabel kustom Anda sendiri. Anda mungkin juga dapat menggunakan Proguard untuk membuat fungsi ini selalu mengembalikan false, atau sesuatu (Anda dapat menghapus log, misalnya, seperti yang ditunjukkan di sini: medium.com/tixdo-labs/… , jadi mungkin itu mungkin juga)
pengembang android
118

Satu sem yang biasa Build.FINGERPRINT.contains("generic")

Aleadam
sumber
Ini bekerja bahkan dengan Galaxy Tab Emulator. Jawaban yang paling disukai tidak.
BufferStack
10
Harap sebutkan apakah sidik jari yang mengandung "generik" adalah emulator atau perangkat. Informasi itu penting tetapi tidak disediakan.
James Cameron
2
Emulator - dinilai dari komentar di depan Anda :)
Dori
8
Ini mengembalikan true pada perangkat saya yang menjalankan CyanogenMod jadi waspadalah.
ardevd
8
The dokumentasi Android mengatakan Anda tidak harus mencoba untuk menafsirkan FINGERPRINTnilai.
gnuf
64

Yah Android id tidak berfungsi untuk saya, saya saat ini menggunakan:

"google_sdk".equals( Build.PRODUCT );
Marcus
sumber
35
Siapa pun yang membaca ini mungkin tertarik untuk mengetahui bahwa string ini tampaknya telah berubah menjadi 'sdk', bukan 'google_sdk'.
Daniel Sloof
15
@Aniel: Saya menggunakan 2.3.3 dengan Google API dan dikatakan 'google_sdk'. Tampaknya itu 'google_sdk' untuk AVD dengan Google API dan 'sdk' untuk yang normal.
Randy Sugianto 'Yuku'
3
Emulator Intel mengembalikan "full_x86" jadi saya tidak akan mengandalkan metode ini.
user462982
3
@GlennMaynard Bentuk sebaliknya jelek, tetapi praktis: Build.PRODUCT bisa jadi nol sedangkan "google_sdk" tidak bisa, jadi formulir ini menghindari potensi kesalahan referensi nol.
Rupert Rawnsley
4
Termasuk lebih banyak kasus: "google_sdk" .equals (Build.PRODUCT) || "sdk" .equals (Build.PRODUCT) || "sdk_x86" .equals (Build.PRODUCT) || "vbox86p" .equals (Build.PRODUCT)
Alberto Alonso Ruibal
31

Berdasarkan petunjuk dari jawaban lain, ini mungkin cara yang paling kuat:

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

Vitali
sumber
Iya. Tidak seperti Build.PRODUCT, Build.HARDWARE (ikan mas) sama dengan SDK dan AOSP resmi. Namun sebelum API 8, Anda harus menggunakan refleksi untuk sampai di bidang HARDWARE.
David Chandler
4
Saya akan pergi denganisEmulator = Build.HARDWARE.contains("golfdish")
holmes
7
@holmes: salah ketik, s / b "ikan mas"
Noah
7
Untuk gambar Android 5.1 x86_64 (dan mungkin gambar 64bit lebih baru lainnya) yang akan menjadi "ranchu" bukannya "ikan mas".
warbi
28

Google menggunakan kode ini di plugin info-perangkat dari Flutter untuk menentukan apakah perangkat itu emulator:

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");
}
Rockney
sumber
20

Bagaimana dengan sesuatu seperti kode di bawah ini untuk mengetahui apakah aplikasi Anda ditandatangani dengan kunci debug? itu tidak mendeteksi emulator tetapi mungkin berhasil untuk tujuan Anda?

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;

} 
Jeff S
sumber
1
Terima kasih untuk kode ini. Saya telah memeriksa dan berfungsi, aldo mengatasi kunci debug panjang bisa menyakitkan tetapi hanya dilakukan sekali. Ini adalah satu-satunya solusi yang dapat diandalkan , karena semua jawaban lainnya membandingkan beberapa bagian dari string info pembuatan OS dengan string statis, dan ini dapat dan telah diubah lebih dari versi Android SDK, dan juga dapat dipalsukan oleh custom Android build.
ZoltanF
Saya pikir itu adalah satu-satunya solusi yang dapat diandalkan. Namun, kunci debug dapat berubah lebih cepat dari yang kita inginkan.
rds
2
Cara yang lebih baik untuk melakukan ini adalah BuildConfig.DEBUG.
Mygod
13

Kode ini berfungsi untuk saya

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

Jika perangkat tidak memiliki kartu sim, ia mengembalikan string kosong: ""

Karena Android emulator selalu mengembalikan "Android" sebagai operator jaringan, saya menggunakan kode di atas.

JJ Kim
sumber
3
Apa yang dikembalikan perangkat tanpa kartu SIM (seperti tablet)?
rds
Menjalankan emulator untuk Android 2.1. Kode ini berfungsi untuk saya, tetapi sejak memutakhirkan Cordova ke 2.7.0, variabel Konteks tampaknya tidak terdefinisi atau apalah. Inilah kesalahan yang saya dapatkan di ADT: "Konteks tidak dapat diselesaikan ke variabel." Juga, menurut komentar di atas, ini BUKAN metode yang dapat diandalkan (meskipun saya sendiri sebenarnya belum gagal).
Rustavore
2
@rds Perangkat yang tidak memiliki kartu SIM mengembalikan string kosong ("")
JJ Kim
Apakah tidak ada cara untuk memiliki nilai ini dengan emulator? karena saya ingin memblokir semua pengguna jika mereka tidak memiliki kartu sim.
c-an
12

Saya mencoba beberapa teknik, tetapi memutuskan untuk memeriksa versi Build.PRODUCT yang sedikit direvisi seperti di bawah ini. Ini tampaknya sedikit berbeda dari emulator ke emulator, itu sebabnya saya memiliki 3 pemeriksaan yang saya miliki saat ini. Saya kira saya bisa saja memeriksa apakah product.contains ("SDK") tetapi berpikir pemeriksaan di bawah ini sedikit lebih aman.

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;
}

FYI - Saya menemukan bahwa Kindle Fire saya memiliki Build.BRAND = "generik", dan beberapa emulator tidak memiliki "Android" untuk operator jaringan.

Patrick
sumber
11

Kedua hal berikut ini disetel ke "google_sdk":

Build.PRODUCT
Build.MODEL

Jadi itu sudah cukup untuk menggunakan salah satu dari baris berikut.

"google_sdk".equals(Build.MODEL)

atau

"google_sdk".equals(Build.PRODUCT)
Sileria
sumber
Saat menjalankan emulator x86 pada Windows, Build.Product adalah sdk_x86.
Edward Brey
memeriksa dengan PRODUCT bukanlah pilihan yang baik karena mengembalikan berbagai nilai dari emulator yang berbeda
Beeing Jk
10

Saya hanya mencari _sdk, _sdk_atau sdk_, atau bahkan hanya sdkbagian dalam Build.PRODUCT:

if(Build.PRODUCT.matches(".*_?sdk_?.*")){
  //-- emulator --
}else{
  //-- other device --
}
SD
sumber
3
Kenapa tidak adil contains("sdk")? Satu-satunya perbedaan (selain menjadi lebih cepat) adalah yang matches(".*_?sdk_?.*")mensyaratkan bahwa jika ada karakter sebelum atau setelah sdk, itu harus garis bawah '_', yang tidak terlalu penting untuk diperiksa.
Nulano
9

Saya tidak pernah menemukan cara yang baik untuk mengetahui apakah Anda berada di emulator.

tetapi jika Anda hanya perlu mendeteksi jika Anda berada dalam lingkungan pengembangan Anda dapat melakukan ini:

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

Semoga bantuan ini ....

Etherpulse
sumber
8

gunakan fungsi ini:

 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;

    }
AndroidCrop
sumber
7

Tidak tahu apakah ada cara yang lebih baik untuk mendeteksi emu, tetapi emulator akan memiliki file init.goldfish.rcdi direktori root.

Ini adalah skrip startup khusus emulator, dan seharusnya tidak ada pada build non-emulator.

Nils Pipenbrinck
sumber
Selama startup sistem Android, kernel Linux pertama memanggil proses "init". init membaca file "/init.rc" dan "init.device.rc". "init.device.rc" adalah perangkat khusus, pada perangkat virtual file ini disebut "init.goldfish.rc".
NET3
7

Ini solusi saya (hanya berfungsi jika Anda menjalankan server web pada mesin debug Anda): Saya telah membuat tugas latar belakang yang dimulai ketika aplikasi dimulai. Itu mencari http://10.0.2.2 dan jika ada itu mengubah parameter global (IsDebug) menjadi true. Ini adalah cara diam untuk mengetahui di mana Anda berlari.

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;
}
}

dari aktivitas utama onCreate:

CheckDebugModeTask checkDebugMode = new CheckDebugModeTask();
checkDebugMode.execute("");
Eyal
sumber
7

Dari Baterai, emulator: Sumber daya selalu AC Charger. Temperatur selalu 0.

Dan Anda dapat menggunakan Build.HOSTuntuk mencatat nilai host, emulator yang berbeda memiliki nilai host yang berbeda.

Louie Liu
sumber
Bagaimana Anda mendapatkan sumber daya dan suhu?
Pengembang Android
6

Saya menemukan emulator baru Build.HARDWARE = "ranchu".

Referensi: https://groups.google.com/forum/#!topic/android-emulator-dev/dltBnUW_HzU

Dan juga saya menemukan cara resmi Android untuk memeriksa apakah emulator atau tidak. Saya pikir itu referensi yang baik untuk kita.

Sejak Android API Level 23 [Android 6.0]

package com.android.internal.util;

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

Kami harus ScreenShapeHelper.IS_EMULATORmemeriksa apakah emulator.

Sejak Android API Level 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");

}

Kami harus Build.IS_EMULATORmemeriksa apakah emulator.

Cara resmi untuk mengecek apakah emulator tidak baru, dan juga mungkin tidak cukup, jawaban di atas juga disebutkan.

Tapi ini mungkin menunjukkan kepada kita bahwa pejabat akan menyediakan cara resmi untuk memeriksa apakah emulator atau tidak.

Seperti menggunakan semua cara yang disebutkan di atas, saat ini kita juga dapat menggunakan dua cara untuk memeriksa apakah emulator.

Cara mengakses com.android.internalpaket dan@hide

dan tunggu SDK resmi yang terbuka.

ifeegoo
sumber
5

Pilihan lain adalah melihat properti ro.hardware dan melihat apakah diatur ke ikan mas. Sayangnya sepertinya tidak ada cara mudah untuk melakukan ini dari Java tetapi sepele dari C menggunakan property_get () .

Tim Kryger
sumber
4
Tampaknya ini berfungsi dari NDK. Sertakan <sys / system_properties.h> dan gunakan __system_property_get ("ro.hardware", buf) lalu periksa bahwa buf adalah "goldfish".
NuSkooler
5

Solusi yang disarankan di atas untuk memeriksa ANDROID_IDbekerja untuk saya sampai saya memperbarui hari ini ke alat SDK terbaru yang dirilis dengan Android 2.2.

Karena itu saya saat ini beralih ke solusi berikut yang berfungsi sejauh ini dengan kerugiannya namun Anda harus meletakkan izin baca 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);
    }
} 
Juri
sumber
5

Semua jawaban dalam satu metode

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;
}
XXX
sumber
Bagus init.goldfish.rchanya ada di emulator; itu juga pemeriksaan yang bagus untuk maju di samping detail Build.
sud007
2
@ sud007 Ada banyak perangkat di luar sana dengan `/init.goldfish.rc dan ini akan mengarah ke false positive. Misalnya, banyak perangkat seri Samsung Galaxy.
laalto
@laalto Anda sebenarnya benar. Saya menemukan itu nanti dan meminta maaf karena saya lupa memperbaruinya di sini.
sud007
kunci tes telah menghasilkan positif palsu bagi saya.
Avi Parshan
Di perangkat mana mereka menghasilkan positif palsu?
Aman Verma
5

Rekomendasi saya:

coba ini dari github.

Mudah mendeteksi emulator android

  • Memeriksa perangkat nyata di Device Farm ( https://aws.amazon.com/device-farm/ )
  • BlueStacks
  • Genymotion
  • Android Emulator
  • Andy 46.2.207.0
  • MEmu bermain
  • Pemutar Aplikasi Nox
  • Koplayer
  • .....

Cara menggunakan dengan Contoh:

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

                    }
                });
Saeed
sumber
4

Anda dapat memeriksa IMEI #, http://developer.android.com/reference/android/telephony/TelephonyManager.html#getDeviceId%28%29

jika saya ingat pada emulator ini kembali 0. Namun, tidak ada dokumentasi saya dapat menemukan yang menjamin itu. walaupun emulator mungkin tidak selalu mengembalikan 0, tampaknya cukup aman bahwa ponsel yang terdaftar tidak akan mengembalikan 0. apa yang akan terjadi pada perangkat android non-ponsel, atau yang tanpa kartu SIM terpasang atau yang saat ini tidak terdaftar pada jaringan?

Sepertinya itu ide yang buruk, bergantung pada itu.

itu juga berarti Anda harus meminta izin untuk membaca keadaan ponsel, yang buruk jika Anda belum memerlukannya untuk hal lain.

jika tidak, maka selalu ada membalik sedikit di suatu tempat sebelum Anda akhirnya menghasilkan aplikasi yang ditandatangani.

Jeff
sumber
5
IMEI kemungkinan juga akan kembali 0pada tablet Android, atau pada ponsel tanpa kartu SIM.
Paul Lammertsma
Kita dapat mengedit IMEI pada emulator. jadi ini mungkin tidak sesuai dengan tujuannya. Juga, mulai dari API 29 kita tidak dapat mengakses IMEI.
Ananth
4
Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")

Ini akan kembali benar jika aplikasi berjalan pada emulator.

Yang harus kita perhatikan adalah tidak mendeteksi semua emulator karena hanya ada beberapa emulator yang berbeda. Mudah diperiksa. Kita harus memastikan bahwa perangkat yang sebenarnya tidak terdeteksi sebagai emulator.

Saya menggunakan aplikasi yang disebut " Berbagi Info Perangkat Android " untuk memeriksa ini.

Pada aplikasi ini, Anda dapat melihat berbagai jenis informasi dari banyak perangkat (mungkin sebagian besar perangkat di dunia; jika perangkat yang Anda gunakan tidak ada dalam daftar, itu akan ditambahkan secara otomatis).

kanji
sumber
Pada Genymotion saya berjalan di mac Build.DEVICE = vbox86p
lxknvlk
4

Memeriksa jawabannya, tidak ada yang berfungsi saat menggunakan emulator LeapDroid, Droid4x atau Andy,

Apa yang berfungsi untuk semua kasus adalah sebagai berikut:

 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;
}
leon karabchesvky
sumber
1
^ airpair.com/android/posts/…
Yousha Aleayoub
Andy_46.16_48 mengembalikan "andy" untuk Build.HARDWARE
Doug Voss
Memimpin positif palsu untuk perangkat seri Samsung J. Digunakan berikut ini untuk mendeteksi emulator: github.com/gingo/android-emulator-detector
bluetoothfx
3

Sebenarnya, ANDROID_ID pada 2.2 selalu sama dengan 9774D56D682E549C (sesuai dengan utas ini + eksperimen saya sendiri).

Jadi, Anda dapat memeriksa sesuatu seperti ini:

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

Bukan yang tercantik, tetapi berhasil.

Eric Eijkelenboom
sumber
8
Saya akan berhati-hati dengan itu karena bug yang mengerikan ini: code.google.com/p/android/issues/detail?id=10603
Brandon O'Rourke
3

Ini bekerja untuk saya

public boolean isEmulator() {
    return Build.MANUFACTURER.equals("unknown");
}
Ribomasi
sumber
3
insinyur firmware yang kami miliki di rumah tidak memperbarui ini; mendapatkan Build.Manufacturer di perangkat keras kami mengembalikan "tidak dikenal". Sidik jari sepertinya cara yang lebih baik.
Seseorang di suatu tempat
3

Letakkan file di sistem file emulator; karena file tidak akan ada pada perangkat nyata, ini harus stabil, dapat diandalkan dan mudah diperbaiki ketika rusak.

Aaron Digulla
sumber
3

Saya telah mengumpulkan semua jawaban pada pertanyaan ini dan muncul dengan fungsi untuk mendeteksi apakah Android berjalan pada vm / emulator:

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;
    }

Diuji pada Emulator, Genymotion dan Bluestacks (1 Oktober 2015).

HUBUNGI19
sumber
3

Kode apa pun yang Anda gunakan untuk melakukan deteksi emulator, saya sangat merekomendasikan penulisan unit test untuk mencakup semua Build.FINGERPRINT, Build.HARDWAREdan Build.MANUFACTURERnilai yang Anda andalkan. Berikut ini beberapa contoh tes:

@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();
}

... dan inilah kode kami (debug log dan komentar dihapus untuk keringkasan):

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;
    }
}
Dan J
sumber
2

Karena mesin emulasi yang mendasari untuk Genymotion adalah VirtualBox dan itu tidak akan berubah dalam waktu dekat saya menemukan kode berikut yang paling dapat diandalkan:

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

Pilihan lain adalah untuk memeriksa apakah Anda dalam mode debug atau mode produksi:

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

sederhana dan andal.

Tidak sepenuhnya menjawab pertanyaan tetapi dalam kebanyakan kasus Anda mungkin ingin membedakan antara sesi debug / tes dan sesi kehidupan basis pengguna Anda.

Dalam kasus saya, saya mengatur google analytics ke dryRun () ketika dalam mode debug sehingga pendekatan ini berfungsi dengan baik untuk saya.


Untuk pengguna yang lebih mahir ada opsi lain. varian gradle build:

di file gradle aplikasi Anda tambahkan varian baru:

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

Di kode Anda, periksa tipe build:

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"); }

Sekarang Anda memiliki kesempatan untuk membangun 3 jenis aplikasi Anda.

mikrofon
sumber