speedy_gcm 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +20 -0
- data/README.md +80 -0
- data/Rakefile +1 -0
- data/lib/speedy_gcm/version.rb +3 -0
- data/lib/speedy_gcm.rb +85 -0
- data/speedy_gcm.gemspec +18 -0
- data/test/helper.rb +18 -0
- data/test/test_speedy_gcm.rb +178 -0
- metadata +59 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Amro Mousa, (c) 2011 Brandon Keene, (c) 2012 Sandeep Ghael, (c) 2012 Keith Ballinger
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# Speedy GCM
|
2
|
+
|
3
|
+
Speedy GCM sends push notifications to Android devices via Google's [GCM](http://developer.android.com/guide/google/gcm/index.html) (Google Cloud Messaging for Android).
|
4
|
+
|
5
|
+
Pull requests are welcome!
|
6
|
+
|
7
|
+
# What is this GCM gem more awesome?
|
8
|
+
|
9
|
+
- Simple Ruby implementation.
|
10
|
+
- No dependencies.
|
11
|
+
- Implemented against the JSON based service for GCM. If you need text/plain support look elsewhere.
|
12
|
+
- Validation of your message options.
|
13
|
+
- Test coverage
|
14
|
+
- Simple way to test your android client from the command line
|
15
|
+
|
16
|
+
|
17
|
+
##Installation
|
18
|
+
|
19
|
+
$ gem install speedy_gcm
|
20
|
+
|
21
|
+
|
22
|
+
##Requirements
|
23
|
+
|
24
|
+
An Android device running 2.2 or newer, its registration token, and a Google account registered for gcm.
|
25
|
+
|
26
|
+
Also, make sure 'net/http' and 'net/https' are available:
|
27
|
+
|
28
|
+
require "net/http"
|
29
|
+
require "net/https"
|
30
|
+
|
31
|
+
The 'shoulda' gem is required for testing:
|
32
|
+
|
33
|
+
$ gem install 'shoulda'
|
34
|
+
|
35
|
+
##Compatibility
|
36
|
+
|
37
|
+
Speedy_GCM will work with Rails 3.x & Ruby 1.9x. It has not been tested on previous versions or Rails or Ruby, and may or may not work with those versions.
|
38
|
+
|
39
|
+
|
40
|
+
##Usage
|
41
|
+
|
42
|
+
For a Rails app, a good place to put the following would be in config/initializers/speedy_gcm.rb :
|
43
|
+
|
44
|
+
GCM_API_KEY = "YOUR API KEY"
|
45
|
+
|
46
|
+
SpeedyGCM::API.set_account(GCM_API_KEY)
|
47
|
+
|
48
|
+
Then, where you want to make a GCM call in your code, create an message_options hash and pass it to send_notification():
|
49
|
+
|
50
|
+
message_options = {
|
51
|
+
:registration_ids => [<array of registration ids>],
|
52
|
+
# optional parameters below. Read the docs here: http://developer.android.com/guide/google/gcm/gcm.html#send-msg
|
53
|
+
:collapse_key => "foobar",
|
54
|
+
:data => { :score => "3x1" },
|
55
|
+
:delay_while_idle => false,
|
56
|
+
:time_to_live => 1
|
57
|
+
}
|
58
|
+
|
59
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
60
|
+
|
61
|
+
puts response[:code] # some http response code like 200
|
62
|
+
puts response[:data] # usually nil is returned
|
63
|
+
|
64
|
+
Note: there are blocking calls in both .set_account() and .send_notification(). You should use an async queue like [Sidekiq](https://github.com/mperham/sidekiq) to ensure a non-blocking code path in your application code, particularly for the .send_notification() call.
|
65
|
+
|
66
|
+
|
67
|
+
##Testing
|
68
|
+
|
69
|
+
To test, first fill out these variables in test/test_speedy_gcm.rb:
|
70
|
+
|
71
|
+
GCM_API_KEY = "TODO - Fill in with your GCM API Key"
|
72
|
+
TEST_PHONE_GCM_REGISTRATION_ID = "TODO - Fill in with some valid GCM Registration ID"
|
73
|
+
|
74
|
+
then run:
|
75
|
+
|
76
|
+
$ ruby test/test_speedy_gcm.rb
|
77
|
+
|
78
|
+
##Copyrights
|
79
|
+
|
80
|
+
* See LICENSE.txt for details.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/lib/speedy_gcm.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require "speedy_gcm/version"
|
2
|
+
|
3
|
+
module SpeedyGCM
|
4
|
+
|
5
|
+
# message_options
|
6
|
+
#
|
7
|
+
# :registration_ids
|
8
|
+
# A string array with the list of devices (registration IDs) receiving the message. It must contain at least 1 and at most 1000 registration IDs. To send a multicast message, you must use JSON. For sending a single message to a single device, you could use a JSON object with just 1 registration id, or plain text (see below). Required.
|
9
|
+
#
|
10
|
+
# :collapse_key
|
11
|
+
# An arbitrary string (such as "Updates Available") that is used to collapse a group of like messages when the device is offline, so that only the last message gets sent to the client. This is intended to avoid sending too many messages to the phone when it comes back online. Note that since there is no guarantee of the order in which messages get sent, the "last" message may not actually be the last message sent by the application server. See Advanced Topics for more discussion of this topic. Optional, unless you are using the time_to_live parameter—in that case, you must also specify a collapse_key.
|
12
|
+
#
|
13
|
+
# :data
|
14
|
+
# A JSON object whose fields represents the key-value pairs of the message's payload data. If present, the payload data it will be included in the Intent as application data, with the key being the extra's name. For instance, "data":{"score":"3x1"} would result in an intent extra named score whose value is the string 3x1. There is no limit on the number of key/value pairs, though there is a limit on the total size of the message (4kb). The values could be any JSON object, but we recommend using strings, since the values will be converted to strings in the GCM server anyway. If you want to include objects or other non-string data types (such as integers or booleans), you have to do the conversion to string yourself. Also note that the key cannot be a reserved word (from or any word starting with google.). To complicate things slightly, there are some reserved words (such as collapse_key) that are technically allowed in payload data. However, if the request also contains the word, the value in the request will overwrite the value in the payload data. Hence using words that are defined as field names in this table is not recommended, even in cases where they are technically allowed. Optional.
|
15
|
+
#
|
16
|
+
# :delay_while_idle
|
17
|
+
# If included, indicates that the message should not be sent immediately if the device is idle. The server will wait for the device to become active, and then only the last message for each collapse_key value will be sent. Optional. The default value is false, and must be a JSON boolean.
|
18
|
+
#
|
19
|
+
# :time_to_live
|
20
|
+
# How long (in seconds) the message should be kept on GCM storage if the device is offline. Optional (default time-to-live is 4 weeks, and must be set as a JSON number). If you use this parameter, you must also specify a collapse_key.
|
21
|
+
|
22
|
+
class API
|
23
|
+
PUSH_URL = 'https://android.googleapis.com/gcm/send'
|
24
|
+
|
25
|
+
class << self
|
26
|
+
|
27
|
+
def set_account(api_key)
|
28
|
+
@api_key = api_key
|
29
|
+
end
|
30
|
+
|
31
|
+
def send_notification(message_opts)
|
32
|
+
headers = { "Content-Type" => "application/json",
|
33
|
+
"Authorization" => "key=#{@api_key}" }
|
34
|
+
|
35
|
+
# validate the message options
|
36
|
+
message_validation(message_opts)
|
37
|
+
|
38
|
+
url = URI.parse PUSH_URL
|
39
|
+
http = Net::HTTP.new(url.host, url.port)
|
40
|
+
http.use_ssl = true
|
41
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
42
|
+
|
43
|
+
resp, dat = http.post(url.path, message_opts.to_json, headers)
|
44
|
+
|
45
|
+
return {:code => resp.code.to_i, :message => dat }
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def message_validation(message_opts)
|
50
|
+
# check if message_opts has required info
|
51
|
+
raise ArgumentError, "registration_ids is a required param of the GCM message" unless message_opts.has_key? :registration_ids
|
52
|
+
|
53
|
+
# if you use the delay_while_idle is an included parameter, it must be a boolean
|
54
|
+
if message_opts.has_key? :delay_while_idle
|
55
|
+
raise ArgumentError, "if you include the delay_while_idle parameter, it must be a boolean" unless ( [true, false].include? message_opts[:delay_while_idle])
|
56
|
+
end
|
57
|
+
|
58
|
+
# if you use the time_to_live parameter, you must also include a collapse_key
|
59
|
+
if (message_opts.has_key? :time_to_live) and (!message_opts.has_key? :collapse_key)
|
60
|
+
raise ArgumentError, "if you use the time_to_live parameter, you must also include a collapse_key"
|
61
|
+
end
|
62
|
+
|
63
|
+
# if you use the time_to_live parameter, it should be an integer
|
64
|
+
if message_opts.has_key? :time_to_live
|
65
|
+
raise ArgumentError, "if you use the time_to_live parameter, it should be an integer" unless (message_opts[:time_to_live].is_a? Integer)
|
66
|
+
end
|
67
|
+
|
68
|
+
# registration_ids must contain at least 1 and at most 1000 registration IDs
|
69
|
+
registration_ids = message_opts[:registration_ids]
|
70
|
+
if (registration_ids.length < 1) or (registration_ids.length > 1000)
|
71
|
+
raise ArgumentError, "registration_ids must contain at least 1 and at most 1000 registration IDs"
|
72
|
+
end
|
73
|
+
|
74
|
+
message_opts_json = message_opts.to_json
|
75
|
+
|
76
|
+
if (message_opts_json.to_s.bytesize > 4096)
|
77
|
+
# data must be less than 4kb in length
|
78
|
+
raise StandardError, "the size of the message is over 4kb"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
data/speedy_gcm.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "speedy_gcm/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "speedy_gcm"
|
7
|
+
s.version = SpeedyGCM::VERSION
|
8
|
+
s.authors = ["Sandeep Ghael"]
|
9
|
+
s.email = ["sghael@ravidapp.com"]
|
10
|
+
s.homepage = "https://github.com/sghael/speedy_gcm"
|
11
|
+
s.summary = %q{Speedy GCM is an intelligent gem for sending push notifications to Android devices via GCM.}
|
12
|
+
s.description = %q{Speedy GCM efficiently sends push notifications to Android devices via GCM (Google Cloud Messaging).}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'speedy_gcm'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
current_dir = File.expand_path(File.dirname(__FILE__))
|
2
|
+
require File.join(current_dir, 'helper')
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
require "net/http"
|
6
|
+
require "net/https"
|
7
|
+
|
8
|
+
class TestSpeedyGCM < Test::Unit::TestCase
|
9
|
+
|
10
|
+
GCM_API_KEY = "TODO - Fill in with your GCM API Key"
|
11
|
+
TEST_PHONE_GCM_REGISTRATION_ID = "TODO - Fill in with some GCM Registration ID"
|
12
|
+
|
13
|
+
should "not raise an error if the API key is valid" do
|
14
|
+
assert_nothing_raised do
|
15
|
+
SpeedyGCM::API.set_account(GCM_API_KEY)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
should "raise an error if the api key is not provided" do
|
20
|
+
assert_raise(ArgumentError) do
|
21
|
+
SpeedyGCM::API.set_account()
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
should "raise an error if the registration_ids are not provided" do
|
26
|
+
SpeedyGCM::API.set_account(GCM_API_KEY)
|
27
|
+
|
28
|
+
assert_raise(ArgumentError) do
|
29
|
+
message_options = {}
|
30
|
+
# message_options.merge!({ :registration_ids => [1,2] })
|
31
|
+
message_options.merge!({ :collapse_key => "foobar" })
|
32
|
+
message_options.merge!({ :data => { :score => "3x1" } })
|
33
|
+
message_options.merge!({ :delay_while_idle => true })
|
34
|
+
message_options.merge!({ :time_to_live => 1 })
|
35
|
+
|
36
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
should "raise an error if the time_to_live is provided but collapse_key is not" do
|
41
|
+
SpeedyGCM::API.set_account(GCM_API_KEY)
|
42
|
+
|
43
|
+
assert_raise(ArgumentError) do
|
44
|
+
message_options = {}
|
45
|
+
message_options.merge!({ :registration_ids => [1,2] })
|
46
|
+
# message_options.merge!({ :collapse_key => "foobar" })
|
47
|
+
message_options.merge!({ :data => { :score => "3x1" } })
|
48
|
+
message_options.merge!({ :delay_while_idle => true })
|
49
|
+
message_options.merge!({ :time_to_live => 1 })
|
50
|
+
|
51
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
should "raise an error if the time_to_live is provided but it is not an integer" do
|
56
|
+
SpeedyGCM::API.set_account(GCM_API_KEY)
|
57
|
+
|
58
|
+
assert_raise(ArgumentError) do
|
59
|
+
message_options = {}
|
60
|
+
message_options.merge!({ :registration_ids => [1,2] })
|
61
|
+
message_options.merge!({ :collapse_key => "foobar" })
|
62
|
+
message_options.merge!({ :data => { :score => "3x1" } })
|
63
|
+
message_options.merge!({ :time_to_live => "a" })
|
64
|
+
|
65
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
66
|
+
end
|
67
|
+
|
68
|
+
assert_nothing_raised do
|
69
|
+
message_options = {}
|
70
|
+
message_options.merge!({ :registration_ids => [1,2] })
|
71
|
+
message_options.merge!({ :collapse_key => "foobar" })
|
72
|
+
message_options.merge!({ :data => { :score => "3x1" } })
|
73
|
+
message_options.merge!({ :time_to_live => 1 })
|
74
|
+
|
75
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
should "check that delay_while_idle is a boolean if provided" do
|
80
|
+
SpeedyGCM::API.set_account(GCM_API_KEY)
|
81
|
+
|
82
|
+
assert_raise(ArgumentError) do
|
83
|
+
message_options = {}
|
84
|
+
message_options.merge!({ :registration_ids => [1,2] })
|
85
|
+
message_options.merge!({ :collapse_key => "foobar" })
|
86
|
+
message_options.merge!({ :data => { :score => "3x1" } })
|
87
|
+
message_options.merge!({ :delay_while_idle => nil })
|
88
|
+
message_options.merge!({ :time_to_live => 1 })
|
89
|
+
|
90
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
91
|
+
end
|
92
|
+
|
93
|
+
assert_nothing_raised do
|
94
|
+
message_options = {}
|
95
|
+
message_options.merge!({ :registration_ids => [1,2] })
|
96
|
+
message_options.merge!({ :collapse_key => "foobar" })
|
97
|
+
message_options.merge!({ :data => { :score => "3x1" } })
|
98
|
+
message_options.merge!({ :delay_while_idle => true })
|
99
|
+
message_options.merge!({ :time_to_live => 1 })
|
100
|
+
|
101
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
102
|
+
end
|
103
|
+
|
104
|
+
assert_nothing_raised do
|
105
|
+
message_options = {}
|
106
|
+
message_options.merge!({ :registration_ids => [1,2] })
|
107
|
+
message_options.merge!({ :collapse_key => "foobar" })
|
108
|
+
message_options.merge!({ :data => { :score => "3x1" } })
|
109
|
+
message_options.merge!({ :delay_while_idle => false })
|
110
|
+
message_options.merge!({ :time_to_live => 1 })
|
111
|
+
|
112
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
should "raise error if registration_ids contain no registration IDs" do
|
117
|
+
SpeedyGCM::API.set_account(GCM_API_KEY)
|
118
|
+
|
119
|
+
assert_raise(ArgumentError) do
|
120
|
+
message_options = {}
|
121
|
+
message_options.merge!({ :registration_ids => [] })
|
122
|
+
message_options.merge!({ :collapse_key => "foobar" })
|
123
|
+
message_options.merge!({ :data => { :score => "3x1" } })
|
124
|
+
message_options.merge!({ :time_to_live => 1 })
|
125
|
+
|
126
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
should "raise error if registration_ids contains more than 1000 registration IDs" do
|
131
|
+
assert_raise(ArgumentError) do
|
132
|
+
SpeedyGCM::API.set_account(GCM_API_KEY)
|
133
|
+
|
134
|
+
reg_ids = *(1..1001)
|
135
|
+
|
136
|
+
message_options = {}
|
137
|
+
message_options.merge!({ :registration_ids => reg_ids })
|
138
|
+
message_options.merge!({ :collapse_key => "foobar" })
|
139
|
+
message_options.merge!({ :data => { :score => "3x1" } })
|
140
|
+
message_options.merge!({ :time_to_live => 1 })
|
141
|
+
|
142
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
should "not raise an error if a send notification call succeeds" do
|
147
|
+
assert_nothing_raised do
|
148
|
+
SpeedyGCM::API.set_account(GCM_API_KEY)
|
149
|
+
|
150
|
+
message_options = {}
|
151
|
+
message_options.merge!({ :registration_ids => [1] })
|
152
|
+
message_options.merge!({ :collapse_key => "foobar" })
|
153
|
+
message_options.merge!({ :data => { :score => "3x1" } })
|
154
|
+
message_options.merge!({ :time_to_live => 1 })
|
155
|
+
|
156
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
should "not raise an error and send a message with a success response" do
|
161
|
+
assert_nothing_raised do
|
162
|
+
SpeedyGCM::API.set_account(GCM_API_KEY)
|
163
|
+
|
164
|
+
message_options = {}
|
165
|
+
message_options.merge!({ :registration_ids => [TEST_PHONE_GCM_REGISTRATION_ID] })
|
166
|
+
message_options.merge!({ :collapse_key => Time.now.to_s })
|
167
|
+
message_options.merge!({ :data => { :vmr_id => "3" } })
|
168
|
+
|
169
|
+
response = SpeedyGCM::API.send_notification(message_options)
|
170
|
+
|
171
|
+
assert response[:code].eql? 200
|
172
|
+
|
173
|
+
# puts response[:code]
|
174
|
+
# puts response[:message]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: speedy_gcm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sandeep Ghael
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-01 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Speedy GCM efficiently sends push notifications to Android devices via
|
15
|
+
GCM (Google Cloud Messaging).
|
16
|
+
email:
|
17
|
+
- sghael@ravidapp.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- LICENSE.txt
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- lib/speedy_gcm.rb
|
28
|
+
- lib/speedy_gcm/version.rb
|
29
|
+
- speedy_gcm.gemspec
|
30
|
+
- test/helper.rb
|
31
|
+
- test/test_speedy_gcm.rb
|
32
|
+
homepage: https://github.com/sghael/speedy_gcm
|
33
|
+
licenses: []
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 1.8.24
|
53
|
+
signing_key:
|
54
|
+
specification_version: 3
|
55
|
+
summary: Speedy GCM is an intelligent gem for sending push notifications to Android
|
56
|
+
devices via GCM.
|
57
|
+
test_files:
|
58
|
+
- test/helper.rb
|
59
|
+
- test/test_speedy_gcm.rb
|