我目前正在尝试在iOS应用上测试应用内购买,但我不确定我是否已正确完成实施,因为当我在iOS设备上测试时,只要我点击购买产品,应用就会崩溃。这是我的代码:
store.Java
final MyGame game;
final Asset asset;
OrthographicCamera camera;
Vector3 touchPos;
Texture green_heart,cyan_heart,purple_heart,doublefuel,restore;
int life;
long itemTime;
Preferences prefs;
public static final int APPSTORE_UNDEFINED = 0;
public static final int APPSTORE_GOOGLE = 1;
public static final int APPSTORE_OUYA = 2;
public static final int APPSTORE_AMAZON = 3;
public static final int APPSTORE_DESKTOP = 4;
public static int isAppStore = APPSTORE_UNDEFINED;
public final static String cyan_1 = "cyanheart"; //cyanheart
public final static String green_2 = "greenheart"; //greenheart
public final static String purple_3 = "purpleheart"; //purpleheart
public final static String upgrade_fuel = "doublefuel"; //doublefuel
static PlatformResolver m_platformResolver;
public PurchaseManagerConfig purchaseManagerConfig;
public PurchaseObserver purchaseObserver = new PurchaseObserver() {
@Override
public void handleRestore (Transaction[] transactions) {
for (int i = 0; i < transactions.length; i++) {
if (checkTransaction(transactions[i].getIdentifier(), true) == true) break;
}
}
@Override
public void handleRestoreError (Throwable e) {
throw new GdxRuntimeException(e);
}
@Override
public void handleInstall () { }
@Override
public void handleInstallError (Throwable e) {
Gdx.app.log("ERROR", "PurchaseObserver: handleInstallError!: " + e.getMessage());
throw new GdxRuntimeException(e);
}
@Override
public void handlePurchase (Transaction transaction) {
checkTransaction(transaction.getIdentifier(), false);
}
@Override
public void handlePurchaseError (Throwable e) { //--- Amazon IAP: this will be called for cancelled
throw new GdxRuntimeException(e);
}
@Override
public void handlePurchaseCanceled () { //--- will not be called by amazonIAP
}
};
protected boolean checkTransaction (String ID, boolean isRestore) {
boolean returnbool = false;
if (cyan_1.equals(ID)) {
life += 1;
prefs.putInteger("LIFE",life);
prefs.flush();
//----- put your logic for full version here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
returnbool = true;
}
if (green_2.equals(ID)) {
life += 3;
prefs.putInteger("LIFE",life);
prefs.flush();
//----- put your logic for full version here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
returnbool = true;
}
if (purple_3.equals(ID)) {
life += 10;
prefs.putInteger("LIFE",life);
prefs.flush();
//----- put your logic for full version here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
returnbool = true;
}
if (upgrade_fuel.equals(ID)) {
prefs.putInteger("FUEL",100);
prefs.flush();
//----- put your logic for full version here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
returnbool = true;
}
return returnbool;
}
public Store(final MyGame game, final Asset asset){
this.game = game;
this.asset = asset;
camera = new OrthographicCamera();
camera.setToOrtho(false,625,280); //(width,height) 625,280
touchPos = new Vector3();
game.font3.setColor(Color.WHITE);
game.font4.setColor(Color.GOLD);
green_heart = asset.manager.get("greenheart.png",Texture.class);
purple_heart = asset.manager.get("purpleheart.png",Texture.class);
cyan_heart = asset.manager.get("cyanheart.png",Texture.class);
doublefuel = asset.manager.get("doublefuel.png",Texture.class);
restore = asset.manager.get("restore.png",Texture.class);
prefs = Gdx.app.getPreferences("My Preferences");
life = prefs.getInteger("LIFE",0);
purchaseManagerConfig = new PurchaseManagerConfig();
purchaseManagerConfig.addOffer(new Offer().setType(OfferType.CONSUMABLE).setIdentifier(cyan_1));
purchaseManagerConfig.addOffer(new Offer().setType(OfferType.CONSUMABLE).setIdentifier(green_2));
purchaseManagerConfig.addOffer(new Offer().setType(OfferType.CONSUMABLE).setIdentifier(purple_3));
purchaseManagerConfig.addOffer(new Offer().setType(OfferType.ENTITLEMENT).setIdentifier(upgrade_fuel));
}
@Override
public void show() {
setPlatformResolver(new AppStoreResolver(this));
getPlatformResolver().installIAP();
}
@Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
game.batch.draw(MainMenu.background_final, camera.position.x - (camera.viewportWidth / 2), 0);
game.font3.draw(game.batch, "BACK",4, camera.viewportHeight - 5);
game.font.draw(game.batch, "1 LIFE",50, camera.viewportHeight/(float)1.5);
game.font.draw(game.batch, "3 LIFE",195, camera.viewportHeight/(float)1.5);
game.font.draw(game.batch, "10 LIFE",340, camera.viewportHeight/(float)1.5);
game.font4.draw(game.batch, "BEST VALUE",320, camera.viewportHeight/(float)1.35);
game.font.draw(game.batch, "FOREVER",490, camera.viewportHeight/(float)1.23);
game.font.draw(game.batch, "DOUBLE",495, camera.viewportHeight/(float)1.35);
game.font.draw(game.batch, "FUEL",507, camera.viewportHeight/(float)1.5);
game.batch.draw(cyan_heart,55,camera.viewportHeight/3);
game.batch.draw(green_heart,200,camera.viewportHeight/3);
game.batch.draw(purple_heart,350,camera.viewportHeight/3);
game.batch.draw(doublefuel,500,camera.viewportHeight/3);
game.batch.draw(restore,(camera.viewportWidth / 2 - restore.getWidth() / 2),camera.viewportHeight/16);
game.font5.draw(game.batch, "RESTORE",271, camera.viewportHeight/5);
if(TimeUtils.millis() - itemTime < 1000){
game.font6.draw(game.batch, "ITEMS RESTORED",230, camera.viewportHeight/(float) 1.1);
}
game.batch.end();
if (Gdx.input.justTouched()) {
touchPos.set(Gdx.input.getX(),Gdx.input.getY(),0);
camera.unproject(touchPos);
if((touchPos.x >= 4 && touchPos.x <= 55) && touchPos.y >= camera.viewportHeight - 18){
game.setScreen(new MainMenu(game,this.asset));
dispose();
}
if((touchPos.x >= 55 && touchPos.x <= 55 + cyan_heart.getWidth()) && (touchPos.y >= camera.viewportHeight/3 && touchPos.y <= camera.viewportHeight/3 + cyan_heart.getHeight())){
getPlatformResolver().requestPurchase(cyan_1);
}
if((touchPos.x >= 200 && touchPos.x <= 200 + green_heart.getWidth()) && (touchPos.y >= camera.viewportHeight/3 && touchPos.y <= camera.viewportHeight/3 + green_heart.getHeight())){
getPlatformResolver().requestPurchase(green_2);
}
if((touchPos.x >= 350 && touchPos.x <= 350 + purple_heart.getWidth()) && (touchPos.y >= camera.viewportHeight/3 && touchPos.y <= camera.viewportHeight/3 + purple_heart.getHeight())){
getPlatformResolver().requestPurchase(purple_3);
}
if((touchPos.x >= 500 && touchPos.x <= 500 + doublefuel.getWidth()) && (touchPos.y >= camera.viewportHeight/3 && touchPos.y <= camera.viewportHeight/3 + doublefuel.getHeight())){
getPlatformResolver().requestPurchase(upgrade_fuel);
}
if((touchPos.x >= (camera.viewportWidth / 2 - restore.getWidth() / 2) && touchPos.x <= (camera.viewportWidth / 2 - restore.getWidth() / 2) + restore.getWidth()) && (touchPos.y >= camera.viewportHeight/16 && touchPos.y <= camera.viewportHeight/16 + restore.getHeight())){
itemTime = TimeUtils.millis();
getPlatformResolver().requestPurchaseRestore();
}
}
}
@Override
public void resize(int width, int height) {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void hide() {
}
@Override
public void dispose() {
getPlatformResolver().dispose();
}
public static PlatformResolver getPlatformResolver() {
return m_platformResolver;
}
public static void setPlatformResolver (PlatformResolver platformResolver) {
m_platformResolver = platformResolver;
}
public int getAppStore () {
return isAppStore;
}
public void setAppStore (int isAppStore) {
this.isAppStore = isAppStore;
}
}
AppStore resolver.Java
import com.badlogic.gdx.pay.PurchaseManagerConfig;
public class AppStoreResolver extends PlatformResolver {
private final static String APPLEKEY = "......";
static final int RC_REQUEST = 10001; // (arbitrary) request code for the purchase flow
public AppStoreResolver(Store game) {
super(game);
PurchaseManagerConfig config = game.purchaseManagerConfig;
config.addStoreParam(PurchaseManagerConfig.STORE_NAME_IOS_APPLE, APPLEKEY);
initializeIAP(null, game.purchaseObserver, config);
}}
这是我在游戏中点击应用内商品时登录xcode:
gdx-pay 4 initializeIAP(): purchaseManager == null => call
PurchaseSystem.hasManager()
IAP 4 IAP: gdx-pay successfully instantiated.
gdx-pay 4 calls PurchaseSystem.install() via reflection
[GdxPay/AppleIOS] Installing purchase observer...
[GdxPay/AppleIOS] Requesting products...
gdx-pay 4 installed manager: AppleiOS
[GdxPay/AppleIOS] 0 products successfully received
[GdxPay/AppleIOS] Invalid product received, purpleheart
[GdxPay/AppleIOS] Invalid product received, greenheart
[GdxPay/AppleIOS] Invalid product received, doublefuel
[GdxPay/AppleIOS] Invalid product received, cyanheart
[GdxPay/AppleIOS] Purchase observer successfully installed!
[GdxPay/AppleIOS] There are 0 unfinished transactions. Try to
finish...
art I 5041 733097 /Users/rolandvigh/Migeran-
1.3/aosp/art/runtime/gc/heap.cc:2729] Background sticky concurrent
mark sweep GC freed 46610(1434KB) AllocSpace objects, 0(0B) LOS
objects, 58% free, 1595KB/3MB, paused 10.712ms total 124.734ms
[GdxPay/AppleIOS] Requesting product info for cyanheart
gdx-pay 4 calls purchasemanager.purchase()
[GdxPay/AppleIOS] Error purchasing product (wrong product info count
returned: 0)!
2018-03-02 14:43:18.738 MyGame[5041:732911] *** Terminating app due
to
uncaught exception 'com.badlogic.gdx.utils.GdxRuntimeException',
reason:
'com.badlogic.gdx.utils.GdxRuntimeException:
java.lang.RuntimeException:
Error purchasing product (wrong product info count returned: 0)!
at com.robot1games.game.Store$1.handlePurchaseError(Store.java:70)
at com.badlogic.gdx.pay.ios.apple.PurchaseManageriOSApple$AppleProductsDelegatePurchase.productsRequestDidReceiveResponse(PurchaseManageriOSApple.java:319)
at apple.uikit.c.UIKit.UIApplicationMain(Native Method)
at com.robot1games.game.IOSMoeLauncher.main(IOSMoeLauncher.java:24)
Caused by: java.lang.RuntimeException: Error purchasing product
(wrong product info count returned: 0)!
... 3 more'
*** First throw call stack:
(0x218af91b 0x2104ae17 0x403219f 0x4038175 0x4041619 0x403f0a4
0x475fb7f 0x475fb6b 0x4764655 0x21871b6d 0x21870067 0x217bf229
0x217bf015 0x22dafac9 0x25e93189 0x403f01c 0x40412d5 0x403a103
0x403a033 0x403ab9b 0x4041619 0x403f0a4 0x3d52851 0x3da1117 0x3da0f0f
0x3e606e5 0x3bffe73 0x3f22b25 0x3aff319 0x174a25 0x21467873)
libc++abi.dylib: terminating with uncaught exception of type
ObjCException
(lldb)
PS:我还需要在xcode中为IAP处理添加任何swift类,如果是的话,我该怎么做这个Libgdx项目。
您的应用程序崩溃因为抛出异常 - Store.java的第70行:
throw new GdxRuntimeException(e);
您是否正确设置了所有应用内购买?以下是有关如何使用测试用户测试您的应用内购买的信息:https://support.magplus.com/hc/en-us/articles/203809008-iOS-How-to-Test-In-App-Purchases-in-Your-App
并且不需要添加任何swift类