プッシュ通知(GCM版)システムの構築(2014 改訂)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="xxxxxx.permission.RECEIVE" /> <permission android:name="xxxxxx.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="xxxxxx.permission.C2D_MESSAGE" /> <application ・・・・・・・・・・・ ・・・・・・・・・・・ ・・・・・・・・・・・ <service android:name=".GcmIntentService" android:enabled="true"/> <receiver android:name=".GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <category android:name="xxxxxx" /> </intent-filter> </receiver> ・・・・・・・・・・・ ・・・・・・・・・・・ ・・・・・・・・・・・ </application>
import java.util.Iterator; import com.google.android.gms.gcm.GoogleCloudMessaging; import android.app.IntentService; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.SystemClock; import android.support.v4.app.NotificationCompat; import android.util.Log; import android.widget.Toast; public class GcmIntentService extends IntentService { public static final int NOTIFICATION_ID = 1; private NotificationManager mNotificationManager; NotificationCompat.Builder builder; public GcmIntentService() { super("GcmIntentService"); } @Override protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this); String messageType = gcm.getMessageType(intent); if (!extras.isEmpty()) { if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) { Log.d("LOG","messageType(error): " + messageType + ",body:" + extras.toString()); } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) { Log.d("LOG","messageType(deleted): " + messageType + ",body:" + extras.toString()); } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) { Log.d("LOG","messageType(message): " + messageType + ",body:" + extras.toString()); Iterator<String> it = extras.keySet().iterator(); String key; String value; while(it.hasNext()) { key = it.next(); value = extras.getString(key); } //通知バーに表示 sendNotification("Received Message"); } } GcmBroadcastReceiver.completeWakefulIntent(intent); } private void sendNotification(String msg) { mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_launcher) .setContentTitle("GCM Notification") .setStyle(new NotificationCompat.BigTextStyle() .bigText(msg)) .setContentText(msg); mBuilder.setContentIntent(contentIntent); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } }
import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.support.v4.content.WakefulBroadcastReceiver; public class GcmBroadcastReceiver extends WakefulBroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // Explicitly specify that GcmMessageHandler will handle the intent. ComponentName comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName()); // Start the service, keeping the device awake while it is launching. startWakefulService(context, (intent.setComponent(comp))); setResultCode(Activity.RESULT_OK); } }
import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.gcm.GoogleCloudMessaging; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.os.AsyncTask; import java.util.Map; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; public class MainActivity extends Activity { private final String PROJECT_ID = "<プロジェクトID>"; AsyncTask<Void, Void, String> registtask = null; public static final String EXTRA_MESSAGE = "message"; public static final String PROPERTY_REG_ID = "registration_id"; private static final String PROPERTY_APP_VERSION = "appVersion"; private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000; public GoogleCloudMessaging gcm; public String regid = ""; Context context; @Override public void onStart() { super.onStart(); context = getApplicationContext(); // Play serviceが有効かチェック if (checkPlayServices()) { gcm = GoogleCloudMessaging.getInstance(context); regid = getRegistrationId(context); if(regid.equals("")){ regist_id(); } } else { Log.i("", "Google Play Services は無効"); } } private boolean checkPlayServices() { int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); if (resultCode != ConnectionResult.SUCCESS) { if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) { GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_RESOLUTION_REQUEST).show(); } else { Log.i("", "Play Service not support"); } return false; } return true; } private String getRegistrationId(Context context) { final SharedPreferences prefs = getGCMPreferences(context); String registrationId = prefs.getString(PROPERTY_REG_ID, ""); if (regid.equals("")) { return ""; } // アプリケーションがバージョンアップされていた場合、レジストレーションIDをクリア int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE); int currentVersion = getAppVersion(context); if (registeredVersion != currentVersion) { return ""; } return registrationId; } private SharedPreferences getGCMPreferences(Context context) { return getSharedPreferences(MainActivity.class.getSimpleName(), Context.MODE_PRIVATE); } private int getAppVersion(Context context) { try { PackageInfo packageInfo = context.getPackageManager() .getPackageInfo(context.getPackageName(), 0); return packageInfo.versionCode; } catch (NameNotFoundException e) { throw new RuntimeException("package not found : " + e); } } private void storeRegistrationId(Context context, String regId) { final SharedPreferences prefs = getGCMPreferences(context); int appVersion = getAppVersion(context); SharedPreferences.Editor editor = prefs.edit(); editor.putString(PROPERTY_REG_ID, regId); editor.putInt(PROPERTY_APP_VERSION, appVersion); editor.commit(); } private void regist_id(){ if (regid.equals("")) { registtask = new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... params) { if (gcm == null) { gcm = GoogleCloudMessaging.getInstance(context); } try { //GCMサーバーへ登録 regid = gcm.register(PROJECT_ID); } catch (IOException e) { e.printStackTrace(); } //取得したレジストレーションIDを自分のサーバーへ送信して記録しておく //サーバーサイドでは、この レジストレーションIDを使ってGCMに通知を要求します registeid2YouServer(regid); // レジストレーションIDを端末に保存 storeRegistrationId(context, regid); return null; } @Override protected void onPostExecute(String result) { registtask = null; } }; registtask.execute(null, null, null); } } public boolean registid2YouServer(String regId) { String serverUrl = "<あなたのサーバーのURLと実行ファイル名>"; Map<String, String> params = new HashMap<String, String>(); params.put("my_id", regId); try { post(serverUrl, params); return true; } catch (IOException e) { e.printStackTrace(); } return false; } public static void post(String endpoint, Map<String, String> params) throws IOException { URL url; try { url = new URL(endpoint); } catch (MalformedURLException e) { throw new IllegalArgumentException("invalid url: " + endpoint); } StringBuilder bodyBuilder = new StringBuilder(); Iterator<Entry<String, String>> iterator = params.entrySet().iterator(); while (iterator.hasNext()) { Entry<String, String> param = iterator.next(); bodyBuilder.append(param.getKey()).append('=') .append(param.getValue()); if (iterator.hasNext()) { bodyBuilder.append('&'); } } String body = bodyBuilder.toString(); byte[] bytes = body.getBytes(); HttpURLConnection conn = null; try { conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setUseCaches(false); conn.setFixedLengthStreamingMode(bytes.length); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded;charset=UTF-8"); OutputStream out = conn.getOutputStream(); out.write(bytes); out.close(); int status = conn.getResponseCode(); if (status != 200) { throw new IOException("Post failed with error code " + status); } } finally { if (conn != null) { conn.disconnect(); } } } }
<?php $registatoin_ids = array(); //レジストレーションIDの配列セットは記録したDBからとって来るなりなんなりしてやってください array_push($registatoin_ids, '<レジストレーションID>'); //以下はダミー $name = "dummy"; $title = "dummy"; $message = "dummy"; $gcm = new GCM(); $send_content = array("name"=> $name ,"title"=> $title ,"message"=> $message); $result_android = $gcm->send_notification($registatoin_ids,$send_content,$ttl); class GCM{ function __construct(){} public function send_notification($registatoin_ids,$send_content){ // GOOGLE API KEY define("GOOGLE_API_KEY","<APIキー>"); $url = "https://android.googleapis.com/gcm/send"; $fields = array( "collapse_key" => "score_update", "delay_while_idle" => true, "registration_ids" => $registatoin_ids, "data" => $send_content ); $headers = array( "Authorization: key=".GOOGLE_API_KEY, "Content-Type: application/json" ); $ch = curl_init(); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_POST,true); curl_setopt($ch,CURLOPT_HTTPHEADER,$headers); curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); curl_setopt($ch,CURLOPT_POSTFIELDS,json_encode($fields)); $result = curl_exec($ch); if($result === FALSE){ die("Curl failed: ".curl_error($ch)); } curl_close($ch); echo $result; } } ?>