本文的合集已經(jīng)編著成書限府,高級Android開發(fā)強化實戰(zhàn)碎紊,歡迎各位讀友的建議和指導(dǎo)。在京東即可購買:https://item.jd.com/12385680.html
介紹關(guān)于Android的一些有趣的小知識點. 本文是第五篇了, 幾乎一周一篇, 歡迎閱讀.
其余第一篇, 第二篇, 第三篇, 第四篇.
1. 模擬系統(tǒng)回收Activity.
使用adb命令可以模擬Android系統(tǒng)自動回收Activity進程, 可以調(diào)試這個效果.
單進程
adb shell am force-stop [包名]
多進程
adb shell ps | grep [包名]
adb shell kill [PID]
2. Android庫動態(tài)權(quán)限建議
Android 6.0使用動態(tài)權(quán)限, 在創(chuàng)建第三方庫時, 需要充分考慮這一特性.
(1) 在自動Merge庫的AndroidManifest時, 需要提供危險權(quán)限的提示文檔.
(2) 當權(quán)限未獲取時, 用戶可以使用庫的某一部分, 并提示缺少權(quán)限.
(3) 需要提供在權(quán)限獲取失敗時, 庫使用方式的文檔.
(4) 確保所有權(quán)限都是必須的, 不含有未使用權(quán)限.
關(guān)于提示用戶獲取權(quán)限的解決方案, 可以參考.
3. RxJava處理Retry請求服務(wù)器
服務(wù)器經(jīng)常會出現(xiàn)異常, 應(yīng)用需要連續(xù)嘗試請求, RxJava可以非常簡單的實現(xiàn).
模板
Observable<Boolean> source = ...; // Something that eventually emits true
source
.repeatWhen(completed -> completed.delay(1, TimeUnit.SECONDS))
.takeUntil(result -> result)
.filter(result -> result)
.subscribe(
res -> System.out.println("onNext(" + res + ")"),
err -> System.out.println("onError()"),
() -> System.out.println("onCompleted()")
);
示例
/**
* This is a class that should be
* mapped on your json response from the server
*/
class ServerPollingResponse {
boolean isJobDone;
@Override
public String toString() {
return "isJobDone=" + isJobDone;
}
}
Subscription checkJobSubscription = mDataManager.pollServer(inputData)
.repeatWhen(new Func1<Observable<? extends Void>, Observable<?>>() {
@Override
public Observable<?> call(Observable<? extends Void> observable) {
Log.v(TAG, "repeatWhen, call");
/**
* This is called only once.
* 5 means each repeated call will be delayed by 5 seconds
*/
return observable.delay(5, TimeUnit.SECONDS);
}
})
.takeUntil(new Func1<ServerPollingResponse, Boolean>() {
@Override
public Boolean call(ServerPollingResponse response) {
/** Here we can check if the responce is correct and if we should
* finish polling
* We finish polling when job is done.
* In other words : "We stop taking when job is done"
*/
Log.v(TAG, "takeUntil, call response " + response);
return response.isJobDone;
}
})
.filter(new Func1<ServerPollingResponse, Boolean>() {
@Override
public Boolean call(ServerPollingResponse response) {
/**
* We are filtering results if we return "false".
* Filtering means that onNext() will not be called.
* But onComplete() will be delivered.
*/
Log.v(TAG, "filter, call response " + response);
return response.isJobDone;
}
})
.subscribe(
new Subscriber<ServerPollingResponse>() {
@Override
public void onCompleted() {
Log.v(TAG, "onCompleted ");
}
@Override
public void onError(Throwable e) {
Log.v(TAG, "onError ");
}
@Override
public void onNext(ServerPollingResponse response) {
Log.v(TAG, "onNext response " + response);
// Do whatever you need. Server polling has been finished
}
}
);
4. Chrome的JsonView插件
添加插件之后, 可以格式化的顯示Json數(shù)據(jù).
5. 顯示Activity棧的Shell命令
Shell命令
adb shell dumpsys activity | sed -n -e '/Stack #/p' -e '/Running activities/,/Run #0/p'
直接獲取Activity信息有些冗余, 我們只關(guān)注堆棧信息即可.
sed可以編輯顯示的文字.
-n
, 從截取處開始連續(xù)處理.
-e
, 多選參數(shù).
'/Stack #/p'
, 輸出含有Stack #
的行.
-e '/Running activities/,/Run #0/p'
, 輸出從Running activities
至Run #0
的所有行.
輸出結(jié)果
Stack #1:
Running activities (most recent first):
TaskRecord{299f41ea #2269 A=me.chunyu.spike.wcl_activity_launchmode_demo U=0 sz=6}
Run #5: ActivityRecord{33926043 u0 me.chunyu.spike.wcl_activity_launchmode_demo/.MainActivity t2269}
Run #4: ActivityRecord{3f181566 u0 me.chunyu.spike.wcl_activity_launchmode_demo/.MainActivity t2269}
Run #3: ActivityRecord{22737e45 u0 me.chunyu.spike.wcl_activity_launchmode_demo/.MainActivity t2269}
Run #2: ActivityRecord{ce0a990 u0 me.chunyu.spike.wcl_activity_launchmode_demo/.MainActivity t2269}
Run #1: ActivityRecord{3de8e378 u0 me.chunyu.spike.wcl_activity_launchmode_demo/.MainActivity t2269}
Run #0: ActivityRecord{1cb28ec4 u0 me.chunyu.spike.wcl_activity_launchmode_demo/.MainActivity t2269}
Stack #0:
Running activities (most recent first):
TaskRecord{bfee9cf #2241 A=com.miui.home U=0 sz=1}
Run #0: ActivityRecord{279bc098 u0 com.miui.home/.launcher.Launcher t2241}
6. dp和sp的區(qū)別
dp是Android頁面常用的度量單位, sp主要用于字體度量.
在標準情況下, dp等于sp. 然而, Android系統(tǒng)允許用戶設(shè)置字體大小, sp會隨著字體的大小而改變, 放大或是縮小.
設(shè)置位置(紅米): Android -> 設(shè)置 -> 字體大小 -> 標準(默認)或大小號.
7. AlertDialog獲取全部屏幕監(jiān)聽
在Android 4.0以上, AlertDialog在觸摸對話框邊緣外部時, 對話框消失.
在AlertDialog.Builder.create(), 可以設(shè)置屬性獲取屏幕監(jiān)聽.
方法一:
setCanceledOnTouchOutside(false);
調(diào)用這個方法時, 按對話框以外的地方不起作用. 按返回鍵仍起作用.
方法二:
setCancelable(false);
調(diào)用這個方法時, 按對話框以外的地方不起作用. 按返回鍵也不起作用.
8. getColor遺棄
最新版本的getColor被遺棄(deprecated), 使用時, 需要添加主題.
也可以使用兼容模式, 即
ContextCompat.getColor(context, R.color.your_color);
ContextCompat.getColor
的源碼
public static final int getColor(Context context, int id) {
final int version = Build.VERSION.SDK_INT;
if (version >= 23) {
return ContextCompatApi23.getColor(context, id);
} else {
return context.getResources().getColor(id);
}
}
9. libarchive和expat簡介
libarchive
Multi-format archive and compression library. 多格式存檔和壓縮庫.
Android的toolchain使用libArchive.
參考
expat
Expat is an XML parser library written in C. Expat是用C語言寫的XML解析庫.
Android的Platform的擴展.
參考
libarchive 2.8.4和expat 2.1.0會產(chǎn)生漏洞, 如需修復(fù), 需要升級Android的編譯版本.
10. 網(wǎng)頁重定向
默認鏈接會跳轉(zhuǎn)其他鏈接, 根據(jù)鏈接內(nèi)容, 進行相應(yīng)操作, 如下載Apk等. 如果使用重定向, 則返回false; 如果非重定向, 則返回true.
WebViewClient webClient = new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.endsWith(".apk")) {
DownloadUtils.downloadFiles(url);
if (mStartDownloadAppListener != null) {
mStartDownloadAppListener.doAfter();
}
return true;
}
return false;
}
};
setWebViewClient(webClient);
OK, that's all! Enjoy it!