Einige Geräte nicht erhalten GCM push, auch wenn alle Nachrichten erfolgreich vom server

Entwickeln wir eine Anwendung, die verwendet GCM. Es funktioniert gut auf den meisten Handys, jedoch haben wir zwei Telefone (galaxy note 2 und galaxy s plus), die nicht die Nachrichten empfangen. Oder vielleicht ist es nur die broadcast-Empfänger nicht genannt wird.

Server-side-push:

$data = array(
        'data' => array('message' => $messageData),
        'delay_while_idle' => false,
        'type' => 'New',
        'flag' => 1,
        'registration_ids' => $registrationIdsArray
    );

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_URL, "https://android.googleapis.com/gcm/send");
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));

    $response = curl_exec($ch);
    curl_close($ch);

Response Empfänger beim senden von push:

{
   "multicast_id":4735518740307255391,
   "success":4,
   "failure":0,
   "canonical_ids":0,
   "results":[
      {
         "message_id":"0:1390919813717906%2d15d04af9fd7ecd"
      },
      {
         "message_id":"0:1390919813717694%2d15d04af9fd7ecd"
      },
      {
         "message_id":"0:1390919813717290%2d15d04af9fd7ecd"
      },
      {
         "message_id":"0:1390919813717907%2d15d04af9fd7ecd"
      }
   ]
}

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.innocreate.app"
    android:versionCode="2"
    android:versionName="0.1.1" >

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="17" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <permission android:name="com.innocreate.app.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="com.innocreate.app.permission.C2D_MESSAGE" />
    <uses-permission android:name="android.permission.VIBRATE"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:logo="@drawable/menu"
        android:theme="@style/Theme.Styled" >
        <meta-data
            android:name="AA_DB_VERSION"
            android:value="3" />
        <meta-data android:name="com.google.android.gms.version"
           android:value="@integer/google_play_services_version" />

        <activity
            android:name="com.innocreate.app.NavigationParent"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@style/Theme.Styled"
            android:launchMode="singleTop" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.innocreate.app.DibsPaymentActivity" >
        </activity>

        <service
            android:name="com.octo.android.robospice.GsonSpringAndroidSpiceService"
            android:exported="false" />

        <receiver
            android:name="com.innocreate.app.gcm.GCMBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
                <category android:name="com.app.muf_appen" />
            </intent-filter>
        </receiver>
        <service android:name="com.innocreate.app.gcm.GCMIntentService" />
        <service android:name="com.innocreate.app.gcm.GCMRegistrationService" />

    </application>

</manifest>

GcmIntentService.java

public class GCMIntentService extends IntentService {

    public GCMIntentService(String name) {
        super(name);
        //TODO Auto-generated constructor stub
    }

    public static final int NOTIFICATION_ID = 1;
    private NotificationManager mNotificationManager;
    NotificationCompat.Builder builder;

    public GCMIntentService() {
        super("GCMIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle extras = intent.getExtras();
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
        //The getMessageType() intent parameter must be the intent you received
        //in your BroadcastReceiver.
        String messageType = gcm.getMessageType(intent); 

        if (!extras.isEmpty()) {  //has effect of unparcelling Bundle
            /*
             * Filter messages based on message type. Since it is likely that GCM
             * will be extended in the future with new message types, just ignore
             * any message types you're not interested in, or that you don't
             * recognize.
             */
            if (GoogleCloudMessaging.
                    MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
//               sendNotification("Send error: " + extras.toString());
            } else if (GoogleCloudMessaging.
                    MESSAGE_TYPE_DELETED.equals(messageType)) {
//               sendNotification("Deleted messages on server: " +
//                       extras.toString());
            //If it's a regular GCM message, do some work.
            } else if (GoogleCloudMessaging.
                    MESSAGE_TYPE_MESSAGE.equals(messageType)) {

//               Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
                //Post notification of received message.
                sendNotification(extras.getString("message"));
//               Log.i(TAG, "Received: " + extras.toString());
            }
        }
        //Release the wake lock provided by the WakefulBroadcastReceiver.
//       GCMBroadcastReceiver.completeWakefulIntent(intent);
    }

    //Put the message into a notification and post it.
    //This is just one simple example of what you might choose to do with
    //a GCM message.
    private void sendNotification(String msg) {
        mNotificationManager = (NotificationManager)
                this.getSystemService(Context.NOTIFICATION_SERVICE);

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, NavigationParent.class), PendingIntent.FLAG_UPDATE_CURRENT);

        Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        long[] vibration = {0, 200, 50, 200};
        Builder mBuilder =
                new NotificationCompat.Builder(this)
        .setSmallIcon(R.drawable.ic_launcher)
        .setContentTitle("MUF - Nyhet")
        .setContentText(msg)
        .setVibrate(vibration);

        mBuilder.setContentIntent(contentIntent);

        Notification notification =  mBuilder.build();
        notification.flags |= Notification.FLAG_AUTO_CANCEL;


        mNotificationManager.notify(NOTIFICATION_ID, notification);
    }

}

GcmBroadcastreceiver.java

public class GCMBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //Explicitly specify that GcmIntentService will handle the intent.
        ComponentName comp = new ComponentName(context.getPackageName(),
                GCMIntentService.class.getName());

        //Start the service, keeping the device awake while it is launching.
        SharedPreferences p = context.getSharedPreferences(
                GCMRegistrationService.class.getSimpleName(),
                Context.MODE_PRIVATE);
        if (p.getBoolean("ENABLE_GCM", true)) {
            context.startService(intent.setComponent(comp));
        }
        setResultCode(Activity.RESULT_OK);
    }

}

GcmRegistrationService.java

public class GCMRegistrationService extends Service {

    public static final String REGISTRATION_ID_EXTRA = "REGISTRATION_ID_EXTRA";
    public static final String BACKOFF_TIME_EXTRA = "BACKOFF_TIME_EXTRA";
    public static final String PROPERTY_REG_ID = "PROPERTY_REG_ID";
    public static final String PROPERTY_APP_VERSION = "PROPERTY_APP_VERSION";
    private static final String BACKEND_REGISTRATION_URL = "MY URL (REMOVED)";
    private static final String SENDER_ID = "MY SENDER ID (REMOVED)";



    private String mRegistrationId;
    private GoogleCloudMessaging mGCM;

    private Handler mHandler = new Handler();

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //TODO Auto-generated method stub

        //try request
        Thread registerThread = new Thread(new Runnable() {

            @Override
            public void run() {
                long currentBackoffTime = 1000;
                int iterationCounter = 0; //maximum number of iterations 11 => 4095 seconds
                while(!tryRegistration() && iterationCounter < 11) {
                    try {
                        Thread.sleep(currentBackoffTime);
                    } catch (InterruptedException e) {
                        //TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    currentBackoffTime *= 2;
                    iterationCounter++;
                }
                stopSelf();
            }
        });

        registerThread.start();

        return super.onStartCommand(intent, flags, startId);
    }



    @Override
    public IBinder onBind(Intent intent) {
        //TODO Auto-generated method stub
        return null;
    }


    private boolean tryRegistration() {
        try {
            if (mGCM == null) {
                mGCM = GoogleCloudMessaging.getInstance(this);
            }
            mRegistrationId = mGCM.register(SENDER_ID);

            //You should send the registration ID to your server over HTTP,
            //so it can use GCM/HTTP or CCS to send messages to your app.
            //The request to your server should be authenticated if your app
            //is using accounts.
            sendRegistrationIdToBackend();

            //For this demo: we don't need to send it because the device
            //will send upstream messages to a server that echo back the
            //message using the 'from' address in the message.

            //Persist the regID - no need to register again.
            storeRegistrationId(this, mRegistrationId);
        } catch (IOException ex) {
            //If there is an error, don't just keep trying to register.
            //Require the user to click a button again, or perform
            //exponential back-off.
            return false;
        }
        return true;
    }

    private void sendRegistrationIdToBackend() throws IOException {
        RestMethod rm = new RestMethod(BACKEND_REGISTRATION_URL);
        rm.appendQueryParameter("gcm", mRegistrationId);
        rm.appendQueryParameter("from", "1");
        rm.execute(Type.POST);
        if(rm.mResponseCode >= 299) {
            throw new IOException();
        }
    }

    /**
     * Stores the registration ID and app versionCode in the application's
     * {@code SharedPreferences}.
     *
     * @param context application's context.
     * @param regId registration ID
     */
    private void storeRegistrationId(Context context, String regId) {
        final SharedPreferences prefs = getGCMPreferences(context);
        int appVersion = getAppVersion(context);
//     Log.i(TAG, "Saving regId on app version " + appVersion);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString(PROPERTY_REG_ID, regId);
        editor.putInt(PROPERTY_APP_VERSION, appVersion);
        editor.commit();
    }


     /**
     * @return Application's version code from the {@code PackageManager}.
     */
    private static int getAppVersion(Context context) {
        try {
            PackageInfo packageInfo = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
        } catch (NameNotFoundException e) {
            //should never happen
            throw new RuntimeException("Could not get package name: " + e);
        }
    }


    private SharedPreferences getGCMPreferences(Context context) {
        //This sample app persists the registration ID in shared preferences, but
        //how you store the regID in your app is up to you.
        return getSharedPreferences(GCMRegistrationService.class.getSimpleName(),
                Context.MODE_PRIVATE);
    }



}

Haben wir versucht, so ziemlich alles, und nichts scheint zu funktionieren.
Das galaxy note 2 läuft 4.3 auch ohne google-Konto und WLAN.
Das Galaxy s plus läuft android 2.3.5 mit einem google-Konto über WLAN.

Lesen wir, dass einige Geräte über WLAN nicht erhalten würde GCM deshalb haben wir versucht, Neustart des Handys, aber es ist nichts passiert.

Vielen Dank im Voraus für irgendwelche Hinweise oder Antworten!

Freundlichen GRÜßEN
Johan Risch
Simon Evertsson

InformationsquelleAutor Risch | 2014-01-28
Schreibe einen Kommentar