The new Android Billing v3 documentation and helper code uses startIntentSenderForResult()
when launching a purchase flow. I want to start a purchase flow (and
I suggest two solutions:
1.) Put the IabHelper mHelper on the activity and call the IabHelper from the fragment.
Something like:
To use this solution, Declare IabHelper as public in the activity and use a method to call the launcher from the Fragment.
public class MyActivity extends Activity{
public IabHelper mHelper
public purchaseLauncher(){
mHelper.launchPurchaseFlow(this, SKU_GAS, 10001,
mPurchaseFinishedListener, "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
}
/*The finished, query and consume listeners should also be implemented in here*/
}
public class FragmentActivity extends Fragment{
MyActivity myAct = (MyActivity) getActivity();
myAct.purchaseLauncher();
}
2.) In onActivityResult, call the appropriate fragment that contains the IabHelper object. Appropriate fragment can have an access method to the helper object.
protected void onActivityResult(int requestCode, int resultCode,Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag("YourTag");
if (fragment != null)
{
((MyFragmentWithIabHelper)fragment).onActivityResult(requestCode, resultCode,data);
}
}
You need to pass fragment and data to parent activity, then call fragment onActivityResult from the parent activity.
like this
in fragment:
HomeActivity activity = (HomeActivity) getActivity();
activity.purchaseLauncher(this, mHelper, productDTO.getSku(), RC_REQUEST, mPurchaseFinishedListener, PAYLOAD);
in parent activity:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (storeFragment != null) {
storeFragment.onActivityResult(requestCode, resultCode, data);
}
}
public void purchaseLauncher(StoreFragment storeFragment, IabHelper mHelper, String sku, int requestCode, IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener, String payload) {
this.storeFragment = storeFragment;
mHelper.launchPurchaseFlow(this, sku, requestCode, mPurchaseFinishedListener, payload);
}
You need to call
super.onActivityResult(requestCode, resultCode, data);
at the beginning of your Activity's and Fragment's onActivityResult to cascade the Results to the fragments.
In my FragmentActivity this reads as
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// No action here, call super to delegate to Fragments
super.onActivityResult(requestCode, resultCode, data);
}
1) You should modify your resultCode (RC_REQUEST) to put fragment index to it.
int rc_reqest = RC_REQUEST + ((getActivity().getSupportFragmentManager().getFragments().indexOf(this)+1)<<16) ;
mHelper.launchPurchaseFlow(getActivity(), sku, rc_reqest ,mPurchaseFinishedListener, payload);
2) in IabHelper.launchPurchaseFlow(...)
change mRequestCode = requestCode
to
mRequestCode = requestCode&0xffff;
From SDK 24 and above, there is a startIntentSenderForResult method available in support Fragment also, which works as intended. Note that there is an additional Bundle parameter, which can be passed as null. Thus, final code will be:
startIntentSenderForResult(pendingIntent.getIntentSender(),
1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0),
Integer.valueOf(0), null);
Of course, for API 23 and below, we will still need to use the tricks described in other answers.