无法使用 Android 将数据写入 Firebase 数据库时如何获取错误消息
Posted
技术标签:
【中文标题】无法使用 Android 将数据写入 Firebase 数据库时如何获取错误消息【英文标题】:How to get an error message when data could not be written into the Firebase Database using Android 【发布时间】:2021-12-19 17:42:36 【问题描述】:我使用的是 android,我想在 Firebase 实时数据库中存储一些数据。奇怪的是,有时这有效,有时却无效。我认为这可能与我的 WLAN 连接并不总是很好有关,但即使 WLAN 连接良好,有时数据也可以写入 Firebase 数据库,但有时它就无法正常工作。
无论如何,我希望以敬酒的形式向用户发送一条消息,说明数据尚未写入 Firebase 数据库。为此,我有以下 Java 片段:
package com.example.td.bapp;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.database.Cursor;
import android.os.Bundle;
import android.text.InputType;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.navigation.Navigation;
import com.example.td.bapp.databinding.TestFragmentBinding ;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicBoolean;
public class TestFragment extends Fragment implements View.OnClickListener
@Override
public void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
@Nullable
private TestFragmentBinding binding;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
binding = TestFragmentBinding.inflate(inflater, container, false);
/*
Set onClickListeners to the buttoms
*/
binding.orderingButton.setOnClickListener(this);
return binding.getRoot();
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
@Override
public void onClick(View view)
if(view.getId() == R.id.ordering_button)
/*
Write data into the Firebase DB
*/
long currentTimeMillis = System.currentTimeMillis();
SimpleDateFormat sdf1 = new SimpleDateFormat("dd-MM-yy");
sdf1.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
SimpleDateFormat sdf2 = new SimpleDateFormat("HH-mm-ss");
sdf1.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
DatabaseReference rootRef = FirebaseDatabase.getInstance("https://drink-server-db-default-rtdb.europe-west1.firebasedatabase.app").getReference();
DatabaseReference ordersRef = rootRef.child("orders");
String id ="table_" + MainActivity.tableNumber + "_order_" + MainActivity.orderNumberOfTheSession + "_date_" + sdf1.format(new Date()) + "_time_" + sdf2.format(new Date());
String name1 = "Test_1";
String name2 = "Test_2";
FirebaseDBItem_Order currentOrder = new FirebaseDBItem_Order(name1, name2);
Log.e("LogTag", "Before write into DB");
ordersRef.child(id).setValue(currentOrder).addOnCompleteListener(new OnCompleteListener<Void>()
@Override
public void onComplete(@NonNull Task<Void> task)
if (task.isSuccessful())
Log.e("dbTAG", "Data successfully written.");
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(getContext(), getString(R.string.message_orderSubmittedSuccessfully), duration);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
else
Log.e("dbTAG", task.getException().getMessage());
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(getContext(), getString(R.string.message_orderSubmittedNotSuccessfully), duration);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
);
try
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
Log.e("LogTag", "After write into DB");
Navigation.findNavController(getView()).navigate(TestFragmentDirections.actionFRCocktailToFRMenu());
如果数据成功写入 Firebase 数据库,则会显示 toast,并且我会收到正确的 dbTAG 和 LogTag 消息:
E/LogTag:写入数据库之前
E/LogTag:写入数据库后
E/dbTAG:数据写入成功。
但是,当数据没有成功写入 Firebase 数据库时,我只是没有从 onComplete 方法的 dbTAG 收到任何消息,并且在数据库中找不到新条目。我刚刚收到 LogTag 消息:
E/LogTag:写入数据库之前
E/LogTag:写入数据库后
现在实际上我有两个问题:
-
为什么有时数据可以写入 Firebase 数据库,有时却不能,为什么这似乎是“随机”发生的?你能想出一些原因吗?
更重要的是:当数据无法写入 Firebase 数据库时,如何获得错误消息以便通知用户?与此相关:当数据未成功写入 Firebase 数据库时,为什么我没有收到
Log.e("dbTAG", task.getException().getMessage());
消息?所以onComplete
方法的else分支在数据没有成功存储的时候不会执行。
如果您需要任何进一步的信息,请告诉我。
【问题讨论】:
【参考方案1】:为什么有时数据可以写入 Firebase 数据库,而有时却不能,为什么这似乎是“随机”发生的?你能想到一些原因吗?
这很可能是因为缺乏互联网连接。要解决这个问题,您应该启用离线持久性。在 Java 代码中,这可以使用以下行来完成:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
根据文档:
即使您的应用暂时失去网络连接,Firebase 应用也能正常工作。
Firebase 应用会自动处理临时网络中断。缓存数据在离线时可用,并且 Firebase 会在网络连接恢复时重新发送任何写入。
回答你的第二个问题:
更重要的是:当数据无法写入 Firebase 数据库时,如何获得错误消息以便通知用户?与此相关:为什么我没有得到 Log.e("dbTAG", task.getException().getMessage());数据未成功写入 Firebase 数据库时的消息?所以onComplete方法的else分支在数据存储不成功时不会执行。
您正在以正确的方式处理错误:
Log.e("dbTAG", task.getException().getMessage());
当写入数据出现问题时,您会收到一条错误消息,这意味着写入操作被 Firebase 服务器拒绝,例如,当您的安全规则不正确时。
还请注意,Firebase 实时数据库 SDK不会在没有互联网连接时抛出异常,这是有道理的,因为 Firebase 实时数据库旨在离线工作。在幕后,Firebase 实时数据库 SDK 会尝试重新连接,直到设备重新连接。但是,当 Firebase 服务器由于安全规则问题而拒绝请求时,它确实会抛出异常。
【讨论】:
感谢亚历克斯的回答。我对此有几点意见:1)有时即使我有良好的互联网连接,数据也不会写入 Firebase 数据库。你能想到发生这种情况的任何其他原因吗? 2)即使没有插入您建议的代码FirebaseDatabase.getInstance().setPersistenceEnabled(true);
,有时在编写订单时也无法完成,一段时间后,许多订单被写入数据库(因此它们以某种方式在缓存中)。那么这是标准行为(即使没有代码),为什么有时会发生,有时不会?
1.也许操作没有完成,因为它需要太多时间。尝试constantly check for internet connectivity。 2. 如果设备恢复连接时这些写入仍保留在缓存中,则所有写入器都将发送到 Firebase 服务器。
除此之外,不要让主线程进入睡眠状态。这也是可以提供这种行为的原因。
感谢亚历克斯的回答。那么这种持久行为FirebaseDatabase.getInstance().setPersistenceEnabled(true);
默认启用吗?如果没有,我到底应该在哪里插入它?在主要活动或片段中(将其插入片段时收到一些错误消息)。你会在哪里以及为什么建议我经常检查互联网连接?在写入 Firebase 数据库之前?
此外,当您将建议的语句放在主要活动中时,我有时会收到错误“原因:com.google.firebase.database.DatabaseException:必须在任何其他使用之前调用 setPersistenceEnabled() FirebaseDatabase 实例。”您写道(关于我的第二个问题):“如果设备重新连接时这些写入仍保留在缓存中,则所有写入器都将被发送到 Firebase 服务器。” --> 我怎样才能确保它们保留在缓存中,因为在以前的运行中有时会发生这种情况,有时不会发生。以上是关于无法使用 Android 将数据写入 Firebase 数据库时如何获取错误消息的主要内容,如果未能解决你的问题,请参考以下文章
Android *** 服务 Bytebuffer 无法写入
(Android和Firebase)无法解析符号“dataSnapshot”[关闭]
无法从 Android 中 FirebaseMessagingService 的 onMessageReceived 生成通知