我很难通过 c2dm 接收消息。实际上,我偶尔会收到来自我们服务器的消息,但实际上只是数据的一半。(我期待一个 4 位数字,但只收到前 2 位数字.. oO")。但是最近我们的广播接收器保持绝对沉默。因此我开始试验并将我自己的 c2dm 消息推送到谷歌服务器,看看情况如何是做。
在帖子的底部,您可以找到我如何发送和接收 c2dm 消息的示例类。这一切几乎都是独立的,因此您可以将其插入一些活动并拍摄C2dmStaticTest.autopilot( yourSenderId, "foo bar", yourServerSideAuthCode, this, this.getPackageName());
让我概述正在发生的事情:
- 设置要在 BroadcastReceiver 中使用的静态变量
- 注册广播接收器并设置动作和类别,
androidManifest.xml
否则它将如何。 - 向 c2dm 服务器发送注册意图。
注意:本地内置广播接收器将为每个接收到的意图生成一条日志消息!每次在类中发出日志消息时,标签都会是“c2dmTest”。
当收到带有 registration_id 的 c2dm 答案时,这也会被记录下来,然后会推送一条 c2dm 消息。
我在这里尽可能地模拟我们的服务器以获得更多控制权。作为回测,我还发出了一条模拟实际 Intent 的 fakeC2DM 消息,并测试广播接收器在 RECEIVE 操作上的功能。
虽然我可以从 c2dm 服务器接收注册令牌,但我没有收到我推送到服务器的任何消息。正如介绍中提到的,当我们的 Web 服务器发送消息时,我观察到相同的行为。
我尽了最大努力,我相信我已经相应地实现了广播接收器,并且由于消息发送的服务器响应代码始终为 200/OK,我也相信消息已成功传递到服务器。
然而结果不是预期的,但我真的缺乏任何想法我还能做什么。寻找诸如“无法保证消息传递”之类的段落也不令人鼓舞。我的意思是现在根本没有交付任何东西:C
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
public class C2dmStaticTest {
private static String RECEIVE = "com.google.android.c2dm.intent.RECEIVE";
private static String REGISTER = "com.google.android.c2dm.intent.REGISTER";
private static String REGISTRATION = "com.google.android.c2dm.intent.REGISTRATION";
private static Context ctx;
private static String packageName;
private static String message;
private static String auth_code;
private static IntentFilter mIntFilt = new IntentFilter();
//@formatter:off
private static BroadcastReceiver mBroadRec = new BroadcastReceiver() {
@Override
public void onReceive( Context context, Intent intent ) {
final String broadcastAction = intent.getAction();
C2dmStaticTest.log("localReceiver onReceive for action: "+ broadcastAction);
if (C2dmStaticTest.REGISTRATION.equals(broadcastAction)) {
//execution continues here upon arrival of registration_id
String registration_id = intent.getStringExtra("registration_id");
C2dmStaticTest.log("registered for c2dm.\n key is: "+registration_id);
C2dmStaticTest.log("==> start real self test");
selfTestC2DM(registration_id, message, auth_code);
C2dmStaticTest.log("<== real self test done");
C2dmStaticTest.log("==> start fake test");
selfTestFake();
C2dmStaticTest.log("<== fake test done");
C2dmStaticTest.log("<~~ bye");
} else if (C2dmStaticTest.RECEIVE.equals(broadcastAction)) {
C2dmStaticTest.log("Received message: " + intent.getStringExtra("message") );
}
}
};
//@formatter:on
public static void autopilot( String sender_id, String message, String auth_code, Context ctx, String packageName ) {
// setup static variables
C2dmStaticTest.ctx = ctx;
C2dmStaticTest.packageName = packageName;
C2dmStaticTest.message = message;
C2dmStaticTest.auth_code = auth_code;
C2dmStaticTest.log("==> register broadcastReceiver");
mIntFilt.addAction("com.google.android.c2dm.intent.RECEIVE");
mIntFilt.addAction("com.google.android.c2dm.intent.REGISTRATION");
mIntFilt.addCategory(packageName);
ctx.registerReceiver(mBroadRec, mIntFilt);
C2dmStaticTest.log("==> register for c2dm");
C2dmStaticTest.registerForC2dm(ctx, sender_id);
// will continue in localBroadCastReceiver on Receive for REGISTRATION
}
private static void registerForC2dm( Context ctx, String sender_id ) {
Intent registrationIntent = new Intent(C2dmStaticTest.REGISTER);
registrationIntent.putExtra("app", PendingIntent.getBroadcast(ctx, 0, new Intent(), 0)); // boilerplate
registrationIntent.putExtra("sender", sender_id);
ctx.startService(registrationIntent);
}
private static void selfTestFake() {
Intent intent = new Intent();
intent.setAction(C2dmStaticTest.RECEIVE);
intent.putExtra("message", "Bender: \"kiss my shiny metal ass!\"");
intent.addCategory(C2dmStaticTest.packageName);
C2dmStaticTest.ctx.sendBroadcast(intent);
}
public static void selfTestC2DM( String registration_id, String message, String auth_code ) {
// create HttpClient
HttpClient mHttpClient = new DefaultHttpClient();
// create HttpPost
final HttpPost post = new HttpPost("https://android.apis.google.com/c2dm/send");
post.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
post.addHeader("Authorization", "GoogleLogin auth=" + auth_code);
// set payload data ...
final List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("registration_id", registration_id));
nameValuePairs.add(new BasicNameValuePair("collapse_key", "foo"));
nameValuePairs.add(new BasicNameValuePair("data.message", message));
// ... and push it in the post
try {
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
} catch (final Exception e) {
e.printStackTrace(); // never had a problem here
}
// start it!
try {
HttpResponse resp = mHttpClient.execute(post);
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// now the message should be send, not?
C2dmStaticTest.log("Message send.\nServer response: " + resp.getStatusLine().getStatusCode());
} else {
C2dmStaticTest.log("Unexpected Server response.\nServer response: " + resp.getStatusLine().getStatusCode());
}
} catch (final Exception e) {
C2dmStaticTest.log("Unexpected Exception in execute()");
e.printStackTrace();
}
}
public static void log( String message ) {
Log.d("c2dmTest", message);
}
}