2016-05-25 2 views
30

Я создаю свое первое приложение Firebase. Одним из его требований является то, что он запускается, когда сеть недоступна. В руководстве Firebase указано:setPersistenceEnabled (true) crashes app

«Включение сохранения на диске позволяет нашему приложению сохранять все его состояние даже после перезапуска приложения. Мы можем включить жесткость диска только с одной строкой кода. FirebaseDatabase.getInstance().setPersistenceEnabled(true); С диска настойчивостью включен, наши синхронизированные данные и записи будут сохранены на диск через приложение перезагружается, и наше приложение должно работать без проблем в офлайновых ситуациях.»

Другим требованием является использование Google Вход в систему. Поэтому в моем MainActivity я проверяю, был ли пользователь подписан, если нет, я запускаю SignInActivity. (SignInActivity из примеров Firebase.) Работает SignInActivity, пользователь вошел в систему, и MainActivity запускается во второй раз. Теперь мое приложение падает на строку кода FirebaseDatabase.getInstance().setPersistenceEnabled(true); со следующим сообщением:

Звонки на setPersistenceEnabled() должна быть произведена до любого другого использования экземпляра FirebaseDatabase.

Теперь, если я перезапущу приложение, пользователь выполнил вход, SignInActivity не запущен, мое приложение работает нормально.

Любые предложения о том, как я избегаю этого сбоя после того, как пользователь запишет?

Поскольку я отправлял этот вопрос, я получил предложение переместить FirebaseDatabase.getInstance().setPersistenceEnabled(true); в мой «Класс приложения». Я получаю точно такой же результат ... SignInActivity запускается, заканчивается, и я получаю сбой на setPersistenceEnabled.

Ниже мой 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(); 
     } 
    } 

ответ

1

Я столкнулся некоторые проблемы тоже, но это мое временное решение для моего приложения.

Create BaseActivity расширяет AppcompatActivity и переопределяет onCreate, ставит setPersistenceEnabled.

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

И изменить MainActivity продлить BaseActivity

public class MainActivity extends BaseActivity 

EDIT:Follow @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(); 
     } 
    } 
} 
+0

Благодаря Chip ... единственное место, где setPersistenceEnabled существует в настоящее время в моем MainActivity это не называется в моей SignInActivity. – Loren

+0

Chip ... ваше предложение окружить setPersistenceEnable с помощью try/catch, а затем просто зарегистрировать ошибку и продолжить. Вы проверяли, сохраняются ли данные на локальном уровне? – Loren

+0

@Loren мое приложение падает только тогда, когда я закрываю и открываю снова, я думаю, что он все еще работает в автономном режиме, потому что я пытаюсь включить режим полета, и мои данные остаются в моем приложении. – Sucipto

22

Я столкнулся с аналогичной проблемой и с помощью статической переменной, казалось, разрешите проблему для меня. Таким образом, в первом мой код посмотрел что-то вроде этого

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

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

    //..code 
} 

и теперь он больше похож

static boolean calledAlready = false; 

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

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

    FirebaseDatabase database = FirebaseDatabase.getInstance(); 

    //..code 
} 

Надеется, что это помогает!

+0

Это работает, спасибо. – Sucipto

+0

не работает для меня – Borja

+1

Это сработало для меня. Mind 'calledAlready' должен быть статическим для работы. –

42

FirebaseApp инициализируется ContentProvider, так что он не инициализируется в момент вызова функцииCreate().

Получите ваш FirebaseDatabase как это:

public class Utils { 
private static FirebaseDatabase mDatabase; 

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

} 

Затем вызовите Utils.getDatabase() от любой деятельности, использовать базу данных.

Не забудьте поставить компиляции 'com.google.firebase: firebase-базы данных: ... в build.gradle

+0

это не работает для меня – Borja

+3

Я думаю, вы взяли это отсюда ... https://github.com/firebase/quickstart-android/issues/15 –

+0

Это работа для меня. –

1

решаемые его, сделав Справочной Firebase поле статического класса, как это :

public class MainActivity extends AppCompatActivity 

private static FirebaseDatabase fbDatabase; 

@Override 
    protected void onCreate(Bundle savedInstanceState) { 

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

Это не проблема для создания новых Firebase ссылок (без setPersistenceEnabled (истина)) в других видах деятельности тоже.

0

Я столкнулся с той же проблемой. Я изменил код, как показано ниже.

ДО (Причинение Крушения)

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

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

ПОСЛЕ (Решено Крэш)

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

Я исправил это исключение с помощью setPersistenceEnabled (истинного) в своем классе приложений.

public class MApplication extends Application { 

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

В Manifest.xml, установите имя приложения в качестве MApplication:

<application 
    android:name=".MApplication" 
    ... /> 
+0

Просто скопируйте и прошёл –

+3

Это правильный ответ и должен быть отмечен как принятый. – flame3

+2

И не забудьте добавить файл манифеста: D –

11

я немного поздно, но сегодня я получил эту проблему, я решил, добавив

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

к моей деятельности

+0

Упрощенный и самый эффективный ответ! –

1

Если вам не нравятся статические поля, это сделало трюк для меня:

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

Это может быть вызвано тем, что один процесс инициализируется дважды с использованием firebase или Multidex. Для получения дополнительной информации см это: https://github.com/firebase/quickstart-android/issues/15

-1

Сообщение об ошибке описывает проблему:

звонки в setPersistenceEnabled() должны быть сделаны прежде, чем любое другое использование экземпляра FirebaseDatabase.

Исправление этой проблемы описано в документации: Как и в SDK 2.x, сохранение на диске должна быть включена другие вызовы к базе данных сделаны.

FirebaseDatabase.getInstance().setPersistenceEnabled(true);

https://firebase.google.com/support/guides/firebase-android

1

Для меня это легче обрабатывать, создавая отдельный класс для Firebase. Это связано с тем, что Firebase имеет свой собственный экземпляр, и если вы используете его в нескольких действиях, есть вероятность, что он сработает, если вы снова вызовеете setPersistenceEnabled в другом действии.

Другое дело, что при необходимости вы можете передать свой контекст или параметры в конструктор FirebaseHandler. Или, если у вас есть фиксированное местоположение в базе данных, их можно легко назвать без шаблона .child («location»).

Пример:

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

Это тогда может быть вызвана в любой деятельности, как показано ниже.

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

Вы можете использовать:

FirebaseDatabase.getInstance().setPersistenceEnabled(true); 

FirebaseDatabase.getInstance().getReference(); перед использованием

+0

Кажется, что 'setPersistenceEnabled' уже вызывается перед' FirebaseDatabase.getInstance(). GetReference() 'в коде исходного вопроса ... я не понимаю ваш ответ? – BalinKingOfMoria

0

В Menifest

android:name=".AppName 

Создание класса Java, который расширяет приложение

public class AppName extends Application { 

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

} 
0

Я бы не рекомендовал использовать приложение для хранения данных, так как его написано в CodePath

Существует всегда данные и информация, необходимые во многих местах в вашем приложении. Это может быть токен сеанса, результат дорогостоящего вычисления и т. Д. Возможно, возникает соблазн использовать экземпляр приложения, чтобы избежать накладных расходов на передачу объектов между действиями или сохранение их в постоянном хранилище.

Однако вы никогда не должны хранить изменяемые данные экземпляра внутри объекта Application, потому что, если вы предполагаете, что ваши данные останутся там, ваше приложение неизбежно сбой в какой-то момент с помощью исключения NullPointerException. Объект приложения не гарантированно останется в памяти навсегда, он будет убит. Вопреки распространенному мнению, приложение не будет перезапущено с нуля. Android создаст новый объект приложения и начнет действие, в котором пользователь раньше был, чтобы представить иллюзию, что приложение никогда не было убито в первую очередь.

Вот причины, я бы рекомендовал использовать в Singleton, как это:

public class DataBaseUtil { 

private static FirebaseDatabase mDatabase; 

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

просто использовать его в коде, тогда как

private FirebaseDatabase fdb = DataBaseUtil.getDatabase(); 
0

Создайте класс Util.java

и добавить следующий код

public class Util { 

     private static FirebaseDatabase mData; 

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

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


} 

Теперь заменяйте FirebaseDatabase.getIntance() на Util.getDatabase() каждый раз в каждом действии. Вызов один раз получит ошибку!

0

Удостоверьтесь, что .setpersistenceenabled (true) не происходит дважды, в то время как вы входите в Google в вашем случае, вторая помощь setPersistenceEnabled (true) должна быть вызвана до того, как любой экземпляр firebase назвал это решением моей проблемы.

0

Для Котлин Попробуйте это:

class DatabaseUtil { 

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

     init { 
      firebaseDatabase.setPersistenceEnabled(true) 
     } 

     fun getDatabase() : FirebaseDatabase { 
      return firebaseDatabase 
     } 
    } 
}