2017-03-17 3 views
0

は、次の例を考えてみましょう:Firebaseデータベース:クライアントがオフラインの場合は明らかにルールが適用されません。

私はtest/ノードに値を書いている、と私は唯一の「(新しい値)場合、書き込みを許可するルールを、設定しているが(古い値+ 1に等しいです。 ) "であり、newData.val() == data.val() + 1

test/ノードの初期値は0であるとします。

クライアントがオフラインになり、次のコマンドを実行した場合:彼は再びオンラインになったとき

testRef.setValue(1); 
testRef.setValue(2); 
testRef.setValue(3); 
testRef.setValue(4); 
testRef.setValue(5); 

はその後、値5は、データベースに書き込まれますが、私は理由を理解していません、5 != 0 + 1以降です。私はこれがローカルデータベースの以前の値のキャッシュのために起こったと思いますが、残念ながらそれは私が達成しようとしている結果ではありません。私はそれがデータベースのルールに従わないので、サーバーがその値を拒否したい。

これを達成する方法はありますか?

またはその他の回避策があり、私は次のように実装することができるように:

testRef.setValue(1);- >書き込み値ローカルデータベースへ - > - >チェック値がをオンラインデータベースの規則に従っている場合値がルールに従わない場合、またはオフラインになっていることを確認できない場合は、ローカルデータベースから値を削除してください。

答えて

0

私はあなたの質問に対して「オフライン」とはクライアントが接続していないことを意味します。私のテストでは、飛行機モードを有効にしてシミュレートしました。

Firebaseのオフライン機能については、user guideに記載されています。あなたの質問に重要であるが設けられて1つの詳細は以下のとおりです。

がFirebaseリアルタイムデータベースクライアントが自動的にあなたのアプリケーションがオフラインの間に実行されているすべての書き込み動作 のキューを保持します... アプリは、接続が回復すると、すべての操作はFirebase Realtime Databaseサーバ に送信されます。

この動作は、setValue()呼び出しに完了リスナーを追加する以下のコードを使用して確認できます。私のテストでは、デバイスを飛行機モード(オフライン)にし、コードを実行してから飛行機モードを無効にしてオンラインに戻しました。 setValue()ごとにログメッセージが生成され、接続が再確立されたときに書き込み操作がキューに入れられて送信されたことが確認されます。これは、書き込みがあなたの検証ルールを満たしている理由を説明しています。クライアントは最終値5で書き込み要求を1回送信せず、元の増分値で5回の要求を送信します。

testの値を最初に0にリセットせずにテストを再実行することで、ルールが機能することを確認できます。各書き込みは失敗します。

このコードでは、クライアントがオフラインで、セキュリティルールによって後で拒否されたときの変更をFirebaseクライアントがどのように処理するかを示します。オフラインの間、クライアントキャッシュに変更が加えられ、onDataChange()コールバックが新しい(検証されていない)値で起動します。その後、クライアントがオンラインになり、サーバーによって変更が拒否されると、onDataChange()は以前の値で再び発生します。

final DatabaseReference ref = FirebaseDatabase.getInstance().getReference("test"); 

ref.addValueEventListener(new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot dataSnapshot) { 
     Log.d(TAG, "onDataChange: test=" + dataSnapshot.getValue(Integer.class)); 
    } 
    @Override 
    public void onCancelled(DatabaseError databaseError) { 
     throw databaseError.toException(); 
    } 
}); 

final DatabaseReference.CompletionListener completionListener = 
     new DatabaseReference.CompletionListener() { 
    @Override 
    public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) { 
     if (databaseError == null) { 
      Log.d(TAG, "setValue() Success"); 
     } else { 
      Log.d(TAG, "setValue() Failed " + databaseError.getMessage()); 
     } 
    } 
}; 

ref.setValue(1, completionListener); 
ref.setValue(2, completionListener); 
ref.setValue(3, completionListener); 
ref.setValue(4, completionListener); 
ref.setValue(5, completionListener); 
+0

インターネット接続が不足しているため、ルールを検証できない場合は、個人的にローカルキャッシュから値を削除することをお勧めします。私が必要とする理由は、私が共同アプリケーションを開発しているためであり、いくつかのノードには1人以上のユーザーがアクセスできるからです。いずれにしても、インターネット接続がない場合、ローカルキャッシュから値を削除するための回避策がありますか?何かタイムアウトのようなもの? (サーバーが5秒間到達できない場合は、キャッシュから保留中のすべての書き込み/ローカル値を削除してください) – MScott

+0

AFAIK保留中の書き込みを削除するAPIはありません。Firebaser FvPからこの回答を参照してください:http://stackoverflow.com/a/34625545/4815718。あなたができることは、[接続状態を監視する](https://firebase.google.com/docs/database/android/offline-capabilities#section-connection-state)だけで、書き込みを許可することです接続時。 –

関連する問題