How do I handle a custom scheme from a Fragement in Android? - android

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();
}
}
}

Related

zxing-android-embedded: Load new Fragment from continous scan

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();

Best way to Handle Login on Android

Right now I have three activies:
HandleActivity
LoginActivity
MainActivity
When the user opens the app, the HandleActivity checks if the users is already logged in, if so it opens the MainActivity, if the user is not logged in it opens the LoginActivity.
Is there a better way to implement login on Android?
You don't have to have HandleActivity. When user open the app, always show your MainActivity. If user isn't logged in, redirect to LoginActivity.
MainActivity onCreate() {
if(isLoggedIn)
loadContent()
else
redirectToLoginActivity()
}
If you are using share preferences then check the share Preferences if data exist then move to Main Activity else to login activity..
If Using database to store data then check the size of table data
try {
if (UserdataController.getSingletonInstance().getUserdata(this).size() > 0) {
Fragment dashboardFragment = new DashboardFragment();
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.framlayout, dashboardFragment);
// fragmentTransaction.addToBackStack("dashboard");
fragmentTransaction.commit();
} else {
Fragment loginFragment = new LoginFragment();
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.framlayout, loginFragment);
fragmentTransaction.commit();
}
}
catch (SQLException e){
}

When Activity is destroyed on background,how to remove fragment

When my app switches to background,the system memory is low, then android will destroy my activity.At that time,I want to remove the fragments attached to activity,so that when activity switches to foreground,I can avoid any abnormal behavior of that activity.I do it like this:
#Override
public void onSaveInstanceState(Bundle outState) {
FragmentManager fm = getSupportFragmentManager();
AbstractBaseViewFragment previous = (AbstractBaseViewFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (previous != null) {
fm.beginTransaction().remove(previous).commitAllowingStateLoss();
fm.executePendingTransactions();
}
super.onSaveInstanceState(outState);
}
so I want to ask:Are there any other good ideas to finish this target?Will my method cause any crashes?
You can try this: ft.detach(previous);
if (previous != null) {
FragmentTransaction ft = fm.beginTransaction();
ft.detach(previous);
ft.remove(previous);
ft.commitAllowingStateLoss();
... // the rest of your code
}

Update arguments for already created fragment

I have a fragment A and a fragment B.
Fragment A is called from 2 different screens (which are also fragments).
Now, fragment A passes arguments to fragment B, using setArguments(bundle), whenever called.
Like this:(These lines are written in Fragment A)
Bundle bundle = new Bundle();
bundle.putString("bookId", bookListItems.get(position).getBookId());
bundle.putString("bookName", bookListItems.get(position).getBookName());
Fragment b = new B();
b.setArguments(bundle);
replaceFragment(b, bundle);
and the function replaceFragment is as follows:
private void replaceFragment (Fragment fragment, Bundle bundle) {
String backStateName = fragment.getClass().getName();
FragmentManager manager = mActivity.getFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped) { //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.addToBackStack(backStateName);
ft.commit();
} else {
fragment.getArguments().putString("bookId", bundle.getString("bookId"));
fragment.getArguments().putString("bookName", bundle.getString("bookName"));
}
}
Now, the problem is, when Fragment A is called from Screen 1, it works fine and passes right arguments to fragment B. But when it is called from Screen 2, the arguments passed to B are never updated, it always opens up the last state of fragment B.
Please help.
you could create in your Fragment's subclass which takes the new data, for instance, and call this method from the hosting Activity when you want to update it
public void updateData(String bookName, String bookId) {
if (getView() == null) {
return;
}
((TextView)getView().findViewById(R.id.texviewid)).setText(bookName);
}
In your Activity you will have to keep a reference to the specific subclass, as class member.
Another approach could make use of a BroadcastReceiver. In your Fragment register it with a specific IntentFilter and from your Activity use a LocalBroadcastManager to broadcast locally the intent with the changes. You could still use the same method, to update the UI. When onReceive is invoked, check the fragment status, and if it is in a correct status, extracts the data from the Intent, and call the method. E.g.
#Override
public void onReceive(Context context, Intent intent) {
if (isRemoving() || isDetached() || !isAdded()) {
return;
}
// extract data from intent
// call updateData
}

Why addToBackStack() method doesn't work

Here is my main activity. I followed this guide about Fragments correctly. When I click "Back" button, my application is closed instead of returning to the MainScreenFragment. Why is this happening and why addToBackStack() doesn't work?
public class MainScreenActivity extends ActionBarActivity implements MainScreenFragment.OnFrameChoiced {
private MainScreenFragment mainScreenFragment;
private AddWordsFragment addWordsFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
mainScreenFragment = new MainScreenFragment();
addWordsFragment = new AddWordsFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.container, mainScreenFragment).addToBackStack(null).commit();
}
#Override
public void choiceFrame(int id) {
switch (id) {
case R.id.add_new_words_frame:
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container, addWordsFragment).addToBackStack(null).commit();
fm.executePendingTransactions();
break;
}
}
P.S. I tried to use a solution from this topic, but It still doesn't work.
did you try overriding the back like below:
#overide
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 1) {
fm.popBackStack();
} else {
finish();
}
}
(I know you have picked up your desirable answer, but I have found a little more against this problem)
Though as Android official site has documented:
By calling addToBackStack(), the replace transaction is saved to the back stack so the user can reverse the transaction and bring back the previous fragment by pressing the Backbutton.
But as a matter of fact, this is in a precondition that you are using the standard android activity, specifically, the android.app.Activity. Because this methods in android.app.Activity will work when Backbutton is pressed:
public void onBackPressed() {
if (mActionBar != null && mActionBar.collapseActionView()) {
return;
}
if (!mFragments.getFragmentManager().popBackStackImmediate()) {
finishAfterTransition();
}
}
But, if you are extending your xxxxActivity from someone else, for example, the AppCompatActivity, FragmentActivity, ActionBarActivity, it will be another story, because in FragmentActivity, onBackPressed() method is totally overrode:
public void onBackPressed() {
if (!mFragments.getSupportFragmentManager().popBackStackImmediate()) {
supportFinishAfterTransition();
}
}
Note that mFragments.getFragmentManager() is replaced by mFragments.getSupportFragmentManager(), so in cases like this, you should begin your FragmentTransaction using getSupportFragmentManager() of the Activity. and as a consequence of that, you don't have to override onBackPressed method in your Activity.
BTW, ActionBarActivity extends AppCompatActivity extends FragmentActivity,they all come from the support library, you know what I mean, remember to use getSupportFragmentManager() instead of getFragmentManager() when using support library in order to get the compatible behavior.

Categories

Resources