Я перемещаю проект от Ant до Gradle, но есть кое-что, что я просто не могу понять.Переключение в Gradle: почему я должен запрещать запутывание пользовательских представлений?
ДАННЫЕ
После построения выпуска APK (т.е. затемненный), я заметил, что приложение было сбой плохо. Ошибка может быть суммированы следующим образом:
java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]
отладки (то есть, не затемненный) APK работает просто отлично, так что я предположил, что это было связано с моей ProGuard/DexGuard конфигурации.
Я пытался сохранить ссылку на класс, добавив следующее утверждение:
-keep class com.mypackage.MyCustomView
и, как следствие, релиз APK работает просто отлично. Затем я сделал некоторые исследования, и я попытался это более конкретная конфигурация ProGuard/DexGuard:
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
, который также работает, и это класса независимого.
ВОПРОС
Интересно:
- Почему я не приходится иметь дело с в то время как с помощью Ant?
- Какова конкретная причина появления этой ошибки? (Следующим образом ответить на первый вопрос)
ОТВЕТ
Ответ от @Blundell был по существу правильно. Оказывается, я пропускал одну линию от конфигурации build.gradle
:
android {
...
buildTypes {
debug {
...
}
release {
proguardFile getDefaultDexGuardFile('dexguard-release.pro') # <----- this line
proguardFile 'dexguard-project.txt'
}
}
}
Вероятно, что линия на самом деле является обязательным, так как он служит в качестве базового набора правил для ProGuard/DexGuard. На самом деле, это часть файла dexguard-release.pro
:
-keepclassmembers !abstract class !com.google.ads.** extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keepclassmembers !abstract class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.content.Context {
public void *(android.view.View);
}
Я нашел документацию немного слишком расплывчатое на это, я надеюсь, что это может быть отредактирован, чтобы очистить любую двусмысленность может иметь. В общем, моя вина.
как/где вы создаете свой собственный вид? – pskink
Конструкторы должны храниться, потому что 'LayoutInflater' использует их, но это не может быть выведено из статического анализа только источника. Я предполагаю, что ваш реальный вопрос - почему конфигурация по умолчанию ProGuard/DexGuard, которая раньше была частью SDK, не использовалась? Я предполагаю, что это связано с недавними изменениями в плагине Gradle, а также с переименованием 'runProguard' и другими подобными вещами. Если вы используете ProGuard из SDK, обратитесь в группу adt-dev Google. Если вы используете DexGuard, проверьте портал загрузки, было несколько последних обновлений в быстрой последовательности. – Barend
@Barend Я не уверен, почему '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' должен использоваться. Мне интересно, почему в Ant и Gradle существует другое поведение, поскольку оба используют одну и ту же версию DexGuard, и оба используют один и тот же файл конфигурации. – Sebastiano