2015-10-05 117 views
0

正在開發一個使用GCM發送和接收消息的Android應用程序。 am能夠向GCM註冊我的應用並接收GCM註冊令牌。但我沒有在收到新郵件通知。(好像沒有在我的MyGcmListenerService類hapenning。)無法接收來自GCM的消息

我只能看到在重裝我聊天的用戶界面我的新郵件(即單擊後退按鈕和然後再次單擊我的聊天按鈕。沒有什麼是發生在我的MyGcmListenerService.java !!!!)

下面

是我的班和AndroidManifest.xml中

AndroidManifest.xml中

<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/> 
<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.WAKE_LOCK" /> 
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> 

<permission android:name="com.me.myapp.permission.C2D_MESSAGE" 
    android:protectionLevel="signature" /> 
<uses-permission android:name="com.me.myapp.permission.C2D_MESSAGE" /> 
<application 
    android:allowBackup="true" 
    android:icon="@mipmap/ic_launcher" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme" 
    android:name="android.support.multidex.MultiDexApplication" 
    > 

    <receiver 
     android:name="com.google.android.gms.gcm.GcmReceiver" 
     android:exported="true" 
     android:permission="com.google.android.c2dm.permission.SEND" > 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
      <category android:name="com.me.myapp" /> 
     </intent-filter> 
    </receiver> 
    <service 
     android:name="com.me.myapp.MyGcmListenerService" 
     android:exported="false" > 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
     </intent-filter> 
    </service> 
    <service 
     android:name="com.me.myapp.MyInstanceIDListenerService" 
     android:exported="false"> 
     <intent-filter> 
      <action android:name="com.google.android.gms.iid.InstanceID"/> 
     </intent-filter> 
    </service> 

MyGcmListenerService.java

public class MyGcmListenerService extends GcmListenerService { 

private static final String TAG = "MyGcmListenerService"; 

public static final String AC_GCM_MESSAGE_ACTION = "com.me.myapp.MyGcmListenerService.OrderedBroadcast"; 
public static final String INTERCEPTED = "intercepted"; 



/** 
* Called when message is received. 
* 
* @param from SenderID of the sender. 
* @param data Data bundle containing message data as key/value pairs. 
*    For Set of keys use data.keySet(). 
*/ 
// [START receive_message] 
@Override 
public void onMessageReceived(String from, Bundle data) { 
    d("on receive called"); 
    final String message = data.getString("message"); 
    final String senderName = data.getString("sender"); 
    final String senderId = data.getString("senderId"); 
    final String dateCreated = data.getString("dateCreated"); 
    Log.d(TAG, "From: " + from); 
    Log.d(TAG, "Message: " + message); 

    d("Message received from "+ from); 

    Intent intent = new Intent(AC_GCM_MESSAGE_ACTION); 
    intent.putExtra("message", message); 
    intent.putExtra("senderName", senderName); 
    intent.putExtra("senderId", senderId); 
    intent.putExtra("dateCreated", dateCreated); 
    //dateCreated 
    intent.putExtra(INTERCEPTED, false); 

    sendOrderedBroadcast(intent, null, new MyBroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      Bundle results = getResultExtras(true); 
      d("entered onreceive"); 
      boolean intercepted = results.getBoolean(INTERCEPTED); 
      if (!intercepted) { 
       sendNotification(message, senderName, senderId); 
      } 
     } 
    }, null, Activity.RESULT_OK, null, null); 
} 
// [END receive_message] 

/** 
* Create and show a simple notification containing the received GCM message. 
* 
* @param message GCM message received. 
*/ 
private void sendNotification(String message, String senderName, String senderId) { 
    Intent intent = new Intent(this, ChatActivity.class); 
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
    intent.putExtra("senderId", senderId); 
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, 
      PendingIntent.FLAG_ONE_SHOT); 

    Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); 
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) 
      .setSmallIcon(R.drawable.ic_stat_name) 
      .setContentTitle(senderName) 
      .setContentText(message) 
      .setAutoCancel(true) 
      .setSound(defaultSoundUri) 
      .setContentIntent(pendingIntent); 

    NotificationManager notificationManager = 
      (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 

    notificationManager.notify(0 /* ID of notification */, notificationBuilder.build()); 
} 

private void d(String s){ 
    Log.d("MyGcmListenerService", s); 
} 

}

我RegistrationIntentService.java

private static final String TAG = "RegIntentService"; 
public RegistrationIntentService() { 
    super(TAG); 
} 

@Override 
protected void onHandleIntent(Intent intent) { 
    d("onHandleIntent"); 

    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); 

    try { 
     // In the (unlikely) event that multiple refresh operations occur simultaneously, 
     // ensure that they are processed sequentially. 
     synchronized (TAG) { 
      // [START register_for_gcm] 
      // Initially this call goes out to the network to retrieve the token, subsequent calls 
      // are local. 
      // [START get_token] 
      InstanceID instanceID = InstanceID.getInstance(this); 
      String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId), 
        GoogleCloudMessaging.INSTANCE_ID_SCOPE, null); 
      // [END get_token] 
      d("GCM Registration Token: " + token); 

      sendRegistrationToServer(token); 

      // You should store a boolean that indicates whether the generated token has been 
      // sent to your server. If the boolean is false, send the token to your server, 
      // otherwise your server should have already received the token. 
      sharedPreferences.edit().putBoolean(AlphaCashPreferences.SENT_TOKEN_TO_SERVER, true).apply(); 
      // [END register_for_gcm] 
      d("registration succeeded"); 
     } 
    } catch (Exception e) { 
     d("Failed to complete token refresh", e); 
     // If an exception happens while fetching the new token or updating our registration data 
     // on a third-party server, this ensures that we'll attempt the update at a later time. 
     sharedPreferences.edit().putBoolean(AlphaCashPreferences.SENT_TOKEN_TO_SERVER, false).apply(); 
    } 
    // Notify UI that registration has completed, so the progress indicator can be hidden. 
    Intent registrationComplete = new Intent(AlphaCashPreferences.REGISTRATION_COMPLETE); 
    d("regestration intent broadcasted"); 
    LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete); 
} 

/** 
* Persist registration to third-party servers. 
* 
* Modify this method to associate the user's GCM registration token with any server-side account 
* maintained by your application. 
* 
* @param token The new token. 
*/ 
private void sendRegistrationToServer(String token) { 
    d("Send registration token to server"); 
    // Add custom implementation, as needed. 
    Context c = getApplication(); 
    SaveRegistrationIdRequest req = new SaveRegistrationIdRequest(); 
    req.setCredentials(Installation.createCredentials(c)); 
    req.setRegId(token); 
    Installation installation = Installation.getInstance(c); 
    SendGcmRegistrationIdTask task = new SendGcmRegistrationIdTask(new ApiTask.ResultListener() { 
     @Override 
     public void successHook(Object o) { 
      //TODO After registration of the gcm id 
     } 
    }, installation, req); 

    task.execute(); 
    d("successflly sent"); 
} 

private void d(String s){ 
    Log.d("RegIntentService", s); 
} 

private void d(String s, Exception e){ 
    Log.d("RegIntentService", s, e); 
} 

}

問題

如何我可以解決我的問題,並能即時接收郵件,而不來回?

調試後我的申請,這都是警告AM充分利用logcat的

com.me.myapp W/dalvikvm﹕ VFY: unable to resolve virtual method 247: Landroid/app/ 
Notification$Builder;.setLocalOnly (Z)Landroid/app/Notification$Builder; 
10-05 16:18:11.594 32178-32178/com.me.myapp W/dalvikvm﹕ VFY: unable to resolve instance field 18 
10-05 16:18:11.603 32178-32178/com.me.myapp W/dalvikvm﹕ VFY: unable to resolve virtual method 1507: Landroid/os/UserManager;.getApplicationRestrictions (Ljava/lang/String;)Landroid/os/Bundle; 
10-05 16:18:11.605 32178-32178/com.me.myapp E/dalvikvm﹕ Could not find class 'android.app.AppOpsManager', referenced from method com.google.android.gms.common.GooglePlayServicesUtil.zzb 
+0

所以你的意思是你收到消息?只是他們沒有及時顯示或沒有刷新頁面? – Skynet

+0

@Skynet正是男人。我的通知機制沒有被觸發! –

+0

@Skynet你認爲哪裏錯了?我已經掙扎了近2周! –

回答

0

我終於解決了我的問題,這是存在的,因爲我不是從GCM服務器得到它後發送GCM註冊ID到我的應用服務器。

但是,在將它發送到我的應用程序服務器後,我的客戶端應用程序能夠在收到新消息時收到通知。

任何人遇到同樣的問題。這是的應用無法從GCM收到通知或消息(或兩者),請確保您已經(在程序上)發送GCM註冊令牌你的應用服務器

像這樣的事情

public class RegistrationIntentService extends IntentService { 
public static final String GCM_SENDER_ID = "Your ProjectID";//your project id 
private static final String TAG = "RegIntentService"; 
public static final String SENT_TOKEN_TO_SERVER = "sentTokenToServer"; 
public static final String REGISTRATION_COMPLETE = "registrationComplete"; 
public static final long GCM_TIME_TO_LIVE = 60L * 60L * 24L * 7L * 4L; // 4 Weeks 

private static final String TAG = "RegIntentService"; 

public RegistrationIntentService() { 
    super(TAG); 

} 
String regId; 
@Override 
protected void onHandleIntent(Intent intent) { 
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); 

    try { 
     // [START register_for_gcm] 
     // Initially this call goes out to the network to retrieve the token, subsequent calls 
     // are local. 
     // [START get_token] 
     InstanceID instanceID = InstanceID.getInstance(this); 
     String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId), 
       GoogleCloudMessaging.INSTANCE_ID_SCOPE, null); 
     regId = token; 
     // [END get_token] 
     Log.i(TAG, "GCM Registration Token: " + token); 

     // TODO: Implement this method to send any registration to your app's servers. 
     sendRegistrationToServer(token); 


     // You should store a boolean that indicates whether the generated token has been 
     // sent to your server. If the boolean is false, send the token to your server, 
     // otherwise your server should have already received the token. 
     sharedPreferences.edit().putBoolean(SENT_TOKEN_TO_SERVER, true).apply(); 
     // [END register_for_gcm] 
    } catch (Exception e) { 
     Log.d(TAG, "Failed to complete token refresh", e); 
     // If an exception happens while fetching the new token or updating our registration data 
     // on a third-party server, this ensures that we'll attempt the update at a later time. 
     sharedPreferences.edit().putBoolean(SENT_TOKEN_TO_SERVER, false).apply(); 
    } 
    // Notify UI that registration has completed, so the progress indicator can be hidden. 
    Intent registrationComplete = new Intent(REGISTRATION_COMPLETE); 
    LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete); 
} 


/** 
* Sends the registration ID to the 3rd party server via an upstream 
* GCM message. Ideally this would be done via HTTP to guarantee success or failure 
* immediately, but it would require an HTTP endpoint. 
*/ 

private void sendRegistrationToServer(String token) { 

String name = token 
new AsyncTask<String, Void, String>() 
{ 
    @Override 
    protected String doInBackground(String... params) 
    { 
    String msg = ""; 
    try 
    { 
     Bundle data = new Bundle(); 
     data.putString("name", params[0]); 
     data.putString("action", "com.antoinecampbell.gcmdemo.REGISTER"); 
     String id = Integer.toString(msgId.incrementAndGet()); 
     gcm.send(GCM_SENDER_ID + "@gcm.googleapis.com", id,GCM_TIME_TO_LIVE, data); 
     msg = "Sent registration"; 
    } 
    catch (IOException ex) 
    { 
     msg = "Error :" + ex.getMessage(); 
    } 
    return msg; 
    } 

    @Override 
    protected void onPostExecute(String msg) 
    { 
    Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); 
    } 
}.execute(name); 
} 
} 

試一試!

+0

請讓我知道什麼是msgId是在String id = Integer.toString(msgId.incrementAndGet());那麼在下面的行什麼是gcm和GCM_TIME_TO_LIVE? gcm.setnd(GCM_SENDER_ID +「@ gcm.googleapis.com」,id,GCM_TIME_TO_LIVE,data);和我們必須給我們的第三方服務器的網址?請讓我知道.... – shripal

+0

@shripal你收到了什麼錯誤? –

+0

我沒有收到錯誤,但沒有收到來自服務器的任何通知...只是我想確保我的應用程序註冊在服務器端或不是?或者我必須調用任何Web服務將令牌發送到服務器端? – shripal

相關問題