GCM 구현1 - Android
안드로이드 : http://ghj1001020.tistory.com/783?category=719597
서버 : http://ghj1001020.tistory.com/784?category=756570
가이드 : https://developers.google.com/cloud-messaging/android/client
1. 앱은 GCM 토큰을 가져와서 앱에 저장합니다
2. 서버에서 앱에 저장된 GCM 토큰을 사용하여 메시지를 요청합니다
3. 앱이 GCM 메시지 수신하고 알림을 띄웁니다
* 테스트 용도 이므로 토큰을 서버에 저장하는 부분은 제외했습니다. (서버에서는 디바이스의 GCM 토큰을 하드코딩해서 보냅니다)
build.gradle
1 2 3 4 5 | dependencies { ... //gcm implementation 'com.google.android.gms:play-services-gcm:11.8.0' } | cs |
AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <uses-permission android:name="android.permission.WAKE_LOCK" /> <application> ... <!-- GCM --> <!-- GCM으로 부터 message를 받을 수 있도록 권한선언 --> <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" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="com.ghj.gcmex" /> </intent-filter> </receiver> <!-- 등록 토큰 생성 및 업데이트 처리 --> <service android:name=".gcm.MyInstanceIDService" android:exported="false"> <intent-filter> <action android:name="com.google.android.gms.iid.InstanceID" /> </intent-filter> </service> <!-- 메시지 수신처리 --> <service android:name=".gcm.MyGcmListenerService" android:exported="false"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> </intent-filter> </service> <!-- 토큰 가져오기 --> <service android:name=".gcm.RegistrationIntentService" android:exported="false" /> </application> |
* 메시지 수신할 때 절전모드를 유지하기위해 WAKE_LOCK 권한을 줍니다
* com.google.android.gms.gcm.GcmReceiver 은 GCM으로부터 메시지를 받는 리시버입니다
MyInstanceIDService.java
1 2 3 4 5 6 7 8 9 10 | public class MyInstanceIDService extends InstanceIDListenerService { //등록 토큰이 업데이트 되면 호출된다 @Override public void onTokenRefresh() { Intent intent = new Intent(this, RegistrationIntentService.class); startService(intent); } } | cs |
* GCM 토큰이 업데이트 되면 호출되는 서비스 입니다
* 토큰을 가져와서 앱에 저장하기 위해 RegistrationIntentService 서비스를 호출합니다
RegistrationIntentService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | //IntentService : 작업을 수행하는 스레드를 별도로 생성 , stopService도 자동적으로 호출 public class RegistrationIntentService extends IntentService { private static final String TAG = "RegistIntentService"; public RegistrationIntentService() { super( TAG ); } //서비스 시작시 호출 @Override protected void onHandleIntent(@Nullable Intent intent) { String senderId = getString(R.string.gcm_sender_id); try { synchronized ( TAG ) { //토큰 가져와서 앱에 저장 InstanceID instanceID = InstanceID.getInstance(this); String token = instanceID.getToken( senderId , GoogleCloudMessaging.INSTANCE_ID_SCOPE , null); Log.d("GCM_Token" , token); saveGcmToken(token); } } catch ( Exception e ) { e.printStackTrace(); } } //shared preferences 에 토큰 저장 public void saveGcmToken(String token) { SharedPreferences pref = getSharedPreferences(getString(R.string.pref_gcm_token) , Context.MODE_PRIVATE); SharedPreferences.Editor editor = pref.edit(); editor.putString(getString(R.string.pref_key_gcm_token) , token); editor.commit(); } } | cs |
* GCM 토큰을 가져와서 앱에 저장하는 서비스 입니다
MyGcmListenerService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | public class MyGcmListenerService extends GcmListenerService { private final String TAG = "MyGcmListenerService"; //알림 private final String GCM_DATA_KEY_TITLE = "title"; private final String GCM_DATA_KEY_BODY = "body"; private static int NOTIFICATION_ID = 0; private final long[] ALARM_PATTERN = new long[]{ 100, 100, 100, 100 }; //메시지 수신시 호출 @Override public void onMessageReceived(String s, Bundle bundle) { //메시지 수신 후 알림 띄우기 if( bundle != null ) { Log.d(TAG, "onMessageReceived : "+bundle.toString()); String title = bundle.getString(GCM_DATA_KEY_TITLE , ""); String body = bundle.getString(GCM_DATA_KEY_BODY , ""); sendNotificaion(title , body); } } //알림에 띄우기 public void sendNotificaion(String title, String body) { NotificationManager notiManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); String chGroupId = getString(R.string.alarm_ch_group_id_gcm); String channelId = getString(R.string.alarm_ch_id_gcm); //26 오레오 이상 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if( !checkNotificationChannelGroup(chGroupId) ) { //알림 채널 그룹 NotificationChannelGroup notiGroup = new NotificationChannelGroup( chGroupId, getString(R.string.alarm_ch_group_name_gcm) ); notiManager.createNotificationChannelGroup( notiGroup ); } if( !checkNotificationChannel(channelId) ) { //알림 채널 NotificationChannel notiChannel = new NotificationChannel(channelId, getString(R.string.alarm_ch_name_gcm), NotificationManager.IMPORTANCE_HIGH); notiChannel.setGroup(chGroupId); notiChannel.enableLights(true); notiChannel.setLightColor(Color.GREEN); notiChannel.enableVibration(true); notiChannel.setVibrationPattern( ALARM_PATTERN ); notiChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); notiChannel.setShowBadge(true); notiManager.createNotificationChannel(notiChannel); } } //알림 생성 String appName = getString(R.string.app_name); Intent intent = new Intent(this, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); //이미 존재할 경우 이를 유지하고 추가 데이터만 새로운 Intent에 있는 것으로 대체 NotificationCompat.Builder noti = new NotificationCompat.Builder(this, channelId); noti.setAutoCancel(true); //클릭시 알림 제거 noti.setContentTitle(title); noti.setContentText(body); noti.setTicker(appName); noti.setSmallIcon(R.mipmap.ic_launcher); noti.setContentIntent(pi); noti.setVibrate( ALARM_PATTERN ); noti.setSound( RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) ); noti.setOngoing(false); //지우기 버튼으로 삭제 (true - 일반 알림 위에 정렬, 지우기 버튼으로 삭제 못함) noti.setOnlyAlertOnce(true); //알림이 아직 표시되지 않은 경우 사운드, 진동, 티커만 재생되도록 noti.setWhen( System.currentTimeMillis() ); //알림에서 보여지는 발생시간 noti.setNumber(1); //알림의 오른쪽 번호 noti.setGroupSummary(true); if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) { noti.setVisibility( Notification.VISIBILITY_SECRET ); //보안화면에서 알림 보이지 않음 } try { notiManager.notify(NOTIFICATION_ID++ , noti.build() ); } catch (Exception e) { e.printStackTrace(); } } //notification channel group 등록 체크 public boolean checkNotificationChannelGroup(String groupId) { boolean result = false; //true : 이미 등록됨 , false : 미등록 if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ) { NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); List<NotificationChannelGroup> groups = notificationManager.getNotificationChannelGroups(); if( groups != null && groups.size() > 0 ) { for ( NotificationChannelGroup group : groups ) { if( groupId.equalsIgnoreCase(group.getId()) ) { result = true; break; } } } } return result; } //notification channel 등록 체크 public boolean checkNotificationChannel( String channelId ) { if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ) { NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); return notificationManager.getNotificationChannel(channelId) != null ? true : false; } return false; } } | cs |
* GCM 메시지를 수신한 후 알림을 띄웁니다
* GCM 메시지 수신이 되면 onMessageReceived 함수가 호출됩니다
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getGcmToken(); } //token 가져오기 public void getGcmToken(){ SharedPreferences pref = getSharedPreferences(getString(R.string.pref_gcm_token) , Context.MODE_PRIVATE); String token = pref.getString(getString(R.string.pref_key_gcm_token), ""); if( TextUtils.isEmpty(token) ) { Intent intent = new Intent( this, RegistrationIntentService.class ); startService( intent ); } else { Log.d("GCM_Token", token); } } } | cs |
* MainActivity 시작시 GCM 토큰이 없으면 GCM 토큰을 가져오는 서비스를 시작합니다
'IT > - 프로그래밍' 카테고리의 다른 글
Android Retrofit2 예제 (0) | 2020.04.20 |
---|---|
GCM 구현2 - 서버 (0) | 2018.08.11 |
Android Google의 Mobile Vision을 이용한 바코드 스캐너 만들기 (0) | 2018.07.21 |
Android canvas 에서 속이 빈 도형 그리기 (0) | 2018.07.21 |
Android 액티비티를 팝업(Popup)으로 띄우기 , 데이터 주고받기 (6) | 2018.07.14 |