圖片的顯示,加載,上傳、下載

一、圖片顯示
1、要做到圖片不變形,不裁剪,正常顯示,必須知道圖片的寬高或者是寬高比,加載的時(shí)候,如果高度大于寬度,就先加載高度為父布局高度,寬度根據(jù)比例加載,反之一樣。

  private fun setImageWidthHeight(imageView: ImageView,width:Int,height:Int){
        imageView.post {
            val params: RelativeLayout.LayoutParams = imageView.layoutParams as RelativeLayout.LayoutParams
            if (height >= width){ //撐滿高度
                imageView.layoutParams.height = mImageWidth
                val tempWidth: Float = (width.toFloat()) / (height.toFloat())
                imageView.layoutParams.width = (tempWidth * mImageWidth).toInt()
                imageView.layoutParams = params
                Log.d("setImageWidthHeight", "setImageWidthHeight: 圖片寬度是:${imageView.layoutParams.width},," +
                        ",高度是:${imageView.layoutParams.height}"+ ",,,,"+tempWidth)
            }else{
                imageView.layoutParams.width = mImageWidth
                val tempHeight: Float = (height.toFloat()) / (width.toFloat())
                imageView.layoutParams.height = (tempHeight * mImageWidth).toInt()
                imageView.layoutParams = params
                Log.d("setImageWidthHeight", "setImageWidthHeight: 圖片寬度是:${imageView.layoutParams.width},," +
                        ",高度是:${imageView.layoutParams.height}"+ ",,,,"+tempHeight)
            }
        }
    }

或者使用約束布局,前提也是必須知道寬高比或者寬高,只有知道了寬高比,才不會(huì)壓縮和變形

二、圖片加載
圖片的選取,壓縮、顯示,建議使用第三方加載庫(kù):pictureselector,里面已經(jīng)適配了Android 13版本
注:GIF圖片不能進(jìn)行壓縮,一旦壓縮就變成了靜態(tài)圖片

三、圖片上傳
上傳時(shí)區(qū)分類型
gif圖片使用MediaType.parse("image/gif");
靜態(tài)圖片使用MediaType.parse("image/png");類型

  fun <T> uploadImage(
        cls: Class<T>,
        reqUrl: String,
        fileList: ArrayList<BeanImage>,
        callBack: RequestCallBack<T>
    ) {

        val params = HashMap<String, Any>()
        HttpUtils.addCommonData(params)
        val multipartBodyBuilder = MultipartBody.Builder()
        multipartBodyBuilder.setType(MultipartBody.FORM)

        //遍歷map中所有參數(shù)到builder
        for (key in params.keys) {
            multipartBodyBuilder.addFormDataPart(key, params[key].toString() + "")
        }

        //遍歷paths中所有圖片絕對(duì)路徑到builder,并約定key如“upload”作為后臺(tái)接受多張圖片的key
        LogUtils.d(TAG, "uploadImage: 需要上傳的圖片是:${fileList}")
        for (index in 0 until fileList.size) {
            val url = fileList[index].url ?: ""
            val file = File(url)
            if (!file.exists()) {
                return
            }
            val fileName = System.currentTimeMillis().toString() + "_" + file.name
            LogUtils.d(TAG, "uploadImage 文件的名稱是: $fileName")
            if (fileList[index].isGif()) {
                Log.d(TAG, "uploadImage: 當(dāng)前是gif圖,,$fileName")
                multipartBodyBuilder.addFormDataPart(
                    "file${index}",
                    fileName,
                    file.asRequestBody(HttpUtils.MEDIA_TYPE_GIF)
                )
            } else {
                multipartBodyBuilder.addFormDataPart(
                    "file${index}",
                    fileName,
                    file.asRequestBody(HttpUtils.MEDIA_TYPE_PNG)
                )
            }
            multipartBodyBuilder.addFormDataPart("type", "1")
        }

        val builder = CacheControl.Builder()
        builder.noCache() //不使用緩存,全部走網(wǎng)絡(luò)
        builder.noStore() //不使用緩存,也不存儲(chǔ)緩存
        val cache: CacheControl = builder.build()
        val requestBody: RequestBody = multipartBodyBuilder.build()
        val requestBuilder = Request.Builder()
        requestBuilder.url(reqUrl)
        requestBuilder.cacheControl(cache)
        requestBuilder.post(requestBody)
        //設(shè)置header
        var headersMap: HashMap<String, String> = HashMap()
        headersMap = OKHttpExecuter.initHttpRequestHeader(headersMap)
        if (headersMap != null && headersMap.size > 0) {
            try {
                val headers: Headers = headersMap.toHeaders()
                requestBuilder.headers(headers)
            } catch (e: Exception) {
                Log.d(TAG, "uploadImage: " + e.message)
            }
        }
        val request: Request = requestBuilder.build()
        HttpUtils.client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                call.cancel()
                Log.d(TAG, "onFailure: " + e.message.toString())
                BaseUtils.getHandler().post {
                    callBack.error(e.message.toString())
                }
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: Response) {
                val str = response.body?.string() //圖片返回json數(shù)據(jù)
                call.cancel()
            }
        })
    }

三、圖片下載
圖片下載保存到圖庫(kù)需要申請(qǐng)存儲(chǔ)權(quán)限,使用XXPermissions申請(qǐng)權(quán)限。
保存到圖庫(kù)需要適配Android12分區(qū)存儲(chǔ),代碼參考pictureselector,靜態(tài)圖和動(dòng)態(tài)圖的下載要注意區(qū)分。

    /**
     * 保存文件
     *
     * @param context  上下文
     * @param path     文件下載路徑url
     * @param mimeType 文件類型
     * @param listener 結(jié)果回調(diào)監(jiān)聽(tīng)
     */
    public static void saveLocalFile(Context context, String path, String mimeType,
                                     OnCallbackListener<String> listener) {

        PictureThreadUtils.executeByIo(new PictureThreadUtils.SimpleTask<String>() {
            @Override
            public String doInBackground() {
                try {
                    Uri uri;
                    ContentValues contentValues = new ContentValues();
                    String time = ValueOf.toString(System.currentTimeMillis());
                    if (PictureMimeType.isHasAudio(mimeType)) {
                        contentValues.put(MediaStore.Audio.Media.DISPLAY_NAME, DateUtils.getCreateFileName("AUD_"));
                        contentValues.put(MediaStore.Audio.Media.MIME_TYPE, TextUtils.isEmpty(mimeType)
                                || mimeType.startsWith(PictureMimeType.MIME_TYPE_PREFIX_VIDEO)
                                || mimeType.startsWith(PictureMimeType.MIME_TYPE_PREFIX_IMAGE) ? PictureMimeType.MIME_TYPE_AUDIO : mimeType);
                        if (SdkVersionUtils.isQ()) {
                            contentValues.put(MediaStore.Audio.Media.DATE_TAKEN, time);
                            contentValues.put(MediaStore.Audio.Media.RELATIVE_PATH, Environment.DIRECTORY_MUSIC);
                        } else {
                            File dir = TextUtils.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)
                                    ? Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)
                                    : context.getExternalFilesDir(Environment.DIRECTORY_MUSIC);
                            contentValues.put(MediaStore.MediaColumns.DATA, dir.getAbsolutePath() + File.separator
                                    + DateUtils.getCreateFileName("AUD_") + PictureMimeType.AMR);
                        }
                        uri = context.getContentResolver().insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, contentValues);
                    } else if (PictureMimeType.isHasVideo(mimeType)) {
                        contentValues.put(MediaStore.Video.Media.DISPLAY_NAME, DateUtils.getCreateFileName("VID_"));
                        contentValues.put(MediaStore.Video.Media.MIME_TYPE, TextUtils.isEmpty(mimeType)
                                || mimeType.startsWith(PictureMimeType.MIME_TYPE_PREFIX_AUDIO)
                                || mimeType.startsWith(PictureMimeType.MIME_TYPE_PREFIX_IMAGE) ? PictureMimeType.MIME_TYPE_VIDEO : mimeType);
                        if (SdkVersionUtils.isQ()) {
                            contentValues.put(MediaStore.Video.Media.DATE_TAKEN, time);
                            contentValues.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_MOVIES);
                        } else {
                            File dir = TextUtils.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)
                                    ? Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
                                    : context.getExternalFilesDir(Environment.DIRECTORY_MOVIES);
                            contentValues.put(MediaStore.MediaColumns.DATA, dir.getAbsolutePath() + File.separator
                                    + DateUtils.getCreateFileName("VID_") + PictureMimeType.MP4);
                        }
                        uri = context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);
                    } else { // 如果是圖片
                        contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, DateUtils.getCreateFileName("IMG_"));
                        contentValues.put(MediaStore.Images.Media.MIME_TYPE, TextUtils.isEmpty(mimeType)
                                || mimeType.startsWith(PictureMimeType.MIME_TYPE_PREFIX_AUDIO)
                                || mimeType.startsWith(PictureMimeType.MIME_TYPE_PREFIX_VIDEO) ? PictureMimeType.MIME_TYPE_IMAGE : mimeType);
                        if (SdkVersionUtils.isQ()) {
                            contentValues.put(MediaStore.Images.Media.DATE_TAKEN, time);
                            contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, PictureMimeType.DCIM);
                        } else {
                            if (PictureMimeType.isHasGif(mimeType) || PictureMimeType.isUrlHasGif(path)) {
                                File dir = TextUtils.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)
                                        ? Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
                                        : context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
                                contentValues.put(MediaStore.MediaColumns.DATA, dir.getAbsolutePath() + File.separator
                                        + DateUtils.getCreateFileName("IMG_") + PictureMimeType.GIF);
                            }
                        }
                        //插入到圖庫(kù)相冊(cè)
                        uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
                    }
                    if (uri != null) {
                        InputStream inputStream;
                        if (PictureMimeType.isHasHttp(path)) {
                            inputStream = new URL(path).openStream();
                        } else {
                            if (PictureMimeType.isContent(path)) {
                                inputStream = PictureContentResolver.getContentResolverOpenInputStream(context, Uri.parse(path));
                            } else {
                                inputStream = new FileInputStream(path);
                            }
                        }
                        OutputStream outputStream = PictureContentResolver.getContentResolverOpenOutputStream(context, uri);
                        boolean bufferCopy = PictureFileUtils.writeFileFromIS(inputStream, outputStream);
                        if (bufferCopy) {
                            return PictureFileUtils.getPath(context, uri);
                        }
                    }
                } catch (Exception e) {
                    Log.d("saveLocalFile", "Exception - doInBackground: " + e.getMessage());
                    PictureThreadUtils.cancel(this);
                    if (listener != null) {
                        listener.onCall("");
                    }
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            public void onSuccess(String result) {
                PictureThreadUtils.cancel(this);
                ModifyExif.setExif(context,result);

                if (listener != null) {
                    listener.onCall(result);
                }
            }

            @Override
            public void onCancel() {
                Log.d("saveLocalFile", "onCancel: " + "");
                PictureThreadUtils.cancel(this);
                if (listener != null) {
                    listener.onCall("");
                }
            }

            @Override
            public void onFail(Throwable t) {
                Log.d("saveLocalFile", "onFail: " + t.getMessage());
//                PictureThreadUtils.cancel(this);
//                if (listener != null) {
//                    listener.onCall("");
//                }
            }
        });

    }

2、坑:解決圖片插入到圖庫(kù)時(shí)間不對(duì)的bug,系統(tǒng)自帶的相冊(cè)圖庫(kù)會(huì)根據(jù)圖片攜帶的時(shí)間信息進(jìn)行時(shí)間順序排列,可以通過(guò)代碼修改圖片的創(chuàng)建時(shí)間來(lái)修改圖片原始的創(chuàng)建時(shí)間

導(dǎo)入exifinterface框架,需要先申請(qǐng)存儲(chǔ)權(quán)限

 implementation 'androidx.exifinterface:exifinterface:1.3.0'
   //設(shè)置exif
    public static void setExif(Context context,String filepath) {
        boolean granted = XXPermissions.isGranted(context, Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE);
        if (!granted){
            return;
        }
        LogUtils.d("ModifyExif","需要修改的圖片的路徑是:" + filepath);
        SimpleDateFormat lastModifiedDate = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss", Locale.CHINA);

        try {
            exif = new ExifInterface(filepath);     //根據(jù)圖片的路徑獲取圖片的Exif
        } catch (IOException ex) {
            Log.e("Mine", "cannot read exif", ex);
        }
        exif.setAttribute(ExifInterface.TAG_DATETIME, lastModifiedDate.format(System.currentTimeMillis()));              //把時(shí)間寫(xiě)進(jìn)exif
        try {
            exif.saveAttributes();         //最后保存起來(lái)
        } catch (IOException e) {
            Log.e("Mine", "cannot save exif", e);
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容