जब एंड्रॉइड एप्लिकेशन एमुलेटर में चल रहा हो तो मैं कैसे पता लगा सकता हूं?


313

मैं अपने कोड को डिवाइस पर चलाते समय एमुलेटर पर चलने से थोड़ा अलग तरीके से चलाना चाहूंगा। ( उदाहरण के लिए , सार्वजनिक URL के बजाय 10.0.2.2 का उपयोग करके एक विकास सर्वर के खिलाफ स्वचालित रूप से चलाने के लिए।) जब एंड्रॉइड एप्लिकेशन एमुलेटर में चल रहा हो तो पता लगाने का सबसे अच्छा तरीका क्या है?


2
पर एक नज़र हो सकता है android.os.Build
यान्चेंको

11
मुझे विस्मित करना ... Google को ऐसा करने का एक मानक तरीका होना चाहिए?
पाउडर 366

@kreker क्या समस्या है, आप मौजूदा समाधानों का सामना कर रहे हैं?
खेमराज

@ खेमराज धोखाधड़ी के मामले बुराई आदमी कुछ सेंसर का मजाक उड़ा सकता है और असली डिवाइस का नाटक करने के लिए कुछ तार बदल सकता है
kreker

जवाबों:


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

ध्यान दें कि कुछ एमुलेटर असली उपकरणों के नकली सटीक चश्मे हैं, इसलिए इसका पता लगाना असंभव हो सकता है।

यहां एक छोटा सा स्निपेट जिसे आप एपीके में बना सकते हैं, इसके बारे में विभिन्न चीजें दिखा सकते हैं, ताकि आप अपने नियम जोड़ सकें:

        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
यही कारण है कि फेसबुक रिएक्ट-नेटिव में वैद्यों का पता लगाता है
वैडन

यह वही है जो मुझे काफी कुछ समय के लिए @Aleadam से उत्तर का उपयोग करने के बाद अद्यतन करना था (इसने मेरे लिए काम करना बंद कर दिया)।
ckbhodge

@ क्या इसके लिए क्या जोड़ा जाना चाहिए?
एंड्रॉयड डेवलपर

2
@ क्या आपने वहां विभिन्न बिल्ड क्लास चर मुद्रित किए हैं? कुछ खास नहीं लगता? क्या आपने यह कोशिश की है: github.com/framgia/android-emulator-detector ?
एंड्रॉयड डेवलपर

1
@DrDeo आप BuildConfig.DEBUG का उपयोग करके वर्तमान बिल्ड का चेक जोड़ सकते हैं, या अपने स्वयं के कस्टम चर के साथ अपना स्वयं का निर्माण कर सकते हैं। आप इस फ़ंक्शन को हमेशा झूठा लौटाने के लिए, या कुछ और (आप लॉग्स को हटा सकते हैं, उदाहरण के लिए, जैसे कि यहां दिखाया गया है: medium.com/tixdo-labs/… , ताकि शायद यह भी संभव हो)
एंड्रॉयड डेवलपर

118

एक आम एक होने के लिए गाता है Build.FINGERPRINT.contains("generic")


यह गैलेक्सी टैब एमुलेटर के साथ भी काम करता है। शीर्ष पसंद किया गया उत्तर नहीं था।
बफ़रस्टैक

10
कृपया बताएं कि क्या "जेनरिक" युक्त फिंगरप्रिंट या तो एमुलेटर या डिवाइस है। यह जानकारी महत्वपूर्ण है लेकिन प्रदान नहीं की गई है।
जेम्स कैमरून

2
एमुलेटर - आपकी पहले की टिप्पणियों को देखते हुए :)
डोरी

7
यह CyanogenMod चल रहे मेरे उपकरणों पर सच है इसलिए सावधान रहें।
आर्देव

8
Android दस्तावेज़ कहते हैं आप व्याख्या करने के लिए कोशिश नहीं करनी चाहिए FINGERPRINTमूल्य।
gnuf

64

वैसे एंड्रॉइड आईडी मेरे लिए काम नहीं करता है, मैं वर्तमान में उपयोग कर रहा हूं:

"google_sdk".equals( Build.PRODUCT );

35
इसे पढ़ने वाला कोई भी व्यक्ति यह जानने के लिए इच्छुक हो सकता है कि यह स्ट्रिंग 'google_sdk' के बजाय 'sdk' में परिवर्तित हुई है।
डेनियल स्लॉफ

15
@ डैनियल: मैं Google API के साथ 2.3.3 का उपयोग करता हूं और यह 'google_sdk' कहता है। ऐसा लगता है कि यह Google API के साथ AVD के लिए 'google_sdk' है और सामान्य लोगों के लिए 'sdk' है।
रैंडी सुगियंटो 'युकू'

3
Intel एमुलेटर "full_x86" लौटाता है इसलिए मैं इस पद्धति पर भरोसा नहीं करूंगा।
user462982

3
@GlennMaynard रिवर्स फॉर्म बदसूरत है, लेकिन व्यावहारिक: Build.PRODUCT शून्य हो सकता है, जबकि "google_sdk" नहीं हो सकता है, इस प्रकार यह फॉर्म एक संभावित अशक्त संदर्भ त्रुटि से बचा जाता है।
रूपर्ट रॉन्सले

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 के लिए समान है। एपीआई 8 से पहले, आपको हार्डवेयर क्षेत्र पर पहुंचने के लिए प्रतिबिंब का उपयोग करना होगा।
डेविड चैंडलर

4
मैं के साथ जाना चाहते हैंisEmulator = Build.HARDWARE.contains("golfdish")
होम्स

7
@होल्म्स: टाइपो, एस / बी "गोल्डफ़िश"
नूह

7
एंड्रॉइड 5.1 x86_64 छवि के लिए (और शायद अन्य हाल ही में 64 बिट छवियां) जो "सुनहरी" के बजाय "रेंचू" होगी।
वॉरबी

28

Google इस कोड का उपयोग फ़्लटर से डिवाइस- इंफो प्लगइन में यह निर्धारित करने के लिए करता है कि क्या डिवाइस एमुलेटर है:

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
इस कोड के लिए धन्यवाद। मैंने जाँच की है और यह काम कर रहा है, लंबी डिबग कुंजी का मुकाबला करना दर्दनाक हो सकता है लेकिन यह केवल एक बार किया जाता है। यह एकमात्र विश्वसनीय समाधान है, क्योंकि अन्य सभी उत्तर ओएस बिल्ड के कुछ हिस्से की तुलना स्टैटिक स्ट्रिंग के साथ करते हैं, और यह एंड्रॉइड एसडीके संस्करणों में बदल सकता है, और कस्टम एंड्रॉइड बिल्ड द्वारा जाली भी बनाया जा सकता है।
ZoltanF

मुझे लगता है कि यह एकमात्र विश्वसनीय समाधान है। हालाँकि, डिबग कुंजी हम चाहते हैं की तुलना में अधिक तेजी से बदल सकते हैं।
आरडीएस

2
ऐसा करने का एक बेहतर तरीका है BuildConfig.DEBUG
मायगॉड

13

यह कोड मेरे लिए काम करता है

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

यदि डिवाइस में सिम कार्ड नहीं है, तो यह खाली स्ट्रिंग को फिर से जमा करता है: ""

चूंकि एंड्रॉइड एमुलेटर हमेशा "एंड्रॉइड" को नेटवर्क ऑपरेटर के रूप में पुन: पेश करता है, इसलिए मैं उपरोक्त कोड का उपयोग करता हूं।


3
बिना सिम कार्ड (जैसे टैबलेट) के बिना कोई डिवाइस क्या लौटाता है?
आरडीएस

Android 2.1 के लिए रनिंग एमुलेटर। यह कोड मेरे लिए काम कर रहा था, लेकिन कॉर्डोवा को 2.7.0 में अपग्रेड करने के बाद से, कॉनटेक्स्ट वैरिएबल अपरिभाषित या कुछ और प्रतीत होता है। यहाँ मुझे ADT में त्रुटि मिल रही है: "संदर्भ को एक चर में हल नहीं किया जा सकता है।" इसके अलावा, उपरोक्त टिप्पणी के अनुसार, यह एक विश्वसनीय तरीका नहीं है (हालांकि मैंने वास्तव में इसे स्वयं विफल नहीं किया है)।
रुस्तवोर

2
@rds डिवाइसेस जिनके पास सिम कार्ड नहीं है, वे खाली स्ट्रिंग ("")
JJ Kim

क्या एमुलेटर के साथ इस मूल्य का कोई तरीका नहीं है? क्योंकि मैं सभी उपयोगकर्ताओं को ब्लॉक करना चाहता हूँ अगर उनके पास कोई सिम कार्ड नहीं है।
सी-एक

11

दोनों निम्नलिखित "google_sdk" पर सेट हैं:

Build.PRODUCT
Build.MODEL

तो यह निम्न पंक्तियों में से किसी एक का उपयोग करने के लिए पर्याप्त होना चाहिए।

"google_sdk".equals(Build.MODEL)

या

"google_sdk".equals(Build.PRODUCT)

Windows पर x86 एमुलेटर चलाते समय, Build.Product है sdk_x86
एडवर्ड ब्रे

PRODUCT के साथ जाँच करना एक अच्छा विकल्प नहीं है क्योंकि यह विभिन्न एमुलेटर से विभिन्न मान लौटाता है
बीइंग जेके

11

मैंने कई तकनीकों की कोशिश की, लेकिन नीचे दिए गए 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;
}

FYI करें - मैंने पाया कि मेरे किंडल फायर में Build.BRAND = "जेनेरिक" था, और कुछ एमुलेटर में नेटवर्क ऑपरेटर के लिए "एंड्रॉइड" नहीं था।


10

मैं बस के लिए देख रहा हूँ _sdk, _sdk_या sdk_, या यहाँ तक कि sdkभाग में Build.PRODUCT:

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

3
सिर्फ क्यों नहीं contains("sdk")? एकमात्र अंतर (तेजी से होने के अलावा) यह matches(".*_?sdk_?.*")आवश्यक है कि अगर sdk से पहले या बाद में कोई चरित्र है, तो यह एक अंडरस्कोर '_' होना चाहिए, जो कि जांच के लिए महत्वपूर्ण नहीं है।
17 अगस्त को नूलानो

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

पता नहीं कि इमू का पता लगाने के बेहतर तरीके हैं या नहीं, लेकिन एमुलेटर के पास init.goldfish.rcरूट-डायरेक्टरी में फाइल होगी ।

यह एमुलेटर विशिष्ट स्टार्टअप-स्क्रिप्ट है, और यह एक गैर-एमुलेटर बिल्ड पर नहीं होना चाहिए।


एंड्रॉइड सिस्टम के स्टार्टअप के दौरान लिनक्स कर्नेल पहले "इनिट" प्रक्रिया को कॉल करता है। init "/init.rc" और "init.device.rc" फाइलें पढ़ता है। "init.device.rc" डिवाइस विशिष्ट है, आभासी डिवाइस पर इस फ़ाइल को "init.goldfish.rc" कहा जाता है।
नेट 3

7

यहां मेरा समाधान है (यह केवल तभी काम करता है जब आप अपने डिबग मशीन पर एक वेब सर्वर चलाते हैं): मैंने एक पृष्ठभूमि कार्य बनाया है जो एप्लिकेशन शुरू होने पर शुरू होता है। यह के लिए लग रहा है http://10.0.2.2 और यदि वह मौजूद है यह सच करने के लिए एक वैश्विक पैरामीटर (IsDebug) बदल जाता है। यह पता लगाने का एक मौन तरीका है कि आप कहां भाग रहे हैं।

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

बैटरी से, एमुलेटर: पावर स्रोत हमेशा एसी चार्जर है। तापमान हमेशा 0 होता है।

और आप Build.HOSTमेजबान मूल्य रिकॉर्ड करने के लिए उपयोग कर सकते हैं , विभिन्न एमुलेटर के अलग-अलग मेजबान मूल्य हैं।


आप बिजली स्रोत और तापमान कैसे प्राप्त करते हैं?
Android डेवलपर

5

एक और विकल्प यह होगा कि ro.hardware प्रॉपर्टी को देखें और देखें कि इसका सेट गोल्डफिश के लिए है या नहीं। दुर्भाग्य से यह जावा से ऐसा करने का एक आसान तरीका नहीं लगता है, लेकिन प्रॉपर्टी_गेट () का उपयोग करके सी से इसका तुच्छ है ।


4
यह NDK से काम करता प्रतीत होता है। <Sys / system_properties.h> शामिल करें और __system_property_get ("ro.hardware", buf) का उपयोग करें, फिर जांचें कि buf "सुनहरी मछली" है।
नुस्कूलर

5

उपर्युक्त समाधान ANDROID_IDने मेरे लिए काम करने के लिए जाँच करने का सुझाव दिया जब तक कि मैं आज अपडेट नहीं किया गया नवीनतम एंड्रॉइड 2.2 के साथ जारी एसडीके टूल्स।

इसलिए मैंने वर्तमान में निम्नलिखित समाधान पर स्विच किया, जो अब तक नुकसान के साथ काम करता है, हालांकि आपको 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

एक विधि में सभी उत्तर

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केवल एमुलेटर में मौजूद है; इसके अतिरिक्त बिल्ड विवरण के अलावा एक अच्छी जाँच आगे बढ़ रही है।
सूद 7

2
@ sud007 `/init.goldfish.rc के साथ कई डिवाइस हैं और इससे झूठी सकारात्मकता बढ़ेगी। उदाहरण के लिए, कई सैमसंग गैलेक्सी श्रृंखला के उपकरण।
लालाटो

@ अल्टो आप वास्तव में सही थे। मुझे पता चला कि बाद में और माफी माँगने के बाद मैं इसे यहाँ अपडेट करना भूल गया।
सुद 7००

परीक्षण-कुंजी मेरे लिए झूठी सकारात्मकता उत्पन्न कर रही है।
एवी दर्शन

किस उपकरण पर वे झूठी सकारात्मकता उत्पन्न कर रहे हैं?
अमन वर्मा

5

मुझे नया एमुलेटर मिला Build.HARDWARE = "ranchu"

संदर्भ: https://groups.google.com/forum/# .topic/ android- emulator-dev/ dltBnUWHz

और मुझे यह भी पता लगाने के लिए एंड्रॉइड आधिकारिक तरीका मिला कि क्या एमुलेटर है या नहीं। मुझे लगता है कि यह हमारे लिए अच्छा संदर्भ है।

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जांचना होगा कि क्या एमुलेटर।

जिस तरह से यह जांचने के लिए कि एम्यूलेटर नया नहीं है, और शायद पर्याप्त नहीं है, ऊपर दिए गए उत्तर भी बताए गए हैं।

लेकिन यह शायद हमें दिखा सकता है कि आधिकारिक एमुलेटर की जांच करने के लिए आधिकारिक तरीका प्रदान करेगा।

उपर्युक्त सभी तरीकों का उपयोग करते हुए, अभी हम एमुलेटर की जाँच करने के बारे में दो तरीकों का उपयोग कर सकते हैं।

com.android.internalपैकेज का उपयोग कैसे करें और@hide

और आधिकारिक खुले एसडीके की प्रतीक्षा करें।


5

मेरी सिफारिश:

जीथब से यह कोशिश करो ।

Android एमुलेटर का पता लगाना आसान है

  • डिवाइस फ़ार्म में वास्तविक उपकरणों पर जाँच की गई ( https://aws.amazon.com/device-farm/ )
  • BlueStacks
  • Genymotion
  • Android एमुलेटर
  • एंडी 46.2.207.0
  • मेमु खेलते हैं
  • नोक्स ऐप प्लेयर
  • Koplayer
  • .....

उदाहरण के साथ उपयोग कैसे करें:

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. एक गैर-फोन एंड्रॉइड डिवाइस पर क्या होगा, या एक सिम कार्ड स्थापित किए बिना या जो वर्तमान में पंजीकृत नहीं है। नेटवर्क?

ऐसा लगता है कि उस पर निर्भर करने के लिए एक बुरा विचार होगा।

इसका मतलब यह भी है कि आपको फोन की स्थिति को पढ़ने के लिए अनुमति मांगनी होगी, जो कि खराब है यदि आपको पहले से किसी और चीज की आवश्यकता नहीं है।

यदि ऐसा नहीं है, तो अंत में आपके हस्ताक्षर किए गए एप्लिकेशन को उत्पन्न करने से पहले हमेशा कहीं न कहीं थोड़ा सा फ़्लिप होता है।


5
IMEI के 0एंड्रॉइड टैबलेट पर या सिम कार्ड के बिना फोन पर भी लौटने की संभावना है ।
पॉल लामर्ट्समा

हम इम्यूलेटर पर IMEI संपादित कर सकते हैं। इसलिए यह उद्देश्य की पूर्ति नहीं कर सकता है। इसके अलावा, एपीआई 29 से शुरू होकर हम IMEI तक नहीं पहुँच सकते।
अनंत

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

यदि ऐप किसी एमुलेटर पर चल रहा है तो यह सही होना चाहिए।

हमें जिन चीज़ों के बारे में सावधान रहना चाहिए, वे सभी एमुलेटरों का पता नहीं लगा रहे हैं क्योंकि केवल कई अलग-अलग एमुलेटर हैं। यह जांचना आसान है। हमें यह सुनिश्चित करना होगा कि वास्तविक उपकरणों को एमुलेटर के रूप में नहीं पहचाना जाए।

मैंने इसे जांचने के लिए " Android Device Info Share " नाम के ऐप का इस्तेमाल किया ।

इस एप्लिकेशन पर, आप कई उपकरणों की विभिन्न प्रकार की जानकारी देख सकते हैं (शायद दुनिया में सबसे अधिक उपकरण; यदि आप जिस उपकरण का उपयोग कर रहे हैं वह सूची से गायब है, तो यह स्वचालित रूप से जोड़ा जाएगा)।


मेरी उत्पत्ति पर एक मैक पर चल रहा है Build.DEVICE = vbox86p
lxknvlk

3

दरअसल, 2.2 पर ANDROID_ID हमेशा 9774D56D682E549C ( इस थ्रेड + मेरे अपने प्रयोगों के अनुसार) के बराबर है ।

तो, आप कुछ इस तरह की जाँच कर सकते हैं:

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

सबसे सुंदर नहीं है, लेकिन यह काम करता है।


8
मैं इस भयानक बग की वजह से सावधान रहूँगा
ब्रैंडन ओ'रोरके

3

यह मेरे लिए काम करता है

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

3
हमारे पास जो फर्मवेयर इंजीनियर है, उसने इसे अपडेट नहीं किया है; हमारे हार्डवेयर पर Build.Manufacturer "अज्ञात" लौटा। फिंगरप्रिंट बेहतर तरीके से लगता है।
किसी ने

3

एमुलेटर की फाइल सिस्टम में एक फ़ाइल रखो; चूंकि फ़ाइल वास्तविक डिवाइस पर मौजूद नहीं होगी, इसलिए इसे टूटने पर स्थिर, विश्वसनीय और ठीक करने में आसान होना चाहिए।


3

मैंने इस प्रश्न पर सभी उत्तर एकत्र किए हैं और यह पता लगाने के लिए फ़ंक्शन के साथ आया है कि क्या एंड्रॉइड 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;
    }

एमुलेटर, जीनोमिशन और ब्लूस्टैक्स (1 अक्टूबर 2015) पर परीक्षण किया गया।


3

जवाबों की जाँच करते हुए, उनमें से किसी ने भी काम नहीं किया, जब LeapDroid, Droid4x या एंडी एमुलेटर का उपयोग किया गया,

सभी मामलों के लिए क्या काम करता है निम्नलिखित है:

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


एंडी_46.16_48 बिल्ड "के लिए" एंडी "। हार्डवेयर
डग वॉस

सैमसंग J श्रृंखला उपकरणों के लिए लीड पॉजिटिव पॉज़िटिव है। एमुलेटर का पता लगाने के लिए उपयोग किया जाता है: github.com/gingo/android-emulator-detector
bluetoothfx

2

चूंकि Genymotion के लिए अंतर्निहित एमुलेशन इंजन VirtualBox है और यह जल्द ही किसी भी समय बदलने वाला नहीं है, इसलिए मुझे निम्नलिखित कोड सबसे विश्वसनीय लगा:

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

2

जो भी कोड आप एमुलेटर डिटेक्शन करने के लिए उपयोग करते हैं, मैं अत्यधिक सभी को कवर करने के लिए यूनिट टेस्ट लिखने की सलाह दूंगा Build.FINGERPRINT, Build.HARDWAREऔर उन Build.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

एक अन्य विकल्प यह देखने के लिए है कि क्या आप डिबग मोड या प्रोडक्शन मोड में हैं:

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

सरल और विश्वसनीय।

पूरी तरह से सवाल का जवाब नहीं है, लेकिन ज्यादातर मामलों में आप डिबगिंग / टेस्ट सत्र और अपने उपयोगकर्ता आधार के जीवन सत्र के बीच अंतर करना चाहते हैं।

मेरे मामले में मैंने डिबग मोड में सूखने के लिए गूगल एनालिटिक्स सेट किया है (इसलिए डिबग मोड में है तो यह दृष्टिकोण मेरे लिए पूरी तरह से ठीक है।


अधिक उन्नत उपयोगकर्ताओं के लिए एक और विकल्प है। ग्रेडेल बिल्ड वेरिएंट:

अपने एप्लिकेशन की फ़ाइल में एक नया संस्करण जोड़ें:

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 अलग-अलग प्रकार के ऐप बनाने का अवसर है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.