Google Cloud Messaging (GCM) with local device groups on Android gives HTTP Error code 401

后端 未结 3 1444
死守一世寂寞
死守一世寂寞 2020-11-30 14:37

I am trying to get Google Cloud Messaging (GCM) to work on Android with local device groups as described on https://developers.google.com/cloud-messaging/android/client-devi

3条回答
  •  伪装坚强ぢ
    2020-11-30 15:28

    This is how it is done using the SERVER_API_KEY (not best practice, but the best I have arrived at yet):

    First, get an application instance id:

    InstanceID instanceID = InstanceID.getInstance(this);
    String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
        GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
    
    // Variable "token" now has the instance id. :-)
    

    Next, get the messaging id token:

    String account = ACCOUNT_NAME; // E.g. "johndoe@google.com"
    String scope = "audience:server:client_id:" + WEB_APPLICATION_CLIENT_ID;
    String idToken = GoogleAuthUtil.getToken(context, account, scope);
    
    // Variable "idToken" now hods the messaging id token. :-)
    

    Now to the magic part. Create a new device group with the instance Id as a member:

    URL url = new URL("https://gcm-http.googleapis.com/gcm/notification"); // <-- Use this URL!
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("POST");
    connection.setDoOutput(true);
    connection.setDoInput(true);
    connection.setRequestProperty("Authorization", "key=" + SERVER_API_KEY); // <--- Auth!
    connection.setRequestProperty("project_id", NUMERICAL_PROJECT_ID);
    connection.setRequestProperty("Content-Type", "application/json");
    connection.setRequestProperty("Accept", "application/json");
    connection.connect();
    
    JSONObject requestBody = new JSONObject();
    requestBody.put("operation", "create");               // <--- Not "add"
    requestBody.put("notification_key_name", "foobar");
    requestBody.put("registration_ids", 
        new JSONArray(Arrays.asList(new String[]{token}))); // <--- Instance Id token here!
    requestBody.put("id_token", idToken);
    
    OutputStream os = connection.getOutputStream();
    os.write(requestBody.toString().getBytes("UTF-8"));
    os.close();
    
    InputStream is = connection.getInputStream();
    String responseString = new Scanner(is, "UTF-8").useDelimiter("\\A").next();
    is.close();
    
    JSONObject response = new JSONObject(responseString);
    Log.d(TAG, "Server response:\n" + response.toString(4));
    String notificationKey = response.getString("notification_key");
    

    At this point, the variable "notificationKey" holds the notification key which is the recipient that must be used when sending messages to this device group.

    Send a message like this (use the "notificationKey" value as parameter as receipient from above):

    private void sendMessage(String recipient) throws IOException, JSONException {
    
        Log.i(TAG, "Sending message to: " + recipient);
        URL url = new URL("https://gcm-http.googleapis.com/gcm/send");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        connection.setDoOutput(true);
        connection.setDoInput(true);
    
        Log.d(TAG, "Opening connection to " + url.toString());
    
        connection.setRequestProperty("Authorization", "key=" + SERVER_API_KEY);
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("Accept", "application/json");
        connection.connect();
    
        JSONObject requestBody = new JSONObject();
        requestBody.put("to", recipient);
        JSONObject requestData = new JSONObject();
        requestData.put("hello", "Hello World!");
        requestData.put("hellodata", "42");
        requestBody.put("data", requestData);
    
        Log.d(TAG, "Request body:\n" + requestBody.toString(4));
    
        OutputStream os = connection.getOutputStream();
        os.write(requestBody.toString().getBytes("UTF-8"));
        os.close();
    
        Log.d(TAG, "Response code: " + connection.getResponseCode());
    
        InputStream is = connection.getInputStream();
        String responseString = new Scanner(is, "UTF-8").useDelimiter("\\A").next();
        is.close();
    }
    

    I have not succeeded in doing this without using the server API key. It might be worthwhile to investigate with different Authorization header values on the https://http.googleapis.com/gcm/googlenotification endpoint.

    Hopefully this makes sense. Have fun. :-)

提交回复
热议问题