From c06a27c0bbb86b44515e946adb6dcab97610e32d Mon Sep 17 00:00:00 2001 From: jinan Date: Fri, 1 Sep 2023 15:38:14 +0800 Subject: [PATCH] [Android] Add FCM quickstart example. --- Chat-Android/build.gradle | 6 +- Chat-Android/fcmquickstart/.gitignore | 1 + Chat-Android/fcmquickstart/build.gradle | 48 +++++ .../fcmquickstart/google-services.json | 68 ++++++ Chat-Android/fcmquickstart/proguard-rules.pro | 21 ++ .../src/main/AndroidManifest.xml | 34 +++ .../io/agora/fcmquickstart/FCMMSGService.java | 89 ++++++++ .../io/agora/fcmquickstart/MainActivity.java | 198 ++++++++++++++++++ .../drawable-v24/ic_launcher_foreground.xml | 30 +++ .../res/drawable/ic_launcher_background.xml | 170 +++++++++++++++ .../src/main/res/layout/activity_main.xml | 63 ++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 6 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 6 + .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 1404 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 2898 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 982 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 1772 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 1900 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 3918 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 2884 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 5914 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 3844 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 7778 bytes .../src/main/res/values-night/themes.xml | 7 + .../src/main/res/values/colors.xml | 5 + .../src/main/res/values/strings.xml | 3 + .../src/main/res/values/themes.xml | 9 + Chat-Android/settings.gradle | 3 +- 28 files changed, 765 insertions(+), 2 deletions(-) create mode 100644 Chat-Android/fcmquickstart/.gitignore create mode 100644 Chat-Android/fcmquickstart/build.gradle create mode 100644 Chat-Android/fcmquickstart/google-services.json create mode 100644 Chat-Android/fcmquickstart/proguard-rules.pro create mode 100644 Chat-Android/fcmquickstart/src/main/AndroidManifest.xml create mode 100644 Chat-Android/fcmquickstart/src/main/java/io/agora/fcmquickstart/FCMMSGService.java create mode 100644 Chat-Android/fcmquickstart/src/main/java/io/agora/fcmquickstart/MainActivity.java create mode 100644 Chat-Android/fcmquickstart/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 Chat-Android/fcmquickstart/src/main/res/drawable/ic_launcher_background.xml create mode 100644 Chat-Android/fcmquickstart/src/main/res/layout/activity_main.xml create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 Chat-Android/fcmquickstart/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp create mode 100644 Chat-Android/fcmquickstart/src/main/res/values-night/themes.xml create mode 100644 Chat-Android/fcmquickstart/src/main/res/values/colors.xml create mode 100644 Chat-Android/fcmquickstart/src/main/res/values/strings.xml create mode 100644 Chat-Android/fcmquickstart/src/main/res/values/themes.xml diff --git a/Chat-Android/build.gradle b/Chat-Android/build.gradle index 00f269e..04b9a0a 100644 --- a/Chat-Android/build.gradle +++ b/Chat-Android/build.gradle @@ -7,7 +7,11 @@ buildscript { } dependencies { classpath "com.android.tools.build:gradle:4.2.2" - + // Firebase + classpath 'com.google.gms:google-services:4.3.15' + // Add the Crashlytics Gradle plugin (be sure to add version + // 2.0.0 or later if you built your app with Android Studio 4.1). + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/Chat-Android/fcmquickstart/.gitignore b/Chat-Android/fcmquickstart/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/Chat-Android/fcmquickstart/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/Chat-Android/fcmquickstart/build.gradle b/Chat-Android/fcmquickstart/build.gradle new file mode 100644 index 0000000..e58a9de --- /dev/null +++ b/Chat-Android/fcmquickstart/build.gradle @@ -0,0 +1,48 @@ +plugins { + id 'com.android.application' + id 'com.google.gms.google-services' +} + +android { + compileSdkVersion 33 + + defaultConfig { + applicationId "io.agora.fcmquickstart" + minSdkVersion 21 + targetSdkVersion 33 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.6.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + // Google firebase cloud messaging + // Import the BoM for the Firebase platform + implementation platform('com.google.firebase:firebase-bom:32.2.3') + // Declare the dependencies for the Firebase Cloud Messaging and Analytics libraries + // When using the BoM, you don't specify versions in Firebase library dependencies + implementation 'com.google.firebase:firebase-messaging' + implementation 'com.google.firebase:firebase-analytics' + // Required: Agora Chat SDK + implementation 'io.agora.rtc:chat-sdk:1.1.0' +} \ No newline at end of file diff --git a/Chat-Android/fcmquickstart/google-services.json b/Chat-Android/fcmquickstart/google-services.json new file mode 100644 index 0000000..ac513a4 --- /dev/null +++ b/Chat-Android/fcmquickstart/google-services.json @@ -0,0 +1,68 @@ +{ + "project_info": { + "project_number": "142290967082", + "project_id": "chatim-9b3ae", + "storage_bucket": "chatim-9b3ae.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:142290967082:android:fa1734c82786f78184c153", + "android_client_info": { + "package_name": "io.agora.chatdemo" + } + }, + "oauth_client": [ + { + "client_id": "142290967082-kffai4lca6v8f70lbku18hquh72747qa.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDE682uNgGqIfEL7o6BkShzx5Pi2nuIIS0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "142290967082-kffai4lca6v8f70lbku18hquh72747qa.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:142290967082:android:096ac679236ff8d084c153", + "android_client_info": { + "package_name": "io.agora.fcmquickstart" + } + }, + "oauth_client": [ + { + "client_id": "142290967082-kffai4lca6v8f70lbku18hquh72747qa.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDE682uNgGqIfEL7o6BkShzx5Pi2nuIIS0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "142290967082-kffai4lca6v8f70lbku18hquh72747qa.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/Chat-Android/fcmquickstart/proguard-rules.pro b/Chat-Android/fcmquickstart/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/Chat-Android/fcmquickstart/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/Chat-Android/fcmquickstart/src/main/AndroidManifest.xml b/Chat-Android/fcmquickstart/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9cce4a7 --- /dev/null +++ b/Chat-Android/fcmquickstart/src/main/AndroidManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Chat-Android/fcmquickstart/src/main/java/io/agora/fcmquickstart/FCMMSGService.java b/Chat-Android/fcmquickstart/src/main/java/io/agora/fcmquickstart/FCMMSGService.java new file mode 100644 index 0000000..4c40549 --- /dev/null +++ b/Chat-Android/fcmquickstart/src/main/java/io/agora/fcmquickstart/FCMMSGService.java @@ -0,0 +1,89 @@ +package io.agora.fcmquickstart; + +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.content.pm.PackageManager; +import android.os.Build; + +import androidx.annotation.NonNull; +import androidx.core.app.NotificationCompat; + +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; + +import io.agora.chat.ChatClient; +import io.agora.util.EMLog; + +public class FCMMSGService extends FirebaseMessagingService { + private static final String CHANNEL_ID = "fcmquickstart_notification"; + private static final long[] VIBRATION_PATTERN = new long[]{0, 180, 80, 120}; + private static int NOTIFY_ID = 1000; // start notification id + private static final String TAG = "EMFCMMSGService"; + + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + super.onMessageReceived(remoteMessage); + if (remoteMessage.getData().size() > 0) { + String message = remoteMessage.getData().get("alert"); + EMLog.i(TAG, "onMessageReceived: " + message); + notify(message); + } + } + + @Override + public void onNewToken(@NonNull String token) { + super.onNewToken(token); + EMLog.i(TAG, "onNewToken: " + token); + ChatClient.getInstance().sendFCMTokenToServer(token); + } + + private void notify(String message) { + NotificationManager notificationManager = (NotificationManager) getApplication().getSystemService(Context.NOTIFICATION_SERVICE); + + if (Build.VERSION.SDK_INT >= 26) { + // Create the notification channel for Android 8.0 + NotificationChannel channel = new NotificationChannel(CHANNEL_ID, + "fcm quick start message default channel.", NotificationManager.IMPORTANCE_DEFAULT); + channel.setVibrationPattern(VIBRATION_PATTERN); + notificationManager.createNotificationChannel(channel); + } + try { + NotificationCompat.Builder builder = generateBaseBuilder(message); + Notification notification = builder.build(); + notificationManager.notify(NOTIFY_ID, notification); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Generate a base Notification#Builder, contains: + * 1.Use the app icon as default icon + * 2.Use the app name as default title + * 3.This notification would be sent immediately + * 4.Can be cancelled by user + * 5.Would launch the default activity when be clicked + * + * @return + */ + private NotificationCompat.Builder generateBaseBuilder(String content) { + PackageManager pm = getApplication().getPackageManager(); + String title = pm.getApplicationLabel(getApplication().getApplicationInfo()).toString(); + Intent i = getApplication().getPackageManager().getLaunchIntentForPackage(getApplication().getApplicationInfo().packageName); + PendingIntent pendingIntent = PendingIntent.getActivity(getApplication(), NOTIFY_ID, i, PendingIntent.FLAG_UPDATE_CURRENT); + + return new NotificationCompat.Builder(getApplication(), CHANNEL_ID) + .setSmallIcon(getApplication().getApplicationInfo().icon) + .setContentTitle(title) + .setTicker(content) + .setContentText(content) + .setWhen(System.currentTimeMillis()) + .setAutoCancel(true) + .setContentIntent(pendingIntent); + } +} \ No newline at end of file diff --git a/Chat-Android/fcmquickstart/src/main/java/io/agora/fcmquickstart/MainActivity.java b/Chat-Android/fcmquickstart/src/main/java/io/agora/fcmquickstart/MainActivity.java new file mode 100644 index 0000000..c30da28 --- /dev/null +++ b/Chat-Android/fcmquickstart/src/main/java/io/agora/fcmquickstart/MainActivity.java @@ -0,0 +1,198 @@ +package io.agora.fcmquickstart; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; + +import android.os.Bundle; +import android.text.TextUtils; +import android.text.method.ScrollingMovementMethod; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailabilityLight; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.analytics.FirebaseAnalytics; +import com.google.firebase.messaging.FirebaseMessaging; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import io.agora.CallBack; +import io.agora.ChatLogListener; +import io.agora.chat.ChatClient; +import io.agora.chat.ChatOptions; +import io.agora.push.PushConfig; +import io.agora.push.PushHelper; +import io.agora.push.PushListener; +import io.agora.push.PushType; + +public class MainActivity extends AppCompatActivity { + // Create a user from Agora Console or by your app server + private static final String USERNAME = ""; + // Gets token from Agora Console or generates by your app server + private static final String TOKEN = ""; + // Gets AppKey from Agora Console + private static final String APP_KEY = ""; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + ((TextView)findViewById(R.id.tv_log)).setMovementMethod(new ScrollingMovementMethod()); + initSDK(); + initListener(); + } + + private void initSDK() { + ChatOptions options = new ChatOptions(); + // Get your appkey applied from Agora Console + if(TextUtils.isEmpty(APP_KEY)) { + showLog("You should set your AppKey first!", true); + return; + } + // Set your appkey to options + options.setAppKey(APP_KEY); + /** + * NOTE:You need to set up your own account to use the three-way push function, see the integration documentation + */ + PushConfig.Builder builder = new PushConfig.Builder(this); + + // The FCM sender id should equals with the project_number in google-services.json + builder.enableFCM("142290967082"); + options.setPushConfig(builder.build()); + // To initialize Agora Chat SDK + ChatClient.getInstance().init(this, options); + // Make Agora Chat SDK debuggable + ChatClient.getInstance().setDebugMode(true); + // Show current user + ((TextView)findViewById(R.id.tv_username)).setText("Current user: "+USERNAME); + + // Set push listener + PushHelper.getInstance().setPushListener(new PushListener() { + @Override + public void onError(PushType pushType, long errorCode) { + showLog("Push client occur a error: " + pushType + " - " + errorCode, true); + } + + @Override + public boolean isSupportPush(PushType pushType, PushConfig pushConfig) { + if (pushType == PushType.FCM) { + showLog("GooglePlayServiceCode:" + GoogleApiAvailabilityLight.getInstance().isGooglePlayServicesAvailable(MainActivity.this), true); + return GoogleApiAvailabilityLight.getInstance().isGooglePlayServicesAvailable(MainActivity.this) == ConnectionResult.SUCCESS; + } + return super.isSupportPush(pushType, pushConfig); + } + }); + } + + private void initListener() { + if(ChatClient.getInstance().isSdkInited()) { + ChatClient.getInstance().addLogListener(new ChatLogListener() { + @Override + public void onLog(String log) { + if(log.contains(PushHelper.class.getSimpleName()) || log.contains("ns : CHAT")) { + showLog(log, false); + } + } + }); + } + } + + /** + * Login with token + */ + public void signInWithToken(View view) { + loginToAgora(); + } + + private void loginToAgora() { + if(TextUtils.isEmpty(USERNAME) || TextUtils.isEmpty(TOKEN)) { + showLog("Username or token is empty!", true); + return; + } + showLog("Signing in...", false); + ChatClient.getInstance().loginWithAgoraToken(USERNAME, TOKEN, new CallBack() { + @Override + public void onSuccess() { + showLog("Sign in success!", true); + } + + @Override + public void onError(int code, String error) { + showLog(error, true); + } + }); + } + + /** + * Sign out + */ + public void signOut(View view) { + if(ChatClient.getInstance().isLoggedInBefore()) { + ChatClient.getInstance().logout(true, new CallBack() { + @Override + public void onSuccess() { + showLog("Sign out success!", true); + } + + @Override + public void onError(int code, String error) { + showLog(error, true); + } + }); + }else { + showLog("You were not logged in", false); + } + } + + /** + * Register FCM token + */ + public void registerFCM(View view) { + if(!ChatClient.getInstance().isLoggedIn()) { + showLog("Please login first!", true); + return; + } + if(GoogleApiAvailabilityLight.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS){ + // set enable FCM automatic initialization + if(!FirebaseMessaging.getInstance().isAutoInitEnabled()){ + FirebaseMessaging.getInstance().setAutoInitEnabled(true); + FirebaseAnalytics.getInstance(this).setAnalyticsCollectionEnabled(true); + } + // get FCM token upload + FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (!task.isSuccessful()) { + showLog("Fetching FCM registration token failed: "+task.getException(), true); + return; + } + // Get new FCM registration token + String token = task.getResult(); + ChatClient.getInstance().sendFCMTokenToServer(token); + } + }); + } + } + + private void showLog(String content, boolean showToast) { + if(TextUtils.isEmpty(content)) { + return; + } + runOnUiThread(()-> { + if(showToast) { + Toast.makeText(this, content, Toast.LENGTH_SHORT).show(); + } + TextView tv_log = findViewById(R.id.tv_log); + String preContent = tv_log.getText().toString().trim(); + StringBuilder builder = new StringBuilder(); + builder.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date())) + .append(" ").append(content).append("\n").append(preContent); + tv_log.setText(builder); + }); + } +} \ No newline at end of file diff --git a/Chat-Android/fcmquickstart/src/main/res/drawable-v24/ic_launcher_foreground.xml b/Chat-Android/fcmquickstart/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/Chat-Android/fcmquickstart/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Chat-Android/fcmquickstart/src/main/res/drawable/ic_launcher_background.xml b/Chat-Android/fcmquickstart/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/Chat-Android/fcmquickstart/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Chat-Android/fcmquickstart/src/main/res/layout/activity_main.xml b/Chat-Android/fcmquickstart/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..acfbaaa --- /dev/null +++ b/Chat-Android/fcmquickstart/src/main/res/layout/activity_main.xml @@ -0,0 +1,63 @@ + + + + + + + + + +