読者です 読者をやめる 読者になる 読者になる

androidからGAEのサーバにデータを送信する

androidアプリと、GAE(Python)の連携です。
共円チェッカーでステージを送信するときのコードです。

String url = context.getString(R.string.upload_url);
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>();
nameValuePair.add(new BasicNameValuePair("data", params[0]));
try {
    httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair,
            HTTP.UTF_8));
    HttpResponse response = httpClient.execute(httpPost);
    String ret = EntityUtils.toString(response.getEntity());

    return ret;
} catch (IOException e) {
    throw new RuntimeException(e);
} finally {
    httpClient.getConnectionManager().shutdown();
}

URLはstrings.xmlに定義し、Context#getString(int)にて取得しています。
データの送信には、org.apache.http.client.HttpClientを利用しました。
また、GETではなく、POSTで送信するために、org.apache.http.client.methods.HttpPostを利用しています。
で、送信したいデータはparams[0]に設定してあるので、BasicNameValuePairに設定し、Listに追加しています。
HttpEntityEnclosingRequestBase#setEntity(HttpEntity)に設定する際にUTF-8エンコードしています。(たぶん、この設定のおかげで日本語が送信できています)
設定が完了したら、HttpClient#execute(HttpUriRequest)でデータを送信します。
EntityUtils#toString(HttpEntity)で、レスポンスを文字列として取得しています。
あとは、finally節にてHttpClientのクローズを行っています。


で、これを受け取るサーバ側

#!/usr/bin/env python
#-*- coding: utf-8 -*-
#
import logging
from google.appengine.ext import webapp, db
from google.appengine.ext.webapp.util import run_wsgi_app

# パズルのステージ情報
class KyouenPuzzle(db.Model):
    # ステージ番号
    stageNo = db.IntegerProperty(required=True)
    # サイズ
    size = db.IntegerProperty(required=True)
    # ステージ上の石の配置
    stage = db.StringProperty(required=True)
    # 作者
    creator = db.StringProperty()

# 中略

# 登録処理
class KyouenRegist(webapp.RequestHandler):
    # POSTリクエストを処理します。
    def post(self):
        # パラメータ名:dataを取得
        data = self.request.get('data').split(',')
        logging.debug("post data:" + str(data))

        # 入力データの登録    
        model = KyouenPuzzle(stageNo=self.getNextStageNo(),
                             size=int(data[0]),
                             stage=data[1],
                             creator=data[2].replace('\n', ''))
        model.put()

        # レスポンスの返却
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write('success stageNo=' + str(model.stageNo))
        return

application = webapp.WSGIApplication([('/regist', KyouenRegist)
                                      ], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

KyouenPuzzleクラスがDB登録用のクラスです。
4つのプロパティを持っています。で、それが登録されます。
KyouenRegistクラスは、javaで言う、javax.servlet.http.HttpServletを継承したクラス。
postメソッドを定義し、POSTリクエストを処理します。
リクエストデータをself.request.get('data')で取得できます。('data'はjavaで指定した文字列)
日本語としてちゃんと取得できました。
KyouenPuzzleのコンストラクタに対して、creatorに代入する際にreplace('\n', '')としているのは、エラー対策です。(creatorがmultiline=Trueとして定義されていないので、複数行のデータを登録するとエラーになります)


こんな感じでGAEにデプロイしておけば、android側で

<string name="upload_url">http://[設定したID].appspot.com/regist</string>

と設定しておけば、GAE上のDBにデータを登録できます。


Pythonは初めてだったので、ループの構文やら、文字列操作やらに手間取りましたが、簡潔に記述できて楽しかったです。
暇ができれば、ちゃんと本買って勉強しようと思います。