Android 5.0 如何正確啟用isLoggable(一)__使用詳解

來源:互聯網
上載者:User

標籤:android   isloggable   enable   

isLoggable是什麼

        在Android源碼中,我們經常可以看到如下代碼:

//packages/apps/InCallUI/src/com/android/incallui/Log.javapublic static final String TAG = "InCall";public static final boolean DEBUG = android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);public static void d(String tag, String msg) {    if (DEBUG) {        android.util.Log.d(TAG, delimit(tag) + msg);    }}//packages/apps/InCallUI/src/com/android/incallui/InCallPresenter.javaprivate InCallState startOrFinishUi(InCallState newState) {    Log.d(this, "startOrFinishUi: " + mInCallState + " -> " + newState);    //... ...}
        只有在android.util.Log.isLoggable返回值為true的時候,startOrFinishUi的log才能正常輸出。那什麼時候isLoggable才會返回true呢?如何簡單快捷的開啟isLoggable並使log正常輸出呢?

isLoggable定義

        什麼是isLoggable?isLoggable是android.util.Log提供的方法,用於檢查指定TAG的level,是否滿足輸出條件,如滿足則返回true反之則返回false。isLoggable在源碼中的定義如下:

    /**     * Checks to see whether or not a log for the specified tag is loggable at the specified level.     *     *  The default level of any tag is set to INFO. This means that any level above and including     *  INFO will be logged. Before you make any calls to a logging method you should check to see     *  if your tag should be logged. You can change the default level by setting a system property:     *      'setprop log.tag.<YOUR_LOG_TAG> <LEVEL>'     *  Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPPRESS will     *  turn off all logging for your tag. You can also create a local.prop file that with the     *  following in it:     *      'log.tag.<YOUR_LOG_TAG>=<LEVEL>'     *  and place that in /data/local.prop.     *     * @param tag The tag to check.     * @param level The level to check.     * @return Whether or not that this is allowed to be logged.     * @throws IllegalArgumentException is thrown if the tag.length() > 23.     */    public static native boolean isLoggable(String tag, int level);
從以上定義中可以知道:

1. isLoggable預設level為android.util.Log.INFO;

2. 只有 level >= INFO才能輸出,即level >= INFO時isLoggable返回true,反之則返回false;

3. 可以通過setprop log.tag.<YOUR_LOG_TAG> <LEVEL>來改變log的預設level,如adb shell setprop log.tag.InCall D。也可以將這些屬性按照log.tag.InCall=D的形式,寫入/data/local.prop中;

4. tag的長度如果超過23個字元則會拋出IllegalArgumentException異常;

        在android.util.Log類中定義了Log的6種Level,如下:

    /**     * Priority constant for the println method; use Log.v.     */    public static final int VERBOSE = 2;    /**     * Priority constant for the println method; use Log.d.     */    public static final int DEBUG = 3;    /**     * Priority constant for the println method; use Log.i.     */    public static final int INFO = 4;    /**     * Priority constant for the println method; use Log.w.     */    public static final int WARN = 5;    /**     * Priority constant for the println method; use Log.e.     */    public static final int ERROR = 6;    /**     * Priority constant for the println method.     */    public static final int ASSERT = 7;
        6種level對應不同等級的log,level值的大小隨著log權重的升高而增大。

isLoggable使能方法

        前文提到,在自訂的Log類中通常使用isLoggable來判斷是否輸出log,如代碼:

//packages/apps/InCallUI/src/com/android/incallui/Log.javapublic static final String TAG = "InCall";public static final boolean DEBUG = android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);public static void d(String tag, String msg) {    if (DEBUG) {        android.util.Log.d(TAG, delimit(tag) + msg);    }}//packages/apps/InCallUI/src/com/android/incallui/InCallPresenter.javaprivate InCallState startOrFinishUi(InCallState newState) {    Log.d(this, "startOrFinishUi: " + mInCallState + " -> " + newState);    //... ...}
如果想要輸出startOrFinishUi()方法中的log,可以採用以下方式:

①. 將Log.d修改為android.util.Log.d;使用android.util.Log類取代InCallUI自訂的Log類,重新編譯系統APP並push到手機中即可;

②. 修改com.android.incallui.Log中的DEBUG限制;將DEBUG的值直接置為true,或者注釋掉if(DEBUG)。也可以將isLoggable(TAG, android.util.Log.DEBUG)中的android.util.Log.DEBUG修改為android.util.Log.INFO,即將log的level增大,從而使isLoggable()返回true並使得DEBUG的值為true;

③. 設定log.tag.InCall的屬性值;通過adb shell setprop log.tag.InCall D,或者將"log.tag.InCall=D"寫入/data/local.prop中(不包含引號,如local.prop不存在則需自行建立,許可權設為644)。根據定義中的描述,設定屬性值需要在方法被調用之前,因此需要重啟InCallUI進程。通過修改屬性值的方法,從而使得isLoggable()的返回值為true,從而使得DEBUG的值為true。

        第一種方式直接修改,簡單粗暴,但若修改點較多則比較麻煩,且需要重新編譯代碼。

        第二種方式修改點統一,但和第一種一樣,也需要重新編譯。

        第三種使用屬性的方式使得isLoggable返回true,這種方式比較方便,同時適用於user/userdebug/eng各個版本的裝置。這種方式需要在方法被調用前設定log.tag.InCall,通過代碼:

public static final boolean DEBUG = android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);
可以知道,因為DEBUG是static的變數,所以當Log類被載入時,其值就已經設定好了。如果要使得isLoggable返回為true,那麼setprop需要在Log類被載入前設定好,因此使用setprop之後需要重啟對應的進程,如這裡的com.android.incallui。但在framework中有些代碼也使用isLoggable,framework屬於每一個進程,如何重啟framework呢?可以使用:
adb shell stopadb shell start
adb shell stop會殺掉zygote進程以及所有由zygote孵化而來的子進程。adb shell start則會重啟zygote進程,再由zygote進程啟動其它Android核心進程。當zygote重新啟動時,會重新載入framework相關資源,而此時屬性已經設定。這種方法雖然簡單,但當裝置重啟後,所有設定的log.tag.<TAG>都會失效,若想再次啟用則需重新設定。

        也可以通過將log.tag.InCall=D加入到/data/local.prop檔案中,這種方式與setprop類似,都是設定屬性值,但這種方式的好處是,設定之後重啟裝置該log.tag.InCall依然有效。不過因為/data目錄的許可權控制,只有userdebug/eng版本才可以修改/data/local.prop檔案。

小結

        isLoggable的使能方法如所示:


圖 1 isLoggable使能方案對比

        如果只是想啟用某個進程的isLoggable方法,通過setprop設定屬性是不錯的選擇,同事,想要重啟裝置後依然有效則需要設定/data/local.prop,不過/data目錄只有在userdebug/eng版本中才可以寫入。那如果想在user版中設定log.tag屬性並在重啟後依然有效,可以採取以下方法:

1. 擷取user版系統的root許可權;

2. 將log.tag.InCall=D追加到/system/build.prop檔案中;

3. adb reboot重啟裝置;

        以上方案大家可能會疑惑,既然user版擷取到了root許可權,為什麼不直接修改/data/local.prop呢?這是因為如果是user版,則ro.debuggable=0,所以系統啟動時不會讀取/data/local.prop檔案,並最終導致設定log.tag屬性不會生效。詳細原理將在下一篇文章《Android 5.0 如何正確啟用isLoggable(一)__原理分析》中探討。

Android 5.0 如何正確啟用isLoggable(一)__使用詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.