Android10填坑方法有哪些

本篇內(nèi)容介紹了“Android10填坑方法有哪些”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供烏審網(wǎng)站建設(shè)、烏審做網(wǎng)站、烏審網(wǎng)站設(shè)計(jì)、烏審網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、烏審企業(yè)網(wǎng)站模板建站服務(wù),十載烏審做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

1.Region.Op相關(guān)異常:java.lang.IllegalArgumentException: Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed

當(dāng)targetSdkVersion >=Build.VERSION_CODES.P 時(shí)調(diào)用 canvas.clipPath(path, Region.Op.XXX); 引起的異常,參考源碼如下:

@Deprecatedpublic boolean clipPath(@NonNull Path path, @NonNull Region.Op op) {  checkValidClipOp(op);  return nClipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt);}private static void checkValidClipOp(@NonNull Region.Op op) {  if (sCompatiblityVersion >= Build.VERSION_CODES.P   && op != Region.Op.INTERSECT && op != Region.Op.DIFFERENCE) {   throw new IllegalArgumentException(     "Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed");  }}

我們可以看到當(dāng)目標(biāo)版本從Android P開(kāi)始,Canvas.clipPath(@NonNull Path path, @NonNull Region.Op op) ; 已經(jīng)被廢棄,而且是包含異常風(fēng)險(xiǎn)的廢棄API,只有Region.Op.INTERSECT 和 Region.Op.DIFFERENCE 得到兼容,幾乎所有的博客解決方案都是如下簡(jiǎn)單粗暴:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { canvas.clipPath(path);} else { canvas.clipPath(path, Region.Op.XOR);// REPLACE、UNION 等}

但我們一定需要一些高級(jí)邏輯運(yùn)算效果怎么辦?如小說(shuō)的仿真翻頁(yè)閱讀效果,解決方案如下,用Path.op代替,先運(yùn)算Path,再

給canvas.clipPath:if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){ Path mPathXOR = new Path(); mPathXOR.moveTo(0,0); mPathXOR.lineTo(getWidth(),0); mPathXOR.lineTo(getWidth(),getHeight()); mPathXOR.lineTo(0,getHeight()); mPathXOR.close(); //以上根據(jù)實(shí)際的Canvas或View的大小,畫(huà)出相同大小的Path即可 mPathXOR.op(mPath0, Path.Op.XOR); canvas.clipPath(mPathXOR);}else { canvas.clipPath(mPath0, Region.Op.XOR);}

2.明文HTTP限制

當(dāng)targetSdkVersion >=Build.VERSION_CODES.P 時(shí),默認(rèn)限制了HTTP請(qǐng)求,并出現(xiàn)相關(guān)日志:

java.net.UnknownServiceException: CLEARTEXT communication to xxx not permitted by network security policy

第一種解決方案:在AndroidManifest.xml中Application添加如下節(jié)點(diǎn)代碼

<application android:usesCleartextTraffic="true">

第二種解決方案:在res目錄新建xml目錄,已建的跳過(guò) 在xml目錄新建一個(gè)xml文件network_security_config.xml,然后在AndroidManifest.xml中Application添加如下節(jié)點(diǎn)代碼

android:networkSecurityConfig="@xml/network_config"

名字隨機(jī),內(nèi)容如下:

<?xml version="1.0" encoding="utf-8"?><network-security-config> <base-config cleartextTrafficPermitted="true" /></network-security-config>

3.Android Q中的媒體資源讀寫(xiě)

1、掃描系統(tǒng)相冊(cè)、視頻等,圖片、視頻選擇器都是通過(guò)ContentResolver來(lái)提供,主要代碼如下:

private static final String[] IMAGE_PROJECTION = {   MediaStore.Images.Media.DATA,   MediaStore.Images.Media.DISPLAY_NAME,   MediaStore.Images.Media._ID,   MediaStore.Images.Media.BUCKET_ID,   MediaStore.Images.Media.BUCKET_DISPLAY_NAME}; Cursor imageCursor = mContext.getContentResolver().query(     MediaStore.Images.Media.EXTERNAL_CONTENT_URI,     IMAGE_PROJECTION, null, null, IMAGE_PROJECTION[0] + " DESC");String path = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));String name = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));int id = imageCursor.getInt(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));String folderPath = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[3]));String folderName = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[4]));//Android Q 公有目錄只能通過(guò)Content Uri + id的方式訪問(wèn),以前的File路徑全部無(wú)效,如果是Video,記得換成MediaStore.Videosif(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){  path = MediaStore.Images.Media      .EXTERNAL_CONTENT_URI      .buildUpon()      .appendPath(String.valueOf(id)).build().toString(); }

2、判斷公有目錄文件是否存在,自Android Q開(kāi)始,公有目錄File API都失效,不能直接通過(guò)new File(path).exists();判斷公有目錄文件是否存在,正確方式如下:

public static boolean isAndroidQFileExists(Context context, String path){  AssetFileDescriptor afd = null;  ContentResolver cr = context.getContentResolver();  try {   Uri uri = Uri.parse(path);   afd = cr.openAssetFileDescriptor(uri, "r");   if (afd == null) {    return false;   } else {    close(afd);   }  } catch (FileNotFoundException e) {   return false;  }finally {   close(afd);  }  return true;}

3、copy或者下載文件到公有目錄,保存Bitmap同理,如Download,MIME_TYPE類(lèi)型可以自行參考對(duì)應(yīng)的文件類(lèi)型,這里只對(duì)APK作出說(shuō)明,從私有目錄copy到公有目錄demo如下(遠(yuǎn)程下載同理,只要拿到OutputStream即可,亦可下載到私有目錄再copy到公有目錄):

public static void copyToDownloadAndroidQ(Context context, String sourcePath, String fileName, String saveDirName){  ContentValues values = new ContentValues();  values.put(MediaStore.Downloads.DISPLAY_NAME, fileName);  values.put(MediaStore.Downloads.MIME_TYPE, "application/vnd.android.package-archive");  values.put(MediaStore.Downloads.RELATIVE_PATH, "Download/" + saveDirName.replaceAll("/","") + "/");  Uri external = MediaStore.Downloads.EXTERNAL_CONTENT_URI;  ContentResolver resolver = context.getContentResolver();  Uri insertUri = resolver.insert(external, values);  if(insertUri == null) {   return;  }  String mFilePath = insertUri.toString();  InputStream is = null;  OutputStream os = null;  try {   os = resolver.openOutputStream(insertUri);   if(os == null){    return;   }   int read;   File sourceFile = new File(sourcePath);   if (sourceFile.exists()) { // 文件存在時(shí)    is = new FileInputStream(sourceFile); // 讀入原文件    byte[] buffer = new byte[1444];    while ((read = is.read(buffer)) != -1) {     os.write(buffer, 0, read);    }   }  } catch (Exception e) {   e.printStackTrace();  }finally {   close(is,os);  }}

4、保存圖片相關(guān)

/**  * 通過(guò)MediaStore保存,兼容AndroidQ,保存成功自動(dòng)添加到相冊(cè)數(shù)據(jù)庫(kù),無(wú)需再發(fā)送廣播告訴系統(tǒng)插入相冊(cè)  *  * @param context  context  * @param sourceFile 源文件  * @param saveFileName 保存的文件名  * @param saveDirName picture子目錄  * @return 成功或者失敗  */ public static boolean saveImageWithAndroidQ(Context context,             File sourceFile,             String saveFileName,             String saveDirName) {  String extension = BitmapUtil.getExtension(sourceFile.getAbsolutePath());  ContentValues values = new ContentValues();  values.put(MediaStore.Images.Media.DESCRIPTION, "This is an image");  values.put(MediaStore.Images.Media.DISPLAY_NAME, saveFileName);  values.put(MediaStore.Images.Media.MIME_TYPE, "image/png");  values.put(MediaStore.Images.Media.TITLE, "Image.png");  values.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/" + saveDirName);  Uri external = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;  ContentResolver resolver = context.getContentResolver();  Uri insertUri = resolver.insert(external, values);  BufferedInputStream inputStream = null;  OutputStream os = null;  boolean result = false;  try {   inputStream = new BufferedInputStream(new FileInputStream(sourceFile));   if (insertUri != null) {    os = resolver.openOutputStream(insertUri);   }   if (os != null) {    byte[] buffer = new byte[1024 * 4];    int len;    while ((len = inputStream.read(buffer)) != -1) {     os.write(buffer, 0, len);    }    os.flush();   }   result = true;  } catch (IOException e) {   result = false;  } finally {   close(os, inputStream);  }  return result;}

4.EditText默認(rèn)不獲取焦點(diǎn),不自動(dòng)彈出鍵盤(pán)

該問(wèn)題出現(xiàn)在targetSdkVersion >=Build.VERSION_CODES.P 情況下,且設(shè)備版本為Android P以上版本,解決方法在onCreate中加入如下代碼,可獲得焦點(diǎn),如需要彈出鍵盤(pán)可延遲一下:

mEditText.post(() -> {  mEditText.requestFocus();  mEditText.setFocusable(true);  mEditText.setFocusableInTouchMode(true);});

5.安裝APK Intent及其它共享文件相關(guān)Intent

/** 自Android N開(kāi)始,是通過(guò)FileProvider共享相關(guān)文件,但是Android Q對(duì)公有目錄 File API進(jìn)行了限制,只能通過(guò)Uri來(lái)操作,* 從代碼上看,又變得和以前低版本一樣了,只是必須加上權(quán)限代碼Intent.FLAG_GRANT_READ_URI_PERMISSION*/private void installApk() {  if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){   //適配Android Q,注意mFilePath是通過(guò)ContentResolver得到的,上述有相關(guān)代碼   Intent intent = new Intent(Intent.ACTION_VIEW);   intent.setDataAndType(Uri.parse(mFilePath) ,"application/vnd.android.package-archive");   intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);   intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);   startActivity(intent);   return ;  }  File file = new File(saveFileName + "demo.apk");  if (!file.exists())   return;  Intent intent = new Intent(Intent.ACTION_VIEW);  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {   intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);   intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);   Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "net.oschina.app.provider", file);   intent.setDataAndType(contentUri, "application/vnd.android.package-archive");  } else {   intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");   intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  }  startActivity(intent);}

6.Activity透明相關(guān),windowIsTranslucent屬性

Android Q 又一個(gè)天坑,如果你要顯示一個(gè)半透明的Activity,這在android10之前普通樣式Activity只需要設(shè)置windowIsTranslucent=true即可,但是到了AndroidQ,它沒(méi)有效果了,而且如果動(dòng)態(tài)設(shè)置View.setVisibility(),界面還會(huì)出現(xiàn)殘影...

解決辦法:使用Dialog樣式Activity,且設(shè)置windowIsFloating=true,此時(shí)問(wèn)題又來(lái)了,如果Activity根布局沒(méi)有設(shè)置fitsSystemWindow=true,默認(rèn)是沒(méi)有侵入狀態(tài)欄的,使界面看上去正常。

7.剪切板兼容

Android Q中只有當(dāng)應(yīng)用處于可交互情況(默認(rèn)輸入法本身就可交互)才能訪問(wèn)剪切板和監(jiān)聽(tīng)剪切板變化,在onResume回調(diào)也無(wú)法直接訪問(wèn)剪切板,這么做的好處是避免了一些應(yīng)用后臺(tái)瘋狂監(jiān)聽(tīng)響應(yīng)剪切板的內(nèi)容,瘋狂彈窗。

因此如果還需要監(jiān)聽(tīng)剪切板,可以使用應(yīng)用生命周期回調(diào),監(jiān)聽(tīng)APP后臺(tái)返回,延遲幾毫秒訪問(wèn)剪切板,再保存最后一次訪問(wèn)得到的剪切板內(nèi)容,每次都比較一下是否有變化,再進(jìn)行下一步操作。

8.第三方分享圖片等操作,直接使用文件路徑的,如QQ圖片分享,都需要注意,這是不可行的,都只能通過(guò)MediaStore等API,拿到Uri來(lái)操作

這些是我們根據(jù)sdk升級(jí)到29時(shí)遇到的實(shí)際問(wèn)題而羅列出來(lái)的,不是翻譯AndroidQ中的行為變更,具體問(wèn)題請(qǐng)根據(jù)自身實(shí)際自行解決。

“Android10填坑方法有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

新聞名稱:Android10填坑方法有哪些
本文路徑:http://muchs.cn/article38/iepspp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站、外貿(mào)建站全網(wǎng)營(yíng)銷(xiāo)推廣、網(wǎng)站改版、企業(yè)網(wǎng)站制作、網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)