PythonからGoogleのAPIを利用してAndroidへPUSH通知する
2014-03-08
QiitaPythonAndroidGoogle の API を用いて Android 端末への PUSH とステータスバーへの通知の表示メモ
クライアント(Android)
Android で PUSH 通知をするための準備はhttp://dev.classmethod.jp/smartphone/android/gcm/に書いてあります。 本当に参考になりました。
ここからは上のリンクからの変更点と追加点についてです。
Google Developers Console での手順が多少変わっているので、そこについて説明します。
まず、https://console.developers.google.com/projectにアクセスし、既存の project か"CREATE PROJECT"を選択します。
project を作成 or 選択して project のページを開きます。 ページ上部の"Project Number"は控えておきましょう。 そして、左側のサイドメニューの"APIs & auth" > "APIs" から"Google Cloud Messaging for Android"の STATUS を ON にします。 なお、公式のドキュメントはここです。
次に、"APIs & auth" > "Credentials"で"Public API access"の"CREATE NEW KEY"を選択し、新しく API key を取得します。 表示されるダイアログでは"Server Key"を選択し、IP アドレスは 0.0.0.0 を入力します。 ここは必要があれば変更しましょう。 テスト用であれば 0.0.0.0 で問題ありません。多分。
GcmBroadcastReceiver.java は上のリンクのものをそのまま利用させてもらいます。 次に、GcmIntentService.java を通知のために書き換えます。
public class GcmIntentService extends IntentService {
private static final String TAG = GcmIntentService.class.getSimpleName();
private Notification notification;
private NotificationManager nm;
public GcmIntentService() {
super("GcmIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.v(TAG, "onHandleIntent");
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(TAG, "messageType: " + messageType + ",body:" + extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
Log.d(TAG,"messageType: " + messageType + ",body:" + extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
Log.d(TAG,"messageType: " + messageType + ",body:" + extras.toString());
}
}
// ここまでhttp://dev.classmethod.jp/smartphone/android/gcm/のものとほぼ同じ
// extrasに、サーバーからのdataが入っている
// ここでは、すべて文字列として格納してある
Log.v(TAG, extras.toString());
int userId = Integer.parseInt(extras.getString("user_id"));
String text = extras.getString("text");
// 通知を開くとMainActivityが表示されるようにする
Intent i = new Intent(getApplicationContext(), MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
i.setType("notification");
i.putExtra("user_id", userId);
i.putExtra("text", text);
// 第4引数を0にすると、Intentのextrasだけ更新されず、通知のテキストは違うのにextrasだけ同じなため、
// Intent先のMainActivityでextrasを取得すると同じ値しかとれなくなる事態に
PendingIntent pi = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder notificationBuilder =
new Notification.Builder(getApplicationContext())
.setContentIntent(pi)
.setSmallIcon(R.drawable.icon_small)
.setTicker("通知がきました") // 通知が来た時にステータスバーに表示されるテキスト
.setContentTitle("通知のタイトル") // 通知バーを開いた時に表示されるタイトル
.setContentText("通知のテキスト") // タイトルの下に表示されるテキスト
.setWhen(System.currentTimeMillis()); // 通知が表示されるタイミング?
long[] vibrate_ptn = {0, 100, 300, 1000}; // 振動パターン(適当)
notification = notificationBuilder.build();
notification.vibrate = vibrate_ptn;
notification.defaults |= Notification.DEFAULT_LIGHTS; // デフォルトLED点滅パターンを設定
notification.flags = Notification.FLAG_ONGOING_EVENT;
// NotificationManagerのインスタンス取得
nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(R.string.app_name, notification); // 設定したNotificationを通知する
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
nm.cancel(R.string.app_name);
}
}
続いて通知をタップした時の動作として起動される MainActivity です。
大体上のリンクのものでいいですが、onCreate
に以下のコードを追加します。
// notification表示関係
Intent intent = getIntent();
String intentType = intent.getType();
if (intentType != null && intentType.equals("notification")) {
Log.v(TAG + " extras", intent.getExtras().toString());
// extrasからGcmIntentService.javaでいれたデータを取り出す
int user_id = intent.getIntExtra("user_id", 0);
String text = intent.getStringExtra("text");
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// ダイアログの表示
Toast.makeText(this, text, Toast.LENGTH_LONG);
}
registerInBackground()
によって Log cat に registrationId が表示されるので、これを控えます。
アプリケーションとして実装するなら、この ID をサーバーに渡して保存するようにします。
サーバー(Python)
python からはrequests
を利用して Google へリクエストを送ります。
import requests
import json
def push_notificate(user_id, text):
'''エラーが出るとrにエラーメッセージが入る
これを呼び出せばAndroidに通知が行く
'''
gcm_url = 'https://android.googleapis.com/gcm/send'
# 上で控えたregistrationIdとAPI key
regid = REGID
key = "key=" + APIKEY
headers = {'content-type': 'application/json', 'Authorization': key}
# 渡すデータは適当です。
# dictのkeyはAndroidのextrasのkeyと合わせましょう
params = json.dumps(\
{'registration_ids': [regid], \
'data': {'id': user_id, 'text': text}})
r = requests.post(gcm_url, data=params, headers=headers)
print r.text
return
requests
で basic 認証をクリアするには引数にauth=(username, password)
を渡しますが、今回は headers に入れて渡します。
これで大丈夫だと思います。
from: https://qiita.com/petitviolet/items/4dd5cc8f7dd6d1f22933