How to Deserialize Parcelled "android.messages" in Android Notification's extras? - java

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)

Related

Firebase onMessageReceived() returns no getNotification

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,

NFC reading Android Java - null object from getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)

I'm trying to realize a simple Android application to read from an NFC tag.
I followed the official documentation (https://developer.android.com/guide/topics/connectivity/nfc) to actually realize an application that is almost equal to the one created by "codexpedia" -> Source code.
When a tag is near the smartphone the onNewIntent method is call, but, when I try to get data through the method getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES), I always obtain null.
You can find the code that is causing the problem at the following direct link link
Is there anyone that knows why it happens?
NdefFormatable technology means the card is capable of storing a Ndef message once it has been formatted.
So basically there is no Ndef message on this card, once it has been formatted and a Ndef message put on it then the code will be able to read this card.
You can use Apps like NFC tools or NXP TagWriter App to Format and add an Ndef message
Once formatted it should show the NfcV, Ndef technologies.
The bug in the code https://github.com/codexpedia/android_nfc_read_write/blob/master/app/src/main/java/com/example/peng/nfcreadwrite/MainActivity.java
Line 80 - IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
Should be
IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
As it assumes that all cards have a Ndef message to read from, this is not the case for unformatted cards, bank cards, A lot of Transport cards, etc
Also line 91 to 93 - if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
Should be
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {

How to correctly pass data in the Finite State machine in AKKA

I am following this example here from the doc
Here is part of the finite state machine I'm working with
startWith(ACCEPTED, new myData());
when(ACCEPTED, matchEvent(someMesage.class, MyData.class,
(someMessage, myData) -> goTo(EVALUATING).replying(EVALUATING)));
onTransition(matchState(ACCEPTED,EVALUATING, () -> {
// Here I want to update the nextState data and pass it to another actor
// But the nextState data is always the unititalized object which is new Mydata() when the FSM initializes
}));
whenUnhandled(matchAnyEvent(
(state, data) -> stay().replying("received unhandled request " + state.toString())));
initialize();
}
How do I correctly pass data between various states in the state machine?
How should the actor.tell call look like for the actor sending a message to this FSM actor
If I send the following message
MyFSM.tell(new someMessage(myData), getSelf());
It correctly matches the event and the actor changes the state to EVALUATING and sends back an EVALUATING message. BUt what I really want is, modify 'myData' based on this state change and on transition, send this modified data to another actor.
But when I send a message of type someMessage I have no way to send the existing instance of myData and it is always uninitialized as part of the initialization of the state machine.
In other words, I am trying to manage the state of myData with the finite state machine.
How can I achieve his making the best use of the framework?
A working example from the above information will be really useful!
You can use using to provide a new state, like so:
when(ACCEPTED, matchEvent(someMesage.class, MyData.class,
(someMessage, oldData) -> {
MyData newState = new MyData(); // or transform the old into a new one
return goTo(EVALUATING).using(newState).replying(EVALUATING);
}));

How do I instantiate a Register object in Java using the jamod library?

I'm currently working with jamod in order to set up a small control system for work. We are working with several PLCs and I need to use the MODBUS protocol for communication. I have been able to read the values that are measured by the controllers, however I am unsuccessful in writing to the controller (adjusting amperage).
My question is, how do I instantiate a Register object using jamod?
Register[] reg_1 = new Register[5];
reg_1[0].setValue(16000);
This doesn't work. Essentially I would like to set the value of the register at position 0 to the integer 16000. I have also tried using
reg_1[0].setValue(Integer.parseInt("16000"));
I've been looking through the jamod documentation and can't find any way of creating a proper register object nor any examples of how to set a proper register to write.
If anyone has any ideas, I'd be most grateful. :)
I figured it out. The proper way to set up a Register[] for writing, in my case, was setting up several SimpleRegisters made up of UINT_16s,then throwing them into the Register[] array like so:
Register reg1 = new SimpleRegister(48911);
Register reg2 = new SimpleRegister(23593);
Register reg3 = new SimpleRegister(48911);
Register reg4 = new SimpleRegister(23593);
WriteMultipleRegistersRequest req = new WriteMultipleRegistersRequest(41200,new Register[]{reg1,reg2,reg3,reg4});
WriteMultipleRegistersResponse res = new WriteMultipleRegistersResponse();
Where 41200 was the reference point to which the register writing starts. You can do this with multiple amounts, even 1 or 100, and adjust your register amounts accordingly. In my case I was sending and receiving two 8bit words from the modbus so I had two registers per value.

Spring Facebook Template map fetchObject to PagedList

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.

Categories