안녕하세요.

안드로이드 포스팅을 오래간만에 진행해보겠습니다.

 

안드로이드(JAVA) 환경에서 C혹은 C++(네이티브) 소스를 연동/연결하여 상호 호환하는 기술을 주제로 시작하겠습니다.

 

사용 환경

+ 안드로이드 스튜디오 4.1.3 (JAVA)

+ NDK 22.1.7171670

+ JDK 8_121

 

NDK & JNI

NDK는 네이티브 개발 키트 (Native Development Kit)를 의미합니다.

간단히 말해서 Android에서 C 및 C++ 코드를 사용할 수 있게 해주는 도구 모음입니다.

네이티브 소스코드를 사용함으로써 효과는 속도, 연산, 호환성 등의 SDK 보다 빠른 작업 속도를 확인할 수 있습니다.

 

JNI는 자바 네이티브 인터페이스 (Java Native Interface)를 의미합니다.

간단히 말해서 JAVA(JVM)과 C 및 C++를 연결시켜주는 인터페이스를 말합니다.

사용하고자 하는 목표에 대해 이야기하자면 자바 메서드 호출로 C 및 C++로 작성된 코드 및 함수를 실행할 수 있습니다.

 

Hello, World 예제를 시작하기 전..

상세하고 쉽게 알려드리기 위해 스크린샷과 설명을 최대한 잘하려고 노력하는 편입니다.

먼저 자료를 정리한 후에 포스팅하는 편인데 스크린샷이 상당히 많이 나와 포스팅하기 앞서 걱정이 드네요.

 

처음에는 NDK, JNI 관련 프로젝트를 진행하게 될 것 같아 여럿 찾아보다가, 자료가 너무 중구난방이라 정리하게 되었습니다.

 

1. 프로젝트 생성

 

프로젝트는 '안드로이드 스튜디오'를 이용하여 SDK는 '마쉬멜로우 (안드로이드 6.0)' 언어는 '자바'로 선택하였습니다.

그 이외에 Acitivity는 'Empty'로 보통 일반적인 앱을 작성하는 환경으로 시작하였습니다.

 

2. NDK 설정

 

NDK의 시작과 끝이라고도 할 수 있는 NDK설정을 시작해보도록 하겠습니다.

 

Tools -> SDK Manager

먼저 생성된 프로젝트에서 Tools -> SDK Manager로 들어가 주세요.

 

NDK가 설치되었다면 상관이 없지만, 설치가 되지 않으셨다면 '체크' 후 Apply -> OK 하고 설치를 완료해주세요.

 

NDK 설치과정

 

위의 설치 과정을 모두 마치셨다면, Gradle Scripts 하위의 'local.properties'에 ndk.dir를 추가해주세요.

일반적으로 설치하셨다면 C -> Users -> [사용자] -> AppData -> Local -> Android -> Sdk -> ndk -> [리비전]

해당 경로에 위치해있습니다.

 

사진이 작아서 잘 안보이 실수 있지만, build.gradle에 들어가셔서 android 하위에 'ndkVersion "22.1.7171670"'를 추가해주세요.

NDK VERSION은 사용자마다 다르실 수 있으니 참고 바랍니다.

 

File -> Project Structure

그리고, File -> Project Structure에 들어갑니다.

 

해당 경로가 잡혀있다면 프로젝트의 NDK설정이 끝이 났습니다.

해당 경로가 잡혀있지 않다면, 아까 말씀드린 일반적인 NDK설치경로를 찾아서 지정해주시면 됩니다.

(C -> Users -> [사용자] -> AppData -> Local -> Android -> Sdk -> ndk -> [리비전])

 

이렇게 NDK 설정은 마무리됩니다.

 

3. 안드로이드 앱 환경 설정

 

JNI로 CPP소스코드를 통해 'Hello_ndk'를 출력시켜보도록 하기 위해, 레이아웃을 설정하였습니다.

 

activity_main.xml

activity_main.xml에 code환경으로 진입해주세요.

 

기존 환경에 존재하는 TextView에 ID값만 부여해주었습니다.

android:id="@+id/text"

 

그리고 기본 생성된 MainActivity에 TextView값을 선언 및 사용 설정하였습니다.

 

1
2
text = (TextView) findViewById(R.id.text);
text.setText("텍스트  설정);
cs

 

4. NDK 메서드 설정

 

이제 기본적인 환경설정은 모두 끝이 났습니다.

이제 본격적으로 NDK 관련된 설정을 진행해 보도록 하겠습니다.

 

기본적으로 NDK는 자바 소스를 기반으로 자바에서 C를 읽을 수 있게 도와주는 헤더 파일을 생성합니다.

헤더 파일을 생성하려면 내가 어떠한 메서드를 사용할 것인지를 알아야 하고, 미리 작성을 해두어야 합니다.

 

저는 간단하게, CPP에 String 값을 넘겨 TextView를 찍어보는 소스코드를 작성해 보았습니다.

기본적으로 자바가 CPP 연동할 JNI헤더 파일을 만들 때 public native 함수명을 파악하고 생성을 합니다.

위 스크린샷과 아래 스크립트 코드를 참고해보시면 알 수 있습니다.

 

1
2
3
4
5
6
static {
        System.loadLibrary("helloNdk");
    }
public native String print_ndk(String text);
 
String print = print_ndk("hello_ndk");
cs

 

System.loadLivrary libName은 직접 자바에 연결할 CPP의 라이브러리 이름을 정하게 되어있습니다.

임의로 작성하셔도 상관없습니다.

 

5. JNI 헤더 생성 툴 설정

 

이제 자바와 C 및 C++를 연결해주는 헤더 파일을 생성해보겠습니다.

기본적으로 JDK를 설치하게 되면 가지고 있습니다.

javah.exe -> 해당 파일이 헤더 파일을 생성해주는 것을 도와줍니다.

 

jni 폴더 생성

먼저, 패키지 단위를 Projcet로 변경하여, main 및에 jni라는 폴더를 생성해줍니다.

 

File -> Settings

jni 폴더 생성이 끝이 났다면 File -> Settings에 들어갑니다.

 

Tools -> External Tools에 들어가셔서 '+' 버튼을 눌러서 헤더를 생성할 수 있는 외부 툴을 만들어 보겠습니다.

 

Name : javah

Program : JDK경로 하위의 bin폴더 및 javah.exe를 찾아 설정해줍니다.

Arguments : -classpath "$Classpath$" -v -jni $FileClass$

Working directory : 앱의 방금 만든 jni폴더를 지정해줍니다.

 

(직접 해당 툴을 사용할 때 말씀을 드리겠지만, 결과적으로 해당 javah 외부 툴을 생성 후 호출하게 되면 클래스 경로를 파악하여 native 메서드를 기반한 헤더 파일을 jni폴더에 생성하게 됩니다.)

 

생성이 완료되었다면, Apply -> OK 처리해주세요.

JNI연결 헤더 파일을 완성할 툴 설정을 완료하였습니다.

 

6. JNI 헤더 생성 하기

 

이제 생성한 툴을 이용하여 C/C++ 헤더 파일을 생성해보겠습니다.

MainActivity에 오른쪽 마우스 External Tools -> javah

JNI폴더에 헤더 파일이 생성이 완료됩니다.

 

[에러] 팁

간혹 한 번에 헤더 파일 생성에 안되시는 분이 있을 겁니다.

보통 위와 같은 에러를 출력합니다.

 

그렇다면, 당황하지 마시고 프로젝트 리빌드 후에 다시 시도하시면 정상적으로 생성됩니다.

 

정상적인 로그 출력과 생성된 모습을 확인할 수 있습니다.

 

7. C 및 C++ 소스 코드 작성

 

먼저 C/C++ 소스코드를 작성하기 앞서서, 헤더 파일을 잠깐 열어서 확인해보겠습니다.

파일 하단에 MainActivity.java파일에 작성된 native코드 기반으로 메서드가 생성된 것을 확인할 수 있습니다.

(해당 문법은 JNI문법입니다.)

 

이제 헤더에 생성된 메서드를 기반한 코드를 완성시켜줘야 합니다.

(Method Overriding 느낌의..)

 

먼저 jni폴더에서 New -> C/C++ Source File을 눌러 파일명은 'hello_ndk'로 생성하였습니다.

 

 

1
2
3
4
5
6
#include<com_example_hello_ndk_MainActivity.h>
 
JNIEXPORT jstring JNICALL Java_com_example_hello_1ndk_MainActivity_print_1ndk
  (JNIEnv *env, jobject thiz, jstring text) {
    return text;
}
cs

 

소스코드를 헤더 파일에 기반하여 작성하였습니다.

먼저 javah툴로 생성한 헤더 파일을 include 해주었고, 헤더 하단의 코드를 기반하여 작성하였습니다.

 

저는 바로 jstring text를 변수를 지정하여 리턴 처리하였습니다.

 

여기서 간단히 JNIEnv, jobject에 관하여 간단히 말씀을 드리겠습니다.

 

JNIEnv*와 jobject는 JNI로부터 받은 변수이므로 함수에 꼭 포함시켜서 사용하여야 합니다.

env는 JNI에 가장 중요한 구조체 포인터로 VM에 대한 인터페이스를 포함합니다.

jobject는 클래스의 정보들이 들어가 있습니다. 예를 들어 현재 소스로 판단한다면 print_ndk라는 함수를 포함하는 클래스를 참조하고 있습니다.

 

그 외 jstring은 제가 MainActivity.java를 보셔서 아시겠지만 매개변수로 지정한 값입니다.

 

이제 모든 준비는 끝이 났습니다.

마무리로 빌드 과정과 구동으로 마무리하겠습니다.

 

8. NDK빌드 툴 생성 및 Android Native Gradle 연결 후 실행하기

 

먼저, 최종 작성한 네이티브 소스를 빌드를 빌드하여야 합니다.

이 과정을 앱 빌드할 때 같이 자동 빌드 하기 위한 설정 방법을 가이드해보겠습니다.

 

위 사진과 같이 5번 목차에서 헤더 파일 생성 툴을 만들었던 메뉴인 File -> Settings -> External Tools에 들어갑니다.

그리고 똑같이 '+' 버튼을 눌러서 빌드 툴을 생성합니다.

 

이번에는 헤더 생성 툴에선 JDK를 사용했던 것과 달리 NDK를 사용합니다.

(NDK빌드니깐요.)

 

Name: 저는 ndk-build로 지정하였습니다.

Program: NDK경로 -> ndk-build.cmd를 지정해주세요.

Working directory: app소스 main으로 지정해주시면 됩니다.

 

그리고 OK를 눌러주세요.

 

이제 ndk-build를 그대로 복사해서 clean도 만들어줍니다.

 

clean은 ndk-build와 설정값은 동일하지만,

Arguments: clean 입력해주세요.

ndk-build는 네이티브 파일을 빌드하는 역할을 한다면, clean은 project clean과 비슷한 개념으로 빌드된 파일을 정리한다고 생각하시면 됩니다.

 

이렇게 외부 툴 2가지 생성을 마치셨다면, 거의 마지막 단계인 앱 빌드 Gradle과 연동을 시켜줄 준비를 하겠습니다.

 

 

먼저 연동을 위해서 Android.mk라는 파일과 해당 파일의 설정값이 필요합니다.

jni폴더 내부에 생성하겠습니다.

 

New -> File -> Android.mk

 

Android.mk 내부 파일에 위 사진과 같이 작성해주세요.

 

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := helloNdk
FILES := hello_ndk.cpp
LOCAL_SRC_FILES := $(FILES)
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)

 

여기서 빨간색으로 표시한 부분만 본인이 설정한 값과 맞게 설정하면 됩니다.

*LOCAL_MODULE은 4번 목차에 libName으로 지정한 이름을 지정하셔야 합니다.

그리고 FILES는 연동할 C/C++파일명을 입력해주세요.

 

Android.mk는 jni하위 디렉터리에 존재해야 하고, 빌드 시스템의 소스 및 공유 라이브러리를 설명합니다.

실제로 빌드할 때 한번 이상 파싱 하는 작은 GNU makefile 플래그먼트입니다.

 

더 상세한 설명 및 설정을 하실분은 아래 링크를 확인해주세요.

*developers NDK Android.mk*

 

 

Android.mk까지 생성에 마쳤다면, Gradle과 연결해줍니다.

MainActivity 우클릭 후 'Link C++ Project with Gradle'을 선택해줍니다.

 

해당 설정값이 나오게 되고,

Build System은 기존 만들었던 ndk-build 툴을 설정하시고

Project path는 Android.mk를 지정해주세요.

 

그리고, OK를 눌러주세요.

 

 

OK를 누르면 Gradle에 해당 코드가 작성이 됩니다.

그리고, 실행해줍니다.

 

저는 가상 모듈로 실행하였습니다.

 

빌드 과정 중 NativeBuild도 진행된 것을 확인할 수 있었습니다.

 

MainActivity에서 리턴했던 'hello_ndk'를 볼 수 있었습니다.

 

추가적으로, 자동화 빌드 말고 수동 빌드를 하게 되는 경우에 대해 말씀드리겠습니다.

 

수동으로 External Tools -> ndk-build를 하게 된다면, 해당 네이티브 빌드만 진행이 됩니다.

 

그리고, Working Directory로 지정했던 경로에. so파일이 생성된 것을 볼 수 있습니다.

또한, SharedLibrary에도 함께 올라간 것을 확인할 수 있습니다.

 

이상으로, 안드로이드 NDK&JNI C/C++ 사용하기를 마치겠습니다.

 

사진 무단 도용은 금지합니다!

도움이 되셨다면 아래 '공감', '하트' 버튼을 눌러주세요!

감사합니다.


반응형


안녕하세요.


오늘은 하이브리드 앱으로 많이 사용하고있는 웹뷰를 제작해보도록 하겠습니다.


웹뷰란? 간단하게 설명을 드리겠습니다.

어플리케이션 화면상에 내가 만든 웹페이지 혹은 내가 띄우고싶은 웹페이지를 어플리케이션 안에서 보여주는 프레임을 말합니다.


보통은 웹페이지로 앱상 UI나 기능을 구현을 해놓은 뒤, IOS나 안드로이드 모두 웹뷰를통해 띄우면 별도의 앱작업이 필요없이 어플리케이션을 완성시킬수 있습니다.


오늘은 간단하게 안드로이드로 웹뷰를 생성하는 방법을 포스팅 해보도록 하겠습니다.



안드로이드 프로젝트 생성하기 




안드로이드 프로젝트 생성은 많이 해보셨을꺼라 생각하고 간단하게 진행 하겠습니다.

먼저 도메인과 경로 앱이름등 설정해주시고 N눌러주세요.



저는 API23 마시멜로우로 생성하겠습니다.

설정하신뒤 'Next' 눌러주세요.



빈 액티비티로 생성을 하겠습니다.

선택후 'Next'를 눌러주세요.





액티비티 이름이나 레이아웃 이름을 정해주실분은 정해주세요.

저는 기본(Default)로 진행 하겠습니다.

마지막으로 'Finish'눌러주시면 프로젝트가 생성이 완료 됩니다.



간단하게 웹뷰 띄우기!



1. 매니페스트 설정


매니페스트는 간단하기 퍼미션허용 한줄만 추가해주면 됩니다.

인터넷관련 퍼미션을 열어줘야 웹뷰상 인터넷 동작이 가능합니다.


1
<uses-permission android:name="android.permission.INTERNET"/>
cs



2. 레이아웃 설정


레이아웃 설정도 기본 XML에 <WebView> 태그만 추가하여주었습니다.

크기는 "match_parent" 설정해주었습니다.


1
2
3
4
5
6
7
<WebView
    android:id="@+id/webView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentTop="true"
    android:layout_alignParentStart="true" >
</WebView>
cs



3. Main 코드 설정


기본적인 웹뷰 선언과, 웹뷰 셋팅 선언 하였습니다.

여기서 웹뷰 셋팅은 굉장히 많은데요.

웹페이지상 자바스크립트와 기타 기능들을 모두 동작하게 하려면 허용해줘야하는 설정이 많습니다.

(위 사진상 주석을 보고 설정값을 확인하시면될것 같습니다.)


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
package webview.test.myapplication;
 
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
 
public class MainActivity extends AppCompatActivity {
    private WebView mWebView; // 웹뷰 선언
    private WebSettings mWebSettings; //웹뷰세팅
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // 웹뷰 시작
        mWebView = (WebView) findViewById(R.id.webView);
 
        mWebView.setWebViewClient(new WebViewClient()); // 클릭시 새창 안뜨게
        mWebSettings = mWebView.getSettings(); //세부 세팅 등록
        mWebSettings.setJavaScriptEnabled(true); // 웹페이지 자바스클비트 허용 여부
        mWebSettings.setSupportMultipleWindows(false); // 새창 띄우기 허용 여부
        mWebSettings.setJavaScriptCanOpenWindowsAutomatically(false); // 자바스크립트 새창 띄우기(멀티뷰) 허용 여부
        mWebSettings.setLoadWithOverviewMode(true); // 메타태그 허용 여부
        mWebSettings.setUseWideViewPort(true); // 화면 사이즈 맞추기 허용 여부
        mWebSettings.setSupportZoom(false); // 화면 줌 허용 여부
        mWebSettings.setBuiltInZoomControls(false); // 화면 확대 축소 허용 여부
        mWebSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); // 컨텐츠 사이즈 맞추기
        mWebSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); // 브라우저 캐시 허용 여부
        mWebSettings.setDomStorageEnabled(true); // 로컬저장소 허용 여부
 
        mWebView.loadUrl("http://web-inf.tistory.com"); // 웹뷰에 표시할 웹사이트 주소, 웹뷰 시작
    }
}
 
cs



에뮬레이터로 간단히 실행을 해본결과 제 블로그가 정상적으로 로드되었고, 정상 작동하는것을 확인 할 수 있었습니다.


이상 간단한 웹뷰 생성 포스팅을 마치겠습니다.



반응형


오랜만에 포스팅 입니다.

요즘 바쁜관계로 항상 포스팅해야지 하고선 키워드만 메모해놓고 포스팅을 못하고 있네요.


오늘은 구글 클라우드 메시징 서비스인 FCM 사용방법을 포스팅 하겠습니다.


클라우드 메시징 FCM 푸시는 서버 혹은 특정 요청발생시에 자신의 안드로이드 어플리케이션에서 수신을 받아 메시지를 받는 것을 말합니다.

(IOS에서도 사용가능합니다.)


프로젝트 생성 부터 푸시를 받는 예제까지 작업해보도록 하겠습니다.


1. 프로젝트 생성 및 기본 설정


먼저 자신의 구글 계정을 통하여 파이어베이스 콘솔사이트에 접속을 합니다.


파이어베이스 콘솔

https://console.firebase.google.com/u/0/?hl=ko&pli=1


그리고 다음 사진의 설명과 같이 진행하시면됩니다 



먼저 파이어베이스 콘솔사이트에 접속하여 프로젝트를 생성합니다.

프로젝트 추가를 누릅니다.



저는 테스트용도로 FCM TEST라고 프로젝트명을 지정하였습니다.

프로젝트 이름을 작성하고 약관에 동의후 프로젝트 만들기 하시면 됩니다.



생성된 프로젝트에 들어와서 Project Overview 항목에 '톱니바퀴' 모양을 눌러줍니다.



톱니바퀴를 누른뒤 '프로젝트 설정'에 들어가보시면 나의 프로젝트의 ID와 API키등을 확인할수 있습니다.



프로젝트 설정 하단에 오늘의 주제인 안드로이드 FCM구현을 위해 Android 앱에 Firebase 추가를 선택해줍니다.



안드로이드 추가를 선택하시면 Android 패키지 이름을 요구합니다.

해당 패키지이름은 안드로이드 프로젝트 패키지명을 의미합니다.



안드로이드로 넘어와서 프로젝트를 생성합니다.

프로젝트 이름 패키지명을 지정/생성후 하단 보이는 Package name 을 복사/붙여넣기 하시면됩니다.

(저는 테스트 용도로 'fcm'으로 생성하였습니다.)



다시 파이어베이스 콘솔로 돌아와서 안드로이드 스튜디오에서 생성한 패키지명을 입력해줍니다.

나머지 앱닉네임, 디버그 서명 인증서는 선택사항임으로 생략하겠습니다.



앱등록을 진행후에 'google-services.json' 파일을 제공합니다.

해당 파일은 나의 안드로이드 프로젝트와 파이어베이스를 동기화시키는 연결고리 역할을 합니다.

구글에서 인증 프로토콜로 구글에서 개발하여 하여 기존 RPC프로토콜과 다른 GRPC라고 명칭 합니다.



해당 프로젝트에 App폴더 및에 파일을 복사 해주시면 됩니다.



그리고 프로젝트에 build.gadle의 플러그인을 추가해줍니다.

(자세한 사항은 아래사진에 있습니다.)



먼저 App build.gradle 입니다.

가이드에는 최신버전 16.0.1을 권장하고 있지만, 저는 12.0.0 으로 진행하였습니다.

(보안적으로 업데이트를 하였지만, 안드로이드 스튜디오든 구글 플러그인은 항상 업데이트이후 말썽이 많아 기존 잘 유지되던 버전으로 사용하겠습니다.)


dependencies안에는  implementation 'com.google.firebase:firebase-messaging:12.0.0'


dependencies 밖에는 apply plugin: 'com.google.gms.google-services'


사진을 잘 참고해주시고 붙여넣어주세요!



Project build.gradle 입니다.

구글에서 권장하는 최신버전으로 붙여넣으셔도 문제없습니다.


dependencies안에  classpath 'com.google.gms:google-services:4.0.1' 를 붙여넣어주세요.



이로써 프로젝트 생성과 안드로이드 프로젝트 설정이 끝났습니다.



2.  안드로이드 프로젝트 소스코드 작성



Manifest 퍼미션 설정

FCM은 인터넷 환경에서 작동되는 서비스 입니다.

즉, 어플리케이션의 인터넷 퍼미션을 열어줘야합니다.


매니페스트 상단에 퍼미션 설정을 해주시면 됩니다.


 <uses-permission android:name="android.permission.INTERNET"></uses-permission>



Manifest 서비스 설정

FCM을 사용하기위해 어플을 설치한 기기장치의 디바이스 토큰값을 얻어오는 서비스와 푸시 메시지를 받았을때 동작하는 서비스를 등록해 주어야 합니다.


<application> 태그 안쪽에 붙여넣거나 작성해주시면됩니다.


<service

      android:name=".MyFirebaseMessagingService">

      <intent-filter>

           <action android:name="com.google.firebase.MESSAGING_EVENT"/>

      </intent-filter>

 </service>

 <service

      android:name=".MyFirebaseInstanceIDService">

      <intent-filter>

           <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>

       </intent-filter>

 </service>



메인 소스코드 작성

2가지의 자바 클래스파일을 자바 메인에 생성합니다.

(생성 위치는 다들 아실것이라 생각하지만 혹시나 모르시는분은 아래 사진을참고해주세요.)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
    @Override
    public void onTokenRefresh() {
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d("IDService""Refreshed token: " + refreshedToken);
 
        sendRegistrationToServer(refreshedToken);
    }
 
    private void sendRegistrationToServer(String token) {
 
    }
}
 
cs


MyFirebaseInstanceIDService

해당 클래스 파일은 어플리케이션 실행시 디바이스토큰이 생성 및 재생성 될시에 동작을 작성합니다.


sendRegistrationToServer는 어플리케이션을 실행후, 해당 어플리케이션을 실행한 Device 토큰을 서버로 전송하는 코드를 작성하시면 됩니다.

(앱으로 푸시를 보내기 위해서는 Device토큰이 필수값 입니다.)


오늘은 설정을 마친뒤 발송테스트를 파이어베이스 콘솔에서 진행할것 입니다.

혹시나 별도의 웹서버나 요청을할 서버가 있다면 코드를 작성하시면 될것입니다.


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
public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private static final String TAG = "MyFirebaseMsgService";
 
    /**
     * Called when message is received.
     *
     * @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
     */
    // [START receive_message]
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
 
        // TODO(developer): Handle FCM messages here.
        // Not getting messages here? See why this may be: https://goo.gl/39bRNJ
        Log.d(TAG, "From: " + remoteMessage.getFrom());
 
        // Check if message contains a data payload.
        if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());
 
            if (/* Check if data needs to be processed by long running job */ true) {
                // For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
            } else {
                // Handle message within 10 seconds
                handleNow();
            }
 
        }
 
        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
            sendNotification(remoteMessage.getNotification().getBody());
        }
 
        // Also if you intend on generating your own notifications as a result of a received FCM
        // message, here is where that should be initiated. See sendNotification method below.
    }
    // [END receive_message]
 
    /**
     * Handle time allotted to BroadcastReceivers.
     */
    private void handleNow() {
        Log.d(TAG, "Short lived task is done.");
    }
 
    /**
     * Create and show a simple notification containing the received FCM message.
     *
     * @param messageBody FCM message body received.
     */
    private void sendNotification(String messageBody) {
 
        Intent intent = new Intent(this, MainActivity.class);
 
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 
        PendingIntent pendingIntent = PendingIntent.getActivity(this0, intent, PendingIntent.FLAG_ONE_SHOT);
 
        String channelId = getString(R.string.default_notification_channel_id);
        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
 
        NotificationCompat.Builder notificationBuilder =
                new NotificationCompat.Builder(this, channelId)
                        .setSmallIcon(R.mipmap.ic_launcher)
                        .setContentTitle("FCM Message")
                        .setContentText(messageBody)
                        .setAutoCancel(true)
                        .setSound(defaultSoundUri)
                        .setContentIntent(pendingIntent);
 
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String channelName = getString(R.string.default_notification_channel_name);
            NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
            notificationManager.createNotificationChannel(channel);
        }
        notificationManager.notify(0, notificationBuilder.build());
    }
}
cs


MyFirebaseMessagingService

해당 클래스파일은 메시지를 수신하여 알림으로 보여주는 클래스 입니다.


어플리케이션이 실행되면서 해당 클래스가 서비스로 돌고 있다가 메시지가 수신이된다면 Notification으로 알림을 해주는 코드 입니다.

만약 알림을 수신하지않고 별도의 작업을 하고싶게 작성하고싶으면 onMessageReceived 메소드를 수정하시면 될것 같습니다.



strings.xml 설정

간혹 혹시나, MyFirebaseMessagingService 소스코드를 작성하였을때 Strings.xml에서 없는 String값이라고 에러가 나올수도있습니다.

해당 오류에 맞는 태그 스트링 값입니다.

(에러가 안발생하시는분은 선택사항입니다.)


<string name="default_notification_channel_id">Channel ID</string>

 <string name="default_notification_channel_name" translatable="true">Test</string>


이제 모든 설정이 끝이 났습니다.

작성한 코드가 정상적으로 동작 실행하는지 확인해보겠습니다.


3. 동작 확인



다시 콘솔로 돌아옵니다.

그후 성장 메뉴에 Cloud Messaging메뉴로 들어갑니다.



'Send your first message' 혹은 기존에 메시지를 보내보셨던분은 '알림 생성'으로 메시지 작성을 시작합니다.



어플리케이션에게 발송한 푸시 메시지 제목, 메시지 내용을 작성하였습니다.

(임의로 Test, Fcm Test 라고 작성 테스트 하였습니다.)




푸시 메시지를 받을 타겟을 생성한 앱을 선택해줍니다.

이렇게 된다면 해당 어플리케이션이 설치된 모든 디바이스에게 푸시를 전달합니다.



예약항목에서는 메시지를 언제 발송할것인지 스케쥴링 합니다.

(저는 테스트 목적으로 'Now' 바로 보내기를 설정후 발송하겠습니다.)



나머지 전환 이벤트 및 추가항목은 선택사항임으로 생략하겠습니다.

그리고 게시를 누르고 '발송'을 합니다.


4. 결과 



안드로이드 에뮬레이터로 실행하였습니다.

어플리케이션이 잘 실행되어 메시징 서비스로 메시지를 잘전달받은것을 확인 할 수 있습니다.


이로써 FCM 푸시 서비스 구현을 마치겠습니다.


*추가 푸시메시지 발송 후 확인이 안될시*

모두 정상적으로 작성하였는데도 푸시메시지가 확인이 되지않는다면

매니페스트의 'Messaging서비스'에 'enabled'와 'exported'를 'true' 설정후 다시 실행해보세요.



감사합니다.


반응형

'IT > Android' 카테고리의 다른 글

Android NDK&JNI(C/C++) 사용하기 (JNI-Hello, World)  (8) 2021.03.26
WebView 안드로이드 웹뷰 생성하기  (5) 2019.02.19

+ Recent posts