我正在我的安卓应用程序中实现InApp计费。但是,一切都很好,但是,我正在尝试将广播接收器从活动中分离到清单中。特别是在Android的琐事驱动示例中有这样的建议:
// 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。谢谢你提前提供帮助!
发布于 2017-08-20 15:40:59
controller.Subscription不能分配给“android.content.BroadcastReceiver”
这意味着,Subscription不是BroadcastReceiver的后代。您已经将清单中的Subscription注册为receiver,但实际上它不是BroadcastReceiver的子类。
我的
Subscription类是否必须扩展IabBroadcastReceiver类而不是实现IabBroadcastReceiver.IabBroadcastListener?
为了将类注册为清单中的receiver,类应该是BroadcastReceiver的后代(直接或间接)。因此,Subscription应该是extends BroadcastReceiver还是extends IabBroadcastReceiver。
我仍然想扩展AppCompactActivity.
您不能使一个类同时进行活动和接收(Java中不支持多重继承)。
您仍然可以通过清单将IabBroadcastReceiver注册为<receiver>。但我不知道这背后的理由是什么?显然,当应用程序处于不活动状态时,您永远不会收到任何广播,因为您应该在应用程序中启动购买流程,这就是为什么动态注册和取消注册BroadcastReceiver更有意义。请注意,通过清单注册接收者将使您接收从其他应用程序购买的广播,这是您最可能不感兴趣的。
请参阅文档
不要在应用程序清单中注册这个广播接收器。在清单中声明接收者可能会导致系统启动应用程序,以处理在应用程序未运行时用户进行购买的意图。这种行为是不必要的,可能会使用户感到厌烦。要了解用户在应用程序未运行时所做的任何购买,请在用户启动应用程序时打电话给getPurchases()。
发布于 2017-08-15 03:58:12
这通常是因为您在\控制器\包下没有订阅类。在您的代码中,一切看起来都很好(假设您在清单中添加了相应的intentfilter)。因此,请确保您的订阅类位于正确的包(或文件夹)中。
https://stackoverflow.com/questions/45686172
复制相似问题