android - InAppBilling registering BroadcastReceiver in AndroidManifest -
i'm implementing inapp billing in android app. works well, however, i'm trying decouple broadcast receiver activity manifest. suggestion in android's trivialdrive sample:
// important: dynamically register broadcast messages updated purchases. // register receiver here instead of <receiver> in manifest // because call getpurchases() @ startup, therefore can ignore // broadcasts sent while app isn't running. // note: registering listener in activity bad idea, done here // because sample. regardless, receiver must registered after // iabhelper setup, before first call getpurchases().
currently there's class extends broadcastreceiver
:
public class iabbroadcastreceiver extends broadcastreceiver { /** * intent action receiver should filter for. */ public static final string action = "com.android.vending.billing.purchases_updated"; private final iabbroadcastlistener mlistener; public iabbroadcastreceiver(iabbroadcastlistener listener) { mlistener = listener; } @override public void onreceive(context context, intent intent) { if (mlistener != null) { mlistener.receivedbroadcast(); } } /** * listener interface received broadcast messages. */ public interface iabbroadcastlistener { void receivedbroadcast(); } }
and class implements iabbroadcastreceiver.iabbroadcastlistener
:
public class subscription extends appcompatactivity implements iabbroadcastreceiver.iabbroadcastlistener { iabhelper mhelper; // provides purchase notification while app running iabbroadcastreceiver mbroadcastreceiver; ... // listener that's called when finish querying items , subscriptions own iabhelper.queryinventoryfinishedlistener mgotinventorylistener = new iabhelper.queryinventoryfinishedlistener() { public void onqueryinventoryfinished(iabresult result, inventory inventory) { log.d("iab", "query inventory finished."); if (mhelper == null) return; if (result.isfailure()) { log.d("iab", "failed query inventory: " + result); return; } if (inventory.getskudetails(sku_monthly_tts) != null && inventory.getskudetails(sku_yearly_tts) != null) { ... } log.d("iab", "query inventory successful."); /* * check items own. notice each purchase, check * developer payload see if it's correct! see * verifydeveloperpayload(). */ ... log.d("iab", "initial inventory query finished; enabling main ui."); } }; // callback when purchase finished iabhelper.oniabpurchasefinishedlistener mpurchasefinishedlistener = new iabhelper.oniabpurchasefinishedlistener() { public void oniabpurchasefinished(iabresult result, purchase purchase) { log.d("iab", "purchase finished: " + result + ", purchase: " + purchase); // if disposed of in meantime, quit. if (mhelper == null) return; if (result.isfailure()) { log.d("iab", "error purchasing: " + result); return; } if (!verifydeveloperpayload(purchase)) { log.d("iab", "error purchasing. authenticity verification failed."); return; } log.d("iab", "purchase successful."); ... } }; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_subscription); mhelper = new iabhelper(this, compiledky); mhelper.enabledebuglogging(true); mhelper.startsetup(new iabhelper.oniabsetupfinishedlistener() { @override public void oniabsetupfinished(iabresult result) { log.d("subscription", "insetupfinished: " + result); if (!result.issuccess()) { log.d("subscription", "problem setting in-app billing: " + result); return; } if (mhelper == null) return; // important: dynamically register broadcast messages updated purchases. // register receiver here instead of <receiver> in manifest // because call getpurchases() @ startup, therefore can ignore // broadcasts sent while app isn't running. // note: registering listener in activity bad idea, done here // because sample. regardless, receiver must registered after // iabhelper setup, before first call getpurchases(). mbroadcastreceiver = new iabbroadcastreceiver(subscription.this); intentfilter broadcastfilter = new intentfilter(iabbroadcastreceiver.action); registerreceiver(mbroadcastreceiver, broadcastfilter); // iab set up. now, let's inventory of stuff own. log.d("iab", "setup successful. querying inventory."); try { list<string> additionalskulist = new arraylist<string>(); ... mhelper.queryinventoryasync(true, null, additionalskulist, mgotinventorylistener); } catch (iabhelper.iabasyncinprogressexception e) { log.d("iab", "error querying inventory. async operation in progress."); } } }); button monthlysubbutton = (button) findviewbyid(r.id.monthlysubbutton); monthlysubbutton.setonclicklistener(new view.onclicklistener() { @override public void onclick(view view) { if (!mhelper.subscriptionssupported()) { log.d("iab","subscriptions not supported on device yet. sorry!"); return; } try { ... mhelper.launchpurchaseflow(subscription.this, ..., iabhelper.item_type_subs, oldsku, 10001, mpurchasefinishedlistener, ""); } catch (iabhelper.iabasyncinprogressexception e) { log.d("iab", e.getmessage()); } } }); ... } /** verifies developer payload of purchase. */ boolean verifydeveloperpayload(purchase p) { string payload = p.getdeveloperpayload(); ... return true; } @override protected void ondestroy() { super.ondestroy(); if (mbroadcastreceiver != null) { unregisterreceiver(mbroadcastreceiver); } log.d("iab", "destroying helper."); if (mhelper != null) { mhelper.disposewhenfinished(); mhelper = null; } } @override protected void onactivityresult(int requestcode, int resultcode, intent data) { log.d("iab", "onactivityresult(" + requestcode + "," + resultcode + "," + data); if (mhelper == null) return; if (!mhelper.handleactivityresult(requestcode, resultcode, data)) { super.onactivityresult(requestcode, resultcode, data); } else { log.d("iab", "onactivityresult handled iabutil."); } } @override public void receivedbroadcast() { // received broadcast notification inventory of items has changed log.d("iab", "received broadcast notification. querying inventory."); try { mhelper.queryinventoryasync(mgotinventorylistener); } catch (iabhelper.iabasyncinprogressexception e) { log.d("iab", "error querying inventory. async operation in progress."); } } }
i'm trying add receiver in manifest, gives me error:
</application> ... <activity android:name=".controller.subscription" android:label="subscription" android:parentactivityname=".controller.mainactivity"> <meta-data android:name="android.support.parent_activity" android:value=".controller.mainactivity" /> </activity> <receiver android:name=".controller.subscription" android:exported="true"> <intent-filter> <action android:name="android.intent.action.boot_completed"/> <action android:name="android.intent.action.input_method_changed" /> </intent-filter> </receiver> </application>
error message:.controller.subscription not assignable 'android.content.broadcastreceiver'
the subscription
class in right directory (under controller package). subscription
class have extend iabbroadcastreceiver class , not implementing iabbroadcastreceiver.iabbroadcastlistener
instead? i'll still extend appcompactactivity
, know if there's way resolve this. seems there's no samples online shows how implement inapp billing api broadcast receiver registered in manifest. thank in advance!
controller.subscription not assignable 'android.content.broadcastreceiver'
which means, subscription
not descendant of broadcastreceiver
. have registered subscription
in manifest receiver
, in fact not subclass of broadcastreceiver
.
does
subscription
class have extendiabbroadcastreceiver
class , not implementingiabbroadcastreceiver.iabbroadcastlistener
instead?
in order register class receiver
in manifest, should descendant (direct or indirect) of broadcastreceiver
. thus, subscription
should either extends broadcastreceiver
or extends iabbroadcastreceiver
.
i'll still extend appcompactactivity.
you cannot make class both activity , receiver (multiple inheritance not supported in java).
still can register iabbroadcastreceiver
through manifest <receiver>
. wonder what's reasoning behind that? obviously, never receive broadcast while app inactive because should initiate purchase flow within app, that's why makes more sense register , unregister broadcastreceiver
dynamically. note, having registered receiver through manifest make receive broadcasts of purchases other apps, possibly not interested in.
see docs:
don't register broadcast receiver in app manifest. declaring receiver in manifest can cause system launch app handle intent if user makes purchase while app isn't running. behavior not necessary , may annoying user. find out purchases user made while app wasn't running, call getpurchases() when user launches app.
Comments
Post a Comment