デバッグモードでアプリを実行すると、BuildConfig.DEBUGが機能しません(=論理的にfalseに設定されます)。 Gradleを使用してビルドします。このチェックを行うライブラリプロジェクトがあります。 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" ...
これは別の問題につながります。アプリケーションクラスの前に実行されるDataBaseProviderでDEBUG変数を使用しているため、このバグが原因で適切に実行されません。
これは予想される動作です。
ライブラリプロジェクトは、他のプロジェクトまたはモジュールで使用するためにリリースバリアントのみを公開します。
この問題の修正に取り組んでいますが、これは簡単なことではなく、かなりの作業が必要です。
https://code.google.com/p/Android/issues/detail?id=52962 で問題を追跡できます
Android Studio 1.1で、1.1のgradleバージョンでも可能です。
ライブラリ
_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
[〜#〜] edit [〜#〜]:
issue はAndroid Studio Gradleバージョン3.0の修正済みとしてマークされています。そこではimplementation project(path: ':library')
を使用できます。構成を自動的に修正します。
imports
を確認します。時々BuildConfigが任意のクラスのライブラリから意図せずにインポートされます。例えば:
import io.fabric.sdk.Android.BuildConfig;
この場合、BuildConfig.DEBUGは常にfalse;を返します。
import com.yourpackagename.BuildConfig;
この場合、BuildConfig.DEBUGは実際の値を返しますbuild variant。
これは、コンテキストを必要としないことを除いて、フィルの答えに似ています。
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;
}
回避策として、このメソッドを使用できます。このメソッドは、リフレクションを使用して、アプリ(ライブラリではなく)からフィールド値を取得します。
/**
* 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 Issue Tracker で共有しました。
デバッグフレーバーにあるかどうかを確認する正しい方法ではありませんが、次の方法でアプリ自体がデバッグ可能かどうかを確認できます。
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;
}
別の解決策があります。
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();
Gradleを使用して、ビルドタイプごとに独自のBuildConfigクラスを作成できます
public class MyBuildConfig
{
public static final boolean DEBUG = true;
}
/ src/debug /.../ MyBuildConfig.Java and ...
public class MyBuildConfig
{
public static final boolean DEBUG = false;
}
/ src/release /.../ MyBuildConfig.Java
次に使用します:
if (MyBuildConfig.DEBUG)
Log.d(TAG, "Hey! This is debug version!");
これは私の回避策です:アプリモジュールのBuildConfigを反映します。
`public static boolean debug = isDebug();
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;
}`
同じ問題がありました。私はこのようなものを思いつきました:
SDK(ライブラリ)とデモプロジェクトがあり、階層は次のようになります。
Parent
|
+ SDK (:SDK)
|
+ DemoApp (:DemoApp)
デモアプリの場合、:SDK:jarjarDebug
および:SDK:jarjarRelease
は:SDK
いくつかの後処理されたjarを生成します。
dependencies {
debugCompile tasks.getByPath(":SDK:jarjarDebug").outputs.files
releaseCompile tasks.getByPath(":SDK:jarjarRelease").outputs.files
... more dependencies ...
}
これは、一度にビルドされた複数のbuildTypes
に対しても機能します。ただし、デバッグは少し難しいです。コメントしてください。
Gradleファイルでデバッグ可能なtrueを使用します。
buildTypes {
demo{
debuggable true
}
live{
debuggable true
}
}
BuildConfig.DEBUGはまったく信頼できません。Androidは、ビルドがデバッグモードか非デバッグモードかを示すグローバルに利用可能な内部フラグを提供しました
(getContext().getApplicationInfo().flags &ApplicationInfo.FLAG_DEBUGGABLE) != 0)
デバッグ中であれば真になります
クレジット: https://medium.com/@elye.project/checking-debug-build-the-right-way-d12da109812
各プロジェクトbuildTypesでこれを試すことができます。
parent.allprojects.each{ project -> Android.defaultConfig.debuggable = true}
私のプロジェクトには多くのライブラリモジュールがあるため、私の場合は間違ったBuildConfig
をインポートしていました。修正は、私のBuildConfig
モジュールの正しいapp
をインポートすることでした。