I have questions about loading images from url. How to async load image in Jetpack Compose? I know coin library and use it is pretty simple and works great. But libraries like coil, glide, picasso are prohibited, only Android SDK and Google supported are allowed.
Thank you for your advices
Something like this? But how to display in Jetpack Compose UI?
#Composable
fun LoadImage(url: String, #DrawableRes placeHolderImage: Int): MutableState<Bitmap?> {
var bitmapState: MutableState<Bitmap?> = mutableStateOf(null)
//show place holder image
val defaultBitmap =
BitmapFactory.decodeResource(LocalContext.current.resources, placeHolderImage)
bitmapState.value = defaultBitmap
GlobalScope.launch(Dispatchers.IO) {
val urlConnection = URL(url).openConnection() as HttpURLConnection
try {
urlConnection.doInput = true
urlConnection.connect()
val input = BufferedInputStream(urlConnection.inputStream)
val bitmap = BitmapFactory.decodeStream(input)
withContext(Dispatchers.Main) {
bitmapState.value = bitmap
}
} catch (e: Exception) {
} finally {
urlConnection.disconnect()
}
}
return bitmapState
}
Related
GoogleMap composes support maker icons but does not help get from Url, I hope some coding helps customer properties Icons image easy more. But If you have a solution good more, please comment here
Code in GoogleMap compose
val bitmapState = remember {
mutableStateOf<BitmapDescriptor?>(null)
}
LaunchedEffect(key1 = locationFocus.value.imageUrl) {
getBitmapFromURL(locationFocus.value.imageUrl)?.let { bm ->
getResizedBitmap(bm, 150, 150)?.let {
getRoundedCornerBitmap(it)?.let {
bitmapState.value =
BitmapDescriptorFactory.fromBitmap(it)
}
}
}
}
Marker(
state = MarkerState(position = cameraPositionState.position.target),
title = locationFocus.value.name,
snippet = locationFocus.value.address,
icon = bitmapState.value,
)
}
//Get Bitmap from Url
suspend fun getBitmapFromURL(imgUrl: String?): Bitmap? =
withContext(Dispatchers.IO) {
try {
val url = URL(imgUrl)
val connection: HttpURLConnection =
url.openConnection() as HttpURLConnection
connection.doInput = true
connection.connect()
val input: InputStream = connection.inputStream
BitmapFactory.decodeStream(input)
} catch (e: IOException) {
// Log exception
null
}
}
//Resize Image Bitmap
fun getResizedBitmap(bm: Bitmap, newWidth: Int, newHeight: Int): Bitmap? {
...
bm.recycle()
return resizedBitmap
}
//Border Bitmap
fun getRoundedCornerBitmap(bitmap: Bitmap): Bitmap? {
...
return output
}
If you have another code simple please comment. Good job
Image result marker icon google map compose.
I have created an app with QR code scanner, however I can't scan a QR code with a logo using it, any solution for this?
This is the code of my QR code scanner app:
class QRCode (val onQrCodeScanned: (String) -> Unit) : ImageAnalysis.Analyzer {
#RequiresApi(Build.VERSION_CODES.M)
private val supportedImageFormats = listOf(
ImageFormat.YUV_420_888 ,
ImageFormat.YUV_422_888 ,
ImageFormat.YUV_444_888)
#RequiresApi(Build.VERSION_CODES.M)
override fun analyze(image: ImageProxy) {
if (image.format in supportedImageFormats) {
val bytes = image.planes.first().buffer.toByteArray()
val source = PlanarYUVLuminanceSource(
bytes,
image.width,
image.height,
0,
0,
image.width,
image.height,
false)
val binaryBmp = BinaryBitmap(HybridBinarizer(source))
try {
val result = MultiFormatReader().apply {
setHints(
mapOf(
DecodeHintType.POSSIBLE_FORMATS to arrayListOf(
BarcodeFormat.QR_CODE
)
)
)
}.decode(binaryBmp)
onQrCodeScanned(result.text)
} catch (e: Exception) {
e.printStackTrace()
} finally {
image.close()
}
}
}
private fun ByteBuffer.toByteArray(): ByteArray {
rewind()
return ByteArray(remaining()).also {
get(it)
}
}
}
It can scan other QR codes but not QR codes with logo.
This is my QR code:
I fixed it... The problem is in-app browsers cannot process websites that are built using Javascript.
This is what my code for launching the browser looks like before and after:
Before:
#Composable
fun LoadWebUrl(url: String) {
val context = LocalContext.current
AndroidView(factory = {
WebView(context).apply {
webViewClient = WebViewClient()
loadUrl(url)
}
})
}
After:
#Composable
fun LoadWebUrl(url: String) {
val context = LocalContext.current
IntentUtils.launchBrowser(context, url)
}
So I looked for a solution on StackOverflow and read the documentation to see if I was doing something wrong, but I could find out.
I have a list of activities that I fetch from Firestore and display in a LazyColumn. Every activity has a name of an image that I have to get its link from Firebase storage. After I get the link in my variable, I expect the view (AsyncImage) to recompose as the variable is of type StateFlow, but nothing happens.
In my repository file, the code for getting actitivities and the download URL of the image works fine.
In my viewModel, I have two functions to load the activities and the download URL:
viewModel((private val dataSource: ChadHubDigitDataSource): ViewModel() {
...
var activities: LiveData<ActivityResponse>? = null
private var _uri = MutableStateFlow<Uri>(Uri.parse(""))
val uri: StateFlow<Uri>
get() = _uri
fun loadActivities() {
activities = flow {
emit(dataSource.getActivities())
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = ActivityResponse()
)
}
fun loadImage(imageName: String) {
_uri.value = dataSource.getImage(imageName)
}
Bellow is the code in my compose function:
val activities = _eventsViewModel.activities?.collectAsState()?.value?.activity
LazyColumn {
if (activities != null)
{
items(activities) { item ->
Column(
...
) {
// Loading the URL of the image
_eventsViewModel.loadImage(item.img)
Image(
...
painter = rememberAsyncImagePainter(
ImageRequest.Builder(
LocalContext.current
)
.data(
data = _eventsViewModel.uri.collectAsState().value
)
.apply(
block = fun ImageRequest.Builder.() {
crossfade(false)
placeholder(R.drawable.placeholder)
error(R.drawable.placeholder)
}
).build()
),
...
)
...
}
When the activities are displayed, it's the error image that is displayed even after the value of the variable uri changed in the viewModel.
Do you know a better way I can do such functionality or why my code is not working?
I tried your ImageRequest.Builder block of code, my Firebase Image fetching implementation stopped working, only showing the placeholder and not fetching.
ImageRequest.Builder(context)
.data(url)
.apply (
block = fun ImageRequest.Builder.() {
crossfade(false)
placeholder(R.drawable.placeholder)
error(R.drawable.placeholder)
}
)
.build()
Can you try doing it this way?
ImageRequest.Builder(context)
.data(url)
.crossfade(false)
.placeholder(R.drawable.placeholder)
.error(R.drawable.placeholder)
.build()
I'm trying to create an image crop functionality using CropImageView from ArthurHub's Library and I have a string URL like https://mywebsite.com/library/folder/KeYO8Ff31l178kO.png. Is possible to parse this link to URI or Bitmap so I can use setImageUriAsync or setImageBitmap to set the image? I'm using Kotlin. Thanks
LATER EDIT:
I found the solution, I'm not sure if it's the best but maybe will be useful:
I created this inner class and inside it I parsed the url to bitmap and in OnPostExecute method I set the resource for cropImageView.
Code:
internal class GetBitmapFromUrlAsync(private val cropImageView: CropImageView) : AsyncTask<String, Void?, Bitmap>() {
override fun doInBackground(vararg src: String): Bitmap? {
val url = URL(src[0])
val bitmap: Bitmap
try {
val connection = url.openConnection() as HttpsURLConnection
connection.doInput = true
connection.connect()
val input: InputStream = connection.inputStream
bitmap = BitmapFactory.decodeStream(input)
} catch (e: Exception) {
e.printStackTrace()
return null
}
return bitmap
}
override fun onPostExecute(bitmap: Bitmap?) {
cropImageView.setImageBitmap(bitmap)
}
}
How to get a list of all bitmaps from webp animation using android fresco?
The code below is always returns null instead of a bitmap
val imageRequest = ImageRequestBuilder
.newBuilderWithSource(Uri.parse("https://upload.wikimedia.org/wikipedia/commons/4/41/Sunflower_from_Silesia2.jpg"))
.build()
val imagePipeline = Fresco.getImagePipeline()
val dataSource = imagePipeline.fetchDecodedImage(imageRequest, this)
dataSource.subscribe(object : BaseBitmapDataSubscriber() {
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>?) {
val m = dataSource
}
override fun onNewResultImpl(bitmap: Bitmap?) {
val m = bitmap
}
}, CallerThreadExecutor.getInstance())
For all interested, fresco docs has this line "This subscriber doesn’t work for animated images as those can not be represented as a single bitmap."