6

I am new to Android Studio and especially to Kotlin. I need to load image from internet and then save it to phone. I tried to load image with Glide as Bitmap and then save it. But it doesn't work. This code is best thing i found but it doesn't work.

try {
var bitmap = Glide.with(this)
        .asBitmap()
        .load("https://s3.amazonaws.com/appsdeveloperblog/Micky.jpg")
        .apply(RequestOptions().override(100).downsample(DownsampleStrategy.CENTER_INSIDE).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE))
        .submit().get()
    val wrapper = ContextWrapper(applicationContext)
    var file = wrapper.getDir("Images", Context.MODE_PRIVATE)
    file = File(file, "img.jpg")
    val out = FileOutputStream(file)
    bitmap.compress(Bitmap.CompressFormat.JPEG, 85, out)
    out.flush()
    out.close()
}
catch (e: Exception) {
    println(e)
}

How I understood problem is in this ".submit().get()" part of Glide. But if I take it away then compress doesn't work.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Seiggailion
  • 162
  • 2
  • 2
  • 12

2 Answers2

6

submit(): Returns a future that can be used to do a blocking get on a background thread.

get(): Waits if necessary for the computation to complete, and then retrieves its result.

In your case to download an image from a url and save it to internal storage, you should use a background thread to do that. If you calling on main thread, your app might be throws ANR dialog.

Here I will demo how to download and save the image by using AsyncTask API

First write a class to download and save the image.

class DownloadAndSaveImageTask(context: Context) : AsyncTask<String, Unit, Unit>() {
    private var mContext: WeakReference<Context> = WeakReference(context)

    override fun doInBackground(vararg params: String?) {
        val url = params[0]
        val requestOptions = RequestOptions().override(100)
            .downsample(DownsampleStrategy.CENTER_INSIDE)
            .skipMemoryCache(true)
            .diskCacheStrategy(DiskCacheStrategy.NONE)

        mContext.get()?.let {
            val bitmap = Glide.with(it)
                .asBitmap()
                .load(url)
                .apply(requestOptions)
                .submit()
                .get()

            try {
                var file = it.getDir("Images", Context.MODE_PRIVATE)
                file = File(file, "img.jpg")
                val out = FileOutputStream(file)
                bitmap.compress(Bitmap.CompressFormat.JPEG, 85, out)
                out.flush()
                out.close()
                Log.i("Seiggailion", "Image saved.")
            } catch (e: Exception) {
                Log.i("Seiggailion", "Failed to save image.")
            }
        }
    }
}

Then in activity just call

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        DownloadAndSaveImageTask(this).execute("https://s3.amazonaws.com/appsdeveloperblog/Micky.jpg")
    }
}

If you want to save to internal storage

var file = File(it.filesDir, "Images")
if (!file.exists()) {
    file.mkdir()
}
file = File(file, "img.jpg")

It will save the image in path data/data/yourapppackagename/files/Images/img.jpg

Son Truong
  • 13,661
  • 5
  • 32
  • 58
  • I tried your code and it tells that image is saved but I cannot find it anywhere. Could you help me to undestand what is wrong now? – Seiggailion Nov 04 '18 at 19:00
  • Because you saving the image in phone's internal storage so to find the saved image you must run the app on emulator or rooted phone. Another way is saving the image on phone's external storage. In that case you can find the image by using File Explorer apps. – Son Truong Nov 04 '18 at 23:37
  • I use command to get absolute path and it's "/data/user/0/fi.jamk.k8760.stack_harkka/app_Recent/img.jpg". I just thought that when I use this command `var file = it.getDir("Images", Context.MODE_PRIVATE)` file will be saved to folder "Images". So it means that I undestood wrong and I still have to somehow define directory? – Seiggailion Nov 05 '18 at 00:14
  • So you found the saved image but now you wonder how to save the image into a defined folder such as `Images` instead of `app_Recent`. – Son Truong Nov 05 '18 at 01:09
  • I just noticed that you added about saving to images. I tried it but maybe I explained bad way, I want that image to be seen in gallery. I run this code on emulator and i if I go to files I can't even find that picture anywhere. Is there some way to make that image to appear in gallery? I tried `var file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)` and `var file = File(Environment.DIRECTORY_DCIM)` but then it tells that failed to save. – Seiggailion Nov 05 '18 at 21:24
  • You must declare and enable write to external storage permission before saving the images. – Son Truong Nov 06 '18 at 03:18
  • 1
    my app didn't have permission to access storage. Now it works. Thank you, you saved my life! – Seiggailion Nov 06 '18 at 11:24
  • AsyncTask? DO NOT DO THIS! – Slobodan Antonijević Aug 25 '20 at 14:25
  • Ho do you save the image without Compressing it using this class – Zef Jul 26 '21 at 16:23
1

Just use this method

    fun DownloadImageFromPath(path: String?) {
    var `in`: InputStream? = null
    var bmp: Bitmap? = null
    val iv = findViewById<View>(R.id.imagFullImage) as ImageView
    var responseCode = -1
    try {
        val url = URL(path) //"http://192.xx.xx.xx/mypath/img1.jpg
        val con: HttpURLConnection = url.openConnection() as HttpURLConnection
        con.setDoInput(true)
        con.connect()
        responseCode = con.getResponseCode()
        if (responseCode == HttpURLConnection.HTTP_OK) {
            //download
            `in` = con.getInputStream()
            bmp = BitmapFactory.decodeStream(`in`)
            `in`.close()
            iv.setImageBitmap(bmp)
        }
    } catch (ex: Exception) {
        Log.e("Exception", ex.toString())
    }
}
Jewel Rana
  • 2,397
  • 1
  • 19
  • 28