AWS（SNS, Cognito）を用いてAndroidアプリにプッシュ通知するまでの手順（アプリ編）

以前投稿した、[AWS（SNS, Cognito）を用いてAndroidアプリにプッシュ通知するまでの手順（サーバー編）](http://qiita.com/MJeeeey/items/2b62b6958d8023dec1da) のアプリ側の実装部分をこちらにまとめました。

# Gradle ファイルの編集

プロジェクト直下および app フォルダ直下の build.gradle を編集します。
AWS, GCM に関する依存関係を記述します。（バージョンは投稿時のものです。更新されたものを記述してください）

~~~:SampleApp/build.gradle

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0'

        // gcm
        classpath 'com.google.gms:google-services:1.3.0'
    }
}

~~~

~~~:app/build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'

    // gcm
    compile 'com.google.android.gms:play-services-gcm:8.4.0'
    // aws
    compile 'com.amazonaws:aws-android-sdk-cognito:2.2.14'
    compile 'com.amazonaws:aws-android-sdk-sns:2.2.14'
}

// gcm
apply plugin: 'com.google.gms.google-services'

~~~

# Manifest ファイルの編集

コードに関して参考にしたサンプルファイルを紹介しておきます。
[https://github.com/googlesamples/google-services/tree/master/android/gcm/app/src/main/java/gcm/play/android/samples/com/gcmquickstart](https://github.com/googlesamples/google-services/tree/master/android/gcm/app/src/main/java/gcm/play/android/samples/com/gcmquickstart)

このうち、以下のJavaファイルを使用しますので、MainActivity と同じ場所にコピーしてください。

~~~
MyGcmListenerService.java
MyInstanceIDListenerService.java
RegistrationIntentService.java
~~~

Manifest ファイルに以下を追記します。

~~~xml:AndroidManifest.xml
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <permission android:name="[package name].permission.C2D_MESSAGE" android:protectionLevel="signature" />
    <uses-permission android:name="[package name].permission.C2D_MESSAGE" />

    <application
        ... >

        <!-- 省略 -->

        <receiver
            android:name="com.google.android.gms.gcm.GcmReceiver"
            android:exported="true"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="[package name].gcm" />
            </intent-filter>
            <!-- 4.4以前をサポートする場合は以下が必要 -->
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            </intent-filter>
        </receiver>
        <service
            android:name="[package name].MyGcmListenerService"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </service>
        <service
            android:name="[package name].MyInstanceIDListenerService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.android.gms.iid.InstanceID" />
            </intent-filter>
        </service>
        <service android:name="[package name].RegistrationIntentService"/>
    </application>
~~~

# リソースファイルの編集

Sender Id（数値）は strings.xml にて定義します。

~~~xml:strings.xml
<resources>
    <string name="app_name">SampleApp</string>

    <string name="gcm_defaultSenderId">xxxxxxxxxxx</string>
</resources>
~~~

# プッシュ通知に関する実装

MainActivity にて、RegistrationIntentService を呼び出します。

~~~java:MainActivity.java
public class MainActivity extends AppCompatActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		callRegistrationIntentService();
	}

	private void callRegistrationIntentService() {
		if (checkPlayServices()) {
			// Start IntentService to register this application with GCM.
			Intent intent = new Intent(this, RegistrationIntentService.class);
			startService(intent);
		}
	}

	private boolean checkPlayServices() {
		Log.i(TAG, "checkPlayServices start");
		GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
		int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
		if (resultCode != ConnectionResult.SUCCESS) {
			if (apiAvailability.isUserResolvableError(resultCode)) {
				apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST).show();
			} else {
				Log.i(TAG, "This device is not supported.");
				finish();
			}
			return false;
		}
		return true;
	}
}
~~~

RegistrationIntentService.java では、最初に onHandleIntent メソッドが呼ばれます。
デバイストークンが取得できますので、Cognito, SNS への登録処理を行います。

~~~java:RegistrationIntentService.java
public class RegistrationIntentService extends IntentService {

	@Override
	protected void onHandleIntent(Intent intent) {

		/* 省略（サンプルと同じ） */

		sendRegistrationToServer(token);

		/* 省略（サンプルと同じ） */
	}

	private void sendRegistrationToServer(String token) {
		// Add custom implementation, as needed.

		initAWSCognito(token);
	}

	private void initAWSCognito(String strGcmToken) {
		final String Cognito_Identity_Pool_Id = "ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
		final Regions Cognito_Region_Type = Regions.AP_NORTHEAST_1;

		// Initialize the Amazon Cognito credentials provider
		CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
			getApplicationContext(),
			Cognito_Identity_Pool_Id,	// Identity Pool ID
			Cognito_Region_Type
		);

		initAWSSns(credentialsProvider, strGcmToken);
	}

	private void initAWSSns(CognitoCachingCredentialsProvider credentialsProvider, String strGcmToken) {
		final String SNS_Platform_Application_Arn = "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:app/GCM/SampleApp";
		final String SNS_Topic_Arn = "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:SampleApp_Android";
		final Regions Default_Service_Region_Type = Regions.AP_NORTHEAST_1;

		AmazonSNSClient snsClient = new AmazonSNSClient(credentialsProvider);
		snsClient.setRegion(Region.getRegion(Default_Service_Region_Type));

		CreatePlatformEndpointRequest createRequest = new CreatePlatformEndpointRequest();
		createRequest.setToken(strGcmToken);	// GCMサーバから受け取ったGCMトークン
		createRequest.setPlatformApplicationArn(SNS_Platform_Application_Arn); // 作成したプラットフォームアプリケーションARN
		createRequest.setCustomUserData("任意の文字列");
		CreatePlatformEndpointResult platformEndpoint = snsClient.createPlatformEndpoint(createRequest);

		String endpointArn = platformEndpoint.getEndpointArn();
		snsClient.subscribe(SNS_Topic_Arn, "application", endpointArn); // 作成したトピックARN
	}
}
~~~

# プッシュ通知の受信処理

プッシュ通知の受信に成功すると、MyGcmListenerService.java 内の onMessageReceived メソッドが呼ばれます。

~~~java:MyGcmListenerService.java
public class MyGcmListenerService extends GcmListenerService {

	@Override
	public void onMessageReceived(String from, Bundle data) {
		String message = data.getString("message");
		Log.d(TAG, "From: " + from);
		Log.d(TAG, "Message: " + message);

		/* 実行したい何かを実装 */

	}

}
~~~

以上です。