- 安卓
- 百度
- iOS
- Kindle
- Windows Phone Silverlight 8.x
- 通用 Windows 平台
本教程介绍如何使用 Azure 通知中心和 Firebase Cloud Messaging (FCM) SDK 版本 0.6 将推送通知发送到 Android 应用程序。 在本教程中,请创建一个空白 Android 应用,以便使用 Firebase Cloud Messaging (FCM) 接收推送通知。
重要
Google 将于 2024 年 6 月 20 日停止支持 FCM 旧版 HTTP。 有关详细信息,请参阅 Azure 通知中心和 Google Firebase Cloud Messaging 迁移。
可以从 GitHub下载本教程的已完成代码。
在本教程中,我们将执行以下步骤:
- 创建 Android Studio 项目。
- 创建支持 Firebase Cloud Messaging 的 Firebase 项目。
- 创建中心。
- 将应用连接到中心。
- 测试应用。
先决条件
要完成本教程,必须有一个有效的 Azure 帐户。 如果没有帐户,只需花费几分钟就能创建一个免费试用帐户。 有关详细信息,请参阅 Azure 免费试用。
还需要以下项:
- 最新版本的 Android Studio
- 适用于 Firebase Cloud Messaging 的 Android 2.3 或更高版本
- 适用于 Firebase Cloud Messaging 的 Google Repository 版本 27 或更高版本
- 适用于 Firebase Cloud Messaging 的 Google Play Services 9.0.2 或更高版本
完成本教程是学习有关 Android 应用的所有其他通知中心教程的先决条件。
创建 Android Studio 项目
- 启动 Android Studio。
- 选择“文件”,指向“新建”,然后选择“新建项目”。
- 在“选择项目”页上选择“空活动”,选择“下一步”。
- 在“配置项目”页上执行以下步骤:
输入应用程序的名称。
指定项目文件的保存位置。
选择“完成”。
创建支持 FCM 的 Firebase 项目
登录到 Firebase 控制台。 如果还没有 Firebase 项目,创建一个新项目。
创建项目后,选择“向 Android 应用添加 Firebase”。
在“将 Firebase 添加到 Android 应用”页上,执行以下步骤:
对于“Android 程序包名称”,请在应用程序的 build.gradle 文件中复制 applicationId 的值。 在此示例中,它是
com.fabrikam.fcmtutorial1app
。选择“注册应用”。
选择“下载 google-services.json”,将该文件保存到项目的 app 文件夹中,然后选择“下一步”。
在 Android Studio 中对你的项目进行以下配置更改。
在项目级 build.gradle 文件 (<project>/build.gradle) 中,向 dependencies 部分中添加以下语句。
classpath 'com.google.gms:google-services:4.0.1'
在应用级 build.gradle 文件 (<project>/<app-module>/build.gradle) 中,向 dependencies 部分中添加以下语句。
implementation 'com.google.firebase:firebase-core:16.0.8' implementation 'com.google.firebase:firebase-messaging:17.3.4'
在应用级 build.gradle 文件的末尾,在 dependencies 部分后面添加以下行。
apply plugin: 'com.google.gms.google-services'
在工具栏上选择“立即同步”。
选择“下一步” 。
选择“跳过此步骤”。
在 Firebase 控制台中,选择与项目相对应的齿轮图标。 然后,选择“项目设置”。
如果尚未将 google-services.json 文件下载到你的 Android Studio 项目的 app 文件夹中,则可以在此页面上执行此操作。
切换到顶部的“Cloud Messaging”选项卡。
复制并保存服务器密钥以供将来使用。 此值将用于配置中心。
如果在 Firebase Cloud Messaging 选项卡上看不到“服务器密钥”,请按照以下附加步骤操作。
- 单击“Cloud Messaging API (旧版) 🚫 已禁用”标题的三点菜单
- 按照提供的“在 Google Cloud 控制台中管理 API”的链接进行操作。
- 在 Google Cloud 控制台中,按下按钮启用 googlecloudmessaging API。
- 稍等几分钟。
- 返回 firebase 控制台项目 Cloud Messaging 选项卡,然后刷新页面。
- 注意 Cloud Messaging API 标头已更改为“Cloud Messaging API (旧版) ✅ 已启用”,现在显示服务器密钥。
配置中心
登录 Azure 门户。
在左侧菜单中,选择“所有服务” 。
在“筛选器服务”文本框中键入“通知中心”。 选择服务名称旁边的星形图标,以便将服务添加到左侧菜单上的“收藏夹”部分。 选择“通知中心”。
在“通知中心”页面上,在工具栏上选择“创建”。
在“通知中心”页面上的“基本信息”选项卡中,执行以下步骤:
在订阅中,选择要使用的 Azure 订阅的名称,然后选择现有资源组或创建新资源组。
在命名空间详细信息中为新命名空间输入唯一名称。
命名空间包含一个或多个通知中心,因此请在通知中心详细信息中键入中心的名称。
从位置下拉列表框中选择值。 此值指定要在其中创建通知中心的位置。
查看“可用性区域”选项。 如果选择了具有可用性区域的区域,则默认会选中该复选框。 可用性区域是一项付费功能,因此会向你的层级添加额外费用。
选择“灾难恢复”选项:“无”、“配对恢复区域”或“灵活恢复区域”。 如果选择配对恢复区域,则会显示故障转移区域。 如果选择“灵活恢复区域”,请使用下拉列表从恢复区域列表中选择。
选择“创建” 。
部署完成后,选择“转到资源”。
为中心配置 Firebase Cloud Messaging 设置
在左窗格中的“设置”下,选择“Google (GCM/FCM)” 。
输入前面保存的 FCM 项目“服务器密钥”。
在工具栏上选择“保存”。
Azure 门户中显示一条警报消息,指出通知中心已成功更新。 “保存”按钮已禁用。
现在,中心已配置为使用 Firebase Cloud Messaging。 连接字符串还需要将通知发送到设备并注册应用以接收通知。
将应用连接到通知中心
将 Google Play 服务添加到项目
在 Android Studio 中,在菜单上选择“工具”,然后选择“SDK 管理器”。
选择项目中使用的 Android SDK 的目标版本。 然后选择“显示包详细信息”。
选择“Google API”(如果尚未安装)。
切换到“SDK 工具”选项卡。如果尚未安装 Google Play Services,请选择“Google Play Services”,如下图所示。 然后,选择“应用”以进行安装。 记下 SDK 路径,因为后面的步骤将要用到。
如果看到了“确认更改”对话框,请选择“确定”。 组件安装程序将安装所请求的组件。 在安装组件后,选择“完成”。
选择“确定”以关闭“新项目的设置”对话框。
打开 AndroidManifest.xml 文件,然后将以下标记添加到应用程序标记。
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
添加 Azure 通知中心库
在应用的 Build.Gradle 文件中,添加以下行到依赖项部分。
implementation 'com.microsoft.azure:notification-hubs-android-sdk:0.6@aar'
在 dependencies 节的后面添加以下存储库。
repositories { maven { url "https://dl.bintray.com/microsoftazuremobile/SDK" } }
添加 Google Firebase 支持
在应用的 Build.Gradle 文件中,如果她们不存在就添加以下行到“依赖项”部分。
implementation 'com.google.firebase:firebase-core:16.0.8' implementation 'com.google.firebase:firebase-messaging:17.3.4' implementation 'com.google.firebase:firebase-iid:21.1.0'
在该文件的末尾添加以下插件(如果已经不在那里)。
apply plugin: 'com.google.gms.google-services'
在工具栏上选择“立即同步”。
更新 AndroidManifest.xml 文件
收到 FCM 注册令牌后,使用它在 Azure 通知中心注册。 请使用名为
IntentService
的RegistrationIntentService
在后台支持此注册。 此服务还刷新 FCM 注册令牌。 你还将创建一个名为FirebaseService
的类作为FirebaseMessagingService
的子类,并重写onMessageReceived
方法以接收和处理通知。将以下服务定义添加到 AndroidManifest.xml 文件的
<application>
标记内。<service android:name=".RegistrationIntentService" android:exported="false"> </service> <service android:name=".FirebaseService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
在
</application>
标记下面添加以下必要的 FCM 相关权限。<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.GET_ACCOUNTS"/> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
添加代码
在项目视图中,展开 app>src>main>java 右键单击“java”下的包文件夹,选择“新建”,然后选择“Java 类” 。 输入 NotificationSettings 作为名称,然后选择“确定” 。
确保在
NotificationSettings
类的以下代码中更新这两个占位符:HubListenConnectionString:中心的 DefaultListenAccessSignature 连接字符串。 可以复制此连接字符串,方法是在 Azure 门户的中心单击“访问策略”。
HubName:使用 Azure 门户的中心页中显示的中心的名称。
NotificationSettings
代码:public class NotificationSettings { public static String HubName = "<Your HubName>"; public static String HubListenConnectionString = "<Enter your DefaultListenSharedAccessSignature connection string>"; }
重要
输入中心的名称和 DefaultListenSharedAccessSignature,然后继续 。
将另一个名为
RegistrationIntentService
的新类添加到项目。 此类实现IntentService
接口。 它还处理刷新 FCM 令牌和在通知中心注册。针对此类使用以下代码。
import android.app.IntentService; import android.content.Intent; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.util.Log; import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.iid.FirebaseInstanceId; import com.google.firebase.iid.InstanceIdResult; import com.microsoft.windowsazure.messaging.NotificationHub; import java.util.concurrent.TimeUnit; public class RegistrationIntentService extends IntentService { private static final String TAG = "RegIntentService"; String FCM_token = null; private NotificationHub hub; public RegistrationIntentService() { super(TAG); } @Override protected void onHandleIntent(Intent intent) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); String resultString = null; String regID = null; String storedToken = null; try { FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() { @Override public void onSuccess(InstanceIdResult instanceIdResult) { FCM_token = instanceIdResult.getToken(); Log.d(TAG, "FCM Registration Token: " + FCM_token); } }); TimeUnit.SECONDS.sleep(1); // Storing the registration ID that indicates whether the generated token has been // sent to your server. If it is not stored, send the token to your server. // Otherwise, your server should have already received the token. if (((regID=sharedPreferences.getString("registrationID", null)) == null)){ NotificationHub hub = new NotificationHub(NotificationSettings.HubName, NotificationSettings.HubListenConnectionString, this); Log.d(TAG, "Attempting a new registration with NH using FCM token : " + FCM_token); regID = hub.register(FCM_token).getRegistrationId(); // If you want to use tags... // Refer to : https://azure.microsoft.com/documentation/articles/notification-hubs-routing-tag-expressions/ // regID = hub.register(token, "tag1,tag2").getRegistrationId(); resultString = "New NH Registration Successfully - RegId : " + regID; Log.d(TAG, resultString); sharedPreferences.edit().putString("registrationID", regID ).apply(); sharedPreferences.edit().putString("FCMtoken", FCM_token ).apply(); } // Check to see if the token has been compromised and needs refreshing. else if (!(storedToken = sharedPreferences.getString("FCMtoken", "")).equals(FCM_token)) { NotificationHub hub = new NotificationHub(NotificationSettings.HubName, NotificationSettings.HubListenConnectionString, this); Log.d(TAG, "NH Registration refreshing with token : " + FCM_token); regID = hub.register(FCM_token).getRegistrationId(); // If you want to use tags... // Refer to : https://azure.microsoft.com/documentation/articles/notification-hubs-routing-tag-expressions/ // regID = hub.register(token, "tag1,tag2").getRegistrationId(); resultString = "New NH Registration Successfully - RegId : " + regID; Log.d(TAG, resultString); sharedPreferences.edit().putString("registrationID", regID ).apply(); sharedPreferences.edit().putString("FCMtoken", FCM_token ).apply(); } else { resultString = "Previously Registered Successfully - RegId : " + regID; } } catch (Exception e) { Log.e(TAG, resultString="Failed to complete registration", e); // If an exception happens while fetching the new token or updating registration data // on a third-party server, this ensures that we'll attempt the update at a later time. } // Notify UI that registration has completed. if (MainActivity.isVisible) { MainActivity.mainActivity.ToastNotify(resultString); } } }
在
MainActivity
类中,在类声明的上面添加以下import
语句。import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; import android.content.Intent; import android.util.Log; import android.widget.TextView; import android.widget.Toast;
在该类的最上面添加以下成员。 请使用这些字段来检查 Google 推荐的 Google Play Services 的可用性。
public static MainActivity mainActivity; public static Boolean isVisible = false; private static final String TAG = "MainActivity"; private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
在
MainActivity
类中,添加以下方法来检查 Google Play 服务的可用性。/** * Check the device to make sure it has the Google Play Services APK. If * it doesn't, display a dialog box that enables users to download the APK from * the Google Play Store or enable it in the device's system settings. */ private boolean checkPlayServices() { GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); int resultCode = apiAvailability.isGooglePlayServicesAvailable(this); if (resultCode != ConnectionResult.SUCCESS) { if (apiAvailability.isUserResolvableError(resultCode)) { apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST) .show(); } else { Log.i(TAG, "This device is not supported by Google Play Services."); ToastNotify("This device is not supported by Google Play Services."); finish(); } return false; } return true; }
在
MainActivity
类中添加以下代码,用于在调用IntentService
之前检查 Google Play 服务,以获取 FCM 注册令牌并向中心注册:public void registerWithNotificationHubs() { if (checkPlayServices()) { // Start IntentService to register this application with FCM. Intent intent = new Intent(this, RegistrationIntentService.class); startService(intent); } }
在
OnCreate
类的MainActivity
方法中添加以下代码,以便在创建活动时开始注册过程:@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mainActivity = this; registerWithNotificationHubs(); FirebaseService.createChannelAndHandleNotifications(getApplicationContext()); }
若要验证和报告应用状态,请将这些其他的方法添加到
MainActivity
:@Override protected void onStart() { super.onStart(); isVisible = true; } @Override protected void onPause() { super.onPause(); isVisible = false; } @Override protected void onResume() { super.onResume(); isVisible = true; } @Override protected void onStop() { super.onStop(); isVisible = false; } public void ToastNotify(final String notificationMessage) { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, notificationMessage, Toast.LENGTH_LONG).show(); TextView helloText = (TextView) findViewById(R.id.text_hello); helloText.setText(notificationMessage); } }); }
ToastNotify
方法使用“Hello World” 控件在应用中持续报告状态和通知TextView
。 在 res>layout>activity_main.xml 布局中,为该控件添加以下 ID。android:id="@+id/text_hello"
接下来,为 AndroidManifest.xml 中定义的接收者添加一个子类。 将另一个名为
FirebaseService
的新类添加到项目。在
FirebaseService.java
的顶部添加以下 import 语句:import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; import android.util.Log; import android.app.NotificationChannel; 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.os.Build; import android.os.Bundle; import androidx.core.app.NotificationCompat;
为
FirebaseService
类添加以下代码,使其成为FirebaseMessagingService
的子类。此代码将重写
onMessageReceived
方法,并报告所收到的通知。 它还使用sendNotification()
方法将推送通知发送到 Android 通知管理器。 应用未在运行但收到通知时,应调用sendNotification()
方法。public class FirebaseService extends FirebaseMessagingService { private String TAG = "FirebaseService"; public static final String NOTIFICATION_CHANNEL_ID = "nh-demo-channel-id"; public static final String NOTIFICATION_CHANNEL_NAME = "Notification Hubs Demo Channel"; public static final String NOTIFICATION_CHANNEL_DESCRIPTION = "Notification Hubs Demo Channel"; public static final int NOTIFICATION_ID = 1; private NotificationManager mNotificationManager; NotificationCompat.Builder builder; static Context ctx; @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()); String nhMessage; // Check if message contains a notification payload. if (remoteMessage.getNotification() != null) { Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody()); nhMessage = remoteMessage.getNotification().getBody(); } else { nhMessage = remoteMessage.getData().values().iterator().next(); } // 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. if (MainActivity.isVisible) { MainActivity.mainActivity.ToastNotify(nhMessage); } sendNotification(nhMessage); } private void sendNotification(String msg) { Intent intent = new Intent(ctx, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); mNotificationManager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0, intent, PendingIntent.FLAG_ONE_SHOT); Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder( ctx, NOTIFICATION_CHANNEL_ID) .setContentText(msg) .setPriority(NotificationCompat.PRIORITY_HIGH) .setSmallIcon(android.R.drawable.ic_popup_reminder) .setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL); notificationBuilder.setContentIntent(contentIntent); mNotificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()); } public static void createChannelAndHandleNotifications(Context context) { ctx = context; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH); channel.setDescription(NOTIFICATION_CHANNEL_DESCRIPTION); channel.setShowBadge(true); NotificationManager notificationManager = context.getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } } }
在 Android Studio 的菜单栏上,选择“生成”“重新生成项目”,确保代码中没有任何错误。 如果收到有关
ic_launcher
图标的错误,请从 AndroidManifest.xml 文件中删除以下语句:android:icon="@mipmap/ic_launcher"
确保有用于运行应用的虚拟设备。 如果没有,请添加一个,如下所示:
-
在所选设备上运行该应用,验证其是否已成功注册到中心。
注意
除非已调用实例 ID 服务的
onTokenRefresh()
方法,否则最初启动期间注册可能会失败。 刷新即可成功注册到通知中心。
从通知中心测试性地发送通知
可以执行下述步骤,以便从 Azure 门户发送推送通知:
在 Azure 门户中通知中心的“中心”页上,选择“故障排除”部分的“测试发送”。
对于“平台”,请选择“Android”。
选择“发送”。 目前在 Android 设备上还看不到通知,因为尚未在其上运行移动应用。 运行移动应用以后,再次选择“发送”按钮即可看到通知消息。
请在底部的列表中查看操作结果。
设备上会显示通知消息。
通常,推送通知是在后端服务(例如,移动应用,或者使用兼容库的 ASP.NET)中发送的。 如果后端没有可用库,也可使用 REST API 直接发送通知消息。
下面是可能需要查看的有关发送通知的其他教程列表:
- Azure 移动应用:有关如何从通知中心集成的移动应用后端发送通知的示例,请参阅将推送通知添加到 iOS 应用。
- ASP.NET:使用通知中心将通知推送到用户。
- Azure 通知中心 Java SDK:有关从 Java 发送通知的信息,请参阅 如何通过 Java 使用通知中心 。 这种方法已在 Eclipse for Android 开发环境中进行测试。
- PHP: 如何通过 PHP 使用通知中心。
在仿真器中运行移动应用
在模拟器中测试推送通知之前,请确保模拟器映像支持你为应用程序选择的 Google API 级别。 如果映像不支持本机 Google API,可能会收到“SERVICE_NOT_AVAILABLE”异常。
另外,请确保已在“设置”“帐户”下将 Google 帐户添加到正在运行的模拟器中。 否则,尝试向 FCM 注册可能会导致“AUTHENTICATION_FAILED”异常。
后续步骤
在本教程中,你已使用 Firebase Cloud Messaging 将通知广播到在该服务中注册的所有 Android 设备。 若要了解如何向特定的设备推送通知,请转到以下教程: