PreferenceFragment doesn't get onActivityResult call from in app billing request

半腔热情 提交于 2019-12-02 12:54:39

问题


I have a preference screen that presents the user with a checkbox to disable ads. When the user clicks this for the first time, they are presented with an In App Billing purchase option to disable the ads.

The issue I'm facing here is that I can't see any way to get the onActivityResult callback into the fragment.

So I have a PreferenceActivity loading a PreferenceFragment (of which I can't seem to get a reference). In App Billing requires a call to startIntentSenderForResult, which Fragments don't have, only Activities.

When I launch the purchase flow with startIntentSenderForResult, the Activity's onActivityResult gets called, but I need this in the fragment.

Because I loaded the PreferenceFragment into the PreferenceActivity with the following, I don't think I can get a reference to the Fragment to pass the call down.

@Override
public void onBuildHeaders(List<Header> target) {
    loadHeadersFromResource(R.layout.preferences_headers, target);
}

@Override
public Intent getIntent() {
    final Intent modIntent = new Intent(super.getIntent());
    modIntent.putExtra(EXTRA_SHOW_FRAGMENT, SyncPreferencesFragment.class.getName());
    modIntent.putExtra(EXTRA_NO_HEADERS, true);
    return modIntent;
}

What am I missing here? I dont' want to split up all of my purchase logic, so how do I get my Fragment to get the onActivityForResult call?


回答1:


The original start request must come from the Fragment in order for Android to deliver the result back to the same Fragment. If the Activity starts the request, the result doesn't inherently get handed to every Fragment that may be attached to the manager. In addition to this, you have to ensure that if onActivityResult() is overridden in the top-level Activity, that you call super.onActivityResult() as well, or the message won't get delivered to the Fragment.

The problem with IAB is your given a PendingIntent instead of a standard Intent to fire, and there is no method on Fragment to trigger the initial action even if you can move your code there. To keep things as they are, you may have to do a bit of a swizzle. One thing you could do is make use of a custom interface inside the onAttach() method of your Fragment and use it to allow the Fragment to hand itself up to the Activity. Something like:

public class SyncPreferencesActivity extends PreferenceActivity
        implements SyncPreferencesFragment.OnAttachCallback {
    SyncPreferencesFragment mTargetFragment;

    @Override
    public void onAttachSyncFragment(SyncPreferencesFragment fragment) {
        mTargetFragment = fragment;
    }
}

...with some additions to the corresponding Fragment...

public class SyncPreferencesFragment extends PreferenceFragment {
    public interface OnAttachCallback {
        public void onAttachSyncFragment(SyncPreferencesFragment fragment);
    }

    @Override
    public void onAttach(Activity activity) {
        try {
            OnAttachCallback callback = (OnAttachCallback) activity;
            callback.onAttachSyncFragment(this);
        } catch (ClassCastException e) {
            throw new ClassCastException("You Forgot to Implement the Callback!");
        }
    }
}

With something like this, at least you have a reference to the instance so you can forward the result or anything else that might be necessary. If you want to be super clean, you could also implement a matching "detach" that clears the reference in the Activity.




回答2:


Here is a simpler way that I am using to get a reference to a Preference Fragment from a Preference Activity:

private WeakReference<GeneralPreferenceFragment> mGeneralFragment;

@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);

    // "id" might be arbitrary and "tag" can be null
    Log.d(TAG, "onAttachFragment: "+fragment.getId()+","+fragment.getTag());
    // however class can be used to identify different fragments
    Log.d(TAG, "onAttachFragment: "+fragment.getClass()+","+(fragment instanceof GeneralPreferenceFragment));

    if(fragment instanceof GeneralPreferenceFragment) {
        mGeneralFragment=new WeakReference<>((GeneralPreferenceFragment)fragment);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    Fragment f=mGeneralFragment.get();

    if(f!=null) {
        // can now use findPreference, etc
    }
}

This method is convenient because it doesn't require the use of interfaces or modifications to the fragment classes.



来源:https://stackoverflow.com/questions/18005016/preferencefragment-doesnt-get-onactivityresult-call-from-in-app-billing-request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!