[안드로이드] FCM 화면 깨우기 화면 켜지게 하는 방법

2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 푸시메세지 웹서버(JAVA)에서 보내기

2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 토큰 저장방법 개별 보내는 방법 SharedPreferences 사용

2017/07/12 - [Yame Programmer/Android] - [안드로이드] FCM 백그라운드에서 진동 오도록 하는 방법




후.. FCM메세지를 노티피케이션이 아니라 data로 날리도록 하니


지금까지 삽질해도 안되던 화면 깨우기가 되었다..


진짜 아무것도 모르는 상태로 근본없이 맨땅에 헤딩하니 좀 지친다



화면 깨우기는 간단하다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void onMessageReceived(RemoteMessage remoteMessage) {
        //추가한것
       // sendNotification(remoteMessage.getData().get("message"));
 
        // 이거 추가 하면 
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE );
        PowerManager.WakeLock wakeLock = pm.newWakeLock( PowerManager.SCREEN_DIM_WAKE_LOCK
                | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG" );
        wakeLock.acquire(3000);
 
 
        String title = remoteMessage.getData().get("title");
        String body = remoteMessage.getData().get("body");
        sendNotification(title, body);
    }
cs



이렇게 6,7,8,9,10 번 라인을 추가해주면 된다


그런데 저기에 있는 SCREEN_DIM_WAKE_LOCK는 deprecated 되었다



아 몰랑 그냥 쓸거야!


화면 켜지게 하면 된다구!


지금 안드로이드 버전에서 권장하는 방법은 FLAG_KEEP_SCREEN_ON


이거 쓰라고 하는데


사실 당장 뭐 어떻게 쓰는지도 잘 모르기도 하고


문서들을 찾아보니 뭐 밝게했다가 어둡게도 했다가도 하고 그런 여러가지 기능들이 있는것 같긴 한데


아직 다 써보진 못했다 PARTIAL_WAKE_LOCK 이런거라든가 FLAG_KEEP_SCRREN_ON


이런거 쓰라고 하는데


FLAG_KEEP_SCRREN_ON 얘는 어찌 써야할지 레이아웃에 걸어줘야 하는 애 같아서 못썻고


PARTIAL_WAKE_LOCK 이건 화면이 안켜진다. 그래서 저 위의 코드를 사용하기로 함.


물론 소스는 더 많이 있고 써보기도 했는데 백그라운드에서 안돌아갔던 문제 때문에


되는건지 모르겠고 다시 그 소스들 찾아가면서 해보긴 귀찮다.


그건 다음에 또 이런 어플 만들때 되면 해보도록 하자


아니면 해본 사람들이 댓글을 남겨준다면 더 고마울 것이다.






[안드로이드] FCM 백그라운드에서 진동 오도록 하는 방법






얼마전 포스팅에서 웹서버를 통해  FCM 메세지를 날리는 방법에 대해서 알아보았다


2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 토큰 저장방법 개별 보내는 방법 SharedPreferences 사용

2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 푸시메세지 웹서버(JAVA)에서 보내기



그런데 문제가 있었다.


어플을 켜놓은 상태에선 진동이 오는데


어플을 끄거나 화면을 끈 상태에선 진동알람도 안오고 화면이 켜지는 것도 안되서


알람이 온줄 모르는 상태가 되버린 것



이것때문에 얼마나 삽질을 했던가..



화면켜지는건 고사하고 아얘 어플 끈 상태에선


상단에 알람바만 조용히 생기고 애초에 onMessageReceived 여기서 지정해 놓은 것들이


아얘 안돌아 가는 것 같았다


삽질을 하다가


결국 스택오버 형님들의 글에서 답을 찾았다


저번 포스팅을 보면  웹서버에서 FCM요청을 할떄



1
2
3
4
5
6
7
8
JSONObject root = new JSONObject();
                JSONObject notification = new JSONObject();
                notification.put("body""공조기 장애 현재상태 : OFF");
                notification.put("title""알림 입니다.");
                notification.put("icon""ic_message");
                root.put("notification", notification);
                root.put("to", token);
                root.put("click_action""OPEN_ACTIVITY");
cs




이런식으로 보냈었는데 6번라인의저 노티피케이션이 문제였다.


노티피케이션으로 날려주면 onMessageReceived가 실행이 안된단다


그래서 저 노티피케이션을 data로 바꾸어 주었다



1
2
3
4
5
6
7
8
                JSONObject root = new JSONObject();
                JSONObject notification = new JSONObject();
                notification.put("body""공조기 장애 현재상태 : OFF");
                notification.put("title""알림 입니다.");
                notification.put("icon""ic_message");
                root.put("data", notification);
                root.put("to", token);
                root.put("click_action""OPEN_ACTIVITY"); // click_action 추가!
cs



이렇게 바꾸고 나니 백그라운드 상태에서도 설정해놓은 vibrate대로 진동도 잘온다!!


화면켜지는것까진 바라지도 않는다 


일단 사용자한테 알람이 왔다고 알리기만 하면 되니까



그렇다면 안드로이드 에서도


받는 부분의 메세지를 다르게 받을 필요가 있었다



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
public void onMessageReceived(RemoteMessage remoteMessage) {
        //추가한것
       // sendNotification(remoteMessage.getData().get("message"));
        
        // 이렇게 데이터에 있는걸 키값으로 뽑아 쓰면 된다.
        String title = remoteMessage.getData().get("title");
        String body = remoteMessage.getData().get("body");
        sendNotification(title, body);
    }
 
    private void sendNotification(String title, String body) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 
        PendingIntent pendingIntent = PendingIntent.getActivity(this0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
 
        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(title)
                .setContentText(body)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setVibrate(new long[]{10001000})
                .setLights(Color.BLUE,1,1)
                .setContentIntent(pendingIntent);
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
 
    }
cs



이렇게 코드를 바꿔주면 된다


기존 코드에서 6,7번 라인과 11번읜 매개변수만 바꿔주면 끝!



후.. 이제 다시 화면도 켜지게 하는 방법을 찾아 떠나보도록 하자....

-------------------------------------------------------------------------------

방법 찾았음 ㅋ


2017/07/12 - [Yame Programmer/Android] - [안드로이드] FCM 화면 깨우기 화면 켜지게 하는 방법




 

[안드로이드] FCM 웹(JAVA)서버에서 푸시메세지 보내기


안드로이드의 기존 GCM에서 FCM으로 바뀌었다


구글 클라우드 메세지에서 파이어베이스 클라우드 메세지로 바뀐건진 정확히 모르겠지만..



일단 뜬금없이 웹개발하다가 갑자기 회사에서 안드로이드 개발할 일이 생겼지만


웹뷰로 때워버리자! 라고 외친 후 만들어 놓고 보니 안드로이드 알림 메세지가 가야 한단다...



하....


그래서 뭐 삽질좀 하고 여기저기 뒤적뒤적이면서 구현을 했다




일단 가장 먼저


https://console.firebase.google.com/u/0/


당연히 구글 아이디는 있을것이지 콘솔 파이어베이스로 들어가


알람메세지 구현알 어플을 등록해준다.


이곳의 도움을 많이 받았다. 기초 설정은 여기 보고 따라하자


사실 저 블로그만 봐도


어지간하면 구현 가능하다.



진짜 생각보다 좀 간단하다.



1. Android 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
import android.content.SharedPreferences;
import android.util.Log;
 
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
 
import java.io.IOException;
 
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
 
 
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
 
    private static final String TAG = "MyFirebaseIIDService";
 
    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the InstanceID token
     * is initially generated so this is where you would retrieve the token.
     */
    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // 설치할때 여기서 토큰을 자동으로 만들어 준다
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);
 
        // 생성한 토큰을 서버로 날려서 저장하기 위해서 만든거
        sendRegistrationToServer(refreshedToken);
    }
    
    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
 
        // OKHTTP를 이용해 웹서버로 토큰값을 날려준다. 
        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("Token", token)
                .build();
 
        //request
        Request request = new Request.Builder()
                .url("토큰 저장할라고 보낼 URL")
                .post(body)
                .build();
 
        try {
            client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    }
}
cs




여기서 우리가 잘 봐야 할 건


30번 라인과 


37번라인의 sendRegistrationToServer 메소드다


30번라인에서 토큰을 생성하는데 여기선 어플을 설치할때 한번 생성한다.


그럼 만들어지자마자 


37번라인 메소드로 날려서 HTTP로 전송한다.


그럼 웹서버에서 저 토큰을 받고 저장을 하게 되고


그 해당 토큰으로 메세지를 날려주면 되는 것이다.




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
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
 
import com.google.firebase.messaging.RemoteMessage;
 
 
public class MyFirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
    private static final String TAG = "FirebaseMsgService";
 
    // [START receive_message]
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
 
        //추가한것
        sendNotification(remoteMessage.getData().get("message"));
    }
 
    private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
 
        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("FCM Push Test"// 이부분은 어플 켜놓은 상태에서 알림 메세지 받으면 저 텍스트로 띄워준다.
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);
 
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
 
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }
 
}
 
cs

MyFirebaseMessagingService.java 얘는 알림메세지를 받았을때 처리하는건데

사실 딱히 건들일거 없이 그대로 사용 하면 된다.








일단 저 블로그에서


MyFirebaseInstanceIDService.java 와

MyFirebaseMessagingService.java



이 두개를 구현했다면 




여기로 들어와서 앱단위로 앱선택하고 보내면


모든 앱 설치자들에게 메세지가 날아간다.



하지만 우린 웹서버에서 푸시메세지를 날려주고 싶을 것이다.


알람이라면 뭐 값이 변한다거나 새로운 정보가 등록 되었을때 날려줘야 하니까


그때마다 저기 접속해서 날려주기엔 너무 귀찮으니까 분명히


웹서버에서 인터벌을 돌리든 트리거를 걸든 해서 웹서버에서 날려주고 싶을 것이다


그런데 웹서버에서 날려주는건


잘 안나와있고 복사 붙여넣기 해도 안되는 경우도 있고 하니까


내가 해서 성공한 코드를 보자










2. JAVA Web Server 



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
@RequestMapping(value="mobile/sendFCM")
    public String index(Model model, HttpServletRequest request, HttpSession session, MobileTokenVO vo)throws Exception{
            
            List<MobileTokenVO> tokenList = fcmService.loadFCMInfoList(vo); 
            
                String token = tokenList.get(count).getDEVICE_ID();
                
                final String apiKey = "파이어 베이스의 서버 API키를 여기에 넣는다";
                URL url = new URL("https://fcm.googleapis.com/fcm/send");
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setDoOutput(true);
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Content-Type""application/json");
                conn.setRequestProperty("Authorization""key=" + apiKey);
 
                conn.setDoOutput(true);
                
                String userId =(String) request.getSession().getAttribute("ssUserId");
 
                // 이렇게 보내면 주제를 ALL로 지정해놓은 모든 사람들한테 알림을 날려준다.
                String input = "{\"notification\" : {\"title\" : \"여기다 제목 넣기 \", \"body\" : \"여기다 내용 넣기\"}, \"to\":\"/topics/ALL\"}";
                
                // 이걸로 보내면 특정 토큰을 가지고있는 어플에만 알림을 날려준다  위에 둘중에 한개 골라서 날려주자
                String input = "{\"notification\" : {\"title\" : \" 여기다 제목넣기 \", \"body\" : \"여기다 내용 넣기\"}, \"to\":\" 여기가 받을 사람 토큰  \"}";
 
                OutputStream os = conn.getOutputStream();
                
                // 서버에서 날려서 한글 깨지는 사람은 아래처럼  UTF-8로 인코딩해서 날려주자
                os.write(input.getBytes("UTF-8"));
                os.flush();
                os.close();
 
                int responseCode = conn.getResponseCode();
                System.out.println("\nSending 'POST' request to URL : " + url);
                System.out.println("Post parameters : " + input);
                System.out.println("Response Code : " + responseCode);
                
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String inputLine;
                StringBuffer response = new StringBuffer();
 
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();
                // print result
                System.out.println(response.toString());
                
 
        return "jsonView";
    }
cs



위의 코드처럼 쓰면 된다.



8번 라인의 API키는 






저 파이어베이스 콘솔에서 빨간동그라미 누르고 프로젝트 설정의 클라우드 메세징으로 가면


서버키가 나와있다 그 서버키를 넣으면 된다. 




그런데 20번 21번 라인의  주제가 ALL인걸 어떻게 지정 하냐고?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
 
        // 웹뷰 셋팅팅
       mWebView = (WebView)findViewById(webView);
        mWebView.getSettings().setJavaScriptEnabled(true);
 
        mWebView.loadUrl(myUrl+"/mobile/login");
        mWebView.setWebChromeClient(new WebChromeClient());
        mWebView.setWebViewClient(new WebViewClientClass());
 
        mWebView.addJavascriptInterface(new AndroidBridge(), "android");
 
 
        //이렇게 ALL 추가 하면 이 디바이스는 ALL을 구독한다는 얘기가 된다.
        FirebaseMessaging.getInstance().subscribeToTopic("ALL");
 
    }
cs



안드로이드의 MainActivity.java 의 oncreate에다가 저 18번 라인을 추가 해주자


그런데 주제 등록은 즉시 안되고 몇시간 기다리거나 몇일 기다려야 등록 되는 경우도


있다고 하니까 급하게 하진 말자.




그리고 24번 라인에 들어가는 토큰은 MyFirebaseInstanceIDService.java 의 36번 메소드에 날려준 값이다


여기까지가 기초적인 FCM을 이용한 메세지 보내는 방법이다!


다음강좌는


저 토큰아이디를 어떻게 사용자 ID랑 묶어서 저장하고 원하는 사용자에게


보낼 수 있는지 알아보자



2017/07/10 - [Yame Programmer/Android] - [안드로이드] FCM 토큰 저장방법 개별 보내는 방법 SharedPreferences 사용



+ Recent posts