I'm writing a small android app which has a broadcast receiver for incoming sms messages. Normal text works just fine, but emoji show up as weird characters ().
The relevant code:
class SmsReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val pdus = intent.extras?.get("pdus") as Array<ByteArray>
pdus.map { SmsMessage.createFromPdu(it) }
.forEach { Log.i("Receiver", "Got message ${it.displayMessageBody}") }
}
The message I'm sending to the emulator:
💩💩💩
What I get in my log file:
I/Receiver: Got message
Does anyone know how to get the proper message text?
UPDATE
So after going down a rabbit hole of encodings and the EmojiCompat library, I discovered it's an issue with the emulator itself. When I got hold of a second phone and tried it on an actual device, it just worked. I created a bug with the android developers so hopefully they have a fix: https://issuetracker.google.com/issues/149141727
The message you are sending the emulator is ascii, and the message you are displaying to the log is UTF8, you need to read it as ascii
Related
I am trying to transfer heart rate sensors data from watch to mobile device. On the watch(wearable) side, I am getting message stating that the data has been transferred. I have set the priority of the message(PutDataMapRequest) as urgent on the watch.
However, I am unable to receive the data on the mobile device. Following is my code for AndroidManifest.xml:
<%service android:name=".WearableListenerService1">
<%intent-filter>
<%action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
<%data android:host="*" android:scheme="wear" android:pathPrefix= "/healthcare" />
</intent-filter>
</service>
My WearableListenerService1 class is:
public class WearableListenerService1 extends WearableListenerService {
#Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
String event = messageEvent.getPath();
Log.d("Event ", event);
String [] message = event.split("--");
Intent i = new Intent(this, MainActivity.class);
startActivity(i);
}
#Override
public void onDataChanged(DataEventBuffer dataEventBuffer) {
// super.onDataChanged(dataEventBuffer);
Log.d("Event ", "event data changed");
Intent i = new Intent(this, MainActivity.class);
startActivity(i);
}
}
I am using following libraries:
compile 'com.google.android.support:wearable:2.0.0-alpha2'
compile 'com.google.android.gms:play-services-wearable:9.4.0'
Acording to this tutorial, make sure that the applicationId in the main app and wearable app are matched (build.gradle files) in order for the WearableListenerService to fire the onDataChanged event. Because when you send some data through mobile app or wear app, it will check for the same package to pass that data. So if you give different name, you won't be able to send or receive data.
You can also check this documentation and related SO threads:
Sending messages from Android Wear to host device
Android Wear sending data to Android phone, but phone appears to never receive it
I found the issue. Android version on my Moto360 was 1.5 whereas I was using developer preview of wear 2.0 on Android Studio.
Currently I am trying to modify an incoming SMS before it is saved to the Inbox.
As the system is Android 4.4.4, a simple interception with a high priority broadcast receiver is not possible. That is also the reason why I'm modifying the Android Source (AOSP) and not building an App.
So far I have managed to identify a promising class: InboundSmsHandler. Within the inner class SmsBroadcastReceiver the method onReceive is triggered when a SMS has arrived and later on sends an "SMS_RECEIVED" intend. So basically this method seems to be at a good spot.
The problem is that I can not modify the SMS that is delivered with the intend of onReceive.
I have already tried to modify it with PDU:
byte[] pdu = createFakePDU("15555215556", "modified body");
intent.putExtra("pdus", new Object[] { pdu });
intent.putExtra("format", "3gpp");
(This approach did not work, the SMS App has shown the original message)
Tried to modify the body of a SmsMessage directly:
(I have added a method to SmsMessage to be able to modify the body)
SmsMessage[] msgs = Intents.getMessagesFromIntent(intent);
int pduCount = msgs.length;
for(int i=0; i<pduCount; i++)
{
msgs[i].modifyBody("test");
}
(This approach did not work, the SMS App has shown the original message)
And finally added a new SMS to the database:
....
contentResolver.insert( Uri.parse( SMS_URI ), values );
....
(The problem with that approach is that the original SMS still arrives and therefore not only one modified SMS but one original SMS and one modified arrive. The original SMS must be deleted, but I don't know how.)
Does anyone know how I can modify a SMS before it arrives at the Inbox?
Best regards
mint
AFAIK, on 4.4.4 there is nothing that can prevent your app to receive SMS by registering your BroadcastReceiver, setting the right permissions and the right intent filter. That is:
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
and
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
(if I correctly remember them)
Then inside your BroadcastReceiver you call abortBroadcast(), modify the SMS as needed, and finally store it manually with
getContentResolver().insert(Uri.parse("content://sms/sent"), values);
Thanks for all the answers, I have found a spot in InboundSmsHandler where it is possible to modify the PDU before the broadcast is sent: the method proccessMessagePart. Before the command "intent.putExtra("pdus", pdus);" is executed, the pdus array and therefore the message body can be modified.
I'm using the notification listener api to read notification information but it seems impossible to read the text of a Gmail notification. Here what adb says:
extras={
android.title=john
android.support.actionExtras={0=Bundle[EMPTY_PARCEL], 1=Bundle[EMPTY_PARCEL]}
android.subText=bar#gmail.com
android.showChronometer=false
android.icon=2130837727
android.text=MyText
android.progress=0
android.progressMax=0
android.showWhen=true
android.people=[Ljava.lang.String;#b1564718 {
mailto:foo#gmail.com
}
android.largeIcon=android.graphics.Bitmap#b15c6130 (128x128)
android.infoText=null
android.wearable.EXTENSIONS=Bundle[mParcelledData.dataSize=1200]
android.progressIndeterminate=false
android.scoreModified=false
}
With other notification it works. Any tips? I'm reading the notification in this way:
String text = extras.getString(Notification.EXTRA_TEXT);
Ok problem solved. The information about the notification are stored as CharSequence so you have to get it with getCharSequence(). Since String implements the CharSequence interface it's possible that it works but not always. However using CharSequence it works.
I've got an app that sends a text message as a response after receiving a text message. (Auto Respond) When SMS is enabled in hangouts, my app wasn't sending its messages. I fixed that by doing this:
<intent-filter android:priority="500">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
After sending the message, my app also writes that sent message to the user's SMS log (inbox/outbox displayed by messaging apps.)
But now that my SMS receiver is higher priority than Hangouts, the sent message is written to the user's SMS log AFTER the received message when it should be the other way around.
So it shows like this:
Response Message
Received Message - this is what triggered the response
But it should be:
Received Message - triggers response
Response Message
Is there a way for me to wait for the received message to be written before writing the response message? It works fine when SMS is disabled in Hangouts. But since Hangouts is now writing that message instead of the default SMS receiver, it messes things up like crazy.
EDIT: Thanks to Keith's response, this is the code that worked for me:
context.getContentResolver().registerContentObserver(
Uri.parse("content://sms"),
true,
smsObserver);
And this class:
private class SMSObserver extends ContentObserver
{
public SMSObserver()
{
super(null);
}
#Override
public boolean deliverSelfNotifications() {
return true;
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
if(!selfChange)
//sendResponse
context.getContentResolver().unregisterContentObserver(this);
}
#Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if(!selfChange)
//sendResponse
context.getContentResolver().unregisterContentObserver(this);
}
}
I'm not sure if the self change part is necessary, but it works so I'm not changing it.
Try a ContentObserver on the SMS database to listen for when Hangouts writes to the SMS content provider. This approach should be compatible with 4.4/Hangouts as well as earlier versions; you'd just wait until something is written to write your sent message.
Tested two different versions on Android 4.3, Galaxy Nexus:
context.getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, myContentObserver);
or
cursor = context.getContentResolver().query(Uri.parse("content://sms/inbox"),
new String[] { SMS_ID, SMS_ADDRESS, SMS_READ },
"read = 0",
null,
null);
cursor.registerContentObserver(myContentObserver);
But I couldn't use the non-Cursor version with sms/inbox for some reason. The downside of the Cursor-based version is that it seems to need to stay open so then you have to be sure to close it later.
Also, neither version is being called when the read status changes.
I don't think this is possible, as I haven't found anything in the SDK documentation (yet).
But I could do with knowing if its possible to write an application which logs Toast messages. Logging which application showed it and what the message displayed contained.
This is an entirely personal endeavour to create an app which can detect the toast messages. Because something on my phone is creating a toast saying "Sending..." about once per day, and for the life of me I can't track down the offending application (Service class). I thought it might be GMail or Evernote, but there toast messages for sending are slightly different. I'm going for building an app because 1) I don't know if LogCat would show anything, and 2) I don't want to keep my personal/dev phone plugged in to a PC all the time (as the "Sending..." message occurs so infrequently).
It's possible to catch Messages/Notifications with an Accessibility Service, have a look at that.
You can extend the class AccessibilityService and override the method onAccessibilityEvent() to implement something like this:
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED)
return; // event is not a notification
String sourcePackageName = (String) event.getPackageName();
Parcelable parcelable = event.getParcelableData();
if (parcelable instanceof Notification) {
// Statusbar Notification
}
else {
// something else, e.g. a Toast message
String log = "Message: " + event.getText().get(0)
+ " [Source: " + sourcePackageName + "]";
// write `log` to file...
}
}
Note: This didn't work for me on Android 2.2 as it doesn't seem to catch Toasts, but it worked on Android 4.0+.