Android推送(GCM)从应用引擎使用Zend框架


Android push (GCM) from App Engine using Zend Framework

我试图在谷歌应用引擎上使用PHP和Zend框架实现GCM服务器。到目前为止,它在本地工作得很好,但当上载到App Engine时,此消息失败:

代码如下:

$ids = '....my device id....';
$apiKey = '...my api key...';
$data = array( 'message' => 'Hello World!' );
$gcm_client = new Client();
$gcm_client->setApiKey($apiKey);
$gcm_message = new Message();
$gcm_message->setTimeToLive(86400);
$gcm_message->setData($data);
$gcm_message->setRegistrationIds($ids);
$response = $gcm_client->send($gcm_message);
var_dump($response);

失败,显示如下错误信息:

PHP致命错误:未捕获的异常'ErrorException''stream_socket_client():无法连接到android.googleapis.com:443(未知错误4294967295)' in/基地/数据/home/…/后端:v1.375711862873219029/供应商/zendframework/zend-http/Zend/Http/客户/适配器/Socket.php: 253

我知道App Engine不允许套接字连接,并为http和https提供urlFetch包装,但我如何告诉Zend框架使用这种传输?

尝试启用计费功能。据我所知,套接字仅在付费应用程序中启用。

这不会向您收取任何费用(除非您超过了免费配额),但应该可以消除错误。

从评论中提升了这一点-我最终制作了自己的类实现Zend'Http'Client'Adapter'AdapterInterface,使用URLFetch通过使用通常的fopen流上下文打开URL来发送POST请求。虽然这有效,但我不确定这是最好的方法。如果可能的话,我更愿意使用框架功能。

我不确定这是否会帮助任何人,因为ZendFramework和AppEngine在我问这个问题之后都已经发展了,但这里是我实现的适配器:

use Zend'Http'Client'Adapter'AdapterInterface;
use Zend'Http'Client'Adapter'Exception'RuntimeException;
use Zend'Http'Client'Adapter'Exception'TimeoutException;
use Zend'Stdlib'ErrorHandler;
class URLFetchHttpAdapter implements AdapterInterface
{
    protected $stream;
    protected $options;
    /**
     * Set the configuration array for the adapter
     *
     * @param array $options
     */
    public function setOptions($options = array())
    {
        $this->options = $options;
    }
    /**
     * Connect to the remote server
     *
     * @param string $host
     * @param int $port
     * @param  bool $secure
     */
    public function connect($host, $port = 80, $secure = false)
    {
        // no connection yet - it's performed in "write" method
    }
    /**
     * Send request to the remote server
     *
     * @param string $method
     * @param 'Zend'Uri'Uri $url
     * @param string $httpVer
     * @param array $headers
     * @param string $body
     *
     * @throws 'Zend'Loader'Exception'RuntimeException
     * @return string Request as text
     */
    public function write($method, $url, $httpVer = '1.1', $headers = array(), $body = '')
    {
        $headers_str = '';
        foreach ($headers as $k => $v) {
            if (is_string($k))
                $v = ucfirst($k) . ": $v";
            $headers_str .= "$v'r'n";
        }
        if (!is_array($this->options))
            $this->options = array();
        $context_arr = array("http" =>
                                 array( "method" => $method,
                                        "content" => $body,
                                        "header" => $headers_str,
                                        "protocol_version" => $httpVer,
                                        'ignore_errors' => true,
                                        'follow_location' => false,
                                 ) + $this->options
        );
        $context = stream_context_create($context_arr);
        ErrorHandler::start();
        $this->stream = fopen((string)$url, 'r', null, $context);
        $error = ErrorHandler::stop();
        if (!$this->stream) {
            throw new 'Zend'Loader'Exception'RuntimeException('', 0, $error);
        }
    }

    /**
     * Read response from server
     *
     * @throws 'Zend'Http'Client'Adapter'Exception'RuntimeException
     * @return string
     */
    public function read()
    {
        if ($this->stream) {
            ErrorHandler::start();
            $metadata = stream_get_meta_data($this->stream);
            $headers = join("'r'n", $metadata['wrapper_data']);
            $contents = stream_get_contents($this->stream);
            $error = ErrorHandler::stop();
            if ($error)
                throw $error;
            $this->close();
            //echo $headers."'r'n'r'n".$contents;
            return $headers."'r'n'r'n".$contents;
        } else {
            throw new RuntimeException("No connection exists");
        }
    }
    /**
     * Close the connection to the server
     *
     */
    public function close()
    {
        if (is_resource($this->stream)) {
            ErrorHandler::start();
            fclose($this->stream);
            ErrorHandler::stop();
            $this->stream = null;
        }
    }
    /**
     * Check if the socket has timed out - if so close connection and throw
     * an exception
     *
     * @throws TimeoutException with READ_TIMEOUT code
     */
    protected function _checkSocketReadTimeout()
    {
        if ($this->stream) {
            $info = stream_get_meta_data($this->stream);
            $timedout = $info['timed_out'];
            if ($timedout) {
                $this->close();
                throw new TimeoutException(
                    "Read timed out after {$this->options['timeout']} seconds",
                    TimeoutException::READ_TIMEOUT
                );
            }
        }
    }
}
public function sendAndroidPushNotification($registration_ids, $message) 
{
    $registrationIds = array($registration_ids);
    $msg = array(
        'message' => $message,
        'title' => 'notification center',
        'vibrate' => 1,
        'sound' => 1
    );
    $fields = array(
        'registration_ids' => $registrationIds,
        'data' => $msg
    );
    $fields = json_encode($fields);
    $arrContextOptions=array(
        "http" => array(
            "method" => "POST",
            "header" =>
            "Authorization: key = <YOUR_APP_KEY>". "'r'n" .
            "Content-Type: application/json". "'r'n",
            "content" => $fields,
         ),
         "ssl"=>array(
             "allow_self_signed"=>true,
             "verify_peer"=>false,
         ),
    );
    $arrContextOptions = stream_context_create($arrContextOptions);
    $result = file_get_contents('https://android.googleapis.com/gcm/send', false, $arrContextOptions);
    return $result;
}