In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the relevant knowledge of "what are the methods of filling holes in Android10". In the operation of actual cases, many people will encounter such a dilemma. Next, let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
1.Region.Op related exception: java.lang.IllegalArgumentException: Invalid Region.Op-only INTERSECT and DIFFERENCE are allowed
For the exception caused by calling canvas.clipPath (path, Region.Op.XXX) when targetSdkVersion > = Build.VERSION_CODES.P, the reference source code is as follows:
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");}}
We can see that when the target version starts from Android P, Canvas.clipPath (@ NonNull Path path, @ NonNull Region.Op op); has been abandoned and contains abnormal risks of abandoned API, only Region.Op.INTERSECT and Region.Op.DIFFERENCE are compatible, almost all blog solutions are as follows:
If (Build.VERSION.SDK_INT > = Build.VERSION_CODES.P) {canvas.clipPath (path);} else {canvas.clipPath (path, Region.Op.XOR); / / REPLACE, UNION, etc.}
But we must need some advanced logic operations. what if it works? For example, if the novel simulates the effect of page turning, the solution is as follows: use Path.op instead, calculate Path first, and then
Give canvas.clipPath:if (Build.VERSION.SDK_INT > = Build.VERSION_CODES.P) {Path mPathXOR = new Path (); mPathXOR.moveTo (0Power0); mPathXOR.lineTo (getWidth (), 0); mPathXOR.lineTo (getWidth (), getHeight ()); mPathXOR.lineTo (0GramgetHeight ()); mPathXOR.close (); / / above draw Path of the same size according to the actual size of Canvas or View mPathXOR.op (mPath0, Path.Op.XOR); canvas.clipPath (mPathXOR) } else {canvas.clipPath (mPath0, Region.Op.XOR);}
two。 Plaintext HTTP restrictions
When targetSdkVersion > = Build.VERSION_CODES.P, HTTP requests are restricted by default, and related logs appear:
Java.net.UnknownServiceException: CLEARTEXT communication to xxx not permitted by network security policy
The first solution: add the following node code to Application in AndroidManifest.xml
The second solution: create a new xml directory in the res directory, skip creating a new xml file network_security_config.xml in the xml directory, and then add the following node code to Application in AndroidManifest.xml
Android:networkSecurityConfig= "@ xml/network_config"
The name is random and the content is as follows:
Reading and writing of media resources in 3.Android Q
1. Scan system photo albums, videos, etc., pictures and video selectors are provided through ContentResolver. The main codes are as follows:
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_ project [0])) String name = imageCursor.getString (imageCursor.getColumnIndexOrThrow (IMAGE_ project [1]); int id = imageCursor.getInt (imageCursor.getColumnIndexOrThrow (IMAGE_ project [2])); String folderPath = imageCursor.getString (imageCursor.getColumnIndexOrThrow (IMAGE_ project [3])); String folderName = imageCursor.getString (imageCursor.getColumnIndexOrThrow (IMAGE_ project [4])) / / Android Q public directory can only be accessed through Content Uri + id. All previous File paths are invalid. If it is Video, remember to change it to MediaStore.Videosif (Build.VERSION.SDK_INT > = Build.VERSION_CODES.Q) {path = MediaStore.Images.Media .EXTERNAL _ CONTENT_URI .buildUpon () .appendPath (String.valueOf (id)) .appendPath () .toString ();}
2. Determine the existence of public directory files. Starting from Android Q, the File API of public directories becomes invalid and cannot be directly passed through new File (path). Exists (). The correct way to determine the existence of public directory files is as follows:
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 or download the file to a public directory and save Bitmap. For example, you can refer to the corresponding file type for Download,MIME_TYPE. Only APK is described here, from private directory copy to public directory demo as follows (for remote download, as long as you get OutputStream, you can also download to a private directory and then copy to a public directory):
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 ()) {/ / when the file exists is = new FileInputStream (sourceFile); / / read the original file 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. Save pictures related
/ * saved through MediaStore, compatible with AndroidQ, and automatically added to the album database after successful save. There is no need to send a broadcast to tell the system to insert the album * * @ param context context * @ param sourceFile source file * @ param saveFileName saved file name * @ param saveDirName picture subdirectory * @ return success or failure * / 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 does not get focus by default and does not pop up the keyboard automatically.
The problem occurs in the case of targetSdkVersion > = Build.VERSION_CODES.P, and the device version is above Android P. The solution is to add the following code to onCreate to gain focus. If you need to pop up the keyboard, you can delay it:
MEditText.post (()-> {mEditText.requestFocus (); mEditText.setFocusable (true); mEditText.setFocusableInTouchMode (true);})
5. Install Intent related to APK Intent and other shared files
/ * since Android N, relevant files have been shared through FileProvider, but Android Q restricts the public directory File API and can only be operated through Uri. * from the point of view of the code, it has become the same as the previous earlier version. Only the permission code Intent.FLAG_GRANT_READ_URI_PERMISSION*/private void installApk () {if (Build.VERSION.SDK_INT > = Build.VERSION_CODES.Q) {/ / adapts to Android Q must be added. Note that mFilePath is obtained through ContentResolver. There is a related code Intent intent = new Intent (Intent.ACTION_VIEW) above. 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 transparency related, windowIsTranslucent attribute
AndroidQ is another sinkhole. If you want to display a translucent Activity, before android10, the normal style Activity only needs to set windowIsTranslucent=true, but when it comes to AndroidQ, it has no effect, and if you dynamically set View.setVisibility (), the interface will also appear residual shadow.
Solution: use Dialog style Activity, and set windowIsFloating=true, and then the problem arises again. If fitsSystemWindow=true is not set in the Activity root layout, the default is not to invade the status bar, making the interface look normal.
7. Clipboard compatible
In Android Q, the clipboard can only be accessed and monitored when the application is interactive (the default input method itself is interactive), and the clipboard cannot be accessed directly in the onResume callback. This has the advantage of avoiding some application backend listening frantically to respond to the clipboard contents and crazy pop-up windows.
Therefore, if you still need to monitor the clipboard, you can use the application lifecycle callback to monitor the return of the APP backend, delay the access to the clipboard for a few milliseconds, and then save the clipboard content obtained from the last visit. Each time, compare whether there are any changes, and then proceed to the next step.
8. Third party share pictures and other operations, directly use the file path, such as QQ picture sharing, all need to note that this is not feasible, only through MediaStore and other API, get Uri to operate
These are listed according to the actual problems encountered when sdk is upgraded to 29, not the behavior changes in translation AndroidQ. Please solve the specific problems according to your own reality.
This is the end of the content of "what are the methods of filling holes in Android10". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.