So I'm working on a project designing a home automation app but Im constantly receiving an error I cant figure out after hours and hours of troubleshooting so alas I am posting here for any possible help. Basically I have a "quick access" screen (fragment) titled HomeFragment, with what should be live database readings (firebase). I then also have a dedicated fragment for each item on the HomeFragment. One of those fragments is called DoorFragment, used to read and set the status of what will be a hardware dedicated smart-lock. Currently when the user is on the DoorFragment and locks the door, the status is sent and stored on the database. On the HomeFragment there is a switch that does the same functionality. However my issue lies in when changing the status on one fragment and switching back to the other, it crashes the app when trying to read the current status. The status on the HomeFragment should update when the user locks the door on the DoorFragment and vice versa. I believe this is a simple fix, but I cant figure out how to get around this "not attached to context" error. The error is below, and I will paste a small portion of my code here if anyone can assist. Im not sure how much of the code you will need to see, but this should be enough to get the idea. The java classes are rather large in scope and to protect my source code I wont be posting the entire class, but willing to share more if needed.
Many thanks!!
Error
3:50:30.269 17278-17278/ca.future.home.it.secure.home.automation E/AndroidRuntime: FATAL EXCEPTION: main
Process: ca.future.home.it.secure.home.automation, PID: 17278
java.lang.IllegalStateException: Fragment HomeFragment{6a9b2dc} (dfc55d4f-39ec-4923-8878-eb2f963ce440) not attached to a context.
at androidx.fragment.app.Fragment.requireContext(Fragment.java:900)
at androidx.fragment.app.Fragment.getResources(Fragment.java:964)
at androidx.fragment.app.Fragment.getString(Fragment.java:986)
at ca.future.home.it.secure.home.automation.HomeFragment$1.onDataChange(HomeFragment.java:161)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75)
at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
HomeFragment.java
@Override
public void onViewCreated (View view, Bundle savedInstanceState){
//Door lock status in database
doorKey=dbID(true);
firebaseDatabase = FirebaseDatabase.getInstance();
databaseReference = firebaseDatabase.getReference(doorKey);
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
String doorStatus = snapshot.getValue().toString();
if(doorStatus.equals(getString(R.string.lock_status))){
lockSwitch.setChecked(true);
doorView.setVisibility(View.INVISIBLE);
}
else if(doorStatus.equals(getString(R.string.unlocked_status))){
lockSwitch.setChecked(false);
doorView.setVisibility(View.VISIBLE);
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
pressLock.setVisibility(View.INVISIBLE);
//Lock button
lockBtn.setOnClickListener(view14 -> {
lockBtn.setVisibility(View.INVISIBLE);
pressLock.setVisibility(View.VISIBLE);
//simulate button pressed
handler.postDelayed(() -> getParentFragmentManager().beginTransaction().replace(R.id.flFragment, MainActivity.doorFragment).commit(), 300);
//MainActivity.bottomNav.setSelectedItemId(R.id.door);
});
//Switches selected
//lock switch
lockSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
doorView.setVisibility(View.INVISIBLE);
databaseActivity.toDatabase(getString(R.string.lock_status));
//toDatabase(getString(R.string.lock_status));
} else {
doorView.setVisibility(View.VISIBLE);
toDatabase(getString(R.string.unlocked_status));
//databaseActivity.toDatabase(getString(R.string.unlocked_status));
}
});
}
public void toDatabase(String status){
dbID(false);
firebaseDatabase = FirebaseDatabase.getInstance();
databaseReference = FirebaseDatabase.getInstance().getReference().child((idKey));
databaseReference.setValue(status);
Map<String, Object> updateStatus = new HashMap<>();
updateStatus.put(getString(R.string.status),status);
databaseReference.updateChildren(updateStatus);
}
private String dbID(boolean retrieveKey){
userInfo.typeAccount();
time();
localKey=userInfo.userId;
personalKey=userInfo.idInfo;
if(localKey!=null){
key=localKey;
Log.d(TAG,key);
}
if(personalKey!=null) {
key= personalKey;
Log.d(TAG, key);
}
if(retrieveKey){
return idKey=key+getString(R.string.forwardslash)+getString(R.string.door_status)+getString(R.string.forwardslash);
}
idKey=key+getString(R.string.forwardslash)+getString(R.string.door_status)+getString(R.string.forwardslash);
return "";
}
@SuppressLint("SimpleDateFormat")
private void time(){
date = Calendar.getInstance().getTime();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
dateFormat = new SimpleDateFormat(getString(R.string.formatted));
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
strDate = dateFormat.format(date);
}
System.out.println("Converted String: " + strDate);
}
DoorFragment.java
doorLock.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
Toast.makeText(getActivity(), R.string.closedDoor, Toast.LENGTH_SHORT).show();
status.setText(R.string.lock);
locked.setVisibility(View.VISIBLE);
unlocked.setVisibility(View.INVISIBLE);
doorLock.setBackgroundResource(R.drawable.lock_border_green);
toDatabase(getString(R.string.lock_status));
//databaseActivity.toDatabase(getString(R.string.lock_status));
} else {
Toast.makeText(getActivity(), R.string.openDoor, Toast.LENGTH_SHORT).show();
status.setText(R.string.unlock);
unlocked.setVisibility(View.VISIBLE);
locked.setVisibility(View.INVISIBLE);
doorLock.setBackgroundResource(R.drawable.lock_border_red);
toDatabase(getString(R.string.unlocked_status));
//databaseActivity.toDatabase(getString(R.string.unlocked_status));
}
});
searched this error on google, contacted colleagues, tried to iniate objects of fragments with getContext, getApplicationContext, getApplication, created new interfaces and activities to call on to complete required action, all to no avail.