2011-11-12

在 Android 裡判斷是否為 Debug 模式

先在 AndroidManifest.xml 裡設定為 debug 模式。
<application ... android:debuggable="true">
...
</application>
再來是 DebugActicity.java。
public class DeubgActivity extends Activity {

 private static final String TAG = "DeubgActivity";

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  if (this.isDebug()) {
   // deubg mode
  }
  else {
   // normal mode
  }
 }

 private boolean isDebug() {
  PackageManager mgr = this.getPackageManager();
  try {
   ApplicationInfo info = mgr.getApplicationInfo(
     this.getPackageName(), 0);
   Log.d(TAG, "ApplicationInfo.FLAG_DEBUGGABLE: "
     + ApplicationInfo.FLAG_DEBUGGABLE);
   Log.d(TAG, "applicationInfo.flags: " + info.flags);
   Log.d(TAG, "info.flags & ApplicationInfo.FLAG_DEBUGGABLE: "
     + (info.flags & ApplicationInfo.FLAG_DEBUGGABLE));
   Log.d(TAG,
     "debug: "
       + ((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) == ApplicationInfo.FLAG_DEBUGGABLE));
   return (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) == ApplicationInfo.FLAG_DEBUGGABLE;
  }
  catch (NameNotFoundException e) {
   Log.e(TAG, e.getMessage(), e);
  }
  return false;
 }
}
再來是執行結果,第一張為 debug mode,第二張為 normal mode。



頭開始痛,這是什麼鬼啊!

先來看看文件怎麼說,第一個是 ApplicationInfo 的 flags,文件上說「Flags associated with the application. Any combination of FLAG_SYSTEM, FLAG_DEBUGGABLE, FLAG_HAS_CODE,...」,好,flags 是一堆 flag 的結合,包括我們想知道的 FLAG_DEBUGGABLE,但是怎麼結合啊?

然後再看看 FLAG_DEBUGGABLE,文件上說值為 2,看一下原始碼,「public static final int FLAG_DEBUGGABLE = 1 << 1;」,這這...又是什麼鬼!

好吧,看來得搞懂運算子 & 和 << 怎麼用了,好像從小時候考試的時候就沒搞懂過。

先從 << 開始。
public class BitOperator {

    public static final int FLAG_SYSTEM = 1 << 0;
    public static final int FLAG_DEBUGGABLE = 1 << 1;
    public static final int FLAG_HAS_CODE = 1 << 2;
    public static final int FLAG_PERSISTENT = 1 << 3;
    public static final int FLAG_FACTORY_TEST = 1 << 4;

    public static void main(String[] args) {
        System.out.println("1 << 0 的十進位為 " + FLAG_SYSTEM + ", 二進位為 "
                + Integer.toBinaryString(FLAG_SYSTEM));
        System.out.println("1 << 1 的十進位為 " + FLAG_DEBUGGABLE + ", 二進位為 "
                + Integer.toBinaryString(FLAG_DEBUGGABLE));
        System.out.println("1 << 2 的十進位為 " + FLAG_HAS_CODE + ", 二進位為 "
                + Integer.toBinaryString(FLAG_HAS_CODE));
        System.out.println("1 << 3 的十進位為 " + FLAG_PERSISTENT + ", 二進位為 "
                + Integer.toBinaryString(FLAG_PERSISTENT));
        System.out.println("1 << 4 的十進位為 " + FLAG_FACTORY_TEST + ", 二進位為 "
                + Integer.toBinaryString(FLAG_FACTORY_TEST));
    }
}
執行結果如下。
1 << 0 的十進位為 1, 二進位為 1
1 << 1 的十進位為 2, 二進位為 10
1 << 2 的十進位為 4, 二進位為 100
1 << 3 的十進位為 8, 二進位為 1000
1 << 4 的十進位為 16, 二進位為 10000
嗯,有點概念了,先轉成二進位,再向左移幾位,或者說在右邊補幾個零,然後再轉回十進位。

也就是說,ApplicationInfo 裡的所有 flag 都佔據一個二進位的位置,我們要看的 debug 是在第二個位置上。

所以要知道 applicationInfo.flags 有沒有包括 debug,得先將上面的執行結果 572998 或 572996 轉成二進位,就可以知道了。
int x = 572998;
int y = 572996;
System.out.println(x + " --> " + Integer.toString(x, 2));
System.out.println(y + " --> " + Integer.toString(y, 2));
謎底揭曉!
572998 --> 10001011111001000110
572996 --> 10001011111001000100
最後就是,怎麼寫程式去判斷,也就是另一個運算子 & 上場了。

一樣用範例說明。
int x = 123;
int y = 124;
System.out.println(x + "       --> " + Integer.toString(x, 2));
System.out.println(y + "       --> " + Integer.toString(y, 2));
System.out.println(x + " & " + y + " --> " + Integer.toString(x & y, 2));
執行結果。
123       --> 1111011
124       --> 1111100
123 & 124 --> 1111000
簡單來說,從二進位來看,就是同一個位置都是 1 的話,結果的那個位置就會是 1,如果其中一個是 0,或兩個都是 0,結果的那個位置就是 0。

以上面例子來看,前四碼都是 1 ,所以結果的前四碼也都是 1,後三碼分別為 011 與 100,剛好 1 都錯開,所以後三碼的結果就是 000,最後結果就是 1111000。

應用到 debug 的判斷,就是拿 flags 與 FLAG_DEBUGGABLE 做 & 運算。
572998       --> 10001011111001000110
2            -->                   10
572998 & 2   -->                   10 --> 2

572996       --> 10001011111001000100
2            -->                   10
572996 & 2   -->                    0 --> 0
簡單說, flags & FLAG_DEBUGGABLE 可以把 FLAG_DEBUGGABLE 的部份取出來,再跟 FLAG_DEBUGGABLE 做比較,為 true 者表示 flags 裡含有 FLAG_DEBUGGABLE,為 false 者不含有 FLAG_DEBUGGABLE。

最後附上兩個做進位換算需要的 API。
Integer.toString(int i, int radix); // 將十進位的數字 i 轉成 radix 進位的字串
Integer.parseInt(String s, int radix); // 將 radix 進位的字串轉成十進位數字 i

沒有留言:

張貼留言