Registering devices for push notifications

9 posts, 1 answers
  1. Mark
    Mark avatar
    11 posts
    Member since:
    Oct 2015

    Posted 19 Apr Link to this post

    i am having trouble sending push notifications to segments of users as no userid is getting attached to device registrations. i am checking device registeration after login, in the main activity. all other parameters such as hardware info, location and push token are getting set correctly, but not the user id.

     

    private void registerDeviceTelerik() {
     
        Map<String, Object> params = new HashMap<>();
        params.put("UserId", userId);
        params.put("PushToken", TokenGCM);
        params.put("HardwareId", android_id);
        params.put("HardwareModel", model);
        params.put("PlatformType", 3);
        params.put("PlatformVersion", release);
        params.put("Locale", locale);
        params.put("TimeZone", "Europe/London");
     
     
        Log.d(TAG, params.toString());
     
        JsonObjectRequest postRequest = new JsonObjectRequest(Request.Method.POST, TELERIK_URL, new JSONObject(params),
                new Response.Listener<JSONObject>() {
     
                    @Override
                    public void onResponse(JSONObject response) {
                        try {
                            Log.v("Response:%n %s", response.toString(4));
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                if (error.getMessage() != null) {
                    Log.e("Error: ", error.getMessage());
                }
            }
        }) {
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                HashMap<String, String> headers = new HashMap<>();
                headers.put("Content-Type", "application/json; charset=utf-8");
     
                if (!SingletonClass.getInstance().getAccessToken().getToken().toString().equals(null)) {
                    headers.put("Authorization", "bearer " + SingletonClass.getInstance().getAccessToken().getToken().toString());
                }
                return headers;
     
            }
        };
     
        ConnectionManager.getInstance(MainActivity.this).add(postRequest);
     
    }
     
    private void isDeviceRegisteredTelerik() {
     
        isRegistered = false;
     
        try {
            TELERIK_DEVICE_URL += URLEncoder.encode(android_id, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
     
        JsonObjectRequest postRequest = new JsonObjectRequest(TELERIK_DEVICE_URL, new JSONObject(),
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        try {
                            Log.d("Response:%n %s", response.toString(4));
                            Log.d("Device registered: ", "TRUE");
                            isRegistered = true;
     
                        } catch (JSONException e) {
                            isRegistered = false;
                            Log.d("Device registered: ", "FALSE");
                            e.printStackTrace();
                            registerDeviceTelerik();
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                if (error.getMessage() != null) {
                    Log.e("Error: ", error.getMessage());
                    Log.d("Device registered: ", "FALSE");
                    Log.e("Device registered: ", "FALSE");
     
                } else {
                    registerDeviceTelerik();
                }
     
     
            }
        });
     
        ConnectionManager.getInstance(MainActivity.this).add(postRequest);
     
    }

     

  2. Martin
    Admin
    Martin avatar
    67 posts

    Posted 21 Apr Link to this post

    Hi Mark,

    1. Registering a device - UserId

    When registering a device for push notification, the UserId is set automatically when you provide an authorization token in the header of the request:

    Authorization -> Bearer your-auth-token

    Setting "UserId" explicitly will be disregarded by the server. Please check if there is a logged-in user when registering the device for push notification. 

    2. Registering a device - custom fields

    To pass a custom parameter when registering a device for push notification or updating a device registration you have to pass the custom parameters as a separate JSON object under "Parameters" key in your params JSONObject - here is an example. You may alter your code like this:

    Map < String, Object > customParams = new HashMap < > ();
    customParams.put("City", "Chicago");
     
    Map < String, Object > params = new HashMap < > ();
    params.put("Parameters", customParams);
    params.put("PushToken", TokenGCM);
    params.put("HardwareId", android_id);
    params.put("HardwareModel", model);
    params.put("PlatformType", 3);
    params.put("PlatformVersion", release);
    params.put("Locale", locale);
    params.put("TimeZone", "Europe/London");

     3. Sending a targeted push notification

    To send a push notification to a specific device/devices you can use a device parameter field like "HardwareId" or a User related field like "Email" or a custom field like "City".

    Note that the filter should be a JSON object represented as a string.

    • Filter when sending to device parameter fields:
      {
        "Filter": "{\"HardwareId\": \"device-hardware-id-here\"}",
        "Message": "Sample message"
      }
    • Filter when sending to User related fields ("UserId" should be set):
      {
        "Filter": "{\"User.Email\": \"jsmith@example.com\"}",
        "Message": "Sample message"
      }


    • Filter when sending to custom parameters fields:
      {
        "Filter": "{\"Parameters.City\": \"Chicago\"}",
        "Message": "Sample message"
      }


    • Example of a complex filter (to users either in Chicago or Boston):
      {
        "Filter": "{\"$or\":[{\"Parameters.City\":\"Chicago\"},{\"Parameters.City\":\"Boston\"}]}",
        "Message": "Sample message"
      }


    Hope this has helped.



    Regards,
    Martin
    Telerik
     
    Everlive is now Telerik Backend Services, and is part of the Telerik Platform.
     
  3. Mark
    Mark avatar
    11 posts
    Member since:
    Oct 2015

    Posted 21 Apr in reply to Martin Link to this post

    isn't the following line setting the token? 

    headers.put("Authorization", "bearer " + SingletonClass.getInstance().getAccessToken().getToken().toString());

    the following method doesn't appear to be getting called

    public Map<String, String> getHeaders() throws AuthFailureError

    I have inherited this project and as such did not go trough the pain of setting this up in the first place. I know this was working at some stage on or before i inherited the project as there were  device registrations that had user ids set.

     

     

  4. Martin
    Admin
    Martin avatar
    67 posts

    Posted 25 Apr Link to this post

    Hi Mark,

    Indeed the line:

    headers.put("Authorization", "bearer " + SingletonClass.getInstance().getAccessToken().getToken().toString());

     will set the authorization token if there is a logged-in user. Otherwise the header will not be set and the "UserId" will not be populated.

    You can review the documentation on User Management for more information about the basic user operations.

    Setting the headers in the "postRequest" looks OK. This approach was discussed in your private ticket 989063.

    Please check if you are registering a device with a logged-in user and let me know if you need more help.

    Regards,
    Martin
    Telerik
     
    Everlive is now Telerik Backend Services, and is part of the Telerik Platform.
     
  5. Mark
    Mark avatar
    11 posts
    Member since:
    Oct 2015

    Posted 25 Apr in reply to Martin Link to this post

    Hi Martin, 

    The ticket you mentioned is on my former colleague created. the code appears to work some times as there is a new device registration from someone who has downloaded the app and the user id is set for her device. I also did some more testing on my device and it appears to work properly when using the login form as opposed to facebook login. but creating other content types from the facebook account works fine it only appears to be device registerations

  6. Martin
    Admin
    Martin avatar
    67 posts

    Posted 27 Apr Link to this post

    Hi Mark,

    I have tested the scenario you mentioned - registering a user with Facebook account and then registering the device with this logged in user and all works as expected.

    The steps when testing were:

    1. Login an existing user with Facebook login method
    2. After successful user login, get the stored access token (make sure it is not null)
    3. Register the device for push notification with the access token

    Here is a sample code I used:

     
    // Login a user registered with Facebook with loginWithFacebook method
    everliveApp.workWith().authentication().loginWithFacebook(facebookToken).executeAsync(new RequestResultCallbackAction() {
        @Override
        public void invoke(RequestResult requestResult) {
     
            if (requestResult.getSuccess()) {
                // Make sure the login is successful and there is an access token present.
                String token = everliveApp.getAccessToken().getToken().toString();
                Log.d("TAG", token);
     
                // Register the device for push notification here (after the access token is present).
            } else {
                Log.d("TAG", requestResult.getError().getMessage());
            }
        }
    });

     Could you please test  in your code if when registering the device the access token is not "null"?

    If the problem persists please attach a project that can be used to reproduce the issue in this thread and we will look into it.

    Regards,
    Martin
    Telerik
     
    Everlive is now Telerik Backend Services, and is part of the Telerik Platform.
     
  7. Mark
    Mark avatar
    11 posts
    Member since:
    Oct 2015

    Posted 27 Apr in reply to Martin Link to this post

    Thank you the issue is now solved
  8. Mark
    Mark avatar
    11 posts
    Member since:
    Oct 2015

    Posted 03 May in reply to Martin Link to this post

    The issue was i was not passing on the token when logging in with facebook. i would now like to implement the device registration every time the app runs to register the devices of people who have already registered (release an update). But i am having the same problem here, no userID being set 

     

    private void registerDeviceTelerik() {
     
        Log.d(TAG, app.everliveApp.getAccessToken().toString());
     
        app.everliveApp.workWith().users().getMe().executeAsync(new RequestResultCallbackAction() {
            @Override
            public void invoke(RequestResult requestResult) {
                if (requestResult.getSuccess()) {
     
     
                    Log.d(TAG, requestResult.toString());
     
                    Map<String, Object> params = new HashMap<>();
                    params.put("PushToken", TokenGCM);
                    params.put("HardwareId", android_id);
                    params.put("HardwareModel", model);
                    params.put("PlatformType", 3);
                    params.put("PlatformVersion", release);
                    params.put("Locale", locale);
                    params.put("TimeZone", "Europe/London");
     
                    Log.d(TAG + " Params", params.toString());
     
                    JsonObjectRequest postRequest = new JsonObjectRequest(Request.Method.POST, TELERIK_URL, new JSONObject(params),
                            new Response.Listener<JSONObject>() {
     
                                @Override
                                public void onResponse(JSONObject response) {
                                    try {
                                        Log.v("Response:%n %s", response.toString(4));
                                    } catch (JSONException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }, new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            if (error.getMessage() != null) {
                                Log.e("Error: ", error.getMessage());
                            }
                        }
                    }) {
                        @Override
                        public Map<String, String> getHeaders() throws AuthFailureError {
     
                            HashMap<String, String> headers = new HashMap<>();
                            headers.put("Content-Type", "application/json; charset=utf-8");
     
                            if (!SingletonClass.getInstance().getAccessToken().getToken().equals(null)) {
                                Log.d(TAG + "1: ", SingletonClass.getInstance().getAccessToken().getToken());
                                headers.put("Authorization", "bearer " + SingletonClass.getInstance().getAccessToken().getToken());
                            } else {
                                Log.d(TAG, "no token");
                            }
                            return headers;
                        }
                    };
     
                    try {
                        Log.d(TAG, postRequest.getHeaders().toString());
                    } catch (AuthFailureError e) {
                        e.printStackTrace();
                    }
     
                    ConnectionManager.getInstance(MainActivity.this).add(postRequest);
     
     
                } else {
                    Log.d("ERROR", requestResult.getError().getMessage());
                    final String errorResult = requestResult.getError().getMessage();
     
                    runOnUiThread(new Runnable() {
                        public void run() {
     
                            Toast.makeText(MainActivity.this, errorResult, Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
        });
     
     
    }

     

  9. Answer
    Martin
    Admin
    Martin avatar
    67 posts

    Posted 05 May Link to this post

    Hi Mark,

    You are trying to register a device that already has registration in the backend service the server returns an error 601 with message "The specified device is already registered. You can either unregister it or update its parameters."

    In such case you may use a PUT request and a different endpoint to update the device registration (you can leave the body of the request as the only thing you want to update is the UserId) like this:

    Request:
        PUT http://api.everlive.com/v1/your-app-id/Push/Devices/HardwareId/<device-id-here>
    Headers:
         Content-Type: application/json
         Authorization: bearer access-token-here
    Body:

    You can find out more information in the RESTful API documentation.

    However, you may consider checking and updating the device registration each time the app starts to ensure that you are updating the registration with the new push token (if it has changed), the UserId, etc.

    Let me know if this helped.

    Regards,
    Martin
    Telerik
     
    Everlive is now Telerik Backend Services, and is part of the Telerik Platform.
     
Back to Top