IllegalStateException while casting context - java

I am trying to cast an activity to a FragmentActivty object so I could get FragmentManager object
public class Main extends ListActivity {
...
public void showTimePickerDialog(View v) {
FragmentActivity myContext=(FragmentActivity) getApplicationContext(); //Here: java.lang.IllegalStateException: Could not execute method of the activity
FragmentManager fragManager = myContext.getFragmentManager();
DialogFragment newFragment = new uSharedUtility.TimePickerFragment();
newFragment.show(fragManager, "timePicker");
}
}
But when doing it I get:
java.lang.IllegalStateException: Could not execute method of the activity
I cant use getFragmentManager directly because my activity extends from ListActivity which is very necessary.
Please suggest me to get around this error, i really need to use both ListAdapter & Date/Time pickers in the same activity.

I cant use getFragmentManager directly because my activity extends from ListActivity which is very necessary.
It isn't necessary. You can have a ListView in any activity.
Since you're already using fragments, consider using a ListFragment with a FragmentActivity.

You can't cast Application Context to Activity, you must need Activity Context.
(FragmentActivity) getApplicationContext() // Not Possible
getContext(): Returns the context the view is currently running in. Usually the currently active Activity.
getApplicationContext(): Returns the context for the entire application (the process all the Activities are running inside of). Use this instead of the current Activity context if you need a context tied to the lifecycle of the entire application, not just the current Activity.

Related

How do I set a ClickListener in a Activity to a Button that belongs to a Fragment? (Android studio Java)

i need some help. I'm making an app on android studio and I have a Button initialized in a Fragment. I need to call this button in another Activity and set a click listener on it.
The problem is that when I do this I get the .NullPointerExceptionError and it says that the value of the object is null.
Now i tried to initialize the button in both my fragment and Activity but I keep getting that error and the app crashes.
I need some help to call this button from the Fragment. Maybe my question is similar to some other but it's hours that I'm searching a solution to this problem and I found nothing.
Thanks in advance for all your help
Since the button is part of the fragment, it only fits that any interactions/modifications to the button be defined in the Fragment's scope itself.
There are 2 ways to go about it:
Create the click listener in the Fragment itself and navigate to another activity from there.
Create an interface which your activity implements and the fragment has an instance of that interface. On the button click, call the interface's method. That would give you control in the activity which is hosting the fragment.
MyActivity extends AppCompatActivity implements MyClickListener {
void onMyButtonClick() {
// Navigate to another activity here
}
}
MainFragment extends Fragment {
private MyClickListener listener;
void onAttach(Context context) {
listener = (MyClickListener) context;
// Now call listener.onMyButtonClick() from button's on click listener.
}
}
interface MyClickListener {
void onMyButtonClick();
}

I am trying get back to previous activity but i get my menu activity

this is my main activity---(1)
enter image description here
here activity I want to go back to---(2)
enter image description here
here from where i want back---(3)
enter image description here
why when I use in previous btn I get my main activity and also when I make a btn to get previous I get my main activity
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
updateUI();
}
});
}
private void updateUI() {
Intent regTrip = new Intent(getApplicationContext(), regTrip.class);
startActivity(regTrip);
finish();
}
You can try to create a new Intent, but instead of using Application Context, try using the name of the current activity you are in. For example, if the name of the current Activity was 'NewActivity', you would say:
startActivity(new Intent(NewActivity.this, regTrip.class));
This would take you from the 'NewActivity' page to the 'regTrip' page.
Also you can just try adding onBackPressed() inside of your onClickListener. This is the built in method by android which is run when the user presses the back button on their phone. This means that when the user presses your back button, they are essentially doing the same thing as pressing the back button on their phone.
Toast and Intent, both requires reference to context. And getApplication, getApplicationContext, LoginActivity.this and getBaseContext, they all offer reference to the context.
Now the thing confuses is the declaration of different contexts and their specific-usage. To make things simple, you should count two types of context available in the Android framework.
Application Context
Activity Context
Application context is attached to the application's life-cycle and will always be same throughout the life of application. So if you are using Toast, you can use application context or even activity context (both) because a toast can be raised from anywhere with in your application and is not attached to a window.
Activity context is attached to the Activity's life-cycle and can be destroyed if the activity's onDestroy() is raised. If you want to launch a new activity, you must need to use activity's context in its Intent so that the new launching activity is connected to the current activity (in terms of activity stack). However, you may use application's context too to launch a new activity but then you need to set flag Intent.FLAG_ACTIVITY_NEW_TASK in intent to treat it as a new task.
Now referring to your cases:
LoginActivity.this though its referring to your own class which extends Activity class but the base class (Activity) also extends Context class, so it can be used to offer activity context.
getApplication() though its referring to Application object but the Application class extends Context class, so it can be used to offer application context.
getApplicationContext() offers application context.
getBaseContext() offers activity context.
Go for activity context when using Intent and for toast you can use any context.

Communication Between Two Android Activities via Reference to Caller or Callee

I have two activities Activity A and Activity B inside of the same application and they need to be able to call methods on each other. A needs to communicate to B at the start (possibly see "code" below).
B will call a lot of methods on A (this means that I cannot use the startActivityForResult method for communication because this would close B (Activity B is a Bluetooth Client and Server because it is a Peer to Peer app)). I do use startActivityForResult to start B for more of a kill signal than anything as the result.
Activity A uses a SupportMapFragment and Activity B cannot be a fragment because I want to be able to switch from B to A and then never use B again.
Originally, I started with one activity and tried switching between views using a ViewFlipper and just a call to setContentView(R.layout.my_layout_A) or setContentView(R.layout.my_layout_B). The fragment of course caused a lot of problems for both.
Using Fragments were confusing. The SupportMapFragment is the code for a Google Map which is a Fragment.
When I click a menu option inside of the MapsActivity (Activity A), I would like to be able to start myBluetoothActivity (Activity B) with a reference to the MapsActivity (Activity A) OR start myBluetoothActivity and then be able to set a reference to the caller inside of myBluetoothActivity (but this option would require having a reference to the BluetoothActivity inside of the MapsActivity or having some way to obtain the started activity from the intent).
//the following code is in Kotlin, but this can easily be converted over to java:
//option A: (pass it inside of the constructor)
var mbta:myBluetoothActivity = myBluetoothActivity(this)
//line for intent that I am unsure of
//intent so that I can start the activity with the pointer to the caller already passed into the new activity
startActivity(mbta)
//option B: (set this reference after obtaining a reference from intent):
var mintent:Intent = Intent(this.applicationContext, myBluetoothActivity::class.java)
startActivity(mintent)
//obtain the reference to the BluetoothActivity from the intent (NOT SURE HOW TO DO THIS???)
mbta.setCallerReference(this)
How can I accomplish this communication between the two activities via reference between the two activities? Should I use an interface for communication? If I should use it, (which I did try) how should I?
In other words, I am trying to access the caller activity (Activity A) from (Activity B) directly via a reference to Activity A inside of B OR trying to get the reference to B from the intent that started it inside of Activity A. I am trying to get a reference to that, so I can use it for communication/method calling/member variable and UI modification purposes.
NOTES: 1. The BluetoothActivity and the MapsActivity are NOT SERIALIZABLE. I tried serializing it and then adding it to the extras Bundle in the Intent and it just crashed saying that that was impossible to serialize due to BroadCastReciever. As this also deals with WIFI. Which I am highly considering separating out to be put with the BluetoothActivity in a future release.
I am also ASSUMING that Activity B will never just be started up by anything other than my MapsActivity class.
I am also new to Kotlin, but I know Java.
When I tried using an interface, I caused a StackOverflow error and I have no idea why.
I have read the documentation for Intents on the website.
I have done some research on here which gave me those ideas above. I am not sure how to implement them.
You are using the wrong approach. The solution requires a bit more work than you would think. The correct approach is to:
First, realize that these activities Activity A and Activity B (and any other activities) are activities that are specific to your application and you want to establish direct communication between them.
Second, realize that you are trying to get the current (or a previous) activity's context. The context will help serve the reference.
Third, you can create your own Activity and Application classes by extending the desired classes. The Application class is a low-level class used for the activities.
From here, you will be able to make use of the getApplicationContext() which will return your custom Application class.
Design: It is inside of your CustomApplication class that you must track the references to the activities that you want. From there all that you have to do is cast the getApplicationContext() to your CustomApplication class and then call your methods that access the Activity(ies). You must of course cast your Activities if you want to access certain instances of a specific activity that you created to its "type." For example:
MapsActivity mact = (MapsActivity)(((MyApplication)(this.getApplicationContext())).getCurrentActivity())
You must of course note that this activity must be already created (the onCreate method was already called) for this to return the current activity. The same of course goes for the other life-cycle methods for the activity as you will make a baseActivity which will deal with these as well as you will also have an Application life-cycle that will help deal with this too.
To answer the question: "How to get the current foreground activity context in android?" I turned to StackOverflow and found user: gezdy 's answer to be exactly what I needed at: How to get current foreground activity context in android?.
(BEGIN QUOTATION FROM: GEZDY)
You should manage activities references. Add the name of the
application in the manifest file :
<application
android:name=".MyApp"
....
</application>
Your application class :
public class MyApp extends Application {
public void onCreate() {
super.onCreate();
}
private Activity mCurrentActivity = null;
public Activity getCurrentActivity(){
return mCurrentActivity;
}
public void setCurrentActivity(Activity mCurrentActivity){
this.mCurrentActivity = mCurrentActivity;
}
}
Create a new Activity :
public class MyBaseActivity extends Activity {
protected MyApp mMyApp;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMyApp = (MyApp)this.getApplicationContext();
}
protected void onResume() {
super.onResume();
mMyApp.setCurrentActivity(this);
}
protected void onPause() {
clearReferences();
super.onPause();
}
protected void onDestroy() {
clearReferences();
super.onDestroy();
}
private void clearReferences(){
Activity currActivity = mMyApp.getCurrentActivity();
if (this.equals(currActivity))
mMyApp.setCurrentActivity(null);
}
}
So, now instead of extending Activity class for your activities, just
extend MyBaseActivity. Now, you can get your current activity from
application or Activity context like that :
Activity currentActivity = ((MyApp)context.getApplicationContext()).getCurrentActivity();
(END OF QUOTATION FROM: GEZDY)
Note: All code is written in java for this answer.

Custom Listview not responding to listener after activity destroyed

I have a BaseActivity that takes care of Fragment transitions by acting as the central controller for it's Fragment's touch listeners. One of the Fragment is a custom Listview that will cause the BaseActivity to display a new Fragment when tapped. This works when the Activity is created from scratch, but I have a problem with it when the activity is destroyed (through the Dev options "Don't Keep Activities", or through memory cleanup).
I have verified through logs that I am setting the Fragment's listener when the activity starts up from being destroyed, but tapping on the Listview doesn't transition to a new Fragment. I also tried to see if it was a focusing issue but putting android:descendantFocusability="blocksDescendants" in the Listview layout xml also doesn't solve the issue.
The listener is set when I create the fragment and it is the first fragment the activity instantiates when it starts up. Any insights would be appreciated!
I'll add a answer to be easier to help you. The first thing is that you listener should be set inside fragment's onAttach:
#Override
public void onAttach(Context context) {
// here, your context is also your activity
super.onAttach(context);
if (context instanceof YourListener) {
this.fragmentListener = (YourListener) context;
}
}
Please change this and check if something changed!

Pass a String from a Fragment to another Fragment

I have the following model.
A TabFragment which extends Fragment.
A ListFragment which extends Fragment.
And a DetailFragment which extends Fragment.
TabFragment hosts ListFragment which will launch a DetailFragment.
When I call getActivity().setResult(Activity.RESULT_OK, i); from DetailFragment, onActivityResult is called, but only in TabFragment. I pass from Detail Fragment, one String identifier to TabFragment.
My only problem is that I would like to pass this String from TabFragment back up to ListFragment.
What is the best way to do this?
You can find a fragment you need with FragmentManager's findFragmentById() or findFragmentByTag() where id/tag is one you use whan you add a fragment. After that you can interact with this particular fragment.

Categories