code: def send_async(registration_ids, opts={}, handler=nil)
  
          headers = {
            'Content-Type'  => 'application/json',
            'Authorization' => sprintf("key=%s", @api_key)
          }
  
          body = {
            'registration_ids' => registration_ids,
          }
  
          #fill up option
          OPTIONAL_OPTIONS.each do | key, type |
            if opts.key?(key)
              if type.is_a?(Array)
                @valid_value = false
                type.each do | v |
                  if opts[key] == v
                    @valid_value = true
                    break
                  end
                end
                raise SenderError.new("#{key} should be Type #{type}") unless @valid_value
              else
                raise SenderError.new("#{key} should be Type #{type}") unless opts[key].is_a?(type)
              end
              # convert payload data to String for issue #3
              case key
              when :data
                opts[key] = convert_hash(opts[key])
              end
              body[key] = opts[key]
            end
          end
  
          request = Typhoeus::Request.new(
            'https://android.googleapis.com/gcm/send',
            :headers         => headers,
            :method          => :post,
            :body            => body.to_json,
            :follow_location => true
          )
  
          @hydra ||= Typhoeus::Hydra.new
  
          request.on_complete do | response |
            handler.handle(registration_ids, opts, response)
            response
          end
  
          @hydra.queue(request)
  
          request
        end
docs: http://developer.android.com/guide/google/gcm/gcm.html#server