Android Studio 和推送通知入门

概述

本教程旨在帮助您设置和运行 Android PlayFab 与推送通知的集成。

推送通知需要在多个系统中进行配置。 在开始之前,我们来谈谈基础结构的工作方式。 参与此过程的实体有 4 个:

  1. Google Play Services
  2. Firebase Cloud Messaging 服务(简称 FCM,构建于旧的 Google Cloud Messaging 之上。)
  3. PlayFab 服务
  4. 客户端应用程序

1. Google Play Services

Google Play Services 使用程序包名称确定您在 Play Market 中的页面。

例如:com.bob.games.matchthree

在 Google Play 中注册时,程序包名称将成为唯一的应用程序 ID,该名称可用于多种用途,例如通过 Play Store 安装和防止假冒。

2. Firebase Cloud Messaging (FCM)

Firebase Cloud Messaging 服务为您提供基于云的系统,用于发送、定向和传送推送通知。

它还允许其他服务(例如 PlayFab)使用 FCM 服务器密钥代表您发送推送通知。

3. PlayFab 服务

然后,PlayFab 服务使用 FCM 服务器密钥将推送通知发送到客户端。

4. 客户端服务

最后,客户端应用程序可能会收到通知并根据需要进行处理。

分成四个部分

因此,我们需要设置 4 个不同的系统。 为此,我们的教程分为 4 个章节,涵盖每个部分的配置。

注意

配置系统的顺序 非常重要。

先决条件

  • 您必须有 Google 帐户。
  • 您必须有 PlayFab 帐户。
  • 使用 Android Asset Studio 通知图标生成器生成的通知图标。

方案

在本教程的这一部分中,我们将组装一个名为 Foo PlayFab App 的应用程序。 这是一个 Android 应用程序,具有以下功能:

  • 它使用 Android 设备 ID 登录 PlayFab。
  • 它接收来自 PlayFab 的推送通知。

我们的程序包名称为 com.foo.playfab.app。

重要

在学习本教程时,请务必使用您自己的程序包名称和作品。

第 1 章:配置 Firebase

可以使用 Firebase 的官方控制台页面开始配置 Firebase。 您将看到一个可以添加新项目的页面。

  • 要执行此操作,请选择 Add project 区域,如下图所示。

Firebase - 添加项目

  • 系统将要求您提供 Project Name(在本教程中,我们使用 Foo PlayFab App,但在按照本教程操作时,请务必 使用您自己的 名称)。

  • 选择 Create Project 按钮前往下一步。

Firebase - 创建项目

您将重定向到 New Project Dashboard

  • 通过选择下图中所示的区域,向项目中添加新的 Android 应用程序

Firebase - 将 Firebase 添加到 Android 应用程序

添加新应用程序需要 3 个步骤。

  1. 首先,您必须提供 Android Package Name。 我们使用的是 com.foo.playfab.app,但在按照本教程操作时,请确保使用你自己的程序包名称

  2. 选择 Register App 按钮前往下一步。

Firebase - 注册 Android 应用程序

第 2 步允许您下载名为 google-services.json 的设置文件。 稍后将在应用程序中使用它来自动配置 Google 服务。

  • 下载文件后,选择 Continue 按钮前往下一步。

Firebase - 添加 Google 设置文件

  1. 最后一步提供有关如何设置构建过程以连接 Firebase 和 Google Play SDK 的信息。

注意

您可以忽略此信息,因为我们将使用 Android Studio 内置的自动工具自动执行此设置。

  • 选择 Finish 按钮继续。

Firebase - 完成添加到 Android 应用程序

  • 添加应用程序后,它将显示在仪表板上。

  • 此时,配置已完成,我们需要提取 FCM 服务器密钥(我们将使用此密钥连接 PlayFab 推送通知)。

  • 转到 Project settings,如下图所示。

Firebase - 项目设置

  • Project settings 中,导航到 Cloud Messaging 选项卡。

  • 找到“服务器密钥”区域(下图中的红框区域)。

  • 复制此密钥并将其存放在安全且易于访问的位置。

Firebase - Cloud Messaging - 服务器密钥

至此,我们已在 Firebase 中完成启用推送通知所需的一切设置。

第 2 章:配置 Google Play Console

准备好应用程序后,您可能需要创建一个 Google 控制台项目来维护 Play Store 产品页面。 下面是创建 GooglePlay 项目并将其关联到 Firebase 项目的过程。

首先访问 Google Play Console 页面并创建一个新项目,如下图所示。

Google Play - Console 页面

  • 分配 Title

注意

在本示例中,我们使用 Foo PlayFab App。 在按照本教程操作时,请确保使用您自己的 作品和程序包名称。

  • 选择 Create 按钮继续。

Google Play - 创建应用程序

  • 此时会打开 Google Play Console Project 页面。

  • 在侧边菜单上选择 Services & APIs

Google Play Console - 服务和 API

  • 此时会打开 Services configuration 页面。
  • 找到 Firebase Cloud Messaging 面板。
  • 选择 Link a Sender ID 按钮,如下图所示。

Google Play - FCM 面板 - 关联发送方 ID

关联 Sender ID

  • 使用在上一章中使用 Firebase 控制台时收到(并保存)的 FCM 服务器密钥。
  • 完成后,选择 Link 按钮,如我们的示例所示。

Google Play - 关联发送方 ID - 添加 FCM API 密钥

  • 请花点时间确认 Google Play Console 中显示的 Sender IDFirebase Console 中的 Sender ID 匹配,如下面的示例所示。

Google Play Console - Firebase Console - 匹配发送方 ID

至此,Google Play Console Project 已成功关联到 Firebase Project

第 3 章:配置 PlayFab 作品

本章旨在介绍如何配置 PlayFab 服务,以便它能够代表您向玩家发送推送通知。

  • 首先,你必须去标题设置菜单中的标题设置

  • 选择“推送通知”选项卡。

  • 对于 Android 选项,请选择“设置”图标。

PlayFab - 推送通知 - Android 设置

  • 将要求你提供 Google 服务器 API 密钥

  • 复制你通过 Firebase 控制台收到的密钥,如下面提供的示例所示。

PlayFab - Firebase 控制台 - 添加服务器 api 密钥

  • 如果一切正常,你将看到一个页面,其中显示 推送消息 活动

PlayFab - 推送通知 - 活动

配置 PlayFab 作品的过程到此结束。

第 4 章:配置 Android Studio 项目

要使用 PlayFab JavaSDK,您需要 PlayFab Client JavaSDK 及其依赖项 Google GSON。

  • 在此处下载 PlayFab Client JavaSDK JAR 库。

  • 根据需要查找 client-sdk-*.jar 及相应的 Java Doc。

  • 下载最新的 Google GSON。

  • 查找 gson-*.jar

  • 准备好前面提到的 .jar 文件。

首先创建一个常规的 Android Studio 项目。

  • 验证 Package name 是否与在按照本教程操作时使用的名称(例如 Firebase 中的名称)相匹配。

    注意

    示例中,我们使用的是 com.foo.playfab.app,但在按照本教程操作时,请牢记使用您自己的程序包名称和作品。

Android Studio - 新项目 - 添加应用程序名称

  • 根据您的需要选择一个 Minimum SDK

  • 然后选择 Next 按钮。

Android Studio - 新项目 - 选择最低 SDK

对于本教程,建议使用 Empty Activity 模板开始。

  • 选择要使用的模板。

  • 然后选择 Next 按钮。

Android Studio - 新项目 - 选择模板

  • 根据需要配置模板。

  • 选择 Finish 按钮。

Android Studio - 新项目 - 完成

打开新创建的项目后:

  • 切换到 Project 选项卡 (1)

注意

在上一章中,您从 Firebase 控制台下载了 google-services.json 配置文件。 请在下一步中使用此文件。

  • 验证此文件是否位于 App 文件夹 (2) 下。
  • 然后,导航到 Tools (3)
  • 选择 Firebase (4),如下面提供的示例所示。

Android Studio - 将配置文件添加到项目中

此时会在窗口右侧打开 Firebase Assistant

  • 找到 Cloud Messaging 文件夹,然后选择 Set up Firebase Cloud Messaging,如下所示。

Android Studio - Firebase Asst. - 设置云消息传送

  • Firebase Notifications Assistant 中,选择 Add FCM to your app (1) 按钮,如下图所示。

  • 此时会打开一个对话框,指示将通过 Gradle 添加新的依赖项。

  • 选择 Accept Changes (2) 授予更改。

    注意

    遗憾的是,Gradle 同步过程 (3) 自动添加的依赖项不正确,将报告失败!

  • 要正确设置依赖项,请使用以下内容替换自动添加的语句:

    implementation 'com.google.firebase:firebase-core:16.0.3
    implementation 'com.google.firebase:firebase-messaging:17.0.0

Android Studio - Firebase Asst. - 将 FCM 添加到应用

完成上述过程后:

  • 验证 Firebase Notifications Assistant 是否指示现在正确设置了依赖关系 (1)

注意

在本章开头,我们获取了必要的 JAR 文件。 通常,构建文件会自动获取这些文件。

  • 要确保这些 JAR 文件列在 app/libs 文件夹 (2) 下,请选择所有文件并在其上单击右键。
  • 然后选择 Add as library... (3),如下面提供的示例所示。

Android Studio - Firebase Asst. - 添加为库

  • 使用 Android Asset Studio 通知图标生成器准备图标并将它们放到 app/src/main/res 中。

  • 在下面显示的示例中,图标名为 ic_stat_blur_on

Android Studio - 添加图标

  • 最后,选择 Rebuild Project

Android Studio - 重新构建项目

现在,我们可以开始实现接收和处理通知的代码了。 我们将修改(并在需要时创建)4 个文件:

  1. app/src/main/AndroidManifest.xml
  2. app/src/main/java/..packagePath../MainActivity.java
  3. app/src/main/java/..packagePath../FooAppFirebaseInstanceIdService.java
  4. app/src/main/java/..packagePath../FooAppFirebaseMessagingService.java

注意

为了快速测试通知,我们尽可能缩短了当前的实现。 有关高质量的最佳实践和更复杂的实现示例,请参阅 FCM 指南

AndroidManifest.xml

在以下代码中,将任何 MY_PACKAGE_IDENTIFIER 占位符替换为您自己的 程序包标识符。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="MY_PACKAGE_IDENTIFIER">
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- The following block enables our custom Firebase Instance ID Service-->
        <service android:name=".FooAppFirebaseInstanceIdService" android:exported="true">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>

        <service
            android:name=".FooAppFirebaseMessagingService" android:exported="true">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>

    </application>

</manifest>

MainActivity.java

应根据您的情况替换代码中的以下占位符。

  • PLAYFAB_TITLE_ID

    • 使用您在 PlayFab Game Manager 中收到的作品 ID。
  • PACKAGE_IDENTIFIER

    • 使用与您的设置匹配的 Java 程序包标识符。
package PACKAGE_IDENTIFIER;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.playfab.PlayFabClientAPI;
import com.playfab.PlayFabClientModels.*;
import com.playfab.PlayFabErrors;
import com.playfab.PlayFabSettings;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    // Invoked when activity is started
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Set PlayFab title
        PlayFabSettings.TitleId = "PLAYFAB_TITLE_ID";

        // Start login operation
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                if(login()) FooAppFirebaseInstanceIdService.setAllowRegisterForPush(true); // Ready to register for push notifications
            }
        });
    }

    public boolean login(){
        LoginWithAndroidDeviceIDRequest request = new LoginWithAndroidDeviceIDRequest();
        request.CreateAccount = true;

        // There are several approaches on getting unique android device id.
        // https://stackoverflow.com/questions/2785485/is-there-a-unique-android-device-id
        request.AndroidDeviceId = "qwerty";

        PlayFabErrors.PlayFabResult<LoginResult> response = PlayFabClientAPI.LoginWithAndroidDeviceID(request);
        if(response.Error != null){
            Log.d("Foo PlayFab App",CompileErrorsFromResult(response.Error));
            return false;
        }
        return true;
    }

    // Utility method to compose an error message out of PlayFab result.
    private static String CompileErrorsFromResult(PlayFabErrors.PlayFabError error) {
        if (error == null)
            return null;

        String errorMessage = "";
        if (error.errorMessage != null)
            errorMessage += error.errorMessage;
        if (error.errorDetails != null)
            for (Map.Entry<String, List<String>> pair : error.errorDetails.entrySet())
                for (String msg : pair.getValue())
                    errorMessage += "\n" + pair.getKey() + ": " + msg;
        return errorMessage;
    }
}

FooAppFirebaseInstanceIdService.java

应根据您的情况替换下面显示的代码中的占位符。

  • PACKAGE_IDENTIFIER
    • 与您的设置匹配的 Java 程序包标识符。
package PACKAGE_IDENTIFIER;

import android.text.TextUtils;
import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
import com.playfab.PlayFabClientAPI;
import com.playfab.PlayFabClientModels;
import com.playfab.PlayFabErrors;
import java.util.List;
import java.util.Map;

public class FooAppFirebaseInstanceIdService extends FirebaseInstanceIdService {

    private static String _token;

    private static boolean _allowRegistration;

    // This is invoked from activity that performs authentication.
    // Once login is complete this method is invoked.
    // If we have a pending token, we use it to register for push notifications
    public static void setAllowRegisterForPush(boolean isAllowed) {
        _allowRegistration = isAllowed;
        if (_allowRegistration && !TextUtils.isEmpty(_token)) {
            registerForPush(_token);
        }
    }

    // Invoked when firebase has fetched a token
    // If we already have logged in, we use new token to register for push
    @Override
    public void onTokenRefresh() {
        _token = FirebaseInstanceId.getInstance().getToken();
        if (_allowRegistration && !TextUtils.isEmpty(_token)) {
            registerForPush(_token);
        }
    }


    private static void registerForPush(String token) {
        PlayFabClientModels.AndroidDevicePushNotificationRegistrationRequest request = new PlayFabClientModels.AndroidDevicePushNotificationRegistrationRequest();
        request.DeviceToken = token;

        PlayFabErrors.PlayFabResult<PlayFabClientModels.AndroidDevicePushNotificationRegistrationResult> response = PlayFabClientAPI.AndroidDevicePushNotificationRegistration(request);

        if (response.Error != null) {
            Log.d("Foo PlayFab App", CompileErrorsFromResult(response.Error));
        }
    }

    // Utility method to compose an error message out of PlayFab result.
    private static String CompileErrorsFromResult(PlayFabErrors.PlayFabError error) {
        if (error == null)
            return null;

        String errorMessage = "";
        if (error.errorMessage != null)
            errorMessage += error.errorMessage;
        if (error.errorDetails != null)
            for (Map.Entry<String, List<String>> pair : error.errorDetails.entrySet())
                for (String msg : pair.getValue())
                    errorMessage += "\n" + pair.getKey() + ": " + msg;
        return errorMessage;
    }

}

FooAppFirebaseMessagingService.java

应根据您的情况替换下面显示的代码中的占位符。

  • PACKAGE_IDENTIFIER
    • 与您的设置匹配的 Java 程序包标识符。
package com.foo.playfab.app;

import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class FooAppFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage message) {
        // Intercept the message here
        Log.d("Foo PlayFab App","Message received: "+message.getNotification().getBody());
    }
}

测试

此时,您应该能够将应用程序部署到设备了。

  • 启动应用程序后,它将自动登录并注册推送通知。

  • 在设备上选择 Home 按钮以最小化应用程序。 这很重要,因为这让我们能够测试到达系统托盘的通知。

  • 接下来,转到 PlayFab 作品 Game Manager 页面,然后使用仪表板找到最新的推送注册

  • 选择玩家 ID (1)

PlayFab - PlayStream - 事件日志

这将打开此玩家的发送推送通知页面。

  • 选择 Send Push Notification 按钮 (1)

  • 键入 Title (2)

  • 输入消息正文 (3)

  • 通过选择 Send Push Notification 按钮 (4) 提交更改。

PlayFab - 发送推送通知

  • 验证消息是否到达您的设备。

Android 应用程序 - 接收 PlayFab 推送通知

如果消息到达,将成功传递到您的应用程序。

至此,您已成功实现集成。 在应用程序实际运行期间,可以使用 FooAppFirebaseMessagingService 处理传入消息。