[안드로이드] 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 사용



안드로이드


android 2d Game 기초



android setting



안드로이드 플랫폼 구성.


flatform - linux


안드로이드에서 사용하는 자바는 구글이 배포하고 제공하는 실행환경임.

구글에서 배포하는 라이브러리들은 자바가 아니라 안드로이드 플랫폼임.


단 그 플랫폼을 이용하기 위한 언어가 자바와 같은 뿐이다.


자바버츄얼 머신이 아니라 달빅 버츄얼 머신을 사용.

OpenGL, SQLite 등 라이브러리를 제공하는데 C로 만들어져 있으나

그것을 자바로 사용 할수 있도록 자바라이브러리로 제공


안드로이드 플랫폼 구조






프로젝트 기본구조 익히기.




시작함수는 잊자.


절차적 프로그램의 기본함수인 Main()이 없다.


단 메인을 대신하는 설정파일이 있다.(MainAtivity, MainFrame)


안드로이드는 도스에서 개발 못함.


그래들 - 개발할땐 필요없음 지워도 됨, 하지만 나중에 어차피 추가 해야함


안드로이드 프로그램을 위한 필수 요소


manifest - 어플리케이션에 대한 전반적인 정보를 담고있는 파일. 프로필.


메인 -> 자바  -> 클래스생성(메인엑티비티) -> 엑티비티 이즈상속


여러개의 액티비티 중 가장 먼저 실행되어야 할 놈을 <intent-filter>로 지정


   <action android:name="android.intent.action.MAIN"/> 메니페스트에서 제일 먼저 떠야할 엑티비티 라고 말해주는 거.






폰 설정

환경설정 -> 애플리케이션 관리자 -> usb디버깅 체크



뷰 그룹.


액티비티엔 하나의 뷰만 가질수 있다


하지만 뷰 그룹을 사용하면 여러개를 사용할수 있다?

ViewGroup - 추상클래스

 - 어떻게 배치할 것인가


Linear - 일렬 옆으로 쭉

Relative - 상대적인 기준 정하고…. 설정

Frame - 여러개가 있지만 일렬(맨 마지막것만 보이게)(카드 덱 처럼)

Grid- 격자형

Absolute- 절대 위치좌표 집어주고  설정




리소스를 활용한 배치.


리소스를 이용한 방식???

XML로 코드를 대신 작성하라고?


dpi :: 1인치당 160개의 픽셀 - 1 기준


픽셀단위로 크기를 정하면 폰마다 다르게 나옴


DP로 해야댐




안드로이드 어플리케이션의 구성 요소는 다음과 같다.

* 액티비티(Activity)

* 서비스(Service)

* 브로드캐스트 리시버(Broadcast Receiver)

* 콘텐트 프로바이더(Content Provider)



app_hier.png

1. 액티비티(Activity)

- 어플리케이션의 한 '화면'을 의미한다.

- 휴대용 단말기의 성능은 PC에 비하면 메모리가 턱없이 부족하다. 때문에 액티비티는 액티비티의 상태(활성/비활성)와 액티비티 생애주기(Activity Lifecycle)에 따라 생성되거나 소멸된다.

- 화면에 표시되어 있는 상태가 아니라면 비활성 상태(Inactive)가 되어 액티비티 내에서 처리되는 작업 또한 중단된다.



2. 서비스(Service)

- 백그라운드에서 실행되는 컴포넌트.

- 예를 들면 음악 재생 어플리케이션.

- 서비스는 UI가 없기때문에 자신의 동작 여부를 알림 메세지 혹은 토스트를 통해 사용자에게 알린다.



3. 브로드캐스트 리시버(Broadcast Receiver)

- 인텐트(Intent) 형태의 방송 메시지(Broadcast Message)를 수신하는 역할을 한다.

- 주로 시스템의 상태(배터리 상태, 통신 상태, SD카드 삽입 등)를 알리기 위해 사용하지만, 어플리케이션에서 특정 작업이 완료되었을 때 처리할 동작을 구현할 때도 사용한다.

- 서비스와 마찬가지로 UI를 가지고 있지 않기 때문에 사용자에게 작업의 진행정도나 상태 등을 알리기 위해 알림 메시지나 토스트를 사용한다.



4. 콘텐트 프로바이더(Content Provider)

- 한 어플리케이션 내의 데이터를 다른 어플리케이션에서도 사용할 수 있게 해준다.(SD카드가 아닌 내부)

- 공유하려는 데이터가 있는 어플리케이션에 데이터를 공유할 수 있는 '통로'의 역할을 한다.

- 콘텐트 프로바이더를 통해 외부에서 접근할 수 있는 데이터의 범위, 방법 등을 지정하여 어플리케이션내의 데이터를 안전하고 공유할 수 있다.

- 콘텐트 프로바이더에 접근하려면 콘텐트 리졸버(Content Resolver)가 필요하다.



5. 인텐트(Intent)

- 액티비티, 서비스 호출 및 브로드캐스트 리시버에 메시지를 전달할 떄 사용.

- 내부에 어떤 형식의 정보가 담겨 있느냐에 따라 명시적 인텐트(Explicit Intent)와 암시적 인텐트(Implicit Intent)로 나뉜다.


- 명시적 인텐트 : 호출하거나 메시지를 보낼 컴포넌트가 명확하게 지정되어 있다. ex) 철수

- 암시적 인텐트 : 대상 컴포넌트가 명확하게 지정되어 있지 않고, 대상의 속성만 지정되어 있다. ex) 학생

이러한 암시적 인텐트를 처리하려면, 인텐트 필터(Intent Filter)를 사용하여 해당 컴포넌트의 속성을 안드로이드 시스템에 등록해야 한다.



6. 알림 메시지(Notification)

- 알림 바(Notification bar)나 알림 패널(Notification Panel), 소리, 진동, LED 점멸 등을 통해 사용자에게 특정 이벤트를 알릴 때 사용.

- 서비스, 브로드캐스트 리시버가 사용.



7. 토스트(Toast)

- 특정 이벤트를 사용자에게 알릴 때 사용하며, 주로 간단한 메시지를 표시한다.



클릭 이벤트 처리하기

- 레이아웃 구성과 Toasts활용하기

핸드폰과 PC의 연동 도중 lg android mtp device driver가 설치되지 않아 연결되지 않는 경우가 있다


http://local.sec.samsung.com/comLocal/support/down/kies_main.do?kind=usb


위 링크로 가서 USB 통합 드라이버를 설치 하자


삼성에서 다운로드 받지만 통합 드라이버일뿐 LG의 핸드폰도 적용이 되기 때문이다.



+ Recent posts