안드로이드

강의는 구 버전인 GCM 이나 

블로그는 FCM 으로 작성 하였다.

 

소켓으로 연결방식으로 사용 하는 것이 아니라 구글에서 연결 단말을 이용하는 방식이다.

 

단말을 등록된 사람만 메시가 전송된다.

 

 

 

[안드로이드(22)] - GCM보다 더 간편하게 FCM으로 푸시알림 구현하기 Part1

 

 

[안드로이드 - FCM(Firebase Cloud Messaging)으로 푸시서비스 구현]

 

 

 

안드로이드 스튜디오를 열어서 일단 기본설정으로 프로젝트를 하나 만들자. 여기서 알아 둬야 할것은 패키지 이름이다. 이 패키지 이름을 FCM에서 앱추가하면서 등록해 줘야 하기 때문이다. 다시 firebase 콘솔 페이지에 들어가자.

Firebase consol에서 새로운 프로젝트 만들기

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

 

생성된 나의 프로젝트

https://console.firebase.google.com/project/juhofcm/overview

 

 

firebase.설정

https://firebase.google.com/docs/cloud-messaging/android/client?hl=ko

 

 

 

AndroidMainfest.xml

https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/AndroidManifest.xml#L32-L37

 

 

잡서비스 추가

https://github.com/firebase/firebase-jobdispatcher-android

 

 

 

FCM을 이용해 안드로이드 앱으로 메시지 전송 (1)

 

 

[Android] 안드로이드 FCM(FireBase Cloud Messaging) 푸시알림 구현하기 (2)

출처: http://codersdict.com/20 [코딕트]

 

  

 

 

 

class MainActivity

package kr.co.braverokmc.fcmpushexample;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.messaging.FirebaseMessaging;

public class MainActivity extends AppCompatActivity {

  /*  TextView textView;
    String getMessage;*/

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

     /*   textView =(TextView)findViewById(R.id.text1);*/


        //추가한 라인
        FirebaseMessaging.getInstance().subscribeToTopic("news");
        String message=FirebaseInstanceId.getInstance().getToken();


      /*
       아래 코드 실행 안됨
       Intent intent=getIntent();

        if(intent!=null){

            getMessage=intent.getStringExtra("message");

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    textView.setText(getMessage);
                }
            });

        }*/

        //FirebaseMessaging.getInstance().

      /*  앱을 어떻게 만들지에 따라 얼마든지 다르게 구현 하면 된다. 이 예제에서는 단순히 news라는
        토픽에 등록하는 과정을 구현했을 뿐이다. 버튼을 만들어서 버튼을 클릭했을때 수행되게 할 수도 있다.
        이 예제는 앱이 실행되면 자동으로 news라는 토픽을 구독한다는 의미다.

                FirebaseMessaging.getInstance().subscribeToTopic("news");
        FirebaseInstanceId.getInstance().getToken();
        토픽(주제)에 등록되면 나중에 관리자가 메세지를 보낼때 주제별로 선택해서 보낼
        수 있게 해주는 것이다.기존 토픽에 추가로 등록하거나 없으면 새로운 토픽을 생성할 수도 있다.
        위 샘플은 news라는 토픽에 구독등록을 한다는 의미이다. 자신이 원하는 토픽을 만들어 주면 된다.
        한가지 유의해야 할것은 토픽이 즉시 적용되지 않는다. 생성되는데 몇시간 길게는 하루가 걸리기도 한다고 한다.
                추가) 혹시 토픽을 추가하면 에러가 발생하면 gradle에서 firebase-messaging을 가장 최신 버전으로
        수정해 준다. 최근 다시 해보니 에러가 발생해서 최신버전으로 변경하니 정상적으로 동작했음!*/

    }
}

 

 

class MyFirebaseMessagingService

package kr.co.braverokmc.fcmpushexample;

/**
 * Created by choi on 2017-04-19.
 */

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 android.util.Log;

import com.firebase.jobdispatcher.FirebaseJobDispatcher;
import com.firebase.jobdispatcher.GooglePlayDriver;
import com.firebase.jobdispatcher.Job;
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"));

    // 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.
                scheduleJob();
            } 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());

            //여기에서 메시지가 전달 받는다.


        /*
            아래 코드 실행 안됨
          String message=remoteMessage.getNotification().getBody();
            Intent intent =new Intent(this, MainActivity.class);
            intent.putExtra("message", message);*/
        }

        // 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.


    }



    /**
     * Schedule a job using FirebaseJobDispatcher.
     */
    private void scheduleJob() {
        // [START dispatch_job]
        FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(this));
        Job myJob = dispatcher.newJobBuilder()
                .setService(MyJobService.class)
                .setTag("my-job-tag")
                .build();
        dispatcher.schedule(myJob);
        // [END dispatch_job]


/*
            위에코드는 간략하게 아래는 전체

        Bundle myExtrasBundle = new Bundle();
        myExtrasBundle.putString("some_key", "some_value");

        Job myJob = dispatcher.newJobBuilder()
                // the JobService that will be called
                .setService(MyJobService.class)
                // uniquely identifies the job
                .setTag("my-unique-tag")
                // one-off job
                .setRecurring(false)
                // don't persist past a device reboot
                .setLifetime(Lifetime.UNTIL_NEXT_BOOT)
                // start between 0 and 60 seconds from now
                .setTrigger(Trigger.executionWindow(0, 60))
                // don't overwrite an existing job with the same tag
                .setReplaceCurrent(false)
                // retry with exponential backoff
                .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
                // constraints that need to be satisfied for the job to run
                .setConstraints(
                        // only run on an unmetered network
                        Constraint.ON_UNMETERED_NETWORK,
                        // only run when the device is charging
                        Constraint.DEVICE_CHARGING
                )
                .setExtras(myExtrasBundle)
                .build();

        dispatcher.mustSchedule(myJob);*/


    }

    /**
     * Handle time allotted to BroadcastReceivers.
     */
    private void handleNow() {
        Log.d(TAG, "Short lived task is done.");
    }





    private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* 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());
    }






}

 

class MyFirebaseInstanceIDService

package kr.co.braverokmc.fcmpushexample;

/**
 * Created by choi on 2017-04-19.
 */

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";

    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String token = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + token);

        // 생성등록된 토큰을 개인 앱서버에 보내 저장해 두었다가 추가 뭔가를 하고 싶으면 할 수 있도록 한다.
        sendRegistrationToServer(token);
    }

    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.

        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("Token", token)
                .build();


        //토큰을 실어서 보낼 자신의 서버주소를 적어 준다.
        //request
        Request request = new Request.Builder()
                .url("http://서버주소/fcm/register.php")
                .post(body)
                .build();

        try {
            client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

 

 

class MyJobService

package kr.co.braverokmc.fcmpushexample;

/**
 * Created by choi on 2017-04-19.
 */
import com.firebase.jobdispatcher.JobParameters;
import com.firebase.jobdispatcher.JobService;

public class MyJobService extends JobService {
    @Override
    public boolean onStartJob(JobParameters job) {
        // Do some work here

        return false; // Answers the question: "Is there still work going on?"
    }

    @Override
    public boolean onStopJob(JobParameters job) {
        return false; // Answers the question: "Should this job be retried?"
    }

}

 

R.layout.activity_main

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="kr.co.braverokmc.fcmpushexample.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:id="@+id/text1"
        />
</RelativeLayout>

 

 

 

AndroidMainfest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kr.co.braverokmc.fcmpushexample">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <!-- [START fcm_default_icon] -->
        <!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
             See README(https://goo.gl/l4GJaQ) for more. -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@drawable/a5" />
        <!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
             notification message. See README(https://goo.gl/6BKBk7) for more. -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_color"
            android:resource="@color/colorAccent" />
        <!-- [END fcm_default_icon] -->



        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>




        <!-- [START firebase_service] -->
        <service
            android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
        <!-- [END firebase_service] -->
        <!-- [START firebase_iid_service] -->
        <service
            android:name=".MyFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>
        <!-- [END firebase_iid_service] -->



        <service
            android:exported="false"
            android:name=".MyJobService">
            <intent-filter>
                <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>
            </intent-filter>
        </service>

    </application>




</manifest>

 

 

 

 

 

app1

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files

        classpath 'com.google.gms:google-services:3.0.0'

    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

 

 

 

 

app2

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "kr.co.braverokmc.fcmpushexample"
        minSdkVersion 14
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    testCompile 'junit:junit:4.12'

    //추가한 라인(계속 업그레이드 되고 있다.)
    compile 'com.google.firebase:firebase-messaging:10.0.1'
//서버로 데이터를 보낼때 okhttp를 사용한다면 추가
    compile 'com.squareup.okhttp3:okhttp:3.2.0'

    //잡스서비스 추가
    compile 'com.firebase:firebase-jobdispatcher:0.6.0'
}


apply plugin: 'com.google.gms.google-services'

 

 

 

 

131강

 

 

 

132강

 

 

 

 

about author

PHRASE

Level 60  머나먼나라

스위스 농부들은 온화하지만 용감하다. -쇼펜하우어

댓글 ( 4)

댓글 남기기

작성