Calling remoteMessage.getNotification() returns null and
when calling remoteMessage.getData() I get a strange object back that has an initial property _wp={ as listed below. I need to extract the alert property each time but I am not sure how.
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
RemoteMessage.Notification notification = remoteMessage.getNotification();
Map<String, String> data = remoteMessage.getData();
Log.d("DATA", remoteMessage.getData().toString());
sendNotification(data);
}
The remote data log returns the below. So I can't seem get the title and text I need to in order to construct my notification.
{_wp={"c":"01euntvtna3epk83","alert":{"text":"Body text","title":"test"},"receipt":false,"type":"simple","targetUrl":"wonderpush:\/\/notificationOpen\/default","n":"01eunu08bjla8303","reporting":{"campaignId":"01euntvtna3epk83","notificationId":"01eunu08bjla8303"},"receiptUsingMeasurements":true}, alert=Body text}
I basically want to use them with when using the NotificationCompat.Builder
.setContentTitle(title)
.setContentText(text)
Any help will be greatly appreciated.
It is normal that remoteMessage.getNotification() returns null as WonderPush only uses FCM notifications with data inside them, nothing in the Firebase's own format.
remoteMessage.getData() returns you with a map that can only store String values. This corresponds to the top-level JSON payload. This map's fields are the top-level JSON object fields, and its values are all stringified.
So you'll have to parse the _wp key using new JSONObject(remoteMessage.getData().get("_wp")).
You'll basically read the title and text fields of this parsed _wp JSON object to feed .setContentTitle() and .setContentText() of the NotificationCompat.Builder.
But you should note that the WonderPush Android SDK is precisely here for that purpose:
Here is the code that parses the notification's _wp.alert field: https://github.com/wonderpush/wonderpush-android-sdk/blob/v4.0.2/sdk/src/main/java/com/wonderpush/sdk/AlertModel.java
Here is the code that builds the notification: https://github.com/wonderpush/wonderpush-android-sdk/blob/v4.0.2/sdk/src/main/java/com/wonderpush/sdk/NotificationManager.java#L448-L775
If you have an addition, it would make more sense to fork, hack, submit a pull request, and use your fork in the meanwhile.
Best,
Related
I am trying to have a system where I add an object (shifts in this context) and the front end receives that and processes that without refreshing the page and making another api call. Currently, I have two functions, getAllShifts and addShift. When I add a shift I expect the getAllShifts to be updated automatically using sinks. However, the response that I get is not something I expect. The code is shown below:
private Sinks.Many<Shift> shiftSink=Sinks.many().replay().latest();
public Mono<Shift> addShift(Shift shift) throws InterruptedException {
Mono<Shift> newshift= shiftRepository.save(shift);
newshift.subscribe(u-> this.shiftSink.tryEmitNext(u));
return newshift;
}
public Flux<Shift> getAllShifts(){
this.shiftRepository.findAll().subscribe(u-> this.shiftSink.tryEmitNext(u));
shiftSink.asFlux().subscribe(u-> System.out.println(u + "UUUUUUUUUUUUU"));
return shiftSink.asFlux();
}
When the getAllShifts endpoint is engaged from the frontend using eventsource and I add a shift, I expect to receive one event containing the data from that newly added shift. Instead multiple events containing that data are emitted as shown in the picture below.
Any help would be appreciated...
I am writing my first Android app which includes the NotificationListenerService for the purpose of notification mirroring to other devices. I noticed for messaging applications subsequent messages from the same sender post with the same ID/key and only the latest message text appears in the "android.text" extra field.
My goal is to grab the previous unread messages which look to be attached to the Notification under "android.messages" extra. My issue is that this does not read out to a char sequence or string array, instead it looks like some class which implements Parcellable is stored here.
I'm hoping there is some standard Android class used here that I'm missing which I can use to deserialize to in order to get the previous messages.
Some code:
val pArray: Array<Parcelable>? = bundle.getParcelableArray("android.messages") // Parcelable[6]#17975
println(pArray?.get(0)?.describeContents()) // 1 == CONTENTS_FILE_DESCRIPTOR
val charSequence: Array<CharSequence>? = bundle.getCharSequenceArray("android.messages") // null
val list = bundle.getStringArrayList("android.messages") // null
val arr = bundle.getStringArray("android.messages") // null
If anyone stumbles upon this thread, I figured out how to do it:
val pArray: Array<Parcelable> = bundle.getParcelableArray("android.messages") as Array<Parcelable>
val messages = Notification.MessagingStyle.Message.getMessagesFromBundleArray(pArray)
I use the Parse.com Cloud service in my Android app to sync data between devices.
I use the app mainly offline and use the local data store.
There is one class called Point that has a unique number as identifier I want to display. So when working offline I want to create a Point as draft (with a draft text as number) and when synchronizing I want it to get the real number that is unique over all the devices.
How would I set the number when saving? I was thinking about adding a WebHook in the cloud when saving the Point and giving it a unique number and then in my app use
newPoint.saveEventually(new SaveCallback() {
public void done(ParseException e) {
//query for the number
}
});
to query the point from the cloud to get the number after it has been saved. But this seems kind of too complicated for such a simple requirement. And I am not sure if the SaveCallback() is always triggered when saving it.
I would recommend using an afterSave trigger on the Point class to set the unique identifier when the object is newly created. Then, as you've mentioned, you'll need to fetch the value before displaying it.
Here's what the cloud code could look like:
// Assign the Point a unique identifier on creation
Parse.Cloud.afterSave("Point", function(request) {
// Check if the Point is new
if (!(request.object.existed())) {
// Get the unique identifier
var uniqueIdentifier = ...
// Set the unique identifier
request.object.set('uniqueIdentifier', uniqueIdentifier);
}
});
One important bit of information to keep in mind about using saveEventually with SaveCallback() is:
The callback will only be called if the operation completes within the
current app lifecycle. If the app is closed, the callback can't be
called, even if the save eventually is completed.
Source: Hector Ramos
If the unique identifier should be immediately displayed in the app or if the callback needs to be handled consistently, it would probably be best to use saveInBackground rather than saveEventually.
Another option would be to dynamically change the callback depending on network availability and/or offline settings. For example, if the offline mode is used anytime when the cell signal or wifi is unavailable, then network reachability could be used to check for a network and then use saveInBackground or saveEventually as appropriate.
Update
OP ended up using this code:
Parse.Cloud.beforeSave("Point", function(request, response) {
if (!(request.object.existed())) {
var query = new Parse.Query("Point");
query.addDescending("uniqueIdentifier");
query.first({
success: function(result) {
var maxId = result.get("uniqueIdentifier");
request.object.set("uniqueIdentifier", maxId + 1);
},
error: function() {
}
});
}
response.success();
});
I am new to Android app development and I am stuck at a point where in my app I need to dynamically create class, define its attributes and populate them all dynamically.
This dynamic thing is required because the json file changes every time, a click event is fired and I need to populate a recyclerView, getting header and respective values from that json file.
I have come across few solutions like using javassist library and using hashmap (though I didn't get this one).
Okey I found it.
You want to parse the JSONObject at runtime and get its keys. And you don't know what structure the JSONObject would have.
Just use this Json helper class JSON HELPER
To convert JSONObject use JsonHelper.toMap(JSONObject object) given there.
//Now to get the keys
for ( String key : hashMapObject.keySet() ) {
System.out.println( key );
}
//Here hashMapObject is generated from `JsonHelper.toMap` method.
Just use Retrofit library and everything will get handled automatically and very easily Retrofit
Just follow these steps to use Retrofit
First Download and Integrate Retrofit to your android project.
//In your Gradle file. Add this line.
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
Now suppose you want to implement a Get request from a URL lets say
https://api.github.com/users/{user}/repos.
To get all the repository listed on GitHub. Here {user} will be username
So your base URL here is https://api.github.com and path for
Get Is /users/{user}/repos
Now create an interface.
public interface GitHubService {
#GET("/users/{user}/repos")
Call<List<Repo>> listRepos(#Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com").build();
GitHubService service = retrofit.create(GitHubService.class);
//Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver.
Call<List<Repo>> repos = service.listRepos("robinskumar73");
I'm using the following approach to return a Facebook user's music preferences:
//FIXME: Fetch results in a single operation
val likes = facebook.likeOperations().music
val artists = ArrayList<Artist>()
for (musicLiked in likes)
{
val musicProfile = facebook.fetchObject(musicLiked.id, Page::class.java, "id", "name", "genre");
artists.add(Artist(name = musicProfile.name, genre = musicProfile.genre))
}
The above approach won't scale, since we have an additional network operation for each artist the user likes.
I tried:
I tried using facebook.likeOperations.music however this doesn't fetch genre.
Question:
I would like to use facebook.fetchObject with a query that returns a PagedList. How to do this?
(No need to post example code in Kotlin if you prefer or are more familiar with Java - I'll be happy with information in any language).
Facebook api uses "fields" parameter in requests to return custom fields for objects. This parameter can be also used for liked music rest request.
me/music?fields=id,genre,name
above link will return all liked music with id, genre and name of the artist/group. Unfortunately FacebookTemplate does not have method which will apply for your needs. The method Facebook.likeOperations() returns instance of the LikeTemplate class which has constant PAGE_FIELDS with value
private static final String PAGE_FIELDS = "id,name,category,description,location,website,picture,phone,affiliation,company_overview,likes,checkins";
In above constant you do not have genre field. So you have two ways:
You can simply use facebook rest api with some rest library
You can override FacebookTemplate and return your own implementation of LikeTemplate as result of the likeOperations() method. You implementation of the LikeTemplate class should have different value in mentioned constant (added genre field at the end of the string)
Maybe some one will be more helpful but in my knowledge you do not have other options.
Thanks to advice given in #burovmarley's answer, I inspected the source and came up with:
val music = facebook.fetchConnections(userPage.id, "music", Page::class.java,
PagingParameters(25, 0, null, null).toMap(), "id,name,,genre")
for (musicLiked in music)
{
println("likes: ${musicLiked.name}, genre: ${musicLiked.genre}")
}
This allows using Spring Social Facebook as an unmodified dependency, and without issuing a pull request, which seem to be fairly slow in processing through the queue at the present time.