Android API相容,其他API,UI適配(2)
- Gson、FastJson、org.JSON到底哪一個效率更高,速度更快- https://blog.csdn.net/zml_2015/article/details/52165317
-- Try catch與throw new Exception的區別?
Try catch可以捕獲住異常,不讓程式崩潰;
throw new Exception 與 throws Exception丟擲異常,不去處理,會導致程式崩潰。
丟擲異常,程式會崩潰嗎,會的。
-- WifiP2pManager 4.0,使用WiFi P2P需要Android API Level >= 14才可以;
SDK4.1對應API 16;
Android 4.1API WifiManager新特性;
WifiP2P是在 Android 4.0 以上系統中加入的功能,通過WifiP2P可以在不連線網路的情況下,直接與配對的裝置進行資料交換。他相比藍芽傳輸速率更快,更遠;相比網路傳輸過程中不會消耗流量。WifiP2P的傳輸依賴於無限WiFi,因此裝置之間通訊需要連線同一個WiFi網路。在WifiP2P技術中有一個核心類WifiP2pManager,他提供了所有的通訊相關的廣播資訊,監聽資訊,裝置資訊以及初始化操作等。在資訊傳輸過程中需要有個接收端接收資訊和傳送端傳送資訊,這裡稱為客戶端和服務端,客戶端和服務端通過WifiP2P作為傳輸手段,通過socket作為資訊載體,進行通訊。
https://www.jianshu.com/p/14ec886bb624
android wifi 點對點傳輸- https://github.com/changchengfeng/WifiP2PSample
Wi-Fi DirectAPI在Android 4.1中被增強以支援在WifiP2pManager中的預先關聯服務發現。這允許在連線之前使用Wi-Fi Direct通過服務發現和篩選周圍的裝置。與此同時,Network ServiceDiscovery允許你在一個已存在並保持連線的網路上發現一個服務(例如一個本地的Wi-Fi網路)。
-- 解決Android ImageView用setImageDrawable方法圖片縮小的問題-https://blog.csdn.net/changemyself/article/details/43054933
- setImageDrawable(getResources().getDrawable()但是發現在5.1中是過期的
Android中getResources().getDrawable() 過時的解決方法-https://blog.csdn.net/xu20082100226/article/details/72625266
1.當你這個Drawable不受主題影響時
ResourcesCompat.getDrawable(getResources(), R.drawable.name, null);
2.當你這個Drawable受當前Activity主題的影響時
ContextCompat.getDrawable(getActivity(), R.drawable.name);
3.當你這個Drawable想使用另外一個主題樣式時
ResourcesCompat.getDrawable(getResources(), R.drawable.name, anotherTheme);
Android中圖片setImageResource和setBackgroundResource的區別
剛好專案中碰到需要再一個button點選的時候進行圖片的切換, 很簡單的實現了,但是呢,之前使是iv_setBackgroundResource的方法來設定背景圖片的切換,因為之前都是這麼幹的,可是這個翻水水了,會出現背景圖片重疊陰影的問題,後面使用了setImageResource,直接去設定圖片的資源路徑就顯示正常了。原因是現在的圖片是帶有陰影的背景的,所以設定setBackground會出現問題。
在程式碼中為ImageView引用圖片之setImageDrawable和setBackgroundResource- https://blog.csdn.net/languobeibei/article/details/69389153
- 關於Java中null的十點詳解- https://www.cnblogs.com/greatfish/p/5906617.html
String str = null;
str = str+"hello";
列印結果為:null hello
-- TaskStackBuilder API level16(4.1);4.0對應API是:14.
關於TaskStackBuilder- https://www.cnblogs.com/aheiabai/p/5931536.html
TaskStackBuilder API level16(4.1)
TaskStackBuilder可以構造一個合成的回退棧,主要用於跨任務導航,應用於Android3.0及新版本。
我們通常利用返回鍵導航app,而返回鍵是基於當前任務的導航,這種區域性的導航只有將當前任務中所有Activity結束掉時才返回上個任務,若從當前app跳轉到另一app時就涉及到不同任務的跳轉,也就是從任務一跳轉到任務二時,從任務二中按返回鍵時無法直接返回到任務一,除非任務二中只存在一個Activity。
為了提供更好的使用者體驗,在跨應用的跳轉中,利用TaskStackBuilder的getPendingIntent(int requestCode, int flags),可將當前任務中的Activity和要啟動的Activity合成為一個新的任務,而使用者按返回鍵的操作就作用在這個新任務中,這相當於實現了跨任務直接跳轉。
若從任務一直接啟動一個Intent去開啟另一個應用的Activity,會直接把該Activity加入到這個應用的任務二中去,按返回鍵時最終只會回到主介面,而不會回到任務一。
若要向老版本相容可使用android.support.v4.app.TaskStackBuilder實現相同效果。
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mActivity);
stackBuilder.addParentStack(CarActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager = (NotificationManager) mActivity
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification n = builder.build();
n.flags = n.flags | Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(notificationFinished, n);
} else {
android.support.v4.app.TaskStackBuilder stackBuilder = android.support.v4.app.TaskStackBuilder.create(mActivity);
stackBuilder.addParentStack(CarActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager = (NotificationManager) mActivity
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification n = builder.build();
n.flags = n.flags | Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(notificationFinished, n);
}
private static long getTotalSize(String path) {
StatFs fileStats = new StatFs(path);
fileStats.restat(path);
if (Build.VERSION.SDK_INT >= 18) {
return (long) fileStats.getBlockCountLong() * fileStats.getBlockSizeLong();
} else {
return (long) fileStats.getBlockCount() * fileStats.getBlockSize();
}
}
Canvas.saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int saveFlags):
本身和save方法差不多,但是它單獨分配了一個畫布用於繪製圖層。它定義了一個畫布區域(可設定透明度),此方法之後的所有繪製都在此區域中繪製,直到呼叫canvas.restore()方法。例如:在呼叫saveLayerAlpha方法之前繪製了一個“圓形”,在呼叫saveLayerAlpha方法之後繪製了一個“圓形”此時這兩個圓形並不在同一個圖層。下面給出一個例子以及樣圖來說明這個問題。
-- Thread.run(),start()
呼叫start方法方可啟動執行緒,而run方法只是thread的一個普通方法呼叫,還是在主執行緒裡執行。這兩個方法應該都比較熟悉,把需要並行處理的程式碼放在run()方法中,start()方法啟動執行緒將自動呼叫 run()方法,這是由jvm的記憶體機制規定的。並且run()方法必須是public訪問許可權,返回值型別為void.。
Thread的run()與start()的區別- https://blog.csdn.net/qiumeng_1314/article/details/79466655
1.start()方法來啟動執行緒,真正實現了多執行緒執行。這時無需等待run方法體程式碼執行完畢,可以直接繼續執行下面的程式碼;通過呼叫Thread類的start()方法來啟動一個執行緒, 這時此執行緒是處於就緒狀態, 並沒有執行。 然後通過此Thread類呼叫方法run()來完成其執行操作的, 這裡方法run()稱為執行緒體,它包含了要執行的這個執行緒的內容, Run方法執行結束, 此執行緒終止。然後CPU再排程其它執行緒。
用start方法來啟動執行緒,真正實現了多執行緒執行,這時無需等待run方法體程式碼執行完畢而直接繼續執行下面的程式碼。通過呼叫Thread類的start()方法來啟動一個執行緒,這時此執行緒處於就緒(可執行)狀態,並沒有執行,一旦得到cpu時間片,就開始執行run()方法,這裡方法 run()稱為執行緒體,它包含了要執行的這個執行緒的內容,Run方法執行結束,此執行緒隨即終止。
2.run()方法當作普通方法的方式呼叫。程式還是要順序執行,要等待run方法體執行完畢後,才可繼續執行下面的程式碼; 程式中只有主執行緒——這一個執行緒, 其程式執行路徑還是隻有一條, 這樣就沒有達到寫執行緒的目的。
run()方法只是類的一個普通方法而已,如果直接呼叫Run方法,程式中依然只有主執行緒這一個執行緒,其程式執行路徑還是隻有一條,還是要順序執行,還是要等待run方法體執行完畢後才可繼續執行下面的程式碼,這樣就沒有達到寫執行緒的目的。總結:呼叫start方法方可啟動執行緒,而run方法只是thread的一個普通方法呼叫,還是在主執行緒裡執行。這兩個方法應該都比較熟悉,把需要並行處理的程式碼放在run()方法中,start()方法啟動執行緒將自動呼叫 run()方法,這是由jvm的記憶體機制規定的。並且run()方法必須是public訪問許可權,返回值型別為void。
public class Test {
public static void main(String[] args) {
Runner1 runner1 = new Runner1();
Runner2 runner2 = new Runner2();
// Thread(Runnable target) 分配新的 Thread 物件。
Thread thread1 = new Thread(runner1);
Thread thread2 = new Thread(runner2);
// thread1.start();
// thread2.start();
thread1.run();
thread2.run();
}
}
class Runner1 implements Runnable { // 實現了Runnable介面,jdk就知道這個類是一個執行緒
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("進入Runner1執行狀態——————————" + i);
}
}
}
class Runner2 implements Runnable { // 實現了Runnable介面,jdk就知道這個類是一個執行緒
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("進入Runner2執行狀態==========" + i);
}
}
}
-- 提供的SwitchButton-https://github.com/kyleduo/SwitchButton
-- canvas.saveLayerAlpha
// canvas.saveLayerAlpha(RectF bounds, int alpha, int saveFlags) 在API26被廢棄,Canvas下Flag常量在API27
// canvas.saveLayerAlpha(mSaveLayerRectF, mAlpha, Canvas.MATRIX_SAVE_FLAG
// | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
// | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
canvas.saveLayerAlpha ( mSaveLayerRectF , mAlpha );
View.setBackground上下版本相容型的問題
int sdk = android.os.Build.VERSION.SDK_INT;
if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
setBackgroundDrawable( drawable );
}
else {
setBackground( drawable );
}
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
setBackgroundDrawable( null );
}
else {
setBackground( null );
}
LeftBtn.setBackground(ContextCompat.getDrawable(mActivity, R.drawable.guide_btn_prev_prss));
-- RenderScript; ScriptIntrinsicBlur sdk4.2
AndroidStudio中使用V8包中的RenderScript,只需要修改專案的build.gradle中的程式碼即可
對於android gradle plugin v0.14+:
android {
...
defaultConfig {
...
renderscriptTargetApi 19
renderscriptSupportModeEnabled true
}
...
}
在android gradle plugin v0.13.3及以前的版本中:
android {
...
defaultConfig {
...
renderscriptTargetApi 19
renderscriptSupportMode true
}
...
}
之後,我們就可以在2.2以上的程式碼中使用v8包中的RenderScript了,如:
import android.support.v8.renderscript.*
android.renderscript.ScriptIntrinsicBlur 4.2導致這個問題就是因為這個api不能向下相容,現在我們就來解決這個問題。其實google早就提供了方案,我們只需要使用就好了。
1、引入renderscript-v8.jar(將jar包放在libs目錄下,add to build path)
-- Android 8.0 利用Settings.Global屬性跨應用定義標誌位-https://blog.csdn.net/ouzhuangzhuang/article/details/82258148
系統級別應用
在需要定義的地方使用 SystemProperties.set(“dev.xxx.xxx”, “false”);
在獲取的部分使用 SystemProperties.getBoolean(“ro.mmitest”, false))
最後記得要導包 import android.os.SystemProperties
非系統級別應用
在需要定義的地方使用 Settings.Global.putInt(context.getContentResolver(),“xxx.xxx”,1);
在獲取的部分使用 boolean mTag = Settings.Global.getInt(getActivity().getContentResolver(),“xxx.xxx”, 0) == 1;
依舊別忘記導包 import android.provider.Settings;
Android實踐 -- 設定系統日期時間和時區-https://www.jianshu.com/p/6c6a6091545d
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
--適配未知來源的管理許可權,手機相容劉海屏解決方案
關於Android各個型別手機相容劉海屏解決方案- https://blog.csdn.net/mr_zengkun/article/details/80984117
Android中系統應用適配未知來源的管理許可權-https://blog.csdn.net/zdc9023/article/details/78861822
Android中為了防止一些不良應用的隨便靜默安裝,設定了未知來源應用的開關,在不同的android版本中使上會有所區別
/**
* 開啟未知來源許可權
* @param context
*/
public static void openNonMarketAppsPerm(Context context){
if (Build.VERSION.SDK_INT < 17) {
int flag = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.INSTALL_NON_MARKET_APPS, 0);
if(flag == 0){
Settings.Secure.putInt(context.getContentResolver(),
Settings.Secure.INSTALL_NON_MARKET_APPS, 1);
}
} else {
int flag = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.INSTALL_NON_MARKET_APPS, 0);
if(flag == 0){
Settings.Global.putInt(context.getContentResolver(),
Settings.Global.INSTALL_NON_MARKET_APPS, 1);
}
}
}
/**
* 關閉未知來源許可權
* @param context
*/
public static void closeNonMarketAppsPerm(Context context){
if (Build.VERSION.SDK_INT < 17) {
int flag = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.INSTALL_NON_MARKET_APPS, 1);
if(flag == 1) {
Settings.Secure.putInt(context.getContentResolver(),
Settings.Secure.INSTALL_NON_MARKET_APPS, 0);
}
} else {
int flag= Settings.Global.getInt(context.getContentResolver(),
Settings.Global.INSTALL_NON_MARKET_APPS, 1);
if (flag==1){
Settings.Global.putInt(context.getContentResolver(),
Settings.Global.INSTALL_NON_MARKET_APPS, 0);
}
}
}
/**
* 檢查狀態是否開啟
* @param context
*/
public static boolean checkNonMarketAppsPermStatus(Context context){
boolean unKnowSource=false;
if (Build.VERSION.SDK_INT<17){
unKnowSource=Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.INSTALL_NON_MARKET_APPS, 0)==1;
}else{
unKnowSource=Settings.Global.getInt(context.getContentResolver(),
Settings.Global.INSTALL_NON_MARKET_APPS, 0)==1;
}
return unKnowSource;
}
如果相容4.0以下版本則需要把Settings.Secure 和Settings.Global 改為:Settings.System方式獲取未知來源的狀態或修改狀態
- wait(),notify/notifyAll
當執行緒執行wait()時,會把當前的鎖釋放,然後讓出CPU,進入等待狀態。
當執行notify/notifyAll方法時,會喚醒一個處於等待該 物件鎖 的執行緒,然後繼續往下執行,直到執行完退出物件鎖鎖住的區域(synchronized修飾的程式碼塊)後再釋放鎖。