it-swarm.com.de

setPersistenceEnabled (true) stürzt ab

Ich erstelle meine erste Firebase-App. Eine seiner Anforderungen ist, dass es ausgeführt wird, wenn das Netzwerk nicht verfügbar ist. Der Firebase-Leitfaden besagt: 

Durch die Aktivierung der Festplattenpersistenz kann unsere App auch nach einem Neustart der App ihren gesamten Status beibehalten. Wir können die Festplattenpersistenz mit nur einer Codezeile aktivieren. FirebaseDatabase.getInstance (). SetPersistenceEnabled (true); Wenn die Festplattenpersistenz aktiviert ist, werden unsere synchronisierten Daten und Schreibvorgänge auch nach App-Neustarts auf der Festplatte beibehalten, und unsere App sollte in Offline-Situationen nahtlos funktionieren.

Eine weitere Voraussetzung ist die Verwendung von Google Sign In. Also überprüfe ich in meiner MainActivity, ob der Benutzer angemeldet ist. Wenn nicht, starte ich die SignInActivity. (Die Variable SignInActivity stammt aus den Firebase-Beispielen.) Die Variable SignInActivity funktioniert, der Benutzer wird angemeldet und MainActivity wird ein zweites Mal gestartet. Nun stürzt meine App in der Codezeile FirebaseDatabase.getInstance().setPersistenceEnabled(true); mit der folgenden Meldung ab: 

Aufrufe von setPersistenceEnabled () müssen vor jeder anderen Verwendung der FirebaseDatabase-Instanz erfolgen.

Wenn ich jetzt meine App neu starte, ist der Benutzer angemeldet, die SignInActivity wird nicht gestartet, meine App läuft einwandfrei.

Irgendwelche Vorschläge, wie ich diesen Absturz nach der Anmeldung des Benutzers vermeiden kann?

Während ich diese Frage postete, erhielt ich einen Vorschlag, FirebaseDatabase.getInstance().setPersistenceEnabled(true); in meine "Anwendungsklasse" zu verschieben. Ich bekomme genau das gleiche Ergebnis… SignInActivity startet, wird beendet und ich stürze auf die setPersistenceEnabled ab.

Unten ist meine 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();
        }
    } 
35
Loren

Eine FirebaseApp wird durch eine ContentProvider initialisiert, sodass sie zum Zeitpunkt des Aufrufs von onCreate() nicht initialisiert wird.

Holen Sie sich Ihre FirebaseDatenbank so:

public class Utils {
    private static FirebaseDatabase mDatabase;

    public static FirebaseDatabase getDatabase() {
       if (mDatabase == null) {
          mDatabase = FirebaseDatabase.getInstance();
          mDatabase.setPersistenceEnabled(true);
       }
       return mDatabase;
    }

}

Rufen Sie dann Utils.getDatabase() aus einer beliebigen Aktivität auf.

Lesen Sie mehr in diesem Artikel

49
Dan Alboteanu

Ich habe diese Ausnahme behoben, indem ich setPersistenceEnabled(true) in meiner Application-Klasse verwendete.

public class MApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        FirebaseDatabase.getInstance().setPersistenceEnabled(true);
    }
}

Legen Sie in AndroidManifest.xml den Namen der Anwendung als MApplication fest:

<application
    Android:name=".MApplication"
    ... />
45
dknchris

Ich hatte ein ähnliches Problem und die Verwendung einer statischen Variablen schien das Problem für mich zu lösen. So sah mein Code zuerst so aus 

@Override
protected void onCreate(Bundle savedInstanceState) {
    //..code

    FirebaseDatabase.getInstance().setPersistenceEnabled(true);
    FirebaseDatabase database = FirebaseDatabase.getInstance();

    //..code
}

und jetzt sieht es mehr aus

static boolean calledAlready = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    //..code

    if (!calledAlready)
    {
        FirebaseDatabase.getInstance().setPersistenceEnabled(true);
        calledAlready = true;
    }

    FirebaseDatabase database = FirebaseDatabase.getInstance();

    //..code
}

Ich hoffe es hilft!

24
imakeApps

Ich bin spät dran, aber heute habe ich dieses Problem bekommen, das ich durch Hinzufügen gelöst habe

static {
    FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}

zu meiner Aktivität

14
rkmax

Für mich ist es einfacher, durch Erstellen einer separaten Klasse für Firebase gehandhabt zu werden. Dies liegt daran, dass Firebase über eine eigene Instanz verfügt. Wenn Sie Firebase in mehr als einer Aktivität verwenden, besteht die Möglichkeit, dass es abstürzt, wenn Sie setPersistenceEnabled in einer anderen Aktivität erneut aufrufen.

Eine weitere gute Sache ist, dass Sie Ihren Kontext oder Ihre Parameter bei Bedarf an den FirebaseHandler-Konstruktor übergeben können. Wenn Sie einen festen Speicherort in der Datenbank haben, können Sie sie auch ohne den Speicherort .child ("location") einfach nennen.

Beispiel:

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);
    }
}

Dieser kann dann in einer beliebigen Aktivität aufgerufen werden.

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);
                }
            }
        }
    }
}
3
tingyik90

Wenn Sie die statischen Felder nicht mögen, hat das für mich den Trick:

if (FirebaseApp.getApps(context).isEmpty()) {
     FirebaseApp.initializeApp(context);
     FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}

Dies kann mehr als ein Prozess verursacht werden, bei dem zweimal Firebase- oder Multidex-Apps initialisiert werden. Weitere Informationen finden Sie hier: https://github.com/firebase/quickstart-Android/issues/15

1
Yair Kukielka

Es wurde behoben, indem der Firebase-Verweis auf ein statisches Klassenfeld wie folgt festgelegt wurde:

public class MainActivity extends AppCompatActivity

private static FirebaseDatabase fbDatabase;

@Override
    protected void onCreate(Bundle savedInstanceState) {

if(fbDatabase == null) {
            fbDatabase = FirebaseDatabase.getInstance();
            fbDatabase.setPersistenceEnabled(true);
        }

Es ist kein Problem, neue Firebase-Referenzen (ohne setPersistenceEnabled (true)) auch in anderen Aktivitäten zu erstellen.

1
Helmwag

Erstellen Sie eine Klasse mit dem Namen Util.Java

und folgenden Code hinzufügen

public class Util {

        private static FirebaseDatabase mData;

        public static FirebaseDatabase getDatabase() {
            if (mData == null) {

                mData = FirebaseDatabase.getInstance();
                mData.setPersistenceEnabled(true);
            }
            return mData;
        }


}

Ersetzen Sie nun FirebaseDatabase.getIntance () durch Util.getDatabase () jedes Mal in jeder Aktivität. Wenn Sie nur einmal anrufen, wird der Fehler angezeigt!

1
Rijvi Zaman

Ich habe auch Probleme, aber dies ist meine vorübergehende Lösung für meine App. 

BaseActivity erstellen erweitert AppcompatActivity und überschreibt onCreate, wobei setPersistenceEnabled eingefügt wird.

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();
        }
    }
}

Und ändern Sie MainActivity, um BaseActivity zu erweitern

public class MainActivity extends BaseActivity

EDIT: Antwort von @imakeApps folgen

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();
        }
    }
}
1
Sucipto

Ich würde nicht empfehlen, Application zum Speichern der Daten zu verwenden, da sie in CodePath geschrieben wurden 

Es gibt immer Daten und Informationen, die an vielen Stellen Ihrer App benötigt werden. Dies kann ein Sitzungstoken sein, das Ergebnis einer kostspieligen Berechnung usw. Es kann verlockend sein, die Anwendungsinstanz zu verwenden, um den Aufwand für das Übergeben von Objekten zwischen Aktivitäten zu vermeiden oder diese dauerhaft zu speichern.

Sie sollten jedoch niemals veränderliche Instanzdaten innerhalb des Application-Objekts speichern. Wenn Sie davon ausgehen, dass Ihre Daten dort bleiben, stürzt die Anwendung zwangsläufig mit einer NullPointerException ab. Es ist nicht garantiert, dass das Anwendungsobjekt für immer im Speicher verbleibt, es wird jedoch getötet. Entgegen der landläufigen Meinung wird die App nicht von Grund auf neu gestartet. Android erstellt ein neues Anwendungsobjekt und startet die Aktivität, bei der sich der Benutzer zuvor befunden hat, um den Eindruck zu erwecken, dass die Anwendung niemals zuvor beendet wurde.

Aus diesem Grund würde ich empfehlen, ein Singleton wie folgt zu verwenden:

public class DataBaseUtil {

private static FirebaseDatabase mDatabase;

public static FirebaseDatabase getDatabase() {
    if (mDatabase == null) {
        mDatabase = FirebaseDatabase.getInstance();
        mDatabase.setPersistenceEnabled(true);
    }
    return mDatabase;
}}

verwenden Sie es einfach in Ihrem Code und dann 

private FirebaseDatabase fdb = DataBaseUtil.getDatabase();
1
Musab Kurt

Für Kotlin Versuchen Sie folgendes:

class DatabaseUtil {

    companion object {
        private val firebaseDatabase: FirebaseDatabase = FirebaseDatabase.getInstance()

        init {
            firebaseDatabase.setPersistenceEnabled(true)
        }

        fun getDatabase() : FirebaseDatabase {
            return firebaseDatabase
        }
    }
}
0
Farhan Ar Rafi

Verschieben Sie einfach Ihren Code in ExampleFragment.class von der Methode onCreateView zur Methode 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);
0
Zamatto Koizumi

In Manifest

 Android:name=".AppName

Java-Klasse erstellen, die die Anwendung erweitert

public class AppName extends Application {

@Override
public void onCreate() {
    super.onCreate();
    FirebaseDatabase.getInstance().setPersistenceEnabled(true);

}
0
Pankaj Kudawala

Stellen Sie sicher, dass .setpersistenceenabled (true) nicht zweimal ausgeführt wird. Wenn Sie sich in Ihrem Fall bei Google anmelden, muss second care setPersistenceEnabled (true) aufgerufen werden, bevor eine Instanz von Firebase aufgerufen wird, die dieses Problem behebt.

0

Ich war mit demselben Problem konfrontiert. Ich habe den Code wie folgt geändert.

VOR (Absturz verursachen)

    var rootRef = FIRDatabase.database().reference()

    override func viewDidLoad() {
       super.viewDidLoad()
       FIRDatabase.database().persistenceEnabled = true
    }

NACH (gelöster Absturz)

var rootRef:FIRDatabaseReference!
override func viewDidLoad() {
 super.viewDidLoad()
   FIRDatabase.database().persistenceEnabled = true
   rootRef = FIRDatabase.database().reference()
}
0