快速集成指南

来自AnySDK 文档
跳转至: 导航搜索
本文介绍的是AnySDK Framework 集成流程和注意事项。

Android接入

获取AnySDK Framework

为了集成AnySDK Framework,请在AnySDK客户端的“安妮市场”里,选择C++(Android)框架进行下载,打开以后可以看到如下图的目录结构:

AnySDK Framework目录结构2.png

下载得到的AnySDK Framework框架资源目录内各部分介绍如下图所示:

AnySDK Framework目录结构.png

导入AnySDK Framework

关于cocos2d-x引擎接入AnySDK框架的示例代码,可以参考 https://github.com/AnySDK/Sample_CPP_Cocos2dx 项目(Sample版本为cocos2d-x 3.3rc0)

选择AnySDK Framework版本并导入到工程目录

1.查看游戏项目使用stl库的版本
以cocos2d-x框架为例,开发者可以在工程目录下jni/application.mk文件第一行找到stl库类型设置
如果此处设置的是 APP_STL := gnustl_static,则表示当前工程以gnu静态库的方式引入使用stl标准库,此时应选择集成protocols_gnustl_static这个文件夹中的框架资源。反之,则选择相应的集成protocols_stlport_static、protocols_c++_static文件夹中的框架资源。
2.在android工程目录下面新建protocols目录,然后将上一步选择的对应版本框架目录下的include文件夹和android文件夹拷贝到protocols下面。如下图:
静态库引用图.jpg
3.将框架目录下的res文件夹中的所有资源文件拷贝到android项目对应的文件中。

修改Android.mk文件配置framework编译选项

这一步是修改游戏工程中C++代码的ndk编译配置文件Android.mk,将AnySDK提供的framework库链接到游戏工程的库中。
1.将protocols目录添加到NDK_MODULE_PATH环境变量中:在android.mk第一行 LOCAL_PATH := $(call my-dir) 下面新加一行代码
LOCAL_PATH := $(call my-dir)
$(call import-add-path,$(LOCAL_PATH)/../)
2. 添加AnySDK framework静态库声明:在android.mk文件的LOCAL_C_INCLUDES声明下面添加一行代码
LOCAL_WHOLE_STATIC_LIBRARIES := PluginProtocolStatic
注:1.此处注意语法规则,如果工程原有mk文件中没有其他LOCAL_WHOLE_STATIC_LIBRARIES声明,则添加上面的代码即可,如果mk文件中原来就有其他的LOCAL_WHOLE_STATIC_LIBRARIES声明,那么就需要加在原有声明之后,并且将 :=修改为+=
  2.PluginProtocolStatic请勿使用LOCAL_STATIC_LIBRARIES,否则会导致AnySDK部分函数找不到。
3. 添加库路径声明代码:在android.mk文件的最后一行添加以下代码
$(call import-module,protocols/android)

导入框架自带的jar包并勾选export选项

步骤如下: 右键点击您的工程,选择 Properties 后选择Java Build Path,在面板上点击 Libraries,通过Add JARs... 将libPluginProtocol.jar引进游戏工程,如图
Jar引用图.jpg         Jar输出.jpg

注:游戏工程API最小支持10

cocos2d-x命令编译的话,需要将jar包放在libs里(部分版本是放在jars里)。

配置AndroidManifest.xml添加框架需要的权限

<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.RESTART_PACKAGES" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />

一般来说,即便不集成AnySDK Framework,大部分的项目也都会注册申请这些权限。

初始化AnySDK Framework

初始化JavaVM

首先,要在游戏工程加载jni的时候为AnySDK framework设置JavaVM引用。先找到JNI_OnLoad函数,此函数是jni被加载时会首先被调用的函数。
以cocos2d-x 2.x版本引擎为例,JNI_OnLoad函数定义在jni目录下的hellocpp/main.cpp中,如下图所示:

Javaactivity.jpg Jni onload.jpg

1.导入头文件并声明命名空间
#include "PluginJniHelper.h"
using namespace anysdk::framework ;

注:此处导入头文件时要根据项目设定的头文件定义路径来写,以保证编译时能成功找到相应头文件

2.添加设置javaVM代码
PluginJniHelper::setJavaVM(vm); // add for plugin
  • 若此处已有其他引擎初始化JavaVM的代码,保留其代码并在后面添加PluginJniHelper::setJavaVM(vm);即可

以cocos2d-x为例,设置如下
3.3rc0及以上版本:

#include "PluginJniHelper.h"
    
#define  LOG_TAG    "main"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
    
using namespace cocos2d;
using namespace anysdk::framework;
    
void cocos_android_app_init (JNIEnv* env, jobject thiz) {
    LOGD("cocos_android_app_init");
    AppDelegate *pAppDelegate = new AppDelegate();
    JavaVM* vm;
    env->GetJavaVM(&vm);
    PluginJniHelper::setJavaVM(vm);
}

2.x版本(proj.android/jni/hellocpp/main.cpp)、3.3r0之前版本(例如3.2在cocos2d/cocos/platform/android/javaactivity.cpp):

#include "PluginJniHelper.h"

#define  LOG_TAG    "main"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)

using namespace cocos2d;
using namespace anysdk::framework;

jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
  JniHelper::setJavaVM(vm);
  PluginJniHelper::setJavaVM(vm);
  return JNI_VERSION_1_4;
}

注:因为setJavaVM需要在onCreate之前,所以写在JNI_OnLoad里肯定没错。3.3rc0及其以上版本的cocos_android_app_init是在onCreate之前的,所以也可以写在这里。3.x版本头文件需要写全路径,例如3.2版本#include "../../../../proj.android/protocols/android/PluginJniHelper.h"

在JAVA层初始化AnySDK Framework框架

1.首先找到游戏工程的主Activity,以cocos2d-x引擎游戏为例,主Activity即是继承了cocos2dxActivity的Activity。
2.然后在主Activity的onCreate()方法中新增如下代码来初始化AnySDK Framework:
import com.anysdk.framework.PluginWrapper;

public class MainActivity extends Activity{
    protected void onCreate(Bundle savedState)
    {
        super.onCreate(savedState);
        PluginWrapper.init(this); // for plugins
    }

注:AnySDK的回调函数默认是在主线程,使用cocos2d-x的话,可以在onCreate加上PluginWrapper.setGLSurfaceView(Cocos2dxGLSurfaceView.getInstance());将回调改成在GL线程,不在GL线程里操作界面会有问题。

3.重写Activity生命周期相关方法,代码如下:
import android.content.Intent;
import android.os.Bundle;
import android.content.res.Configuration;

import com.anysdk.framework.PluginWrapper;
@Override
protected void onDestroy() {
    PluginWrapper.onDestroy();
    super.onDestroy();
}

@Override
protected void onPause() {
    PluginWrapper.onPause();
    super.onPause();
}

@Override
protected void onResume() {
    PluginWrapper.onResume();
    super.onResume();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    PluginWrapper.onActivityResult(requestCode, resultCode, data);
    super.onActivityResult(requestCode, resultCode, data);
}

@Override
protected void onNewIntent(Intent intent) {
    PluginWrapper.onNewIntent(intent);
    super.onNewIntent(intent);
}

@Override
protected void onStop() {
    PluginWrapper.onStop();
    super.onStop();
}

@Override
protected void onRestart() {
    PluginWrapper.onRestart();
    super.onRestart();
 }

@Override
public void onBackPressed() {
	PluginWrapper.onBackPressed();
	super.onBackPressed();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
	PluginWrapper.onConfigurationChanged(newConfig);
	super.onConfigurationChanged(newConfig);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
	PluginWrapper.onRestoreInstanceState(savedInstanceState);
	super.onRestoreInstanceState(savedInstanceState);
}

@Override
protected void onSaveInstanceState(Bundle outState) {
	PluginWrapper.onSaveInstanceState(outState);
	super.onSaveInstanceState(outState);
}

@Override
protected void onStart() {
	PluginWrapper.onStart();
	super.onStart();
}

注:在cocos2d-x 3.0之后的版本中集成cocos2dxActivity之后已经不需要手动实现activity里的生命周期方法,因此如果开发者发现主Activity没有这些方法,就需要自己去重写这个方法(直接拷贝上面的代码片段也可以)。且super.onCreate(savedState);请在PluginWrapper.init(this);之前调用,因为init的时候需要调用C++函数,而so文件是在onCreate时加载。

在C++层初始化AnySDK Framework框架

在C++层调用任何AnySDK Framework函数之前都需要调用init函数进行框架初始化,推荐在java层初始化完成之后通知c++层初始化框架,代码如下:
#include "AgentManager.h"
using namespace anysdk::framework;
std::string appKey = "BC26F841-OOOO-OOOO-OOOO-OOOOOOOOOOOO";
std::string appSecret = "1dff378a8f254ecOOOOOOOOOOOOO";
std::string privateKey = "696064B29E9A0OOOOOOOOOOOOO";
std::string oauthLoginServer = "http://oauth.anysdk.com/api/OauthLoginDemo/Login.php";

AgentManager::getInstance()->init(appKey,appSecret,privateKey,oauthLoginServer);
注:appKey、appSecret、privateKey这三个参数是在打包工具客户端创建游戏之后生成的游戏唯一参数,可以在打包工具游戏管理界面查看到,如下图:

游戏参数.jpg


而oauthLoginServer参数是游戏服务提供的用来做登陆验证转发的接口地址,在此处配置的接口地址仅用于sim sdk测试模式下(即直接运行母包时)做登录时框架请求的地址,而在正式打出渠道包的时候会被替换成相应渠道在打包工具中配置的地址参数。

加载及卸载SDK插件

1.在初始化框架完成之后加载所有集成的sdk,代码如下:
AgentManager::getInstance()->loadAllPlugins();//对插件进行初始化,包括对各个sdk的初始化

注:由于部分sdk在初始化时涉及到sdk闪屏的操作强烈建议在onCreate就调用loadAllPlugins接口(新框架在Java层也提供了该接口)

import com.anysdk.framework.PluginWrapper;

public class MainActivity extends Activity{
    protected void onCreate(Bundle savedState){
    super.onCreate(savedState);
    PluginWrapper.init(this);
    PluginWrapper.loadAllPlugins();
}
2.卸载插件

当游戏不需要插件时,可进⾏行卸载:

AgentManager::getInstance()->unloadAllPlugins();//对插件进行卸载,需要卸载时可调用

代码混淆

如果要混淆 java 代码,请不要混淆联编的 jar 包中的类。可以添加以下类到 proguard 配置,排除在混淆之外:

-keep class com.anysdk.framework.** {*;}
-keep class com.anysdk.Util.SdkHttpListener {*;}

iOS接入

参数示例: https://github.com/AnySDK/Sample_Cpp

获取AnySDK Framework

为了集成AnySDK Framework,请在AnySDK客户端的“安妮市场”里,选择C++(iOS)框架进行下载
下载后建议将框架拷贝到其他位置,由于下载文件夹带有空格,可能会导致工程库的搜索路径因为空格被分成两部分,导致编译错误

删除多余的Targets

目前打包工具只支持单个Target,若有多个Targets会导致打包出来的工程文件缺失,无法正常运行
可在目标上右键选择删除

UniTarget.png

如果有其他Target所需要用到的同名.plist文件,也需要删除,否则打包后工程AnySDK文件夹下可能会缺失.plist文件

UniTarget2.png

若不想在原工程文件上操作,可以在同级目录下拷贝一份.xcodeproj,并且打开其包内容,删除xcuserdata文件夹和project.xcworkspace下的xcuserdata文件夹,修改/project.xcworkspace/contents.xcworkspacedata文件中的location值,为改名后的文件名,再对拷贝后的工程文件进行操作

IOSProcess02.png

将图标转为Asset Catalog形式

在母工程中需要将Icon转为Asset Catalog形式,否则可能导致打包后图标替换错误或者闪屏替换出现问题

IconXcassets.png

若按钮为此样式,点击该Use Asset Catalog按钮,Xcode会自动转化原有图标,生成一个Images.xcassets文件夹

在项目中引用libPluginProtocol

打开您的ios项目(也就是your-project-name.xcodeproj),一般有两种方式可以引入一个外部的 framework文件(参考下面的1:添加文件到项目中,2:添加 lib 到项目中),两种方式都可以。

1:添加文件到项目中

一:右键点击 项目中的 lib文件夹,点击“Add Files to “your project name””,之后会弹出选择文件的框,找到protocols, 选取它,并点击 add,添加libPluginProtocol.a就成功了。

请不要修改.a的文件名(不同框架下文件名可能为"libPluginProtocol.a", "libPluginProtocol_libc++.a"或 "libPluginProtocol_libstdc++.a"),否则打包时检测框架版本号时会报错

Add-file.jpg
添加protocols注意要选择 "Create groups".
Addprotocols.jpg

PS:如何选择框架版本
开发者可以在工程配置查询C++ Standard Library 中查看是libc++ 、libstdc++ 、compiler-default来选择相应的库文件 编译设置库.jpg

2:添加 lib 到项目中

二:在xcode里面选中你的项目,选择TARGETS->Build Phases->Link Binary With Libraries, 点击“ + ”,(如图红色箭头所指),弹出一个界面,点击“Add Other...”,之后会弹出选择文件的框,找到libPluginProtocol.a, 选取它,并点击 open,添加libPluginProtocol.a就成功了。(include文件夹要手动添加到项目中,按照第一种方式)

Add-file1.jpg

注:iOS静态库说明: .a文件的体积(46.8M)= 真机用的.a(28.1M) + 模拟器用的.a(18.7M),当然每个.a文件还支持了不同架构:arm64 armv7 armv7s i386 x86_64。.a文件只包含了代码的部分,静态库是在编译时链接二进制代码,对产生的二进制文件的大小并不会有太大的影响,目前iOS的Sample引入AnySDK Framework产生二进制文件也只有1m的大小。

框架依赖库

libPluginProtocol需要依赖以下这几个系统库
CFNetwork.framework
CoreFoundation.framework
MobileCoreServices.framework
SystemConfiguration.framework
libz.dylib(Xcode7:libz.tbd)

添加工程配置

打开项目工程配置,添加库的链接参数,在项目⼯程配置中,找到
Linking中的Linking Other Linker Flags,添加参数: -ObjC

Ios linking.jpg

注意:如果您使用的是cocos2d-x引擎,在添加 -ObjC 后,可能会有编译报错,类似:
Ios cocos error.jpg

此时就要根据不同情况,来添加相应的类库。这里的这个报错,是需要添加库 MediaPlayer.framework和 GameController.framework。

在项目中调用AnySDK的方法

在项目加载插件

在您项目的类(例:AppDelegate来里面)里面。 引用 头文件

   #include "AgentManager.h"

例: 在

   - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

里面调用AgentManager,记得使用命名空间:

using namespace anysdk::framework;
//获取AgentManager
AgentManager* agent = AgentManager::getInstance();
std::string appKey = "Your APPKEY";
std::string appSecret = "Your APPSECRET";
std::string privateKey = "Your PRIVITEKEY";
std::string oauthLoginServer = "http://oauth.anysdk.com/api/OauthLoginDemo/Login.php";
//初始化agent
agent->init(appKey, appSecret, privateKey, oauthLoginServer);
//加载插件
agent->loadAllPlugins();

示例

Ios-pluginchannel.jpg

注意不要在.m文件中调用AnySDK的framework

注意不要在.m文件中调用AnySDK的framework,需要修改成.mm文件。

cocos2dx(V2.2.x)集成注意事项

在修改other linker flag(添加-ObjC)和引入anysdk的framewrok之后,有可能会报类似library not found lluajit的错误。如图
Luajit-notfound.jpg
需做如下修改:
Luajit-notfound1.jpg
此时在编译,会报类似std::**的错误,如图:
Std-error.jpg
解决办法如图:
Std-error1.jpg
再次编译后,会报如下图的错误:
Cocos-error.jpg
解决办法如图:
Cocos-error1.jpg

至此,编译错误搞定。