准备工作
1、配置好手机的环境(一般是googlePay商城和googlePay服务,必须注册一个账号登录)
2、VPN
3、申请一个googlePay的开发者账号把一些基础信息填好,配好商品D(注:商品ID只能用一次,一但注册好删除后,就无法再次注册商品ID)
4、上传一个包体获得publicKey(代码里面需要)
代码工作
1、准备好androidStudio
2、从他官网的样品中找到aidl这个文件夹存放至Main里面
3、在AndroidManifest中添加权限
<uses-permission android:name="com.android.vending.BILLING" />
4、初始化googlePay
String base64EncodedPublicKey ="xxxxxx";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.enableDebugLogging(true);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Log.d(TAG, "Setup finished.");
if (!result.isSuccess()) {
// Oh noes, there was a problem.2
return;
}
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;
// IAB is fully set up. Now, let's get an inventory of stuff we own.
Log.d(TAG, "Setup successful. Querying inventory.");
try {
mHelper.queryInventoryAsync(mGotInventoryListener);
} catch (IabAsyncInProgressException e) {
complain("Error querying inventory. Another async operation in progress.");
}
}
});
5、其余
import com.linecorp.game.commons.android.shaded.google.gson.Gson;
import com.pokeempire.lineykct.util.IabBroadcastReceiver.IabBroadcastListener;
import com.pokeempire.lineykct.util.IabHelper;
import com.pokeempire.lineykct.util.IabHelper.IabAsyncInProgressException;
import com.pokeempire.lineykct.util.IabResult;
import com.pokeempire.lineykct.util.Inventory;
import com.pokeempire.lineykct.util.Purchase;
import com.unity3d.player.*;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.support.v4.content.ContextCompat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import pub.devrel.easypermissions.EasyPermissions;
public class UnityPlayerActivity extends Activity implements IabBroadcastListener
{
static final String TAG = "JW11";
static final String SKU_PREMIUM = "premium";
static String SKU_GAS = "gas";
static final String SKU_INFINITE_GAS_MONTHLY = "infinite_gas_monthly";
static final String SKU_INFINITE_GAS_YEARLY = "infinite_gas_yearly";
String mInfiniteGasSku = "";
String mFirstChoiceSku = "";
String mSecondChoiceSku = "";
boolean mIsPremium = false;
boolean mAutoRenewEnabled = false;
boolean mSubscribedToInfiniteGas = false;
static final int TANK_MAX = 4;
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
IabHelper mHelper;
static final int RC_REQUEST = 10001;
private int IsRun = 0;
// Setup activity layout
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
IsRun = 0;
checkPermission();
}else {
getWindow().setFormat(PixelFormat.RGBX_8888); // <--- This makes xperia play happy
mUnityPlayer = new UnityPlayer(this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
String locale = mUnityPlayer.getResources().getConfiguration().locale.getCountry();
Log.d(TAG, locale+"11111111111111");
String base64EncodedPublicKey ="xxxxxxxx";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.enableDebugLogging(true);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Log.d(TAG, "Setup finished.");
if (!result.isSuccess()) {
// Oh noes, there was a problem.2
return;
}
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;
// IAB is fully set up. Now, let's get an inventory of stuff we own.
Log.d(TAG, "Setup successful. Querying inventory.");
try {
mHelper.queryInventoryAsync(mGotInventoryListener);
} catch (IabAsyncInProgressException e) {
complain("Error querying inventory. Another async operation in progress.");
}
}
});
Log.e("unity", "初始化");
}
}
// 声明一个数组,用来存储所有需要动态申请的权限
String[] permissions = new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
// Manifest.permission.CHANGE_WIFI_STATE,
// Manifest.permission.ACCESS_WIFI_STATE,
// Manifest.permission.ACCESS_COARSE_LOCATION,
// Manifest.permission.ACCESS_FINE_LOCATION
};
// 声明一个集合,在后面的代码中用来存储用户拒绝授权的权
List<String> mPermissionList = new ArrayList<>();
boolean mShowRequestPermission = true;//用户是否禁止权限
private void checkPermission() {
mPermissionList.clear();
/**
* 判断哪些权限未授予
* 以便必要的时候重新申请
*/
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
mPermissionList.add(permission);
}
}
/**
* 判断存储委授予权限的集合是否为空
*/
if (!mPermissionList.isEmpty() && Build.VERSION.SDK_INT > 24)
{
// 后续操作...
String[] aa = new String[mPermissionList.size()];
for (int i = 0;i<mPermissionList.size();i++ )
{
aa[i] = mPermissionList.get(i);
}
EasyPermissions.requestPermissions(this, "手机状态信息", 100,aa);
}
else
{//未授予的权限为空,表示都授予了
// 后续操作...
RunGame();
}
}
public String GetAndroidName(String arg){
String model = getPhoneModel();
return model;
}
public String getPhoneModel() {
return android.os.Build.MODEL;
}
public void RunGame()
{
if(IsRun == 1)
return;
IsRun = 1;
getWindow().setFormat(PixelFormat.RGBX_8888); // <--- This makes xperia play happy
mUnityPlayer = new UnityPlayer(this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
String locale = mUnityPlayer.getResources().getConfiguration().locale.getCountry();
String base64EncodedPublicKey ="xxxxxxxxxx";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.enableDebugLogging(true);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Log.d(TAG, "Setup finished.");
if (!result.isSuccess()) {
// Oh noes, there was a problem.2
return;
}
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;
// IAB is fully set up. Now, let's get an inventory of stuff we own.
Log.d(TAG, "Setup successful. Querying inventory.");
try {
mHelper.queryInventoryAsync(mGotInventoryListener);
} catch (IabAsyncInProgressException e) {
complain("Error querying inventory. Another async operation in progress.");
}
}
});
Log.e("unity", "初始化");
}
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
Log.d(TAG, "Query inventory finished.");
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;
// Is it a failure?
if (result.isFailure()) {
complain("Failed to query inventory: " + result);
return;
}
Log.d(TAG, "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().
*/
// Do we have the premium upgrade?
Purchase premiumPurchase = inventory.getPurchase(SKU_PREMIUM);
mIsPremium = (premiumPurchase != null && verifyDeveloperPayload(premiumPurchase));
Log.d(TAG, "User is " + (mIsPremium ? "PREMIUM" : "NOT PREMIUM"));
// First find out which subscription is auto renewing
Purchase gasMonthly = inventory.getPurchase(SKU_INFINITE_GAS_MONTHLY);
Purchase gasYearly = inventory.getPurchase(SKU_INFINITE_GAS_YEARLY);
if (gasMonthly != null && gasMonthly.isAutoRenewing()) {
mInfiniteGasSku = SKU_INFINITE_GAS_MONTHLY;
mAutoRenewEnabled = true;
} else if (gasYearly != null && gasYearly.isAutoRenewing()) {
mInfiniteGasSku = SKU_INFINITE_GAS_YEARLY;
mAutoRenewEnabled = true;
} else {
mInfiniteGasSku = "";
mAutoRenewEnabled = false;
}
// The user is subscribed if either subscription exists, even if neither is auto
// renewing
mSubscribedToInfiniteGas = (gasMonthly != null && verifyDeveloperPayload(gasMonthly))
|| (gasYearly != null && verifyDeveloperPayload(gasYearly));
Log.d(TAG, "User " + (mSubscribedToInfiniteGas ? "HAS" : "DOES NOT HAVE")
+ " infinite gas subscription.");
// Check for gas delivery -- if we own gas, we should fill up the tank immediately
Log.d("SKU_GAS=", SKU_GAS);
Purchase gasPurchase = inventory.getPurchase(SKU_GAS);
if (gasPurchase != null && verifyDeveloperPayload(gasPurchase)) {
Log.d(TAG, "We have gas. Consuming it.");
try {
mHelper.consumeAsync(inventory.getPurchase(SKU_GAS), mConsumeFinishedListener);
} catch (IabAsyncInProgressException e) {
complain("Error consuming gas. Another async operation in progress.");
}
return;
}else {
Log.d("SKU_GAS=", SKU_GAS);
}
Log.d(TAG, "Initial inventory query finished; enabling main UI.");
}
};
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() {
public void onConsumeFinished(Purchase purchase, IabResult result) {
Log.d(TAG, "Consumption finished. Purchase: " + purchase + ", result: " + result);
// if we were disposed of in the meantime, quit.
if (mHelper == null) return;
// We know this is the "gas" sku because it's the only one we consume,
// so we don't check which sku was consumed. If you have more than one
// sku, you probably should check...
if (result.isSuccess()) {
// successfully consumed, so we apply the effects of the item in our
// game world's logic, which in our case means filling the gas tank a bit
// game world's logic, which in our case means filling the gas tank a bit
Log.d(TAG, "Consumption successful. Provisioning.");
Map<String, Object> map = new HashMap<String, Object>();
map.put("signtureData", purchase.getOriginalJson());
map.put("signture",purchase.getSignature());
String json = new Gson().toJson(map);
mUnityPlayer.UnitySendMessage("Main","PostGooglePay",json);
}
else {
complain("Error while consuming: " + result);
}
Log.d(TAG, "End consumption flow.");
}
};
public void LineGooglePay(String id,String orderId ){
Log.i(TAG,"支付调起");
Log.d(TAG, "支付调起"+id);
SKU_GAS=id;
try {
mHelper.launchPurchaseFlow(this, id, RC_REQUEST, mPurchaseFinishedListener, orderId);
} catch (IabAsyncInProgressException e) {
complain("Error launching purchase flow. Another async operation in progress.");
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);
if (mHelper == null) return;
// Pass on the activity result to the helper for handling
if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
// not handled, so handle it ourselves (here's where you'd
// perform any handling of activity results not related to in-app
// billing...
super.onActivityResult(requestCode, resultCode, data);
}
else {
Log.d(TAG, "onActivityResult handled by IABUtil.");
}
}
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);
// if we were disposed of in the meantime, quit.
if (mHelper == null) return;
if (result.isFailure()) {
complain("Error purchasing: " + result);
return;
}
if (!verifyDeveloperPayload(purchase)) {
complain("Error purchasing. Authenticity verification failed.");
return;
}
Log.d(TAG, "Purchase successful.");
try {
mHelper.consumeAsync(purchase, mConsumeFinishedListener);
} catch (IabAsyncInProgressException e) {
complain("Error consuming gas. Another async operation in progress.");
return;
}
}
};
@Override
public void receivedBroadcast() {
// Received a broadcast notification that the inventory of items has changed
Log.d(TAG, "Received broadcast notification. Querying inventory.");
try {
mHelper.queryInventoryAsync(mGotInventoryListener);
} catch (IabAsyncInProgressException e) {
complain("Error querying inventory. Another async operation in progress.");
}
}
boolean verifyDeveloperPayload(Purchase p) {
String payload = p.getDeveloperPayload();
/*
* TODO: verify that the developer payload of the purchase is correct. It will be
* the same one that you sent when initiating the purchase.
*
* WARNING: Locally generating a random string when starting a purchase and
* verifying it here might seem like a good approach, but this will fail in the
* case where the user purchases an item on one device and then uses your app on
* a different device, because on the other device you will not have access to the
* random string you originally generated.
*
* So a good developer payload has these characteristics:
*
* 1. If two different users purchase an item, the payload is different between them,
* so that one user's purchase can't be replayed to another user.
*
* 2. The payload must be such that you can verify it even when the app wasn't the
* one who initiated the purchase flow (so that items purchased by the user on
* one device work on other devices owned by the user).
*
* Using your own server to store and verify developer payloads across app
* installations is recommended.
*/
return true;
}
void complain(String message) {
//Log.e(TAG, "**** TrivialDrive Error: " + message);
//alert("Error: " + message);
}
void alert(String message) {
AlertDialog.Builder bld = new AlertDialog.Builder(this);
bld.setMessage(message);
bld.setNeutralButton("OK", null);
Log.d(TAG, "Showing alert dialog: " + message);
bld.create().show();
}
// Quit Unity
@Override protected void onDestroy ()
{
mUnityPlayer.quit();
super.onDestroy();
if (mHelper != null) {
try {
mHelper.dispose();
} catch (IabAsyncInProgressException e) {
e.printStackTrace();
}
}
mHelper = null;
}
// Pause Unity
@Override protected void onPause()
{
super.onPause();
mUnityPlayer.pause();
}
// Resume Unity
@Override protected void onResume()
{
super.onResume();
mUnityPlayer.resume();
}
// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}
来源:oschina
链接:https://my.oschina.net/u/4287454/blog/3913459