如何在Android Studio中通过按钮利用OneSignal设备令牌跨设备发送通知
Android通过按钮触发OneSignal设备间通知的正确实现
首先明确:OneSignal不允许在客户端直接使用REST API密钥发送通知(密钥会被反编译泄露,导致滥用),生产环境必须通过后端服务中转调用OneSignal API。以下是完整实现步骤:
一、后端服务实现(以Java Spring Boot为例)
1. 依赖配置(Maven)
添加OkHttp依赖用于发送HTTP请求:
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.10.0</version> </dependency>
2. 编写OneSignal通知发送工具类
import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import org.json.JSONObject; import java.io.IOException; public class OneSignalSender { private static final String ONESIGNAL_API = "https://onesignal.com/api/v1/notifications"; private static final String REST_API_KEY = "你的OneSignal App REST API密钥"; // 在控制台App Settings获取 private static final String APP_ID = "你的OneSignal App ID"; public static void sendToDevice(String targetPlayerId, String title, String content) throws IOException { OkHttpClient client = new OkHttpClient(); // 构造通知JSON payload JSONObject payload = new JSONObject(); payload.put("app_id", APP_ID); JSONObject contents = new JSONObject(); contents.put("en", content); // 支持多语言,比如添加"zh"键对应中文内容 JSONObject headings = new JSONObject(); headings.put("en", title); payload.put("contents", contents); payload.put("headings", headings); payload.put("include_player_ids", new String[]{targetPlayerId}); // 指定目标设备ID RequestBody body = RequestBody.create( payload.toString(), MediaType.parse("application/json; charset=utf-8") ); Request request = new Request.Builder() .url(ONESIGNAL_API) .post(body) .addHeader("Authorization", "Basic " + REST_API_KEY) .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("请求失败:" + response.code()); } } }
3. 暴露后端接口供客户端调用
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; @RestController public class NotificationController { @PostMapping("/send-notification") public String sendNotification( @RequestParam String targetId, @RequestParam String title, @RequestParam String content) { try { OneSignalSender.sendToDevice(targetId, title, content); return "发送成功"; } catch (IOException e) { e.printStackTrace(); return "发送失败:" + e.getMessage(); } } }
二、Android客户端按钮点击实现
1. 添加依赖(Module级build.gradle)
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
2. 按钮点击事件代码
SendNotificationBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 目标设备的player_id:需提前从接收设备获取并存储(比如后端数据库、用户输入) String targetPlayerId = "接收设备的OneSignal用户ID"; String notificationTitle = "好友消息"; String notificationContent = "这是来自另一设备的测试通知"; OkHttpClient client = new OkHttpClient(); // 构造表单请求参数 RequestBody formBody = new FormBody.Builder() .add("targetId", targetPlayerId) .add("title", notificationTitle) .add("content", notificationContent) .build(); Request request = new Request.Builder() .url("你的后端接口地址,例如http://xxx.xxx.xxx.xxx:8080/send-notification") .post(formBody) .build(); // 异步发送请求 client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { e.printStackTrace(); // 主线程更新UI提示失败 runOnUiThread(() -> Toast.makeText(MainActivity.this, "通知发送失败", Toast.LENGTH_SHORT).show()); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { runOnUiThread(() -> { if (response.isSuccessful()) { Toast.makeText(MainActivity.this, "通知发送成功", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "通知发送失败", Toast.LENGTH_SHORT).show(); } }); } }); } });
三、关键注意事项
- 绝对禁止在客户端硬编码REST API密钥,这会导致密钥泄露,被他人恶意利用发送垃圾通知。
- 目标设备的
player_id获取方式:在接收设备的代码中调用OneSignal.getDeviceState().getUserId()获取,然后上传到后端存储。 - 确保后端服务器能访问OneSignal的API地址,无防火墙或网络限制。
- 测试时核对OneSignal控制台的App ID、REST API密钥是否正确,目标
player_id是否有效。
临时测试方案(仅用于本地调试,禁止生产环境使用)
如果不想搭建后端,可临时在客户端直接调用OneSignal API,但测试后必须删除代码中的密钥:
SendNotificationBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String targetPlayerId = "接收设备ID"; String restApiKey = "你的REST API密钥"; String appId = "你的App ID"; OkHttpClient client = new OkHttpClient(); JSONObject payload = new JSONObject(); try { payload.put("app_id", appId); payload.put("contents", new JSONObject().put("en", "测试内容")); payload.put("headings", new JSONObject().put("en", "测试标题")); payload.put("include_player_ids", new String[]{targetPlayerId}); } catch (JSONException e) { e.printStackTrace(); } RequestBody body = RequestBody.create( payload.toString(), MediaType.parse("application/json; charset=utf-8") ); Request request = new Request.Builder() .url("https://onesignal.com/api/v1/notifications") .post(body) .addHeader("Authorization", "Basic " + restApiKey) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { runOnUiThread(() -> Toast.makeText(MainActivity.this, "发送失败", Toast.LENGTH_SHORT).show()); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { runOnUiThread(() -> { Toast.makeText(MainActivity.this, response.isSuccessful() ? "发送成功" : "发送失败", Toast.LENGTH_SHORT).show(); }); } }); } });
内容的提问来源于stack exchange,提问作者Uburundi Soft
相关产品推荐
相关产品推荐

