You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

安卓电影评论应用:如何用One Signal向Firebase用户推送新电影通知?

解决方案:管理员添加新电影时向所有Firebase用户发送OneSignal通知

嘿,我来帮你搞定这个需求!要实现管理员新增电影时自动给所有Firebase用户推送OneSignal通知,你可以按照以下分步流程来操作:

1. 完成OneSignal与Firebase的基础整合

首先得确保你的项目同时对接了Firebase和OneSignal,并且两者能协同工作:

  • 在OneSignal后台的Settings > Platforms > Android中,填入你的Firebase服务器密钥(可以在Firebase控制台的项目设置 > 云消息传递里找到),这样OneSignal就能通过FCM发送通知到安卓设备。
  • 在你的安卓项目中集成OneSignal SDK:
    • 把OneSignal的依赖添加到build.gradle(Module级别):
      dependencies {
        implementation 'com.onesignal:OneSignal:[4.0.0, 4.99.99]'
      }
      
    • 在Application类或者启动Activity中初始化OneSignal:
      import com.onesignal.OneSignal;
      
      public class MyApp extends Application {
        private static final String ONESIGNAL_APP_ID = "你的OneSignal App ID";
      
        @Override
        public void onCreate() {
          super.onCreate();
          // 初始化OneSignal
          OneSignal.initWithContext(this);
          OneSignal.setAppId(ONESIGNAL_APP_ID);
          // 请求通知权限(Android 13+需要)
          OneSignal.promptForPushNotifications();
        }
      }
      

2. 将用户的OneSignal设备令牌存储到Firebase

要给所有用户发通知,你需要收集每个用户的OneSignal设备令牌,并和Firebase用户ID绑定存储起来:

  • 当用户通过Firebase Auth登录后,获取他们的OneSignal设备令牌,并存入Firebase Firestore或实时数据库:
    // 获取当前Firebase用户
    FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
    if (currentUser != null) {
      // 获取OneSignal设备令牌
      OneSignal.getDeviceState().addOnSuccessListener(deviceState -> {
        String playerId = deviceState.getUserId(); // 这就是OneSignal的设备令牌(Player ID)
        // 将Player ID存入Firestore,比如存在"users"集合下,文档ID为用户UID
        FirebaseFirestore.getInstance()
          .collection("users")
          .document(currentUser.getUid())
          .update("onesignal_player_id", playerId)
          .addOnSuccessListener(aVoid -> Log.d("OneSignal", "Player ID已存储"))
          .addOnFailureListener(e -> Log.e("OneSignal", "存储Player ID失败", e));
      });
    }
    
    注意:如果是新用户注册,记得在注册成功后就执行这个存储逻辑。

3. 管理员添加电影时触发通知发送

这一步推荐用Firebase Cloud Functions(更安全,避免在客户端暴露敏感的OneSignal API密钥),也可以在管理员端安卓代码中实现(不推荐,存在密钥泄露风险):

方式一:用Firebase Cloud Functions监听电影新增事件

当管理员在Firestore中添加新的电影文档时,自动触发云函数,获取所有用户的OneSignal Player ID,调用OneSignal API发送通知:

  1. 初始化Firebase Cloud Functions项目,然后创建一个云函数:
    const functions = require("firebase-functions");
    const admin = require("firebase-admin");
    const axios = require("axios");
    
    admin.initializeApp();
    
    // 监听movies集合的新增文档
    exports.sendNewMovieNotification = functions.firestore
      .document("movies/{movieId}")
      .onCreate(async (snap, context) => {
        const newMovie = snap.data();
        const movieTitle = newMovie.title;
    
        // 获取所有用户的OneSignal Player ID
        const usersSnapshot = await admin.firestore().collection("users").get();
        const playerIds = [];
        usersSnapshot.forEach(doc => {
          const playerId = doc.data().onesignal_player_id;
          if (playerId) {
            playerIds.push(playerId);
          }
        });
    
        if (playerIds.length === 0) {
          functions.logger.info("没有可发送通知的用户");
          return null;
        }
    
        // 调用OneSignal API发送通知
        const onesignalApiKey = "你的OneSignal REST API密钥"; // 在OneSignal后台的Settings > Keys & IDs里获取
        const onesignalAppId = "你的OneSignal App ID";
    
        try {
          await axios.post(
            "https://onesignal.com/api/v1/notifications",
            {
              app_id: onesignalAppId,
              include_player_ids: playerIds,
              contents: { en: `新电影上线啦:${movieTitle},快来评论评分吧!` },
              headings: { en: "新电影通知" }
            },
            {
              headers: {
                "Content-Type": "application/json",
                "Authorization": `Basic ${onesignalApiKey}`
              }
            }
          );
          functions.logger.info("通知发送成功");
          return null;
        } catch (error) {
          functions.logger.error("发送通知失败", error);
          return null;
        }
      });
    
  2. 部署这个云函数到Firebase,这样每次管理员添加新电影到movies集合,就会自动触发通知发送。

方式二:在管理员端安卓代码中触发通知(不推荐)

如果你暂时不想用云函数,也可以在管理员的安卓端代码中调用OneSignal API,但一定要注意不要把OneSignal API密钥硬编码在客户端:

// 管理员添加电影成功后,调用这个方法发送通知
private void sendNewMovieNotification(String movieTitle) {
  // 从Firebase获取所有用户的Player ID(这里需要查询users集合)
  FirebaseFirestore.getInstance().collection("users")
    .get()
    .addOnSuccessListener(querySnapshot -> {
      List<String> playerIds = new ArrayList<>();
      for (QueryDocumentSnapshot doc : querySnapshot) {
        String playerId = doc.getString("onesignal_player_id");
        if (playerId != null) {
          playerIds.add(playerId);
        }
      }

      if (playerIds.isEmpty()) {
        Toast.makeText(this, "没有用户可通知", Toast.LENGTH_SHORT).show();
        return;
      }

      // 构建OneSignal通知请求
      JSONObject payload = new JSONObject();
      try {
        payload.put("app_id", "你的OneSignal App ID");
        payload.put("include_player_ids", new JSONArray(playerIds));
        JSONObject contents = new JSONObject();
        contents.put("en", "新电影上线啦:" + movieTitle + ",快来评论评分吧!");
        payload.put("contents", contents);
        JSONObject headings = new JSONObject();
        headings.put("en", "新电影通知");
        payload.put("headings", headings);

        // 发送POST请求到OneSignal API
        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(payload.toString(), MediaType.get("application/json; charset=utf-8"));
        Request request = new Request.Builder()
          .url("https://onesignal.com/api/v1/notifications")
          .post(body)
          .addHeader("Authorization", "Basic 你的OneSignal REST API密钥")
          .addHeader("Content-Type", "application/json")
          .build();

        client.newCall(request).enqueue(new Callback() {
          @Override
          public void onFailure(@NonNull Call call, @NonNull IOException e) {
            Log.e("Notification", "发送失败", e);
            runOnUiThread(() -> Toast.makeText(AdminActivity.this, "通知发送失败", Toast.LENGTH_SHORT).show());
          }

          @Override
          public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
            if (response.isSuccessful()) {
              runOnUiThread(() -> Toast.makeText(AdminActivity.this, "通知发送成功", Toast.LENGTH_SHORT).show());
            } else {
              Log.e("Notification", "响应失败:" + response.body().string());
              runOnUiThread(() -> Toast.makeText(AdminActivity.this, "通知发送失败", Toast.LENGTH_SHORT).show());
            }
          }
        });
      } catch (JSONException e) {
        e.printStackTrace();
      }
    })
    .addOnFailureListener(e -> {
      Log.e("Firestore", "获取用户失败", e);
      Toast.makeText(this, "获取用户列表失败", Toast.LENGTH_SHORT).show();
    });
}

关键注意事项

  • API密钥保密:OneSignal的REST API密钥一定要保密,绝对不能硬编码在安卓客户端里,用Firebase Cloud Functions是最安全的方式。
  • 权限处理:Android 13及以上需要申请POST_NOTIFICATIONS权限,记得在Manifest中添加权限,并在运行时请求。
  • 令牌更新:用户的OneSignal Player ID可能会变化(比如卸载重装应用),所以最好监听OneSignal的令牌更新事件,及时同步到Firebase:
    OneSignal.addSubscriptionObserver((stateChanges) -> {
      if (stateChanges.getFrom().getUserId() != null && !stateChanges.getFrom().getUserId().equals(stateChanges.getTo().getUserId())) {
        // 令牌更新了,同步到Firebase
        FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
        if (currentUser != null) {
          FirebaseFirestore.getInstance()
            .collection("users")
            .document(currentUser.getUid())
            .update("onesignal_player_id", stateChanges.getTo().getUserId());
        }
      }
    });
    

内容的提问来源于stack exchange,提问作者MissAmna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:48:08