Запутанный код Android proguard вызывает исключение NullPointerException, хотя на самом деле этого не должно быть

Я распространил приложение на Android Marketplace. Я получаю отчеты об ошибках от небольшой группы пользователей (возможно, 2%), где они получают исключения NullPointerExceptions, где это не имеет логического смысла.

Мне никогда не удавалось повторить это самому. Код относительно прост и представляет собой общий путь кода, которому должен следовать КАЖДЫЙ пользователь. На самом деле я взял каждую отдельную строку кода, которая могла бы создать NPE, и заключил ее в блок try-catch и выбросил настраиваемое исключение времени выполнения, но я все еще получаю не обнаруженные ошибки NullPointerException.

На данный момент единственное, что я могу представить, это что-то связанное с моей обфускацией Proguard. Я видел другую статью, в которой говорилось об отключении опции -overloadaggressively, если вы заметили странное поведение, но, насколько я могу судить, я не использую эту опцию.

Кто-нибудь еще испытывал таинственные NPE с использованием android и proguard. Есть ли какие-то другие настройки, которые люди могут порекомендовать, чтобы уменьшить количество оптимизаций, которые могут вызвать эту проблему?

Есть другие идеи?

Для справки, вот не запутанная функция, которая получает NPE:

public MainMenuScreen(final HauntedCarnival game) {
    super(game);

    game.startMusic("data/music/intro.mp3");

    stage = new Stage(Screen.SCREEN_WIDTH, Screen.SCREEN_HEIGHT,true);
    stage.addActor(new Image("background", Assets.mainMenuBackground));
    Image title = new Image("title", Assets.mainMenuTitle);
    title.x = 0;
    title.y = 340;
    resetEyeBlink();
    stage.addActor(title);
    dispatcher.registerInputProcessor(stage);
    settings = game.getSettings();

    eyeBlinkImage = new Image("eyeBlink", Assets.eyeBlink);
    if (settings.getPlayers().isEmpty()) {
        settings.addPlayer("Player One");
        settings.save(game);
    }
    setupContinue();


}

Итак, единственный Возможности, которые я вижу, это игра, диспетчер и настройки.

игра устанавливается с помощью этого кода в другом классе. game - последняя переменная в этом другом классе: диспетчер

game.setScreen(new MainMenuScreen(game));

устанавливается внутри в вызове super выше.

getSettings () возвращает объект настроек, который устанавливается в самом начале приложения, является частным и никогда не сбрасывается. Его также использовали перед этим методом несколько раз.

Нет примитивов автобокса.

вот конфиг прогарда:

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-keepattributes Signature

-keep public class com.alkilabs.hauntedcarnival.settings.Settings
-keep public class com.alkilabs.hauntedcarnival.settings.Settings {
    *;
}
-keep public class com.alkilabs.hauntedcarnival.settings.Player
-keep public class com.alkilabs.hauntedcarnival.settings.Player {
    *;
}
-keepnames public class com.alkilabs.hauntedcarnival.world.World
-keepnames public class * extends com.alkilabs.hauntedcarnival.world.upgrades.Upgrade
-keepnames public class * extends com.alkilabs.hauntedcarnival.world.achievments.Achievement

-keepnames public class com.alkilabs.hauntedcarnival.world.monsters.MonsterType
-keepclassmembers class * extends com.alkilabs.hauntedcarnival.world.monsters.Monster {
    public <init>(com.alkilabs.hauntedcarnival.world.monsters.MonsterType, java.lang.Integer, com.alkilabs.hauntedcarnival.world.World);
}

-keepnames public class com.alkilabs.hauntedcarnival.world.items.ItemType
-keepclassmembers class * extends com.alkilabs.hauntedcarnival.world.items.Item {
    public <init>(com.alkilabs.hauntedcarnival.world.World, java.lang.Integer, java.lang.Integer);
}


-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference

-dontwarn com.badlogic.gdx.scenes.scene2d.ui.utils.DesktopClipboard
-dontwarn com.badlogic.gdx.utils.JsonWriter
-dontwarn com.badlogic.gdx.utils.XmlWriter

-keepclasseswithmembernames class * {
    native <methods>;
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
6
задан Paul 2 October 2011 в 23:38
поделиться