I have an activity which is a container for several fragments. One of the fragments starts another activity and from the second activity I want to send some data to one of the fragments. How can I do that? Basically the first activity stays beyond the second one and one of the EditViews will be updated with a new value when the second activity closes. I could've used an intent but how can I send it if the activity is already started? Thank you.
You would need to start your second activity using startActivityForResult(). In your second activity before you finish it, you need to add the data to a bundle pass this to an intent and then set the result to the intent.
Bundle bundle = new Bundle();
bundle.putString("myData", "myValue");
Intent intent = new Intent();
intent.putExtra(bundle);
setResult(intent, 0);
finish();
And then in activity 1 there should be an onactivityresult method which retrieves the value from the intent and sets it where you want in your fragment
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Bundle bundle = data.getData();
string value = bundle.getString("myData");
}
I'm not sure if I have it exactly right as remembering it at the top of my head but should be enough to get you started I think.
If you want to pass data back to its containing activity from your fragment, can do it by declaring an interface handler and through that interface pass the data. And ensure your containing activity implements those interfaces.
For example: In your fragment, declare this interface as follows :
public interface CallBackInterface {
public void onCallBack(String param);
}
//Declare this interface in your fragment
CallBackInterface callBk;
#Override
public void onAttach(Activity a) {
super.onAttach(a);
callBk= (CallBackInterface ) a;
}
Within your fragment, when you need to handle the passing of data, just call it on the "callBk " object:
public void callBack(String param) {
callBk.onCallBack(param);
}
Finally, in your containing activity which implements CallBackInterface ...
#Override
public void onCallBack(String param) {
Log.d("TAG","hi " + param);
}
Related
I have two activities says Activity A and Activity B.
Activity A contains Fragments AF1,AF2.
Activity B contains Fragments BF1,BF2.
Currently I am in AF1.
How can we pass data(bundle) from AF1 to AF2?
How can we pass data (bundle) from AF1 to BF2?
The first approach is to use interfaces. Here is a breakdown of the steps:
Create an interface in your AF1 fragment - a method in that interface will be called and the data passed back through the arguments passed to it. In your activity, you implement that interface and override the method. Once the method is called, you could create another method in AF2 which you can easily call and pass the corresponding values.
The above described process has been shown in this tutorial: how to communicate between fragments and activities
FragmentOne.java
public class FragmentOne extends Fragment{
private Activity activity;
#Override
public void onAttach(Activity act){
super.onAttach(act);
activity = act;
}
#Override
public View onCreateView(..........){
/* somethind was clicked here*/
try{
((OnSomethingClickedListener) activity).updateActivity(position);
}catch(ClassCastException e){}
return view;
}
public interface OnSomethingCllickedListener{
void updateActivity(int position);
}
}
In your activity, implement the interface and override the method above:
public class ActivityOne extends Activity implements FragmentOne.OnSomethingCllickedListener{
#Override
public void onCreate(Bundle saveInstanceState){
/* as usual here */
}
#Override
public void updateActivity(int position){
/* call FragmentTwo's method here to update the view based on the position of item clicked here*/
FragmentTwo.updateView(position);
}
}
Secondly, to decouple your activities from your fragments, use EventBus library. This is quite simple and goes like this:
Download the jar file and add it to your project.
Create an Event class
Register for Events in your activities (unregister inside onDestroy)
When you want to notify the activity of the events, just call EventBus' post method and pass back the respective data.
Inside your activity, you need a method onEvent(YourEventClassName event) then you can pass the values respectively to your fragments as needed.
I hope this helps.
Code to pass and retrieve data:
Bundle bundle =new Bundle();
bundle.putString("message", message);
Frag1 _fragment = new Frag1();
fragmentTransaction.replace(android.R.id.content, _fragment);
fragmentTransaction.commit();
Bundle bundle=getArguments(); //get data
if(bundle!=null)
{
message=bundle.getString("message") ;
}
This might have already answered but I am still troubling with a function like this. Let's say I have activity A and activity B. B holds a viewpager with several fragments in it. I would like to call a function in the fragment held by activity B from activity A.
I used callbacks many times to communicate between activites and fragments but every single time it was only the fragment and its holder activity. I do not want to make a static method (the callback listener cannot be static anyway) so it causes a headache for me. The simple static solution to make a static method in the fragment and have it called from the other actually works very well, but I am not sure if it was a good idea as I need to change several things static.
So communicating between Activity B and its fragments is ok, but I cannot call this method in Activity A.
Activity B:
public class ActivityB extends FragmentActivity implements Fragment1.OnWhateverListener
{
...
#Override
public void onWhateverSelected(int position) {
//stuff, here I can call any function in Fragment 1
}
}
The following code snippet is a wrong solution (doesnt even work) but makes a better picture what I would like to do.
Activity A:
ActivityB ab = new ActivityB ();
ab.onWhateverSelected(number);
So how can I do this?
Thank you!
EDIT
Activity A: the method I call
Bundle args = new Bundle();
args.putString("ID", id); // the data to send
Intent frag_args = new Intent(Intent.ACTION_VIEW);
frag_args.setClass(this, MainActivity.class);
frag_args.putExtra("args", args);
startActivity(frag_args);
Activity B:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
...
processIntent(getIntent()); //last line of onCreate, always gets called here
}
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
processIntent(intent); // this never gets called here only in OnCreate
}
private void processIntent(Intent intent) {
Bundle args = intent.getBundleExtra("args");
if (args != null) { // check if ActivityB is started to pass data to fragments
String id = args.getString("ID");
Log.i("ID_FROM", "id: " + id); //works well
if (id != null) {
List<Fragment> fragments = new ArrayList<Fragment>();
fragments = getSupportFragmentManager().getFragments();
//NULLPOINTER for the following line
FragmentMainDiscover fr = (FragmentMainDiscover) fragments.get(0);
fr.RefreshHoverView(id);
}
}
}
You are right to stay away from statics. Way too risky, for visual objects that may or may not be on screen.
I would recommend going through activity B, since it is the parent of your target fragment. Create an Intent that starts activity B, and include an intent extra that tells activity B what it should do to the target fragment. Then activity B can make sure that the fragment is showing, and pass the information on to it.
One other idea to pass the info to the fragment is to use setArguments, rather than direct calls. This is a nice approach because Android will restore the arguments automatically if the activity and its fragments are removed from memory.
Does this make sense? Do you want the code?
EDIT
To use arguments, you still need to have activity A go through activity B. This is because activity A doesn't know if activity B, and all its fragments, is running unless it sends it an Intent. But you can include data targeted for the fragments, by putting them inside the intent. Like this:
public class ActivityA extends Activity {
public static final String KEY_FRAG = "frag"; // tells activity which fragment gets the args
public static final String KEY_ARGS = "args";
public static final String KEY_MY_PROPERTY = "myProperty";
public void foo() {
Bundle args = new Bundle();
args.putString(KEY_FRAG, "frag1Tag"); // which fragment gets the data
args.putCharSequence(KEY_MY_PROPERTY, "someValue"); // the data to send
// Send data via an Intent, to make sure ActivityB is running
Intent frag_args = new Intent(Intent.ACTION_VIEW);
frag_args.setClass(this, ActivityB.class);
frag_args.putExtra(KEY_ARGS, args);
startActivity(frag_args);
}
}
public class ActivityB extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//TODO configure activity including fragments
processIntent(getIntent()); // this call is in case ActivityB was not yet running
}
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
processIntent(intent); // this call is in case ActivityB was already running
}
private void processIntent(Intent intent) {
Bundle args = intent.getBundleExtra(ActivityA.KEY_ARGS);
if (args != null) { // check if ActivityB is started to pass data to fragments
String fragTag = args.getString(ActivityA.KEY_FRAG);
if (fragTag != null) {
Fragment frag = getSupportFragmentManager().findFragmentByTag(fragTag);
frag.setArguments(args);
//TODO either show the fragment, or call a method on it to let it know it has new arguments
}
}
}
}
public class Fragment1 extends Fragment {
public static final String TAG = "frag1Tag";
#Override
public void onResume() {
super.onResume();
Bundle args = getArguments();
String value = args.getString(ActivityA.KEY_MY_PROPERTY);
...
}
}
On a click of a button within a fragment, is it possible to close the two fragments within the same activity and return the result of the fragment to another activity? One fragment is expecting input while the other fragment has information for the user to view and is not expecting input.
Also, my code worked prior to using fragments in the activity, however the fragments are no longer showing up when clicking the intent to go to the activity (NextActivity.class) that holds the fragments...does any happen to know why the fragments are not appearing?
Here is some of my code below
A piece from the original activity:
public class MessageList extends ListActivity {
private void createMessage() {
Intent i = new Intent(this, NextActivity.class);
startActivityForResult(i, ACTIVITY_CREATE); //this line is incorrect, right?
}}
Here is a snippet from a fragment class:
public class MessageEditorFragment extends Fragment {
confirmButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
getActivity().finish();
}}
Also here is the activity class that holds the fragments, just incase you want a look:
public class NextActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab one = actionBar.newTab().setText("Message Editor");
Tab two = actionBar.newTab().setText("Information");
one.setTabListener(new MyTabListener(new MessageEditorFragment()));
two.setTabListener(new MyTabListener(new InformationFragment()));
actionBar.addTab(one);
actionBar.addTab(two);
}
public class MyTabListener implements TabListener{
Fragment fragment;
public MyTabListener(Fragment f){
fragment = f;
}}}
I deeply appreciate all and any help!! Please let me know if you need to see more code as well.. Thank you :)
When the Activity is destroyed by calling finish , both the fragments will be destroyed/closed.
So, Before you finish the Activity from fragment, you can pass the values to the Activity which started it.
When you start the Activity , You need to start the Activity for Result , to return back the result data from the Fragment/Activity
In your Activity declare a integer request code
int FRAGMENT_REQUEST_CODE = 1000;
Start the activity , as per your logic
Intent intent = new Intent(this,MainActivityEx.class);
startActivityForResult(intent, FRAGMENT_REQUEST_CODE);
Add a callback method onActivityResult to receive the result
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == FRAGMENT_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
TextView textView = (TextView)findViewById(R.id.textView1);
textView.setText(data.getExtras().getString("DATA"));
}
}
}
Now. In your Fragment, When you close the two Fragments , You can pass the data back to the caller Activity
Intent intent = new Intent();
intent.putExtra("DATA","Hai");
getActivity().setResult(Activity.RESULT_OK,intent);
getActivity().finish();
When The user Click on the button it want to call the dialog- that dialog contain list of product in ListView.After user slect the product it should come to previuous activity.
I have done using startActivityForResult ().
There aresome issue.My calling activity is in normal tab activity that normal tab activty in Tab Activity Group.
Actualy i want to do in drrop down(Spinner).In my scanerio i couldn't get context.It awalys give Android Spinner Error : android.view.WindowManager$BadTokenException: Unable to add window
So I have change to my design like this: When User click buttion it load the list of product in ListView.After pick the product, it come back to previous activity.
This is my previous question : link
Here calling activity:
//Click Product button
l_prod.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent showContent = new Intent(LineDiscountActivity.this,ListProductActivity.class);
Bundle bundle = new Bundle();
bundle.putString("Activity", "LineDiscountActivity");
bundle.putString("RetailerName", retailerName);
bundle.putString("RetailerCode", retailerCode);
showContent.putExtra("discountProduct", discountList);
showContent.putExtras(bundle);
getParent().startActivityForResult(showContent, 5);
}
});
And my receiver activity :
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Object o = this.getListAdapter().getItem(position);
String book = o.toString();
Intent i = new Intent();
Bundle bundle = new Bundle();
bundle.putString("Activity", "ListProductActivity");
bundle.putString("RetailerName", retailerName);
bundle.putString("RetailerCode", retailerCode);
bundle.putString("seletcedProductCode", products.get(position).getProductCode());
bundle.putString("seletcedProductName", products.get(position).getDescription());
bundle.putDouble("seletcedProductQty", products.get(position).getAvailableQuantity());
i.putExtra("discountProduct", discountList);
i.putExtras(bundle);
if (getParent() == null) {
setResult(Activity.RESULT_OK, i);
} else {
getParent().setResult(Activity.RESULT_OK, i);
}
ListProductActivity.this.finish();
}
And calling activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// super.onActivityResult(requestCode, resultCode, data);
Log.i("-requestCode from LineDisocunt--" ,"" + requestCode);
}
I have written this code(onActivityResult) in calling activity & Tab main Activty also.
I didn't go anywhere..
onActivityResult mehtod.But it didn't go it.
What is wrong in my code.
Please let me know if anybody know this...
Thanks in advance
I have same issue when I was using startActivityForResult() with activity group.
your activity result will go to your activity group.You will not get activity result in your first activity
So you can solve this issue by taking one public static object in your first activity and when you call second activity you have to assign your first activity object from second activity.and then finish second activity so that your first activity will resume and you can update your ui by overriding onResume() method in first activity.You have to check validation weather your object is assigned or not.
For example
You have one static object product in your first activity
First Activity
public static Product product;
start second activity
startactivity(this, SecondActivity.class);
don't finish First Activity
You have to override onResume() method and then you can use product object which is assigned by second activity
second activity
FirstActivity.product.setName(name);
FirstActivity.product.setPrice(price);
After assign the product object you have to finish second activity
like
finish()
EDIT
I got the solution for your issue of badTokenException
Here is the solution
CLICK HERE
Suppose I have a class first.java (activity class) and I start another activity in this class (second.java - activity class).
How can I access the instance of first.java from second.java?
Can someone give me a good explanation on this... An example would be great...
If you need your second activity to return some data to your first activity I recommend you use startActivityForResult() to start your second activity. Then in onResult() in your first activity you can do the work needed.
In First.java where you start Second.java:
Intent intent = new Intent(this, Second.class);
int requestCode = 1; // Or some number you choose
startActivityForResult(intent, requestCode);
The result method:
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
// Collect data from the intent and use it
String value = data.getString("someValue");
}
In Second.java:
Intent intent = new Intent();
intent.putExtra("someValue", "data");
setResult(RESULT_OK, intent);
finish();
If you do not wish to wait for the Second activity to end before you do some work in the First activity, you could instead send a broadcast which the First activity reacts to.
You can simply call getParent() from the child activity.
I have no clue why other answers are so complicated.
Only this should work
class first
{
public static first instance;
oncreate()
{
instance = this;
}
}
first.instance is the required thing that is accessible from the second class
try this if this work 4 u.........
something like this.....
class first
{
public static first instance;
oncreate()
{
instance=this;
}
public static getInstance()
{
return instance;
}
}
now from second class call first.getInstance();
you can also directly acess instance in static way like this first.instance.......
Thanks...
You can't create an activity directly.
In the first activity take a static activity variable like this,
public static Activity activity;
In the onCreate do this.
activity = this;
Then in the second activity do this,
Activity activity = (your activity name).activity;
Edit:
For passing data from one activity to other activity this is not the way.
Above answer was to get activity instance from other activity which was initially asked.
To pass data from one activity to other activty generally use bundle. But if the data is not primitive data type, then use object class which should implement parcelable or serializable interface. Then through bundle only parcelable list of objects we can pass.