如何在Android Studio中集成应用内订阅?新手技术求助
Hey there! I totally get how frustrating it can be when test IDs work but real subscriptions throw errors—let's work through this step by step. First, let's spot the issues in your current code, then I'll share a complete working implementation, plus key checks to get your real subscription up and running.
First, Let's Fix the Issues in Your Current Code
Your code has a couple of critical problems that are likely causing the error with real subscription IDs:
- You're calling
purchase()too early: You're triggering the purchase immediately inonCreate(), but theBillingProcessorhasn't finished initializing yet. You should only start purchase flows afteronBillingInitialized()is called. - Wrong Activity context: You're passing
MainSellerActivity.thisbut your class isMainActivity—that's a context mismatch that can break the purchase flow. - Missing lifecycle handling: You haven't implemented
onActivityResult()oronDestroy(), which are required to properly manage the billing connection and handle purchase results.
Complete Working Subscription Integration Code
Here's a revised, full implementation that fixes these issues and handles subscriptions correctly. I'll add comments to explain key parts:
import android.os.Bundle; import android.view.View; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import org.jetbrains.annotations.Nullable; import com.anjlab.android.iab.v3.BillingProcessor; import com.anjlab.android.iab.v3.TransactionDetails; public class MainActivity extends AppCompatActivity implements BillingProcessor.IBillingHandler { private BillingProcessor bp; // Replace with YOUR real subscription product ID from Google Play Console private static final String SUBSCRIPTION_ID = "your_real_subscription_product_id"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Initialize BillingProcessor with your license key bp = new BillingProcessor(this, Constants.base64EncodedPublicKey, this); // Add a button in your layout to trigger the subscription (don't call purchase directly in onCreate!) findViewById(R.id.btn_subscribe).setOnClickListener(v -> { // Only attempt purchase if billing is initialized if (bp.isInitialized()) { // Check if the subscription is already owned first (optional but recommended) if (!bp.isSubscribed(SUBSCRIPTION_ID)) { bp.subscribe(MainActivity.this, SUBSCRIPTION_ID); } else { Toast.makeText(MainActivity.this, "Already subscribed!", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(MainActivity.this, "Billing not initialized yet. Try again.", Toast.LENGTH_SHORT).show(); } }); } @Override public void onProductPurchased(String productId, @Nullable TransactionDetails details) { if (productId.equals(SUBSCRIPTION_ID)) { Toast.makeText(this, "Monthly subscription activated successfully!", Toast.LENGTH_LONG).show(); // Here you should unlock premium features, save the subscription status to your backend, etc. } } @Override public void onPurchaseHistoryRestored() { // This is called when past purchases are restored // Check if the subscription is active here if (bp.isSubscribed(SUBSCRIPTION_ID)) { Toast.makeText(this, "Subscription restored!", Toast.LENGTH_SHORT).show(); // Unlock premium features } } @Override public void onBillingError(int errorCode, @Nullable Throwable error) { // Handle billing errors here—log the error to debug String errorMsg; switch (errorCode) { case BillingProcessor.ERROR_USER_CANCELED: errorMsg = "Purchase canceled by user"; break; case BillingProcessor.ERROR_ITEM_UNAVAILABLE: errorMsg = "Subscription not available (check Google Play Console setup)"; break; default: errorMsg = "Billing error: " + errorCode; if (error != null) { errorMsg += " - " + error.getMessage(); } } Toast.makeText(this, errorMsg, Toast.LENGTH_LONG).show(); } @Override public void onBillingInitialized() { // Billing is ready to use—you can pre-load subscription details here if needed Toast.makeText(this, "Billing initialized", Toast.LENGTH_SHORT).show(); // Optional: Check if user is already subscribed on app launch if (bp.isSubscribed(SUBSCRIPTION_ID)) { Toast.makeText(this, "You already have an active subscription!", Toast.LENGTH_SHORT).show(); // Unlock premium features } } // Required to handle purchase results @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable android.content.Intent data) { if (!bp.handleActivityResult(requestCode, resultCode, data)) { super.onActivityResult(requestCode, resultCode, data); } } // Clean up billing connection when activity is destroyed @Override public void onDestroy() { if (bp != null) { bp.release(); } super.onDestroy(); } }
Critical Checks for Real Subscription IDs
If you're still getting errors with your real product ID, make sure you've covered these steps in Google Play Console:
- Your subscription product is active: Go to Google Play Console > Your App > Monetization > Products > Subscriptions, and ensure your monthly subscription is set to "Active" (not "Draft").
- Test accounts are added: Add your test Google account to the "License testing" list in Google Play Console > Your App > Setup > License testing. Only these accounts can test real subscriptions without being charged.
- Correct public key: Double-check that
Constants.base64EncodedPublicKeymatches the "LICENSE KEY" found in Google Play Console > Your App > Setup > App integrity > App signing. - App signature is configured: If you're using a debug build, make sure your debug keystore's SHA-1 fingerprint is added to Google Play Console > Your App > Setup > App integrity > App signing (under "App signing certificate" or "Upload certificate").
Testing Tips
- Always test with a license test account—never use your personal account (you'll get charged!).
- Check Logcat for detailed error messages—they'll tell you exactly why the purchase is failing (e.g., "Item not found" means your product ID is wrong or not active).
- Verify that your app's package name in AndroidManifest.xml matches exactly what's registered in Google Play Console.
内容的提问来源于stack exchange,提问作者Hussain Developers

