简体   繁体   中英

Can't connect to Google Cloud Messaging (GCM) server using Google App Engine (GAE)

I am trying to set up google cloud messaging for my app, and I am using Google App Engine for my server. I have my API key but I can't seem to make a connection to the google cloud messaging servers. Here is my code.

HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://android.googleapis.com/gcm/send");
        try {

            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
            nameValuePairs.add(new BasicNameValuePair("registration_id", regId));
            nameValuePairs.add(new BasicNameValuePair("data.message", messageText));    

            post.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            post.setHeader("Authorization", "key=*MY_API_KEY_HERE*");
            post.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");


            Header[] s=post.getAllHeaders();


            System.out.println("The header from the httpclient:");

            for(int i=0; i < s.length; i++){
            Header hd = s[i];

            System.out.println("Header Name: "+hd.getName()
                    +"       "+" Header Value: "+ hd.getValue());
            }


            HttpResponse response = client.execute(post);
            BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            String line = "";
            while ((line = rd.readLine()) != null) {
            System.out.println(line);
            }

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

When I look at the log the headers are being setup right. However, I get an error that says

org.apache.http.impl.client.DefaultRequestDirector tryConnect: I/O exception (java.net.SocketException) caught when connecting to the target host: Permission denied: Attempt to access a blocked recipient without permission. (mapped-IPv4)

I've turned google cloud messaging on in the Google APIs Console and I've checked my API key a bunch of times. I have no clue why I'm getting rejected. Is there a jar I need in the war or something I have to put in the manifest?

Thanks for reading this!! Mark

I had the same problem and I was using something similar to what you are using.

  1. I had to enable billing on my GAE app ( which you probably have but I wasn't aware that I would have to)
  2. Read https://developers.google.com/appengine/docs/java/sockets/ and https://developers.google.com/appengine/docs/java/urlfetch/

Therefore my code which looked like yours before now looks like following:

String json ="{}"; 
URL url = new URL("https://android.googleapis.com/gcm/send");
HTTPRequest request = new HTTPRequest(url, HTTPMethod.POST);
request.addHeader(new HTTPHeader("Content-Type","application/json")); 
request.addHeader(new HTTPHeader("Authorization", "key=<>"));
request.setPayload(json.getBytes("UTF-8"));
HTTPResponse response = URLFetchServiceFactory.getURLFetchService().fetch(request);

I was also implementing GCM with GAE, and I had an error like this:

com.google.apphosting.api.ApiProxy$FeatureNotEnabledException: The Socket API will be enabled for this application once billing has been enabled in the admin console.

Nikunj answer helped me too. After implementing what he suggested, notifications are delivered to the device, without need for enabling billing for my GAE App. Here is my implementation, just in case, may be useful for someone with same problem:

private void sendNotificationRequestToGcm(List<String> registrationIds) {
    LOG.info("In sendNotificationRequestToGcm method!");
    JSONObject json = new JSONObject();
    JSONArray jasonArray = new JSONArray(registrationIds);
    try {
        json.put("registration_ids", jasonArray);
    } catch (JSONException e2) {
        LOG.severe("JSONException: " + e2.getMessage());
    }
    String jsonString = json.toString();
    LOG.info("JSON payload: " + jsonString);

    com.google.appengine.api.urlfetch.HTTPResponse response;
    URL url;
    HTTPRequest httpRequest;
    try {
        //GCM_URL = https://android.googleapis.com/gcm/send
        url = new URL(GCM_URL);
        httpRequest = new HTTPRequest(url, HTTPMethod.POST);
        httpRequest.addHeader(new HTTPHeader("Content-Type","application/json"));
        httpRequest.addHeader(new HTTPHeader("Authorization", "key=" + API_KEY));
        httpRequest.setPayload(jsonString.getBytes("UTF-8"));
        LOG.info("Sending POST request to: " + GCM_URL);
        response = URLFetchServiceFactory.getURLFetchService().fetch(httpRequest);
        LOG.info("Status: " + response.getResponseCode());            
        List<HTTPHeader> hdrs = response.getHeaders();
        for(HTTPHeader header : hdrs) {
            LOG.info("Header: " + header.getName());
            LOG.info("Value:  " + header.getValue());
        }            
    } catch (UnsupportedEncodingException e1) {
        LOG.severe("UnsupportedEncodingException" + e1.getMessage());
    } catch (MalformedURLException e1) {
        LOG.severe("MalformedURLException" + e1.getMessage());
    } catch (IOException e) {
        LOG.severe("URLFETCH IOException" + e.getMessage());
    }
}

Hope this will help someone...

The easiest way is to use gcm-server.jar (which you can get from here ).

Then the code you'll need to send a GCM message will look like this :

Sender sender = new Sender(apiKey);
Message message = new Message.Builder()
    .addData("message", "this is the message")
    .addData("other-parameter", "some value")
    .build();
Result result = sender.send(message, registrationId, numOfRetries);

Here's the gradle dependency: compile 'com.google.gcm:gcm-server:1.0.0' and mvnrepository url

source

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM