本文的合集已經編著成書,高級Android開發強化實戰,歡迎各位讀友的建議和指導。在京東即可購買:https://item.jd.com/12385680.html
介紹關于Android的一些有趣的小知識點. 本文是第五篇了, 幾乎一周一篇, 歡迎閱讀.
其余第一篇, 第二篇, 第三篇, 第四篇.
1. 模擬系統回收Activity.
使用adb命令可以模擬Android系統自動回收Activity進程, 可以調試這個效果.
單進程
adb shell am force-stop [包名]
多進程
adb shell ps | grep [包名]
adb shell kill [PID]
2. Android庫動態權限建議
Android 6.0使用動態權限, 在創建第三方庫時, 需要充分考慮這一特性.
(1) 在自動Merge庫的AndroidManifest時, 需要提供危險權限的提示文檔.
(2) 當權限未獲取時, 用戶可以使用庫的某一部分, 并提示缺少權限.
(3) 需要提供在權限獲取失敗時, 庫使用方式的文檔.
(4) 確保所有權限都是必須的, 不含有未使用權限.
關于提示用戶獲取權限的解決方案, 可以參考.
3. RxJava處理Retry請求服務器
服務器經常會出現異常, 應用需要連續嘗試請求, RxJava可以非常簡單的實現.
模板
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數據.
5. 顯示Activity棧的Shell命令
Shell命令
adb shell dumpsys activity | sed -n -e '/Stack #/p' -e '/Running activities/,/Run #0/p'
直接獲取Activity信息有些冗余, 我們只關注堆棧信息即可.
sed可以編輯顯示的文字.
-n
, 從截取處開始連續處理.
-e
, 多選參數.
'/Stack #/p'
, 輸出含有Stack #
的行.
-e '/Running activities/,/Run #0/p'
, 輸出從Running activities
至Run #0
的所有行.
輸出結果
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的區別
dp是Android頁面常用的度量單位, sp主要用于字體度量.
在標準情況下, dp等于sp. 然而, Android系統允許用戶設置字體大小, sp會隨著字體的大小而改變, 放大或是縮小.
設置位置(紅米): Android -> 設置 -> 字體大小 -> 標準(默認)或大小號.
7. AlertDialog獲取全部屏幕監聽
在Android 4.0以上, AlertDialog在觸摸對話框邊緣外部時, 對話框消失.
在AlertDialog.Builder.create(), 可以設置屬性獲取屏幕監聽.
方法一:
setCanceledOnTouchOutside(false);
調用這個方法時, 按對話框以外的地方不起作用. 按返回鍵仍起作用.
方法二:
setCancelable(false);
調用這個方法時, 按對話框以外的地方不起作用. 按返回鍵也不起作用.
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會產生漏洞, 如需修復, 需要升級Android的編譯版本.
10. 網頁重定向
默認鏈接會跳轉其他鏈接, 根據鏈接內容, 進行相應操作, 如下載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!