#android #obfuscation #proguard #minimization
#Android #запутывание #proguard #минимизация
Вопрос:
Общим шаблоном в конфигурациях ProGuard для приложений Android является сохранение пользовательских View
классов, поскольку на них, вероятно, ссылаются только из layout XML, а не из кода приложения.
Поэтому при создании проекта ADT добавляет эти правила в proguard.cfg проекта:
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
Я предполагаю, что идея здесь в том, чтобы сказать, что всякий раз, когда класс определяет конструктор, который может быть вызван раздувателем макета, сохраняйте его. Однако, согласно документам ProGuard, keepclasseswithmembernames
квалификатор является сокращением для keepclasseswithmembers
и allowshrinking
, что, если я правильно понимаю, означает: разрешено удалять эти классы, но если они сохранены, не запутывайте имена его членов (вероятно, чтобы не нарушать привязки между именами атрибутов XML и установщиками классов).
Но не означает ли это, что эти классы все равно будут удалены на этапе сжатия (allowshrinking = true), если на них нет прямых ссылок в коде? Действительно, это то, что произошло с пользовательским виджетом, который мы используем в нашем приложении, и я мог бы исправить проблему, установив для правила значение just keepclasseswithmembers
, поскольку это просто полностью сохранит соответствующие классы (стоит отметить, что это то, что делает и официальный пример ProGuard Android).
Я неправильно читаю документы ProGuard или это ошибка в мастере проекта ADT?
Ответ №1:
Конфигурация в Android SDK (по крайней мере, до версии 11) действительно не совсем правильная.
Конфигурация для Android в документации ProGuard правильно указывает «-keepclasseswithmembers», а не «-keepclasseswithmembernames».
Комментарии:
1. Спасибо, я поднял проблему: code.google.com/p/android/issues/detail?id=16384
2. Спасибо за это замечание, сэкономило мне много времени. Однако, когда я впервые настраиваю Proguard, жаль, что нет автоматической настройки путем просмотра содержимого проекта.
Ответ №2:
Когда я впервые попробовал интегрированную proguard с Ant, мое приложение продолжало сбоить из-за ошибок во время выполнения в обработчиках нажатий. (Я всегда устанавливаю их в XML). Я предположил, что, должно быть, делаю что-то неправильно, не мог понять, что, поэтому добавил строку
-dontshrink
в верхней части файла proguard.cfg.
Возможно, это не оптимально, но это остановило ошибки во время выполнения!
Добавление
На самом деле я проверил это, посмотрев на usage.txt . Обработчики щелчков были перечислены там до того, как я добавил опцию dontshrink, после того, как я добавил ее, usage.txt было пустым, как и следовало ожидать.
Комментарии:
1. Эй, Ник, это именно то, что я тоже подозревал. Проблема в том, что обработчики щелчков в XML преобразуются в вызовы методов посредством отражения, но если ProGuard запутывает имена методов, то это, конечно, ломается.
dontshrink
Вариант, конечно, исправил бы это, но это своего рода кувалда, поскольку он будет применяться ко всем классам.2. Ну, это все еще запутывает все имена методов, которые не были исключены директивой keepclasseswithmembernames, включая clickhandler. Проблема заключалась не в запутывании, а в том факте, что он удалил метод, потому что на него нигде не было ссылок в коде. Итак, пока вы готовы самостоятельно удалять любой действительно неиспользуемый код, это не кажется такой уж сложной задачей.
3. Я использую подобное правило, чтобы сохранить определенные в XML обработчики щелчков:
-keepclassmembers class * extends android.app.Activity { public void *(android.view.View); }
вместо отключения сжатия.