I have a problem when receiving a long binary SMS. The client is supposed to receive multipart binary SMS. Upon searching stackoverflow, people have mentioned that onReceive() shall be fired only once. From there you can concatenate the multiple SMS.
I am not sure if that's the same when sending binary SMS. I receive 2 SMS, and onReceive is fired twice. The SMS are separate from each other making it impossible to concatenate.
AndroidManifest:
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.INTERNET" />
<receiver
android:name="com.myapp.smsnotification.SMSReceiver"
android:enabled="true" >
<intent-filter android:priority="100" >
<action android:name="android.intent.action.DATA_SMS_RECEIVED" />
<data
android:host="localhost"
android:port="9515"
android:scheme="sms" />
</intent-filter>
</receiver>
SMSReceiver.java
in my onReceive()
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
try {
if (messages.length > -1) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
for (int i = 0; i < messages.length; i++) {
SmsMessage message = messages[i];
os.write(message.getUserData());
}
byte[] stream = os.toByteArray();
// do something with stream
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
Found out that it was not an issue with the client side but in the server side. They didn't include in the User Data Header the part to indicate that the message is a concatenated SMS.
If the protocol is followed, Android will be able to detect it and handle them accordingly, waiting for all SMS to arrive and fire the SMS broadcast receiver once containing all received SMS.
Related
Is it possible in android to filter the SMS from a specific number in android.And save it in a specific database.and the SMS should not be visible in the inbox...
You have yo do this in 3 step:
read SMS from Specific number you have to look in to this link then after
you have to create Database for store all info about SMS(like id, body, number, time) for that check this link
you have to Delete SMS from INBOX check this link for delete SMS.
add below permission for do all step:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
ya is it possible.
in mainfest file add following code:
<receiver android:name="com.example.Sms_BReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
after that create a class use following code
public class Sms_BReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
SmsMessage[] messageString = null;
Object[] pdus = (Object[]) bundle.get("pdus");
messageString = new SmsMessage[pdus.length];
for (i = 0; i < messageString.length; i++) {
messageString[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
Phone_no = messageString[0].getOriginatingAddress();
Message_body = messageString[0].getMessageBody();
Time = messageString[0].getTimestampMillis();
CharSequence text = str;
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
if (Phone_no.contains(here check no to filter) {
here delete message form inbox
and save in our own db
} else {
}
}
i hope this code will use full for u
I am trying to use a broadcast receiver to read incoming SMS in my app and also able to do so. However, if someone receives SMS on google hangout instead of default SMS app, the broadcast receiver doesn't work.
The following is the code I am using:
public class SmsListener extends BroadcastReceiver {
// Get the object of SmsManager
final SmsManager sms = SmsManager.getDefault();
public void onReceive(Context context, Intent intent) {
// Retrieves a map of extended data from the intent.
final Bundle bundle = intent.getExtras();
try {
if (bundle != null) {
final Object[] pdusObj = (Object[]) bundle.get("pdus");
for (int i = 0; i < pdusObj.length; i++) {
SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
String phoneNumber = currentMessage.getDisplayOriginatingAddress();
String senderNum = phoneNumber;
String message = currentMessage.getDisplayMessageBody();
Log.i("SmsReceiver", "senderNum: "+ senderNum + "; message: " + message);
// Show Alert
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context,
"senderNum: "+ senderNum + ", message: " + message, duration);
toast.show();
} // end for loop
} // bundle is null
} catch (Exception e) {
Log.e("SmsReceiver", "Exception smsReceiver" +e);
}
}
The manifest has:
<receiver android:name=".SmsListener">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Permissions:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
Did you add this permission?
<uses-permission android:name="android.permission.RECEIVE_SMS" />
You may want to set the android priority value to a suitable value.
Ordered broadcasts (sent with Context.sendOrderedBroadcast) are delivered to one receiver at a time. As each receiver executes in turn, it can propagate a result to the next receiver, or it can completely abort the broadcast so that it won't be passed to other receivers. The order receivers run in can be controlled with the android:priority attribute of the matching intent-filter; receivers with the same priority will be run in an arbitrary order.
Is it Good paractice to Detect Incoming and Outgoing Sms through ContentObserver or use BroadCast Receiver for Incoming SMS and ContentObserver for Outgoing Sms??
I had an application about SMS and Call blocker but i never upload it to play store because of after Kitkat ,you cant block sms messages. If you wanna do that just dont. I am sharing the sms part only, you can modify it as you want.
<!-- Android Permissions in manifest -->
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<!-- Define receiver inside the application tag -->
<receiver android:name="catchPackage.SmsController" android:process=":hascode_process" android:label="#string/sms_receiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_DELIVER"/>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<!-- Broadcast receiver java code -->
public void onReceive(Context context, Intent intent) {
this.context = context;
try{
Bundle bundle = intent.getExtras(); //---get the SMS message passed in---
SmsMessage[] msgs = null;
String msg_from = null;
String msg_body = null;
if (bundle != null){
try{
boolean delete= false;
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for(int k=0; k<msgs.length; k++){
msgs[k] = SmsMessage.createFromPdu((byte[])pdus[k]);
msg_from = msgs[k].getOriginatingAddress();
System.out.println(msg_from);
String msgBody = msgs[k].getMessageBody();
msg_body = msgBody;
}
}catch(Exception e){
System.out.println(e.getMessage());
}
}
} catch (Exception e) {
Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
}
Is it possible to read incoming sms and reply back only to specific or desire number. i-e i want to make app that will run in back ground ... whenever i will send sms with my number it will automatically respond back to me with XYZ information
Yes, it's possible. You need to add a BroadcastReceiver in your app that will intercept incoming SMS messages and then send a message if it matches the number you're looking for.
Following source code from:
BroadcastReceiver + SMS_RECEIVED
http://shreymalhotra.me/blog/tutorial/receive-sms-using-android-broadcastreceiver-inside-an-activity/
In AndroidManifest.xml:
<receiver android:name=".SMSReceiver">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
In a new file called SMSReceiver.java:
public class SMSReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
// get SMS data, if bundle is null then there is no data so return
Bundle extras = intent.getExtras();
if (extras == null) return;
// extract SMS data from bundle
Object[] pdus = (Object[]) extras.get("pdus");
for (int i = 0; i < pdus.length; i++) {
SmsMessage SMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = SMessage.getOriginatingAddress();
String body = SMessage.getMessageBody().toString();
// if there's an SMS from this number then send
if(sender.equals("+1800555555") {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(sender, null, "sms received", null, null);
}
}
}
}
I want implement an app which receives SMS on a specific port.
Manifest Code:
<receiver android:name=".BinarySMSReceiver">
<intent-filter>
<action android:name="android.intent.action.DATA_SMS_RECEIVED"/>
<data android:port="8091"/>
<data android:scheme="sms"/>
</intent-filter>
</receiver>
And receiver class code below.
public class BinarySMSReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
if(null != bundle)
{
String info = "Binary SMS from ";
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
byte[] data = null;
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
info += msgs[i].getOriginatingAddress();
info += "\n*****BINARY MESSAGE*****\n";
data = msgs[i].getUserData();
for(int index=0; index<data.length; ++index)
{
info += Character.toString((char)data[index]);
}
}
Toast.makeText(context, info, Toast.LENGTH_SHORT).show();
}
}
}
I am getting all SMS which are on this (8091) port or not. I want to receive only those messages which are port specific.
For those who are still wondering why the app is receiving data SMS directed to other ports and not just to port 8091. The problem lies in the Manifest code. I've seen many solutions that were posted and most of them are actually wrong.
The Manifest should be :
<receiver
android:name = ".SmsReceiver">
<intent-filter>
<action android:name="android.intent.action.DATA_SMS_RECEIVED" />
<data
android:scheme="sms"
android:host="*"
android:port="8095" />
</intent-filter>
</receiver>
The scheme, host and port attributes must be defined in only one "data" element of the intent-filter, not in separate "data" elements.
Also not that from this link, under "data test" section it states that
"The host and port together constitute the URI authority; if a host is not specified, the port is ignored."
So keep in mind that you need to specify the host if you want the app to receive the data SMS for only a specific port.
The "host" element is * (asterisk) is to specify that it accepts data SMS from all hosts / phone numbers
Hope this helps someone (:
I had similar problem, just add following check condition at begin of your 'onReceive' code:
String dataStr = intent.getDataString();
if (dataStr.indexOf(":8888" ) == -1) {
return;
}