2015-09-11 13 views
8

私はこれを与えるためにどのようなタイトルがわからない、それはとても奇妙です。私はARGB整数形式で色の値を使用する少しAndroid logic puzzleを構築しました。あなたがレベルを完了すると、アニメーションの色をブレンドするために、私は次の関数があります。最も奇妙なAndroidのバグ - おそらくProGuardの問題?

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; 
} 

は、私は(デバッグprint文を含んでいる)このコードでアニメーション中にこの関数を呼び出す:

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)); 

ここでは、posは単なる0.0から1.0までの倍の値です。

Android開発者プラグインを使用してEclipse内から直接このコードを携帯電話で実行すると、すべて正常に動作します。

しかし:私はAPK、それ確実ねじアップ、与えるのアプリをパッケージ化してインストールする場合、私のような出力:この例では

... 
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 
... 

、位置100は、すべてが正常であるアップまで。それから、Rコンポーネント(0に設定されています; は常にのRコンポーネントが不正になってしまいます)と、最終的にはこの例では0.93から始まって、物事は常にうまくいきます。そして、まったく同じアニメーションをもう一度実行すると、すぐにねじれ始める...

これはどのように地球可能ですか?このProGuardは私のコードを乱していますか?それが可能ならば、確かに見つけ出す方法はありますか?私は本当にここでアイデアを失っています...それがうまくいくかどうかは、どうやって確率論的になりますか?それとも私はここで完全に明白な何かを見逃していますか?

ProGuardの問題である可能性がある場合、どのような最適化がコードのこの部分に影響する可能性がありますか?不安定なものを見つけるために1つずつスイッチを切ることができるスイッチのリストはありますか?

UPDATE:

マイproject.propertiesファイルは(コメント行が削除された)次のようになります。このような

proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 
target=android-22 

proguard-project.txt

-flattenpackagehierarchy 
-renamesourcefileattribute SourceFile 
-keepattributes SourceFile,LineNumberTable 

proguard-android.txtをSDKディレクトリにすべきではまだSDK Tools v24.1.2に同梱されていたようにProGuardを含むパッケージです...;再び)コメントを除く:

-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:

+ 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) 

私はProGuardのはdump.txtファイルにblend -methodで何をするかのコンパイル出力を見つけたと思います更新3

試しましたこの(アイデアは、私は同じすべてのコンポーネントを扱う場合、もはや一つだけを台無しにすることは可能であってはならないということである)にブレンド法を書き換える:

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; 
} 

驚くことではないが、このコードはちょうど、動作するようになりましたそれはすべきだ!しかし、これはまだ元のコードが失敗し、私のアプリケーションの他のどの場所でも、同様に些細なことが予期しない方法で失敗する可能性があることを理解できなくなってしまいます。

UPDATE 4:

単にこれに行を並べ替えることも、問題が修正されます。

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; 
} 

それはいくつかのローカル変数・再利用のものでなければならない理由、私は知りません上記のdump.txtファイルから明らかではありません... Dalvikが行うことですが(署名されたAPKだけに!?!)

+0

なぜあなたのアプリにリンクしてスパムしていますか?このリンクがどのように質問につながっていますか? – Selvin

+0

@セルヴィンあなたが起こっているエラー(成長している星の色)を見たい場合...また、私は通常、人々が私の答えで何をするのか興味深いと思っています...しかし、それがあればそれを削除することができます不適切な... –

+0

最終的にあなたが使用しているデフォルトのproguardファイルについて、proguardファイル情報を提供できますか? – Selvin

答えて

0

私はproguardについての回答はありませんが、何らかの理由で正しい結果を得ることができるColorヘルパーメソッドがあります。少なくとも、コードを読みやすくします。これを試してみてください:

public static int blend(int color1, int color2, double position) { 
    if (position < 0) { 
     position = 0; 
    } 
    if (position > 1) { 
     position = 1; 
    } 

    int a = Color.alpha(color1); 
    int r = Color.red(color1); 
    int g = Color.green(color1); 
    int b = Color.blue(color1); 

    int da = Color.alpha(color2) - a; 
    int dr = Color.red(color2) - r; 
    int dg = Color.green(color2) - g; 
    int db = Color.blue(color2) - b; 

    a += da * position; 
    r += dr * position; 
    g += dg * position; 
    b += db * position; 

    return Color.argb(a, r, g, b); 
} 
+0

メソッドが本質的に私のコードと同じことをしているので、これが実際にそれを修正するかどうかは疑問です(https://github.com/android/platform_frameworks_base/blob/master/graphics/java/android/graphics/Colorを参照してください)。 java)。だから、もしそれらがインラインになると、基本的に同じコードになります(いくつかの場合には異なるシフト演算子が使われ、いくつかの&0xFFが落とされます)。私はそれを試してみよう、ちょうどそれの楽しみのため... 1秒... –

+0

私はそれが試してみる価値があると思う。おそらくプロゴアードは彼らがSDKに入っていて、何とかあなたのことに迷惑をかけるので、彼らを混乱させないでしょう –

+0

うわー!それは問題を解決しませんでした!上にリンクされたソースを使用して私自身の "Color.java"を作成しなければならなかったのですが、私のコードは実際にAndroid jarをインポートしないクロスプラットフォームのライブラリに入っています! –

1
調査する

本当に興味深い問題と、それは間違いなく(おそらく)ProGuardので専門知識のあなたのレベルを増加しますが、より大きな絵を見てのために、私はのための既存のツールと一緒に行くお勧めします解決色の変化をアニメ化する:

ArgbEvaluator(またはAPI 21+の場合はValueAnimator#ofArgb(int...))レスキュー!

API 21+:

ValueAnimator animator = ValueAnimator.ofArgb(0xFFFF0000, 0xFF00FF00); //red->green 

API 11+:

ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(), 0xFFFF0000, 0xFF00FF00); //red->green 
animator.setDuration(1000);//1second 
animator.start(); 

それはあなたが(別のインターポレータ、遅延、リスナーなど)必要があるとして、あなたはそれを微調整することを可能にし、またそれがあるので、プラットフォームから来ると、ProGuardはそれに手を触れない大きなチャンスがあります

PS。私はまだあなたが経験している問題の根本的な原因を見たいと思っています:)

+0

:)これはオプションかもしれませんが、可能な限り多くのデバイスをサポートしようとしています。だから、私は現在、APIレベル7を越えて私のコードに依存していません。また、このコードはとてもばかげて単純です。実際にはちょうど作業しなければなりません。 –

+0

よく、内部的には何をしているのでしょうか。あなたの他のコメントを見て - これはクロスプラットフォームのlibのように思えますし、あなたはそれにアンドロイドAPIを参照することはできませんので、私はこのソリューションは単純にあなたのために働いていないと思います。 –

+0

それもそうですね。 :)しかし、提案をありがとう。しかし、これは本当に私が今心配している!これほどシンプルなものがひどく壊れてしまうと、他のコードをどのように信頼できますか? –