Menu

Category

Archive

logo


Amazon Device Messagingの実装

2014-10-17 21:30:00 +0900
  • このエントリーをはてなブックマークに追加

ここ最近、既存のAndroidプロジェクトをKindleに対応させています。主に、GoogleのサービスをAmazonのものに取り替えるということをしています。この記事は、その過程で学んだ、Google Cloud Messaging を Amazon Device Messagingに切り替える方法の記事です。

Obtaining Amazon Device Messaging Credentials

ADMでは、デバッグ時にAPIキーが必要です。基本的にプロダクションの際には必要ないようです。

まずは、Amazon Apps & Games Developer Portal にてアプリを新規作成。作成されたアプリのメニューの Device Messaging を選択し、Security Profile を作成。この Security Profileは、いくつかのアプリで共有することもできます。もし、この Profileを共有した場合には、データもそのいくつかのアプリ内でシェアされます。

Amazon Apps & Games Developer Portal の Apps & Services > My Apps にて、アプリを既に登録している場合は、そのアプリを選択し、登録していない場合は登録してください。このアプリを選択して、Device Messagingを選択して、Security profile を作成します。

このSecurity Profileを作成したら、View Security Profileをクリックし、Kindle/Android Settingsタブを表示します。ここでやってAPIキーを作成できます。必要な情報は、パッケージ名signature(後述)APIキーへの名前。APIキーの名前は、任意です。パッケージ名もAndroidのマニフェストファイル等に書いてあるでしょう。signatureは、少し操作が必要です。私が実際に試した方法は、APKファイルを用意し、ターミナルで下記のコマンドを実行しました。

1 $ unzip -p {your-app.apk} META-INF/CERT.RSA | keytool -printcert | grep MD5

これで、MD5: 2E:0B:46:F8:D0:4A:06:AC:18:7A:2E:B0:42:95:58:FE のようなアウトプットがあるはずです。この 2EからFEまでをコピペすればAPIキーを作成されます。

このAPIキーは先程の、Amazon Apps & Games Developer Portalで確認することができます。しかし、ページをリロードするたびにこのAPIキーは変更されます。これらの複数のAPIキーはどれもvalidらしいので、あまり気にしなくて良いようです。私は、ADMが上手く動かなく、自分のAPIキーの作り方が悪かったのかと、これを疑って時間を潰してしまいました。(ソース)

Setting Up Amazon Device Messaging

ここからはEclipseにて既にAndroidのプロジェクトがあるという前提で話を進めていきます。ここでは、ADMを使用するのに必要なファイルをプロジェクトに追加します。

まずは、Eclipseでプロジェクトのルートディレクトリを右クリック等して、Propertiesを選択します。Java Built Pathの中の、Librariesタブを選択。Add External JARs… を選択して、SDKの Android/DeviceMessaging/libの中の amazon-device-messaging.jarを選択。SDKは、ここでダウンロードできます。下記の参考リンクにあるSDKへのリンクが異なるので注意です。

これで完了です。一応、Package ExploreのReferenced Libraries の中に、amazon-device-message-****.jar というのが発見できることを確認してください。

Integrating Your App with Amazon Device Messaging

次に、マニフェストファイルの設定、assetへapi_key.txtの追加、ReceiverとHandler(broadcast receiver)の実装です。

 1 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 2    xmlns:amazon="http://schemas.amazon.com/apk/res/android"
 3    package="[YOUR PACKAGE NAME]"
 4    android:versionCode="1"
 5    android:versionName="1.0" >
 6  
 7    <!-- Because the Fire <span id="XinhaEditingPostion"></span>devices that support ADM are based on Android API level 15,
 8       your minSdkVersion must be NO GREATER THAN 15 (<=15). You may have a lower SDK version,
 9       if that is appropriate for your app. -->
10    <uses-sdk
11       android:minSdkVersion="15"
12       android:targetSdkVersion="15" />
13  
14    <!-- This permission ensures that no other application can intercept your ADM messages.
15       "[YOUR PACKAGE NAME]" is your package name as defined in your <manifest> tag. -->
16    <permission
17       android:name="[YOUR PACKAGE NAME].permission.RECEIVE_ADM_MESSAGE"
18       android:protectionLevel="signature" />
19    <uses-permission android:name="[YOUR PACKAGE NAME].permission.RECEIVE_ADM_MESSAGE" />
20  
21    <!-- This permission allows your app access to receive push notifications from ADM. -->
22    <uses-permission android:name="com.amazon.device.messaging.permission.RECEIVE" />
23  
24    <!-- ADM uses WAKE_LOCK to keep the processor from sleeping when a message is received. -->
25    <uses-permission android:name="android.permission.WAKE_LOCK" />
26  
27    <application
28       android:icon="@drawable/ic_launcher"
29       android:label="@string/app_name"
30       android:theme="@style/AppTheme" >
31  
32       <!-- You must explicitly enable ADM and declare whether your app cannot work without
33          ADM (android:required="true") or can work without ADM (android:required="false").
34          If you specify android:required="false", your app must degrade gracefully if ADM
35          is unavailable. -->
36       <amazon:enable-feature
37          android:name="com.amazon.device.messaging"
38          android:required="true"/>
39  
40       <!-- Provide references to the message handler and broadcast receiver for your app here. Replace
41          the names in the service and receiver tags with names appropriate to your package. -->
42       <service
43          android:name="[YOUR SERVICE NAME]"
44          android:exported="false" />
45  
46       <!-- This permission ensures that only ADM can send your app registration broadcasts. -->
47       <receiver
48          android:name="[YOUR RECEIVER NAME]"
49          android:permission="com.amazon.device.messaging.permission.SEND" >
50  
51          <!-- To interact with ADM, your app must listen for the following intents. -->
52          <intent-filter>
53          <action android:name="com.amazon.device.messaging.intent.REGISTRATION" />
54          <action android:name="com.amazon.device.messaging.intent.RECEIVE" />
55  
56          <!-- You must replace the name in the category tag with your app's package name. -->
57          <category android:name="[YOUR PACKAGE NAME]" />
58          </intent-filter>
59  
60       </receiver>
61    </application>
62 </manifest>

このようにpermission等を追加します。

そして、api_key.txtという名前でファイルをassetsフォルダに置かなければなりません。このファイルには、先ほどのAPIキーをスペース等なくコピペします。

 1 public class MyADMMessageHandler extends ADMMessageHandlerBase
 2 {
 3     public static class Receiver extends ADMMessageReceiver
 4     {
 5         public Receiver()
 6         {
 7             super(MyADMMessageHandler.class);
 8         }
 9   
10     // Nothing else is required here; your broadcast receiver automatically
11     // forwards intents to your service for processing.
12     }
13      
14     @Override
15     protected void onRegistered(final String newRegistrationId)
16         {
17         // You start the registration process by calling startRegister() in your Main
18         // Activity. When the registration ID is ready, ADM calls onRegistered() on
19         // your app. Transmit the passed-in registration ID to your server, so your
20         // server can send messages to this app instance. onRegistered() is also
21         // called if your registration ID is rotated or changed for any reason; your
22         // app should pass the new registration ID to your server if this occurs.
23         // Your server needs to be able to handle a registration ID up to 1536 characters
24         // in length.
25   
26         // The following is an example of sending the registration ID to your
27         // server via a header key/value pair over HTTP.
28         URL url = new URL(YOUR_WEBSERVER_URL);
29         HttpURLConnection con = (HttpURLConnection) url.openConnection();
30         con.setDoInput(true);
31         con.setUseCaches(false);
32         con.setRequestMethod("POST");
33         con.setRequestProperty("RegistrationId", newRegistrationId);
34         con.getResponse();
35         }
36      
37     @Override
38     protected void onUnregistered(final String registrationId)
39     {
40         // If your app is unregistered on this device, inform your server that
41         // this app instance is no longer a valid target for messages.
42     }
43      
44     @Override
45     protected void onRegistrationError(final String errorId)
46     {
47         // You should consider a registration error fatal. In response, your app may
48         // degrade gracefully, or you may wish to notify the user that this part of
49         // your app's functionality is not available.
50     }
51  
52     @Override
53     protected void onMessage(final Intent intent)
54     {
55         // Extract the message content from the set of extras attached to
56         // the com.amazon.device.messaging.intent.RECEIVE intent.
57  
58         // Create strings to access the message and timeStamp fields from the JSON data.
59         final String msgKey = getString(R.string.json_data_msg_key);
60         final String timeKey = getString(R.string.json_data_time_key);
61          
62         // Obtain the intent action that will be triggered in onMessage() callback.
63         final String intentAction = getString(R.string.intent_msg_action);
64  
65         // Obtain the extras that were included in the intent.
66         final Bundle extras = intent.getExtras();
67                  
68         // Extract the message and time from the extras in the intent.
69         // ADM makes no guarantees about delivery or the order of messages.
70         // Due to varying network conditions, messages may be delivered more than once.
71         // Your app must be able to handle instances of duplicate messages.
72         final String msg = extras.getString(msgKey);
73         final String time = extras.getString(timeKey);
74     }
75 }

そして、遂にRegistrationId(デバイストークン)を取得し、それを適宜サーバーへ送信です。後は、サーバー側からメッセージをこのトークンを使用して送ることができます。

雑ですが以上です。

参考

Obtaining Amazon Device Messaging Credentials
Setting Up Amazon Device Messaging
Integrating Your App with Amazon Device Messaging
Requesting an Access Token for Amazon Device Messaging


Thread: why do API keys of game circle keep changing when refreshing the web page ?