This is a migrated thread and some comments may be shown as answers.

Registering devices for push notifications

8 Answers 126 Views
Android SDK
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Mark
Top achievements
Rank 1
Mark asked on 19 Apr 2016, 03:01 PM

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);
 
}

 

8 Answers, 1 is accepted

Sort by
0
Martin
Telerik team
answered on 21 Apr 2016, 12:55 PM

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.
 
0
Mark
Top achievements
Rank 1
answered on 21 Apr 2016, 02:19 PM

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.

 

 

0
Martin
Telerik team
answered on 25 Apr 2016, 01:15 PM

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.
 
0
Mark
Top achievements
Rank 1
answered on 25 Apr 2016, 03:48 PM

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

0
Martin
Telerik team
answered on 27 Apr 2016, 01:46 PM

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.
 
0
Mark
Top achievements
Rank 1
answered on 27 Apr 2016, 03:34 PM
Thank you the issue is now solved
0
Mark
Top achievements
Rank 1
answered on 03 May 2016, 04:17 PM

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();
                    }
                });
            }
        }
    });
 
 
}

 

0
Accepted
Martin
Telerik team
answered on 05 May 2016, 03:06 PM

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.
 
Tags
Android SDK
Asked by
Mark
Top achievements
Rank 1
Answers by
Martin
Telerik team
Mark
Top achievements
Rank 1
Share this question
or