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
Du musst angemeldet sein, um einen Kommentar abzugeben.
Leider aus meiner Erfahrung wird es immer eine Anzahl von Benutzern(aber ein sehr kleiner Prozentsatz), die nicht erhalten GCM.
Einer der Gründe, warum es nicht funktioniert auf einem der Telefone, die wir verwendet wurde, war, dass seine Google-Play-Services app die nicht korrekt installiert(und Ihre wesentlichen, für GCM).
Und das größte Problem war, dass wir uns nicht re-installieren Sie die Google-Play-Dienste über die üblichen Wege(wie eine normale Benutzer), google play store sagte, es sei schon installiert, aber es fehlte das Telefon(habe Sie gelöscht, im letzten Jahr, als google installiert auf allen Telefonen ohne Benutzer bemerken, einige Fehler aufgetreten, dass insbesondere auf die Telefon->Prestigio PAPADUO)....ein weiterer Nebeneffekt war, dass keine apps mit Google maps innerhalb laden konnte Karten->außer die google maps-app...
Könnte es werden nur die Handys selbst, da es doch auf viele andere, wie Sie sagte.
Die Kategorie, in dem broadcast-receiver ist falsch :
Sollte es sein, den Paketnamen Ihrer app
com.innocreate.app
stattcom.app.muf_appen
.Dies führt in der Regel nur Probleme, die in älteren Android-Versionen.
In meinem Fall, es war, weil die Google-Konto verbunden wurde das Gerät falsch konfiguriert (Passwort geändert hatte).
Einmal die login und Passwort waren korrekt eingestellt, meine Bewerbung war gut funktioniert.
Achten, dass es funktioniert :