Android c2dm автоматически отменяет регистрацию

Когда я отправляю уведомление на устройство, это устройство получает push-сообщение, но оно получает намерение «com.google.android.c2dm.intent.REGISTRATION», а не «com.google.android.c2dm.intent.RECEIVE». . Если я попытаюсь отправить второе уведомление, я получаю сообщение об ошибке «Не зарегистрировано» от Google.

Устройство регистрируется нормально (я думаю), потому что я получаю токен аутентификации «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();
    }

Мой получатель:

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 */
    }
}

Я делаю push-уведомления на устройстве, потому что, если я делаю это на стороне сервера, я всегда получаю ошибку «InvalidRegistration».

Странно то, что кажется, что я регистрируюсь, но когда я отправляю одно push-сообщение, это похоже на то, что Google отменяет регистрацию устройства.

Есть идеи/предложения?


person Guillem    schedule 23.05.2011    source источник
comment
Я улучшил код, теперь я выполняю службу ac2dm на своем сервере (php), но ответ тот же, на устройстве я получаю петицию об отмене регистрации. Код такой же, как здесь: ссылка   -  person Guillem    schedule 24.05.2011
comment
Я тоже столкнулся с той же проблемой.. пожалуйста, помогите мне   -  person Jomia    schedule 12.09.2011


Ответы (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

и тогда он работал правильно, поэтому имя пакета 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>
person Hillkorn    schedule 14.06.2012

Иногда решение находится у вас на лице, и вы его не видите, для тех, у кого возникла такая же проблема, как у меня, проблема была в манифесте, я плохо пишу имя пакета.

person Guillem    schedule 24.05.2011
comment
Можете ли вы предоставить больше информации? Я столкнулся с той же проблемой. Я не вижу никаких проблем в моем манифесте. - person paulpooch; 02.04.2012