Solve the problem checkArgs fail, thumbData should not be null or exceed 128kb

1. Phenomenon: WeChat Mini Program Card Sharing’, some mobile phones fail to share

1. Problem detailed error log: checkArgs fail, thumbData should not be null or exceed 128kb

Problem: Parameter error, thumbData cannot be empty or larger than 128kb

2.Solution

Compressed Bitmap
Method: bmpToByteArrayBySize
Parameters: 1. The Bitmap that needs to be compressed; 2. The size that cannot be exceeded, the unit is kb; 3. Whether the image has transparency
Return type: ByteArray
code show as below:

 private fun bmpToByteArrayBySize(
         bmp: Bitmap,
         maxSize: Int,
         isWithAlpha: Boolean = false
     ): ByteArray? {<!-- -->
         val byteArrayOutputStream = ByteArrayOutputStream()
         //Compressed format (if the compressed image has transparency, you need to select PNG)
         var compressFormat = Bitmap.CompressFormat.JPEG
         if (isWithAlpha) {<!-- -->
             compressFormat = Bitmap.CompressFormat.PNG
         }
         //Compression quality (compression quality range 0-100, the larger the value, the better the quality. For PNG and WEBP formats, this parameter has no effect and can be set to 0)
         var compressQuality = 100
         //Compress the bitmap to the specified format
         bmp.compress(compressFormat, compressQuality, byteArrayOutputStream)
         //Determine whether the compressed output stream meets the specified conditions
         while ((byteArrayOutputStream.size() / 1024) > maxSize) {<!-- -->
             compressQuality -= 10
             if (compressQuality <= 0) {<!-- -->
                 break
             }
             byteArrayOutputStream.reset()
             bmp.compress(compressFormat, compressQuality, byteArrayOutputStream)
         }
         return byteArrayOutputStream.toByteArray()
     }

Share mini program card method call, the code is as follows:

fun shareWXSmallProject(context: Context,miniProgramUserName: String,path: String){<!-- -->
    val api = WXAPIFactory.createWXAPI(context, WX_ID)
    if (!api.isWXAppInstalled & amp; & amp; !AppKit.isAvailable(ScaffoldConfig.getApplication(), "com.tencent.mm")) {<!-- -->
        shareTo(ShareMedia.SHARE_WX)
    }else{<!-- -->
        val miniProgramObj = WXMiniProgramObject()
        miniProgramObj.webpageUrl = "http://www.qq.com" // Compatible with lower version web page links
        miniProgramObj.miniprogramType =
            WXMiniProgramObject.MINIPTOGRAM_TYPE_RELEASE // Official version: 0, test version: 1, experience version: 2
        miniProgramObj.userName = miniProgramUserName // Mini program original id
        miniProgramObj.path = path //Mini program page path; for mini games, you can only pass in the query part to achieve the parameter passing effect, such as: passing in "?foo=bar"
        val msg = WXMediaMessage(miniProgramObj)
        msg.title = getString(R.string.mini_program_title) // Mini program message title
        msg.description = getString(R.string.mini_program_des) // Mini program message desc
        val bmp = BitmapFactory.decodeResource(resources, R.mipmap.mini_program_share)
        val thumb = bmpToByteArrayBySize(bmp,128)
        msg.thumbData = thumb // Mini program message cover image, less than 128k
        val req = SendMessageToWX.Req()
        req.transaction = buildTransaction("miniProgram")
        req.message = msg
        req.scene = SendMessageToWX.Req.WXSceneSession // Currently only supports sessions
        api.sendReq(req)
    }
}

2. Solution ideas

1. Discovery of problems

After developing the sharing mini program card function, I used the test machine on hand to test it. I found that the error message picture was too large. My first reaction was to check the resource file size of 65kb. At this time, I thought that the picture met the requirement of less than 128kb. Why is there still this error? After comparing other resource files, I found that the digits of this picture are different from those of other resource files. I thought there might be other requirements for the picture but the document didn’t write them down, so I went to the designer to ask for them again. A picture with the same number of digits as other resource files. The size of the picture given to me by the designer later was 24kb. I found that the test machine I had was fine. I thought it was really a problem with the number of digits of the picture. The document did not make it clear.
Up to this point I didn’t realize that the picture was actually getting smaller, so my test machine could use this function normally
Later, I used the test machine I had on hand to test and all passed, thinking that there was no problem with this function. However, there was a mobile phone and there was no response when clicking WeChat. The error was the same as before, because only one mobile phone had this error. I have no clue. I wonder if there is no way to use this picture on this phone? Is WeChat not compatible? I’ll try changing a random resource picture to see if it’s the problem with the picture. At this time, I didn’t think about the error log. It was clearly written in the log that the picture did not meet the requirements and exceeded 128kb, but I didn’t think about it.

2. Reasons for the above strange ideas

1. Don’t understand the principle of generating Bitmap from resource files

val bmp = BitmapFactory.decodeResource(resources, R.mipmap.mini_program_share)

The BitmapFactory.decodeResource() method is used to decode a bitmap from a resource.

The size of the resource file and the size of the decoded bitmap will be different because the resource file will be decompressed and restored to a bitmap object during the decoding process. This is to facilitate operation and display in memory. So the decoded bitmap will be affected by size, color, and screen pixels.

This is why some mobile phones have problems being unable to share, because the size of the bitmap in the memory is greater than 128kb; different mobile phones have different resolutions and different screen pixels, so the generated bitmaps are different.

2. Not understanding the method call parameters

bmp.compress(compressFormat, compressQuality, byteArrayOutputStream)

Parameter 1: Compression format to be used
Bitmap.CompressFormat enumeration type. You can choose one of three formats:
Bitmap.CompressFormat.JPEG: Compress bitmap to JPEG format.
Bitmap.CompressFormat.PNG: Compress bitmap to PNG format.
Bitmap.CompressFormat.WEBP: Compress bitmap to WEBP format.
Parameter 2: Compression quality, the value range is 0 to 100. For JPEG format, higher values mean higher quality but larger files; for PNG and WEBP formats, this parameter has no effect and can be set to 0.
Parameter three: Output stream, usually ByteArrayOutputStream is used to store compressed data.

In fact, I found that when the error message said that it was larger than 128kb, some people used the compression method to compress the image. However, I found that calling the compression method had no effect, so I did not continue to think about image compression.
The compression method used at that time was copied from the Internet. There was no thought at all about the principle and method parameters of this compression method, so there was no clue. If you had copied the compression method from the Internet and understood the parameters, the problem would have been solved soon.

3. Summary

For the used code, especially the copied code, you must understand the principle clearly. This is not a way to solve the problem, and you missed the solution because you used it incorrectly; when you use the code, you will find that it is used. It is a knowledge point that I am not familiar with. I need to understand the principle, just like the generation of Bitmap. If I knew the storage method and principle of bitmap and resource file size before, I would immediately realize that there will indeed be larger than 128kb. situation, this will not cause the designer to keep changing the pictures without any reason.

4. Knowledge expansion

1. The reason why the size of the resource file and the size of the decoded bitmap may be different is because they represent different concepts.

Resource file size: Resource file size refers to the size of the file stored on disk. It represents the number of bytes occupied by resource files (such as image files) in the file system. Resource file size is usually determined based on the file’s compression format and the complexity of the image content. For example, a
Resource files in PNG format may be larger than corresponding JPEG format files because PNG uses a lossless compression algorithm while JPEG uses a lossy compression algorithm.

Decoded bitmap size: The decoded bitmap size refers to the size of the space occupied by the bitmap object in memory. It represents the number of bytes occupied by the pixel data stored in memory by the bitmap. The size of a bitmap depends on the width, height, and color depth of each pixel. For example, a
A bitmap of 100×100 pixels with RGB 24-bit color depth will occupy 100x100x3 = 30,000 bytes of memory space.

2.Bitmap.CompressFormat.JPEG, Bitmap.CompressFormat.PNG and Bitmap.CompressFormat.WEBP are three different bitmap compression formats. They have different characteristics and applicable scenarios.

  1. JPEG (Joint Photographic Experts Group):

    • Compression algorithm: JPEG uses a lossy compression algorithm that reduces file size by removing detail and redundant information from the image.
    • Compression Quality: The compressQuality parameter plays a role in JPEG compression, with higher values indicating higher quality but larger file sizes.
    • Supported color depth: JPEG supports 24-bit true color (RGB) images, as well as grayscale images.
    • Applicable scenarios: The JPEG format is suitable for storing photos and images, especially when color details are not required but smaller file sizes are required.
  2. PNG (Portable Network Graphics):

    • Compression algorithm: PNG uses a lossless compression algorithm that retains all details and information of the image.
    • Compression Quality: The compressQuality parameter has no practical effect in PNG compression and can be set to 0.
    • Supported color depth: PNG supports 8-bit indexed color, 24-bit true color (RGB), and 32-bit images with transparency.
    • Applicable scenarios: The PNG format is suitable for situations where image details need to be retained, transparency is supported, and the file size is relatively small, such as icons, transparent background images, etc.
  3. WEBP:

    • Compression algorithm: WEBP is an image format that supports lossy and lossless compression and has good compression performance.
    • Compression Quality: The compressQuality parameter plays a role in WEBP compression, higher values mean higher quality but also larger file sizes.
    • Color depth support: WEBP supports 24-bit true color (RGB), as well as images with transparency.
    • Applicable scenarios: The WEBP format is suitable for transmitting images on the network and can provide better image quality while maintaining a smaller file size.

The choice of compression format should be determined based on specific needs and usage scenarios. JPEG is suitable for photos and color images, PNG is suitable for images that need to retain details and transparency, and WEBP is a format with better overall performance and is suitable for network transmission and image display.

3.Bitmap.Config enumeration type can be used to create bitmaps

Bitmap.Config.ALPHA_8: This configuration is suitable for situations where you only need to store the transparency information of the image without color information. Each pixel uses 8 bits to represent transparency and no color information is stored.

Bitmap.Config.ARGB_4444: This configuration is suitable for situations where transparency and color information need to be stored. Each pixel uses 4 bits to represent transparency and 4 bits to represent red, green, and blue components.

Bitmap.Config.ARGB_8888: This is the most commonly used configuration and is suitable for situations where transparency and high-quality color information need to be stored. Each pixel uses 8 bits for transparency, 8 bits for the red component, 8 bits for the green component, and 8 bits for the blue component.

Bitmap.Config.RGB_565: This configuration is suitable for situations where color information needs to be stored but transparency is not required. Each pixel uses 5 bits to represent the red component, 6 bits to represent the green component, and 5 bits to represent the blue component.