Reading Firebase data, onDataChange is never called
I am new to here, I am currently working on an application that works on the background and checks the processes in the phone if "com.igg.castleclash"
in processes. The list sets the value of lockclash to true and stores the data in Firebase. Everything works fine, but I cannot read data from Firebase using addValueEventListener
.
public class SensorService extends Service {
boolean castleclash = false;
DatabaseReference databaaseUsers;
public SensorService(Context applicationContext) {
super();
}
public SensorService() {
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
databaaseUsers.child("user1").addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
UsersData user = dataSnapshot.getValue(UsersData.class);
Log.i("user name", user.getName());
}
@Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w("Failed to read value.", error.toException());
}
});
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Intent broadcastIntent = new
Intent("uk.ac.shef.oak.ActivityRecognition.RestartSensor");
sendBroadcast(broadcastIntent);
}
public void startTimer() {
synchronized (this) {
while (true) {
try {
wait(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
databaaseUsers = FirebaseDatabase.getInstance().getReference();
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
final List<ActivityManager.RunningAppProcessInfo> runningProcesses = manager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo process : runningProcesses) {
if (process.processName.equals("com.igg.castleclash")) {
castleclash = true;
break;
} else {
castleclash = false;
}
}
UsersData user1 = new UsersData(castleclash, "name");
databaaseUsers.child("user1").setValue(user1);
}
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Any ideas why this isn't working?
source to share
There are several problems. Most importantly, this processing does not happen "in the background" as you might think. It works on the main thread. This is a common misunderstanding with the Services, described in the documentation :
What is a service?
Much confusion about the Service class actually revolves around the fact that it is not:
- The service is not a separate process. The service object itself does not imply that it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
- Service is not a thread. This does not mean that you have to do the work of the main thread (to avoid errors associated with an application error).
An IntentService is a convenient subclass of the Service for doing work from the main thread.
The cycle while(true)
c startTimer()
runs endlessly. The call addValueEventListener()
to is onStartCommend()
never executed, because it startTimer()
never returns.
Database change listeners run on the main thread. Since the main thread is blocked by the call wait()
, the callback onDataChange()
will fail (if the listener was added successfully).
Also, to check if your database entry failed in startTimer()
, add CompletionListener
. The most common cause of failure is access denied due to inappropriate security rules.
UsersData user1 = new UsersData(castleclash, "name");
databaaseUsers.child("user1").setValue(user1, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError == null) {
Log.d(TAG, "onComplete: success");
} else {
Log.e(TAG, "onComplete: failed", databaseError.toException());
}
}
});
source to share
Are you viewing this video from David East? https://youtu.be/lpFDFK44pX8 I am following his method and it helps a lot.
On the first line, you should write it like this:
DatabaseReference dbRef = FirebaseDatabase.getInstance (). getReference
Then you will need to declare a different DatabaseReference for each db in the console.
DatabaseReference moooww = dbRef.child ("nameOfYourDbValue");
The rest is shown in the video.
source to share