BuildConfig.DEBUG हमेशा गलत होता है जब लाइब्रेरी प्रोजेक्ट को ग्रेडेल के साथ बनाया जाता है


83

जब मैं डीबग मोड में अपना ऐप चलाता हूं तो BuildConfig.DEBUG काम नहीं कर रहा है (= तार्किक रूप से गलत पर सेट)। मैं बनाने के लिए ग्रेड का उपयोग करता हूं। मेरे पास एक पुस्तकालय परियोजना है जहां मैं यह जांच करता हूं। BuildConfig.java बिल्ड डीबग फ़ोल्डर में इस तरह दिखता है:

/** Automatically generated the file. DO NOT MODIFY */
package common.myProject;

public final class BuildConfig {
    public static final boolean DEBUG = Boolean.parseBoolean("true");

}

और रिलीज़ फ़ोल्डर में:

public static final boolean DEBUG = false;

दोनों पुस्तकालय परियोजना में और आवेदन परियोजना में।

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

<application
        android:name=".MyPrj" ...

यह एक और समस्या की ओर जाता है: यह है कि मैं एक डेटाबेसप्रॉइडर में अपने डेबग चर का उपयोग करता हूं जो कि आवेदन वर्ग से पहले चलता है, और यह इस बग के कारण ठीक से नहीं चलेगा।


यह एक सामान्य व्यवहार है। मुद्दा कहां है? आपको BuildVariants
Gabriele Mariotti

1
BuildConfig फ़ाइल सही ढंग से जनरेट की गई है, लेकिन रन टाइम में यह गलत है। मुझे भी वही समस्या हो रही है।
jophde

जवाबों:


52

इसके लिए यह अपेक्षित व्यवहार है।

लाइब्रेरी प्रोजेक्ट केवल अन्य प्रोजेक्ट्स या मॉड्यूल द्वारा खपत के लिए अपने रिलीज़ वेरिएंट प्रकाशित करते हैं।

हम इसे ठीक करने पर काम कर रहे हैं, लेकिन यह गैर तुच्छ है और इसके लिए महत्वपूर्ण मात्रा में काम करना पड़ता है।

आप इस मुद्दे को https://code.google.com/p/android/issues/detail?id=52962 पर ट्रैक कर सकते हैं


4
वर्कअराउंड: BuildConfig.DEBUG के उदाहरण ने lib-Project के eg BuildConfig.RELEASE में एक और बूलियन वैरिएबल बनाया और इसे एप्लिकेशन के बिल्ड टाइप के साथ लिंक किया। विवरण: gist.github.com/almozavr/d59e770d2a6386061fcb
ओलेक्सी मालोवैनी

मुद्दा ट्रैकर में डोडोनेट द्वारा प्रदान किया गया समाधान सिर्फ ठीक काम करता है, काम के लिए कोई ज़रूरत नहीं है।
3c71

अब ऐसा नहीं है। उसके लिए उचित समाधान है। अधिक जानकारी के लिए मेरा जवाब देखें ।
निकल्स

यह सच है, लेकिन यह मैन्युअल रूप से किया जाना है, और जायके के साथ अच्छी तरह से पैमाने पर नहीं है। हम भविष्य में इसे और अधिक स्वचालित बनाना चाहते हैं।
ज़ेवियर डुक्रोटे

@XavierDucrohet यह एक अप्रत्याशित और काउंटर सहज व्यवहार है। यदि आप कर सकते हैं तो आपको निश्चित रूप से इसे ठीक करने की कोशिश करनी चाहिए।
रादु

86

एंड्रॉइड स्टूडियो 1.1 के साथ और 1.1 पर ग्रेडेल संस्करण होने के साथ यह संभव है:

पुस्तकालय

android {
    publishNonDefault true
}

ऐप

dependencies {
    releaseCompile project(path: ':library', configuration: 'release')
    debugCompile project(path: ':library', configuration: 'debug')
}

पूरा दस्तावेज यहां पाया जा सकता है http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication

संपादित करें :

इस मुद्दे को केवल एंड्रॉइड स्टूडियो ग्रैडल संस्करण 3.0 के लिए तय किया गया है। वहाँ आप बस का उपयोग कर सकते हैं implementation project(path: ':library')और यह स्वचालित रूप से सही कॉन्फ़िगरेशन का चयन करेगा।


5
इस तरह काम करता है। लेकिन एक खामी है: ": पुस्तकालय: एसेंबरलीज" को यहां तक ​​कहा जाता है कि आप ": ऐप: एसेम्बेटडेबग" बना रहे हैं, और इसके परिणामस्वरूप लंबा समय लगेगा।
एलन ज़िलियांग फेंग

वाह, उन्होंने आखिरकार उस पेज को थोड़ा अपडेट किया और उन्होंने आखिरकार इस सुविधा को जोड़ा।
जेरेड बुरोज

धन्यवाद, यह काम किया!
Aykut Ayevik

@ कोनिका लॉन्ग ग्रैड बिल्ड समय का भुगतान करने के लिए एक छोटी सी कीमत है - यह वैसे भी लम्बा और लम्बा है !! यह अद्भुत काम किया! बहुत बढ़िया!
राडू

हमें हमारे द्वारा उपयोग की जाने वाली प्रत्येक लाइब्रेरी के लिए "ऐप" भाग जोड़ना होगा? यदि ऐसा है, तो यह काफी कष्टप्रद है ...
Android डेवलपर

46

के लिए जाँच करें imports, कभी कभी BuildConfig पुस्तकालय के किसी भी वर्ग से अनजाने आयात किया जाता है। उदाहरण के लिए:

import io.fabric.sdk.android.BuildConfig;

इस मामले में BuildConfig.DEBUG हमेशा गलत लौटेगा ;

import com.yourpackagename.BuildConfig;

इस स्थिति में BuildConfig.DEBUG आपका वास्तविक बिल्ड वैरिएंट लौटाएगा


8

यह फिल के जवाब की तरह है सिवाय इसके कि संदर्भ की आवश्यकता नहीं है:

private static Boolean sDebug;

/**
 * Is {@link BuildConfig#DEBUG} still broken for library projects? If so, use this.</p>
 * 
 * See: https://code.google.com/p/android/issues/detail?id=52962</p>
 * 
 * @return {@code true} if this is a debug build, {@code false} if it is a production build.
 */
public static boolean isDebugBuild() {
    if (sDebug == null) {
        try {
            final Class<?> activityThread = Class.forName("android.app.ActivityThread");
            final Method currentPackage = activityThread.getMethod("currentPackageName");
            final String packageName = (String) currentPackage.invoke(null, (Object[]) null);
            final Class<?> buildConfig = Class.forName(packageName + ".BuildConfig");
            final Field DEBUG = buildConfig.getField("DEBUG");
            DEBUG.setAccessible(true);
            sDebug = DEBUG.getBoolean(null);
        } catch (final Throwable t) {
            final String message = t.getMessage();
            if (message != null && message.contains("BuildConfig")) {
                // Proguard obfuscated build. Most likely a production build.
                sDebug = false;
            } else {
                sDebug = BuildConfig.DEBUG;
            }
        }
    }
    return sDebug;
}

इस ( blog.javia.org/static-the-android-application-package ) ब्लॉग पोस्ट के अनुसार आपको कभी भी गतिविधि थ्रेड (UI थ्रेड) के अलावा किसी भी थ्रेड से currentPackageName विधि को कॉल नहीं करना चाहिए। हालांकि शांत समाधान।
रॉल्फ R

@ रॉल्फ R वैसे आप इसके बजाय एप्लिकेशन-संदर्भ का उपयोग कर सकते हैं।
Android डेवलपर

6

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

/**
 * Gets a field from the project's BuildConfig. This is useful when, for example, flavors
 * are used at the project level to set custom fields.
 * @param context       Used to find the correct file
 * @param fieldName     The name of the field-to-access
 * @return              The value of the field, or {@code null} if the field is not found.
 */
public static Object getBuildConfigValue(Context context, String fieldName) {
    try {
        Class<?> clazz = Class.forName(context.getPackageName() + ".BuildConfig");
        Field field = clazz.getField(fieldName);
        return field.get(null);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}

DEBUGफ़ील्ड प्राप्त करने के लिए, उदाहरण के लिए, बस इसे अपने से कॉल करें Activity:

boolean debug = (Boolean) getBuildConfigValue(this, "DEBUG");

मैंने इस समाधान को AOSP अंक ट्रैकर पर भी साझा किया है ।


@shkschneider क्या लाइन है? क्या आप अपना अपवाद पोस्ट कर सकते हैं?
फिल

3
दूसरों के लिए उपयोगी हो सकता है: applicationIdSuffixग्रैडल के उपयोग से सावधान रहें जो .BuildConfigवर्ग को इस उपरोक्त कोड से उपलब्ध नहीं करेगा ।
shkschneider

5

यदि आप डिबग फ्लेवर में हैं, तो वास्तव में यह जांचने का सही तरीका नहीं है, लेकिन आप यह जांच सकते हैं कि ऐप स्वयं के माध्यम से डीबग करने योग्य है या नहीं:

private static Boolean sIsDebuggable;

public static boolean isDebuggable(Context context) {
    if (sIsDebuggable == null)
        sIsDebuggable = (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
    return sIsDebuggable;
}

ऐप्स और लाइब्रेरी का डिफ़ॉल्ट व्यवहार पूरी तरह से मेल खाएगा।

यदि आपको बेहतर वर्कअराउंड की आवश्यकता है, तो आप इसके बजाय इसका उपयोग कर सकते हैं:

public static boolean isInDebugFlavour(Context context) {
    if (sDebugFlavour == null) {
        try {
            final String packageName = context.getPackageName();
            final Class<?> buildConfig = Class.forName(packageName + ".BuildConfig");
            final Field DEBUG = buildConfig.getField("DEBUG");
            DEBUG.setAccessible(true);
            sDebugFlavour = DEBUG.getBoolean(null);
        } catch (final Throwable t) {
            sDebugFlavour = false;
        }
    }
    return sDebugFlavour;
}

2

आप ग्रेड का उपयोग करके प्रत्येक बिल्ड प्रकार के लिए अपना स्वयं का BuildConfig वर्ग बना सकते हैं

public class MyBuildConfig
{
    public static final boolean DEBUG = true;
}

के लिए /src/debug/.../MyBuildConfig.java और ...

public class MyBuildConfig
{
    public static final boolean DEBUG = false;
}

for /src/release/..//yBuildConfig.java

फिर उपयोग करें:

if (MyBuildConfig.DEBUG)
    Log.d(TAG, "Hey! This is debug version!");

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

2

यहाँ एक और उपाय है।

1) एक इंटरफ़ेस बनाएँ

public interface BuildVariantDetector {

    boolean isDebugVariant();

}

2) एप्लिकेशन क्लास (एप्लायंस मॉड्यूल) पर इस इंटरफेस का उपयोग करें

public class MyApplication extends Application implements BuildVariantDetector {

    @Override
    public boolean isDebugVariant() {
        return BuildConfig.DEBUG; //application (main module) Buildonfig
    }

}

3) और फिर पुस्तकालय मॉड्यूल में:

boolean debugVariant = ((BuildVariantDetector)getApplication()).isDebugVariant();

यह काम नहीं करता है। BuildConfig.DEBUG अभी भी मेरे लिए गलत है।
दिसदेव

सरल और सुरुचिपूर्ण समाधान। बस सुनिश्चित करें कि आप ऐप मॉड्यूल के BuildConfig का आयात करें न कि लाइब्रेरी का। यह एक बहुत डरपोक गलती है।
विंडराइडर

1

हम भी यही समस्या थी। मैं कुछ इस तरह से आया:

हमारे पास एक एसडीके (पुस्तकालय) और एक डेमो प्रोजेक्ट है, पदानुक्रम इस तरह दिखता है:

Parent
  |
  + SDK (:SDK)
  |
  + DemoApp (:DemoApp)

हमारे पास मौजूद डेमो ऐप के लिए, कुछ पोस्ट-प्रोसेस्ड जार बनाने के लिए कुछ विशिष्ट कार्य हैं :SDK:jarjarDebugऔर :SDK:jarjarReleaseहैं :SDK:

dependencies {
    debugCompile tasks.getByPath(":SDK:jarjarDebug").outputs.files
    releaseCompile tasks.getByPath(":SDK:jarjarRelease").outputs.files
    ... more dependencies ...
}

यह buildTypesएक ही बार में निर्मित कई के लिए भी काम करता है । डिबगिंग हालांकि थोड़ा मुश्किल है। कृपया टिप्पणी करें।


1

यह मेरा काम है: एप्लिकेशन मॉड्यूल के BuildConfig को प्रतिबिंबित करें:

`सार्वजनिक स्थैतिक बूलियन डिबग = इसबग ();

private static boolean isDebug() {
    boolean result = false;
    try {
        Class c = Class.forName("com.example.app.BuildConfig");
        Field f = c.getField("DEBUG");
        f.setAccessible(true);
        result = f.getBoolean(c);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return result;
}`

आपने प्रतिबिंब का उपयोग किया है, लेकिन यह आवश्यक नहीं था। आप build.gradle में फ्लेवर का उपयोग कर सकते हैं।
अभिनव सक्सेना

0

आप प्रत्येक प्रोजेक्ट बिल्ड पर यह प्रयास कर सकते हैं:

parent.allprojects.each{ project -> android.defaultConfig.debuggable = true}

क्या आप समझा सकते हैं? इसे केवल "डीबग" बिल्ड टाइप में जोड़ें? और प्रत्येक मॉड्यूल के लिए? यह मुझे एक त्रुटि देता है: त्रुटि: (31, 0) ऐसी कोई संपत्ति नहीं है: वर्ग के लिए डीबग करने योग्य: com.android.build.gradle.internal.dsl.ProductFlavor_Decorated
Android डेवलपर

Android gradle plugin के स्पेक्स बदल गए हैं इसलिए यह अब मान्य नहीं है। डीबग करने योग्य ध्वज को ले जाया गया है buildTypeऔर बिल्ड कॉन्फ़िगरेशन नहीं। मैं डिबग पर हस्ताक्षर करने वाले सिद्धांत को एक ही चाल के लिए करना चाहिए
pablisco

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

0

मेरे मामले में मैं गलत आयात कर रहा था BuildConfigक्योंकि मेरी परियोजना में कई पुस्तकालय मॉड्यूल हैं। फिक्स BuildConfigमेरे appमॉड्यूल के लिए सही आयात करने के लिए था ।


0

ग्रेडिंग फ़ाइल में डीबग करने योग्य सत्य के साथ कार्य करना।

buildTypes {
  demo{
 debuggable true
    }
  live{
 debuggable true
    }
}

0

BuildConfig.DEBUG बिल्कुल भी विश्वसनीय नहीं है, Android ने एक आंतरिक ध्वज प्रदान किया है जो विश्व स्तर पर उपलब्ध है, यह दर्शाता है कि एक निर्माण डिबग या गैर-डीबग मोड में है

(getContext().getApplicationInfo().flags &ApplicationInfo.FLAG_DEBUGGABLE) != 0) 

यदि यह डिबग में है तो सच होगा

क्रेडिट: https://medium.com/@elye.project/checking-debug-build-the-right-way-d12da1098120

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