我尝试通过从服务器推送到客户端来实现服务器 - 客户端通信。由于客户端是Android设备,因此我使用Google云消息传递将消息从服务器推送到Android设备。我遵循了tutorial
当前状态:客户端从GCM获取注册表ID。所以客户端 - GCM通信应该没问题。尝试将消息推送到gcm时,服务器会收到以下消息:
2015-01-20T23:31:24.289 + 0100 |信息:回复代码:200 2015-01-20T23:31:24.290 + 0100 |信息:{" multicast_id":534481856434 ...,"成功":1,"失败":0 " canonical_ids":0,"结果":[{" MESSAGE_ID":" 0:1421793086402018%64d756d9f9fd7ecd"}]} 2015-01-20T23:31:24.296 + 0100 |信息:com.sun.enterprise.web.connector.coyote.PECoyoteResponse$PECoyoteWriter@49 ......
似乎客户端之间的连接 - gcm正在运行。但是gcm并没有将消息转发给我的客户。
我的gcm项目也只显示了2个请求和2000多个错误。我不太了解推送通知来处理这个问题,也许有人可以帮助我。
这是我的代码
客户 MainActivity
// ... some other imports
import com.google.android.gms.gcm.GoogleCloudMessaging;
public class MainActivity extends ActionBarActivity implements OnCheckedChangeListener {
GoogleCloudMessaging gcm;
String regid;
String PROJECT_NUMBER = pn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getRegId();
}
public void getRegId() {
new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(getApplicationContext());
}
regid = gcm.register(PROJECT_NUMBER);
msg = "Device registered, registration ID = " + regid;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
msg = "Error: " + e.getMessage();
}
Log.d("Systemablauf", "MainActivity getRegId() " + msg);
return msg;
}
}.execute(null, null, null);
}
}
客户端 MessageHandler
import com.google.android.gms.gcm.GoogleCloudMessaging;
public class GcmMessageHandler extends IntentService {
String msg;
private Handler handler;
public GcmMessageHandler(String name) {
super("GcmMessageHandler");
// TODO Auto-generated constructor stub
}
@Override
public void onCreate() {
super.onCreate();
handler = new Handler();
}
@Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
msg = extras.getString("title");
showToast();
Log.d("Systemablauf", "Received: (" + messageType + ") " + extras.getString("title"));
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
private void showToast() {
// TODO Auto-generated method stub
handler.post(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
});
}
}
客户端 BroadcastReceiver
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
// Explicitly specify that GcmMessageHandler will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(), GcmMessageHandler.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
Log.d("Systemablauf", "onReceive()");
}
}
客户端清单
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xml>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="thesis.com.example.clientsync"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
<uses-permission
android:name="android.permission.INTERNET"/>
<uses-permission
android:name="android.permission.VIBRATE"/>
<uses-permission
android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission
android:name="android.permission.WAKE_LOCK"/>
<uses-permission
android:name="com.google.android.c2dm.permission.RECEIVE"/>
<permission
android:name="thesis.com.example.clientsync.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission
android:name="thesis.com.example.clientsync.permission.C2D_MESSAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action
android:name="com.google.android.c2dm.intent.RECEIVE" />
<category
android:name="thesis.com.example.clientsync" />
</intent-filter>
</receiver>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<service
android:name="service.MainService" />
</application>
</manifest>
服务器 Servlet
@WebServlet("/ServerServlet")
public class ServerServlet extends HttpServlet {
public ServerServlet() {
super();
// TODO Auto-generated constructor stub
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
sendNotification();
}
private void sendNotification() {
System.out.println("Sending POST to GCM");
String apiKey = "AIzaSyA0pOZf13cZzqQHrWBZfFE9XFMHA5ftiAo";
Content content = createContent();
POST2GCM.post(apiKey, content);
}
private static Content createContent() {
// TODO Auto-generated method stub
Content c = new Content();
c.addRegId("APA91bFrSX_mGLzLUf2Va6...");
c.createData("Test Title", "Test Message");
return c;
}
}
服务器发布
public class POST2GCM {
public static void post(String apiKex, Content content) {
String apiKey = "AIzaSyA0pO...";
try {
URL url = new URL("https://android.googleapis.com/gcm/send");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Authorization", "key = " + apiKey);
connection.setDoOutput(true);
Gson gsonMapper = new GsonBuilder().create();
DataOutputStream writer = new DataOutputStream(connection.getOutputStream());
writer.writeBytes(gsonMapper.toJson(content));
writer.flush();
writer.close();
int responseCode = connection.getResponseCode();
System.out.println("\nSending 'POST' request to URL: " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null)
response.append(inputLine);
in.close();
System.out.println(response.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
服务器内容
@SuppressWarnings("serial")
public class Content implements Serializable {
private List<String> registration_ids;
private Map<String, String> data;
public void addRegId (String regId) {
if (registration_ids == null)
registration_ids = new LinkedList<String>();
registration_ids.add(regId);
}
public void createData (String title, String message) {
if (data == null)
data = new HashMap<String, String>();
data.put("title", title);
data.put("message", message);
}
}