I want to do get reference from any image with random name in Firebase Storage. I set image name with UUID.randomUUID method but I can not reference that image for deleting it before uploading new image. I can delete that image with entering that file original name which is I copied from Firebase Storage. But I need getting reference for file, without entering name manually.
Here is my Firebase Storage and image names
Here is my Kotlin codes
val uuid = UUID.randomUUID()
val imageName = "$uuid.jpg"
val imagereference =
FirebaseStorage.getInstance().reference.child("images/$cu/profphoto")
.child(imageName)
val ref2 = FirebaseStorage.getInstance().reference.child("images/$cu/profphoto/5a91e7f3-144a-4c38-b7b5-36ed644603ca.jpg")
val db = FirebaseFirestore.getInstance()
ref2.delete().addOnSuccessListener {
}
imagereference.putFile(imageUri!!)
.addOnSuccessListener {}
UPDATE: Solution
Getting to create imagename in Firestore/Realtime Database documents.
/////
val uploadPictureReference =
storage.reference.child("images/$cu/profphoto").child(imageName)
uploadPictureReference.downloadUrl.addOnSuccessListener {
val downloadUrl = it.toString()
val auth = FirebaseAuth.getInstance()
val cu = auth.currentUser?.uid
if (cu != null) {
val postMap = hashMapOf<String, Any>()
postMap.put("imgName", imageName)
postMap.put("downloadUs", downloadUrl)
postMap.put("date", Timestamp.now())
if ("downloadUs".isEmpty()) {
val new = db.collection("Publikusers").document(cu)
new.set(postMap, SetOptions.merge())
.addOnSuccessListener {}
2. Reference to that name
val ref = db.collection("Publikusers").document(cu!!)
ref.get().addOnSuccessListener {
val currentImageName = it.data?.get("imgName")?.toString()
val ref2 =
FirebaseStorage.getInstance().reference.child("images/$cu/profphoto/$currentImageName")
ref2.delete().addOnSuccessListener {}
Related
I'm trying to display data from Firestore and add it to a PieChart.
I can't figure out why I can't access my data
This is how data are stored in Firestore:
This is how I try to access it:
private val mFirestore = FirebaseFirestore.getInstance()
var chartdata: ArrayList<Measurements> = ArrayList()
private var chart: ScatterChart? = null
fun getCurrentUserID(): String {
val currentUser = FirebaseAuth.getInstance().currentUser
var currentUserID = ""
if (currentUser != null) {
currentUserID = currentUser.uid
}
return currentUserID
}
mFirestore.collection(Constants.MEASUREMENTS)
.whereEqualTo(Constants.USER_ID, getCurrentUserID())
.get()
.addOnSuccessListener { queryDocumentSnapshots ->
val userdata : ArrayList<Measurements> = ArrayList()
val weekdata = ArrayList<Measurements>()
if (!queryDocumentSnapshots.isEmpty) {
for (journals in queryDocumentSnapshots) {
val displayData: Measurements = journals.toObject(Measurements::class.java)
userdata.add(displayData)
Log.e("Data for chart", journals.toString())
}
And I get this error:
enter image description here
The data is being fetched precisely that's why you can see all the document names in the logcat but as you are logging DocumentSnapshot object, that's why you are seeing the data in unusual format. Try logging displayData variables like:
Log.d("Data for chart", displayData.activity) // Use Log.d instead of Log.e
or userdata as an array and it will work as desired.
On clicking like button , it is not either increasing like count in UI nor adding a userid in likes array. It is not adding a userid into an array instead it is updating value at 0th index. I am attaching photos of logic to add values in array in firestore.
I have also added the project on github. Please take a look at it for more clearification.
https://github.com/Anshi10/Social-Media-App
Post data class which has array of user ids which liked a post.
data class Post(
val text : String = "" ,
val createdBy : user = user() ,
val createdAt : Long = 0L ,
val Likes : ArrayList<String> = ArrayList()
)
Post Dao for adding post into firestore and updating likes
class PostDao {
val db = FirebaseFirestore.getInstance()
val PostCollection = db.collection("Post")
val auth = Firebase.auth
fun addPost(text : String){
//!! is to ensure that post is created only when user is logged in otherwise it will count as illegal exception
val currentUserId = auth.currentUser!!.uid
val userdao = userDao()
GlobalScope.launch{
//getuserbyid return task which will turn into object of user data class
val Postuser = userdao.getuserbyId(currentUserId).await().toObject(user::class.java)!!
//this will give the time when the post is created
val currentTime = System.currentTimeMillis()
val post = Post(text,Postuser,currentTime)
PostCollection.document().set(post)
}
}
fun getPostById(postid : String) : Task<DocumentSnapshot>{
return PostCollection.document(postid).get()
}
fun updateLikes(postid: String) {
GlobalScope.launch {
val currentUserid = auth.currentUser!!.uid
val post = getPostById(postid).await().toObject(Post::class.java)!!
val isliked = post.Likes.contains(currentUserid)
if (isliked) {
post.Likes.remove(currentUserid)
} else {
post.Likes.add(currentUserid)
}
PostCollection.document(postid).set(post)
}
Log.d("msg","updateLikes called")
}
}
onBindViewHolder function
override fun onBindViewHolder(holder: PostViewHolder, position: Int, model: Post) {
holder.userName.text = model.createdBy.name
holder.userText.text = model.text
//with(context) load(url) into(view)
Glide.with(holder.userImage.context).load(model.createdBy.imageUrl).circleCrop().into(holder.userImage)
holder.Likecount.text = model.Likes.size.toString()
holder.userTime.text = Utils.getTimeAgo(model.createdAt)
val auth = FirebaseAuth.getInstance()
val currentuserId = auth.currentUser!!.uid
val isliked = model.Likes.contains(currentuserId)
if(isliked){
holder.likeButton.setImageDrawable(ContextCompat.getDrawable(holder.likeButton.context,R.drawable.ic_baseline_favorite_24))
}
else{
holder.likeButton.setImageDrawable(ContextCompat.getDrawable(holder.likeButton.context,R.drawable.unliked))
}
}
}
Firestore structure
first collection named post which contains field createdAt , createdBy,likesCount,text of the post.
second collection named users which contains field id , imageUrl , name
I am trying to iterate through the database documents and have the fields update with the click of the next button and previous button. As of right now, it's only happening with one and then it stops. I don't know why it only does it once and stops. Any reason as to why? Here is a snapshot of what I got right now.
This image is hardcoded in there with the code that is below here.
[![private lateinit var locationTextView: TextView
private lateinit var descriptionTextView: TextView
private lateinit var previousArrow: Button
private lateinit var nextArrow: Button
private lateinit var usersImage: ImageView][2]][2]
val db = FirebaseFirestore.getInstance()
db.collection("Post").orderBy("timestamp")
val docRef = db.collection("Post").document("Puppy")
docRef.get()
.addOnSuccessListener { document ->
if (document != null) {
Log.d("Exists", "DocumentSnapshot data: ${document.data}")
// locationTextView.text = document.getString("locationTitle")
locationTextView.setText(document.getString("Name"))
descriptionTextView.setText(document.getString("description"))
val imageName = "Puppy"
val storageRef = FirebaseStorage.getInstance().reference.child("Images/$imageName")
val localFile = File.createTempFile("tempImage", "jpeg")
storageRef.getFile(localFile).addOnSuccessListener {
val bitmap = BitmapFactory.decodeFile(localFile.absolutePath)
usersImage.setImageBitmap(bitmap)
}
}
else {
Log.d("noExist", "No Such Document")
}
}
However, I want to be able to implement these two buttons, so I can get rid of the code above and have it just pull from the database and navigate through each Post with the click of the buttons. I added this onto my next button and it is able to iterate only once. Is there a way that I can iterate through the size of the documents, that way I can go through all of them and not just once?
nextArrow.setOnClickListener {
val first = db.collection("Post").orderBy("timestamp").limit(1)
first.get()
.addOnSuccessListener { documentSnapshots ->
val lastVisible = documentSnapshots.documents[documentSnapshots.size() - 1]
val next = db.collection("Post").orderBy("timestamp").startAfter(lastVisible).limit(2)
next.get().addOnSuccessListener { documents ->
for (document in documents) {
Log.d(TAG, "${document.id} => $${document.data}")
locationTextView.setText(document.getString("Name"))
descriptionTextView.setText(document.getString("description"))
}
}
val imageName = "Puppy"
val storageRef = FirebaseStorage.getInstance().reference.child("Images/$imageName")
val localFile = File.createTempFile("tempImage", "jpeg")
storageRef.getFile(localFile).addOnSuccessListener {
val bitmap = BitmapFactory.decodeFile(localFile.absolutePath)
usersImage.setImageBitmap(bitmap)
}
}
}
previousArrow.setOnClickListener {
}
Here is a snapshot of my database.
Again, to clarify, I am trying to iterate through my database with the Posts with the click of those buttons. Also, the images are stored in a firebase storage database since it's too large for firestore.
As also #FrankvanPuffelen mentioned in his comment, what you are looking for is a pagination algorithm. Since all your images are represented by a documents inside the "Post" collection, it means that you can create a query to load a single image and then load all subsequent images one at a time.
I have answered a similar question a few years ago, where the OP wanted to load more results on a button click:
Is there a way to paginate queries by combining query cursors using FirestoreRecyclerAdapter?
In your case, the first query would be:
val db = FirebaseFirestore.getInstance()
val firstQuery = db.collection("Post").orderBy("timestamp").limit(1)
To construct the second query, inside the first callback you have to get the last visible item using:
val lastVisible = queryDocumentSnapshots.documents[queryDocumentSnapshots.size() - indexFam]
And perform the query:
val next = db.collection("Post").orderBy("timestamp").startAfter(lastVisible).limit(1)
inside this function:
private fun getNext(first: Query, db: FirebaseFirestore, indexFam: Int) {
first.get().addOnSuccessListener { queryDocumentSnapshots ->
val lastVisible = queryDocumentSnapshots.documents[queryDocumentSnapshots.size() - indexFam]
val next = db.collection("Post").orderBy("timestamp").startAfter(lastVisible).limit(1)
next.get().addOnSuccessListener { documents ->
for (document in documents) {
Log.d(TAG, "${document.id} => $${document.data}")
// Whatever you want to iterate right here.
}
}
}
}
Here is how I solved this using my method onto my onCreate():
private lateinit var locationTextView: TextView
private lateinit var descriptionTextView: TextView
private lateinit var previousArrow: Button
private lateinit var nextArrow: Button
private lateinit var usersImage: ImageView
val db = FirebaseFirestore.getInstance()
val first = db.collection("Post").orderBy("timestamp")
getNext(first, db, 2) // This is the original pop up
getPostSizeAsync(first) { postSize ->
nextArrow.setOnClickListener {
nextClicker++
if(nextClicker == postSize) {
nextClicker = 2
}
getNext(first, db, nextClicker)
}
}
// This is for the previous button clicker
previousArrow.setOnClickListener {
if(nextClicker > 1)
{
nextClicker--
getNext(first, db, nextClicker)
}
}
And then with the private functions:
private fun getNext(first: Query, db: FirebaseFirestore, indexFam: Int) {
first.get().addOnSuccessListener { queryDocumentSnapshots ->
val lastVisible = queryDocumentSnapshots.documents[queryDocumentSnapshots.size() - indexFam]
val next = db.collection("Post").orderBy("timestamp").startAfter(lastVisible).limit(1)
next.get().addOnSuccessListener { documents ->
for (document in documents) {
Log.d(TAG, "${document.id} => $${document.data}")
locationTextView.setText(document.getString("Name"))
descriptionTextView.setText(document.getString("description"))
val imageName = document.getString("Name")
val storageRef = FirebaseStorage.getInstance().reference.child("Images/$imageName")
val localFile = File.createTempFile("tempImage", "jpeg")
storageRef.getFile(localFile).addOnSuccessListener {
val bitmap = BitmapFactory.decodeFile(localFile.absolutePath)
usersImage.setImageBitmap(bitmap)
}
}
}
}
}
private fun getPostSizeAsync(first: Query, callback: (Int) -> Unit) {
first.get().addOnSuccessListener { documents ->
val postSize = documents.count()
callback(postSize)
}
}
I'm trying to model a database schema for Firestore. How can I create this database model?
This is my recipe data class
data class Foods(
var foodId:String?,
var foodName:String,
var foodCategory:String,
var foodCalory:Int,
var foodIngredients:String,
var foodRecipe:String,
var foodCookingTime:Int,
var foodImg:String?)
My Users Id getting this
val user : FirebaseUser? = auth?.currentUser
val userID: String = user?.uid.toString()
As I see in your screenshot, your document (vp0q ...) holds an array of Foods objects. If you want to be able to map that document to an object of a particular class, you should consider using the following class declarations:
data class User (recipe: Array<Foods>)
Now, to read that document, you should use the following reference:
val uid = FirebaseAuth.getInstance().currentUser?.uid
val rootRef = FirebaseFirestore.getInstance()
val usersRef = rootRef.collection("users")
usersRef.document(uid).get()
.addOnSuccessListener { document ->
if (document != null) {
val recipe = document.toObject<Foods>().recipe
//Do what you need to do with your recipe array
} else {
Log.d(TAG, "No such document")
}
}
.addOnFailureListener { exception ->
Log.d(TAG, "get failed with ", exception)
}
This is for my messaging app, whenever I try to send a gif from this GIPHY UI SDK, I get this error: An unknown error occurred, please check the HTTP result code and inner exception for server response.
override fun onGifSelected(media: Media, searchTerm: String?, selectedContentType: GPHContentType) {
val image = media.images.fixedWidth
val gif_url = image!!.gifUrl
val gifUri = Uri.parse(gif_url)
val reference2 = FirebaseDatabase.getInstance().getReference("Friends")
reference2.child(firebaseUser!!.uid)
.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.hasChild(visitorsUid!!)) {
//progressDialog
val pd = ProgressDialog(this#ChatActivity)
pd.setTitle("Please wait...")
pd.setMessage("Sending Gif...")
pd.setCanceledOnTouchOutside(false)
pd.show()
val databaseReference = FirebaseDatabase.getInstance().reference
//file name and path in firebase storage
val filenamePath = "Gif Images/" + firebaseUser!!.uid + System.currentTimeMillis()
val storageReference = FirebaseStorage.getInstance().getReference(filenamePath)
//upload image
storageReference.putFile(gifUri!!)
.addOnSuccessListener { taskSnapshot ->
//image uploaded, get url
val p_uriTask = taskSnapshot.storage.downloadUrl
while (!p_uriTask.isSuccessful);
val p_downloadUri = p_uriTask.result
if (p_uriTask.isSuccessful) {
//image url recieved, save in db
//timestamp
val timestamp = "" + System.currentTimeMillis()
//setup message data
val hashMap = HashMap<String, Any>()
hashMap["sender"] = firebaseUser!!.uid
I think the problem is with this line
val gifUri = Uri.parse(gif_url)
I tried to upload it to my firebase storage
storageReference.putFile(gifUri!!)
Here's what my logcat shows
E/StorageException: No content provider: https://media3.giphy.com/media/iJbxNEqePoPp7l8I0g/200w.gif?cid=e8dbb930ge42y7jitdl6z424143u7ah6bti5nmz7v16mdi53&rid=200w.gif
java.io.FileNotFoundException: No content provider: https://media3.giphy.com/media/iJbxNEqePoPp7l8I0g/200w.gif?cid=e8dbb930ge42y7jitdl6z424143u7ah6bti5nmz7v16mdi53&rid=200w.gif
at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1969)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1798)
at android.content.ContentResolver.openInputStream(ContentResolver.java:1475)
There is no way to upload a file to Firebase Storage directly from a URL. You will first have to download the data from the URL, and then upload that local data to Firebase as either a String, a local File object, or a Stream.
Also see:
Upload image from URL to Firebase Storage, which has some valid answers wondering why you'd want to copy the file over to Firebase Storage if Giphy already hosts it.