修改:Please see my answer below for my solution。
我在尝试使用getPurchases()
检查自有项目时收到NullPointerException错误,我不确定为什么我跟着the documentation。我发现文档有时会产生误导,所以我在这里。
我已经设置了应用内结算,以便初始化正常,我收到了成功消息。在初始化之后,我想检查用户是否先前购买了项目并根据结果显示按钮。这是我的代码到目前为止,下面是我的LogCat。错误出现在try / catch的开头。
public class MainActivity extends Activity
{
IabHelper mHelper;
IInAppBillingService mService;
private Button buyButton;
AdView adView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adView = (AdView)this.findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);
buyButton = (Button)findViewById(R.id.buyButton);
String base64EncodedPublicKey = "public_key";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener()
{
@Override
public void onIabSetupFinished(IabResult result)
{
if(!result.isSuccess())
{
Log.d("TEST", "In-app Billing setup failed: " + result);
}
else
{
Log.d("TEST", "In-app Billing is set up OK"); //This passes!
}
}
});
bindService(new Intent("com.android.vending.billing.InAppBillingService.BIND"), mServiceConn, Context.BIND_AUTO_CREATE);
try
{
Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null); //This is line 66 referenced in LogCat error
if(ownedItems.getInt("RESPONSE_CODE") == 0)
{
ArrayList ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE");
String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");
for(int i=0; i<purchaseDataList.size(); ++i)
{
String purchaseData = (String) purchaseDataList.get(i);
String signature = (String) signatureList.get(i);
String sku = (String) ownedSkus.get(i);
Log.d("TEST", "Purchased: "+i+ " -> "+sku);
}
}
else
{
Log.d("TEST", "Not Items Owned!");
}
}
catch(RemoteException e)
{
//TODO: Error, unable to get owned items
e.printStackTrace();
Log.d("TEST", "owned items check failed: "+e);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
ServiceConnection mServiceConn = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
mService = IInAppBillingService.Stub.asInterface(service);
Log.d("TEST", "mService ready to go!"); //This displays if try/catch above is commented out. Is it not waiting for mService to be initialized before running try/catch?
}
@Override
public void onServiceDisconnected(ComponentName name)
{
mService = null;
}
};
@Override
public void onDestroy()
{
super.onDestroy();
if(mServiceConn != null)
{
unbindService(mServiceConn);
}
}
}
Logcat错误
01-04 22:39:35.052: E/AndroidRuntime(32375): FATAL EXCEPTION: main
01-04 22:39:35.052: E/AndroidRuntime(32375): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.iab/com.test.iab.MainActivity}: java.lang.NullPointerException
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread.access$600(ActivityThread.java:141)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.os.Handler.dispatchMessage(Handler.java:99)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.os.Looper.loop(Looper.java:137)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread.main(ActivityThread.java:5041)
01-04 22:39:35.052: E/AndroidRuntime(32375): at java.lang.reflect.Method.invokeNative(Native Method)
01-04 22:39:35.052: E/AndroidRuntime(32375): at java.lang.reflect.Method.invoke(Method.java:511)
01-04 22:39:35.052: E/AndroidRuntime(32375): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
01-04 22:39:35.052: E/AndroidRuntime(32375): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
01-04 22:39:35.052: E/AndroidRuntime(32375): at dalvik.system.NativeStart.main(Native Method)
01-04 22:39:35.052: E/AndroidRuntime(32375): Caused by: java.lang.NullPointerException
01-04 22:39:35.052: E/AndroidRuntime(32375): at com.test.iab.MainActivity.onCreate(MainActivity.java:66)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.Activity.performCreate(Activity.java:5104)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
01-04 22:39:35.052: E/AndroidRuntime(32375): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
01-04 22:39:35.052: E/AndroidRuntime(32375): ... 11 more
01-04 22:39:35.083: E/GooglePlayServicesUtil(32375): The Google Play services resources were not found. Check your project configuration to ensure that the resources are included.
我的猜测是我没有正确初始化mService?但我不明白我是不是因为我认为我完全按照文档概述。感谢您的指导。
答案 0 :(得分:3)
这不起作用的原因是因为onServiceConnected()
在onCreate()
完成之前无法保证被调用。所以我将try / catch代码移到onServiceConnected()
。我不确定这是否是最佳做法,但它似乎解决了我的问题。以下是任何发现自己有同样错误的人的结果代码。这是按钮和购买逻辑。我推荐this tutorial代码。
public class MainActivity extends Activity
{
IabHelper mHelper;
IInAppBillingService mService;
static final String ITEM_SKU = "android.test.purchased";
private Button buyButton;
AdView adView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adView = (AdView)this.findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);
buyButton = (Button)findViewById(R.id.buyButton);
bindService(new Intent("com.android.vending.billing.InAppBillingService.BIND"), mServiceConn, Context.BIND_AUTO_CREATE);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
ServiceConnection mServiceConn = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
mService = IInAppBillingService.Stub.asInterface(service);
Log.d("TEST", "mService ready to go!");
checkOwnedItems();
}
@Override
public void onServiceDisconnected(ComponentName name)
{
mService = null;
}
};
private void checkownedItems()
{
try
{
Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
if(ownedItems.getInt("RESPONSE_CODE") == 0)
{
ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList<String> purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList<String> signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE");
String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");
if(purchaseDataList.size() > 0)
{
//Item(s) owned
for(int i=0; i<purchaseDataList.size(); ++i)
{
String purchaseData = purchaseDataList.get(i);
String signature = signatureList.get(i); //Note signatures do not appear to work with android.test.purchased (silly google)
String sku = ownedSkus.get(i);
}
}
else
{
//Item(s) not owned
String base64EncodedPublicKey = "public_key";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener()
{
@Override
public void onIabSetupFinished(IabResult result)
{
if(!result.isSuccess())
{
Log.d("TEST", "In-app Billing setup failed: " + result);
}
else
{
Log.d("TEST", "In-app Billing is set up OK");
}
}
});
}
}
else
{
//Error checking owned items
}
}
catch(RemoteException e)
{
e.printStackTrace();
}
}
@Override
public void onDestroy()
{
super.onDestroy();
if(mServiceConn != null)
{
unbindService(mServiceConn);
}
}
}
答案 1 :(得分:1)
您的代码只是说
IInAppBillingService mService;
它是null,你需要初始化它。
在System.out.println()
方法中放置onServiceConnected
以查看它是否正在初始化。如果不是,则表示未调用onServiceConnected
,因此bindService
方法可能无法正常工作
在onCreate方法之外添加它作为类变量......
ServiceConnection mServiceConn;
然后改变
ServiceConnection mServiceConn = new ServiceConnection()
到
mServiceConn = new ServiceConnection()