2011-05-23 153 views
5

當我向設備發送通知時,此設備會收到推送消息,但會收到「com.google.android.c2dm.intent.REGISTRATION」意圖,而不是「com.google.android .c2dm.intent.RECEIVE」。 如果我嘗試發送第二個通知,我會收到Google發出的「NotRegistered」錯誤。Android c2dm自動取消註冊

該設備獲得註冊罰款(我猜),因爲我得到的身份驗證令牌「APA91 ... -119個字符」。

這裏是我的代碼,開始註冊設備:

Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER"); 
registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); 
registrationIntent.putExtra("sender", "EMAIL"); 
startService(registrationIntent); 

發件人(這是在Android設備上完成):

HttpClient client = new DefaultHttpClient(); 
    HttpPost post = new HttpPost("https://www.google.com/accounts/ClientLogin"); 

    try { 

     List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1); 
     nameValuePairs.add(new BasicNameValuePair("Email", "SAME AS LOGIN")); 
     nameValuePairs.add(new BasicNameValuePair("Passwd", "****")); 
     nameValuePairs.add(new BasicNameValuePair("accountType", "HOSTED_OR_GOOGLE")); 
     nameValuePairs.add(new BasicNameValuePair("source","Google-cURL-Example")); 
     nameValuePairs.add(new BasicNameValuePair("service", "ac2dm")); 

     post.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 
     HttpResponse response = client.execute(post); 
     BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); 

     String line = ""; 
     while ((line = rd.readLine()) != null) { 
      Log.e("C2DM", line); 
      if (line.startsWith("Auth=")) { 
       s = line.substring(5);//LOGIN TOKEN 
       Log.i("C2DM", "Token get: "+ s); 
        String auth_key = s; /* GETTING THE AUTH TOKEN FROM SERVER */ 
        StringBuilder postDataBuilder = new StringBuilder(); 
        postDataBuilder.append(PARAM_REGISTRATION_ID).append("=").append(auth_key); 
        postDataBuilder.append("&").append(PARAM_COLLAPSE_KEY).append("=").append("0"); 
        postDataBuilder.append("&").append("data.info").append("=").append(URLEncoder.encode("Invitar", UTF8)); 
      URLEncoder.encode(telephonyManager.getDeviceId(), UTF8)); 

      byte[] postData = postDataBuilder.toString().getBytes(UTF8); 

      URL url = new URL("https://android.clients.google.com/c2dm/send"); 

      HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
      conn.setDoOutput(true); 
      conn.setUseCaches(false); 
      conn.setRequestMethod("POST"); 
      conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded;charset=UTF-8"); 
      conn.setRequestProperty("Content-Length",Integer.toString(postData.length)); 
      conn.setRequestProperty("Authorization", "GoogleLogin auth="+ auth_key); 

      OutputStream out = conn.getOutputStream(); 
      out.write(postData); 
      out.close(); 

      int responseCode = conn.getResponseCode(); 

      Log.e("C2DM", String.valueOf(responseCode)); 
      // Validate the response code 

      if (responseCode == 401 || responseCode == 403) { 
       Log.e("C2DM", "Unauthorized - need token"); 
      } 

      // Check for updated token header 
      String updatedAuthToken = conn.getHeaderField(UPDATE_CLIENT_AUTH); 
      if (updatedAuthToken != null && !auth_key.equals(updatedAuthToken)) { 
       Log.i("C2DM","Got updated auth token from datamessaging servers: "+ updatedAuthToken); 
       Editor edit = prefManager.edit(); 
       edit.putString(AUTH, updatedAuthToken); 
      } 

      String responseLine = new BufferedReader(new InputStreamReader(conn.getInputStream())).readLine(); 

      if (responseLine == null || responseLine.equals("")) { 
       Log.i("C2DM", "Got " + responseCode+ " response from Google AC2DM endpoint."); 
       throw new IOException("Got empty response from Google AC2DM endpoint."); 
      } 

      String[] responseParts = responseLine.split("=", 2); 
      if (responseParts.length != 2) { 
       Log.e("C2DM", "Invalid message from google: " + responseCode+ " " + responseLine); 
       throw new IOException("Invalid response from Google "+ responseCode + " " + responseLine); 
      } 

      if (responseParts[0].equals("id")) { 
       Log.i("C2DM", "Successfully sent data message to device: "+ responseLine); 
       retval = 1; 
      } 

      if (responseParts[0].equals("Error")) { 
       String err = responseParts[1]; 
       Log.w("C2DM","Got error response from Google datamessaging endpoint: "+ err); 
       // No retry. 
       throw new IOException(err); 
      } 
       return sendMessage(); 
      } 

     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

我reciever:

public void onReceive(Context context, Intent intent) { 
    Log.d("C2DM", "Intent recieved: "+intent.getAction()); 
    if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) { 
     handleRegistration(context, intent); 
    } else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) { 
     handleMessage(context, intent); 
    } 
} 

private void handleRegistration(Context context, Intent intent) { 
    String registration = intent.getStringExtra("registration_id"); 
    if (intent.getStringExtra("error") != null) { 
     // Registration failed, should try again later. 
     Log.d("C2DM", "registration failed"); 
     String error = intent.getStringExtra("error"); 
     if(error == "SERVICE_NOT_AVAILABLE"){ 
      Log.d("c2dm", "SERVICE_NOT_AVAILABLE"); 
     }else if(error == "ACCOUNT_MISSING"){ 
      Log.d("c2dm", "ACCOUNT_MISSING"); 
     }else if(error == "AUTHENTICATION_FAILED"){ 
      Log.d("c2dm", "AUTHENTICATION_FAILED"); 
     }else if(error == "TOO_MANY_REGISTRATIONS"){ 
      Log.d("c2dm", "TOO_MANY_REGISTRATIONS"); 
     }else if(error == "INVALID_SENDER"){ 
      Log.d("c2dm", "INVALID_SENDER"); 
     }else if(error == "PHONE_REGISTRATION_ERROR"){ 
      Log.d("c2dm", "PHONE_REGISTRATION_ERROR"); 
     } 
    } else if (intent.getStringExtra("unregistered") != null) { 
     //HERE IS WHERE ARRIVES THE SEND NOTIFICATION (NOT THE UNREGISTER NOTIFICATION) 
     Log.d("C2DM", "unregistered: "+intent.getStringExtra("unregistered")); 

    } else if (registration != null) { 
     Log.d("C2DM", registration); 
     /* SENDING THE AUTH TOKET TO SERVER */ 
    } 
} 

我在設備上執行推送通知,因爲如果我在服務器端執行操作,我總是會收到「InvalidRegistration」錯誤。

奇怪的是,它似乎我已經註冊,但當我發送一個推送消息,就像谷歌取消註冊設備。

任何想法/建議?

+0

我改進了代碼,現在,我在我的服務器(php)中執行了ac2dm服務,但響應是相同的,在設備上我收到請求註銷的設備。代碼是這樣的:[鏈接](http://stackoverflow.com/questions/4121508/c2dm-implementation-php-code) – Guillem 2011-05-24 08:31:30

+0

我也面臨同樣的問題..請幫我 – Jomia 2011-09-12 05:40:42

回答

1

有時候,解決的辦法是在你的臉上,你看不到它,對於那些誰得到了同樣的問題,我的問題是在清單中,我不寫的不好的包命名

+0

你能提供更多信息?我遇到了同樣的問題。我的清單中沒有看到任何問題。 – paulpooch 2012-04-01 20:24:06

2

我有同樣的問題,並修復它。

這裏是錯誤的代碼

<receiver android:name=".MyC2DMReceiver" 
      android:permission="com.google.android.c2dm.permission.SEND"> 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> 
      <category android:name="com.package.myapp" /> 
     </intent-filter> 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.permission.RECEIVE" /> 
      <category android:name="com.package.myapp" /> 
     </intent-filter> 
    </receiver> 

我不得不寫意圖,而不是許可

com.google.android.c2dm.permission.RECEIVE => com.google.android.c2dm.intent.RECEIVE 

,然後它的工作正確 所以接收的包名是錯誤的

權代碼

<receiver android:name=".MyC2DMReceiver" 
      android:permission="com.google.android.c2dm.permission.SEND"> 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> 
      <category android:name="com.package.myapp" /> 
     </intent-filter> 
     <intent-filter> 
      <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
      <category android:name="com.package.myapp" /> 
     </intent-filter> 
    </receiver>