Android c2dm自动注销
当我向设备发送通知时,该设备会收到推送消息,但它会收到“com.google.android.c2dm.intent.REGISTRATION”意图,而不是“com.google.android.c2dm.intent.RECEIVE” 。 如果我尝试发送第二个通知,我会收到来自 Google 的“NotRegistered”错误。
该设备注册正常(我猜),因为我获得了身份验证令牌“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 */
}
}
我在设备上执行推送通知,因为如果我在服务器端执行,我总是会收到“InvalidRegistration”错误。
奇怪的是,似乎我已经注册了,但是当我发送一条推送消息时,就像 Google 取消注册设备一样。
有什么想法/建议吗?
When I send a notification to a device, this device gets the push message, but it receive a "com.google.android.c2dm.intent.REGISTRATION" intent, not a "com.google.android.c2dm.intent.RECEIVE".
If I try to send a second notification, I get the "NotRegistered" error from Google.
The device gets registered fine (I guess), because I get the Auth token "APA91... -119 characters-".
Here is my code to start registering the device:
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);
The sender (this is done in the Android device):
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();
}
My 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 */
}
}
I do the push notifications on the device because if I do in server side, I always get an "InvalidRegistration" error.
The strange thing is that it seems like I get registered, but when I send one push message, is like Google unregister the device.
Any idea/suggestion?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我有同样的问题并解决了它。
这是错误的代码,
我写的是意图而不是权限
,然后它就可以正常工作
所以RECEIVE的包名是错误的
正确代码
I had the same problem and fixed it.
here is the wrong code
I had write intent instead of permission
and then it worked correctly
so the package name of RECEIVE was wrong
right code
有时候,解决方案就在你的面前,你却看不到它,对于那些和我有同样问题的人来说,问题出在Manifest中,我没有写好包名
Sometimes, the solution is in your face and you don't see it, for those who got the same problem as me, the issue was in the Manifest, I don't write well the packages name