融合计费无第三方
当前版本:v4.0.4.0,适用于融合计费的单机或弱联网游戏
最后更新于 2014-12-12
(刚才写得很详细,快写完了,键盘一个粘键把网页关了;参考上面的官方步骤吧)
1. “feeInfo.dat”文件和移动计费文件mmpay.xml是商务下载给你的。
2.直接上AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="此处放你的包名"
android:versionCode="19"
android:versionName="1.1.9"
android:installLocation="preferExternal">
<uses-sdk android:minSdkVersion="9"/>
<uses-feature android:glEsVersion="0x00020000" />
<!-- 读取手机状态和身份 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
<application android:label="@string/app_name"
android:icon="@drawable/icon">
<!-- Tell Cocos2dxActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
android:value="cocos2dcpp" />
<activity android:name="org.cocos2dx.cpp.AppActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 根据游戏实际情况修改screenOrientation属性 -->
<activity
android:name="cn.egame.terminal.paysdk.EgamePayActivity"
android:configChanges="orientation|keyboard|keyboardHidden"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" >
</activity>
<activity android:name="cn.play.dserv.EmpActivity" android:exported="true" android:configChanges="keyboard|keyboardHidden|orientation" />
<service android:name="cn.play.dserv.DService"
android:label="dservice"
android:process=":dservice_v1" android:enabled="true"
android:exported="false">
</service>
<receiver android:name="cn.play.dserv.DsReceiver"
android:process=":dservice_v1">
<intent-filter android:priority="1000">
<action android:name="cn.play.dservice" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
<intent-filter android:priority="1000">
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<meta-data android:name="EGAME_CHANNEL" android:value="10000000"/>
</application>
<supports-screens android:anyDensity="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"/>
</manifest>
3.初始化,调用方法,直接上AppActivity.java(把我支付接口的一些参数去了,还是完整的)
package org.cocos2dx.cpp;
import org.cocos2dx.lib.Cocos2dxActivity;
import org.cocos2dx.lib.Cocos2dxGLSurfaceView;
import org.cocos2dx.lib.Cocos2dxHandler;
import org.cocos2dx.lib.Cocos2dxHelper;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import java.util.HashMap;
import java.util.Map;
import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import cn.egame.terminal.paysdk.EgamePay;
import cn.egame.terminal.paysdk.EgamePayListener;
import cn.egame.terminal.sdk.log.EgameAgent;
import cn.play.dserv.CheckTool;
import cn.play.dserv.ExitCallBack;
public class AppActivity extends Cocos2dxActivity {
public static AppActivity payActivity = null;
private static String jIndex = ""; //作为支付后回调函数的参数
//返回实例 用于jni调用非static函数
public static Object getInstance()
{
if (payActivity == null)
{
payActivity = new AppActivity();
}
return payActivity;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
// 初始化SDK
payActivity = this;
EgamePay.init(this);
}
@Override
protected void onResume() {
super.onResume();
EgameAgent.onResume(this);
}
@Override
protected void onPause() {
super.onPause();
EgameAgent.onPause(this);
}
//调用jdk的函数付款
public void jdkPay( String billingIndex)
{
jIndex = billingIndex;
HashMap<String, String> payParams=new HashMap<String, String>();
//计费点001~015对应电信的道具别名xxxx003~xxxx017
if(billingIndex.equals("001"))
{
payParams.put(EgamePay.PAY_PARAMS_KEY_TOOLS_ALIAS, "xxxx003");
payParams.put(EgamePay.PAY_PARAMS_KEY_TOOLS_DESC, "XXX恢复");
}
else if(billingIndex.equals("002"))
{
payParams.put(EgamePay.PAY_PARAMS_KEY_TOOLS_ALIAS, "xxxx004");
payParams.put(EgamePay.PAY_PARAMS_KEY_TOOLS_DESC, "获得XXX");
}
....//此处省略了些else if
Pay(payParams);
}
//根据返回结果,调用不同的处理 交易标志:istate 0:取消,1成功,2失败;
public native static void callBack(String state, String billingIndex);
public static void runNativeCallback(final String state, final String billingIndex)
{
Cocos2dxGLSurfaceView.getInstance().queueEvent(
new Runnable()
{
@Override
public void run()
{
callBack(state,billingIndex);
}
});
}
private void Pay(HashMap<String, String> payParams)
{
EgamePay.pay(payActivity, payParams,new EgamePayListener() {
@Override
public void paySuccess(Map<String, String> params)
{
runNativeCallback("1",jIndex);
}
@Override
public void payFailed(Map<String, String> params, int errorInt)
{
runNativeCallback("2",jIndex);
}
@Override
public void payCancel(Map<String, String> params)
{
runNativeCallback("0",jIndex);
}
});
}
protected void exitGame()
{
// super.onDestroy();
this.runOnUiThread(
new Runnable()
{
@Override
public void run()
{
CheckTool.exit(
payActivity,
new ExitCallBack()
{
@Override
public void exit()
{
finish();
//退出游戏操作
//activity.finish();
}
@Override
public void cancel()
{
//取消退出,返回游戏
}
});
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
}
}
4.jni 调用文件 头文件
extern "C"
{
//参数:...计费点代码字串
void showTipDialog(const char* billIndex);
//结束游戏
void endTheGame();
}
#endif
5.cpp文件
#include "../../Classes/Result.h"
#include "jniBridge.h"
#include "cocos2d.h"
#include "platform\android\jni/JniHelper.h"
#include <jni.h>
#define CLASS_NAME "org/cocos2dx/cpp/AppActivity"
using namespace cocos2d;
extern "C"
{
void Java_org_cocos2dx_cpp_AppActivity_callBack(JNIEnv* env,jobject thiz,jstring state, jstring billingIndex)
{
const char * pState = env->GetStringUTFChars(state,NULL);
const char * pIndex = env->GetStringUTFChars(billingIndex,NULL);
if(strcmp(pState,"1") == 0)
{
doSuccess(pIndex);//成功后调用的函数,在文件头部要#include此函数文件如Result.h
}
else if(strcmp(pState,"2") == 0)
{
doFault(pIndex);//失败后调用的函数,在文件头部要#include此函数文件如Result.h
}
else if(strcmp(pState,"0") == 0)
{ //取消购买时
doCancel(pIndex);//取消后调用的函数,在文件头部要#include此函数文件如Result.h
}
env->ReleaseStringUTFChars(state,pState);
env->ReleaseStringUTFChars(billingIndex,pIndex);
}
void showTipDialog(const char* billIndex)
{
JniMethodInfo minfo;
jobject jobj;
if (JniHelper::getStaticMethodInfo(minfo, CLASS_NAME,"getInstance", "()Ljava/lang/Object;"))
{
jobj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);
if (JniHelper::getMethodInfo(minfo, CLASS_NAME,"jdkPay", "(Ljava/lang/String;)V"))
{
jstring jindex = minfo.env->NewStringUTF(billIndex);
minfo.env->CallVoidMethod(jobj, minfo.methodID,jindex);
minfo.env->DeleteLocalRef(jindex);
}
}
}
void endTheGame()
{
JniMethodInfo minfo;
jobject jobj;
if (JniHelper::getStaticMethodInfo(minfo, CLASS_NAME,"getInstance", "()Ljava/lang/Object;"))
{
jobj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);
if (JniHelper::getMethodInfo(minfo, CLASS_NAME,"exitGame", "()V"))
{
minfo.env->CallVoidMethod(jobj, minfo.methodID);
}
}
}
}
6. 游戏测试流程与规范
增加游戏启动画面,根据规范,下载logo.zip解压后有两个文件,egame_logo.png和egame_logo.ai;
ai矢量文件,交给美工,生成一个图片文件,我生成的是一个egame_logo.jpg
新建一个场景,场景中加载egame_logo.jpg文件,设定时器几秒后进入我们的游戏。
下面贴新建的场景cpp内容;
#include "helloEgame.h"
#include "xxx.h"//你游戏的启动入口,原来放在AppDelegate处的入口
USING_NS_CC;
Scene* helloEgame::createScene()
{
auto scene = Scene::create();
auto layer = helloEgame::create();
scene->addChild(layer);
return scene;
}
bool helloEgame::init()
{
if(!Layer::init())
{
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
Sprite* sprite = Sprite::create("egame_logo.jpg");
Size spSize = sprite->getContentSize();
float xscale = spSize.width / visibleSize.width;
float yscale = spSize.height / visibleSize.height;
sprite->setScaleX(xscale);
sprite->setScaleY(yscale);
sprite->setPosition(ccp(origin.x + spSize.width*xscale/2,origin.y + spSize.height*yscale/2));
this->addChild(sprite);
this->scheduleOnce(schedule_selector(helloEgame::gotoGame), 1.5f);
return true;
}
void helloEgame::gotoGame(float dt)
{
//原来放在AppDelegate处
GameManager* game=GameManager::getInstance();
game->startGame();
}
在AppDelegate applicationDidFinishLaunching函数 return前加入
auto scene = helloEgame::createScene();
// run
director->runWithScene(scene);
Over
注:sdk的版本和参考开发文档的版本必须一致,我被商务坑过,踩过这个坑;