golang实现Google云消息推送服务插件库gcm的使用

golang实现Google云消息推送服务插件库gcm的使用

概述

Android SDK提供了一个方便的库(com.google.android.gcm.server),它极大地简化了基于Java的应用服务器与Google GCM服务器之间的交互。然而,Google没有为Java以外的语言(特别是Go语言)实现的应用服务器提供太多支持。gcm包有助于填补这一空白,提供了一个简单的接口来发送GCM消息,并在服务不可用时自动重试请求。

安装

要安装gcm,使用go get命令:

go get github.com/Aorioli/gcm

导入gcm包:

import "github.com/Aorioli/gcm"

使用示例

以下是一个快速示例,展示如何向GCM服务器发送消息:

package main

import (
	"fmt"
	"net/http"
	"time"

	"github.com/Aorioli/gcm"
)

func main() {
	// 创建要发送的消息
	data := map[string]interface{}{"score": "5x1", "time": "15:10"}
	regIDs := []string{"4", "8", "15", "16", "23", "42"}
	m := new(gcm.Message)
	m.RegistrationIDs = regIDs
	m.Data = data

	// 创建一个Sender来发送消息
	sender := gcm.NewSender("sample_api_key", 2, time.Minute)

	// 发送消息并最多重试两次接收响应
	response, err := sender.Send(m)
	if err != nil {
		fmt.Println("Failed to send message:", err)
		return
	}

	/* ... */
}

代码说明

  1. 创建消息

    • data变量定义了要发送的数据内容
    • regIDs是目标设备的注册ID数组
    • gcm.Message结构体用于封装消息内容
  2. 创建Sender

    • gcm.NewSender创建一个新的发送者实例
    • 参数说明:
      • sample_api_key: 你的GCM API密钥
      • 2: 最大重试次数
      • time.Minute: 重试间隔时间
  3. 发送消息

    • sender.Send(m)发送消息并返回响应
    • 错误处理检查发送是否成功

贡献

欢迎贡献代码:

  1. 创建一个issue描述bug、增强功能或其他问题
  2. Fork仓库,在master以外的分支上进行更改
  3. 创建pull请求

更多关于golang实现Google云消息推送服务插件库gcm的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现Google云消息推送服务插件库gcm的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang实现Google云消息推送服务(GCM)插件库

Google云消息推送服务(GCM)是Google提供的移动消息推送服务,后来被Firebase Cloud Messaging(FCM)取代。不过对于仍需要与GCM交互的系统,我们可以使用Go语言实现相关功能。

GCM基本概念

GCM(Google Cloud Messaging)允许服务器向Android设备发送消息,主要特点包括:

  • 支持向单个设备或设备组发送消息
  • 消息大小限制为4KB
  • 支持下游消息(服务器到设备)和上游消息(设备到服务器)

Go实现GCM客户端

下面是一个完整的GCM客户端实现示例:

package gcm

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
)

const (
	gcmSendEndpoint = "https://android.googleapis.com/gcm/send"
)

// Message represents a GCM message.
type Message struct {
	RegistrationIDs       []string               `json:"registration_ids"`
	CollapseKey           string                 `json:"collapse_key,omitempty"`
	Priority              string                 `json:"priority,omitempty"` // "normal" or "high"
	ContentAvailable      bool                   `json:"content_available,omitempty"`
	DelayWhileIdle        bool                   `json:"delay_while_idle,omitempty"`
	TimeToLive            int                    `json:"time_to_live,omitempty"`
	RestrictedPackageName string                 `json:"restricted_package_name,omitempty"`
	DryRun                bool                   `json:"dry_run,omitempty"`
	Data                  map[string]interface{} `json:"data,omitempty"`
	Notification          *Notification          `json:"notification,omitempty"`
}

// Notification represents a GCM notification payload.
type Notification struct {
	Title        string `json:"title,omitempty"`
	Body         string `json:"body,omitempty"`
	Icon         string `json:"icon,omitempty"`
	Sound        string `json:"sound,omitempty"`
	Badge        string `json:"badge,omitempty"`
	Tag          string `json:"tag,omitempty"`
	Color        string `json:"color,omitempty"`
	ClickAction  string `json:"click_action,omitempty"`
	BodyLocKey   string `json:"body_loc_key,omitempty"`
	BodyLocArgs  string `json:"body_loc_args,omitempty"`
	TitleLocKey  string `json:"title_loc_key,omitempty"`
	TitleLocArgs string `json:"title_loc_args,omitempty"`
}

// Response represents a GCM response.
type Response struct {
	MulticastID  int64    `json:"multicast_id"`
	Success      int      `json:"success"`
	Failure      int      `json:"failure"`
	CanonicalIDs int      `json:"canonical_ids"`
	Results      []Result `json:"results"`
}

// Result represents a GCM message result for a single device.
type Result struct {
	MessageID      string `json:"message_id"`
	RegistrationID string `json:"registration_id"`
	Error          string `json:"error"`
}

// Client represents a GCM client.
type Client struct {
	apiKey string
	client *http.Client
}

// NewClient creates a new GCM client.
func NewClient(apiKey string, httpClient *http.Client) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	return &Client{
		apiKey: apiKey,
		client: httpClient,
	}
}

// Send sends a GCM message.
func (c *Client) Send(msg *Message) (*Response, error) {
	data, err := json.Marshal(msg)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal message: %v", err)
	}

	req, err := http.NewRequest("POST", gcmSendEndpoint, bytes.NewBuffer(data))
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %v", err)
	}

	req.Header.Set("Authorization", "key="+c.apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := c.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to send request: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
	}

	var response Response
	if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
		return nil, fmt.Errorf("failed to decode response: %v", err)
	}

	return &response, nil
}

使用示例

package main

import (
	"fmt"
	"log"

	"./gcm" // 替换为你的实际包路径
)

func main() {
	// 初始化GCM客户端
	apiKey := "YOUR_GCM_API_KEY" // 从Google开发者控制台获取
	client := gcm.NewClient(apiKey, nil)

	// 准备消息
	msg := &gcm.Message{
		RegistrationIDs: []string{"device_registration_id_1", "device_registration_id_2"},
		Priority:        "high",
		Notification: &gcm.Notification{
			Title: "Hello GCM",
			Body:  "This is a test message from GCM",
		},
		Data: map[string]interface{}{
			"key1": "value1",
			"key2": "value2",
		},
	}

	// 发送消息
	response, err := client.Send(msg)
	if err != nil {
		log.Fatalf("Failed to send message: %v", err)
	}

	// 处理响应
	fmt.Printf("Success: %d, Failure: %d\n", response.Success, response.Failure)
	for i, result := range response.Results {
		if result.Error != "" {
			fmt.Printf("Error for device %d: %s\n", i, result.Error)
		} else {
			fmt.Printf("Message sent to device %d: %s\n", i, result.MessageID)
			if result.RegistrationID != "" {
				fmt.Printf("New registration ID: %s\n", result.RegistrationID)
			}
		}
	}
}

注意事项

  1. API密钥:需要从Google开发者控制台获取GCM API密钥
  2. 设备注册ID:每个Android设备在安装应用并注册GCM服务后会获得唯一的注册ID
  3. 响应处理:需要检查响应中的CanonicalIDs,如果有新的注册ID,应该更新服务器上的记录
  4. 错误处理:常见的错误包括:
    • “InvalidRegistration” - 注册ID无效
    • “NotRegistered” - 设备已取消注册
    • “MessageTooBig” - 消息超过4KB限制
  5. 迁移到FCM:Google推荐新项目使用FCM而不是GCM

高级功能

如果需要更复杂的功能,可以考虑:

  1. 重试机制:对于暂时性错误实现指数退避重试
  2. 批量发送:将大量设备分批发送以避免超时
  3. 结果持久化:将发送结果存储到数据库供后续分析
  4. 设备组管理:实现设备组的创建、添加和删除功能

虽然GCM已被FCM取代,但对于维护旧系统或需要与遗留代码交互的场景,这个Go实现仍然非常有用。

回到顶部