Kotlin Store Download Image Bitmap Into External Storage Example

In this example, I will show you how to download image using url retrofit and display into imageview and store download image bitmap into external storage. 

Kotlin Store Download Image Bitmap Into External Storage Example Video

  • You can also go through this video explanation.

Kotlin Store Download Image Bitmap Into External Storage Example

Creating a New Project

  • So first create a new Android Studio project using Kotlin.
  • Once the project is loaded come inside the activity_main.xml and remove the Hello World TextView.
Android studio project screen

Step 1:
Open build.gradle and add following dependency and rebuild the project.
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
Step 2:
Open AndroidManifest.xml and add Internet Permission.
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Step 3:
Create new Class:- ManagePermissions.kt
Add following code into ManagePermissions.kt
package com.kotlinkatta.imgdowretrofit

import android.app.Activity
import android.app.AlertDialog
import android.content.pm.PackageManager
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat


class ManagePermissions(val activity: Activity,val list: List<String>,val code:Int) {

// Check permissions at runtime
fun checkPermissions() {
if (isPermissionsGranted() != PackageManager.PERMISSION_GRANTED) {
showAlert()
} else {
Toast.makeText(activity, "Permissions already granted.", Toast.LENGTH_SHORT).show()
}
}

// Check permissions status
private fun isPermissionsGranted(): Int {
// PERMISSION_GRANTED : Constant Value: 0
// PERMISSION_DENIED : Constant Value: -1
var counter = 0;
for (permission in list) {
counter += ContextCompat.checkSelfPermission(activity, permission)
}
return counter
}

// Find the first denied permission
private fun deniedPermission(): String {
for (permission in list) {
if (ContextCompat.checkSelfPermission(activity, permission)
== PackageManager.PERMISSION_DENIED) return permission
}
return ""
}

// Show alert dialog to request permissions
private fun showAlert() {
val builder = AlertDialog.Builder(activity)
builder.setTitle("Need permission")
builder.setMessage("All permissions are required.")
builder.setPositiveButton("OK", { dialog, which -> requestPermissions() })
builder.setNeutralButton("Cancel", null)
val dialog = builder.create()
dialog.show()
}

// Request the permissions at run time
private fun requestPermissions() {
val permission = deniedPermission()
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
// Show an explanation asynchronously
Toast.makeText(activity, "Should show an explanation.", Toast.LENGTH_SHORT).show()
} else {
ActivityCompat.requestPermissions(activity, list.toTypedArray(), code)
}
}

// Process permissions result
fun processPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray): Boolean {
var result = 0
if (grantResults.isNotEmpty()) {
for (item in grantResults) {
result += item
}
}
if (result == PackageManager.PERMISSION_GRANTED) return true
return false
}
}
Step 4:
Create new Class:- RetrofitClient.kt
Add following code into RetrofitClient.kt
package com.kotlinkatta.imgdowretrofit

import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit

object RetrofitClient {
var BASE_URL:String="https://wallpapersite.com"
val getClient: DataService
get() {

val interceptor = HttpLoggingInterceptor()
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)

val client = OkHttpClient.Builder().addInterceptor(interceptor).build()

val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.build()

return retrofit.create(DataService::class.java)
}
}
Step 5:
Create new Interface Class:- DataService.kt
Add following code into DataService.kt
package com.kotlinkatta.imgdowretrofit

import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Url

public interface DataService {
@GET
fun downloadFileUsingUrl(@Url fileUrl: String): Call<ResponseBody>
}
Step 6:
Create new Class:- SaveImageBitmap.kt
Add following code into SaveImageBitmap.kt
package com.kotlinkatta.imgdowretrofit

import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import java.io.File
import java.io.FileOutputStream

public class SaveImageBitmap {

public fun SaveImage(context: Context,imageBitmap: Bitmap, imagename: String): Uri {
val root = context.getExternalFilesDir(null).toString()
val myDir = File(root+ "/Images/")
myDir.mkdirs()
val fname = "" + imagename
val file = File(myDir, fname)
if (file.exists()) file.delete()
try {
val out = FileOutputStream(file)
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)
out.flush()
out.close()
} catch (e: Exception) {
e.printStackTrace()
}
return Uri.parse(file.absolutePath)
}
}
Step 7:
activity_main.xml
Add following code into activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">

<Button
android:id="@+id/btn_down_image"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Click To Downlaod Image"
android:layout_gravity="center_horizontal"
android:layout_margin="10dp" />

<ImageView
android:id="@+id/img_disp_down_img"
android:layout_width="match_parent"
android:layout_height="180dp" />

<TextView
android:id="@+id/txt_img_stor_path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#000000"
android:gravity="left"
android:textSize="18dp"
android:text="Display Storage Image File Path"
android:layout_margin="10dp" />

<ImageView
android:id="@+id/img_disp_save_img"
android:layout_width="match_parent"
android:layout_height="180dp" />

</LinearLayout>
Step 8:
MainActivity.kt
Add following code into MainActivity.kt
package com.kotlinkatta.imgdowretrofit

import android.Manifest
import android.app.ProgressDialog
import android.content.Context
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class MainActivity : AppCompatActivity() {

private val PermissionsRequestCode = 123
private lateinit var managePermissions: ManagePermissions

lateinit var img_disp_down_img: ImageView
lateinit var btn_down_image: Button
lateinit var txt_img_stor_path: TextView
lateinit var img_disp_save_img: ImageView

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

// Initialize a list of required permissions to request runtime
val permission_list = listOf<String>(
Manifest.permission.INTERNET,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)

// Initialize a new instance of ManagePermissions class
managePermissions = ManagePermissions(this, permission_list, PermissionsRequestCode)
//Check Permissions are denied or not
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
managePermissions.checkPermissions()
}

img_disp_down_img = findViewById<ImageView>(R.id.img_disp_down_img)
btn_down_image = findViewById<Button>(R.id.btn_down_image)
txt_img_stor_path = findViewById<TextView>(R.id.txt_img_stor_path)
img_disp_save_img = findViewById<ImageView>(R.id.img_disp_save_img)

btn_down_image.setOnClickListener {
//Download Image
funDownloadImage()
}
}

private fun funDownloadImage() {
@Suppress("DEPRECATION")
val progressDialog = ProgressDialog(this@MainActivity)
progressDialog.setTitle("Image is downloading, please wait")
progressDialog.show()

val call: Call<ResponseBody> = RetrofitClient.getClient.downloadFileUsingUrl("/images/pages/pic_w/6408.jpg")
call.enqueue(object : Callback<ResponseBody> {

override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
val bytes: ByteArray = response.body()!!.bytes()
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
img_disp_down_img.setImageBitmap(bitmap)

// Save image bitmap into storage
val uri: Uri= SaveImageBitmap().SaveImage(applicationContext,bitmap, "download_image.jpg")
txt_img_stor_path.setText(""+uri)
// set storage image to imageview using file storage path
img_disp_save_img.setImageURI(uri)
progressDialog.dismiss()
}

override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
progressDialog.dismiss()
}
})
}

// Receive the permissions request result
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
PermissionsRequestCode -> {
val isPermissionsGranted = managePermissions.processPermissionsResult(requestCode, permissions, grantResults)
if (isPermissionsGranted) {
// Do the task now
toast("Permissions granted.")
} else {
toast("Permissions denied.")
}
return
}
}
}

// Extension function to show toast message
fun Context.toast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
Output:

Comments