2

我希望我的Android应用程序从我的buddyplatform后端接收GCM推送消息。我已经实现了像在android docs中显示的GCM客户端,但我没有在我的两个测试设备(Android 4.2.2原始版本和CM mod 10.1 Android 4.2.2)上收到任何推送消息。 这是我的权限和变化,我AndroidManifest.xmlGCM客户端不接收推送通知

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> 
<uses-permission android:name="android.permission.WAKE_LOCK" /> 
<uses-permission android:name=".permission.C2D_MESSAGE" /> 
<uses-permission android:name="com.google.android.c2dm.SEND" /> 
<uses-permission android:name="com.google.android.c2dm.intent.RECEIVE" /> 
<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> 
<uses-permission android:name=".permission.C2D_MESSAGE" /> 
... 
<application> 
    <receiver 
     android:name=".GcmBroadcastReceiver" 
     android:permission="com.google.android.c2dm.permission.SEND" > 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 

      <category android:name=".gcm" /> 
     </intent-filter> 
    </receiver> 

    <service android:name=".GcmIntentService" /> 
</application> 

GcmIntentService

package .wop; 

import android.app.IntentService; 
import android.app.NotificationManager; 
import android.app.PendingIntent; 
import android.content.Context; 
import android.content.Intent; 
import android.os.Bundle; 
import android.os.SystemClock; 
import android.support.v4.app.NotificationCompat; 
import android.util.Log; 

import com.google.android.gms.gcm.GoogleCloudMessaging; 

/** 
* This {@code IntentService} does the actual handling of the GCM message. 
* {@code GcmBroadcastReceiver} (a {@code WakefulBroadcastReceiver}) holds a 
* partial wake lock for this service while the service does its work. When the 
* service is finished, it calls {@code completeWakefulIntent()} to release the 
* wake lock. 
*/ 
public class GcmIntentService extends IntentService { 
    public static final int NOTIFICATION_ID = 1; 
    private NotificationManager mNotificationManager; 
    NotificationCompat.Builder builder; 

    public GcmIntentService() { 
     super("GcmIntentService"); 
    } 
    public static final String TAG = "GCM Demo"; 

    @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)) { 
       // This loop represents the service doing some work. 
       for (int i = 0; i < 5; i++) { 
        Log.i(TAG, "Working... " + (i + 1) 
          + "/5 @ " + SystemClock.elapsedRealtime()); 
        try { 
         Thread.sleep(5000); 
        } catch (InterruptedException e) { 
        } 
       } 
       Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime()); 
       // Post notification of received message. 
       sendNotification("Received: " + extras.toString()); 
       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, MainActivity.class), 0); 

     NotificationCompat.Builder mBuilder = 
       new NotificationCompat.Builder(this) 
         .setSmallIcon(R.drawable.common_signin_btn_icon_dark) 
         .setContentTitle("GCM Notification") 
         .setStyle(new NotificationCompat.BigTextStyle() 
           .bigText(msg)) 
         .setContentText(msg); 

     mBuilder.setContentIntent(contentIntent); 
     mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); 
    } 
} 

GcmBroadcastReceiver

package .wop; 

import android.app.Activity; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.Intent; 
import android.support.v4.content.WakefulBroadcastReceiver; 

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     System.out.println("PUSH RECEIVED!!!"); 
     // 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. 
     startWakefulService(context, (intent.setComponent(comp))); 
     setResultCode(Activity.RESULT_OK); 
    } 
} 

而且我在MainActivity没有为GCM的变化:

public class MainActivity extends ActionBarActivity { 

//GCM 
public static final String EXTRA_MESSAGE = "message"; 
public static final String PROPERTY_REG_ID = "registration_id"; 
private static final String PROPERTY_APP_VERSION = "appVersion"; 
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000; 

/** 
* Substitute you own sender ID here. This is the project number you got 
* from the API Console, as described in "Getting Started." 
*/ 
String SENDER_ID = "3019882..."; 

/** 
* Tag used on log messages. 
*/ 
static final String TAG = "GCMDemo"; 

TextView mDisplay; 
GoogleCloudMessaging gcm; 
AtomicInteger msgId = new AtomicInteger(); 
SharedPreferences prefs; 
Context context; 

String regid; 


@Override 
protected void onCreate(Bundle savedInstanceState) { 
    mDisplay = (TextView) findViewById(R.id.displayPush); 
    context = getApplicationContext(); 

    //GCM 
    // Check device for Play Services APK. If check succeeds, proceed with 
    // GCM registration. 
    if (checkPlayServices()) { 
     gcm = GoogleCloudMessaging.getInstance(this); 
     regid = getRegistrationId(context); 

     if (regid.isEmpty()) { 
      registerInBackground(); 
     } else { 
      System.out.println("regid: " + regid); 
     } 
    } else { 
     Log.i(TAG, "No valid Google Play Services APK found."); 
    } 

/** 
* Registers the application with GCM servers asynchronously. 
* <p/> 
* Stores the registration ID and the app versionCode in the application's 
* shared preferences. 
*/ 
private void registerInBackground() { 
    new AsyncTask<Void, Void, String>() { 
     @Override 
     protected String doInBackground(Void... params) { 
      String msg = ""; 
      try { 
       if (gcm == null) { 
        gcm = GoogleCloudMessaging.getInstance(context); 
       } 
       regid = gcm.register(SENDER_ID); 
       msg = "Device registered, registration ID=" + regid; 
       System.out.println(msg); 

       // 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. 
       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(context, regid); 
      } catch (IOException ex) { 
       msg = "Error :" + ex.getMessage(); 
       System.out.println(msg); 
       // 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 msg; 
     } 

     @Override 
     protected void onPostExecute(String msg) { 
      mDisplay.append(msg + "\n"); 
     } 
    }.execute(null, null, null); 
} 

/** 
* Sends the registration ID to your server over HTTP, so it can use GCM/HTTP 
* or CCS to send messages to your app. Not needed for this demo since the 
* device sends upstream messages to a server that echoes back the message 
* using the 'from' address in the message. 
*/ 
private void sendRegistrationIdToBackend() { 
    //ADDED BY MYSELF 
    Buddy.setPushToken(regid, new BuddyCallback<Boolean>(Boolean.class) { 

     @Override 
     public void completed(BuddyResult<Boolean> result) { 
      System.out.println("sendPushToken successfully"); 
     } 
    }); 
} 

/** 
* 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(); 
} 

/** 
* Gets the current registration ID for application on GCM service. 
* <p/> 
* If result is empty, the app needs to register. 
* 
* @return registration ID, or empty string if there is no existing 
* registration ID. 
*/ 
private String getRegistrationId(Context context) { 
    final SharedPreferences prefs = getGCMPreferences(context); 
    String registrationId = prefs.getString(PROPERTY_REG_ID, ""); 
    if (registrationId.isEmpty()) { 
     Log.i(TAG, "Registration not found."); 
     return ""; 
    } 
    // Check if app was updated; if so, it must clear the registration ID 
    // since the existing regID is not guaranteed to work with the new 
    // app version. 
    int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE); 
    int currentVersion = getAppVersion(context); 
    if (registeredVersion != currentVersion) { 
     Log.i(TAG, "App version changed."); 
     return ""; 
    } 
    return registrationId; 
} 

/** 
* @return Application's {@code SharedPreferences}. 
*/ 
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(MainActivity.class.getSimpleName(), 
      Context.MODE_PRIVATE); 
} 

/** 
* @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 (PackageManager.NameNotFoundException e) { 
     // should never happen 
     throw new RuntimeException("Could not get package name: " + e); 
    } 
} 


//GCM 
// You need to do the Play Services APK check here too. 
@Override 
protected void onResume() { 
    super.onResume(); 
    checkPlayServices(); 
} 

//GCM 

/** 
* Check the device to make sure it has the Google Play Services APK. If 
* it doesn't, display a dialog that allows users to download the APK from 
* the Google Play Store or enable it in the device's system settings. 
*/ 
private boolean checkPlayServices() { 
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); 
    if (resultCode != ConnectionResult.SUCCESS) { 
     if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) { 
      GooglePlayServicesUtil.getErrorDialog(resultCode, this, 
        PLAY_SERVICES_RESOLUTION_REQUEST).show(); 
     } else { 
      Log.i(TAG, "This device is not supported."); 
      finish(); 
     } 
     return false; 
    } 
    return true; 
} 

如您所见,我复制了&粘贴了Android文档中的大部分代码。 我添加了我的SENDER_ID(项目编号)并实施了发送伙伴我的PushToken的方法。

当我启动应用程序时,输出表示设备注册成功,regid如:APA91bF_uwCWiurDgc...。它还说我的谷歌播放服务是有效的,但我没有得到任何推送通知,虽然我的好友仪表板告诉我,我成功地发送了推送通知。

我忘记了什么吗?

+0

所以你需要测试你的gcm沟通服务。您的gcm通信服务可能会出错。此链接可以测试您的android应用程序.http://www.androidbegin.com/tutorial/gcm.html – 2014-08-28 08:26:05

+0

感谢您的快速评论。我测试了它,结果是:'{“multicast_id”:7328710106740104328,“success”:1,“failure”:0,“canonical_ids”:0,“results”:[{“message_id”:“0:1409214898016680 %e98399c7​​f9fd7ecd“}]}'。我在手机上成功推送了该推送。那么,为什么我不能从伙伴平台获得推送消息呢? – Peter 2014-08-28 08:37:15

+0

示例链接是使用PHP开发的。 – 2014-08-28 08:46:01

回答

2

您需要测试您的gcm通信服务。您的gcm通信服务可能有问题。 This链接,你可以测试你的Android应用程序,样本链接是用PHP开发的。如果您使用该链接测试可以连接您的android应用程序,则需要修改您的gcm通信服务。希望得到帮助。

+0

这个答案并没有真正解决我的问题,但现在我知道它与伙伴后端有关,而与我的GCM客户端无关。 – Peter 2014-08-28 16:21:10

+0

所以你的gcm沟通服务没错?你说我的示例gcm通信服务可以调用你的客户端android应用程序。所以我认为你需要修改你的gcm通信服务。我只是指出你的错误。 – 2014-08-29 01:45:20

+0

为了荣誉,我真的不知道什么是错的。我认为我的代码必须是正确的,如果它可以从这个网站推。那么你怎么看,我的代码的哪部分可能是错的?对不起,我误解了你的答案,我对这个主题没有任何经验。 – Peter 2014-08-29 10:24:48