Android開発 C2DMを触ってみよう

こんにちは熊谷です。

前回は簡単なWEBブラウザを作成しましたが、今回はそこからちょっと離れて、Android 2.2以降から使えるC2DM(Cloud to Device Messaging)でメッセージの受信を試してみたいと思います。

今現在、C2DMを使うには
http://code.google.com/intl/ja/android/c2dm/signup.html
ここで登録を行う必要があります。登録フォームで必要な情報を入力し送信して、しばらく待っていると登録完了したよ的なメールが送られてきます。

そのメールが来たら早速使ってみましょう。

まずはC2DMを使って端末にメッセージを送信するため、認証Tokenを取得します。


<?php
$url = 'https://www.google.com/accounts/ClientLogin';
// signupページで入力したgoogleアカウントのIDとパスワード
$google_id = 'メールアドレス'; // 送信者ID
$google_pwd = 'パスワード';
$header = array(
  'Content-type: application/x-www-form-urlencoded',
);
$post_list = array(
  'accountType' => 'GOOGLE',
  'Email' => $google_id,
  'Passwd' => $google_pwd,
  'source' => 'sample-sample',
  'service' => 'ac2dm',
);
$post = http_build_query($post_list, ' &');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$ret = curl_exec($ch);
print_r($ret);

メールアドレス/パスワード部分には先ほどの登録フォームで登録したGoogleアカウントの情報を入力します(ちなみにこのGoogleアカウントIDが送信者IDになります)。
このPHPを実行すると


SID=XXXXXXXXXXXXXXXXXXXXXX
LSID=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
Auth=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

といった感じで結果が表示されます。このAuth=以降が認証Tokenになります。

つぎにメッセージを受信するためのAndroidアプリケーションを作成するわけですが、C2DMを簡単に使うために、chrometophoneアプリケーションで使用されているGoogleのパッケージを利用します。
http://code.google.com/p/chrometophone/
このアプリケーションで使用されているcom.google.android.c2dmパッケージはC2DMを利用する上で色々便利なので今回それを使用します。

このパッケージを利用して以下のようなコードを書いていきます。

C2DMReceiver.java


package com.example.app;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import com.google.android.c2dm.C2DMBaseReceiver;
public class C2DMReceiver extends C2DMBaseReceiver {
    public C2DMReceiver() {
        super("送信者ID");
    }
    @Override
    public void onRegistrered(Context context, String registrationId) {
        Log.w("registration id:", registrationId);
        sendMessage("id:" + registrationId);
    }
    @Override
    public void onUnregistered(Context context) {
        sendMessage("C2DM Unregistered");
    }
    @Override
    public void onError(Context context, String errorId) {
        sendMessage("err:" + errorId);
    }
    @Override
    protected void onMessage(Context context, Intent intent) {
        String str = intent.getStringExtra("message");
        Log.w("message:", str);
        sendMessage(str);
    }
   
    private void sendMessage(String str) {
        Message mes = Message.obtain(TopActivity.mH);
        Bundle data = mes.getData();
        data.putBoolean("receivedMessageFlag", true);
        data.putString("receivedMessageString", str);
        TopActivity.mH.sendMessage(mes);
        mes = null;
    }
 }

TopActivity.java


package com.example.app;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.c2dm.C2DMessaging;
public class TopActivity extends Activity {
    public static Handler mH;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        C2DMessaging.register(this, "この端末利用者のGoogleアカウントID");
        TextView textView = (TextView) findViewById(R.id.text_view);
        textView.setText(C2DMessaging.getRegistrationId(this));
       
        mH = new Handler() {
            public void handleMessage(android.os.Message msg) {
                if (msg.getData().getBoolean("receivedMessageFlag")) {
                    String message = msg.getData().getString("receivedMessageString");
                   
                    Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
                   
                    TextView textView = (TextView) findViewById(R.id.message);
                    textView.setText(message);
                }
            }
        };
    }
}

ビューとなるXMLは以下のような感じです。

main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="registration id"
    android:id="@+id/text_view"
    />
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="message"
    android:id="@+id/message"
    />
</LinearLayout>

また、C2DMを利用するためにはAndroidManifestにパーミッション等々を追加する必要もあります。それを追加したものは以下のようになります。

AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.app"
      android:versionCode="1"
      android:versionName="1.0">
<permission android:name="com.example.app.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.example.app.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application android:label="@string/app_name"
android:icon="@drawable/icon">
<activity android:name="TopActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".C2DMReceiver" />
<receiver android:name="com.google.android.c2dm.C2DMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.app" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.example.app" />
</intent-filter>
</receiver>
</application>
</manifest>

これでアプリケーションを実行すると

このようにid:xxxxxxxxxxxxxxxxxといった感じで英数字が表示されると思います。これがこの端末のregistration idになります。

このregistration idに向けてサーバからメッセージが送信されます。で、そのメッセージを送信するためのスクリプトは以下のようになります。認証Token部分には先に取得した認証Tokenを入れ、registration idにはActivityに表示されていたあの英数字を入れます。


<?php
$url = 'https://android.apis.google.com/c2dm/send';
$registration_id = 'XXXXXXXXXXXXXXXXXXXXXXXX'; // registration id
$message = 'あいうえおかきくけこ';
$header = array(
  'Content-type: application/x-www-form-urlencoded',
  'Authorization: GoogleLogin auth=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', // 認証Token
);
$post_list = array(
  'registration_id' => $registration_id,
  'collapse_key' => 1,
  'data.message' => $message,
);
$post = http_build_query($post_list, ' &');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$ret = curl_exec($ch);
var_dump($ret);

これでこのPHPスクリプトを実行すると

端末上にこのような感じで送信したメッセージが表示されます。

以上、駆け足でしたがC2DMを触ってみた記録です。プッシュでメッセージを送信できるので色々楽しめると思いますので試してみてください。