Как исправить исключения хранилища firebase? - PullRequest
0 голосов
/ 05 августа 2020

Здравствуйте, я разрабатываю приложение Kotlin и использую Firebase. Однако я столкнулся с этой ошибкой:

2020-08-05 00:56:45.764 9163-9296/com.example.realtimechat E/StorageException: StorageException has occurred.
    Object does not exist at location.
     Code: -13010 HttpResult: 404
2020-08-05 00:56:45.767 9163-9296/com.example.realtimechat E/StorageException: {  "error": {    "code": 404,    "message": "Not Found.  Could not get object",    "status": "GET_OBJECT"  }}
    java.io.IOException: {  "error": {    "code": 404,    "message": "Not Found.  Could not get object",    "status": "GET_OBJECT"  }}
        at com.google.firebase.storage.network.NetworkRequest.parseResponse(com.google.firebase:firebase-storage@@19.1.1:433)
        at com.google.firebase.storage.network.NetworkRequest.parseErrorResponse(com.google.firebase:firebase-storage@@19.1.1:450)
        at com.google.firebase.storage.network.NetworkRequest.processResponseStream(com.google.firebase:firebase-storage@@19.1.1:441)
        at com.google.firebase.storage.network.NetworkRequest.performRequest(com.google.firebase:firebase-storage@@19.1.1:272)
        at com.google.firebase.storage.network.NetworkRequest.performRequest(com.google.firebase:firebase-storage@@19.1.1:286)
        at com.google.firebase.storage.internal.ExponentialBackoffSender.sendWithExponentialBackoff(com.google.firebase:firebase-storage@@19.1.1:70)
        at com.google.firebase.storage.internal.ExponentialBackoffSender.sendWithExponentialBackoff(com.google.firebase:firebase-storage@@19.1.1:62)
        at com.google.firebase.storage.GetDownloadUrlTask.run(com.google.firebase:firebase-storage@@19.1.1:76)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)

Я пытаюсь получить информацию из Firebase, чтобы отобразить ее в представлении ресайклера, но я не знаю, что я делаю неправильно.

Мой фрагмент:

package com.example.realtimechat.findfriends

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.realtimechat.R
import com.example.realtimechat.common.Constants
import com.example.realtimechat.common.NodeNames
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.database.*

class FindFriendsFragment: Fragment() {

    private var rvFindFriends: RecyclerView? = null
    private var findFriendsAdapter: FindFriendAdapter? = null
    private var findFriendsModelList: MutableList<FindFriendModel> = ArrayList()
    private var tvEmptyFriendsList: TextView? = null

    private var databaseReference: DatabaseReference? = null
    private var currentUser: FirebaseUser? = null
    private var progressBar: View? = null

    private var databaseReferenceFriendRequests: DatabaseReference? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_find_friends, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        rvFindFriends = view.findViewById(R.id.rvFindFriends)
        tvEmptyFriendsList = view.findViewById(R.id.tvEmptyFriendsList)
        progressBar = view.findViewById(R.id.progressBar)

        rvFindFriends!!.layoutManager = LinearLayoutManager(activity)

        findFriendsModelList = ArrayList()
        findFriendsAdapter = FindFriendAdapter(activity!!, findFriendsModelList)
        rvFindFriends!!.adapter = findFriendsAdapter

        databaseReference = FirebaseDatabase.getInstance().reference.child(NodeNames.USERS);
        currentUser  = FirebaseAuth.getInstance().currentUser;

        databaseReferenceFriendRequests = FirebaseDatabase.getInstance().reference.child(NodeNames.FRIEND_REQUESTS).child(currentUser!!.uid);

        tvEmptyFriendsList!!.visibility = View.VISIBLE;
        progressBar!!.visibility = View.VISIBLE;

        val query: Query = databaseReference!!.orderByChild(NodeNames.USERNAME)
        query.addValueEventListener(object: ValueEventListener{
            override fun onDataChange(snapshot: DataSnapshot) {
                findFriendsModelList.clear()

                for(ds: DataSnapshot in snapshot.children){
                    val userId = ds.key
                    if(userId.equals(currentUser?.uid)){
                        continue
                    }

                    if(ds.child(NodeNames.USERNAME).value !=null){
                        val username = ds.child(NodeNames.USERNAME).value.toString()
                        val photoFileName = ds.child(NodeNames.PHOTO).value.toString()

                        databaseReferenceFriendRequests!!.child(userId!!).addListenerForSingleValueEvent(object: ValueEventListener{
                            override fun onDataChange(snapshot: DataSnapshot) {
                                if(snapshot.exists()){
                                    val requestType = snapshot.child(NodeNames.REQUEST_TYPE).value.toString()
                                    if(requestType == Constants.REQUEST_STATUS_SENT){
                                        findFriendsModelList.add(FindFriendModel(userId, photoFileName, username, true))
                                        findFriendsAdapter!!.notifyDataSetChanged()
                                    }
                                }else{
                                    findFriendsModelList.add(FindFriendModel(userId, photoFileName, username, false))
                                    findFriendsAdapter!!.notifyDataSetChanged()
                                }
                            }

                            override fun onCancelled(error: DatabaseError) {
                                progressBar?.visibility = View.GONE
                            }
                        })
                        progressBar?.visibility = View.GONE
                        tvEmptyFriendsList?.visibility = View.GONE
                    }
                }
            }

            override fun onCancelled(error: DatabaseError) {
                progressBar?.visibility = View.GONE
                Toast.makeText(context, "Failed to fetch friend list ${error.message}", Toast.LENGTH_SHORT).show()
            }
        })
    }
}

Мой адаптер:

package com.example.realtimechat.findfriends

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.realtimechat.R
import com.example.realtimechat.common.Constants
import com.example.realtimechat.common.NodeNames
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.storage.FirebaseStorage


class FindFriendAdapter(private val context: Context,
                        private val findFriendModelList: List<FindFriendModel> = mutableListOf()) : RecyclerView.Adapter<FindFriendAdapter.FindFriendViewHolder>() {


    private var friendRequestDatabase: DatabaseReference? = null
    private var currentUser: FirebaseUser? = null
    private var userId: String? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FindFriendAdapter.FindFriendViewHolder {
        val view: View = LayoutInflater.from(context).inflate(R.layout.custom_find_friends_layout, parent, false)
        return FindFriendViewHolder(view)
    }

    override fun onBindViewHolder(holder: FindFriendAdapter.FindFriendViewHolder, position: Int) {
        val friendModel = findFriendModelList[position]
        holder.tvUsername.text = friendModel.username

        val fileRef = FirebaseStorage.getInstance().reference.child(Constants.IMAGES_FOLDER + "/" + friendModel.photoFileName)
        fileRef.downloadUrl.addOnSuccessListener { uri ->
            Glide.with(context)
                .load(uri)
                .placeholder(R.drawable.ic_profileicon)
                .error(R.drawable.ic_profileicon)
                .into(holder.ivProfile)
        }

        friendRequestDatabase = FirebaseDatabase.getInstance().reference.child(NodeNames.FRIEND_REQUESTS)
        currentUser = FirebaseAuth.getInstance().currentUser

        if(friendModel.requestSent!!){
            holder.btnSendRequest.visibility = View.GONE
            holder.pbRequest.visibility = View.VISIBLE
        }else{
            holder.btnSendRequest.visibility = View.VISIBLE
            holder.pbRequest.visibility = View.GONE
        }

        holder.btnSendRequest.setOnClickListener {
            holder.btnSendRequest.visibility = View.GONE
            holder.pbRequest.visibility = View.VISIBLE

            userId = friendModel.userId

            friendRequestDatabase!!.child(currentUser!!.uid).child(userId!!).child(NodeNames.REQUEST_TYPE)
                .setValue(Constants.REQUEST_STATUS_SENT)
                .addOnCompleteListener { task ->
                    if(task.isSuccessful){
                        friendRequestDatabase!!.child(userId!!).child(currentUser!!.uid).child(NodeNames.REQUEST_TYPE)
                            .setValue(Constants.REQUEST_STATUS_RECEIVED)
                            .addOnCompleteListener { task ->
                                if(task.isSuccessful){
                                    Toast.makeText(context, "Request sent successfully!", Toast.LENGTH_SHORT).show()

                                    holder.btnSendRequest.visibility = View.GONE
                                    holder.pbRequest.visibility = View.GONE
                                    holder.btnCancelRequest.visibility = View.VISIBLE
                                }
                            }.addOnFailureListener{ exception ->
                                Toast.makeText(context, "Failed to send request ${exception.localizedMessage}", Toast.LENGTH_SHORT).show()

                                holder.btnSendRequest.visibility = View.VISIBLE
                                holder.pbRequest.visibility = View.GONE
                                holder.btnCancelRequest.visibility = View.GONE
                            }
                    }
                }.addOnFailureListener{ exception ->
                    Toast.makeText(context, "Failed to send request ${exception.localizedMessage}", Toast.LENGTH_SHORT).show()

                    holder.btnSendRequest.visibility = View.VISIBLE
                    holder.pbRequest.visibility = View.GONE
                    holder.btnCancelRequest.visibility = View.GONE
                }
        }

        holder.btnCancelRequest.setOnClickListener {
            holder.btnCancelRequest.visibility = View.GONE
            holder.pbRequest.visibility = View.VISIBLE

            userId = friendModel.userId

            friendRequestDatabase!!.child(currentUser!!.uid).child(userId!!).child(NodeNames.REQUEST_TYPE)
                .setValue(null)
                .addOnCompleteListener { task ->
                    if(task.isSuccessful){
                        friendRequestDatabase!!.child(userId!!).child(currentUser!!.uid).child(NodeNames.REQUEST_TYPE)
                            .setValue(null)
                            .addOnCompleteListener { task ->
                                if(task.isSuccessful){
                                    Toast.makeText(context, "Request cancelled successfully!", Toast.LENGTH_SHORT).show()

                                    holder.btnSendRequest.visibility = View.VISIBLE
                                    holder.pbRequest.visibility = View.GONE
                                    holder.btnCancelRequest.visibility = View.GONE
                                }
                            }.addOnFailureListener{ exception ->
                                Toast.makeText(context, "Failed to cancel request ${exception.localizedMessage}", Toast.LENGTH_SHORT).show()

                                holder.btnSendRequest.visibility = View.GONE
                                holder.pbRequest.visibility = View.GONE
                                holder.btnCancelRequest.visibility = View.VISIBLE
                            }
                    }
                }.addOnFailureListener{ exception ->
                    Toast.makeText(context, "Failed to cancel request ${exception.localizedMessage}", Toast.LENGTH_SHORT).show()

                    holder.btnSendRequest.visibility = View.GONE
                    holder.pbRequest.visibility = View.GONE
                    holder.btnCancelRequest.visibility = View.VISIBLE
                }
        }
    }

    override fun getItemCount(): Int {
        return findFriendModelList.size
    }

    inner class FindFriendViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val ivProfile: ImageView = itemView.findViewById(R.id.ivProfilePic)
        val tvUsername: TextView = itemView.findViewById(R.id.tvUsername)
        val btnSendRequest: Button = itemView.findViewById(R.id.btnSendRequest)
        val btnCancelRequest: Button = itemView.findViewById(R.id.btnCancelRequest)
        val pbRequest: ProgressBar = itemView.findViewById(R.id.pbRequest)

    }
}

Мой XML Файл для фрагмента:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".findfriends.FindFriendsFragment"
    android:background="@android:color/white">

    <include
        android:id="@+id/progressBar"
        layout="@layout/custom_progressbar"
        android:visibility="gone"/>


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvFindFriends"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </androidx.recyclerview.widget.RecyclerView>

    <TextView
        android:id="@+id/tvEmptyFriendsList"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:text="Friends list will appear here"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Любая помощь будет принята с благодарностью!

Ответы [ 2 ]

0 голосов
/ 06 августа 2020

Я решил эту проблему.

Посмотрев на файл адаптера (где произошла ошибка), я обнаружил, что friendModel.photoFileName возвращает:

/v0/b/realtimechat-280e1.appspot.com/o/images/D7sZ9AdePTZIsniSGEIhlfSXbfD2.jpg

Однако имя файла в хранилище:

D7sZ9AdePTZIsniSGEIhlfSXbfD2.jpg

Следовательно, имя файла было неправильным, поэтому изображение не могло быть отображено. Чтобы эта проблема исчезла, необходимо удалить /v0/b/realtimechat-280e1.appspot.com/o/images/ из /v0/b/realtimechat-280e1.appspot.com/o/images/D7sZ9AdePTZIsniSGEIhlfSXbfD2.jpg, чтобы осталось только D7sZ9AdePTZIsniSGEIhlfSXbfD2.jpg. Итак, я сделал requestModel.photoFileName!!.substring(requestModel.photoFileName!!.lastIndexOf("/")+1), что означает, что я сохраняю только части String после последнего /, поэтому остается только D7sZ9AdePTZIsniSGEIhlfSXbfD2.jpg.

Последний код: val fileRef = FirebaseStorage.getInstance().reference.child(Constants.IMAGES_FOLDER + "/" + friendModel.photoFileName!!.substring(friendModel.photoFileName!!.lastIndexOf("/")+1))

fileRef.downloadUrl.addOnSuccessListener {uri -> Glide.with(context).load(uri).placeholder(R.drawable.ic_profileicon).error(R.drawable.ic_profileicon).into(holder.ivProfile)}

Я не уверен, работает ли этот код для всех случаев, поэтому, если у вас есть лучшее решение для этого, было бы лучше для вас опубликуйте это. Спасибо

0 голосов
/ 05 августа 2020

Вы столкнулись с ошибкой 404 network request, что означает, что объект, к которому вы пытаетесь получить доступ, недоступен на сервере.

 val fileRef = FirebaseStorage.getInstance().reference.child(Constants.IMAGES_FOLDER + "/" + friendModel.photoFileName)

  //your firebase storage path is not available or exist please have a look on it.
...