con - firebase rules auth
aplicaciĆ³n setPersistenceEnabled(true) crashes (17)
Estoy creando mi primera aplicación de Firebase. Uno de sus requisitos es que se ejecute cuando la red no esté disponible. La guía de Firebase dice:
Al habilitar la persistencia del disco, nuestra aplicación también puede mantener todo su estado incluso después de reiniciar la aplicación. Podemos habilitar la persistencia del disco con solo una línea de código. FirebaseDatabase.getInstance (). SetPersistenceEnabled (true); Con la persistencia de disco habilitada, nuestros datos y escrituras sincronizados se mantendrán en el disco durante los reinicios de la aplicación y nuestra aplicación debería funcionar sin problemas en situaciones fuera de línea.
Otro requisito es utilizar Google Iniciar sesión. Por lo tanto, en mi actividad principal MainActivity
si el usuario está registrado, si no es así, SignInActivity
. ( SignInActivity
es de los ejemplos de Firebase.) SignInActivity
funciona, el usuario MainActivity
sesión y MainActivity
se inicia por segunda vez. Ahora mi aplicación se bloquea en la línea de código FirebaseDatabase.getInstance().setPersistenceEnabled(true);
con el siguiente mensaje:
Las llamadas a setPersistenceEnabled () deben realizarse antes de cualquier otro uso de la instancia de FirebaseDatabase.
Ahora, si reinicio mi aplicación, el usuario SignInActivity
, SignInActivity
no se inicia, mi aplicación funciona bien.
¿Alguna sugerencia de cómo evitar este bloqueo después de que el usuario inicie sesión?
Mientras publicaba esta pregunta, recibí una sugerencia para reubicar FirebaseDatabase.getInstance().setPersistenceEnabled(true);
a mi "clase de aplicación". Obtengo exactamente el mismo resultado ... SignInActivity
inicia, completa y obtengo un bloqueo en setPersistenceEnabled
.
A continuación está mi MainActivity onCreate
:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Calls to setPersistenceEnabled() must be made before any other usage of FirebaseDatabase instance.
// Crash here upon returning from SignInActivity.
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
mFirebaseDbReference = FirebaseDatabase.getInstance().getReference();
// Initialize Firebase Auth
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseUser = mFirebaseAuth.getCurrentUser();
if (mFirebaseUser == null) {
// Not signed in, launch the Sign In activity
Timber.tag("MainActivity").i("onCreate(): User not signed in, launching SignInActivity");
startActivity(new Intent(this, SignInActivity.class));
finish();
} else {
mUsername = mFirebaseUser.getDisplayName();
Timber.tag("MainActivity").i("onCreate(): User /"%s/" signed in.", mUsername);
if (mFirebaseUser.getPhotoUrl() != null) {
mPhotoUrl = mFirebaseUser.getPhotoUrl().toString();
}
}
Asegúrate de que .setpersistenceenabled (true) no esté sucediendo dos veces, mientras que inicie sesión en Google en tu caso, se debe llamar a second care setPersistenceEnabled (true) antes de que cualquier instancia de firebase llamada esto resuelva mi problema.
Crea una clase llamada Util.java
y agregue el siguiente código
public class Util {
private static FirebaseDatabase mData;
public static FirebaseDatabase getDatabase() {
if (mData == null) {
mData = FirebaseDatabase.getInstance();
mData.setPersistenceEnabled(true);
}
return mData;
}
}
Ahora reemplace FirebaseDatabase.getIntance () con Util.getDatabase () cada vez en cada actividad. ¡Llamar solo una vez recibirá el error!
El mensaje de error describe el problema:
Las llamadas a setPersistenceEnabled () deben realizarse antes de cualquier otro uso de la instancia de FirebaseDatabase.
La solución a este problema se describe en la documentación: como en SDK 2.x, la persistencia del disco debe estar habilitada antes de que se realicen otras llamadas a la base de datos.
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
Estaba enfrentando el mismo problema. Cambié el código como abajo.
ANTES (Causando Crash)
var rootRef = FIRDatabase.database().reference()
override func viewDidLoad() {
super.viewDidLoad()
FIRDatabase.database().persistenceEnabled = true
}
DESPUÉS (Bloqueo resuelto)
var rootRef:FIRDatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
FIRDatabase.database().persistenceEnabled = true
rootRef = FIRDatabase.database().reference()
}
Lo resolvió haciendo que la referencia de Firebase sea un campo de clase estático como este:
public class MainActivity extends AppCompatActivity
private static FirebaseDatabase fbDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
if(fbDatabase == null) {
fbDatabase = FirebaseDatabase.getInstance();
fbDatabase.setPersistenceEnabled(true);
}
No es problema crear nuevas referencias de Firebase (sin setPersistenceEnabled (true)) en otras actividades también.
Me enfrentaba a un problema similar y el uso de una variable estática parecía resolver el problema para mí. Así que al principio mi código se veía algo como esto
@Override
protected void onCreate(Bundle savedInstanceState) {
//..code
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
FirebaseDatabase database = FirebaseDatabase.getInstance();
//..code
}
y ahora se parece más a
static boolean calledAlready = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
//..code
if (!calledAlready)
{
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
calledAlready = true;
}
FirebaseDatabase database = FirebaseDatabase.getInstance();
//..code
}
¡Espero eso ayude!
Mordí tarde, pero hoy recibí este problema, lo resolví añadiendo
static {
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}
a mi actividad
No recomendaría usar Application para almacenar los datos porque, como está escrito en CodePath
Siempre hay datos e información que se necesita en muchos lugares dentro de su aplicación. Esto podría ser un token de sesión, el resultado de un cálculo costoso, etc. Podría ser tentador usar la instancia de la aplicación para evitar la sobrecarga de pasar objetos entre actividades o mantenerlas en almacenamiento persistente.
Sin embargo, nunca debe almacenar datos de instancias mutables dentro del objeto Aplicación porque si supone que sus datos permanecerán allí, su aplicación se bloqueará inevitablemente en algún momento con una NullPointerException. No se garantiza que el objeto de la aplicación permanezca en la memoria para siempre, será asesinado. Contrario a la creencia popular, la aplicación no se reiniciará desde cero. Android creará un nuevo objeto Aplicación e iniciará la actividad donde el usuario estaba antes para dar la ilusión de que la aplicación nunca se mató en primer lugar.
Esa es la razón por la que recomendaría usar un Singleton como este:
public class DataBaseUtil {
private static FirebaseDatabase mDatabase;
public static FirebaseDatabase getDatabase() {
if (mDatabase == null) {
mDatabase = FirebaseDatabase.getInstance();
mDatabase.setPersistenceEnabled(true);
}
return mDatabase;
}}
solo úsalo en tu código y luego
private FirebaseDatabase fdb = DataBaseUtil.getDatabase();
Para Kotlin Pruebe esto:
class DatabaseUtil {
companion object {
private val firebaseDatabase: FirebaseDatabase = FirebaseDatabase.getInstance()
init {
firebaseDatabase.setPersistenceEnabled(true)
}
fun getDatabase() : FirebaseDatabase {
return firebaseDatabase
}
}
}
Para mí, es más fácil manejarlo creando una clase separada para Firebase. Esto se debe a que Firebase tiene su propia instancia y si la está utilizando en más de una actividad, existe la posibilidad de que se cuelgue si vuelve a llamar a setPersistenceEnabled en otra actividad.
Otra cosa buena es que puedes pasar tu contexto o tus parámetros al constructor de FirebaseHandler si es necesario. O si ha fijado la ubicación en la base de datos, se puede llamar fácil sin la repetición .child ("location").
Ejemplo:
public class FirebaseHandler {
// parameters
private Context context;
private String userKey;
private DatabaseReference databaseReference;
private static boolean isPersistenceEnabled = false;
private static String fixedLocationA = "locationA";
private static String fixedLocationB = "locationB";
public FirebaseHandler(Context context, String userKey) {
this.context = context; // context can be used to call PreferenceManager etc.
this.userKey = userKey;
if (!isPersistenceEnabled) {
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
isPersistenceEnabled = true;
}
databaseReference = FirebaseDatabase.getInstance().getReference().child(userKey);
}
public DatabaseReference getRefA() {
return databaseReference.child(fixedLocationA);
}
public DatabaseReference getRefB() {
return databaseReference.child(fixedLocationB);
}
}
Esto se puede llamar en cualquier actividad como a continuación.
public class MyActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get instance
FirebaseHandler firebaseHandler = new FirebaseHander(this, "userKey");
// to set value
firebaseHandler.getRefA().setValue("value");
// to set listener
firebaseHandler.getRefB().addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// TODO here....
// also, can remove listener if required
if (certain condition) {
firebaseHandler.getRefB().removeEventListener(this);
}
}
}
}
}
Puedes usar:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
antes de usar FirebaseDatabase.getInstance().getReference();
Si no te gustan los campos estáticos, este me fue el truco:
if (FirebaseApp.getApps(context).isEmpty()) {
FirebaseApp.initializeApp(context);
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}
Esto puede deberse a que más de un proceso inicializó dos veces las aplicaciones Firebase o Multidex. Para obtener más información, consulte esto: github.com/firebase/quickstart-android/issues/15
Simplemente mueva su código en ExampleFragment.class desde el método onCreateView al método onCreate:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
....
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container, false);
Solucioné esta excepción usando setPersistenceEnabled(true)
en mi clase de Application
.
public class MApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}
}
En AndroidManifest.xml, establezca el nombre de la aplicación como MApplication:
<application
android:name=".MApplication"
... />
También estoy enfrentando algún problema, pero esta es mi solución temporal para mi aplicación.
Create BaseActivity extends AppcompatActivity y anula onCreate, pon setPersistenceEnabled
allí.
public class BaseActivity extends AppCompatActivity {
private static String TAG = "BaseActivity";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try{
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
Log.d(TAG,FirebaseDatabase.getInstance().toString());
}catch (Exception e){
Log.w(TAG,"SetPresistenceEnabled:Fail"+FirebaseDatabase.getInstance().toString());
e.printStackTrace();
}
}
}
Y cambie MainActivity para extender BaseActivity
public class MainActivity extends BaseActivity
EDITAR: Sigue la respuesta de @imakeApps
public class BaseActivity extends AppCompatActivity {
private static String TAG = "BaseActivity";
static boolean isInitialized = false;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try{
if(!isInitialized){
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
isInitialized = true;
}else {
Log.d(TAG,"Already Initialized");
}
}catch (Exception e){
e.printStackTrace();
}
}
}
Un ContentProvider
inicializa una FirebaseApp para que no se inicialice en el momento en que se llama a onCreate()
.
Obtenga su FirebaseDatabase así:
public class Utils {
private static FirebaseDatabase mDatabase;
public static FirebaseDatabase getDatabase() {
if (mDatabase == null) {
mDatabase = FirebaseDatabase.getInstance();
mDatabase.setPersistenceEnabled(true);
}
return mDatabase;
}
}
A continuación, llame a Utils.getDatabase()
desde cualquier actividad para usar la base de datos.
No te olvides de compile ''com.google.firebase:firebase-database:...''
en build.gradle
En Menifest
android:name=".AppName
Crear una clase Java que extienda la aplicación
public class AppName extends Application {
@Override
public void onCreate() {
super.onCreate();
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}