<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.mobile.push.gcm">
    <title>Zend_Mobile_Push_Gcm</title>

    <para>
        <classname>Zend_Mobile_Push_Gcm</classname> provides the ability to
        send push notifications to Android devices that contain Google Services. 
        A message will always be constructed with
        <classname>Zend_Mobile_Push_Message_Gcm</classname>.
    </para>

    <sect2 id="zend.mobile.push.gcm.server">
        <title>Pushing Messages</title>

        <note>
            <para>Prior to pushing and receiving messages; you will need to create a Google
                API Project and setup your Android app to listen to GCM
                messages..  If you have not done this, follow the <ulink
                url="http://developer.android.com/guide/google/gcm/gs.html">
                GCM: Getting Started</ulink> document.
            </para>
        </note>

        <para>
            When implementing GCM; you have a few components that
            you will utilize.  <classname>Zend_Mobile_Push_Gcm</classname>
            which contains the server components,
            <classname>Zend_Mobile_Push_Message_Gcm</classname> which contains
            the message that you would like to send, and
            <classname>Zend_Mobile_Push_Response_Gcm</classname> which contains
            the response from GCM. Each message sent must do an HTTP request; so
            remember this when sending in large batches.
        </para>

        <para>
            The actual implementation of the code is fairly minimal; however,
            considerations to error handling must be taken.
        </para>

        <programlisting language="php"><![CDATA[
$message = new Zend_Mobile_Push_Message_Gcm();
$message->addToken('ABCDEF0123456789');
$message->setData(array(
    'foo' => 'bar',
    'bar' => 'foo',
));

$gcm = new Zend_Mobile_Push_Gcm();
$gcm->setApiKey('YOUR_API_KEY');

try {
    $response = $gcm->send($message);
} catch (Zend_Mobile_Push_Exception $e) {
    // exceptions require action or implementation of exponential backoff.
    die($e->getMessage());
}

// handle all errors and registration_id's
foreach ($response->getResults() as $k => $v) {
    if ($v['registration_id']) {
        printf("%s has a new registration id of: %s\r\n", $k, $v['registration_id']);
    }
    if ($v['error']) {
        printf("%s had an error of: %s\r\n", $k, $v['error']);
    }
    if ($v['message_id']) {
        printf("%s was successfully sent the message, message id is: %s", $k, $v['message_id']);
    }
}
]]></programlisting>

        <table id="zend.mobile.push.gcm.server.exceptions">
            <title>Exceptions and Remediation Techniques</title>
            <tgroup cols="3" align="left" colsep="1" rowsep="1">
                <thead>
                    <row>
                        <entry>Exception</entry>
                        <entry>Meaning</entry>
                        <entry>Handling</entry>
                    </row>
                </thead>
                <tbody>
                    <row>
                        <entry>Zend_Mobile_Push_Exception</entry>
                        <entry>These types of exceptions are more generic in nature
                        and are thrown either from gcm when there was an unknown exception
                        or internally on input validation.</entry>
                        <entry>Read the message and determine remediation steps.</entry>
                    </row>
                    <row>
                        <entry>Zend_Mobile_Push_Exception_InvalidAuthToken</entry>
                        <entry>Your API key was likely typed in wrong or does
                        not have rights to the GCM service.</entry>
                        <entry>Check your project on the <ulink
                        url="https://code.google.com/apis/console">Google APIs Console
                        page</ulink>.</entry>
                    </row>
                    <row>
                        <entry>Zend_Mobile_Push_Exception_ServerUnavailable</entry>
                        <entry>This exception means there was either an internal
                        server error OR that the server denied your request and
                        you should look at the Retry-After header.</entry>
                        <entry>Read the exception message and utilize
                        Exponential Backoff</entry>
                    </row>
                    <row>
                        <entry>Zend_Mobile_Push_Exception_InvalidPayload</entry>
                        <entry>Generally the payload will not throw an exception
                        unless the size of the payload is too large or the JSON
                        is too large.</entry>
                        <entry>Check the size of the payload is within the
                        requirements of GCM, currently it is 4K.</entry>
                    </row>
                </tbody>
            </tgroup>
        </table>
    </sect2>

    <sect2 id="zend.mobile.push.gcm.message">

        <title>Advanced Messages</title>

        <para>
            GCM provides the ability for sending more advanced messages; for
            instance the examples above show the most basic implementation of a
            message.  <classname>Zend_Mobile_Push_Message_Gcm</classname>
            allows you to do far more advanced messaging outlined below.
        </para>

        <sect3 id="zend.mobile.push.gcm.message.delay-while-idle">

            <title>Delay While Idle</title>

            <para>
                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.
            </para>

            <programlisting language="php"><![CDATA[
    $message = new Zend_Mobile_Push_Message_Gcm();
    $message->setDelayWhileIdle(true);
    ]]></programlisting>

        </sect3>

        <sect3 id="zend.mobile.push.gcm.message.ttl">

            <title>Time to Live</title>

            <para>
                You may set the time to live in seconds, by default GCM will
                save it for 4 weeks.  Additionally if you specify a Time to
                Live, you must also set an ID (the collapse key).  Generally it
                is best by using the message data so that you know it is a
                unique message.
            </para>

            <programlisting language="php"><![CDATA[
    $message = new Zend_Mobile_Push_Message_Gcm();
    $message->setTtl(86400);
    $message->addData('key', 'value');
    $message->setId(md5(json_encode($message->getData())));
            ]]></programlisting>

        </sect3>
    </sect2>

    <sect2 id="zend.mobile.push.gcm.response">

        <title>Response</title>

        <para>
            GCM gives a response back that contains detail that needs to be
            understood.  Most of the time you can just send a message but the
            server may come back telling you any the message id, any errors and
            potentially new registration ids.
        </para>

        <sect3 id="zend.mobile.push.gcm.response.result">

            <title>Results</title>

            <para>
                The results are most commonly retrieved by calling the
                getResults() method.  However, you may prefer to just get
                certain results by using the getResult() method.  The getResult
                method utilizes the constants RESULT_* correlating to message
                id, error or registration id.
            </para>

            <para>
                Several utility methods exist to give you a better idea of what
                happened during your send.  Methods getSuccessCount(),
                getFailureCount() and getCanonicalCount() let you know how many
                where successful, how many failures and how many updates to
                registration ids you have.
            </para>

        </sect3>
    </sect2>
</sect1>
