java - एंड्रॉइड UserManager.isUserAGoat()के लिए उचित उपयोग के मामले?




android (11)

एपीआई 21 (पहला एंड्रॉइड 5.0 / लॉलीपॉप एसडीके) के रूप में , यह पता लगाता है कि बकरी सिम्युलेटर ऐप इंस्टॉल है या नहीं:

/**
 * Used to determine whether the user making this call is subject to
 * teleportations.
 *
 * <p>As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method can
 * now automatically identify goats using advanced goat recognition technology.</p>
 *
 * @return Returns true if the user making this call is a goat.
 */
public boolean isUserAGoat() {
    return mContext.getPackageManager()
            .isPackageAvailable("com.coffeestainstudios.goatsimulator");
}

इससे यह स्पष्ट हो जाना चाहिए कि if (false) एक संभावित विनाशकारी रणनीति है if (false) इसे चेतावनी मुक्त के रूप में उपयोग करने का डीजेक्लिन का सुझाव । जो पहले हर डिवाइस के लिए false लौटा था, वह अब एक यादृच्छिक यादृच्छिक मूल्य देता है: यदि इसे आपके कोड में काफी गहरा दफनाया गया था तो यह पता लगाने में काफी समय लग सकता है कि आपकी नई बग कहां से आ रही हैं।

निचली पंक्ति: यदि आप किसी विधि के कार्यान्वयन को नियंत्रित नहीं करते हैं और एपीआई दस्तावेज में बताए गए उद्देश्यों के अलावा इसका उपयोग करने का निर्णय लेते हैं, तो आप परेशानी के लिए जा रहे हैं।

मैं एंड्रॉइड 4.2 में पेश किए गए नए एपीआई देख रहा था। UserManager क्लास को देखते हुए मैं निम्नलिखित विधि में आया:

public boolean isUserAGoat()

यह निर्धारित करने के लिए प्रयोग किया जाता है कि यह कॉल करने वाला उपयोगकर्ता टेलीपोर्टेशन के अधीन है या नहीं।

यह लौटाता है कि उपयोगकर्ता यह कॉल कर रहा है या नहीं।

इसका उपयोग कब और कब किया जाना चाहिए?


बकरियों और बकरी के आधार पर ईस्टर अंडे के लिए Google को गंभीर पसंद है। इसके बारे में पिछली स्टैक ओवरफ़्लो पोस्ट भी रही है

जैसा कि पिछले पदों में उल्लेख किया गया है, यह क्रोम टास्क मैनेजर के भीतर भी मौजूद है ( यह पहली बार 200 9 में जंगली में दिखाई दिया था ):

<message name="IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN" desc="The goats teleported column">
    Goats Teleported
</message>

और फिर विंडोज़ में, 2010 की शुरुआत में क्रोम के लिनक्स और मैक संस्करण )। "बकरी टेलीपोर्ट" की संख्या वास्तव में यादृच्छिक है :

 int TaskManagerModel::GetGoatsTeleported(int index) const {
     int seed = goat_salt_ * (index + 1);
     return (seed >> 16) & 255;
 }

बकरियों के अन्य Google संदर्भों में शामिल हैं:

जहां तक ​​मैं कह सकता हूं, बकरियों और Google के सबसे शुरुआती सहसंबंध मूल "मूसिंग विद बकरी" ब्लॉग पोस्ट में हैं।

हम सुरक्षित रूप से यह मान सकते हैं कि यह केवल ईस्टर अंडे है और false वापसी के अलावा, कोई वास्तविक दुनिया का उपयोग नहीं है।


@ डीजेक्लिन answer (जिस तरह से अच्छा जवाब!) को पूरक करना, इस फ़ंक्शन कॉल को आईडीई में ब्रेकपॉइंट रखने के लिए डमी कोड के रूप में भी इस्तेमाल किया जा सकता है जब आप कुछ विशिष्ट पुनरावृत्ति या किसी विशेष रिकर्सिव कॉल में रुकना चाहते हैं, उदाहरण के लिए:

isUserAGoat() को डमी वेरिएबल घोषणा के बजाए इस्तेमाल किया जा सकता है जो आईडीई में एक चेतावनी के रूप में दिखाया जाएगा और, एक्लिप्स विशेष मामले में, ब्रेकपॉइंट मार्क को बंद कर देगा, जिससे इसे सक्षम / अक्षम करना मुश्किल हो जाएगा। यदि विधि को एक सम्मेलन के रूप में उपयोग किया जाता है, तो सभी आमंत्रणों को बाद में कुछ स्क्रिप्ट द्वारा फ़िल्टर किया जा सकता है (प्रतिबद्ध चरण के दौरान शायद?)।

Google लोग भारी ग्रहण उपयोगकर्ता हैं (वे अपनी कई परियोजनाएं एक्लिप्स प्लगइन के रूप में प्रदान करते हैं: एंड्रॉइड एसडीके, जीएई, इत्यादि), इसलिए @ डीजेक्लिन जवाब और यह पूरक उत्तर बहुत कम समझ में आता है (कम से कम मेरे लिए)।


मुझे नहीं पता कि यह "आधिकारिक उपयोग केस" था, लेकिन निम्नलिखित जावा में एक चेतावनी उत्पन्न करता है (जो return स्टेटमेंट के साथ मिश्रित होने return संकलन त्रुटियों का उत्पादन कर सकता है, जिससे पहुंचने योग्य कोड नहीं होता है):

while (1 == 2) { // Note that "if" is treated differently
    System.out.println("Unreachable code");
}

हालांकि यह कानूनी है:

while (isUserAGoat()) {
    System.out.println("Unreachable but determined at runtime, not at compile time");
}

इसलिए मैं अक्सर कोड कोड को डमी करने के सबसे तेज़ तरीके के लिए एक मूर्खतापूर्ण उपयोगिता विधि लिखता हूं, फिर डिबगिंग को पूरा करने में इसे सभी कॉल मिलते हैं, इसलिए कार्यान्वयन में बदलाव नहीं होता है, इसका उपयोग इसके लिए किया जा सकता है।

JLS बताता है कि if (false) विशिष्ट कारण के लिए "पहुंचने योग्य कोड" ट्रिगर नहीं करता है, तो यह डीबग झंडे के लिए समर्थन तोड़ देगा, यानी मूल रूप से इस उपयोग के मामले (एच / टी @auselen)। (उदाहरण के लिए static final boolean DEBUG = false; )।

if मैं अधिक अस्पष्ट उपयोग के मामले का उत्पादन कर रहा हूं, if मैं बदल गया। मेरा मानना ​​है कि आप ग्रहण की तरह अपने आईडीई की यात्रा कर सकते हैं, इस व्यवहार के साथ, लेकिन यह संपादन भविष्य में 4 साल है, और मेरे पास खेलने के लिए ग्रहण पर्यावरण नहीं है।


उनके source , एपीआई 21 में परिवर्तित होने तक विधि को false वापसी के लिए उपयोग किया जाता था।

/**
 * Used to determine whether the user making this call is subject to
 * teleportations.
 * @return whether the user making this call is a goat 
 */
public boolean isUserAGoat() {
    return false;
}

ऐसा लगता है कि इस विधि के लिए डेवलपर्स के रूप में हमारे लिए कोई वास्तविक उपयोग नहीं है। किसी ने पहले कहा है कि यह एक ईस्टर अंडे हो सकता है।

एपीआई 21 में कार्यान्वयन को बदलने के लिए बदल दिया गया था कि पैकेज com.coffeestainstudios.goatsimulator साथ एक स्थापित ऐप है com.coffeestainstudios.goatsimulator

/**
 * Used to determine whether the user making this call is subject to
 * teleportations.
 *
 * <p>As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method can
 * now automatically identify goats using advanced goat recognition technology.</p>
 *
 * @return Returns true if the user making this call is a goat.
 */
public boolean isUserAGoat() {
    return mContext.getPackageManager()
            .isPackageAvailable("com.coffeestainstudios.goatsimulator");
}

स्रोत लिंक यहां है


एंड्रॉइड के प्रत्येक संस्करण में एक मजेदार नाम विधि / निरंतर / जो कुछ भी है।

मैंने कभी देखा एकमात्र व्यावहारिक उपयोग Google I / O प्रतियोगिता के लिए अंतिम कॉल में था, जहां उन्होंने पूछा कि यह एक विशेष संस्करण के लिए क्या था, यह देखने के लिए कि प्रतियोगियों प्रत्येक रिलीज के लिए एपीआई diff रिपोर्ट पढ़ते हैं या नहीं। प्रतियोगिता में प्रोग्रामिंग समस्याएं भी थीं, लेकिन आम तौर पर कुछ सामान्य ज्ञान जिन्हें स्वचालित रूप से सबमिशन की संख्या को उचित मात्रा में कम करने के लिए स्वचालित रूप से वर्गीकृत किया जा सकता है, जो जांचना आसान होगा।


एक समान कॉल है, isUserAMonkey() , यह बंद हो जाता है यदि MonkeyRunner टूल का उपयोग किया जा रहा है। एसडीके स्पष्टीकरण सिर्फ इस के रूप में उत्सुक है।

public static boolean isUserAMonkey(){}     

यदि उपयोगकर्ता इंटरफ़ेस वर्तमान में बंदर द्वारा गड़बड़ कर रहा है तो true वापस आता true

Here स्रोत है।

मैं उम्मीद करता हूं कि यह एक नए SDK उपकरण की प्रत्याशा में जोड़ा गया था जिसे बकरी के साथ कुछ नाम दिया गया था और वास्तव में उस उपकरण की उपस्थिति के परीक्षण के लिए कार्यात्मक होगा।

एक समान प्रश्न भी देखें, ActivityManager में अजीब फ़ंक्शन: isUseramonkey है। इसका क्या मतलब है, इसका उपयोग क्या है?


कृपया नीचे स्रोत कोड देखें:

/**
 * Used to determine whether the user making this call is subject to
 * teleportations.
 *
 * <p>As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method can
 * now automatically identify goats using advanced goat recognition technology.</p>
 *
 * @return Returns true if the user making this call is a goat.
 */
public boolean isUserAGoat() {
    return mContext.getPackageManager()
            .isPackageAvailable("com.coffeestainstudios.goatsimulator");
}

यह Google पर एक अंदरूनी मजाक प्रतीत होता है। यह Google क्रोम टास्क मैनेजर में भी दिखाया गया है। इसका कोई उद्देश्य नहीं है, कुछ इंजीनियरों के अलावा यह मनोरंजक लगता है। यदि आप करेंगे, तो यह एक उद्देश्य है।

  1. क्रोम में, Shift + Esc के साथ कार्य प्रबंधक खोलें।
  2. Goats Teleported कॉलम जोड़ने के लिए राइट क्लिक करें।
  3. आश्चर्य।

बहुत से टेलीपोर्ट बकरियों के बारे में भी एक बड़ी क्रोमियम बग रिपोर्ट है।

निम्नलिखित क्रोमियम स्रोत कोड स्निपेट HN टिप्पणियों से चोरी हो गया है।

int TaskManagerModel::GetGoatsTeleported(int index) const {
  int seed = goat_salt_ * (index + 1);
  return (seed >> 16) & 255;
}

भाषण मान्यता के अनुशासन में, उपयोगकर्ताओं को बकरियों और भेड़ों में विभाजित किया जाता है।

उदाहरण के लिए, पृष्ठ 89 पर :

भेड़ें वे लोग हैं जिनके लिए भाषण मान्यता असाधारण रूप से अच्छी तरह से काम करती है, और बकरियां ऐसे लोग हैं जिनके लिए यह असाधारण रूप से खराब काम करता है। केवल आवाज पहचानकर्ता जानता है कि उन्हें अलग करता है। लोग भविष्यवाणी नहीं कर सकते कि किसकी आवाज आसानी से पहचानी जाएगी और जिसका नहीं होगा। सबसे अच्छी नीति इंटरफ़ेस को डिज़ाइन करना है ताकि यह सभी प्रकार के वातावरण में सभी प्रकार की आवाज़ें संभाल सके

शायद, भविष्य में बकरियों के रूप में एंड्रॉइड उपयोगकर्ताओं को बकरियों की जरूरतों के लिए भाषण मान्यता इंजन को कॉन्फ़िगर करने में सक्षम होने की योजना बनाई गई है। ;-)


मैं इसे थोड़ा अलग करता हूं, और एक अतिरिक्त डिटेक्टर वर्ग लिखा जो View.onTouchListener लागू करता है

onCreate बस इसे निम्नतम लेआउट में जोड़ता है:

ActivitySwipeDetector activitySwipeDetector = new ActivitySwipeDetector(this);
lowestLayout = (RelativeLayout)this.findViewById(R.id.lowestLayout);
lowestLayout.setOnTouchListener(activitySwipeDetector);

जहां id.lowestLayout id.xxx है, लेआउट पदानुक्रम में निम्नतम दृश्य के लिए और सबसे कम लेआउट को रिलेटिवलायआउट के रूप में घोषित किया गया है

और फिर वास्तविक गतिविधि स्वाइप डिटेक्टर वर्ग है:

public class ActivitySwipeDetector implements View.OnTouchListener {

static final String logTag = "ActivitySwipeDetector";
private Activity activity;
static final int MIN_DISTANCE = 100;
private float downX, downY, upX, upY;

public ActivitySwipeDetector(Activity activity){
    this.activity = activity;
}

public void onRightSwipe(){
    Log.i(logTag, "RightToLeftSwipe!");
    activity.doSomething();
}

public void onLeftSwipe(){
    Log.i(logTag, "LeftToRightSwipe!");
    activity.doSomething();
}

public void onDownSwipe(){
    Log.i(logTag, "onTopToBottomSwipe!");
    activity.doSomething();
}

public void onUpSwipe(){
    Log.i(logTag, "onBottomToTopSwipe!");
    activity.doSomething();
}

public boolean onTouch(View v, MotionEvent event) {
    switch(event.getAction()){
        case MotionEvent.ACTION_DOWN: {
            downX = event.getX();
            downY = event.getY();
            return true;
        }
        case MotionEvent.ACTION_UP: {
            upX = event.getX();
            upY = event.getY();

            float deltaX = downX - upX;
            float deltaY = downY - upY;

       // swipe horizontal?
        if(Math.abs(deltaX) > Math.abs(deltaY))
        {
            if(Math.abs(deltaX) > MIN_DISTANCE){
                // left or right
                if(deltaX > 0) { this.onRightSwipe(); return true; }
                if(deltaX < 0) { this.onLeftSwipe(); return true; }
            }
            else {
                    Log.i(logTag, "Horizontal Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                    return false; // We don't consume the event
            }
        }
        // swipe vertical?
        else 
        {
            if(Math.abs(deltaY) > MIN_DISTANCE){
                // top or down
                if(deltaY < 0) { this.onDownSwipe(); return true; }
                if(deltaY > 0) { this.onUpSwipe(); return true; }
            }
            else {
                    Log.i(logTag, "Vertical Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                    return false; // We don't consume the event
            }
        }

            return true;
        }
    }
    return false;
}

}

मेरे लिए वास्तव में अच्छा काम करता है!





java android usermanager