why is my image not showing in recyclerview? - android

I followed a tutorial on youtube on how to retrieve images and text from Firestore and display them in the RecyclerView. I'm using the Glide library to display captured images. I bind my image using this code:
override fun onBindViewHolder(holder: itemViewHolder, position: Int) {
val produk=listOfItem[position]
holder.kategori.text=produk.productCategory
holder.berat.text=produk.productWeight.toString()
//img
Glide.with(context)
.load(produk.productIcon)
.into(holder.gambarBarang)
}
I try to use FirebaseStorage references:
val storage = FirebaseStorage.getInstance()
val gsReference = storage.getReferenceFromUrl(produk.productIcon.toString())
Glide.with(context)
.load(produk.productIcon)
.into(holder.gambarBarang)
but that seems to make the situation even worse, i get this error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.b1, PID: 8300
java.lang.IllegalArgumentException: The storage Uri could not be
parsed.
I also noticed that some of the images that I put in the imageView are not visible. Is this a result of the inserted image being too large? Anyone know how to solve it?
Edit: I try to log the produk.productIcon.toString() inside the onBindViewHolder, and get this:
D/TAG: com.google.firebase.storage.UploadTask$TaskSnapshot#7e89f3c
gggg
D/TAG: com.google.firebase.storage.UploadTask$TaskSnapshot#213e98e
gggg
D/TAG: com.google.firebase.storage.UploadTask$TaskSnapshot#df9e78f
I think the UploadTask come from the code that i use for adding the image to Firebase Storage:
val filePathAndName="product_images/"+""+timeStamp
val storageReference=FirebaseStorage.getInstance().
getReference(filePathAndName)
val uploadTask= storageReference.putFile(image_Uri!!)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
val downloadUri = task.result
val item = Item(
""+firebaseAuth.uid,
timeStamp,
kategori,
berat_sampah.toDouble(),
deskripsi,
""+downloadUri,
)
FirestoreClass().addItem(this#AddProductActivity, FirestoreClass().getCurrentUserID(),item)
ClearData()
Is this code the cause of the error?

produk.productIcon is not an URL, in fact, it is a UploadTask.TaskSnapshot which is why it can neither be parsed as a storage reference nor as an image URL. While I don't yet understand where you are getting the UploadTask from(it's best if you make the changes there), I'd suggest you use getDownloadUrl to get a Task which will give you the URL you need to pass to Glide.
This is how it should look:
val storage = FirebaseStorage.getInstance()
storage.getReference(YOUR_STORAGE_PATH).getDownloadUrl()
.addOnSuccessListener(OnSuccessListener() {
// onSuccess method call
Glide.with(context)
.load(URL FROM LISTENER)
.into(holder.gambarBarang)
}
)

So based on #Abdullah Z Khan answer, i notice that the problem is with my image uri. I use task.getResult to get the uri, but it give me taskSnapShot instead.

Related

How to solve Null Pointer Exception inside of Repository function while returning from function?

View model File code:
fun retrive(doc_name : String,uid: String){
viewModelScope.launch(Dispatchers.IO){
bitmap.value = repository.retrive(doc_name,uid)!!
}
}
The below code is the code of My repository Implementation
override suspend fun retrive(doc_name:String,uid: String) : Bitmap{
var bitmap :Bitmap? = null
val storageRef = FirebaseStorage.getInstance().reference?.child("/image/0XhL4jD4XCemk38rcRkIEjJMgjh2/Aadhar")
val localfile = createTempFile("tempImage", null)
if (storageRef.getFile(localfile).isSuccessful) {
bitmap = BitmapFactory.decodeFile(localfile.absolutePath)
Log.d("Check","$bitmap")
}
return bitmap!!
}
So this function is going to Firebase Storage and retrieving the image and storing it into a file and than converting it into a bitmap.
I am trying to return the bitmap from Repository so I can use it in UI as the project is following MVVM architecture
But as soon as I run it displays the following error:
E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: com.example.adminv1, PID: 23030
java.lang.NullPointerException
at com.example.alliaise_adminv1.Admin.Admin_Verif_rp_imp.retrive(Admin_Verif_rp_imp.kt:70)
at com.example.alliaise_adminv1.Admin.Admin_Verif_VM$retrive$1.invokeSuspend(Admin_Verif_VM.kt:30)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
So the error is in 2 places , the first is in Admin repository implementation File as shows in error line 70 and the same in Admin View model file as shown in error Line number 30
The error lines are :
In repository
return bitmap!!
In View Model:
bitmap.value = repository.retrive(doc_name,uid)!!
I am not sure what is going wrong but I have got a feeling stating the image is falling to get Retrieved from Firebase . I have cross checked all the paths. I think there is some issue in generating a temp file as that can be the only issue not sure tbh. Kindly help please
Just remove !! , using !! means you tell the compiler that this method will return something (non-null) and if it is return null it will throw an Exception at runtime.
Only use !! when you are sure that you will return non-null data.
In your case, the data from storage are nullable , so use ? instead.
override suspend fun retrive(doc_name:String,uid: String) : Bitmap? //add ?
{
...
//remove `!!`
return bitmap
}
// also here remove "!!", and change your bitmap data type to Bitmap?
bitmap.value = repository.retrive(doc_name,uid)
If your receiver method required non-null bitmap, you could use if else statement, although loading a nullable bitmap to imageView is actually safe.

How to store multiple images in one document(Firestore) Android

User should be able to upload multiple images in one post.
I tried to add all urls to a ArrayList and then to store them to firestore.
All I get are errors.
"imageList" returns always null
Here is my code:
fun uploadPost(images:ArrayList<Uri>, imageCount: Int, description:String){
images.forEach { image->
val imageRef = storageReferenence.child(System.currentTimeMillis().toString()
+"."+ image.lastPathSegment)
val uploadTask = imageRef.putFile((image))
uploadTask.addOnSuccessListener {
val downloadUrl = imageRef.downloadUrl
downloadUrl.addOnSuccessListener {uri->
Log.d("IMAGES", uri.toString())
imageList!!.add(uri.toString())
count++
}
}
}
//firebaseRepository.firestoreDB.collection("post").document(firebaseRepository.userid.toString()).update(post)
}
You can see that the Log has the url but when I try to add it to the imageList
it fails to do so.
THIS CAUSES THE ERROR: imageList!!.add(uri.toString())
ERROR MSG: AddViewModel$uploadPost$$inlined$forEach$lambda$1$1.onSuccess
I don`t really know what is better to store the images as an array or to store each image like this: image1:url... , image2: url..
I need them to be part of the same document.

Can we use firebase console to upload images manually?

In my app , I have to display images in RecyclerView from Firebase database but the problem is I don't want to upload images using my app but I want them to be manually added using console of Firebase storage and later use their location to be added in Firebase database. I tried doing this way but glide is not loading the images. So is there any way to upload images manually and load images in app ?
Edited :
enter image description here
Look at my image, I have simply added the storage location of image in my database table. After then I am using those functions to get the image location and loading them with the help of glide library.
Here is my code of retrieving categories from Firebase database.
fun getCategories() : List<Categories>{
val categoriesList = mutableListOf<Categories>()
CoroutineScope(IO).launch {
databaseReference.child("categories")
.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
for (postSnapshot in dataSnapshot.children) {
val categories = postSnapshot.getValue(Categories::class.java)
categoriesList.add(categories!!)
}
}
override fun onCancelled(p0: DatabaseError) {
}
})
}
return categoriesList
}
And after retrieving categories list ,I am loading my Images in Adapter class. Here is my Adapter class code
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val model = modelList[position]
holder.nameOfFruit?.text = model.name
holder.nameOfFruit?.setOnClickListener {
it.findNavController().navigate(R.id.action_mainFragment_to_choiceSelectedFragmentModel)
}
Glide.with(myContext!!).load(model.url).into(holder.imageOfFruit)
}
Edited : It is my image URL stored in my database.
enter image description here
You've stored a "gs://" URL in your database. This is a special Cloud Storage URL that only works with Google infrastructure. It will not work in browsers or applications.
You will have to instead store a download URL in the database. If you've done it correctly, it will start with "https://".

Load class into val with Picasso

I want to load a String out of a class to load it with picasso
val pic = String
Picasso.get().load(User1::profileImageUrl).into(pic)
but the "load" gets a red line underneath it and it doesnt work.
here you can see my class
class User1(val uid: String, val username: String, val profileImageUrl: String)
so later I want to use that string with glide like this
Glide.with(applicationContext).load(personPhotoUrl)
.thumbnail(0.3f)
.apply(RequestOptions.circleCropTransform())
.into(profilepicture!!)
any Ideas?
I am not familiar with Picasso, but from javadoc load method takes String, Uri, File or resource id. You pass some kind of reflection reference on a property (if this construction makes sense at all).
If you want create pic one time you should use an instance of user:
val user : User1 = getUserSomewhere()
Picasso.get().load(user1.profileImageUrl).into(pic)
Or you can make a method:
fun loadUserProfileImage(user: User1, target: ImageView) {
Picasso.get().load(user1.profileImageUrl).into(target)
}
Also underneath red line tells you that there is an error and it has a message of what's wrong.)
Also this: val pic = String is not correct, at least in your case. pic here is of type StringCompanionObject.

Android Kotlin - Firestore image upload and display

At the moment as a sample I'm recreating instagram-like post, where user can post a description and image (along with username since I'm still not configuring authentication). So far as follows I can only post username and description. Along side of that I can load new image as a source into the imageview on the screen.
My data class is:
data class Post(val username: String,
val timestamp: Date,
val postTxt: String,
val numLikes: Int,
val numComments: Int,
val documentId: String)
I put data in a hashmap as follows:
val data = hashMapOf(
NUM_LIKES to 0,
NUM_COMMENTS to 0,
POST_TXT to addPostTxt.text.toString().trim(),
TIMESTAMP to FieldValue.serverTimestamp(),
USERNAME to addUsernameTxt.text.toString().trim()
)
and then pass it to upload to firestore:
FirebaseFirestore.getInstance().collection(POST_REF)
.add(data)
.addOnSuccessListener { finish() }
.addOnFailureListener {
Log.e("Exception", "Could not add post: $it")
toast("Could not add post")
}
And to get the data I created a function which takes snapshot of type QuerySnapshot like so:
// Clear all the posts before relaod
posts.clear()
snapshot.documents.forEach { document ->
val data = document.data
val name = data?.get(USERNAME) as String
val timestamp = data[TIMESTAMP] as Date
val postTxt = data[POST_TXT] as String
val numLikes = data[NUM_LIKES] as Long
val numComments = data[NUM_COMMENTS] as Long
val documentId = document.id
val newPost = Post(name, timestamp, postTxt, numLikes.toInt(), numComments.toInt(), documentId)
posts.add(newPost)
}
postsAdapter.notifyDataSetChanged()
So far uploading text, current time of upload works fine for both upload and reading it from the database; however my question here is:
- What is the best way (following current codebase) to upload image to firestore and storage and display it accordingly in the main window (preferably using Glide or picasso)?
It's generally not a good idea to store binary data like images in Firestore. You could very easily exceed the limit for how much data you can store in a document, which is 1MB. Large documents also take more time to load on the client, which is even worse if you don't even need to use the image at the time of the read.
Instead, consider uploading the image to Cloud Storage and saving a path to that location in a field in your document. Then, when it's time to display the image, load it from there.

Categories

Resources