Ich weiß nicht einmal, welchen Titel ich geben soll, es ist so seltsam. Ich habe ein kleines Android logic puzzle gebaut, das Farbwerte in einem ARGB-Ganzzahlformat verwendet. Um die Farben für die Animation zu mischen, wenn Sie einen Level beenden, ich habe die folgende Funktion:Der seltsamste Android-Bug aller Zeiten - Vielleicht ein ProGuard-Problem?
public static int blend(int color1, int color2, double position) {
if (position<0) position=0;
if (position>1) position=1;
int a = (color1 >>> 24) & 0xFF;
int r = (color1 >>> 16) & 0xFF;
int g = (color1 >>> 8) & 0xFF;
int b = color1 & 0xFF;
int da = ((color2 >>> 24) & 0xFF) - a;
int dr = ((color2 >>> 16) & 0xFF) - r;
int dg = ((color2 >>> 8) & 0xFF) - g;
int db = (color2 & 0xFF) - b;
a += da * position;
r += dr * position;
g += dg * position;
b += db * position;
return (a<<24) | (r<<16) | (g<<8) | b;
}
Ich nenne diese Funktion während der Animation mit diesem Code (enthält Debug-print-Anweisung):
int color = blend(START_COLOR, END_COLOR, pos*pos*pos*pos*pos);
System.out.println(Integer.toHexString(START_COLOR)+", "+Integer.toHexString(END_COLOR)+", "+pos+" -> "+Integer.toHexString(color));
Hier ist pos
einfach ein Doppelwert, der von 0,0 bis 1,0 zählt.
Wenn ich diesen Code direkt aus dem Eclipse über das Android-Entwickler-Plug-in auf Eclipse ausführe, funktioniert alles einwandfrei.
ABER: Wenn ich die App-Paket und installieren Sie die APK, es zuverlässig vermasselt, was mir eine Ausgabe wie folgt aus:
...
fff9b233, f785a307, 0.877 -> fabcaa1c
fff9b233, f785a307, 0.881 -> fabbaa1b
fff9b233, f785a307, 0.883 -> fabaa91b
fff9b233, f785a307, 0.886 -> fab9a91a
fff9b233, f785a307, 0.89 -> fab8a91a
fff9b233, f785a307, 0.891 -> fa00a91a
fff9b233, f785a307, 0.895 -> fab6a919
fff9b233, f785a307, 0.896 -> fa00a919
fff9b233, f785a307, 0.901 -> fab4a918
fff9b233, f785a307, 0.901 -> fab4a918
fff9b233, f785a307, 0.907 -> fab1a817
fff9b233, f785a307, 0.907 -> fab1a817
fff9b233, f785a307, 0.912 -> f9afa817
fff9b233, f785a307, 0.913 -> f900a817
fff9b233, f785a307, 0.919 -> f9aca816
fff9b233, f785a307, 0.919 -> f9aca816
fff9b233, f785a307, 0.925 -> f9aaa715
fff9b233, f785a307, 0.925 -> f9aaa715
fff9b233, f785a307, 0.93 -> f900a714
fff9b233, f785a307, 0.931 -> f900a714
fff9b233, f785a307, 0.936 -> f900a713
fff9b233, f785a307, 0.937 -> f900a713
fff9b233, f785a307, 0.942 -> f900a612
fff9b233, f785a307, 0.942 -> f900a612
fff9b233, f785a307, 0.947 -> f800a611
fff9b233, f785a307, 0.948 -> f800a611
fff9b233, f785a307, 0.954 -> f800a610
fff9b233, f785a307, 0.954 -> f800a610
fff9b233, f785a307, 0.959 -> f800a50f
...
In diesem Beispiel bis Position 0,89, alles in Ordnung ist. Dann beginnen die Dinge zu oszillieren zwischen Arbeit und Verschrauben nur der R-Komponente (auf 0 gesetzt; es ist immer die R-Komponente, die vermasselt), und schließlich, beginnend bei 0,93 in diesem Beispiel, Dinge immer vermasseln. Und dann, wenn ich genau die gleiche Animation wieder laufen lasse, fängt es an, sofort zu verschrauben ...
Wie in aller Welt ist das möglich? Verletzt dieser ProGuard meinen Code? Wenn das eine Möglichkeit ist, gibt es einen Weg, es herauszufinden? Ich habe hier wirklich einen Verlust an Ideen ... Und wie kann es probabilistisch sein, ob es funktioniert oder nicht? Oder verpasse ich hier etwas völlig Offensichtliches?
Wenn es ein ProGuard-Problem sein könnte, welche Art von Optimierungen könnte diesen Teil des Codes beeinflussen? Gibt es eine Liste von Schaltern, die ich nacheinander ausschalten könnte, um den Flockigen zu finden?
UPDATE:
Meine project.properties
Datei sieht wie folgt aus (kommentierten Zeilen gelöscht):
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
target=android-22
und proguard-project.txt
wie folgt aus:
-flattenpackagehierarchy
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
proguard-android.txt
im SDK-Verzeichnis sollte nach wie vor wie es mit den SDK Tools v24.1.2 ausgeliefert wurde (vorausgesetzt, dass ist das Paket, das ProGuard enthält ...; wieder ohne Kommentare):
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose
-dontoptimize
-dontpreverify
-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
-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 *;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
-dontwarn android.support.**
UPDATE 2:
Ich glaube, ich die kompilierte Ausgabe von dem, was ProGuard hat mit dem blend
-Methode in der dump.txt
Datei gefunden:
+ Method: a(IID)I
Access flags: 0x9
= public static int a(int,int,double)
Class member attributes (count = 1):
+ Code attribute instructions (code length = 171, locals = 12, stack = 6):
[0] dload_2 v2
[1] dconst_0
[2] dcmpg
[3] ifge +5 (target=8)
[6] dconst_0
[7] dstore_2 v2
[8] dload_2 v2
[9] dconst_1
[10] dcmpl
[11] ifle +5 (target=16)
[14] dconst_1
[15] dstore_2 v2
[16] iload_0 v0
[17] bipush 24
[19] iushr
[20] sipush 255
[23] iand
[24] istore v4
[26] iload_0 v0
[27] bipush 16
[29] iushr
[30] sipush 255
[33] iand
[34] istore v5
[36] iload_0 v0
[37] bipush 8
[39] iushr
[40] sipush 255
[43] iand
[44] istore v6
[46] iload_0 v0
[47] sipush 255
[50] iand
[51] istore v7
[53] iload_1 v1
[54] bipush 24
[56] iushr
[57] sipush 255
[60] iand
[61] iload v4
[63] isub
[64] istore v8
[66] iload_1 v1
[67] bipush 16
[69] iushr
[70] sipush 255
[73] iand
[74] iload v5
[76] isub
[77] istore v9
[79] iload_1 v1
[80] bipush 8
[82] iushr
[83] sipush 255
[86] iand
[87] iload v6
[89] isub
[90] istore v10
[92] iload_1 v1
[93] sipush 255
[96] iand
[97] iload v7
[99] isub
[100] istore v11
[102] iload v4
[104] i2d
[105] iload v8
[107] i2d
[108] dload_2 v2
[109] dmul
[110] dadd
[111] d2i
[112] istore v4
[114] iload v5
[116] i2d
[117] iload v9
[119] i2d
[120] dload_2 v2
[121] dmul
[122] dadd
[123] d2i
[124] istore v5
[126] iload v6
[128] i2d
[129] iload v10
[131] i2d
[132] dload_2 v2
[133] dmul
[134] dadd
[135] d2i
[136] istore v6
[138] iload v7
[140] i2d
[141] iload v11
[143] i2d
[144] dload_2 v2
[145] dmul
[146] dadd
[147] d2i
[148] istore v7
[150] iload v4
[152] bipush 24
[154] ishl
[155] iload v5
[157] bipush 16
[159] ishl
[160] ior
[161] iload v6
[163] bipush 8
[165] ishl
[166] ior
[167] iload v7
[169] ior
[170] ireturn
Code attribute exceptions (count = 0):
Code attribute attributes (attribute count = 2):
+ Line number table attribute (count = 15)
[0] -> line 33
[8] -> line 34
[16] -> line 35
[26] -> line 36
[36] -> line 37
[46] -> line 38
[53] -> line 40
[66] -> line 41
[79] -> line 42
[92] -> line 43
[102] -> line 45
[114] -> line 46
[126] -> line 47
[138] -> line 48
[150] -> line 50
+ Stack map table attribute (count = 2):
- [8] Var: ..., Stack: (empty)
- [16] Var: ..., Stack: (empty)
UPDATE 3:
Ich versuchte es neu zu schreiben, das Mischverfahren zu dieser (diese Idee zu sein, wenn ich alle Komponenten die gleiche Behandlung, ist es nicht möglich sein sollte, nur eine mehr vermasseln):
public static int blend(int color1, int color2, double position) {
if (position<0) position=0;
if (position>1) position=1;
int result = 0;
for (int shift = 0; shift<32; shift += 8) {
int component = (color1 >>> shift) & 0xFF;
int change = ((color2 >>> shift) & 0xFF) - component;
component += change * position;
result |= component << shift;
}
return result;
}
nicht überraschend, dieser Code funktioniert jetzt nur so wie es sollte! Aber das bringt mich immer noch nicht näher zu verstehen, warum der ursprüngliche Code versagt hat und an welchen anderen Stellen meiner App etwas ähnlich Triviales auf unerwartete Weise scheitern könnte.
UPDATE 4:
einfach die Linien Neuordnungs dazu auch das Problem behebt:
public static int blend(int color1, int color2, double position) {
if (position<0) position=0;
if (position>1) position=1;
int a = (color1 >>> 24) & 0xFF;
int da = ((color2 >>> 24) & 0xFF) - a;
a += da * position;
int r = (color1 >>> 16) & 0xFF;
int dr = ((color2 >>> 16) & 0xFF) - r;
r += dr * position;
int g = (color1 >>> 8) & 0xFF;
int dg = ((color2 >>> 8) & 0xFF) - g;
g += dg * position;
int b = color1 & 0xFF;
int db = (color2 & 0xFF) - b;
b += db * position;
return (a<<24) | (r<<16) | (g<<8) | b;
}
Es muss einige lokale Variablen-Wiederverwendung Sache sein, ich weiß nur nicht, warum das ist nicht ersichtlich aus der dump.txt-Datei oben ... Ist das etwas, was Dalvik tut (aber nur für APKs!?!)?
Warum spammen Sie mit einem Link zu Ihrer App? Wie ist dieser Link mit der Frage verbunden? – Selvin
@Selvin Wenn Sie sehen möchten, dass der Fehler passiert (die Farbe des wachsenden Sterns) ... Auch finde ich es normalerweise interessant zu sehen, was Leute mit meinen Antworten auf SO machen ... Aber ich kann es löschen, wenn es ist unpassend ... –
Könnten Sie Progard-Datei Informationen darüber geben, welche Proguard-Datei Sie eventuell verwenden? – Selvin