skip to Main Content

I had it working with SQLite database but then when I tried to switch to Firebase Real-time Database it decided to start crashing on me… I’m completely lost on this one. Some help would be much appreciated.

Here is my Firebase data

Registered Users
xJnXFIRYehWTXq4oKTOEdEXGY4D3
dob: "5/7/2024"
gender: "Male"
mobile: "2042322553"

dailies
-Nztkpg1DjX9CvdYuH8b
dailyID: 0
info: "3x Guitar"
weekly: false

Here is my Fragment

package com.example.goalhero;

import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import static android.app.Activity.RESULT_OK;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

public class FragDailies extends Fragment {
    Button newDailyBtn;
    RecyclerView dailiesRecyclerView;
    RecyclerViewAdapterDailies adapter;
    final static int requestCodeForCreateNewDailyActivityCall = 2;
    ArrayList<DataDaily> dailies;
    private DatabaseReference dailiesDatabaseReference;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FirebaseDatabase database = FirebaseDatabase.getInstance();
        dailiesDatabaseReference = database.getReference("dailies");
        dailies = new ArrayList<>();
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_dailies, container, false);
        dailiesRecyclerView = rootView.findViewById(R.id.dailiesRecyclerView);
        dailiesRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        adapter = new RecyclerViewAdapterDailies(getContext(), dailies);
        dailiesRecyclerView.setAdapter(adapter);

        newDailyBtn = rootView.findViewById(R.id.launchCreateNewDailyActivityBtn);
        newDailyBtn.setOnClickListener(v -> {
            Intent intent = new Intent(getContext(), CreateNewDailyActivity.class);
            startActivityForResult(intent, requestCodeForCreateNewDailyActivityCall);
        });

        return rootView;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        loadDailiesFromFirebase();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == requestCodeForCreateNewDailyActivityCall && resultCode == RESULT_OK) {
            if (!data.getStringExtra("title").equals("")) {
                DataDaily curDaily = new DataDaily(
                        data.getBooleanExtra("mon", true),
                        data.getBooleanExtra("tues", true),
                        data.getBooleanExtra("wed", true),
                        data.getBooleanExtra("thurs", true),
                        data.getBooleanExtra("fri", true),
                        data.getBooleanExtra("sat", true),
                        data.getBooleanExtra("sun", true),
                        false,
                        data.getBooleanExtra("isEasy", true),
                        data.getStringExtra("title"),
                        data.getStringExtra("timeframe"),
                        data.getStringExtra("reps")
                );
                addDailyToFirebase(curDaily);
            }
        }
    }

    private void addDailyToFirebase(DataDaily daily) {
        dailiesDatabaseReference.push().setValue(daily)
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
                        Toast.makeText(getContext(), "Daily added successfully", Toast.LENGTH_LONG).show();
                    } else {
                        Toast.makeText(getContext(), "Failed to add daily", Toast.LENGTH_LONG).show();
                    }
                });
    }

    private void loadDailiesFromFirebase() {
        dailiesDatabaseReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                dailies.clear();
                for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
                    DataDaily daily = postSnapshot.getValue(DataDaily.class);
                    if (daily != null) {
                        daily.setDailyID(postSnapshot.getKey()); // Store the Firebase ID
                        dailies.add(daily);
                    } else {
                        System.out.println("DataDaily is null for snapshot: " + postSnapshot.getKey());
                    }
                }
                adapter.setDailies(dailies);
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                Toast.makeText(getContext(), "Failed to load dailies: " + databaseError.getMessage(), Toast.LENGTH_LONG).show();
                System.out.println("DatabaseError: " + databaseError.getMessage());
            }
        });
    }

    public void deleteDailyFromFirebase(DataDaily daily) {
        dailiesDatabaseReference.child(daily.getDailyID()).removeValue()
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
                        Toast.makeText(getContext(), "Daily deleted successfully", Toast.LENGTH_LONG).show();
                        dailies.remove(daily);
                        adapter.notifyDataSetChanged();
                    } else {
                        Toast.makeText(getContext(), "Failed to delete daily", Toast.LENGTH_LONG).show();
                    }
                });
    }
}

You might also want to look at the RecyclerViewAdapter


package com.example.goalhero;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

import java.util.ArrayList;
import java.util.Random;

public class RecyclerViewAdapterDailies extends RecyclerView.Adapter<RecyclerViewAdapterDailies.ViewHolder> {
    private ArrayList<DataDaily> dailies;
    private Context context;
    private DatabaseReference dailiesDatabaseReference;
    private boolean isUpdating = false;

    public RecyclerViewAdapterDailies(Context context, ArrayList<DataDaily> dailies) {
        this.context = context;
        this.dailies = dailies;

        FirebaseDatabase database = FirebaseDatabase.getInstance();
        dailiesDatabaseReference = database.getReference("dailies");
    }

    public void setDailies(ArrayList<DataDaily> dailies) {
        this.dailies = dailies;
        notifyDataSetChanged();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        private CheckBox dailyListItemCB;
        private TextView dailyTextView;
        private ImageView deleteImage;
        private RelativeLayout parent;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            parent = itemView.findViewById(R.id.parent);
            dailyListItemCB = itemView.findViewById(R.id.list_itemCB);
            dailyTextView = itemView.findViewById(R.id.textView);
            deleteImage = itemView.findViewById(R.id.imageViewDeleteDaily);
        }
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.dailies_list_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        final DataDaily currentDaily = dailies.get(position);

        holder.dailyListItemCB.setText(currentDaily.getInfo());
        if (currentDaily.getTimeFrame() != null && !currentDaily.getTimeFrame().isEmpty()) {
            holder.dailyTextView.setText(currentDaily.getTimeFrame());
        } else {
            holder.dailyTextView.setText("");
        }

        holder.dailyListItemCB.setChecked(currentDaily.isCompletedToday());

        holder.dailyListItemCB.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (!isUpdating) {
                currentDaily.setCompletedToday(isChecked);
                updateCompletionStatusInFirebase(currentDaily);

                Random random = new Random();
                int randomNumber = random.nextInt(10) + 1;
                if (randomNumber == 10 && context instanceof ActivityMain) {
                    ((ActivityMain) context).showPopupWindow();
                }
            }
        });

        holder.deleteImage.setOnClickListener(v -> deleteDailyFromFirebase(currentDaily));
    }

    @Override
    public int getItemCount() {
        return dailies.size();
    }

    private void updateCompletionStatusInFirebase(DataDaily daily) {
        isUpdating = true;
        dailiesDatabaseReference.child(daily.getKey()).setValue(daily)
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
                        Toast.makeText(context, "Status updated successfully", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(context, "Status update failed", Toast.LENGTH_SHORT).show();
                    }
                    isUpdating = false;
                });
    }

    private void deleteDailyFromFirebase(DataDaily daily) {
        dailiesDatabaseReference.child(daily.getKey()).removeValue()
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
                        dailies.remove(daily);
                        notifyDataSetChanged();
                        Toast.makeText(context, "Daily deleted successfully", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(context, "Failed to delete daily", Toast.LENGTH_SHORT).show();
                    }
                });
    }
}

Here is my data daily class…

package com.example.goalhero;

public class DataDaily {
    private String key; // This will store the Firebase key
    private String dailyID;
    private boolean mon, tues, wed, thurs, fri, sat, sun, completedToday, isEasy;
    private String title, timeFrame, reps;

    // Default constructor required for calls to DataSnapshot.getValue(DataDaily.class)

    public DataDaily(boolean mon, boolean tues, boolean wed, boolean thurs, boolean fri,
                     boolean sat, boolean sun, boolean completedToday, boolean isEasy,
                     String title, String timeFrame, String reps) {
        this.mon = mon;
        this.tues = tues;
        this.wed = wed;
        this.thurs = thurs;
        this.fri = fri;
        this.sat = sat;
        this.sun = sun;
        this.completedToday = completedToday;
        this.isEasy = isEasy;
        this.title = title;
        this.timeFrame = timeFrame;
        this.reps = reps;
    }

    public DataDaily() {}

    // Getters and setters for all member variables
    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }
    public boolean isMon() {
        return mon;
    }

    public void setMon(boolean mon) {
        this.mon = mon;
    }

    public boolean isTues() {
        return tues;
    }

    public void setTues(boolean tues) {
        this.tues = tues;
    }

    public boolean isWed() {
        return wed;
    }

    public void setWed(boolean wed) {
        this.wed = wed;
    }

    public boolean isThurs() {
        return thurs;
    }

    public void setThurs(boolean thurs) {
        this.thurs = thurs;
    }

    public boolean isFri() {
        return fri;
    }

    public void setFri(boolean fri) {
        this.fri = fri;
    }

    public boolean isSat() {
        return sat;
    }

    public void setSat(boolean sat) {
        this.sat = sat;
    }

    public boolean isSun() {
        return sun;
    }

    public void setSun(boolean sun) {
        this.sun = sun;
    }

    public boolean isCompletedToday() {
        return completedToday;
    }

    public void setCompletedToday(boolean completedToday) {
        this.completedToday = completedToday;
    }

    public boolean isEasy() {
        return isEasy;
    }

    public void setEasy(boolean easy) {
        isEasy = easy;
    }

    public String getDailyName() {
        return title;
    }

    public void setDailyName(String dailyName) {
        this.title = dailyName;
    }

    public String getTimeFrame() {
        return timeFrame;
    }

    public void setTimeFrame(String timeFrame) {
        this.timeFrame = timeFrame;
    }

    public String getRepetitions() {
        return reps;
    }

    public void setRepetitions(String repetitions) {
        this.reps = repetitions;
    }
public String getDailyID() {
    return dailyID;
}

public void setDailyID(String dailyID) {
    this.dailyID = dailyID;
}

public String getInfo() {
    return reps + "x " + title;
}

}

Here’s what I believe to be the error causing the application to stop working…

Error 1:
2024-06-09 14:09:55.550 7896-7896 RecyclerView com.example.goalhero E No adapter attached; skipping layout

Error 2:
2024-06-09 14:18:56.177 656-4713 AppOps system_server E noteOperation
java.lang.SecurityException: Specified package com.google.android.gms.location.history under uid 10108 but it is really -1
at com.android.server.appop.AppOpsService.verifyAndGetBypass(AppOpsService.java:3874)
at com.android.server.appop.AppOpsService.noteOperationUnchecked(AppOpsService.java:3030)
at com.android.server.appop.AppOpsService.noteOperationImpl(AppOpsService.java:3018)
at com.android.server.appop.AppOpsService.noteOperation(AppOpsService.java:3001)
at com.android.internal.app.IAppOpsService$Stub.onTransact(IAppOpsService.java:447)
at android.os.Binder.execTransactInternal(Binder.java:1159)
at android.os.Binder.execTransact(Binder.java:1123)

I’m completely lost here I just started using Firebase so I have no
idea… Also I’m a newbie to programming.

I don’t even know where to put debig statements so any help would be appreciated…

2

Answers


  1. Chosen as BEST ANSWER

    All I had to do was delete the current Firebase data because the DataDailies object changed. Now everything is working correctly.


  2. Calling postSnapshot.getValue(DataDaily.class); requires the DataDaily.java class to have a no-argument constructor.

    You can resolve this by adding public DataDaily(){} to DataDaily.java

    Check out the example in the official Firebase documentation

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search