Google Cloud Messaging 서비스를 이용한 Push 정리
1. 사전준비
1)필요한 키
(1) client
가). GCMIntentService Project_id OR Push Plugin의 Sender ID
API Console의 project ID
나). Register ID: Client에서 GCM Server로부터 발급 받은 Register ID (①)
(2) Server
가). API Key
https://code.google.com/apis/console에서 발급받은 API Key
나). Client Reg ID(메세지를 받을 Client Register ID ==>①)
2. https://code.google.com/apis/console 등록
※ api Console 등록으로 알수얻을수 있는것
Proejct ID : https://code.google.com/apis/console/#project:0000XXXXX
#project 뒤부분의 0000XXXXX가 프로젝트 ID 이다.
=> Client에서 GCM Server로 등록시 사용.
API Key : GCM Service를 등록하여 받은 Key
=> GCM Server로 메세지 전송시 사용
1) https://code.google.com/apis/console에 접속
2) Sercies를 클릭
3) Google Cloud Messaging for Android 클릭
4) 동의가 완료되면 아래와 같이 On으로 표시 되어 있는것을 확인.
5) 그리고 다시 API Service를 클릭하면 아래와 같이 API Key가 발급된것을 확인 할 수 있음
4. GCM 개발환경 설정
1) GCM 관련 Plugin 설정
(1) android SDK가 설치된 Eclipse에서 Window > Android SDK Manager를 실행 합니다.
(2) Google Clound Messaging for Android를 선택하고 install packages..를 클릭.
(3) 설치가 완료되면 아래와 같이 Android SDK가 설치된 디렉토리 하위에 관련 jar파일이 생성된것을 확인 할 수 잇습니다.
gcm.jar를 Client로 복사하고
gcm-server.jar, json-simple-1.1jar를 서버 프로젝트로 복사하면 설정이 완료 됩니다.
4. cordova Push plugin 설정
cordova prject생성한 디렉토리로 이동
cd /Users/myname/java/hybridweb/helloworld
1) Push Notification Plugin 추가
cordova plugin add https://github.com/phonegap-build/PushPlugin.git
2) device Plugin 추가
cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-device.git
vi platforms/android/AndroidManifest.xml을 열어
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> 이부분이 있는지 확인 하고 없으면 추가 합니다.
최종 AndroidManifest.xml의 내용
<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="1" android:versionName="1.0.0" android:windowSoftInputMode="adjustPan" package="com.example.helloworld" xmlns:android="http://schemas.android.com/apk/res/android">
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:debuggable="true" android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/app_name" android:name="HelloWorld" android:theme="@android:style/Theme.Black.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.plugin.gcm.PushHandlerActivity" />
<receiver android:name="com.plugin.gcm.CordovaGCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.example.helloworld" />
</intent-filter>
</receiver>
<service android:name="com.plugin.gcm.GCMIntentService" />
</application>
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.example.helloworld.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.example.helloworld.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
</manifest>
3) PushNotification java file 확인
※ PushNotification을 설치 했을경우 com.plugin.gcm에 GCMIntentService.java이 생성되고
PushNotification을 사용하지 않을 경우 com.example.helloworl에 GCMIntentService.java을 구현 해야 함.
4) assets/www/PushNotification.js 화일을 확인후 없으면 찾아서 복사해줘야 함.
https://github.com/phonegap-build/PushPlugin/releases여기에서 최신버젼을 다운받아 설치 할 수도 있다.
5. Client Program
1). index.html
<!doctype html>
<html>
<meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1">
<title>Windorado.com</title>
<link rel="stylesheet" href="css/jquery.mobile-1.3.2.css" />
<script src="js/jquery-1.9.1.js"></script>
<script src="cordova.js"></script>
<script src="PushNotification.js"></script>
<script type="text/javascript">
var pushNotification;
function onDeviceReady() {
try
{
pushNotification = window.plugins.pushNotification;
if (device.platform == 'android' || device.platform == 'Android') {
$("#app-status-ul").append('<li>registering android</li>');
pushNotification.register(successHandler, errorHandler, {"senderID":"894488614381","ecb":"onNotificationGCM"}); // required!
} else {
$("#app-status-ul").append('<li>registering iOS</li>');
pushNotification.register(tokenHandler, errorHandler, {"badge":"true","sound":"true","alert":"true","ecb":"onNotificationAPN"}); // required!
}
}
catch(err)
{
txt="There was an error on this page.\n\n";
txt+="Error description: " + err.message + "\n\n";
alert(txt);
}
}
// result contains any error description text returned from the plugin call
function tokenHandler (result) {
$("#app-status-ul").append('<li>token: '+ result +'</li>');
// Your iOS push server needs to know the token before it can push to this device
// here is where you might want to send it the token for later use.
}
function successHandler (result) {
$("#app-status-ul").append('<li>success:'+ result +'</li>');
}
function errorHandler (error) {
$("#app-status-ul").append('<li>error:'+ error +'</li>');
}
// iOS
function onNotificationAPN(event) {
if (event.alert) {
navigator.notification.alert(event.alert);
}
if (event.sound) {
var snd = new Media(event.sound);
snd.play();
}
if (event.badge) {
pushNotification.setApplicationIconBadgeNumber(successHandler, errorHandler, event.badge);
}
}
// Android
function onNotificationGCM(e) {
$("#app-status-ul").append('<li>EVENT -> RECEIVED:' + e.event + '</li>');
switch( e.event )
{
case 'registered':
if ( e.regid.length > 0 )
{
$("#app-status-ul").append('<li>REGISTERED -> REGID:' + e.regid + "</li>");
// Your GCM push server needs to know the regID before it can push to this device
// here is where you might want to send it the regID for later use.
console.log("regID = " + e.regid);
//alert("regID = " + e.regid);
}
break;
case 'message':
// if this flag is set, this notification happened while we were in the foreground.
// you might want to play a sound to get the user's attention, throw up a dialog, etc.
if (e.foreground)
{
$("#app-status-ul").append('<li>--INLINE NOTIFICATION--' + '</li>');
// if the notification contains a soundname, play it.
var my_media = new Media("/android_asset/www/"+e.soundname);
my_media.play();
}
else
{ // otherwise we were launched because the user touched a notification in the notification tray.
if (e.coldstart)
$("#app-status-ul").append('<li>--COLDSTART NOTIFICATION--' + '</li>');
else
$("#app-status-ul").append('<li>--BACKGROUND NOTIFICATION--' + '</li>');
}
$("#app-status-ul").append('<li>MESSAGE -> MSG: ' + e.payload.message + '</li>');
$("#app-status-ul").append('<li>MESSAGE -> MSGCNT: ' + e.payload.msgcnt + '</li>');
break;
case 'error':
$("#app-status-ul").append('<li>ERROR -> MSG:' + e.msg + '</li>');
break;
default:
$("#app-status-ul").append('<li>EVENT -> Unknown, an event was received and we do not know what it is</li>');
break;
}
}
document.addEventListener('deviceready', onDeviceReady, false);
</script>
<script src="js/jquery.mobile-1.3.2.js"></script>
</head>
<body>
<div id="app-status-div">
<ul id="app-status-ul">
<li>Cordova PushNotification Plugin Demo</li>
</ul>
</div>
</div>
</body>
</html>
2). GCMIntentService.java
package com.plugin.gcm;
import java.util.Iterator;
import java.util.List;
import com.google.android.gcm.GCMBaseIntentService;
import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
@SuppressLint("NewApi")
public class GCMIntentService extends GCMBaseIntentService {
public static final int NOTIFICATION_ID = 237;
private static final String TAG = "GCMIntentService";
public GCMIntentService() {
super("GCMIntentService");
}
@Override
public void onRegistered(Context context, String regId) {
Log.v(TAG, "onRegistered: "+ regId);
JSONObject json;
try
{
json = new JSONObject().put("event", "registered");
json.put("regid", regId);
Log.v(TAG, "onRegistered: " + json.toString());
// Send this JSON data to the JavaScript application above EVENT should be set to the msg type
// In this case this is the registration ID
PushPlugin.sendJavascript( json );
}
catch( JSONException e)
{
// No message to the user is sent, JSON failed
Log.e(TAG, "onRegistered: JSON exception");
}
}
@Override
public void onUnregistered(Context context, String regId) {
Log.d(TAG, "onUnregistered - regId: " + regId);
}
@Override
protected void onMessage(Context context, Intent intent) {
Log.d(TAG, "onMessage - context: " + context);
// Extract the payload from the message
Bundle extras = intent.getExtras();
StringBuffer msg = new StringBuffer();
Iterator<String> iterator = extras.keySet().iterator();
while(iterator.hasNext()) {
String key = iterator.next();
String value = extras.get(key).toString();
Log.i(TAG, "onMessage. "+key+" : "+value);
msg.append(String.format("key:[%s]value:[%s]", key,value));
}
extras.putString("message",msg.toString());
extras.putString("msgcnt", "0");
createNotification(context, extras);
/*
if (extras != null)
{
PushPlugin.sendExtras(extras);
// Send a notification if there is a message
if (extras.getString("message").length() != 0) {
createNotification(context, extras);
}
}
*/
}
public void createNotification(Context context, Bundle extras)
{
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String appName = getAppName(this);
Intent notificationIntent = new Intent(this, PushHandlerActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationIntent.putExtra("pushBundle", extras);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setDefaults(Notification.DEFAULT_ALL)
.setSmallIcon(context.getApplicationInfo().icon)
.setWhen(System.currentTimeMillis())
.setContentTitle(appName)
.setTicker(appName)
.setContentIntent(contentIntent);
String message = extras.getString("message");
if (message != null) {
mBuilder.setContentText(message);
} else {
mBuilder.setContentText("<missing message content>");
}
String msgcnt = extras.getString("msgcnt");
if (msgcnt != null) {
mBuilder.setNumber(Integer.parseInt(msgcnt));
}
mNotificationManager.notify((String) appName, NOTIFICATION_ID, mBuilder.build());
}
public static void cancelNotification(Context context)
{
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel((String)getAppName(context), NOTIFICATION_ID);
}
private static String getAppName(Context context)
{
CharSequence appName =
context
.getPackageManager()
.getApplicationLabel(context.getApplicationInfo());
return (String)appName;
}
@Override
public void onError(Context context, String errorId) {
Log.e(TAG, "onError - errorId: " + errorId);
}
}
6. Server Program
http://developer.android.com/intl/ko/google/gcm/server.html을 참고하여 서버 모듈을 작성합니다.
{
"registration_ids" : ["APA91bEcaH32K2lAD-EHn739Utx_6l3Ntaiu1K5PDeSAKRpB5Gelxuj..."],
"data" : {"name":"james.. "
,"nation":"korea"
,"age":"18"
},
}
6.실행 결과..
아래의 REGID로 서버에서 호출 해줘야 클라이언트에 메세지를 전달 할 수있습니다.
'5.하이브리드 앱 > 개발' 카테고리의 다른 글
IOS iphone cordova phonegap status bar(폰갭 코드바 제목과 겹치는 문제 해결) (0) | 2013.12.17 |
---|---|
Text 입력시 키보드 위로 텍스트 박스 올리기 설정 (0) | 2013.10.29 |
IOS Simulator에 사진 넣기 (0) | 2013.09.22 |
PhoneGap(cordova) api로 하드웨어 접근하기 (0) | 2013.09.10 |
첫 하이브리드 앱(Ajax JSONP을 이용한 비동기 서버 호출) (1) | 2013.09.03 |