Как проверить, подписана ли APK или "отладить сборку"?
Насколько я знаю, в андроидном "релиз-сборке" подписан APK. Как проверить его с помощью кода или определяет ли Eclipse какой-то секрет?
Мне нужно это для отладки заполнения элементов ListView из данных веб-службы (нет, logcat не опция).
Мои мысли:
- Приложение
android:debuggable
, но по какой-то причине оно не выглядит надежным.
- Идентификатор жесткого диска не является хорошей идеей, потому что я использую одно и то же устройство для тестирования подписанных APK.
- Использование флага вручную в коде? Правдоподобно, но определенно забудьте изменить в какой-то момент, плюс все программисты ленивы.
Ответы
Ответ 1
Существует другой способ проверить, работает ли приложение с использованием сертификата отладки или выпуска, но мне кажется, что следующий способ выглядит лучше.
Согласно информации в документации для Android Подписывание вашего приложения, ключ отладки содержит следующее имя различающегося имени: " CN = Android Debug, O = Android, C = US". Мы можем использовать эту информацию, чтобы проверить, подписан ли пакет с помощью отладочного ключа без подписи ключа отладки в коде.
Дано:
import android.content.pm.Signature;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
Вы можете реализовать метод isDebuggable следующим образом:
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;
}
Ответ 2
Чтобы проверить флаг отладки, вы можете использовать этот код:
boolean isDebuggable = ( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) );
Котлин:
val isDebuggable = 0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE
Для получения дополнительной информации см. Защита приложений Android LVL.
Кроме того, если вы используете Gradle правильно, вы можете проверить, является ли BuildConfig.DEBUG
истинным или ложным.
Ответ 3
Отвечено Марк Мерфи
Простейшим и лучшим долгосрочным решением является использование BuildConfig.DEBUG
. Это значение boolean
, которое будет true
для сборки отладки, false
иначе:
if (BuildConfig.DEBUG) {
// do something for a debug build
}
Ответ 4
Возможно, поздно, но iosched использует BuildConfig.DEBUG
Ответ 5
Если вы хотите статически ставить APK
, вы можете использовать
aapt dump badging /path/to/apk | grep -c application-debuggable
Это выводит 0
, если APK
не отлаживается и 1
, если оно есть.
Ответ 6
Сначала добавьте это в свой файл 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;
}
}
Ответ 7
Отладочная сборка также подписана, просто с другим ключом. Он автоматически генерируется Eclipse, и его сертификат действителен только один год. Какая проблема с android:debuggable
? Вы можете получить это значение из кода с помощью PackageManager
.
Ответ 8
Еще один вариант, заслуживающий упоминания. Если вам нужно выполнить какой-то код только при подключенном отладчике, используйте этот код:
if (Debug.isDebuggerConnected() || Debug.waitingForDebugger()) {
//code to be executed
}
Ответ 9
Решено с помощью android:debuggable
. Это была ошибка при чтении элемента, где в некоторых случаях флаг отладки на элементе не сохранялся в записи, получая if (m.debug && !App.isDebuggable(getContext()))
, всегда оцениваемый до false
. Мой плохой.
Ответ 10
Решение в Kotlin, которое я использую на данный момент:
@SuppressLint("PackageManagerGetSignatures")
@Suppress("DEPRECATION")
fun isSigned(context: Context?): Boolean {
return (context?.packageManager?.getPackageInfo(context.packageName, PackageManager.GET_SIGNATURES)?.signatures?.firstOrNull()?.toByteArray()
?.let {
[email protected] CertificateFactory.getInstance("X.509").generateCertificate(ByteArrayInputStream(it))
} as? X509Certificate)
?.issuerDN
?.name
?.contains("O=Android", ignoreCase = false) ?: true
}
таким образом, я все еще могу ПОДПИСАТЬСЯ в отладке, и они будут сообщены Crashlytics (например, для процесса QA)