Firebase, Node server + Android

android studio,

firebase 홈페이지>프로젝트선택>프로젝트설정>일반에서 google-services.json을 다운로드 하여 프로젝트에 추가

project gradle에 아래 내용추가

apply plugin: 'com.google.gms.google-services'
...
implementation 'com.google.firebase:firebase-core:16.0.1'
implementation 'com.google.firebase:firebase-messaging:17.1.0'
implementation 'com.google.firebase:firebase-auth:16.0.2'

android, onStart

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( new OnSuccessListener<InstanceIdResult>() {
    @Override
    public void onSuccess(InstanceIdResult instanceIdResult) {
        deviceToken = instanceIdResult.getToken();
    }
});

node.js

var admin = require('firebase-admin');
var serviceAccount = require('./smallet-27f86-firebase-adminsdk-7vwqg-b48b172508.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: 'https://smallet-27f86.firebaseio.com/'
});

여기서 사용되는 json file은 firebase 홈페이지>프로젝트선택>프로젝트설정>서비스계정>새 비공개 키 생성 에서 만들어야 한다. 위에서 만든 google-services.json을 쓰면 안된다.(이것만 헛갈리고 대부분 그냥 절차대로 하면 됨)

서버에서 메시지를 특정 device에 보낼때는 아래 예제와 같이 한다. message 안의 data부분은 알아서 만들면된다. 중요한건 token이고 token은 위 안드로이드 예제에서 저장된  deviceToken을 사용하면 된다.

function sendNotification(tokenId, _receipt) {
  var message = {
    data: {
      transactionHash: _receipt.transactionHash,
      gasUsed: _receipt.gasUsed + "",
      to: _receipt.to + "",
      status: _receipt.status + ""
    },
    token: tokenId
  };
  (async () => {
    console.log(message);
    admin.messaging().send(message)
      .then((response) => {
        // Response is a message ID string.
        console.log('Successfully sent message:', response);
      })
      .catch((error) => {
        console.log('Error sending message:', error);
      });
  })();
}

안드로이드쪽에서 이 메시지를 수신하려면 서비스를 만들면 되고, 포그라운드이든 백그라운드이든 onMessageReceived는 호출되므로 백그라운드에서는 노티피케이션을, 포그라운드에서는 보여지는 액티비티에서 적절히 처리 하면 되겠다.

public class FirebaseService extends FirebaseMessagingService {
    String TAG = "wallet";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        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());
            Bundle bundle = new Bundle();
            for (Map.Entry<String, String> entry : remoteMessage.getData().entrySet()) {
                bundle.putString(entry.getKey(), entry.getValue());
            }
            if (MainActivity.isActivityVisible()) {
                Message msg = new Message();
                msg.what = Constants.RECEIVE_TX_RECEIPT;
                msg.setData(bundle);
                MainActivity.mHandle.sendMessage(msg);
            } else {
                sendNotification(bundle);
            }
        }

    }

    private void sendNotification(Bundle data) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtras(data);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
        String channelId = getString(R.string.default_notification_channel_id);
        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        String title = data.getString("status").equals("true") ? "Transaction Success" : "Transaction Fail";
        NotificationCompat.Builder notificationBuilder =
                new NotificationCompat.Builder(this, channelId).setSmallIcon(R.drawable.ic_notification)
                        .setContentTitle(title)
                        .setContentText(String.format("to %s", data.getString("to")))
                        .setAutoCancel(true)
                        .setSound(defaultSoundUri)
                        .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        // Since android Oreo notification channel is needed.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(channelId,
                    "Channel human readable title",
                    NotificationManager.IMPORTANCE_DEFAULT);
            notificationManager.createNotificationChannel(channel);
        }

        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }
}

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *