I´ve the following problem: I want to load a new Fragment from my QR Activity. I start the activity from my fragment like this:
IntentIntegrator.forSupportFragment(this).setCaptureActivity(QrHorizontalActivity.class).initiateScan();
Then in the scan activity I want to load my new fragment:
#Override
public void barcodeResult(BarcodeResult result) {
SwipeOverviewFragment.newInstance().add_fragment(R.id.barcode_scanner,curr_activity, detail_frag);
Why will this not work? Thanks a lot for your help
Try below code for calling fragment;
FragmentTransaction fragmenttransaction = getSupportFragmentManager().beginTransaction();
SwipeOverviewFragment regcomplainfragment = new SwipeOverviewFragment();
fragmenttransaction.replace(R.id.content_frame, regcomplainfragment).addToBackStack("tag");
fragmenttransaction.commit();
Related
I'm working with an Android app which I inherited. On a certain screen, which is defined as a Fragment, I need to open an external web page, and then wait for that web page to do a redirect back to my app using a custom scheme.
I understand how to open the web page, and I understand how to set up an intent-filter in my Manifest that responds to the custom scheme by starting another activity. But, starting another activity is not what I need. Instead, I need for control to return to the Fragment that originally started this process.
What is the best way to accomplish this?
You have to parse the intent in the activity and use the fragment manager to populate late the fragment you wish. Replace Action and Fragment with your own.
#Override
protected void onNewIntent(final Intent intent) {
super.onNewIntent(intent);
parseIntent(intent);
}
private void parseIntent(Intent intent) {
final String action = intent.getAction();
if (action != null) {
if (Action.<ONE>.equals(action)) {
FragmentManager fm = getFragmentManager();
Fragment<ONE> fragment = (Fragment<ONE>) Fragment.instantiate(this,
Fragment<ONE>.class.getCanonicalName(),
getIntent().getExtras());
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_id, fragment);
ft.commit();
} else if (Action.<TWO>.equals(action)) {
FragmentManager fm = getFragmentManager();
Fragment<TWO> fragment = (Fragment<TWO>) Fragment.instantiate(this,
Fragment<TWO>.class.getCanonicalName(),
getIntent().getExtras());
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_id, fragment);
ft.commit();
}
}
}
I read Android documentation on how to add a Fragment to an activty. It says that to add a Fragment to an Activty I should write this code inside the Activity class:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
but this is for android.app.Fragment class.
For android.support.v4.Fragment, documentation say that instead of getFragmentManager() I should call getSupportFragmentManager() and that Activity must extends FragmentActivty.
So I did this change, and now this is my activity code:
public class ExampleActivity extends AppCompactActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
}
AppCompactActivity is a subclass of FragmentActivity so I respected the constraints.
The problem is that if I run my application I get this error:
java.lang.RuntimeException:
com.myapplication.ExampleActivity#13388c6 must implement OnFragmentInteractionListener
I typed OnFragmentInteractionListener on Android doc web search and this is what I get:
Immediately below there is the link
https://developer.android.com/training/basics/fragments/communicating.html
that shows me a guide to communication between fragments. It speaks about ListFragment and I don't care it.
I'm very very confuse because every time I read documentation there are always things that force me to make internet search to find workaround or fix to problems.
Is there a persone that can explain me first how to fix this problem.
From the tutorial, you can read the following:
In order to receive event callbacks from the fragment, the activity
that hosts it must implement the interface defined in the fragment
class.
So, implement it in your Activity with something like this in your fragment:
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
...
public void onArticleSelected(int position) {
// The user selected the headline of an article from the HeadlinesFragment
// Do something here to display that article
}
}
Why did you need it? Because you've forced the host activity to implement it with something like this:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
I am trying to prevent my DialogFragment opening twice. Here is what I do:
I try to keep only one instance of my fragment. I create and add my fragment like this:
//MyFragment.java
public static MyFragment mInstance;
public static void instantiateFragment() {
MyFragment myFragment = MyFragment.getInstance();
if(!myFragment.isAdded()) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(myFragment, TAG);
ft.commit();
}
}
private static MyFragment getInstance() {
if(mInstance == null) {
mInstance = new MyFragment();
}
return mInstance;
}
And when a button is clicked, I intentionally try to add fragment twice like this:
MyFragment.instantiateFragment();
MyFragment.instantiateFragment();
But I get IllegalStateException: Fragment already added. Any ideas about that?
Thanks.
Indeed it's a problem with asynchronous commit of transactions, so as #Android jack stated you can use executePendingTransactions() like in this answer,
or even better use commitNow(),
or try something like this:
public static void instantiateFragment() {
Fragment myFragment = getSupportFragmentManager().findFragmentByTag(TAG);
if (myFragment == null) {
myFragment = MyFragment.getInstance();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(myFragment, TAG);
ft.commit();
}
}
I think this has to do with the asynchronous behaviour of fragment transactions.Fragment Transactions are committed asynchronously. So at first call, your fragment is added but it is committed asynchronously.Again in your next call your fragment is not added as it is not committed yet so !myFragment.isAdded() returns false.Then while adding the fragment the previous transaction is committed due to which it raises exception.
Try to use this
getFragmentManager().executePendingTransactions();
before your (!myFragment.isAdded()) code.
In my application I am using google map in fragment. I am using this code for adding fragments.
public void addPage(final BaseFragment pBaseFragment, final boolean isAddToBackStack){
FragmentTransaction transaction = mFragmentManager.beginTransaction();
transaction.add(R.id.content_frame, pBaseFragment);
if (isAddToBackStack) transaction.addToBackStack(null);
transaction.commit();
}
In MyMapFragment I call this for removing map (If I don't do this I got duplicate id for map exception)
public void onDestroyView() {
super.onDestroyView();
Fragment fragment = (getFragmentManager().findFragmentById(R.id.map_n));
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
ft.remove(fragment);
ft.commit();
}
but when I press back button and application is closed I got this error. (in the line ft.commit())
Caused by: java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1365)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:578)
Could anyone tell me what is the solution here how avoid this error I've already stuck on this 3 days.
Try this way:
#Override
public void onDestroyView ()
{
try{
SupportMapFragment fragment = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.map_n));
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.remove(fragment);
ft.commit();
}catch(Exception e){
}
super.onDestroyView();
}
Working with Robolectric , I'm very new to android. I made a first test class using Activity. It worked nicely.
Now I want make a test for fragment.
#RunWith(RobolectricTestRunner.class)
public class LoginFragmentTest {
private LoginFragment fragment;
#Before
public void setup() {
fragment = new LoginFragment();
startFragment(fragment);
assertThat(fragment, notNullValue());
assertThat(fragment.getActivity(), notNullValue());
}
private void startFragment(LoginFragment fragment) {
FragmentManager fragmentManager = new FragmentActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(fragment, null);
fragmentTransaction.commit();
}
#Test
public void login() {
EditText idEditText = (EditText)fragment.getActivity().findViewById(R.id.main_id);
assertThat(idEditText, notNullValue());
}
}
This is my first test class for Fragment class. It throws
"java.lang.IllegalStateException: Activity has been destroyed" in startFragment#fragmentTransaction.commit().
Anyone knows how to fix this ?
You can find whole source from https://github.com/msbaek/frame-test
Thanks in advance !!
In my case, specifically, my problem was when creating the activity.
I was using
activity = Robolectric.buildActivity(MyActivity.class).get();
And it should be
activity = Robolectric.buildActivity(MyActivity.class).create().get();
Hope it helps someone :D
#RunWith(RobolectricTestRunner.class)
public class LoginFragmentTest {
private LoginFragment fragment;
#Before
public void setup() {
fragment = new LoginFragment();
startFragment();
assertThat(fragment, notNullValue());
assertThat(fragment.getActivity(), notNullValue());
}
private void startFragment() {
FragmentActivity activity = new FragmentActivity();
shadowOf(activity).callOnCreate(null);
shadowOf(activity).callOnStart();
shadowOf(activity).callOnResume();
FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(fragment, null);
fragmentTransaction.commit();
}
#Test
public void login() {
EditText idEditText = (EditText) fragment.getView().findViewById(R.id.main_id);
assertThat(idEditText, notNullValue());
}
}
This is working version. Following 3 lines are important(it's from robolectric source - DialogFragmentTest).
shadowOf(activity).callOnCreate(null);
shadowOf(activity).callOnStart();
shadowOf(activity).callOnResume();
The fragments are supposed to be displayed from an Activity. The flow should be:
allocate a new fragment object in a FragmentActivity class
get the fragment manager to add the newly allocated fragment
In your case you do not have a connection to a real activity. You allocate a FragmentActivity with new FragmentActivity() and try to get the support manager. While this compiles there is no "real" activity able to manage your fragment. Fragments can be added on activities already displayed and here it's not the case.
I recommend reading this page as it explains these things very well: http://developer.android.com/guide/components/fragments.html
That happened for me when I used fragmentTransaction.commitAllowingStateLoss(); from sub Fragment whose parent fragment had setRetainInstance(true); I had activity as property what lead to leaking activity on rotation.