使用 Glide 将图片保存到存储设备

31
我正在尝试为我的应用程序添加一个“下载”功能。我正在使用Glide库从URL加载图片。使用下面的代码,我可以将图片保存到设备存储器中,但它的效果并不如我预期的那样好。

我正在尝试为我的应用程序添加一个下载功能。我正在使用Glide库从它们的URL加载图片。使用下面的代码,我可以将图片保存到设备存储器中,但效果不如我预期。

                    new AsyncTask<FutureTarget<Bitmap>, Void, Bitmap>() {
                        @Override protected Bitmap doInBackground(FutureTarget<Bitmap>... params) {
                            try {
                                return params[0].get();
                            } catch (Exception ex) {
                                return null;
                            }
                        }
                        @Override protected void onPostExecute(Bitmap bitmap) {
                            if(bitmap == null) return;
                            MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "Art_"+System.currentTimeMillis());
                        }
                    }.execute(Glide.with(getApplicationContext()).load(url).asBitmap().diskCacheStrategy(DiskCacheStrategy.SOURCE).into(width, height));

有人能帮我解决这个问题吗?

4个回答

53

更新

1.清单文件中的权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

需要使用协程来执行一些后台工作。
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
  1. 使用Glide将图像转换为位图
CoroutineScope(Dispatchers.IO).launch {
    saveImage(Glide.with(this@MainActivity)
        .asBitmap()
        .load("https://i.imgur.com/4HFRb2z.jpg") // sample image
        .placeholder(android.R.drawable.progress_indeterminate_horizontal) // need placeholder to avoid issue like glide annotations
        .error(android.R.drawable.stat_notify_error) // need error to avoid issue like glide annotations
        .submit()
        .get())
}
  1. 将图像保存在新创建的具有特定名称的文件夹中
private fun saveImage(image: Bitmap): String? {
        var savedImagePath: String? = null
        val imageFileName = "JPEG_" + "FILE_NAME" + ".jpg"
        val storageDir = File(
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
                .toString() + "/YOUR_FOLDER_NAME"
        )
        var success = true
        if (!storageDir.exists()) {
            success = storageDir.mkdirs()
        }
        if (success) {
            val imageFile = File(storageDir, imageFileName)
            savedImagePath = imageFile.getAbsolutePath()
            try {
                val fOut: OutputStream = FileOutputStream(imageFile)
                image.compress(Bitmap.CompressFormat.JPEG, 100, fOut)
                fOut.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }

            // Add the image to the system gallery
            galleryAddPic(savedImagePath)
            //Toast.makeText(this, "IMAGE SAVED", Toast.LENGTH_LONG).show() // to make this working, need to manage coroutine, as this execution is something off the main thread
        }
        return savedImagePath
    }
  1. 将图片添加到图库并发送广播(不多提及,因为这已经是毋庸置疑的事情)
 private fun galleryAddPic(imagePath: String?) {
        imagePath?.let { path ->
            val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
            val f = File(path)
            val contentUri: Uri = Uri.fromFile(f)
            mediaScanIntent.data = contentUri
            sendBroadcast(mediaScanIntent)   
        }
    }

翻译

1.清单文件中的权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2. 使用 Glide 下载图片并转换为位图

Glide.with(mContext)
         .load("YOUR_URL")
         .asBitmap()
         .into(new SimpleTarget<Bitmap>(100,100) {
             @Override
             public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation)  {
                   saveImage(resource);
             }
         });
  1. 将位图保存到内存中
    private String saveImage(Bitmap image) {
        String savedImagePath = null;
        
        String imageFileName = "JPEG_" + "FILE_NAME" + ".jpg";
        File storageDir = new File(            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
                           + "/YOUR_FOLDER_NAME");
        boolean success = true;
        if (!storageDir.exists()) {
        success = storageDir.mkdirs();
        }
        if (success) {
            File imageFile = new File(storageDir, imageFileName);
            savedImagePath = imageFile.getAbsolutePath();
            try {
                OutputStream fOut = new FileOutputStream(imageFile);
                image.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
                fOut.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        
            // Add the image to the system gallery
            galleryAddPic(savedImagePath);
            Toast.makeText(mContext, "IMAGE SAVED", Toast.LENGTH_LONG).show();
        }
        return savedImagePath;
    }
   
    private void galleryAddPic(String imagePath) {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File f = new File(imagePath);
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        sendBroadcast(mediaScanIntent);
    }

Glide 的默认位图格式是 RGB_565。请查看此链接:https://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en - Akshay Nandwana
2
那么如何检索图像? - Mahdi
onResourceReady 没有被调用 :( - Jesus Almaral - Hackaprende
1
图像质量非常差。 - Magudesh
这个会不会被加载到内存中? - TheRealChx101

7
基于Akshay Nandwana的答案,我使用了以下代码来写入内部存储器:
Glide.with(context)
     .asBitmap()
     .load(url)
     .into(new SimpleTarget<Bitmap>() {
         @Override
         public void onResourceReady(Bitmap resource,Transition<? super Bitmap> transition) {
            write(fileName, resource);
         }
     });

这里是 write 方法:

public void write(String fileName, Bitmap bitmap) {
    FileOutputStream outputStream;
    try {
        outputStream = context.openFileOutput(fileName, Context.MODE_PRIVATE);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
        outputStream.close();
    } catch (Exception error) {
        error.printStackTrace();
    }
}

3

SimpleTarget<Bitmap>已被弃用,请使用CustomTarget<Bitmap>,您的Glide请求现在变成了

kotlin

Glide.with(context)
    .asBitmap()
    .load(url)
    .into(object: CustomTarget<Bitmap>() {
        override fun onLoadCleared(placeholder: Drawable?) {
            
        }

        override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {

        }
    })

Java

    Glide.with(context)
            .asBitmap()
            .load(url)
            .into(new CustomTarget<Bitmap>() {

                @Override
                public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                    
                }

                @Override
                public void onLoadCleared(@Nullable Drawable placeholder) {

                }
            });

0

我使用了以下代码,它对我很有帮助,希望也能帮到其他人

  val bitmap: Bitmap = binding.imvbg.drawable.toBitmap()//bitmapDrawable.bitmap
        saveImage(bitmap)
    
   private fun saveImage(bitmap: Bitmap){
    binding.progressBar.visibility = View.VISIBLE
    val imageFileName = "SMILE_" + Random.nextInt()
    val savedImageURL: String = MediaStore.Images.Media.insertImage(
        requireContext().contentResolver,
        bitmap,
        imageFileName,
        "Promo Image"
    )
    Handler().postDelayed({
        binding.progressBar.visibility = View.GONE
        Toast.makeText(requireContext(),"Image Downloaded",Toast.LENGTH_LONG).show()
    },1000*5)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接