游戏sdk接入教程:360渠道SDK接入
官方文档及SDK的下载地址为:http://dev.360.cn/wiki/index/id/73
在接入之前,需先在360后台创建游戏,获取一些接入参数。
客户端所需要参数包括:APPID、APPKEY、PRIVATEKEY 三个值填写在 AndroidManifest 文件中,不能使用@string 引用;禁止把 AppSecret 保存在手机客户端,AndroidManifest 中存放的是 Private Key,而非 App-Secret。
Private Key 的算法为:QHOPENSDK_PRIVATEKEY = MD5(appSecret + "#" + appKey),格式为 32 位小写。
准备工作做为,正式开始接入,首先肯定是把所需要的资源如JAR包之类的复制到我的工程中去。
我这边的接入环境是Eclipse
打开我们下载好解压出来的文档目录找到所需要依赖的JAR包
红框所示就是我们Eclipse所需要的资源文件了。
把assets内的文件复制到我们自己工程中的assets目录内。
把libs内的文件复制到我们自己工程中的libs目录内。
下图中红框内的文件夹按自己所需要复制
至于demo工程如何创建在上一篇的接入文档中有详细教程,请至:
http://www.cnblogs.com/laohaizei/p/6724250.html
复制完成之后,我们的demo目录应该是多了这些目录
至此,我们已经把所有需要的东西都复制到了我们的demo工程中。
首先我们打开我们工程的AndroidManifest.xml文件。
然后复制以下代码
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.demo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" /> <!-- 亲加sdk所需权限 --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" /> <uses-permission android:name="android.permission.SET_WALLPAPER" /> <uses-permission android:name="android.permission.BATTERY_STATS" /> <uses-permission android:name="android.permission.GET_PACKAGE_SIZE" /> <uses-permission android:name="android.permission.GET_TASKS" /> <uses-permission android:name="android.permission.RESTART_PACKAGES" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_LOGS" /> <uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_SMS" /> <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" /> <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- 添加360SDK必需要的权限。begin --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_SMS" /> <!-- payment --> <uses-permission android:name="android.permission.GET_TASKS" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.RESTART_PACKAGES" /> <uses-permission android:name="android.webkit.permission.PLUGIN" /> <!-- 浮窗 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.VIBRATE" /> <!-- 微信分享相关 --> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <!-- qiku start --> <!-- 系统账户操作权限 --> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" /> <uses-permission android:name="android.permission.USE_CREDENTIALS" /> <!-- 系统设置操作权限 --> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.READ_SETTINGS" /> <!-- qiku end --> <!-- QDAS打点SDK所需权限 --> <uses-permission android:name="android.permission.READ_LOGS" /> <!-- 添加360SDK必需要的权限。end --> <application android:name="com.qihoo.gamecenter.sdk.matrix.QihooApplication" android:allowBackup="false" android:icon="@drawable/demo_icon" android:label="@string/demo_app_name" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 添加360SDK必需的activity:com.qihoopay.insdk.activity.ContainerActivity --> <activity android:name="com.qihoo.gamecenter.sdk.activity.ContainerActivity" android:configChanges="fontScale|orientation|keyboardHidden|locale|navigation|screenSize|uiMode|layoutDirection" android:exported="true" android:theme="@android:style/Theme.Translucent.NoTitleBar" > <!-- 支付宝签约后自动跳转到sdk配置 --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <!-- android host的值必须为游戏的包名 --> <data android:host="com.example.demo" /> <!-- android scheme的值必须不能变 --> <data android:scheme="qihooonlinepay" /> </intent-filter> </activity> <!-- payment activities begin --> <!-- 添加360SDK必需的activity:com.qihoopp.qcoinpay.QcoinActivity --> <activity android:name="com.qihoopp.qcoinpay.QcoinActivity" android:configChanges="fontScale|orientation|keyboardHidden|locale|navigation|screenSize|uiMode" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:windowSoftInputMode="stateAlwaysHidden|adjustResize" > </activity> <!-- alipay sdk begin --> <activity android:name="com.alipay.sdk.app.H5PayActivity" android:screenOrientation="portrait" > </activity> <!-- alipay sdk end --> <!-- 微信支付界面 --> <activity android:name="com.iapppay.pay.channel.weixinpay.WeixinWapPayActivity" android:configChanges="screenSize|orientation|keyboard|navigation|layoutDirection" android:theme="@android:style/Theme.Translucent" /> <activity android:name="com.junnet.heepay.ui.activity.WelcomeActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:excludeFromRecents="true" android:screenOrientation="behind" android:theme="@android:style/Theme.Dialog" android:windowSoftInputMode="stateAlwaysHidden|adjustResize" /> <activity android:name="com.junnet.heepay.ui.activity.WechatPaymentActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:excludeFromRecents="true" android:screenOrientation="behind" android:theme="@android:style/Theme.Dialog" android:windowSoftInputMode="stateAlwaysHidden|adjustResize" /> <activity android:name="com.ipaynow.plugin.activity.PayMethodActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:exported="false" android:screenOrientation="behind" android:theme="@android:style/Theme.Dialog" /> <activity android:name="com.ipaynow.plugin.inner_plugin.wechat_plugin.activity.WeChatNotifyActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:screenOrientation="behind" android:theme="@android:style/Theme.NoDisplay" /> <!-- 以下两个Activity是SDK插件化使用的代理Activity --> <activity android:name="com.qihoo.sdkplugging.host.HostProxyActivity" android:configChanges="fontScale|orientation|keyboardHidden|locale|navigation|screenSize|uiMode|layoutDirection" android:label="360SDK" android:theme="@android:style/Theme.Translucent.NoTitleBar" > <intent-filter> <action android:name="com.qihoo.sdkplugging.host.proxy.activity.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <!-- payment activities end --> <meta-data android:name="QHOPENSDK_APPKEY" android:value="@app_key@" > </meta-data> <meta-data android:name="QHOPENSDK_PRIVATEKEY" android:value="@private_key@" > </meta-data> <meta-data android:name="QHOPENSDK_APPID" android:value="@app_id@" > </meta-data> <!-- 如下是360游戏实时推送SDK必要声明,不可修改 --> <receiver android:name="com.qihoo.psdk.local.QBootReceiver" android:permission="android.permission.RECEIVE_BOOT_COMPLETED" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver> <activity android:name="com.qihoo.psdk.app.QStatActivity" android:launchMode="singleInstance" android:theme="@android:style/Theme.Translucent.NoTitleBar" > </activity> <service android:name="com.qihoo.psdk.remote.QRemoteService" android:exported="true" android:process=":QRemote" > <intent-filter> <action android:name="com.qihoo.psdk.service.action.remote" /> </intent-filter> </service> <service android:name="com.qihoo.psdk.local.QLocalService" android:exported="true" android:process=":QLocal" > <intent-filter> <action android:name="com.qihoo.psdk.service.action.local" /> </intent-filter> </service> <!-- 推送SDK end --> <!-- 微信SDK --> <!-- 微信相关的activity,如果游戏接入微信分享需要在游戏工程内实现这个activity,请直接使用demo中的代码实现,并放在游戏的工程的对应路径下。 --> <activity android:name=".wxapi.WXEntryActivity" android:exported="true" android:label="@string/app_name" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> <!-- 从微信开放平台申请的appid,游戏需要去申请自己的appid --> <meta-data android:name="QHOPENSDK_WEIXIN_APPID" android:value="@wx_app_id@" > </meta-data> <!-- 注意:此处的微信 appid 申请只与微信分享有关,微信支付功能无需 appid 即可使用 --> <!-- 微信SDK end --> <!-- UpdateLib start --> <activity android:name="com.qihoo.updatesdk.lib.UpdateTipDialogActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:exported="false" android:screenOrientation="portrait" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> <service android:name="com.qihoo.appstore.updatelib.CheckUpdateService" android:exported="false" /> <!-- UpdateLib end --> <!-- gameunion plugin start --> <activity android:name="com.qihoo.gameunionforsdk.SimpleWebView" android:configChanges="fontScale|orientation|keyboardHidden|locale|navigation|screenSize|uiMode|layoutDirection" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> <!-- gameunion plugin end --> <!-- 默认参数,不需要修改,直接复制就行 --> <meta-data android:name="DC_APPKEY" android:value="02522a2b2726fb0a03bb19f2d8d9524d" /> </application> </manifest>
以上是需要添加在AndroidManifest.xml中的。(@xxx@部分请注意替换修改,具体有:@app_key@、@private_key@、@app_id@、@wx_app_id@)
然后到我们demo工程的AndroidManifest.xml全选替换粘贴
这样AndroidManifest.xml修改好了。
做完以上步骤,接下来,我们开始接入SDK的接口。
首先打开我们的MainActivity.java
打开的MainActivity.java应该是这个样子的
然后把下面的代码复制进去,注意别把第一行的代码覆盖了。
import java.util.HashMap; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import com.qihoo.gamecenter.sdk.activity.ContainerActivity; import com.qihoo.gamecenter.sdk.common.IDispatcherCallback; import com.qihoo.gamecenter.sdk.matrix.Matrix; import com.qihoo.gamecenter.sdk.protocols.CPCallBackMgr.MatrixCallBack; import com.qihoo.gamecenter.sdk.protocols.ProtocolConfigs; import com.qihoo.gamecenter.sdk.protocols.ProtocolKeys; public class MainActivity extends Activity { final static String TAG = "demo"; boolean isInit = false; Activity appActivity = MainActivity.this; Context appContext = this; public boolean isLoginFinished = false; public boolean isInitFinished = false; private boolean mIsInOffline = false; private boolean isLandScape = true; private boolean isShowClose = false; // 是否显示关闭按钮 private boolean isSupportOffline = false; // 可选参数,是否支持离线模式,默认值为false private boolean isShowSwitchButton = true; // 可选参数,是否在自动登录的过程中显示切换账号按钮 private boolean isHideWellcome = false; // 可选参数,是否隐藏欢迎界面 private boolean isShowDlgOnFailedAutoLogin = true; // 可选参数,静默自动登录失败后是否显示登录窗口,默认不显示 private boolean isAutoLoginHideUI = false; // 可选参数,自动登录过程中是否不展示任何UI,默认展示。 private boolean isDebugSocialShare = true; // 测试参数,发布时要去掉 protected String mAccessToken = null; // private ProgressDialog mProgress; // AccessToken是否有效 protected static boolean isAccessTokenValid = true; // QT是否有效 protected static boolean isQTValid = true; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); Matrix.onPause(appActivity); } @Override protected void onRestart() { // TODO Auto-generated method stub super.onRestart(); Matrix.onRestart(appActivity); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); Matrix.onResume(appActivity); } @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); Matrix.onStart(appActivity); } @Override protected void onStop() { // TODO Auto-generated method stub super.onStop(); Matrix.onStop(appActivity); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Matrix.destroy(this); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); Matrix.onActivityResult(appActivity, requestCode, resultCode, data); } @Override protected void onNewIntent(Intent intent) { // TODO Auto-generated method stub super.onNewIntent(intent); Matrix.onNewIntent(appActivity, intent); } private void init() { // TODO Auto-generated method stub MatrixCallBack mSDKCallback = new MatrixCallBack() { @Override public void execute(Context context, int functionCode, String functionParams) { // TODO Auto-generated method stub if (functionCode == ProtocolConfigs.FUNC_CODE_SWITCH_ACCOUNT) { // 调用 sdk 的切换帐号接口 doSdkSwitchAccount(getLandscape(context)); } else if (functionCode == ProtocolConfigs.FUNC_CODE_INITSUCCESS) { // 这里返回成功之后才能调用 SDK 其它接口 TypeSDKLogger.d( // "initSDK success"); isInit = true; } } }; // 调用其他SDK接口之前必须先调用init Matrix.init(appActivity, mSDKCallback); } protected boolean getLandscape(Context context) { if (context == null) { return false; } boolean landscape = (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE); return landscape; } /** * 使用360SDK的切换账号接口 * * @param isLandScape * 是否横屏显示登录界面 */ protected void doSdkSwitchAccount(boolean isLandScape) { Intent intent = getSwitchAccountIntent(isLandScape); IDispatcherCallback callback = mAccountSwitchCallback; if (isSupportOffline) { callback = mAccountSwitchSupportOfflineCB; } Matrix.invokeActivity(appActivity, intent, callback); } /*** * 生成调用360SDK切换账号接口的Intent * * @param isLandScape * 是否横屏 * @param isBgTransparent * 是否背景透明 * @param clientId * 即AppKey * @return Intent */ private Intent getSwitchAccountIntent(boolean isLandScape) { Intent intent = new Intent(appActivity, ContainerActivity.class); // 界面相关参数,360SDK界面是否以横屏显示。 intent.putExtra(ProtocolKeys.IS_SCREEN_ORIENTATION_LANDSCAPE, isLandScape); // 必需参数,使用360SDK的切换账号模块。 intent.putExtra(ProtocolKeys.FUNCTION_CODE, ProtocolConfigs.FUNC_CODE_SWITCH_ACCOUNT); // 是否显示关闭按钮 intent.putExtra(ProtocolKeys.IS_LOGIN_SHOW_CLOSE_ICON, isShowClose); // 可选参数,是否支持离线模式,默认值为false intent.putExtra(ProtocolKeys.IS_SUPPORT_OFFLINE, isSupportOffline); // 可选参数,是否在自动登录的过程中显示切换账号按钮 intent.putExtra(ProtocolKeys.IS_SHOW_AUTOLOGIN_SWITCH, isShowSwitchButton); // 可选参数,是否隐藏欢迎界面 intent.putExtra(ProtocolKeys.IS_HIDE_WELLCOME, isHideWellcome); // 可选参数,登录界面的背景图片路径,必须是本地图片路径 // intent.putExtra(ProtocolKeys.UI_BACKGROUND_PICTRUE, // getUiBackgroundPicPath()); // 可选参数,指定assets中的图片路径,作为背景图 // intent.putExtra(ProtocolKeys.UI_BACKGROUND_PICTURE_IN_ASSERTS, // getUiBackgroundPathInAssets()); // -- 以下参数仅仅针对自动登录过程的控制 // 可选参数,自动登录过程中是否不展示任何UI,默认展示。 intent.putExtra(ProtocolKeys.IS_AUTOLOGIN_NOUI, isAutoLoginHideUI); // 可选参数,静默自动登录失败后是否显示登录窗口,默认不显示 intent.putExtra(ProtocolKeys.IS_SHOW_LOGINDLG_ONFAILED_AUTOLOGIN, isShowDlgOnFailedAutoLogin); // 测试参数,发布时要去掉 intent.putExtra(ProtocolKeys.IS_SOCIAL_SHARE_DEBUG, isDebugSocialShare); return intent; } // 切换账号的回调 private IDispatcherCallback mAccountSwitchCallback = new IDispatcherCallback() { @Override public void onFinished(String data) { // press back if (isCancelLogin(data)) { return; } // 显示一下登录结果 // Toast.makeText(appActivity, data, Toast.LENGTH_LONG).show(); // TypeSDKLogger.d( "mAccountSwitchCallback, data is " + data); // 解析User info // QihooUserInfo info = parseUserInfoFromLoginResult(data); // 解析access_token mAccessToken = parseAccessTokenFromLoginResult(data); } }; // 支持离线模式的切换账号的回调 private IDispatcherCallback mAccountSwitchSupportOfflineCB = new IDispatcherCallback() { @Override public void onFinished(String data) { // press back if (isCancelLogin(data)) { return; } // 显示一下登录结果 // Toast.makeText(appActivity, data, Toast.LENGTH_LONG).show(); // TypeSDKLogger.d( "mAccountSwitchSupportOfflineCB, data is " + data); // 解析User info // 解析access_token mAccessToken = parseAccessTokenFromLoginResult(data); } }; private void login() { mIsInOffline = false; Intent intent = getLoginIntent(isLandScape); IDispatcherCallback callback = mLoginCallback; if (isSupportOffline) { callback = mLoginCallbackSupportOffline; } Matrix.execute(appActivity, intent, callback); } /** * 生成调用360SDK登录接口的Intent * * @param isLandScape * 是否横屏 * @return intent */ private Intent getLoginIntent(boolean isLandScape) { Intent intent = new Intent(appActivity, ContainerActivity.class); // 界面相关参数,360SDK界面是否以横屏显示。 intent.putExtra(ProtocolKeys.IS_SCREEN_ORIENTATION_LANDSCAPE, isLandScape); // 必需参数,使用360SDK的登录模块。 intent.putExtra(ProtocolKeys.FUNCTION_CODE, ProtocolConfigs.FUNC_CODE_LOGIN); // 是否显示关闭按钮 intent.putExtra(ProtocolKeys.IS_LOGIN_SHOW_CLOSE_ICON, isShowClose); // 可选参数,是否支持离线模式,默认值为false intent.putExtra(ProtocolKeys.IS_SUPPORT_OFFLINE, isSupportOffline); // 可选参数,是否在自动登录的过程中显示切换账号按钮 intent.putExtra(ProtocolKeys.IS_SHOW_AUTOLOGIN_SWITCH, isShowSwitchButton); // 可选参数,是否隐藏欢迎界面 intent.putExtra(ProtocolKeys.IS_HIDE_WELLCOME, isHideWellcome); // 可选参数,登录界面的背景图片路径,必须是本地图片路径 // intent.putExtra(ProtocolKeys.UI_BACKGROUND_PICTRUE, // getUiBackgroundPicPath()); // 可选参数,指定assets中的图片路径,作为背景图 // intent.putExtra(ProtocolKeys.UI_BACKGROUND_PICTURE_IN_ASSERTS, // getUiBackgroundPathInAssets()); // -- 以下参数仅仅针对自动登录过程的控制 // 可选参数,自动登录过程中是否不展示任何UI,默认展示。 intent.putExtra(ProtocolKeys.IS_AUTOLOGIN_NOUI, isAutoLoginHideUI); // 可选参数,静默自动登录失败后是否显示登录窗口,默认不显示 intent.putExtra(ProtocolKeys.IS_SHOW_LOGINDLG_ONFAILED_AUTOLOGIN, isShowDlgOnFailedAutoLogin); // 测试参数,发布时要去掉 intent.putExtra(ProtocolKeys.IS_SOCIAL_SHARE_DEBUG, isDebugSocialShare); return intent; } // 登录、注册的回调 private IDispatcherCallback mLoginCallback = new IDispatcherCallback() { @Override public void onFinished(String data) { // press back if (isCancelLogin(data)) { // doSdkLogin(true); return; } // 显示一下登录结果 Log.d(TAG, "login callback data:" + data); mIsInOffline = false; // 解析access_token mAccessToken = parseAccessTokenFromLoginResult(data); } }; private IDispatcherCallback mLoginCallbackSupportOffline = new IDispatcherCallback() { @Override public void onFinished(String data) { if (isCancelLogin(data)) { return; } Log.d(TAG, "mLoginCallbackSupportOffline, data is " + data); try { JSONObject joRes = new JSONObject(data); JSONObject joData = joRes.getJSONObject("data"); String mode = joData.optString("mode", ""); if (!TextUtils.isEmpty(mode) && mode.equals("offline")) { // Toast.makeText(appActivity, // "login success in offline mode", // Toast.LENGTH_SHORT).show(); mIsInOffline = true; // 显示一下登录结果 // Toast.makeText(appActivity, data, // Toast.LENGTH_LONG).show(); //TypeSDKLogger.e( "token:" + mAccessToken); // 登录结果直接返回的userinfo中没有qid,需要去应用的服务器获取用access_token获取一下带qid的用户信息 //getUserInfo(mQihooUserInfo); } else { mLoginCallback.onFinished(data); } } catch (Exception e) { Log.e(TAG, "mLoginCallbackSupportOffline exception", e); } } }; private void pay() { String price = "100"; // 支付基础参数 QihooPayInfo payInfo = getQihooPay( price,//_in_pay.GetData(AttName.REAL_PRICE) "商品名", "玩家名", "玩家ID", "服务器ID", "订单号", "回调地址", "360用户ID"); Intent intent = getPayIntent(isLandScape, payInfo); // 必需参数,使用360SDK的支付模块。 intent.putExtra(ProtocolKeys.FUNCTION_CODE, ProtocolConfigs.FUNC_CODE_PAY); // 启动接口 Matrix.invokeActivity(appActivity, intent, mPayCallback); } /*** * 生成调用360SDK支付接口的Intent * * @param isLandScape * @param pay * @return Intent */ protected Intent getPayIntent(boolean isLandScape, QihooPayInfo pay) { Bundle bundle = new Bundle(); // 界面相关参数,360SDK界面是否以横屏显示。 bundle.putBoolean(ProtocolKeys.IS_SCREEN_ORIENTATION_LANDSCAPE, isLandScape); // *** 以下非界面相关参数 *** // 设置QihooPay中的参数。 // 必需参数,用户access token,要使用注意过期和刷新问题,最大64字符。 bundle.putString(ProtocolKeys.ACCESS_TOKEN, pay.getAccessToken()); // 必需参数,360账号id,整数。 bundle.putString(ProtocolKeys.QIHOO_USER_ID, pay.getQihooUserId()); // 必需参数,所购买商品金额, 以分为单位。金额大于等于100分,360SDK运行定额支付流程; 金额数为0,360SDK运行不定额支付流程。 bundle.putString(ProtocolKeys.AMOUNT, pay.getMoneyAmount()); // 必需参数,人民币与游戏充值币的默认比例,例如2,代表1元人民币可以兑换2个游戏币,整数。 bundle.putString(ProtocolKeys.RATE, pay.getExchangeRate()); // 必需参数,所购买商品名称,应用指定,建议中文,最大10个中文字。 bundle.putString(ProtocolKeys.PRODUCT_NAME, pay.getProductName()); // 必需参数,购买商品的商品id,应用指定,最大16字符。 bundle.putString(ProtocolKeys.PRODUCT_ID, pay.getProductId()); // 必需参数,应用方提供的支付结果通知uri,最大255字符。360服务器将把支付接口回调给该uri,具体协议请查看文档中,支付结果通知接口–应用服务器提供接口。 bundle.putString(ProtocolKeys.NOTIFY_URI, pay.getNotifyUri()); // 必需参数,游戏或应用名称,最大16中文字。 bundle.putString(ProtocolKeys.APP_NAME, pay.getAppName()); // 必需参数,应用内的用户名,如游戏角色名。 若应用内绑定360账号和应用账号,则可用360用户名,最大16中文字。(充值不分区服, // 充到统一的用户账户,各区服角色均可使用)。 bundle.putString(ProtocolKeys.APP_USER_NAME, pay.getAppUserName()); // 必需参数,应用内的用户id。 // 若应用内绑定360账号和应用账号,充值不分区服,充到统一的用户账户,各区服角色均可使用,则可用360用户ID最大32字符。 bundle.putString(ProtocolKeys.APP_USER_ID, pay.getAppUserId()); // 可选参数,应用扩展信息1,原样返回,最大255字符。 bundle.putString(ProtocolKeys.APP_EXT_1, pay.getAppExt1()); // 可选参数,应用扩展信息2,原样返回,最大255字符。 bundle.putString(ProtocolKeys.APP_EXT_2, pay.getAppExt2()); // 可选参数,应用订单号,应用内必须唯一,最大32字符。 bundle.putString(ProtocolKeys.APP_ORDER_ID, pay.getAppOrderId()); // 必需参数,使用360SDK的支付模块。 bundle.putInt(ProtocolKeys.FUNCTION_CODE, ProtocolConfigs.FUNC_CODE_PAY); Intent intent = new Intent(appActivity, ContainerActivity.class); intent.putExtras(bundle); return intent; } /*** * @param moneyAmount * 金额数,使用者可以自由设定数额。金额数为100的整数倍,360SDK运行定额支付流程; * 金额数为0,360SDK运行不定额支付流程。 * @return QihooPay */ private QihooPayInfo getQihooPay(String moneyAmount, String itemName, String userName, String roleId, String productId, String billNumber, String pauBackUrl, String userId) { // String qihooUserId = (mQihooUserInfo != null) ? // mQihooUserInfo.getId() : null; // 创建QihooPay QihooPayInfo qihooPay = new QihooPayInfo(); qihooPay.setQihooUserId(userId); qihooPay.setMoneyAmount(moneyAmount); qihooPay.setAccessToken(mAccessToken); qihooPay.setExchangeRate("1"); qihooPay.setProductName(itemName); qihooPay.setProductId(productId); qihooPay.setNotifyUri(pauBackUrl); qihooPay.setAppName("123"); qihooPay.setAppUserName(userName); qihooPay.setAppUserId(roleId); // 可选参数 qihooPay.setAppExt1("ext1"); qihooPay.setAppExt2("ext2"); qihooPay.setAppOrderId(billNumber); return qihooPay; } // 支付的回调 protected IDispatcherCallback mPayCallback = new IDispatcherCallback() { @Override public void onFinished(String data) { Log.d(TAG, "mPayCallback, data is " + data); if (TextUtils.isEmpty(data)) { return; } boolean isCallbackParseOk = false; JSONObject jsonRes; try { jsonRes = new JSONObject(data); // error_code 状态码: 0 支付成功, -1 支付取消, 1 支付失败, -2 支付进行中, // 4010201和4009911 登录状态已失效,引导用户重新登录 // error_msg 状态描述 int errorCode = jsonRes.optInt("error_code"); isCallbackParseOk = true; switch (errorCode) { case 0: Log.d(TAG, "支付结果回调成功"); break; case 1: Log.d(TAG, "支付失败"); break; case -1: Log.d(TAG, "支付取消"); break; case -2: isAccessTokenValid = true; isQTValid = true; // String errorMsg = jsonRes.optString("error_msg"); // String text = // appActivity.getString(R.string.pay_callback_toast, // errorCode, errorMsg); // Toast.makeText(appActivity, text, // Toast.LENGTH_SHORT).show(); break; case 4010201: // acess_token失效 isAccessTokenValid = false; // Toast.makeText(appActivity, // R.string.access_token_invalid, // Toast.LENGTH_SHORT).show(); break; case 4009911: // QT失效 isQTValid = false; // Toast.makeText(appActivity, R.string.qt_invalid, // Toast.LENGTH_SHORT).show(); break; default: break; } } catch (JSONException e) { e.printStackTrace(); } // 用于测试数据格式是否异常。 if (!isCallbackParseOk) { // Toast.makeText(appActivity, // appActivity.getResources().getString(R.string.data_format_error), // Toast.LENGTH_LONG).show(); } } }; private void sendUserInfo(String type) { HashMap eventParams=new HashMap(); //----------------------------参数设置说明-------------------- //以下列出的五项只是作为参考,请按照上述表格中的参数说明进行补充添加 //仅按 demo 样例上传无法通过审核!请务必仔细阅读上述表格! eventParams.put("zoneid",1);//当前角色所在游戏区服 id eventParams.put("zonename","123");//当前角色所在游戏区服名称 eventParams.put("roleid","321");//当前角色 id eventParams.put("rolename","111");//当前角色名称 eventParams.put("professionid",0); eventParams.put("profession","无"); eventParams.put("gender","无"); eventParams.put("professionroleid",0); eventParams.put("professionrolena me","无"); eventParams.put("rolelevel","1"); eventParams.put("power",0); eventParams.put("vip",0); eventParams.put("balance",0); eventParams.put("partyid",0); eventParams.put("partyname","无"); eventParams.put("partyroleid",0); eventParams.put("partyrolename","无"); eventParams.put("friendlist","无"); eventParams.put("ranking","无"); eventParams.put("type",type);//角色信息接口触发的场景 //---------------------------------------------------------- Matrix.statEventInfo(appContext, eventParams); } private void logout() { Intent intent = getLogoutIntent(); Matrix.execute(appActivity, intent, new IDispatcherCallback() { @Override public void onFinished(String data) { Log.d(TAG, "logout_success"); // Toast.makeText(appActivity, data, Toast.LENGTH_SHORT).show(); // System.out.println(data); } }); } private Intent getLogoutIntent() { /* * 必须参数: function_code : 必须参数,表示调用SDK接口执行的功能 */ Intent intent = new Intent(); intent.putExtra(ProtocolKeys.FUNCTION_CODE, ProtocolConfigs.FUNC_CODE_LOGOUT); return intent; } private void exit() { Bundle bundle = new Bundle(); // 界面相关参数,360SDK界面是否以横屏显示。 bundle.putBoolean(ProtocolKeys.IS_SCREEN_ORIENTATION_LANDSCAPE, isLandScape); // 必需参数,使用360SDK的退出模块。 bundle.putInt(ProtocolKeys.FUNCTION_CODE, ProtocolConfigs.FUNC_CODE_QUIT); // 可选参数,登录界面的背景图片路径,必须是本地图片路径 bundle.putString(ProtocolKeys.UI_BACKGROUND_PICTRUE, ""); Intent intent = new Intent(appActivity, ContainerActivity.class); intent.putExtras(bundle); Matrix.invokeActivity(appActivity, intent, mQuitCallback); } // 退出的回调 private IDispatcherCallback mQuitCallback = new IDispatcherCallback() { @Override public void onFinished(String data) { // TypeSDKLogger.d( "mQuitCallback, data is " + data); JSONObject json; try { json = new JSONObject(data); int which = json.optInt("which", -1); // String label = json.optString("label"); // Toast.makeText(appActivity, // "按钮标识:" + which + ",按钮描述:" + label, Toast.LENGTH_LONG) // .show(); switch (which) { case 0: // 用户关闭退出界面 Log.d(TAG, "用户关闭退出界面"); return; case 1: //进入论坛 Log.d(TAG, "exit_success"); System.exit(0); break; case 2://退出游戏 Log.d(TAG, "exit_success"); System.exit(0); break; default: Log.d(TAG, "exit which:" + which); return; } } catch (Exception e) { e.printStackTrace(); } } }; private boolean isCancelLogin(String data) { try { JSONObject joData = new JSONObject(data); int errno = joData.optInt("errno", -1); if (-1 == errno) { // Toast.makeText(appActivity, data, Toast.LENGTH_LONG).show(); return true; } } catch (Exception e) { } return false; } private String parseAccessTokenFromLoginResult(String loginRes) { try { JSONObject joRes = new JSONObject(loginRes); JSONObject joData = joRes.getJSONObject("data"); return joData.getString("access_token"); } catch (Exception e) { e.printStackTrace(); } return null; } }
再然后,我们需要新创建一个类:
如下图,我们在com.xxx这里右键
名字输入:QihooPayInfo
、
这样就会在这边多出一个类文件,我们打开他
把下面的代码复制到下图标记处
代码:
// 必需参数,用户access token,要使用注意过期和刷新问题,最大64字符。 private String accessToken; // 必需参数,360账号id,整数。 private String qihooUserId; // 必需参数,应用app key。 private String appKey; // 必需参数,值为md5(app_secret +“#”+ // app_key)全小写,用于签名的密钥不能把app_secret写到应用客户端程序里因此使用这样一个特殊的KEY,应算出值直接写在app中,而不是写md5的计算过程。 private String privateKey; // 必需参数,所购买商品金额,以分为单位。金额大于等于100分,360SDK运行定额支付流程; 金额数为0,360SDK运行不定额支付流程。 private String moneyAmount; // 必需参数,人民币与游戏充值币的默认比例,例如2,代表1元人民币可以兑换2个游戏币,整数。 private String exchangeRate; // 必需参数,所购买商品名称,应用指定,建议中文,最大10个中文字。 private String productName; // 必需参数,购买商品的商品id,应用指定,最大16字符。 private String productId; // 必需参数,应用方提供的支付结果通知uri,最大255字符。360服务器将把支付接口回调给该uri,具体协议请查看文档中,支付结果通知接口–应用服务器提供接口。 private String notifyUri; // 必需参数,游戏或应用名称,最大16中文字。 private String appName; // 必需参数,应用内的用户名,如游戏角色名。 若应用内绑定360账号和应用账号,则可用360用户名,最大16中文字。(充值不分区服, // 充到统一的用户账户,各区服角色均可使用)。 private String appUserName; // 必需参数,应用内的用户id。 若应用内绑定360账号和应用账号, 充值不分区服, 充到统一的用户账户, 各区服角色均可使用, // 则可用360用户ID。最大32字符。 private String appUserId; // 可选参数,应用扩展信息1,原样返回,最大255字符。 private String appExt1; // 可选参数,应用扩展信息2,原样返回,最大255字符。 private String appExt2; // 可选参数,应用订单号,应用内必须唯一,最大32字符。 private String appOrderId; // 可选参数,支付类型定制 private String[] payTypes; public String[] getPayTypes() { return payTypes; } public void setPayTypes(String[] payTypes) { this.payTypes = payTypes; } public String getAccessToken() { return accessToken; } public void setAccessToken(String accessToken) { this.accessToken = accessToken; } public String getQihooUserId() { return qihooUserId; } public void setQihooUserId(String qihooUserId) { this.qihooUserId = qihooUserId; } public String getAppKey() { return appKey; } public void setAppKey(String appKey) { this.appKey = appKey; } public String getPrivateKey() { return privateKey; } public void setPrivateKey(String privateKey) { this.privateKey = privateKey; } public String getMoneyAmount() { return moneyAmount; } public void setMoneyAmount(String moneyAmount) { this.moneyAmount = moneyAmount; } public String getAppName() { return appName; } public void setAppName(String appName) { this.appName = appName; } public String getAppUserName() { return appUserName; } public void setAppUserName(String appUserName) { this.appUserName = appUserName; } public String getAppUserId() { return appUserId; } public void setAppUserId(String appUserId) { this.appUserId = appUserId; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getProductId() { return productId; } public void setProductId(String productId) { this.productId = productId; } public String getNotifyUri() { return notifyUri; } public void setNotifyUri(String notifyUri) { this.notifyUri = notifyUri; } public String getExchangeRate() { return exchangeRate; } public void setExchangeRate(String exchangeRate) { this.exchangeRate = exchangeRate; } public String getAppExt1() { return appExt1; } public void setAppExt1(String appExt1) { this.appExt1 = appExt1; } public String getAppExt2() { return appExt2; } public void setAppExt2(String appExt2) { this.appExt2 = appExt2; } public String getAppOrderId() { return appOrderId; } public void setAppOrderId(String appOrderId) { this.appOrderId = appOrderId; }
至此我们就把所有360上线所需的接口完成了,添加UI并添加相应事件调用相应接口后,就是一个最简单的demo了
如果想要了解具体的接口作用,和相应参数的说明,请继续阅读以下内容,或查看官方文档
第一步初始化:
在Activity onCreate中调用360的初始化接口:(必须在UI线程调用)
private void init() {
// TODO Auto-generated method stub
MatrixCallBack mSDKCallback = new MatrixCallBack() {
@Override
public void execute(Context context, int functionCode, String
functionParams) {
// TODO Auto-generated method stub
if (functionCode == ProtocolConfigs.FUNC_CODE_SWITCH_ACCOUNT) {
// 调用 sdk 的切换帐号接口
doSdkSwitchAccount(getLandscape(context));
}else if (functionCode == ProtocolConfigs.FUNC_CODE_INITSUCCESS) {
//这里返回成功之后才能调用 SDK 其它接口 TypeSDKLogger.d( "initSDK success");
isInit = true;
}
}
};
// 调用其他SDK接口之前必须先调用init
Matrix.init(appActivity,mSDKCallback);
}
调用登录接口:
/**
* 使用 360SDK 的登录接口, 生成 intent 参数
*
* @param isLandScape 是否横屏显示登录界面
*/
private Intent getLoginIntent(boolean isLandScape) {
Intent intent = new Intent(this, ContainerActivity.class);
// 必需参数,使用 360SDK 的登录模块
intent.putExtra(ProtocolKeys.FUNCTION_CODE,
ProtocolConfigs.FUNC_CODE_LOGIN);
// 可选参数,360SDK 界面是否以横屏显示,默认为 true,横屏
intent.putExtra(ProtocolKeys.IS_SCREEN_ORIENTATION_LANDSCAPE,
isLandScape);
//可选参数,是否显示关闭按钮,默认不显示
intent.putExtra(ProtocolKeys.IS_LOGIN_SHOW_CLOSE_ICON,
getCheckBoxBoolean(R.id.isShowClose));
// 可选参数,是否支持离线模式,默认值为 false
intent.putExtra(ProtocolKeys.IS_SUPPORT_OFFLINE,
getCheckBoxBoolean(R.id.isSupportOffline));
// 可选参数,是否在自动登录的过程中显示切换账号按钮,默认为 false
intent.putExtra(ProtocolKeys.IS_SHOW_AUTOLOGIN_SWITCH,
getCheckBoxBoolean(R.id.isShowSwitchButton));
// 可选参数,是否隐藏欢迎界面
intent.putExtra(ProtocolKeys.IS_HIDE_WELLCOME,
getCheckBoxBoolean(R.id.isHideWellcome));
/*
* 指定界面背景(可选参数):
* 1.ProtocolKeys.UI_BACKGROUND_PICTRUE 使用的系统路径,如/sdcard/1.png
* 2.ProtocolKeys.UI_BACKGROUND_PICTURE_IN_ASSERTS 使用的 assest 中的图片
* 资源,
* 如传入 bg.png 字符串,就会在 assets 目录下加载这个指定的文件
* 3.图片大小不要超过 5M,尺寸不要超过 1280x720,后缀只能是 jpg、jpeg 或 png
*/
// 可选参数,登录界面的背景图片路径,必须是本地图片路径
intent.putExtra(ProtocolKeys.UI_BACKGROUND_PICTRUE,
getUiBackgroundPicPath());
// 可选参数,指定 assets 中的图片路径,作为背景图
intent.putExtra(ProtocolKeys.UI_BACKGROUND_PICTURE_IN_ASSERTS,
getUiBackgroundPathInAssets());
// 可选参数,是否需要用户输入激活码,用于游戏内测阶段。
// 如果不需激活码相关逻辑,客户传 false 或者不传入该参数。
intent.putExtra(ProtocolKeys.NEED_ACTIVATION_CODE,
getCheckBoxBoolean(R.id.isNeedActivationCode));
//-- 以下参数仅仅针对自动登录过程的控制
// 可选参数,自动登录过程中是否不展示任何 UI,默认展示。
intent.putExtra(ProtocolKeys.IS_AUTOLOGIN_NOUI,
getCheckBoxBoolean(R.id.isAutoLoginHideUI));
// 可选参数,静默自动登录失败后是否显示登录窗口,默认不显示
intent.putExtra(ProtocolKeys.IS_SHOW_LOGINDLG_ONFAILED_AUTOLOGIN,
getCheckBoxBoolean(R.id.isShowDlgOnFailedAutoLogin));
// 社交分享测试参数,发布时要去掉,具体说明见分享接口
// intent.putExtra(ProtocolKeys.IS_SOCIAL_SHARE_DEBUG,
// getCheckBoxBoolean(R.id.isDebugSocialShare));
return intent;
}
// 调用接口
protected void doSdkLogin(boolean isLandScape) {
mIsInOffline = false;
Intent intent = getLoginIntent(isLandScape);
IDispatcherCallback callback = mLoginCallback;
if (getCheckBoxBoolean(R.id.isSupportOffline)) {
callback = mLoginCallbackSupportOffline; //离线模式
}
Matrix.execute(this, intent, callback);
}
// 登录接口回调(不支持离线模式)
// 登录、注册的回调
privateIDispatcherCallback mLoginCallback = newIDispatcherCallback() {
@Override
publicvoid onFinished(String data) {
// press back
if (isCancelLogin(data)) {
return;
}
// 显示一下登录结果
Toast.makeText(SdkUserBaseActivity.this, data,
Toast.LENGTH_LONG).show();
mIsInOffline = false;
mQihooUserInfo = null;
// 解析 access_token
mAccessToken = parseAccessTokenFromLoginResult(data);
if (!TextUtils.isEmpty(mAccessToken)) {
// 需要去应用的服务器获取用 access_token 获取一下用户信息
getUserInfo();
} else {
Toast.makeText(SdkUserBaseActivity.this, "get access_token
failed!", Toast.LENGTH_LONG).show();
}
}
};
// 登录结果回调(支持离线模式)
private IDispatcherCallback mLoginCallbackSupportOffline
= new IDispatcherCallback() {
@Override
public void onFinished(String data) {
if (isCancelLogin(data)) {
return;
}
Log.d(TAG, "mLoginCallbackSupportOffline, data is " + data);
try {
JSONObject joRes = new JSONObject(data);
JSONObject joData = joRes.getJSONObject("data");
String mode = joData.optString("mode", "");
if (!TextUtils.isEmpty(mode) && mode.equals("offline")) 、
{
Toast.makeText(SdkUserBaseActivity.this,
"login success in offline mode",
Toast.LENGTH_SHORT).show();
mIsInOffline = true;
// 显示一下登录结果
Toast.makeText(SdkUserBaseActivity.this, data,
Toast.LENGTH_LONG).show();
} else {
mLoginCallback.onFinished(data);
}
} catch (Exception e) {
Log.e(TAG, "mLoginCallbackSupportOffline exception", e);
}
}
};
private boolean isCancelLogin(String data) {
try {
JSONObject joData = new JSONObject(data);
int errno = joData.optInt("errno", -1);
if (-1 == errno) {
// Toast.makeText(appActivity, data, Toast.LENGTH_LONG).show();
return true;
}
} catch (Exception e) {
}
return false;
}
private String parseAccessTokenFromLoginResult(String loginRes) {
try {
JSONObject joRes = new JSONObject(loginRes);
JSONObject joData = joRes.getJSONObject("data");
return joData.getString("access_token");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
调用支付接口:
注意:
1、 必选参数不能为空, 不能为 0,否则支付失败。
2、 参数名,以 ProtocolKeys 中定义的常量为准。
3、 请务必对 case 0、1、-1 加入处理语句,如果为空的会导致游戏崩溃。
/**
* 使用 360SDK 的支付接口
*
* @param isLandScape 是否横屏显示支付界面
* @param isFixed 是否定额支付
* @param functioncode 标示支付模块类型。
*/
protected void doSdkPay(QihooUserInfo usrinfo, boolean isLandScape,int functionCode) {
if(!isAccessTokenValid) {
Toast.makeText(SdkUserBaseActivity.this, R.string.access_token_invalid,
Toast.LENGTH_SHORT).show();
return;
}
if(!isQTValid) {
Toast.makeText(SdkUserBaseActivity.this, R.string.qt_invalid,
Toast.LENGTH_SHORT).show();
return;
}
boolean isFixed = getCheckBoxBoolean(R.id.isPayFixed);
// 支付基础参数
QihooPayInfo payInfo = getQihooPay(
price,//_in_pay.GetData(AttName.REAL_PRICE)
_in_pay.GetData(AttName.ITEM_NAME).isEmpty()?"商品
":_in_pay.GetData(AttName.ITEM_NAME),
userInfo.GetData(AttName.ROLE_NAME).isEmpty() ? "玩家" :
userInfo.GetData(AttName.ROLE_NAME),
userInfo.GetData(AttName.ROLE_ID).isEmpty()?"1":
userInfo.GetData(AttName.ROLE_ID),
_in_pay.GetData(AttName.ITEM_SERVER_ID).isEmpty()?"1":
_in_pay.GetData(AttName.ITEM_SERVER_ID),
_in_pay.GetData(AttName.BILL_NUMBER),
platform.GetData(AttName.PAY_CALL_BACK_URL),
userInfo.GetData(AttName.USER_ID));
Intent intent = getPayIntent(isLandScape, isFixed, functionCode);
// 必需参数,使用 360SDK 的支付模块:CP 可以根据需求选择使用 带有收银台的支付模
// 块 或者 直接 调用微信支付模块或者直接调用支付宝支付模块。
// functionCode 对应三种类型的支付模块:
// ProtocolConfigs.FUNC_CODE_PAY;//支付模块。(有收银台,显示多种支付方式) // ProtocolConfigs.FUNC_CODE_WEIXIN_PAY;//微信支付模块。
//(无收银台,直接用微信进行支付)
//ProtocolConfigs.FUNC_CODE_ALI_PAY;
//支付宝支付模块。(无收银台,直接用支付宝进行支付)
intent.putExtra(ProtocolKeys.FUNCTION_CODE, functionCode);
// 可选参数,登录界面的背景图片路径,必须是本地图片路径
intent.putExtra(ProtocolKeys.UI_BACKGROUND_PICTRUE, "");
Matrix.invokeActivity(this, intent, mPayCallback);
}
/**
* @param moneyAmount
*金额数,使用者可以自由设定数额。金额数为100的整数倍,360SDK运行定额支付流程;
*金额数为0,360SDK运行不定额支付流程。
* @return QihooPay
*/
private QihooPayInfo getQihooPay(String moneyAmount, String itemName,
String userName, String roleId, String productId,
String billNumber, String pauBackUrl, String userId) {
// String qihooUserId = (mQihooUserInfo != null) ?
// mQihooUserInfo.getId() : null;
// 创建QihooPay
QihooPayInfo qihooPay = new QihooPayInfo();
qihooPay.setQihooUserId(userId);
qihooPay.setMoneyAmount(moneyAmount);
qihooPay.setAccessToken(mAccessToken);
qihooPay.setExchangeRate("1");
qihooPay.setProductName(itemName);
qihooPay.setProductId(productId);
qihooPay.setNotifyUri(pauBackUrl);
qihooPay.setAppName(platform.GetData(AttName.CP_ID));
qihooPay.setAppUserName(userName);
qihooPay.setAppUserId(roleId);
// 可选参数
qihooPay.setAppExt1("ext1");
qihooPay.setAppExt2("ext2");
qihooPay.setAppOrderId(billNumber);
return qihooPay;
}
/**
* 生成调用 360SDK 支付接口基础参数的 Intent
*
* @param isLandScape 是否横屏显示登录界面
* @param isFixed 是否定额支付
*
* @return Intent
*/
protected Intent getPayIntent(boolean isLandScape, boolean isFixed) {
Bundle bundle = new Bundle();
QihooPayInfo pay = getQihooPayInfo(isFixed);
// 界面相关参数,360SDK 界面是否以横屏显示。
bundle.putBoolean(ProtocolKeys.IS_SCREEN_ORIENTATION_LANDSCAPE, isLandScape);
// 可选参数,登录界面的背景图片路径,必须是本地图片路径
bundle.putString(ProtocolKeys.UI_BACKGROUND_PICTRUE, "");
// *** 以下非界面相关参数 ***
// 设置 QihooPay 中的参数。
// 必需参数,用户 access token,要使用注意过期和刷新问题,最大 64 字符。 bundle.putString(ProtocolKeys.ACCESS_TOKEN, pay.getAccessToken());
// 必需参数,360 账号 id。
bundle.putString(ProtocolKeys.QIHOO_USER_ID, pay.getQihooUserId());
//必需参数,所购买商品金额, 以分为单位。金额大于等于 100 分,360SDK 运行定额支
//付流程; 金 额数为 0,360SDK 运行不定额支付流程。
bundle.putString(ProtocolKeys.AMOUNT, pay.getMoneyAmount());
// 必需参数,所购买商品名称,应用指定,建议中文,最大 10 个中文字。
bundle.putString(ProtocolKeys.PRODUCT_NAME, pay.getProductName());
// 必需参数,购买商品的商品 id,应用指定,最大 16 字符。
bundle.putString(ProtocolKeys.PRODUCT_ID, pay.getProductId());
// 必需参数,应用方提供的支付结果通知 uri,最大 255 字符。360 服务器将把支付接口
//回调给该 uri, 具体协议请查看文档中,支付结果通知接口–应用服务器提供接口。
bundle.putString(ProtocolKeys.NOTIFY_URI, pay.getNotifyUri());
// 必需参数,游戏或应用名称,最大 16 中文字。
bundle.putString(ProtocolKeys.APP_NAME, pay.getAppName());
// 必需参数,应用内的用户名,如游戏角色名。 若应用内绑定 360 账号和应用账号,则
//可用 360 用户 名,最大 16 中文字。(充值不分区服,充到统一的用户账户,各区服角
//色均可使用)。
bundle.putString(ProtocolKeys.APP_USER_NAME, pay.getAppUserName());
// 必需参数,应用内的用户 id。 // 若应用内绑定 360 账号和应用账号,充值
//不分区服,充到统一的用户账户,各区服角色均可使用, 则可用 360 用户 ID 最大 32 //字符。
bundle.putString(ProtocolKeys.APP_USER_ID, pay.getAppUserId());
// 必需参数,应用订单号,应用内必须唯一,最大 32 字符。
bundle.putString(ProtocolKeys.APP_ORDER_ID, pay.getAppOrderId());
// 可选参数,应用扩展信息 1,原样返回,最大 255 字符。
bundle.putString(ProtocolKeys.APP_EXT_1, pay.getAppExt1());
// 可选参数,应用扩展信息 2,原样返回,最大 255 字符。
bundle.putString(ProtocolKeys.APP_EXT_2, pay.getAppExt2());
Intent intent = new Intent(this, ContainerActivity.class);
intent.putExtras(bundle);
return intent;
}
/**
* 支付的回调
*/
protected IDispatcherCallback mPayCallback = new IDispatcherCallback() {
@Override
public void onFinished(String data) {
Log.d(TAG, "mPayCallback, data is " + data);
if(TextUtils.isEmpty(data)) {
return;
}
boolean isCallbackParseOk = false;
JSONObject jsonRes;
try {
jsonRes = new JSONObject(data);
// error_code 状态码:0 支付成功,-1 支付取消,1 支付失败,-2 支付进行中。
// 请务必对 case 0、1、-1 加入处理语句,如果为空会导致游戏崩溃 // error_msg 状态描述
int errorCode = jsonRes.optInt("error_code");
isCallbackParseOk = true;
switch (errorCode) {
case 0:
case 1:
case -1:
case -2: {
isAccessTokenValid = true;
String errorMsg = jsonRes.optString("error_msg");
String text = getString(R.string.pay_callback_toast, errorCode, errorMsg);
Toast.makeText(SdkUserBaseActivity.this, text, Toast.LENGTH_SHORT).show();
}
break;
case 4010201:
isAccessTokenValid = false;
Toast.makeText(SdkUserBaseActivity.this, R.string.access_token_invalid,
Toast.LENGTH_SHORT).show();
break;
case 4009911:
//QT 失效
isQTValid = false;
Toast.makeText(SdkUserBaseActivity.this, R.string.qt_invalid,
Toast.LENGTH_SHORT).show();
break;
default:
break;
}
} catch (JSONException e) {
e.printStackTrace();
}
// 用于测试数据格式是否异常。
if (!isCallbackParseOk) {
Toast.makeText(SdkUserBaseActivity.this, getString(R.string.data_format_error),
Toast.LENGTH_LONG).show();
}
}
};
接入提交游戏角色数据信息:(可选客户端接入还是服务端接入,以下只展示客户端接入示例)
数据提交时机:
1、玩家进入游戏区服时调用该接口。
2、角色创建时调用该接口。
3、角色升级时调用该接口。
4、角色退出游戏时调用该接口。
/**
角色信息采集接口
*/
protected void doSdkGetUserInfoByCP() {
HashMap eventParams=new HashMap();
//----------------------------参数设置说明--------------------
//以下列出的五项只是作为参考,请按照上述表格中的参数说明进行补充添加
eventParams.put("zoneid",1);//当前角色所在游戏区服 id
eventParams.put("zonename","刀塔传奇 1 区");//当前角色所在游戏区服名称 eventParams.put("roleid","12345678");//当前角色 id
eventParams.put("rolename","三国风吹来的鱼");//当前角色名称 eventParams.put("type","levelUp");//角色信息接口触发的场景
//----------------------------------------------------------
Matrix.statEventInfo(getApplicationContext(), eventParams);
}
参数说明:
接入切换账号接口:
/**
* 使用 360SDK 的切换账号接口
*
* @param isLandScape 是否横屏显示登录界面
*/
protected void doSdkSwitchAccount(boolean isLandScape) {
Intent intent = getSwitchAccountIntent(isLandScape);
if (isSupportOffline) {
callback = mAccountSwitchSupportOfflineCB;//离线模式
}
Matrix.invokeActivity(this, intent, mAccountSwitchCallback);
}
/***
* 生成调用360SDK切换账号接口的Intent
*
* @param isLandScape
* 是否横屏
* @param isBgTransparent
* 是否背景透明
* @param clientId
* 即AppKey
* @return Intent
*/
private Intent getSwitchAccountIntent(boolean isLandScape) {
Intent intent = new Intent(appActivity, ContainerActivity.class);
// 界面相关参数,360SDK界面是否以横屏显示。
intent.putExtra(ProtocolKeys.IS_SCREEN_ORIENTATION_LANDSCAPE,
isLandScape);
// 必需参数,使用360SDK的切换账号模块。
intent.putExtra(ProtocolKeys.FUNCTION_CODE,
ProtocolConfigs.FUNC_CODE_SWITCH_ACCOUNT);
// 是否显示关闭按钮
intent.putExtra(ProtocolKeys.IS_LOGIN_SHOW_CLOSE_ICON, isShowClose);
// 可选参数,是否支持离线模式,默认值为false
intent.putExtra(ProtocolKeys.IS_SUPPORT_OFFLINE, isSupportOffline);
// 可选参数,是否在自动登录的过程中显示切换账号按钮
intent.putExtra(ProtocolKeys.IS_SHOW_AUTOLOGIN_SWITCH,
isShowSwitchButton);
// 可选参数,是否隐藏欢迎界面
intent.putExtra(ProtocolKeys.IS_HIDE_WELLCOME, isHideWellcome);
// 可选参数,登录界面的背景图片路径,必须是本地图片路径
// intent.putExtra(ProtocolKeys.UI_BACKGROUND_PICTRUE,
// getUiBackgroundPicPath());
// 可选参数,指定assets中的图片路径,作为背景图
// intent.putExtra(ProtocolKeys.UI_BACKGROUND_PICTURE_IN_ASSERTS,
// getUiBackgroundPathInAssets());
// -- 以下参数仅仅针对自动登录过程的控制
// 可选参数,自动登录过程中是否不展示任何UI,默认展示。
intent.putExtra(ProtocolKeys.IS_AUTOLOGIN_NOUI, isAutoLoginHideUI);
// 可选参数,静默自动登录失败后是否显示登录窗口,默认不显示
intent.putExtra(ProtocolKeys.IS_SHOW_LOGINDLG_ONFAILED_AUTOLOGIN,
isShowDlgOnFailedAutoLogin);
// 测试参数,发布时要去掉
intent.putExtra(ProtocolKeys.IS_SOCIAL_SHARE_DEBUG, isDebugSocialShare);
return intent;
}
// 切换账号的回调
private IDispatcherCallback mAccountSwitchCallback = new IDispatcherCallback() {
@Override
public void onFinished(String data) {
// press back
if (isCancelLogin(data)) {
return;
}
// 显示一下登录结果
// Toast.makeText(appActivity, data, Toast.LENGTH_LONG).show();
// TypeSDKLogger.d( "mAccountSwitchCallback, data is " + data);
// 解析access_token
mAccessToken = parseAccessTokenFromLoginResult(data);
}
};
// 支持离线模式的切换账号的回调
private IDispatcherCallback mAccountSwitchSupportOfflineCB = new IDispatcherCallback() {
@Override
public void onFinished(String data) {
// press back
if (isCancelLogin(data)) {
return;
}
// 显示一下登录结果
// Toast.makeText(appActivity, data, Toast.LENGTH_LONG).show();
// TypeSDKLogger.d( "mAccountSwitchSupportOfflineCB, data is " + data);
// 解析access_token
mAccessToken = parseAccessTokenFromLoginResult(data);
}
};
parseAccessTokenFromLoginResult (String data) 此函数登录时就有用到,解析TOKEN
接入退出接口:
/**
* 使用 360SDK 的退出接口
*
* @param isLandScape 是否横屏显示支付界面
*/
protected void doSdkQuit(boolean isLandScape) {
Bundle bundle = new Bundle();
// 界面相关参数,360SDK 界面是否以横屏显示。
bundle.putBoolean(ProtocolKeys.IS_SCREEN_ORIENTATION_LANDSCAPE, isLandScape);
// 可选参数,登录界面的背景图片路径,必须是本地图片路径
bundle.putString(ProtocolKeys.UI_BACKGROUND_PICTRUE, "");
// 必需参数,使用 360SDK 的退出模块。
bundle.putInt(ProtocolKeys.FUNCTION_CODE, ProtocolConfigs.FUNC_CODE_QUIT);
Intent intent = new Intent(this, ContainerActivity.class);
intent.putExtras(bundle);
Matrix.invokeActivity(this, intent, mQuitCallback);
}
// 退出的回调
private IDispatcherCallback mQuitCallback = new IDispatcherCallback() {
@Override
public void onFinished(String data) {
// TODO your job
}
};
接入销毁接口:
@Override
protected void onDestroy() {
super.onDestroy();
Matrix.destroy(this);
}
游戏 activity 生命周期接口:
//游戏 Activity 必接 生命周期接口
public static void onStart(Activity activity)
//游戏 Activity 必接生命周期接口
public static void onResume(Activity activity)
//游戏 Activity 必接生命周期接口
public static void onPause(Activity activity)
//游戏 Activity 必接生命周期接口
public static void onStop(Activity activity)
//游戏 Activity 必接生命周期接口
public static void onReStart(Activity activity)
//游戏 Activity 必接生命周期接口
public static void onActivityResult (Activity activity,int requestCode, int resultCode, Intent data)
//游戏 Activity 必接生命周期接口
public static void onNewIntent (Activity activity,Intent intent)
代码混淆要求
如果游戏发布时采用proguard进行代码混淆,请在proguard配置文件加入以下代码,以避免对SDK进行混淆,否则会造成SDK部分功能不正常。
-keep class a.a.a.** { *; }
-keep class cn.pp.** { *; }
-keep class com.alipay.** {*;}
-keep class com.qihoo.** {*;}
-keep class com.qihoo360.** { *; }
-keep class com.qihoopp.** { *; }
-keep class com.yeepay.safekeyboard.** { *; }
-keep class com.amap.** {*;}
-keep class com.aps.** {*;}
-keep class com.iapppay.** {*;}
-keep class com.ipaynow.** {*;}
-keep class com.junnet.heepay.** {*;}
-keep class com.tencent.mm.** {*;}
-keep class com.ta.utdid2.** {*;}
-keep class com.ut.device.** {*;}
-keep class com.qihoo.sdkplugging.host.** {*;}
-keep public class com.qihoo.gamecenter.sdk.matrix.PluggingHostProxy {*;}
-dontwarn cn.pp.**
-dontwarn com.alipay.android.app.**
-dontwarn com.qihoo.**
-dontwarn com.qihoo360.**
-dontwarn com.qihoopp.**
-dontwarn com.yeepay.safekeyboard.**
-dontwarn com.amap.**
-dontwarn org.apache.http.conn.ssl.SSLSocketFactory
如果想了解更多,请联系我们或关注官网
了解更多:www.typesdk.com
问题解答:1771930259
联系邮箱:qianyuzhou@typesdk.com
项目地址:https://github.com/typesdk