我正在我的 Android 应用程序中实施 InApp 计费。一切正常,但是,我正在尝试将广播接收器与活动分离为清单。尤其是在 Android 的 trivialdrive 示例中的这个建议:
// Important: Dynamically register for broadcast messages about updated purchases.
// We register the receiver here instead of as a <receiver> in the Manifest
// because we always call getPurchases() at startup, so therefore we can ignore
// any broadcasts sent while the app isn't running.
// Note: registering this listener in an Activity is a bad idea, but is done here
// because this is a SAMPLE. Regardless, the receiver must be registered after
// IabHelper is setup, but before first call to getPurchases().
目前有一个扩展类BroadcastReceiver
:
public class IabBroadcastReceiver extends BroadcastReceiver {
/**
* The Intent action that this 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 for received broadcast messages.
*/
public interface IabBroadcastListener {
void receivedBroadcast();
}
}
还有一个实现的类IabBroadcastReceiver.IabBroadcastListener
:
public class Subscription extends AppCompatActivity implements
IabBroadcastReceiver.IabBroadcastListener {
IabHelper mHelper;
// Provides purchase notification while this app is running
IabBroadcastReceiver mBroadcastReceiver;
...
// Listener that's called when we finish querying the items and subscriptions we 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 to query inventory: " + result);
return;
}
if (inventory.getSkuDetails(SKU_MONTHLY_TTS) != null
&& inventory.getSkuDetails(SKU_YEARLY_TTS) != null) {
...
}
Log.d("IAB", "Query inventory was successful.");
/*
* Check for items we own. Notice that for each purchase, we check
* the developer payload to see if it's correct! See
* verifyDeveloperPayload().
*/
...
Log.d("IAB", "Initial inventory query finished; enabling main UI.");
}
};
// Callback for when a purchase is finished
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d("IAB", "Purchase finished: " + result + ", purchase: " + purchase);
// if we were disposed of in the 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 up In-app Billing: " + result);
return;
}
if (mHelper == null) return;
// Important: Dynamically register for broadcast messages about updated purchases.
// We register the receiver here instead of as a <receiver> in the Manifest
// because we always call getPurchases() at startup, so therefore we can ignore
// any broadcasts sent while the app isn't running.
// Note: registering this listener in an Activity is a bad idea, but is done here
// because this is a SAMPLE. Regardless, the receiver must be registered after
// IabHelper is setup, but before first call to getPurchases().
mBroadcastReceiver = new IabBroadcastReceiver(Subscription.this);
IntentFilter broadcastFilter = new IntentFilter(IabBroadcastReceiver.ACTION);
registerReceiver(mBroadcastReceiver, broadcastFilter);
// IAB is fully set up. Now, let's get an inventory of stuff we 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. Another 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 your 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 the developer payload of a 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 by IABUtil.");
}
}
@Override
public void receivedBroadcast() {
// Received a broadcast notification that the 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. Another async operation in progress.");
}
}
}
我正在尝试在清单中添加一个接收器,但它给了我一个错误:
</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 is not assignable to 'android.content.BroadcastReceiver'
该类Subscription
位于正确的目录中(在控制器包下)。我的Subscription
班级是否必须扩展 IabBroadcastReceiver 班级而不是实施IabBroadcastReceiver.IabBroadcastListener
?我仍然想扩展AppCompactActivity
,想知道是否有任何方法可以解决这个问题。似乎没有在线示例显示如何使用清单中注册的广播接收器实现 inApp 计费 api。提前谢谢你的帮助!