Mehedi Hassan Piash [Sr. Software Engineer]

July 28, 2021

Image picker and convert uri to file

July 28, 2021 Posted by Piash , No comments

 1. Fetch uri with https://github.com/Dhaval2404/ImagePicker

 ImagePicker.with(this)  
     .compress(1024)     //Final image size will be less than 1 MB(Optional)  
     .maxResultSize(1080, 1080) //Final image resolution will be less than 1080 x 1080(Optional)  
     .createIntent { intent ->  
       startForProfileImageResult.launch(intent)  
     }  
 private val startForProfileImageResult =  
   registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->  
     val resultCode = result.resultCode  
     val data = result.data  
     if (resultCode == Activity.RESULT_OK) {  
       //Image Uri will not be null for RESULT_OK  
       val fileUri = data?.data!!  
       mProfileUri = fileUri  
       imgProfile.setImageURI(fileUri)  
     } else if (resultCode == ImagePicker.RESULT_ERROR) {  
       Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()  
     } else {  
       Toast.makeText(this, "Task Cancelled", Toast.LENGTH_SHORT).show()  
     }  
   }  

 2. Convert Uri to file using the following function 

  private fun fileFromContentUri(context: Context, contentUri: Uri): File {  
     // Preparing Temp file name  
     val fileExtension = getFileExtension(context, contentUri)  
     val fileName = "temp_file" + if (fileExtension != null) ".$fileExtension" else ""  
     // Creating Temp file  
     val tempFile = File(context.cacheDir, fileName)  
     tempFile.createNewFile()  
     try {  
       val oStream = FileOutputStream(tempFile)  
       val inputStream = context.contentResolver.openInputStream(contentUri)  
       inputStream?.let {  
         copy(inputStream, oStream)  
       }  
       oStream.flush()  
     } catch (e: Exception) {  
       e.printStackTrace()  
     }  
     return tempFile  
   }  
 private fun getFileExtension(context: Context, uri: Uri): String? {  
     val fileType: String? = context.contentResolver.getType(uri)  
     return MimeTypeMap.getSingleton().getExtensionFromMimeType(fileType)  
   }  
  @Throws(IOException::class)  
   private fun copy(source: InputStream, target: OutputStream) {  
     val buf = ByteArray(8192)  
     var length: Int  
     while (source.read(buf).also { length = it } > 0) {  
       target.write(buf, 0, length)  
     }  
   }  

July 19, 2021

onActivity result for fragment navigation component

July 19, 2021 Posted by Piash , No comments

 1. Get result after navigationUp in the previous fragment 

setFragmentResultListener("requestKey") { requestKey, bundle ->  
       // We use a String here, but any type that can be put in a Bundle is supported  
       val result = bundle.getParcelable<Address>("bundleKey")  
       Toast.makeText(context, "$result", Toast.LENGTH_SHORT).show()  
     }  

 1. Set data for getting results in the previous fragment 

  val data = arguments?.getParcelable<Address>(AppConstants.DataTask.DATA)  
     Timber.e("data : $data")  
     binding.detail.setOnClickListener {  
       errorLog("detailFragment")  
       setFragmentResult("requestKey", bundleOf("bundleKey" to Address("Dhaka", "1205")))  
       it?.findNavController()?.navigateUp()  
     }  

OnActivityResult method is deprecated, what is the alternative?

July 19, 2021 Posted by Piash , No comments

 1. Call another activity with contract api

  resultContract.launch(requireContext().openActivityResult<DetailActivity>())  

2. Call an activity for the result 

  private val resultContract =  
     registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {  
       if (it.resultCode == Activity.RESULT_OK) {  
         // get the result here   
       }  
     }  

4. Get back to previous activity with result 

  val data = intent.getParcelableExtra<Address>(AppConstants.DataTask.ADDRESS)  
     Timber.e("address : $data")  
     bind.result.setOnClickListener {  
       setResult(Activity.RESULT_OK, data)  
       finish()  
     }  

3.Utils for openActivity with intent:

 // this extension function is for resultContract  
 inline fun <reified T : Activity> Context.openActivityResult(vararg params: Pair<String, Any>): Intent {  
   val intent = Intent(this, T::class.java)  
   return intent.putExtras(*params)  
 }  
 fun Intent.putExtras(vararg params: Pair<String, Any>): Intent {  
   if (params.isEmpty()) return this  
   params.forEach { (key, value) ->  
     when (value) {  
       is Int -> putExtra(key, value)  
       is Byte -> putExtra(key, value)  
       is Char -> putExtra(key, value)  
       is Long -> putExtra(key, value)  
       is Float -> putExtra(key, value)  
       is Short -> putExtra(key, value)  
       is Double -> putExtra(key, value)  
       is Boolean -> putExtra(key, value)  
       is Bundle -> putExtra(key, value)  
       is String -> putExtra(key, value)  
       is IntArray -> putExtra(key, value)  
       is ByteArray -> putExtra(key, value)  
       is CharArray -> putExtra(key, value)  
       is LongArray -> putExtra(key, value)  
       is FloatArray -> putExtra(key, value)  
       is Parcelable -> putExtra(key, value)  
       is ShortArray -> putExtra(key, value)  
       is DoubleArray -> putExtra(key, value)  
       is BooleanArray -> putExtra(key, value)  
       is CharSequence -> putExtra(key, value)  
       is Array<*> -> {  
         when {  
           value.isArrayOf<String>() ->  
             putExtra(key, value as Array<String?>)  
           value.isArrayOf<Parcelable>() ->  
             putExtra(key, value as Array<Parcelable?>)  
           value.isArrayOf<CharSequence>() ->  
             putExtra(key, value as Array<CharSequence?>)  
           else -> putExtra(key, value)  
         }  
       }  
       is Serializable -> putExtra(key, value)  
     }  
   }  
   return this  
 }  

July 11, 2021

Json extension for kotlin

July 11, 2021 Posted by Piash , No comments
 // Transform simple object to String with Gson  
  fun <reified T : Any> T.toPrettyJson() : String = Gson().toJson(this, T::class.java)  
   
 // Transform String Json to Object   
 inline fun <reified T : Any> String.fromPrettyJson() : T = Gson().fromJson(this , T::class.java)  
   
 // Transform String List Json to Object   
 inline fun <reified T : Any> String.fromPrettyJsonList() : MutableList <T> = when( this.isNotEmpty()){  
     true -> Gson().fromJson(this, object : TypeToken<MutableList<T>>() {}.type)  
     false -> mutableListOf()  
 }  

July 08, 2021

Click again to exit the app in navigation component [kotlin]

July 08, 2021 Posted by Piash , No comments
 class MainActivity : BaseActivity() {  
   private lateinit var navController: NavController  
   private lateinit var navHostFragment: NavHostFragment  
   private var doubleBackToExitPressedOnce = false
 override fun onCreate(savedInstanceState: Bundle?) {  
     super.onCreate(savedInstanceState)  
     binding = ActivityMainBinding.inflate(layoutInflater)  
     setContentView(binding.root)  
  navHostFragment =  
       supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment  
     navController = navHostFragment.navController  
   }  
 override fun onBackPressed() {  
     if (navHostFragment.childFragmentManager.backStackEntryCount > 0) {  
       super.onBackPressed()  
     } else {  
       if (doubleBackToExitPressedOnce) {  
         finish()  
         return  
       }  
       this.doubleBackToExitPressedOnce = true  
       showToast("Click again to Exit")  
       Handler().postDelayed(  
         { doubleBackToExitPressedOnce = false },  
         2000  
       )  
     }  
   }  
 }  

July 07, 2021

Prevent or avoid Multiple clicks in Android app [Kotlin]

July 07, 2021 Posted by Piash , No comments

 Step 1 : Create class with name SafeClickListener.kt

 class SafeClickListener(  
 private var defaultInterval: Int = 1000,  
 private val onSafeCLick: (View) -> Unit  
  ) : View.OnClickListener {  
 private var lastTimeClicked: Long = 0  
 override fun onClick(v: View) {  
   if (SystemClock.elapsedRealtime() - lastTimeClicked < defaultInterval) {  
     return  
   }  
   lastTimeClicked = SystemClock.elapsedRealtime()  
   onSafeCLick(v)  
    }   
  }  

 Step 2 : Add extension function to make it works with any view, this will create a new SafeClickListener and delegate the work to it.

   fun View.setSafeOnClickListener(onSafeClick: (View) -> Unit) {  
   val safeClickListener = SafeClickListener {  
     onSafeClick(it)  
    }  
   setOnClickListener(safeClickListener)  
  }  

 Step 3 : Now it is very easy to use it. Just replace button1.setonclicklistner with setSafeOnClickListener.

 settingsButton.setSafeOnClickListener {  
   showSettingsScreen()  
 }