How to leverage Glide cache for loading notification icons? Those are IconCompat used in the Person object in the MessagingStyle notifications and Shortcuts. Also, Bubbles require using both of those.
I used Glid as fallowing:
private IconCompat loadIcon(String url) throws ExecutionException, InterruptedException {
RequestOptions requestOptions = new RequestOptions().override(ADAPTIVE_BITMAP_SIZE);
Bitmap bitmap = Glide.with(G.app).asBitmap().apply(requestOptions).load(url).submit().get();
return IconCompat.createWithAdaptiveBitmap(bitmap);
}
I got several questions about this solution
What should be the size of ADAPTIVE_BITMAP_SIZE?
When will the bitmap get recycled?
How to handle errors in loading the bitmap?
Create a custom TargetWrapper for the async loading icon.
The config your Glide using your TargetWrapper instance.
asyncLoadIcon("http://YOUR_URL.com"){
val person = Person.Builder()
.setName("John Doe")
.setIcon(it)
notificationManagerHelper.notify(
person.build()
)
}
Helper function for async loading bitmap then wrap into Icon
private fun asyncLoadIcon(avatar: String?, block: (IconCompat?) -> Unit) {
if (avatar.isNullOrEmpty())
block(null)
else {
GlideHelper.createWithAdaptiveBitmap(requireContext(), avatar) { result ->
if (result?.isSuccess() == true)
block(IconCompat.createWithAdaptiveBitmap(result.toData()))
else block(null)
}
}
}
Here is the Glide image request function with retrieving bitmap with a callback.
fun createWithAdaptiveBitmap(
context: Context,
url: String,
listener: ((Result<Bitmap>?) -> Unit)
) {
val options = RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.DATA)
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.dontTransform()
Glide.with(context)
.asBitmap()
.apply(options)
.load(url)
.into(CustomTargetWrapper(listener))
}
CustomTargetWrapper class for async loading bitmap.
class CustomTargetWrapper(
private val listener: ((Result<Bitmap>?) -> Unit)
) : CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
listener.invoke(Result.Success(resource))
}
override fun onLoadCleared(placeholder: Drawable?) {
listener.invoke(null)
}
override fun onLoadFailed(errorDrawable: Drawable?) {
super.onLoadFailed(errorDrawable)
listener.invoke(Result.Error(IOException("Glide load failed")))
}
}
Related
Im having problem with caching image with Glide.
My sample code is like this.
items.forEach { item ->
Glide.with(context)
.asBitmap()
.apply(requestOptions)
.diskCacheStrategy(DiskCacheStrategy.DATA)
.load(item.url)
.into(object : CustomTarget<Bitmap>() {
override fun onLoadCleared(placeholder: Drawable?) {
}
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?
) {
}
})
}
I want to cache the data in first for loop, and after first loop is over,
the glide should not request to remote url, should use cache.
I tested with the DiskCacheStrategy options, but it didn't work.
Anyone who can solve this problem, please help me...
One of our APIs returns bytes of a jpg file.
As I see, there are Network Libraries to download bytes,
But I just want to use Glide to download and display.
https://subdomain.example.com:81/stack/146237.jpg
Response Headers type
Content-Length : 209067
Content-Type : image/jpg
A Postman Screenshot of APIs responses
val glideUrl = GlideUrl(
"${BuildConfig.BASE_URL}/stack/146237.jpg",
LazyHeaders.Builder()
.addHeader("Auth", token)
.build()
)
Glide.with(itemView.context)
.asBitmap()
.load(glideUrl)
// .into(object : SimpleTarget<Bitmap?>() {
// override fun onResourceReady(
// resource: Bitmap,
// transition: Transition<in Bitmap?>?
// ) {
// itemView.ivContactHRProfile.setImageBitmap(resource)
// }
// })
.into(object: CustomTarget<Bitmap>(){
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?
) {
itemView.ivContactHRProfile.setImageBitmap(resource)
}
override fun onLoadCleared(placeholder: Drawable?) {
}
})
The problem is that I don't know how to implement it with Glide.
I have this piece of code, this is my first use of Glide, I still do not understand how to do it differently
try {
Glide.with(this#TestBitmapActivity)
.asBitmap()
.load("https://firebasestorage.googleapis.com/v0/b/mymodeapp-3f9a7.appspot.com/o/heroes%2Fman%2Fbg_hero.png?alt=media&token=2182a224-bb65-4f06-90d9-8e5c5d9b07d9")
.into(object : CustomTarget<Bitmap>(){
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
bg_imageview_test.setImageBitmap(resource)
Glide.with(this#TestBitmapActivity)
.asBitmap()
.load("https://firebasestorage.googleapis.com/v0/b/mymodeapp-3f9a7.appspot.com/o/heroes%2Fman%2Fhero_man.png?alt=media&token=6358e564-1fe0-41ff-bc87-0e28d3fe1c1e")
.into(object : CustomTarget<Bitmap>(){
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
val bitmap1:Bitmap = resource
Glide.with(this#TestBitmapActivity)
.asBitmap()
.load("https://firebasestorage.googleapis.com/v0/b/mymodeapp-3f9a7.appspot.com/o/heroes%2Fman%2Fhero_sword.png?alt=media&token=f3d003f8-b65f-4e69-afe3-ea9653c3a925")
.into(object : CustomTarget<Bitmap>(){
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
val bitmap2:Bitmap = resource
Glide.with(this#TestBitmapActivity)
.asBitmap()
.load("https://firebasestorage.googleapis.com/v0/b/mymodeapp-3f9a7.appspot.com/o/heroes%2Fman%2Fhero_wear.png?alt=media&token=4f88b869-347e-4bf8-842e-4a728b8d743f")
.into(object : CustomTarget<Bitmap>(){
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
val bitmap3:Bitmap = resource
val bitmapa = overlay(bitmap1,bitmap2,bitmap3)
setAva(bitmapa!!)
}
override fun onLoadCleared(placeholder: Drawable?) {
}
})
}
override fun onLoadCleared(placeholder: Drawable?) {
}
})
}
override fun onLoadCleared(placeholder: Drawable?) {
}
})}
override fun onLoadCleared(placeholder: Drawable?) {
}
})
}
catch (e: Exception) {
Log.d("Test","Erorr?")
}
and the whole problem is that these threads are nested in each other and it would be better if I used For, how to do it in Kotlin?
I suggest that you first write the code that downloads one bitmap. Then you can copy/paste the exact same code to download a different bitmap instead. Assuming that the result of downloading each bitmap is independent, you don't need to nest anything. Also, the changes you make after copy/pasting the first bitmap should give you an idea of how to turn this into a function that takes a few parameters to specify which bitmap to download.
I wanted to load image from url into bottomnavigationview's menu item icon. same like instagram we wanted to show profile image in one of our menu which might change while switching from different available profiles.
Currently, I am trying below code but it does not load image every time.
val menu = mViewDataBinding?.bnvNavigation?.menu
val menuItem = menu?.findItem(R.id.menu_profile)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
menuItem?.setIconTintList(null)
menuItem?.setIconTintMode(null)
}
Glide.with(this)
.asBitmap()
.load(profilePic)
.apply(
RequestOptions.circleCropTransform()
.placeholder(R.drawable.user_profile_icon_updated)
)
.into(object :
CustomTarget<Bitmap>(UIHelper.dpToPx(this, 24), UIHelper.dpToPx(this, 24)) {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
menuItem?.icon = BitmapDrawable(resources, resource)
}
override fun onLoadCleared(placeholder: Drawable?) {
}
})
Above code is working as expected, it just a matter of passing application context to Glide, Glide.with(App.instance)
App is my application class
val menu = mViewDataBinding?.bnvNavigation?.menu
val menuItem = menu?.findItem(R.id.menu_profile)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
menuItem?.setIconTintList(null)
menuItem?.setIconTintMode(null)
}
Glide.with(App.instance)
.asBitmap()
.load(profilePic)
.placeholder(getProfilePlaceholderFilled())
.error(getProfilePlaceholderFilled())
.apply(
RequestOptions.circleCropTransform().placeholder(getProfilePlaceholderFilled())
)
.into(object :
CustomTarget<Bitmap>(UIHelper.dpToPx(this, 80), UIHelper.dpToPx(this, 80)) {
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?
) {
menuItem?.icon = BitmapDrawable(
resources, resource
)
}
override fun onLoadFailed(errorDrawable: Drawable?) {
menuItem?.icon = errorDrawable
}
override fun onLoadCleared(placeholder: Drawable?) {
}
})
i recommended you to use chip navigation and create custom bottom navigation its very better than default android bottom navigation and more easy...
if you interest to learn you can use this tutorial https://www.youtube.com/watch?v=DQtdOSN21lQ&feature=emb_logo and the library https://github.com/ismaeldivita/chip-navigation-bar
if you have any question tag me to answer you
I am working on a side project and in notification i wanted to show some default place Holder(drawable) in ImageView.
So i tried this:
Glide.with(appContext)
.load(iconDrawable)
.into(object : CustomTarget<Drawable>() {
override fun onLoadCleared(placeholder: Drawable?) {
}
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
val resBitmap : Bitmap = Utils.drawableToBitmap(resource)
remoteViews.setImageViewBitmap(R.id.primaryIcon, resBitmap))
}
})
Above code is working perfectly but as you can notice i don't want to handle creation and conversion of Drawable to Bitmap .So i tried to use asBitmap().
Glide.with(appContext)
.asBitmap()
.load(iconDrawable)
.into(object : CustomTarget<Bitmap>() {
override fun onLoadCleared(placeholder: Drawable?) {
}
override fun onResourceReady(resource: Bitmap, transition: Transition<in Drawable>?) {
remoteViews.setImageViewBitmap(R.id.primaryIcon, resource))
}
})
I expected to work but bitmap it empty and drawable is not loading to the view.
even i tried using placeholder(),error() nothing worked
Glide.with(appContext)
.asBitmap()
.load(iconDrawable)
.placeholder(iconDrawable)
.error(iconDrawable)
.into(object : CustomTarget<Bitmap>() {
override fun onLoadCleared(placeholder: Drawable?) {
}
override fun onResourceReady(resource: Bitmap, transition: Transition<in Drawable>?) {
remoteViews.setImageViewBitmap(R.id.primaryIcon, resource))
}
})
NOTE:Above case arises even if i use NotificationTarget
// try this, ...
remoteView.setImageBitmap(R.id.yourImageView, bitmap);