Monday 6 January 2020

java - Updated global variables does not reflect inside ValueEventListener's onCancelled method

I am currently testing a ValueEventListener's onCancelled() method to implement proper firebase error management. I have succeeded thus far, onCancelled() was firing well. I have set-up the firebase rules for a specific node to return a permission denied error.



But I'm confused as to how global variables are managed inside the onCancelled() method. Why does it seem like global variables retain their default initial state when called inside onCancelled()? Updates on the variables from outside do not reflect when they're called inside this method but are reflected when called from onDataChange() and other in-Activity methods.




UPDATE NO. 2:
Inserted the firebase auth codes, added test flow execution. Also added the log outputs as suggested by @Doug Stevenson. From the logs, it seems onCancelled() was only called once (during app onCreate()). I think that's what gave me the wrong impression that currentSynId was never changed coz its value is still Hello!!! there, and I didn't look at the after-logs before.



But now I see there's a log W/RepoOperation: updateChildren at /2014 failed: DatabaseError: Permission denied that fires everytime R.id.btn_sync is called (and never again the log for onCancelled where the updated currentSyncId should be). Maybe I should rephrase my question? I would like to catch the instance where/when the current cancellations logs are fired. Thanks.



UPDATE NO. 1 I took out relevant pieces from the complete codes and replaced the previous snippets:




...


public class Demo extends AppCompatActivity {

// Database reference
private DatabaseReference mFirebaseMain2014;

//
private FirebaseAuth mAuth;

public String currentSyncId = "Hello!!!";


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);

// Initialize firebase auth
mAuth = FirebaseAuth.getInstance();
mAuth.addAuthStateListener(new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {

if(mAuth.getCurrentUser() != null) {
Log.d("MAIN", "A user was logged in: " + mAuth.getCurrentUser().getUid());
initDatabase(mAuth.getCurrentUser().getUid());
}


findViewById(R.id.btn_sync).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
syncData();

}
});

findViewById(R.id.btn_echovalue).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
printId();
}
});
}

});
}


/**
* Initialize database and listeners
* @param userid
*/
public void initDatabase(String userid){
Log.d("MAIN", "Initialized databases");

// Initialize database references
mFirebaseMain2014 = FirebaseDatabase.getInstance().getReference("2014");
mFirebaseMain2014.child("app_final/" + userid).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
// data processing here..
}

@Override
public void onCancelled(@NonNull DatabaseError databaseError) {

Log.d("MAIN-ON-CANCELLED-EVENT", "An error occurred while syncing data: " +
databaseError.getMessage() + "\n id: " + currentSyncId);
}
});
}


/**
* Initiate firebase syncing (which will lead to Permission-Denied
*/

public void syncData(){
// Log values
Log.d("MAIN", "Initiating sync...");
currentSyncId = "00001";

// Set the dummy data that will be sent to firebase
HashMap map = new HashMap();
map.put(currentSyncId, "Hello, world!");

// Sync dummy data to firebase

mFirebaseMain2014.updateChildren(map);

Log.d("MAIN", "Sync called.");
}


/**
* Print the contents of global currentSyncId
*/
public void printId(){

Log.d("MAIN", "PRINTING CURRENT id value: " + currentSyncId + ", userid: " + getAuthUserId());
}


public String getAuthUserId(){
return mAuth.getCurrentUser().getUid();
}
}



TEST FLOW




  1. Loaded the app

  2. Pressed the R.id.btn_echovalue button

  3. Pressed the R.id.btn_sync button

  4. Pressed the R.id.btn_echovalue button



LOG OUTPUT





D/FirebaseAuth: Notifying id token listeners about user ( WN1b3pJyggNOvaoHDdtPsHrFLmG3 ).
I/FirebaseInitProvider: FirebaseApp initialization successful
D/FirebaseApp: Notifying auth state listeners.
Notified 0 auth state listeners.
D/MAIN: A user was logged in: WN1b3pJyggNOvaoHDdtPsHrFLmG3
D/MAIN: Initialized databases
W/SyncTree: Listen at /2014/app_final/WN1b3pJyggNOvaoHDdtPsHrFLmG3 failed: DatabaseError: Permission denied
D/MAIN-ON-CANCELLED-EVENT: An error occurred while syncing data: Permission denied

id: Hello!!!
I/FirebaseAuth: [FirebaseAuth:] Loading module via FirebaseOptions.
[FirebaseAuth:] Preparing to create service connection to gms implementation
D/FirebaseAuth: Notifying id token listeners about user ( WN1b3pJyggNOvaoHDdtPsHrFLmG3 ).
D/FirebaseApp: Notifying auth state listeners.
Notified 1 auth state listeners.
D/MAIN: PRINTING CURRENT id value: Hello!!!, userid: WN1b3pJyggNOvaoHDdtPsHrFLmG3
D/MAIN: Initiating sync...
D/MAIN: Sync called.
W/RepoOperation: updateChildren at /2014 failed: DatabaseError: Permission denied

D/MAIN: PRINTING CURRENT id value: 00001, userid: WN1b3pJyggNOvaoHDdtPsHrFLmG3


The Log inside onCancelled() was firing well. I expect to see



MAIN: An error occurred while syncing data: Permission denied.
Sync ID: 0001


But instead, I see:




MAIN: An error occurred while syncing data: Permission denied.
Sync ID: Hello!!!


I need to keep track of the currentSyncId when the onCancelled() was fired so I can reset its local sync status references in the app to false.



I have looked for similar cases and questions but the closest threads I found are how to call onCancelled here and here, and a few references to onDataChange. I found an interesting answer by @vincrichaud here, but I'm not really sure if this is applicable to firebase android as well.



TIA!

No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...