Soru Gradient ile kütüphane projeleri oluştururken BuildConfig.DEBUG her zaman yanlış


Uygulamamı hata ayıklama modunda çalıştırdığımda BuildConfig.DEBUG çalışmıyor (= mantıksal olarak false değerine ayarlı). Ben inşa etmek için kürek kullanırım. Bu kontrolü yaptığım bir kütüphane projem var. BuildConfig.java, derleme hata ayıklama klasöründe şöyle görünür:

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

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

}

ve serbest bırakma klasöründe:

public static final boolean DEBUG = false;

hem kütüphane projesinde hem de uygulama projesinde.

Projemin bir sınıfını belirleyen bir değişkeni kontrol ederek bunu aşmaya çalıştım. Bu sınıf kütüphaneden miras alır ve başlangıçta başlar.

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

Bu başka bir soruna yol açtı: DEBUG değişkenimi, uygulama sınıfından önce çalışan bir DataBaseProvider'da kullanıyorum.


76
2017-11-24 15:29


Menşei


Bu normal bir davranış. Sorun nerede? BuildVariants arasında geçiş yapmalısınız - Gabriele Mariotti
BuildConfig dosyası doğru bir şekilde üretilir, ancak çalışma zamanında yanlıştır. Aynı sorunu yaşıyorum. - jophde


Cevaplar:


Bunun için beklenen davranış budur.

Kütüphane projeleri, yalnızca diğer projeler veya modüller tarafından tüketime yönelik yayın çeşitlerini yayınlamaktadır.

Bunu düzeltmek için çalışıyoruz, ancak bu önemsiz ve önemli miktarda iş gerektiriyor.

Sorunu şu adresten takip edebilirsiniz https://code.google.com/p/android/issues/detail?id=52962


50
2017-12-16 18:18



Geçici çözüm: BuildConfig.DEBUG öğesinden, lib-projesinde ör. BuildConfig.RELEASE ve uygulamanın buildType ile bağlayın. Detaylar: gist.github.com/almozavr/d59e770d2a6386061fcb - Aleksey Malevaniy
DodoEnte'nin konu takibinde sağladığı çözüm gayet iyi çalışıyor, çalışmalara gerek yok. - 3c71
Artık böyle değil. Bunun için uygun bir çözüm var. Görmek cevabım daha fazla bilgi için. - Niklas
Bu doğru ama elle yapılması ve lezzetlerle çok iyi ölçeklenmemesi gerekiyor. Bunu gelecekte daha otomatik hale getirmek istiyoruz. - Xavier Ducrohet
@XavierDucrohet Bu beklenmeyen ve karşı sezgisel bir davranış. Yapabiliyorsan kesinlikle düzeltmeye çalışmalısın. - Radu


Android Studio 1.1 ile ve 1.1 de gradle sürümüne sahip olmak mümkündür:

Kütüphane

android {
    publishNonDefault true
}

Uygulama

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

Komple dokümantasyon burada bulunabilir http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication

DÜZENLE:

konu Android Studio Gradle Sürüm 3.0 için sabit olarak işaretlendi. Orada sadece kullanabilirsin implementation project(path: ':library') ve doğru yapılandırmayı otomatik olarak seçer.


85
2018-03-20 09:32



Bu şekilde çalışır. Ama bir dezavantajı var: ": app: assembleDebug" 'ı oluştururken bile ": library: assembleRelease" denir ve bu da daha uzun bir bina süresine neden olur. - Alan Zhiliang Feng
Vay, sonunda bu sayfayı güncellediler birazcık ve sonunda bu özelliği eklediler. - Jared Burrows
Teşekkürler, bu iş yaptı! - Aykut Çevik
Mükemmel çözüm, kabul edilen cevap olmalıdır. - natanavra
Temiz çözüm ve harika çalışıyor. - FMontano


Kontrol imports, ara sıra BuildConfig istemeden herhangi bir kütüphane sınıfından içe aktarılır. Örneğin:

import io.fabric.sdk.android.BuildConfig;

Bu durumda BuildConfig.DEBUG her zaman dönecek yanlış;

import com.yourpackagename.BuildConfig;

Bu durumda BuildConfig.DEBUG gerçek geri dönecek varyantı oluştur.


37
2017-07-14 11:49



Bu benim durumumdu. - Subin Sebastian
@SubinSebastian da bana. - user1510006
Hayat kurtarıcı, teşekkürler ... - Arif Nadeem


Bu, Phil'in cevabı gibi bir bağlam gerektirmez.

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

7
2018-02-03 02:55



Buna göre (blog.javia.org/static-the-android-application-package) blog mesajını asla currentPackageName yöntemini hiçbir zaman iş parçacığı (UI iş parçacığı) dışında herhangi bir iş parçacığından aramamalısınız. Yine de güzel bir çözüm. - Rolf ツ
@Rolf ツ Bunun yerine uygulama bağlamını kullanabilirsiniz. - android developer


Bir geçici çözüm olarak, alan değerini uygulamadan almak için yansımayı kullanan bu yöntemi kullanabilirsiniz (kitaplık değil):

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

Almak için DEBUG Örneğin, bu alanı sadece Activity:

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

Ben de bu çözümü paylaştım. AOSP Konu Takibi.


6
2017-08-27 01:41



Bu geçici çözüm bana veriyor StackOverflowError... - shkschneider
@shkschneider hangi hatta? Özel durumunuzu gönderir misiniz? - Phil
Başkalarına faydalı olabilir: kullanımından sakının applicationIdSuffix Gradle içinde .BuildConfig Bu kod yukarıdaki koddan ulaşılabilir değil. - shkschneider


Hata ayıklama tadında olup olmadığınızı kontrol etmek için doğru yol değil, ancak uygulamanın kendiliğinden hata ayıklama olup olmadığını kontrol edebilirsiniz:

private static Boolean sIsDebuggable;

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

Uygulamaların ve kitaplıkların varsayılan davranışı mükemmel bir şekilde eşleşecektir.

Daha iyi bir çözüme ihtiyacınız varsa, bunun yerine kullanabilirsiniz:

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

3
2018-06-21 09:51





Her derleme türü için gradyanı kullanarak kendi BuildConfig sınıfınızı oluşturabilirsiniz.

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

için /src/debug/.../MyBuildConfig.java ve...

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

için /src/release/.../MyBuildConfig.java

Sonra kullan:

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

2
2017-10-19 15:08



Kütüphanenin paketi için "..." yazıyor mu? Eğer öyleyse, bu işe yaramaz. Derse erişemiyorum. - android developer


İşte başka bir çözüm.

1) Bir arayüz oluştur

public interface BuildVariantDetector {

    boolean isDebugVariant();

}

2) Bu arayüzü Uygulama sınıfı (Appplication module) üzerinden kullanın

public class MyApplication extends Application implements BuildVariantDetector {

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

}

3) Ve sonra kütüphane modülünde:

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

2
2018-05-06 12:59



Bu işe yaramıyor. BuildConfig.DEBUG hala benim için yanlıştır. - DiscDev
Basit ve zarif bir çözüm. Sadece uygulama modülünün BuildConfig dosyasını kütüphanenin değil ithal ettiğinden emin ol. Bu çok sinsi bir hata. - WindRider


Biz de aynı sorunu yaşadık. Böyle bir şeyle geldim:

Bir SDK (kütüphane) ve bir demo projemiz var, hiyerarşi şöyle:

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

Sahip olduğumuz demo uygulaması için :SDK:jarjarDebug ve :SDK:jarjarRelease için bazı özel görevler :SDK Bazı post-işlenmiş kavanozlar üretmek:

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

Bu çoklu için bile çalışır buildTypes bir kerede inşa edildi. Hata ayıklama biraz zor olsa da. Lütfen yorum yapın.


1
2017-11-25 23:51





Bunu buildTypes projelerinin her birinde deneyebilirsiniz:

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

0
2018-02-11 14:26



Açıklayabilir misin? Bunu yalnızca "debug" buildType öğesine ekleyin? Ve modüllerin her birine? Bana bir hata veriyor: Hata: (31, 0) Böyle bir özellik yok: sınıf için hata ayıklanabilir: com.android.build.gradle.internal.dsl.ProductFlavor_Decorated - android developer
Android gradle eklentisinin özellikleri değişti, dolayısıyla bu artık geçerli değil. Hata ayıklama bayrağı taşındı. buildTypeve yapı yapılandırması değil. Ben hata ayıklama imzalama kuralı aynı hile yapmalıyım - pablisco
Kontrol edip cevabı günceller misiniz? Kolay bir çözüm varsa, bunu bilmek isterim. - android developer