标签 Amazon 下的文章

使用Golang开发微信公众平台-接入验证

今年我涉猎的领域有些“广泛”,并且有那么一点“跳跃”:从上半年的终端(游戏)开发到下半年golangdocker以及目前将要提及的微信公众平台 接口开发,似乎有些远离了老本行C以及技术管理的内容。但在这个转型以及创新驱动的时代,这显然是顺势而为。寻求与新兴领域的主动接轨,在实打实的实践 中,扩大了自己的视野,并可以进一步甄别发现适合自己的领域。

移动互联网时代,微信平台一枝独秀,是社交领域的巨人,但其诞生也才不到4年。微信平台的发展前景十分广阔,企鹅公司将其打造为人与人、人与物、物与物的统一、万能入口之雄心不变,因此围绕微信平台广大开发者依旧有诸多机会。

微信公众平台接口应该算是微信平台首批对外开放的接口吧。公众平台相对成熟,但其业务模式依旧在演进和创新。公众平台接口的开发并非不难,上手几个月就可 以写成一本诸如“微信公众平台应用开发实践”的事情就发生在你我眼前,因此这里后续有关微信公众平台接口开发的文章也都是一些入门级的,我个人也是边学 习,边实践,边记录,边分享,就像上半年写Cocos2d-x文章那样。

一、公众号申请(可选

本着“再小的个体,也有自己的品牌”的微信公众平台产品哲学,只要你是合法自然人类,你就可以到https://mp.weixin.qq.com/上申请一个公众号,一般对于个体而言,只能申请订阅号。

对于具有开发能力的订阅号拥有者,你可以在订阅号的“开发者中心”,启用开发者账号。并且“一旦启用并设置服务器配置后,用户发给公众号的消息以及开发者需要的事件推送,将被微信转发到该URL中”。

不过此时即便你填写相关信息并提交,你也不会通过验证。这正是本篇要告诉你的事情,如何写程序实现微信公众平台的接入验证,后续道来。

二、测试号申请(可选)

正式的订阅号申请有些繁琐,需要提交个人信息,需要审核,不会立即生效。并且未认证的订阅号所能使用的功能接口有限(只能使用普通消息接口),而认证又需 要一笔费用(现价300rmb/次)。对于学习者而言,也许真的没有必要。于是我们在学习开发的过程中可以申请测试号来替代真正的公众号。

测试号是一种体验账号,有效期一年,具有各种功能接口体验权限。测试号可以在http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login下申请,申请时有一个类似公众号开发者配置的页面需要你填写服务器配置。同样,你需要进行接入验证(后续道来)。

一旦申请成功,可以用终端微信app扫一扫测试号的QR,关注微信平台测试号,用于后续平台接口开发测试。

以上公众号和测试号二选一

三、公众号服务器

为何需要公众号服务器,这就要谈及微信公众平台的架构了。

很多人觉得微信公众平台的业务模式有些类似于若干年前火爆一时的短信增值业务模式-SP/CP模式:

【终端用户】 <—-短信—> 【移动运营商移动增值业务网关】 <—-> 【SP/CP服务器】

微信公众号时代,这个业务模式变成了:

【终端用户】 <—-微信消息—> 【微信公众平台】 <—–> 【公众号服务器】

短信变成了微信,SP/CP变成了公众号。微信公众平台将终端用户发给公众号的信息转发至公众号配置的公众号服务器URL,公众号服务器做业务处理后,将响应信息通过微信公众平台再发给终端用户。因此我们需要实现公众号业务逻辑的公众号服务器。

本文标题里所说的“接入验证”,指的就是微信公众平台对公众号服务器提供服务的URL有效性的验证。我们在填写开发者中心的“接口配置信 息”并提交时,微信公众平台会向配置的公众号服务器的URL发送验证Request,只有公众号服务存在,且按要求返回包含特定信息的Response, 我们才能真正通过微信公众平台的验证,“接口配置信息”才真正生效。

因此我们需要一台放在公网的主机。如果采用Golang开发公众号服务的话,这样的主机只能是独立的VPS,像国内新浪提供的app engine主机不能运行Golang,无法满足要求(当然如果你使用其他语言开发的话,比如PHP,那么可用的主机范围就很广泛了)。

这里建议申请一个亚马逊免费EC2主机(t2.micro型,免费一年,学习够用)用作学习测试使用或者购买像LinodeDigitalOcean的VPS。关于如何申请亚马逊主机可以咨询谷歌和度娘,这里不赘述。

注意:Amazon EC2实例默认采用的时动态IP,instance重启后IP会发生变化。因此可申请分配一个Elastic IP,并绑定在你的EC2实例上,目前绑定instance的Elastic IP是免费的,这个IP在instance重启后不会变更。当你EC2主机到期后,记得释放这个IP,否则就收费了。

四、接入验证逻辑

前面提到过,无论是公众号还是测试号,当你提交配置URL时会收到提交失败的信息,这是微信公众平台接入验证失败所致。在公众平台开发者文档中,关于URL验证逻辑如下:

开发者提交信息(包括URL、Token)后,微信服务器将发送Http Get请求到填写的URL上,GET请求携带四个参数:signature、timestamp、nonce和echostr。公众号服务程序应该按如下要求进行接入验证:

1. 将token、timestamp、nonce三个参数进行字典序排序
2. 将三个参数字符串拼接成一个字符串进行sha1加密
3. 将加密后获得的字符串与signature对比,如果一致,说明该请求来源于微信
4. 如果请求来自于微信,则原样返回echostr参数内容

以上完成后,接入验证就会生效,开发者配置提交就会成功。

列出Http抓包分析后的文本,理解起来就更容易些:

微信服务器发出的验证Request如下:

GET /?signature=d01007dcff994c555bc51d22e154956ccdc61ec5&timestamp=1418970951&nonce=484765335&echostr=qwe1235 HTTP/1.0\r\n
User-Agent: Mozilla/4.0\r\n
Accept: */*\r\n
Host: wechat.tonybai.com\r\n
Pragma: no-cache\r\n
Content-Length: 0\r\n

应答返回如下:
HTTP/1.0 200 OK\r\n
Date: Fri, 19 Dec 2014 06:35:59 GMT\r\n
Content-Length: nn\r\n
Content-Type: text/plain; charset=utf-8\r\n

qwe1235

五、参考实现

环境:AWS t2.micro ubuntu 14.04 x86_64 Server
     go 1.4

Go语言标准库提供了一个强大的http server,我们直接利用这个server来处理微信平台的Url验证请求。另外微信平台发给公众平台服务器的http request都是请求到"/"下的,这样我们的service无需设置太多http route。

//urlvalidation.go
package main

import (
        "crypto/sha1"
        "fmt"
        "io"
        "log"
        "net/http"
        "sort"
        "strings"
)

const (
        token = "wechat4go"
)

func makeSignature(timestamp, nonce string) string {
        sl := []string{token, timestamp, nonce}
        sort.Strings(sl)
        s := sha1.New()
        io.WriteString(s, strings.Join(sl, ""))
        return fmt.Sprintf("%x", s.Sum(nil))
}

func validateUrl(w http.ResponseWriter, r *http.Request) bool {
        timestamp := strings.Join(r.Form["timestamp"], "")
        nonce := strings.Join(r.Form["nonce"], "")
        signatureGen := makeSignature(timestamp, nonce)

        signatureIn := strings.Join(r.Form["signature"], "")
        if signatureGen != signatureIn {
                return false
        }
        echostr := strings.Join(r.Form["echostr"], "")
        fmt.Fprintf(w, echostr)
        return true
}

func procRequest(w http.ResponseWriter, r *http.Request) {
        r.ParseForm()
        if !validateUrl(w, r) {
                log.Println("Wechat Service: this http request is not from Wechat platform!")
                return
        }
        log.Println("Wechat Service: validateUrl Ok!")
}

func main() {
        log.Println("Wechat Service: Start!")
        http.HandleFunc("/", procRequest)
        err := http.ListenAndServe(":80", nil)
        if err != nil {
                log.Fatal("Wechat Service: ListenAndServe failed, ", err)
        }
        log.Println("Wechat Service: Stop!")
}

编译这个go源码,执行urlvalidation。

$> urlvalidation
2014/12/18 17:48:10 Wechat Service: Start!
2014/12/18 17:48:10 Wechat Service: ListenAndServe failed, listen tcp :80: bind: permission denied

程序提示没有权限绑定80端口。80端口只有管理员权限才能绑定,因此我们需要通过sudo方式执行validation。

$ sudo ./urlvalidation
2014/12/18 09:56:29 Wechat Service: Start!

接下来我们回到订阅号开发者中心配置页面或测试号服务器配置页面,点击提交。在我们的公众号服务器后台可以看到如下日志:

2014/12/18 09:56:52 Wechat Service: validateUrl Ok!

同时你的提交也会显示成功,Url已经验证通过,你将正式成为开发者。

如果我们随意构造一个http get 请求发给validate程序,比如:

curl -s http://wechat.tonybai.com(比如我的URL为http://wechat.tonybai.com)

那么我们将看到validation输出如下错误日志:

2014/12/18 10:02:07 Wechat Service: this http request is not from Wechat platform!

以上源码文件在这里可以下载。

处于安全考虑,后续订阅号平台均需要对收到的http request进行验证,以确保请求来源于微信公众平台。

Cocos2d-x集成Amazon内购和GameCircle服务

由于种种原因,这篇文章已经拖延了N多时间了。今天花了些时间把如何在Cocos2d-x(我用的版本是2.2.2)游戏中集成Amazon内购GameCircle服务(仅适用于Android版本)整理一下,发出来,作备忘。

之前在做“手指足球世界杯2014”时,想给这款小游戏加上内购(In-App Purchasing)和积分榜(ScoreBoard)功能。说到Android手机游戏的内购,人们第一时间想到的就是Google Play,不过悲催的是,Google Play在国内各种无法访问,行货机也不预装,其相关Service的测试十分困难,翻看了一些集成Google Game Service的文章,其过程坎坷之程度让人望而却步。于是我将目光转而投向了Amazon Game Service。亚马逊的游戏服务起步要晚些,成熟性肯定不如Google,但在国内来说也不失为另一个不错的选择,Google虽好,但访问不了有啥 法。但似乎国内同行使用Amazon游戏服务的并不多,度娘上相关中文资料甚少。但从Amazon发布的数据来看,其市场正在逐步扩大,并紧紧跟随 Google Play的脚步。

之前用kindle paperwhite时在amazon.com上注册了一个国际帐号,这次正好用这个。不过你要使用Amazon的Game Service,普通Amazon帐号是不行的。你要升级为Amazon的Developer。申请Developer帐号的过程还是蛮繁琐的,要提交一 堆资料,具体细节我大致忘的差不多了,这里就不说了。按照Amazon网站的提示一步一步做就是了。

有了帐号后,你可以下载Amazon的Game SDK了,这个包有近50M大小,本地解压后可以看到其提供的Android SDK种类:

AmazonSDK/Android$ ls
Ads  AmazonInsights  DeviceMessaging  GameCircle  InAppPurchasing  LoginWithAmazon  Maps  MobileAssociates  README.txt

Ads我之前用的是Google Admob,这里就不再用Amazon的了,我需要的是这里的InAppPurchasing和GameCircle。我们接下来一个一个来说。

* Amazon InAppPurchasing

Amazon支持三种内购类型:Consumables、Entitlements和Subscriptions:
    Consumables就像游戏中的红心、金币等,用户可以多次购买,每次可以买多个,并根据游戏规则,每次消耗若干个以达到某种游戏目的;在哪台设备上购买,就只能在哪台设备上使用。
    Entitlements是某种授权协议,一个用户只需购买一次,即可长期使用某种特权功能,并与设备无关,可在多个设备下授权使用。比如鳄鱼洗澡游戏中购买高级关卡等。
    Subscriptions有订阅的意思,需要某种Entitlements或某种访问权,在一定时间段内绑定有效,到期后自动renew,比如某种杂志的阅读权等。

我只想给游戏增加一些红心功能,一颗红心,可以让游戏者有一次续命的机会,因此我需要实现Consumables型内购。Amazon SDK中提供了Consumeables类内购的Android范例AmazonSDK/Android/InAppPurchasing/samples/SampleIAPConsumablesApp。我们可以参考这个例子来实现我的"红心内购"。

    1、添加依赖的jar包
    在你的游戏proj中添加内购功能所依赖的Amazon SDK jar包,包括AmazonInsights-android-sdk-2.1.26.jar、in-app-purchasing-1.0.3.jar 和login-with-amazon-sdk.jar。

    2、添加源文件
    参照例子,将AppPurchasingObserver.java、AppPurchasingObserverListener.java和MySKU.java拷贝到你的与XXActivity.java同级目录下。

    3、初始化Amazon IAP
   
    在你的XXActivity类中添加如下方法:

    public PurchaseDataStorage purchaseDataStorage;

    private void setupIAPOnCreate() {
        purchaseDataStorage = new PurchaseDataStorage(this);

        AppPurchasingObserver purchasingObserver
              = new AppPurchasingObserver(this, purchaseDataStorage);
        purchasingObserver.setListener(this);

        Log.i(TAG, "onCreate: registering AppPurchasingObserver");
        PurchasingManager.registerObserver(purchasingObserver);
    }

    protected void onCreate(Bundle savedInstanceState){
        … …
        setupIAPOnCreate();
    }

        protected void onResume() {
        super.onResume();
       
        Log.i(TAG, "onResume: call initiateGetUserIdRequest");
        PurchasingManager.initiateGetUserIdRequest();

        Log.i(TAG, "onResume: call initiateItemDataRequest for skus: "
                        + MySKU.getAll());
        PurchasingManager.initiateItemDataRequest(MySKU.getAll());
    }

    4、添加购买方法

    在Cocos2d-x的某个Scene或Layer中实现的购买方法事件的callback,后者通过Jni调用Java静态方法:

    void BuyHeartScene::buyHearts(int number) {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    JniMethodInfo t;
    if (JniHelper::getStaticMethodInfo(t, "net/iwobi/game/flickworldcup/FlickWorldCupActivity",
                "onBuyHeartClick", "(I)V")) {
        t.env->CallStaticVoidMethod(t.classID, t.methodID, number);
        if (t.env->ExceptionOccurred()) {
            t.env->ExceptionDescribe();
            t.env->ExceptionClear();
            return;
        }
        t.env->DeleteLocalRef(t.classID);
    }
#endif
    }

    该Java方法的实现如下(我这里有五种商品ONEHEART到FIVEHEART):

    public static void onBuyHeartClick(int type) {
        String requestId;
      
        switch (type) {
            case 1:
                requestId = PurchasingManager.initiatePurchaseRequest(MySKU.ONEHEART.getSku());
                break;
            case 2:
                requestId = PurchasingManager.initiatePurchaseRequest(MySKU.TWOHEART.getSku());
                break;
            case 3:
                requestId = PurchasingManager.initiatePurchaseRequest(MySKU.THREEHEART.getSku());
                break;
            case 4:
                requestId = PurchasingManager.initiatePurchaseRequest(MySKU.FOURHEART.getSku());
                break;
            case 5:
                requestId = PurchasingManager.initiatePurchaseRequest(MySKU.FIVEHEART.getSku());
                break;
            default:
                requestId = PurchasingManager.initiatePurchaseRequest(MySKU.ONEHEART.getSku());
                break;
        }

        PurchaseData purchaseData = ((FlickWorldCupActivity)context).purchaseDataStorage
                .newPurchaseData(requestId);
        Log.i(TAG, "onBuyHeartClick: requestId (" + requestId
                + ") requestState (" + purchaseData.getRequestState() + ")");
    }

    5、修改各种回调方法

    将SampleIAPConsumablesApp/src/com/amazon/sample/iap/consumable /MainActivity.java中的onPurchase为前缀名的方法以及onGetUserIdResponseSuccessful挪到你的 Activity源文件中。这些方法绝大部分是不需要修改的,除非你不喜欢例子中日志输出的格式,或是想用toast之类的提示方式改造各种 callback的结果显示方式。

    这里我主要修改了一个方法:onPurchaseResponseSuccess。该方法在购买成功后被调用,我们在这个事件发生时更新Scene或Layer的显示(updateHeartInScene)。

    @Override
    public void onPurchaseResponseSuccess(String userId, String sku,
            String purchaseToken) {
        Log.i(TAG, "onPurchaseResponseSuccess: for userId (" + userId
                + ") sku (" + sku + ")");
        SKUData skuData = purchaseDataStorage.getSKUData(sku);
        if (skuData == null)
            return;

        if (MySKU.ONEHEART.getSku().equals(skuData.getSKU())) {
            updateHeartInScene(1);
        }

        if (MySKU.TWOHEART.getSku().equals(skuData.getSKU())) {
            updateHeartInScene(2);
        }

        if (MySKU.THREEHEART.getSku().equals(skuData.getSKU())) {
            updateHeartInScene(3);
        }

        if (MySKU.FOURHEART.getSku().equals(skuData.getSKU())) {
            updateHeartInScene(4);
        }

        if (MySKU.FIVEHEART.getSku().equals(skuData.getSKU())) {
            updateHeartInScene(5);
        }
    }

    6、AndroidManifest.xml和其他Java文件

    AppPurchasingObserver.java和AppPurchasingObserverListener.java你可以原封不动的使用。MySKU.java可以根据你的内购项目做改造:

    public enum MySKU {

    ONEHEART("net.iwobi.game.flickworldcup.iap.consumable.oneheart", 1),
    TWOHEART("net.iwobi.game.flickworldcup.iap.consumable.twoheart", 1),
    THREEHEART("net.iwobi.game.flickworldcup.iap.consumable.threeheart", 1),
    FOURHEART("net.iwobi.game.flickworldcup.iap.consumable.fourheart", 1),
    FIVEHEART("net.iwobi.game.flickworldcup.iap.consumable.fiveheart", 1);
   
    private String sku;
    private int quantity;

    private MySKU(String sku, int quantity) {
        this.sku = sku;
        this.quantity = quantity;
    }

    public static MySKU valueForSKU(String sku) {
        if (ONEHEART.getSku().equals(sku)) {
            return ONEHEART;
        }
       
        if (TWOHEART.getSku().equals(sku)) {
            return TWOHEART;
        }

        if (THREEHEART.getSku().equals(sku)) {
            return THREEHEART;
        }

        if (FOURHEART.getSku().equals(sku)) {
            return FOURHEART;
        }

        if (FIVEHEART.getSku().equals(sku)) {
            return FIVEHEART;
        }
       
        return null;
    }

    public String getSku() {
        return sku;
    }

    public int getQuantity() {
        return quantity;
    }

    private static Set<String> SKUS = new HashSet<String>();
    static {
        SKUS.add(ONEHEART.getSku());
        SKUS.add(TWOHEART.getSku());
        SKUS.add(THREEHEART.getSku());
        SKUS.add(FOURHEART.getSku());
        SKUS.add(FIVEHEART.getSku());
    }

    public static Set<String> getAll() {
        return SKUS;
    }

 }

 AndroidManifest.xml中在application标签下添加如下配置:
        <receiver android:name="com.amazon.inapp.purchasing.ResponseReceiver" >
            <intent-filter>
                <action
                    android:name="com.amazon.inapp.purchasing.NOTIFY"
                    android:permission="com.amazon.inapp.purchasing.Permission.NOTIFY" />
            </intent-filter>
        </receiver>
 有了以上代码,我们的内购就可以运行起来了。
   

* 内购测试

使用Amazon In-app Purchasing API一个最大好处就是测试简单。Amazon提供一个本地测试程序Amazon App Tester(安装到Android模拟器中),可以模拟内购Server,SDK自动判断当前场景,如果是测试,你的集成了内购SDK的游戏将连接本地 测试程序完成内购流程。通过在本地测试程序中设置模拟不同的内购流程,我们可以轻松完成测试。

你需要给Amazon App Tester提供一个名为amazon.sdktester.json的文件,这样Amazon App Tester可以知道你的游戏有哪些内购项目,并模拟出这些内购项目。这个json文件可以自行编辑,也可以在Amazon deveoper网站上生成下载。

我直接将内购项目添加到我的Amazon帐号的游戏应用下面,一共五个,添加成功后,下载json文件。将该文件放在模拟器的/mnt/sdcard下,绝对路径为/mnt/sdcard/amazon.sdktester.json。

之后,启动App Tester,再启动你的游戏,点击内购项目,看看是否能购买成功。

* 内购上线

按照Amazon官方说法,SDK会自动区分测试场景和正式场景,因此通过App Tester测试的游戏在发布后,理论上内购是没有问题的。不过我上线后还是遇到了问题,即点击购买某个项目后,游戏没有任何反应,等了若干分钟都是这 样。我将这个问题反馈给Amazon Support,得到的答复居然是游戏代码没有问题,他们测试了若干中机型,都可以打开内购页面,并进行内购。只是有时内购页面打开有些延迟,但都能打 开。看到这里,我猜是否又是大陆网络的问题呢!不管它了,至少通过Amazon Support的回复可以证明我的代码是ok的。只能希望美国人民多多购买我的内购项目了^_^。

* Amazon游戏圈

想给游戏增加成就榜和成就提交功能,如果自己实现服务端,显然麻烦,工作量大不说,还得维护一个Server。但市面上提供这类服务的游戏平台不多。 Google Play的游戏Service提供这种服务,不过还是上面提到的原因,我与Google的这个服务无缘啊。Amazon Game SDK后期推出了GameCircle服务。

GameCircle目前提供achievements, leaderboards和Whispersync三种特性:
    achievements就是奖励机制,帮助游戏提高玩家粘性。
    leaderboards类似于积分榜,可以用于提交玩家积分以及显示玩家的全球排名。
    Whispersync是一种数据游戏同步服务,同步玩家进度,保寸玩家个性化数据等。

这里我要用到的是leaderboards。

    1、建立GameCircle
    使用游戏圈前,你需要在Amazon官方的Amazon Apps & Services Developer Console下创建属于你的Game Circle,然后创建一个LeaderBoard,设置LeaderBoard属性。SDK中提供了GameCircle的Demo:AmazonSDK/Android/GameCircle

    2、导入jar包,设置AndroidManifest.xml
    要想使用GameCircle,我们需要导入相应的SDK jar包:gamecirclesdk.jar。

    在AndroidManifest.xml中,需要在application标签下添加以下配置:

                <activity
            android:name="com.amazon.ags.html5.overlay.GameCircleUserInterface"
            android:hardwareAccelerated="false"
            android:theme="@style/GCOverlay" >
        </activity>
        <activity
            android:name="com.amazon.identity.auth.device.authorization.AuthorizationActivity"
            android:allowTaskReparenting="true"
            android:launchMode="singleTask"
            android:theme="@android:style/Theme.NoDisplay" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data
                    android:host="net.iwobi.game.flickworldcup"
                    android:scheme="amzn" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.amazon.ags.html5.overlay.GameCircleAlertUserInterface"
            android:hardwareAccelerated="false"
            android:theme="@style/GCAlert" >
        </activity>

        <receiver
            android:name="com.amazon.identity.auth.device.authorization.PackageIntentReceiver"
            android:enabled="true" >
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_INSTALL" />
                <action android:name="android.intent.action.PACKAGE_ADDED" />

                <data android:scheme="package" />
            </intent-filter>
        </receiver>

   
        这些配置中需要的res,可以从AmazonSDK/Android/GameCircle/GameCircleSDK/res/中找到并copy到你的project中。

    3、初始化GameCircle

    GameCircleSDK这个Demo中没有提供太多源码,src目录下是空的。因此我们只能参考Amazon Developer站点上页面上的说明一步步的添加和调整我们的代码了。

    在你的XXActivity类中,我们添加如下方法:

    //reference to the agsClient
    public AmazonGamesClient agsClient;
    
    AmazonGamesCallback callback = new AmazonGamesCallback() {
            @Override
            public void onServiceNotReady(AmazonGamesStatus status) {
                Message msg = new Message();
                switch (status) {
                // The SDK failed to initialize correctly.
                case CANNOT_INITIALIZE:
                    Log.i(TAG, "onServiceNotReady: CANNOT_INITIALIZE");
                    msg.obj = "Can not initialize Amazon Game Services";
                    break;

                // The SDK is in the process of initializing.
                case INITIALIZING:
                    Log.i(TAG, "onServiceNotReady: INITIALIZING");
                    msg.obj = "Initializing Amazon Game Services";
                    break;

                // The device not registered with an account
                case NOT_AUTHENTICATED:
                    Log.i(TAG, "onServiceNotReady: NOT_AUTHENTICATED");
                    msg.obj = "The Device does not registered with an account";
                    break;

                // The game is not authorized to use this service.
                case NOT_AUTHORIZED:
                    Log.i(TAG, "onServiceNotReady: NOT_AUTHORIZED");
                    msg.obj = "Not authorized to use Amazon Game Services";                   
                    break;
                }
               
                //unable to use service
                msg.what = 21;               
                notifyHandler.sendMessage(msg);
            }
            @Override
            public void onServiceReady(AmazonGamesClient amazonGamesClient) {
                agsClient = amazonGamesClient;
             
                //ready to use GameCircle
                if (agsClient != null)
                    Log.i(TAG, "on AmazonGamesCallback: call onServiceReady, agsClient init ok");
                else
                    Log.i(TAG, "on AmazonGamesCallback: call onServiceReady, agsClient init failed");
            }
    };
    
    //list of features your game uses (in this example, achievements and leaderboards)
    EnumSet<AmazonGamesFeature> myGameFeatures = EnumSet.of(
            AmazonGamesFeature.Leaderboards);

    protected void onResume() {
        super.onResume();
       
        … …
        AmazonGamesClient.initialize(this, callback, myGameFeatures);
    }

        public void onPause() {
        super.onPause();
        if (agsClient != null) {
            agsClient.release();
        }
    }

   
    4、提交成就积分

    当玩家结束游戏时,可以选择将此次的高分上传到leaderboards上。游戏中应对积分提交的代码也在XXActivity中。

    public static void onSubmitScoreToLeaderBoard(int score) {
        if (((FlickWorldCupActivity)context).agsClient == null) {
            Message msg = new Message();
            msg.what = 21;
            msg.obj = "Unable to use Amazon Game Services";
            notifyHandler.sendMessage(msg);
            return;
        }
       
        LeaderboardsClient lbClient = ((FlickWorldCupActivity)context).agsClient.getLeaderboardsClient();
        AGResponseHandle<SubmitScoreResponse> handle = lbClient.submitScore("FlickWorldCupTopScore", score);
         
        // Optional callback to receive notification of success/failure.
        handle.setCallback(new AGResponseCallback<SubmitScoreResponse>() {
         
            @Override
            public void onComplete(SubmitScoreResponse result) {
                if (result.isError()) {
                    // Add optional error handling here.  Not strictly required
                    // since retries and on-device request caching are automatic.
                    Message msg = new Message();
                    msg.what = 22;
                    msg.obj = "Submit Score to LeaderBoard Failed!";
                    notifyHandler.sendMessage(msg);
                } else {
                    // Continue game flow.
                    Message msg = new Message();
                    msg.what = 23;
                    msg.obj = "Submit Score to LeaderBoard OK!";
                    notifyHandler.sendMessage(msg);
                }
            }
        });       
    }

    如果仅是查看积分排行,可以用下面这个方法:

    public static void onShowLeaderBoardOverlay() {
        if (((FlickWorldCupActivity)context).agsClient == null) {
            Message msg = new Message();
            msg.what = 21;
            msg.obj = "Unable to use Amazon Game Services";
            notifyHandler.sendMessage(msg);
            return;
        }
       
        LeaderboardsClient lbClient = ((FlickWorldCupActivity)context).agsClient.getLeaderboardsClient();
        AGResponseHandle<RequestResponse> handle = lbClient.showLeaderboardOverlay("FlickWorldCupTopScore");
       
        handle.setCallback(new AGResponseCallback<RequestResponse>() {
            
            @Override
            public void onComplete(RequestResponse result) {
                if (result.isError()) {
                    // Add optional error handling here.  Not strictly required
                    // since retries and on-device request caching are automatic.
                    Log.i(TAG, "onShowLeaderBoardOverlay – onComplete: Show LeaderBoard Request Failed!");
                }
            }
        });     
    }

   
* 游戏圈上线

游戏圈无法在本地进行测试,只能在真实的游戏圈中测试代码是否ok。不过Amazon的游戏圈提供了管理功能,在测试后发布前可将游戏圈 leaderboard的值reset。游戏圈leaderboard发布后,你就可以使用leaderboard了。游戏圈功能在国内访问是没有任何问 题的,查看积分榜,提交分数到积分榜都很顺畅。

* 小结

Amazon游戏SDK在国内的应用估计比较小众,大家可能更多的选择用Google Play提供的服务或是AppStore的,但Amazon毕竟为游戏开发者提供了一个选择(而且是完全免费的哦),另外Amazon的Support对 提交问题的反馈较为及时(无论是mail还是forum上的提问),基本24小时内就会有答复。各种设施的发布也比较快,有时候3-4个小时即可生效。

目前Amazon Game SDK的资料多为英文,且集中在Amazon官方站点以及官方维护的support论坛中。遇到问题,亚马逊的论坛是第一选择。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats