我正在使用正式的google示例代码进行用户订阅play-billing-sample。切换Google帐户时,我在检查帐户持有状态时得到了nullpointexception(我的手机有两个注册为测试帐户的Google帐户以测试购买)。
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference at com.pishimishi.test.classytaxijava.billing.BillingUtilities.isAccountHold(BillingUtilities.java:151)
BillingUtilities.java:
/**
* Returns true if account hold should be shown.
*/
public static boolean isAccountHold(SubscriptionStatus subscription) {
return subscription != null &&
!subscription.isEntitlementActive &&
subscription.isAccountHold &&
!subscription.subAlreadyOwned;
}
和SubscriptionStatus.java:
/**
* Local subscription data. This is stored on disk in a database.
*/
@Entity(tableName = "subscriptions")
public class SubscriptionStatus {
public class SubscriptionStatusList {
@Nullable
@SerializedName("subscriptions")
List<SubscriptionStatus> subscriptionStatuses;
SubscriptionStatusList(@Nullable List<SubscriptionStatus> subscriptionStatuses) {
this.subscriptionStatuses = subscriptionStatuses;
}
}
public static final String SUBSCRIPTIONS_KEY = "subscriptions";
public static final String SKU_KEY = "sku";
public static final String PURCHASE_TOKEN_KEY = "purchaseToken";
public static final String IS_ENTITLEMENT_ACTIVE_KEY = "isEntitlementActive";
public static final String WILL_RENEW_KEY = "willRenew";
public static final String ACTIVE_UNTIL_MILLISEC_KEY = "activeUntilMillisec";
public static final String IS_FREE_TRIAL_KEY = "isFreeTrial";
public static final String IS_GRACE_PERIOD_KEY = "isGracePeriod";
public static final String IS_ACCOUNT_HOLD_KEY = "isAccountHold";
// Local fields
@PrimaryKey(autoGenerate = true)
public int primaryKey = 0;
@Nullable
public String subscriptionStatusJson;
public boolean subAlreadyOwned;
public boolean isLocalPurchase;
// Remote fields
@Nullable
public String sku;
@Nullable
public String purchaseToken;
public Boolean isEntitlementActive;
public Boolean willRenew;
public Long activeUntilMillisec = 0L;
public Boolean isFreeTrial;
public Boolean isGracePeriod;
public Boolean isAccountHold;
/**
* Parse subscription data from Map and return null if data is not valid.
*/
@Nullable
public static List<SubscriptionStatus> listFromMap(Map<String, Object> map) {
List<SubscriptionStatus> subscriptions = new ArrayList<>();
List<Map<String, Object>> subList = null;
if (map.get(SUBSCRIPTIONS_KEY) instanceof ArrayList) {
subList = (ArrayList) map.get(SUBSCRIPTIONS_KEY);
}
if (subList == null) {
return null;
}
for (Map<String, Object> subStatus : subList) {
SubscriptionStatus subscriptionStatus = new SubscriptionStatus();
subscriptionStatus.sku = (String) subStatus.get(SKU_KEY);
subscriptionStatus.purchaseToken = (String) subStatus.get(PURCHASE_TOKEN_KEY);
subscriptionStatus.isEntitlementActive =
(Boolean) subStatus.get(IS_ENTITLEMENT_ACTIVE_KEY);
subscriptionStatus.willRenew = (Boolean) subStatus.get(WILL_RENEW_KEY);
subscriptionStatus.activeUntilMillisec =
(Long) subStatus.get(ACTIVE_UNTIL_MILLISEC_KEY);
subscriptionStatus.isFreeTrial = (Boolean) subStatus.get(IS_FREE_TRIAL_KEY);
subscriptionStatus.isGracePeriod = (Boolean) subStatus.get(IS_GRACE_PERIOD_KEY);
subscriptionStatus.isAccountHold = (Boolean) subStatus.get(IS_ACCOUNT_HOLD_KEY);
subscriptions.add(subscriptionStatus);
}
return subscriptions;
}
/**
* Parse subscription data from String and return null if data is not valid.
*/
@Nullable
public static List<SubscriptionStatus> listFromJsonString(String dataString) {
Gson gson = new Gson();
try {
SubscriptionStatusList subscriptionStatusList =
gson.fromJson(dataString, SubscriptionStatusList.class);
if (subscriptionStatusList != null) {
return subscriptionStatusList.subscriptionStatuses;
} else {
return null;
}
} catch (JsonSyntaxException e) {
return null;
}
}
/**
* Create a record for a subscription that is already owned by a different user.
*
* The server does not return JSON for a subscription that is already owned by
* a different user, so we need to construct a local record with the basic fields.
*/
public static SubscriptionStatus alreadyOwnedSubscription(String sku, String purchaseToken) {
SubscriptionStatus subscriptionStatus = new SubscriptionStatus();
subscriptionStatus.sku = sku;
subscriptionStatus.purchaseToken = purchaseToken;
subscriptionStatus.isEntitlementActive = false;
subscriptionStatus.subAlreadyOwned = true;
return subscriptionStatus;
}
@Override
public String toString() {
return "SubscriptionStatus{" +
"primaryKey=" + primaryKey +
", subscriptionStatusJson='" + subscriptionStatusJson + '\'' +
", subAlreadyOwned=" + subAlreadyOwned +
", isLocalPurchase=" + isLocalPurchase +
", sku='" + sku + '\'' +
", purchaseToken='" + purchaseToken + '\'' +
", isEntitlementActive=" + isEntitlementActive +
", willRenew=" + willRenew +
", activeUntilMillisec=" + activeUntilMillisec +
", isFreeTrial=" + isFreeTrial +
", isGracePeriod=" + isGracePeriod +
", isAccountHold=" + isAccountHold +
'}';
}
}
我不明白为什么我必须获得NPE。或者,如果我们从服务器上获取信息,为什么我不使用第一个帐户获取它(我甚至测试了暂停第一个帐户的购买)并且可以正常工作。
PS。最初,在我的游戏控制台中,“帐户保留”功能未激活,但是后来,我激活了“帐户保留和帐户暂停”功能。但是切换到第二个Google帐户后,我仍然收到相同的错误。
每次Java在if语句中使用Boolean
对象时,它都会将其解包为使用boolean
方法的Boolean.booleanValue()
类型的基本类型。]
要解决此问题,您必须将isAccountHold
和isEntitlementActive
类型从Boolean
public static boolean isAccountHold(SubscriptionStatus subscription) {
return subscription != null &&
(subscription.isEntitlementActive == null || !subscription.isEntitlementActive) &&
(subscription.isAccountHold != null || subscription.isAccountHold) &&
!subscription.subAlreadyOwned;
}