Repository: jirawatee/FirebaseCloudMessaging-Android Branch: master Commit: b6dce4a8b153 Files: 22 Total size: 27.0 KB Directory structure: gitextract_wv0ejhht/ ├── .gitignore ├── README.md ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── example/ │ │ └── fcm/ │ │ ├── MainActivity.java │ │ ├── MyFirebaseMessagingService.java │ │ └── SecondActivity.java │ └── res/ │ ├── layout/ │ │ ├── activity_main.xml │ │ └── activity_second.xml │ └── values/ │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ #built application files *.apk *.ap_ # files for the dex VM *.dex # Java class files *.class # generated files bin/ gen/ out/ # Local configuration file (sdk path, etc) local.properties # Windows thumbnail db Thumbs.db # OSX files .DS_Store # Log Files *.log # Android Studio *.iml .gradle/ build/ captures/ .navigation/ # Intellij IDEA .idea/ # Eclipse project files .classpath .project # Proguard folder generated by Eclipse proguard/ # Eclipse Metadata .metadata/ # Keystore files *.jks .externalNativeBuild google-services.json ================================================ FILE: README.md ================================================ # Firebase Cloud Messaging (FCM) FCM is just a demo of Android Application which implement Firebase Cloud Messaging. It made for Google I/O Extended 2016 Bangkok ## Prerequisites * Supported Android 4.1 or newer * Android Studio 3.3.2 or higher * google-services.json in app-level folder ## Features * Subscribe and Unsubscribe with topics * Get token * Send message with payload both **notification** and **data** * Send message with **a token**, **token group**, **a topic**, **condition** * Handle message both **foreground** and **background** * Customize notification * Support notification channel for Android 0 or newer ## Limitation in the message payload * Notification : 2KB limit and a predefined set of user-visible keys * Data : 4KB of custom key-value pairs ## Screenshots
## Slide ```FCM https://docs.google.com/presentation/d/1HPLk1PXaGUjqTlPB6RHsgrTunJNo10kbGZ-JX_7JELw/edit?usp=sharing ``` ================================================ FILE: app/.gitignore ================================================ /build ================================================ FILE: app/build.gradle ================================================ apply plugin: 'com.android.application' android { compileSdkVersion compileAndTargetSdkVersion buildToolsVersion '30.0.3' defaultConfig { applicationId "com.example.fcm" minSdkVersion 21 targetSdkVersion compileAndTargetSdkVersion versionCode 1 versionName "1.0" resConfigs('en', 'xxxhdpi') ndk { abiFilters "x86", "x86_64", "arm64-v8a", "armeabi-v7a" } } buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } debug { splits.abi.enable = false splits.density.enable = false aaptOptions.cruncherEnabled = false } } dexOptions { preDexLibraries true maxProcessCount 8 } } dependencies { implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.firebase:firebase-analytics:18.0.3' implementation 'com.google.firebase:firebase-messaging:21.1.0' } apply plugin: 'com.google.gms.google-services' ================================================ FILE: app/proguard-rules.pro ================================================ -keepattributes Signature -keepattributes *Annotation* -keepattributes EnclosingMethod -keepattributes InnerClasses -assumenosideeffects class android.util.Log { public static boolean isLoggable(java.lang.String, int); public static int v(...); public static int i(...); public static int w(...); public static int d(...); public static int e(...); public static int wtf(...); } ================================================ FILE: app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: app/src/main/java/com/example/fcm/MainActivity.java ================================================ package com.example.fcm; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.util.Log; import android.view.View; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import com.google.firebase.iid.FirebaseInstanceId; import com.google.firebase.iid.InstanceIdResult; import com.google.firebase.messaging.FirebaseMessaging; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Scanner; import static com.example.fcm.R.id.txt; public class MainActivity extends AppCompatActivity { private static final String AUTH_KEY = "key=YOUR-SERVER-KEY"; private TextView mTextView; private String token; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = findViewById(txt); Bundle bundle = getIntent().getExtras(); if (bundle != null) { String tmp = ""; for (String key : bundle.keySet()) { Object value = bundle.get(key); tmp += key + ": " + value + "\n\n"; } mTextView.setText(tmp); } FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (!task.isSuccessful()) { token = task.getException().getMessage(); Log.w("FCM TOKEN Failed", task.getException()); } else { token = task.getResult().getToken(); Log.i("FCM TOKEN", token); } } }); } public void showToken(View view) { mTextView.setText(token); } public void subscribe(View view) { FirebaseMessaging.getInstance().subscribeToTopic("news"); mTextView.setText(R.string.subscribed); } public void unsubscribe(View view) { FirebaseMessaging.getInstance().unsubscribeFromTopic("news"); mTextView.setText(R.string.unsubscribed); } public void sendToken(View view) { sendWithOtherThread("token"); } public void sendTokens(View view) { sendWithOtherThread("tokens"); } public void sendTopic(View view) { sendWithOtherThread("topic"); } private void sendWithOtherThread(final String type) { new Thread(new Runnable() { @Override public void run() { pushNotification(type); } }).start(); } private void pushNotification(String type) { JSONObject jPayload = new JSONObject(); JSONObject jNotification = new JSONObject(); JSONObject jData = new JSONObject(); try { jNotification.put("title", "Google I/O 2016"); jNotification.put("body", "Firebase Cloud Messaging (App)"); jNotification.put("sound", "default"); jNotification.put("badge", "1"); jNotification.put("click_action", "OPEN_ACTIVITY_1"); jNotification.put("icon", "ic_notification"); jData.put("picture", "https://miro.medium.com/max/1400/1*QyVPcBbT_jENl8TGblk52w.png"); switch(type) { case "tokens": JSONArray ja = new JSONArray(); ja.put("c5pBXXsuCN0:APA91bH8nLMt084KpzMrmSWRS2SnKZudyNjtFVxLRG7VFEFk_RgOm-Q5EQr_oOcLbVcCjFH6vIXIyWhST1jdhR8WMatujccY5uy1TE0hkppW_TSnSBiUsH_tRReutEgsmIMmq8fexTmL"); ja.put(token); jPayload.put("registration_ids", ja); break; case "topic": jPayload.put("to", "/topics/news"); break; case "condition": jPayload.put("condition", "'sport' in topics || 'news' in topics"); break; default: jPayload.put("to", token); } jPayload.put("priority", "high"); jPayload.put("notification", jNotification); jPayload.put("data", jData); URL url = new URL("https://fcm.googleapis.com/fcm/send"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Authorization", AUTH_KEY); conn.setRequestProperty("Content-Type", "application/json"); conn.setDoOutput(true); // Send FCM message content. OutputStream outputStream = conn.getOutputStream(); outputStream.write(jPayload.toString().getBytes()); // Read FCM response. InputStream inputStream = conn.getInputStream(); final String resp = convertStreamToString(inputStream); Handler h = new Handler(Looper.getMainLooper()); h.post(new Runnable() { @Override public void run() { mTextView.setText(resp); } }); } catch (JSONException | IOException e) { e.printStackTrace(); } } private String convertStreamToString(InputStream is) { Scanner s = new Scanner(is).useDelimiter("\\A"); return s.hasNext() ? s.next().replace(",", ",\n") : ""; } } ================================================ FILE: app/src/main/java/com/example/fcm/MyFirebaseMessagingService.java ================================================ package com.example.fcm; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.media.RingtoneManager; import android.os.Build; import android.os.Bundle; import androidx.core.app.NotificationCompat; import android.util.Log; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; import java.io.IOException; import java.net.URL; import java.util.Map; public class MyFirebaseMessagingService extends FirebaseMessagingService { public static final String FCM_PARAM = "picture"; private static final String CHANNEL_NAME = "FCM"; private static final String CHANNEL_DESC = "Firebase Cloud Messaging"; private int numMessages = 0; @Override public void onMessageReceived(RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); RemoteMessage.Notification notification = remoteMessage.getNotification(); Map data = remoteMessage.getData(); Log.d("FROM", remoteMessage.getFrom()); sendNotification(notification, data); } private void sendNotification(RemoteMessage.Notification notification, Map data) { Bundle bundle = new Bundle(); bundle.putString(FCM_PARAM, data.get(FCM_PARAM)); Intent intent = new Intent(this, SecondActivity.class); intent.putExtras(bundle); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, getString(R.string.notification_channel_id)) .setContentTitle(notification.getTitle()) .setContentText(notification.getBody()) .setAutoCancel(true) .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) //.setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.win)) .setContentIntent(pendingIntent) .setContentInfo("Hello") .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) .setColor(getColor(R.color.colorAccent)) .setLights(Color.RED, 1000, 300) .setDefaults(Notification.DEFAULT_VIBRATE) .setNumber(++numMessages) .setSmallIcon(R.drawable.ic_notification); try { String picture = data.get(FCM_PARAM); if (picture != null && !"".equals(picture)) { URL url = new URL(picture); Bitmap bigPicture = BitmapFactory.decodeStream(url.openConnection().getInputStream()); notificationBuilder.setStyle( new NotificationCompat.BigPictureStyle().bigPicture(bigPicture).setSummaryText(notification.getBody()) ); } } catch (IOException e) { e.printStackTrace(); } NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( getString(R.string.notification_channel_id), CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT ); channel.setDescription(CHANNEL_DESC); channel.setShowBadge(true); channel.canShowBadge(); channel.enableLights(true); channel.setLightColor(Color.RED); channel.enableVibration(true); channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500}); assert notificationManager != null; notificationManager.createNotificationChannel(channel); } assert notificationManager != null; notificationManager.notify(0, notificationBuilder.build()); } } ================================================ FILE: app/src/main/java/com/example/fcm/SecondActivity.java ================================================ package com.example.fcm; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import android.widget.TextView; public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); TextView txt = findViewById(R.id.textView); Bundle bundle = getIntent().getExtras(); if (bundle != null) { for (String key : bundle.keySet()) { Object value = bundle.get(key); txt.append(key + ": " + value + "\n\n"); } } } } ================================================ FILE: app/src/main/res/layout/activity_main.xml ================================================