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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:31:08