├── README.markdown ├── example └── send.go ├── gcm.go └── message.go /README.markdown: -------------------------------------------------------------------------------- 1 | A [GCM(Google Cloud Messaging)](http://developer.android.com/guide/google/gcm/index.html) Client for golang 2 | =========================================================================================================== 3 | 4 | Usage 5 | ----- 6 | 7 | example/send.go 8 | -------------------------------------------------------------------------------- /example/send.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/googollee/go-gcm" 6 | ) 7 | 8 | func main() { 9 | client := gcm.New("your Google APIs key") 10 | 11 | load := gcm.NewMessage("your device id") 12 | load.AddRecipient("abc") 13 | load.SetPayload("data", "1") 14 | load.CollapseKey = "demo" 15 | load.DelayWhileIdle = true 16 | load.TimeToLive = 10 17 | 18 | resp, err := client.Send(load) 19 | 20 | fmt.Printf("id: %+v\n", resp) 21 | fmt.Println("err:", err) 22 | fmt.Println("err index:", resp.ErrorIndexes()) 23 | fmt.Println("reg index:", resp.RefreshIndexes()) 24 | } 25 | -------------------------------------------------------------------------------- /gcm.go: -------------------------------------------------------------------------------- 1 | // Package go-gcm can push a message to android phone through [Google Cloud Messaging(GCM)](http://developer.android.com/guide/google/gcm/index.html) 2 | package gcm 3 | 4 | import ( 5 | "bytes" 6 | "crypto/tls" 7 | "encoding/json" 8 | "fmt" 9 | "io/ioutil" 10 | "net/http" 11 | ) 12 | 13 | var GCMSendApi = "https://android.googleapis.com/gcm/send" 14 | 15 | type Client struct { 16 | key string 17 | http *http.Client 18 | } 19 | 20 | // Create a client with key. Grab the key from [Google APIs Console](https://code.google.com/apis/console) 21 | func New(key string) *Client { 22 | return &Client{ 23 | key: key, 24 | http: new(http.Client), 25 | } 26 | } 27 | 28 | func (c *Client) Send(message *Message) (*Response, error) { 29 | j, err := json.Marshal(message) 30 | if err != nil { 31 | return nil, err 32 | } 33 | request, err := http.NewRequest("POST", GCMSendApi, bytes.NewBuffer(j)) 34 | if err != nil { 35 | return nil, err 36 | } 37 | request.Header.Add("Authorization", fmt.Sprintf("key=%s", c.key)) 38 | request.Header.Add("Content-Type", "application/json") 39 | 40 | resp, err := c.http.Do(request) 41 | if err != nil { 42 | return nil, err 43 | } 44 | defer resp.Body.Close() 45 | 46 | return responseReply(resp) 47 | } 48 | 49 | func httpClientWithoutSecureVerify() *http.Client { 50 | tr := &http.Transport{ 51 | TLSClientConfig: &tls.Config{ 52 | InsecureSkipVerify: true, 53 | }, 54 | } 55 | return &http.Client{Transport: tr} 56 | } 57 | 58 | func responseReply(resp *http.Response) (*Response, error) { 59 | body, err := ioutil.ReadAll(resp.Body) 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | if resp.StatusCode != 200 { 65 | return nil, fmt.Errorf("%s %s", resp.Status, string(body)) 66 | } 67 | 68 | ret := new(Response) 69 | err = json.Unmarshal(body, ret) 70 | return ret, err 71 | } 72 | -------------------------------------------------------------------------------- /message.go: -------------------------------------------------------------------------------- 1 | package gcm 2 | 3 | // The field meaning explained at [GCM Architectural Overview](http://developer.android.com/guide/google/gcm/gcm.html#send-msg) 4 | type Message struct { 5 | RegistrationIDs []string `json:"registration_ids"` 6 | CollapseKey string `json:"collapse_key,omitempty"` 7 | DelayWhileIdle bool `json:"delay_while_idle,omitempty"` 8 | Data map[string]string `json:"data,omitempty"` 9 | TimeToLive int `json:"time_to_live,omitempty"` 10 | } 11 | 12 | func NewMessage(ids ...string) *Message { 13 | return &Message{ 14 | RegistrationIDs: ids, 15 | Data: make(map[string]string), 16 | } 17 | } 18 | 19 | func (m *Message) AddRecipient(ids ...string) { 20 | m.RegistrationIDs = append(m.RegistrationIDs, ids...) 21 | } 22 | 23 | func (m *Message) SetPayload(key string, value string) { 24 | if m.Data == nil { 25 | m.Data = make(map[string]string) 26 | } 27 | m.Data[key] = value 28 | } 29 | 30 | // The field meaning explained at [GCM Architectural Overview](http://developer.android.com/guide/google/gcm/gcm.html#send-msg) 31 | type Response struct { 32 | MulticastID int64 `json:"multicast_id"` 33 | Success int `json:"success"` 34 | Failure int `json:"failure"` 35 | CanonicalIDs int `json:"canonical_ids"` 36 | Results []struct { 37 | MessageID string `json:"message_id"` 38 | RegistrationID string `json:"registration_id"` 39 | Error string `json:"error"` 40 | } `json:"results"` 41 | } 42 | 43 | // Return the indexes of succeed sent registration ids 44 | func (r *Response) SuccessIndexes() []int { 45 | ret := make([]int, 0, r.Success) 46 | for i, result := range r.Results { 47 | if result.Error == "" { 48 | ret = append(ret, i) 49 | } 50 | } 51 | return ret 52 | } 53 | 54 | // Return the indexes of failed sent registration ids 55 | func (r *Response) ErrorIndexes() []int { 56 | ret := make([]int, 0, r.Failure) 57 | for i, result := range r.Results { 58 | if result.Error != "" { 59 | ret = append(ret, i) 60 | } 61 | } 62 | return ret 63 | } 64 | 65 | // Return the indexes of registration ids which need update 66 | func (r *Response) RefreshIndexes() []int { 67 | ret := make([]int, 0, r.CanonicalIDs) 68 | for i, result := range r.Results { 69 | if result.RegistrationID != "" { 70 | ret = append(ret, i) 71 | } 72 | } 73 | return ret 74 | } 75 | --------------------------------------------------------------------------------