यदि एपीके हस्ताक्षरित है या "डीबग बिल्ड" की जांच कैसे करें?


121

जहाँ तक मुझे पता है, Android में "रिलीज़ बिल्ड" पर हस्ताक्षर किए गए हैं। कोड से इसकी जांच कैसे करें या क्या ग्रहण में कुछ प्रकार के गुप्त दोष हैं?

मुझे वेब सेवा डेटा से सूची दृश्य आइटमों को डिबग करने के लिए इसकी आवश्यकता है (नहीं, लॉगकैट एक विकल्प नहीं है)।

मेरे विचार:

  • अनुप्रयोग है android:debuggable, लेकिन किसी कारण से जो विश्वसनीय नहीं दिखता है।
  • हार्ड-कोडिंग डिवाइस आईडी अच्छा विचार नहीं है, क्योंकि मैं साइन किए गए APK के परीक्षण के लिए उसी डिवाइस का उपयोग कर रहा हूं।
  • कोड में कहीं मैनुअल ध्वज का उपयोग करना? प्रशंसनीय, लेकिन निश्चित रूप से कुछ समय में बदलने के लिए भूल जाते हैं, प्लस सभी प्रोग्रामर आलसी हैं।

रोल-बैक फिल का संपादन। यह कार्यक्रम के बारे में सवाल नहीं है कि कानूनी रूप से बाजार में वितरित किया जा रहा है या नहीं। यह सवाल है कि अभी भी "डिबग मोड" में कार्यक्रम है।
Im0rtality

ऐसा करने का यह सबसे आसान तरीका है: stackoverflow.com/a/23844716/2296787
MBH

जवाबों:


80

डिबग या रिलीज़ सर्टिफिकेट का उपयोग करके एप्लिकेशन का निर्माण किया जाता है या नहीं यह जांचने के लिए अलग-अलग तरीके हैं, लेकिन निम्नलिखित तरीका मुझे सबसे अच्छा लगता है।

एंड्रॉइड डॉक्यूमेंटेशन साइनिंग योर एप्लिकेशन में दी गई जानकारी के अनुसार , डिबग की में निम्नलिखित विषय विशिष्ट नाम होते हैं: " CN = Android डिबग, O = Android, C = US "। हम इस जानकारी का उपयोग परीक्षण करने के लिए कर सकते हैं कि क्या हमारे कोड में हार्डकॉग डीबग कुंजी हस्ताक्षर के बिना पैकेज डिबग कुंजी के साथ हस्ताक्षरित है।

दिया हुआ:

import android.content.pm.Signature;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

आप इस तरह एक अलग विधि लागू कर सकते हैं:

private static final X500Principal DEBUG_DN = new X500Principal("CN=Android Debug,O=Android,C=US");
private boolean isDebuggable(Context ctx)
{
    boolean debuggable = false;

    try
    {
        PackageInfo pinfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(),PackageManager.GET_SIGNATURES);
        Signature signatures[] = pinfo.signatures;

        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        for ( int i = 0; i < signatures.length;i++)
        {   
            ByteArrayInputStream stream = new ByteArrayInputStream(signatures[i].toByteArray());
            X509Certificate cert = (X509Certificate) cf.generateCertificate(stream);       
            debuggable = cert.getSubjectX500Principal().equals(DEBUG_DN);
            if (debuggable)
                break;
        }
    }
    catch (NameNotFoundException e)
    {
        //debuggable variable will remain false
    }
    catch (CertificateException e)
    {
        //debuggable variable will remain false
    }
    return debuggable;
}

6
कई आयात मिलानों को हल करने में मदद करने के लिए, यहां उपयोग की जाने वाली कक्षाएं हैं java.security.cert.X509Certificate, java.security.cert.CertificateExceptionऔर android.content.pm.Signature। अन्य सभी वर्ग मेरे लिए कई मैच प्रस्तुत नहीं करते हैं
क्रिस्चियन गार्सिया

1
इन आयातों के साथ संपादित उत्तर। धन्यवाद!
कोरी पेटोस्की

क्या यह अनुप्रयोग वर्ग के ऑनक्रैट विधि पर चलाया जा सकता है?
Android डेवलपर

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

परिणाम दक्षता के लिए कैश किया जा सकता है।
ftvs

138

डीबग करने योग्य ध्वज की जाँच करने के लिए, आप इस कोड का उपयोग कर सकते हैं:

boolean isDebuggable =  ( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) );

Kotlin:

val isDebuggable = 0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE

अधिक जानकारी के लिए, कृपया देखें Android LVL एप्लिकेशन सुरक्षित करना

वैकल्पिक रूप से, यदि आप ग्रेडेल का सही उपयोग कर रहे हैं, तो आप जांच सकते हैं कि क्या BuildConfig.DEBUGयह सही है या गलत।


ऐसा लगता है कि यह अभी भी प्रकट के एंड्रॉइड की जांच करता है: डीबग करने योग्य
xster

2
घोषणापत्र डीबग करने के लिए पहले एक परीक्षण, यह पदावनत है। दूसरा लाइब्रेरियों के लिए संभव नहीं है, लिब का अपना बिल्डकॉनफिग होगा - ऐप का बिल्डकॉनफिग आयात करने में सक्षम नहीं है, जो लीब का उपयोग कर रहा है। इसके लिए स्पष्ट उत्तर "ओके" है
क्रिस्टोफ़

यह उत्तर सभी मामलों में लाइब्रेरी प्रोजेक्ट या एप्लिकेशन प्रोजेक्ट की परवाह किए बिना काम करेगा।
लवकुश अग्रवाल

131

मार्क मर्फी द्वारा उत्तर दिया गया

सबसे सरल, और सबसे अच्छा दीर्घकालिक समाधान , उपयोग करना है BuildConfig.DEBUG। यह एक booleanमान है जो trueडीबग बिल्ड के लिए होगा , falseअन्यथा:

if (BuildConfig.DEBUG) {
  // do something for a debug build
}

8
इस दृष्टिकोण का एकमात्र दोष यह है कि यह पुस्तकालय परियोजनाओं (आरा) में काम नहीं करेगा। जब पुस्तकालयों का निर्माण किया जाता है, तो यह गलत होगा, इसलिए यहां तक ​​कि एक एप्लिकेशन जो लाइब्रेरी का उपयोग करता है डिबग मोड में है, इस चेक के परिणामस्वरूप लाइब्रेरी कोड में झूठी हो जाएगी।
वीटो एंडोलिनी

24

यदि आप एक APKसांख्यिकीय जाँच करना चाहते हैं , तो आप उपयोग कर सकते हैं

aapt dump badging /path/to/apk | grep -c application-debuggable

यह आउटपुट 0यदि APKडिबग करने योग्य नहीं है और 1यदि यह है।


3
अंतिम APK पर सत्यापित करने के लिए यह एकमात्र समाधान है। अन्य प्रतिक्रियाएं मानती हैं कि आपके पास स्रोत है।
गिलर्मो टोबार

1
aaptयहाँ रहता है/Users/USER_NAME/library/Android/sdk/build-tools/28.0.3/aapt
केसी

21

शायद देर से, लेकिन iosched उपयोग करता है BuildConfig.DEBUG


क्या अब इसका उपयोग करना सुरक्षित है? एक लेख में कहा गया है कि इसमें कुछ मुद्दे हैं: digipom.com/be-careful-with-buildconfig-debug
Android डेवलपर

यह सबसे अच्छा जवाब है!
पीटर फॉर्चिन

यदि आप एक 3 पार्टी पुस्तकालय लिख रहे हैं और संकलन समय पर बिल्डकॉनफिग के पैकेज को नहीं जानते हैं।
सैम डोज़ोर

सैम, क्या आप इस पर विस्तार से बता सकते हैं?
अग्नमनीस

10

सबसे पहले इसे अपनी build.gradle फ़ाइल में जोड़ें, इससे डिबग और रिलीज़ बिल्ड के साथ-साथ चलने की भी अनुमति मिलेगी:

buildTypes {
    debug {
        applicationIdSuffix ".debug"
    }
}

इस विधि को जोड़ें:

public static boolean isDebug(Context context) {
    String pName = context.getPackageName();
    if (pName != null && pName.endsWith(".debug")) {
        return true;
    } else {
        return false;
    }
}

1
मैं इस जवाब को पसंद करता हूं, क्योंकि यह विश्वसनीय है। मुझे अपने Google मानचित्र API कुंजी में एक नई "अनुमत Android एप्लिकेशन" प्रविष्टि जोड़ने की आवश्यकता थी (हालांकि एप्लिकेशन आईडी अलग है)।
बाज

5

डिबग बिल्ड के रूप में अच्छी तरह से हस्ताक्षरित है, बस एक अलग कुंजी के साथ। यह स्वचालित रूप से ग्रहण द्वारा उत्पन्न होता है, और इसका प्रमाण पत्र केवल एक वर्ष के लिए मान्य होता है। क्या समस्या है android:debuggable? आप यह मान कोड का उपयोग करके प्राप्त कर सकते हैं PackageManager


3

एक और विकल्प, ध्यान देने योग्य है। यदि आपको केवल डिबगर संलग्न होने पर कुछ कोड निष्पादित करने की आवश्यकता है, तो इस कोड का उपयोग करें:

if (Debug.isDebuggerConnected() || Debug.waitingForDebugger()) { 
    //code to be executed 
}

0

के साथ हल किया android:debuggable। यह पढ़ने की मद में बग था जहां कुछ मामलों में आइटम पर डिबग ध्वज को रिकॉर्ड में संग्रहीत नहीं किया जा रहा था जिसका if (m.debug && !App.isDebuggable(getContext()))हमेशा मूल्यांकन किया जाता था false। मेरी गलती।


13
मुझे लगता है कि यह एक साल से अधिक पुराना है, हालांकि आपको @ ओहर रहमान के जवाब को स्वीकार करना चाहिए था, यह नहीं। जबकि आपने जो पोस्ट किया है वह आपने आखिरकार किया है, यह वास्तव में आपके द्वारा पूछे गए सवाल का जवाब नहीं देता है, जबकि उमर का समाधान ऐसा प्रतीत होता है, जिसका अर्थ है कि वह स्वीकृत क्रेडिट का हकदार है।
महा

7
@ मा - अपनी समस्या को स्वयं हल करने के लगभग एक साल बाद पोस्ट किए गए उत्तर को स्वीकार न करने के लिए किसी को धमकाना अनुचित है ! और वह यह भी अनदेखा कर रहा है कि आप जिस नाम के साथ गए थे, उसके मुकाबले कितना अधिक जटिल है - जो वास्तव में पूछे गए प्रश्न का उत्तर देता है, क्योंकि प्रश्न बग से गलत धारणा के कारण संकेत दिया गया था कि ध्वज अविश्वसनीय है ।
क्रिस स्ट्रैटन

4
@ChrisStratton अगर आपको लगता है कि मेरी प्रतिक्रिया बदमाशी थी, तो मुझे लगता है कि आप इंटरनेट को ज्यादा नहीं पढ़ते हैं। मैंने आपके विरोध के दृष्टिकोण को टिप्पणी के रूप में पोस्ट करने के अपने अधिकार का समर्थन किया है, और परिणामस्वरूप मैंने अपनी टिप्पणी और इस प्रश्न के अन्य पदों की समीक्षा की है, और मैं अपनी मूल टिप्पणी द्वारा खड़ा हूं: पोस्टर ने एक प्रश्न पूछा था जो कि वैध था और किसी ने सही उत्तर दिया। अपने स्वयं के "उत्तर" के आधार पर, उनका मूल प्रश्न वह नहीं है जो वह पहली जगह में पूछना चाहता था ... एक एपीके के हस्ताक्षर (रिलीज या डिबग) के प्रकट होने पर बिल्कुल शून्य असर होता है।
महिंद्रा

3
@mah - यह पूछने वाले पर निर्भर है, न कि आपको यह तय करने के लिए कि उनके वास्तविक आवेदन की आवश्यकता को पूरा करता है, जिसमें यह भी शामिल है कि आप जो अंतर जुटाते हैं, उसका एक महत्व है - या, जैसा कि इस मामले में जाहिर है, नहीं। इससे भी महत्वपूर्ण बात, आप पूरी तरह से इस बात को नजरअंदाज कर देते हैं कि आप जिस उत्तर को नामांकित करेंगे, उनकी वास्तविक जरूरत पूरी होने के लगभग एक साल बाद पोस्ट किया गया था । यह किसी को एक वर्ष के बाद अपनी स्वीकार्यता को बदलने के लिए वापस नहीं आने के लिए दंडित कर रहा है, जो बदमाशी का गठन करता है।
क्रिस स्ट्रैटन

3
@ChrisStratton यह पूछने वाले से वास्तविक प्रश्न पूछने के लिए भी है / वह एक उत्तर चाहता है - ऐसा कुछ जो इस मामले में नहीं किया गया था। आप सही हैं कि मैंने अनदेखी की जब जवाब जो वास्तव में जवाब दे रहा है कि क्या पोस्ट किया गया था, हालांकि, कोई सजा नहीं है, मेरी राय का केवल एक उचित अभिव्यक्ति है। अगर आपको लगता है कि मैं यहां धमकाने का काम कर रहा हूं, तो मैं दृढ़ता से अनुरोध करता हूं कि आप मेरी टिप्पणी को दुरुपयोग के लिए चिह्नित करें। हालांकि ऐसा करने से पहले, आप यहां अपनी स्वयं की पोस्टिंग की जांच करना चाह सकते हैं।
महा

0

कोटलिन में समाधान जो मैं इस समय उपयोग कर रहा हूं:

@SuppressLint("PackageManagerGetSignatures")
@Suppress("DEPRECATION")
fun isSigned(context: Context?): Boolean {
    return (context?.packageManager?.getPackageInfo(context.packageName, PackageManager.GET_SIGNATURES)?.signatures?.firstOrNull()?.toByteArray()
            ?.let {
                return@let CertificateFactory.getInstance("X.509").generateCertificate(ByteArrayInputStream(it))
            } as? X509Certificate)
            ?.issuerDN
            ?.name
            ?.contains("O=Android", ignoreCase = false) ?: true
}

इस तरह से मैं अभी भी डिबग में SIGN कर सकता हूं और उन पर Crashlytics को सूचित किया जाएगा (उदाहरण के लिए, QA प्रक्रिया के लिए)

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