安卓电影评论应用:如何用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(); } }
- 把OneSignal的依赖添加到
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发送通知:
- 初始化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; } }); - 部署这个云函数到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
相关产品推荐
相关产品推荐

