I want to match a String sms phone number (incoming sms) to a String Studentno (variable). How can i match and notify popup msg if successful. here's my code:
public void onReceive( Context context, Intent intent )
{
// Get SMS map from Intent
Bundle extras = intent.getExtras();
String messages = "";
String address = "";
String studentsno = "+0999234678";
String no;
if ( extras != null )
{
// Get received SMS array
Object[] smsExtra = (Object[]) extras.get( SMS_EXTRA_NAME );
// Get ContentResolver object for pushing encrypted SMS to incoming folder
ContentResolver contentResolver = context.getContentResolver();
for ( int i = 0; i < smsExtra.length; ++i )
{
SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
String body = sms.getMessageBody().toString();
address = sms.getOriginatingAddress();
messages += "SMS from " + address + " :\n";
messages += body + "\n";
no = sms.getOriginatingAddress().toString();
// Here you can add any your code to work with incoming SMS
if(no == studentsno){
Toast.makeText( context, "SUCCESS", Toast.LENGTH_LONG ).show();
}
// I added encrypting of all received SMS
putSmsToDatabase( contentResolver, sms );
}
// Display SMS message
Toast.makeText( context, messages, Toast.LENGTH_SHORT ).show();
}
}
This is my problem. how can I match 2 Strings to display popup msg? :
if(no == studentsno){
Toast.makeText( context, "SUCCESS", Toast.LENGTH_LONG ).show();
}
In Java, all strings are objects. When you use the == operator with objects, you are testing whether two objects are the same object.
Because of string interning, strings might be the same object but often not, and you are not able to influence this.
The Java Object class implements an equals method which simply tests if two objects are the same object. Any class which inherits from Object may override this method to provide it's own equality test. string does this by overriding the equals method to test whether two strings (the same object or different objects, it doesn't matter) contain the same content.
Therefore, when testing whether two strings have the same content, you should use string1.equals(string2).
http://en.wikipedia.org/wiki/String_interning
Try
if(no.equals(studentsno))
instead of
if(no == studentsno)
EDIT: Long story short, String.equals() will compare if the values of the given strings are equal (this is what you need in your situation).
== will check if the compare objects are referring to the exact same String object. So even if the comparing Strings have the same value, they are not referring to the same String object.
Related
I have written a SMSReceiver for Android and all works fine on real devices and when I test the App over Telnet.
But how can I create a unit test for the following onReceive Method in Android Studio?
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle!=null){
Object[] smsExtras = (Object[]) bundle.get("pdus");
String format = (String)bundle.get("format");
String strMessage = "";
for (Object smsExtra : smsExtras) {
SmsMessage smsMessage;
if (Build.VERSION.SDK_INT < 23){
smsMessage = SmsMessage.createFromPdu((byte[]) smsExtra);
}else {
smsMessage = SmsMessage.createFromPdu((byte[]) smsExtra, format);
}
String messageBody = smsMessage.getMessageBody();
String messageSource = smsMessage.getOriginatingAddress();
strMessage += "SMS from " + messageSource + " : " + messageBody;
Log.i(AppConstants.DEBUG_TAG, strMessage);
}
}
}
It depends on what you want to test, but it looks like you want to check that the message body and address is correctly parsed and has the expected contents. In that case you can break out that logic into a separate method and unit test it, by passing in a PDU and checking the return value.
If you want to test onReceive, it should be possible to use Mockito, pass in a MockContext and mock Intent's getExtra to return your own test Bundle object. Still, you'll need to verify something in the end. Perhaps you're planning to store the parsed data somewhere later? If so you can use that as your verification point - either by capturing and checking the argument, or verifying that the data was stored (though that's stretching the boundaries of the unit test quite a bit).
I have setup a background service to registerContentObserver to get notified whenever an SMS is sent. Upon receiving this event, I would increment a variable to know the count of messages sent. This is working as expected.
When someone sends SMS with more than 140 characters, the mobile carrier would treat this as multiple SMS, but it seems that I get only 1 callback for the sent message. This is causing my app to miss counting some messages.
Is there any proper way to know how many messages were actually sent?
When an app is responsible for writing its own messages to the Provider, it's most likely going to write the whole message in one go, regardless of whether the message must be sent as multipart. This would be why your Observer is often firing only once for each complete message, no matter how big.
Since KitKat, the system will automatically save the outgoing messages for any non-default apps, and for multipart messages, each part will be saved individually, firing your Observer each time. Of course, this doesn't help for anything prior to KitKat, or if a default app saves its own messages on later versions.
One possibility is to fetch the message body in your ContentObserver, and determine how many message parts it would've been split into. The SmsMessage.calculateLength() method can do this for us. It returns an int array, the first element of which will have the message count for the given text.
For example, using the old onChange(boolean) method, to support API < 16:
private class SmsObserver extends ContentObserver {
private static final Uri SMS_SENT_URI = Uri.parse("content://sms/sent");
private static final String COLUMN_ID = "_id";
private static final String COLUMN_BODY = "body";
private static final String[] PROJECTION = {COLUMN_ID, COLUMN_BODY};
// You might want to persist this value to storage, rather than
// keeping a field, in case the Observer is killed and recreated.
private int lastId;
public SmsObserver(Handler handler) {
super(handler);
}
#Override
public void onChange(boolean selfChange) {
Cursor c = null;
try {
// Get the most recent sent message.
c = getContentResolver().query(SMS_SENT_URI, PROJECTION, null,
null, "date DESC LIMIT 1");
if (c != null && c.moveToFirst()) {
// Check that we've not already counted this one.
final int id = c.getInt(c.getColumnIndex(COLUMN_ID));
if (id == lastId) {
return;
}
lastId = id;
// Get the message body, and have the SmsMessage
// class calculate how many parts it would need.
final String body = c.getString(c.getColumnIndex(COLUMN_BODY));
final int numParts = SmsMessage.calculateLength(body, false)[0];
// Add the number of parts to the count,
// however you might be doing that.
addToCount(numParts);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (c != null) {
c.close();
}
}
}
}
Should you be supporting API 16 and above, we can use the onChange(boolean, Uri) overload, and things get a little simpler, since we don't necessarily need to keep track of the last message ID.
#Override
public void onChange(boolean selfChange, Uri uri) {
Cursor c = null;
try {
// type=2 restricts the query to the sent box, so this just
// won't return any records if the Uri isn't for a sent message.
c = getContentResolver().query(uri, PROJECTION, "type=2", null, null);
if (c != null && c.moveToFirst()) {
final String body = c.getString(c.getColumnIndex(COLUMN_BODY));
final int numParts = SmsMessage.calculateLength(body, false)[0];
addToCount(numParts);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (c != null) {
c.close();
}
}
}
sir, i have a problem in updating my database. i've made a listview containing this data
name
phone number
status
i would like to update the status of person if he sent a message with a keyword "available" in it and would update my listview like this
name
phone number
available
so i decided to make the phone number as the trigger. if the phone number of the person who sent the message is in my listview, it will update the database. but here is my problem, if i saved the phone number in my listview in this format
09211234567
the sender will return their phone number as
+639211234567
so i worked around this by getting the substring and cut the phone number into "9211234567", and then add 0 to transform it into "09211234567".
however, the database status still doesn't update. but when i used the same technique in sending sms from emulator to emulator, it works just fine.
i saved the number of emulator in my listview as
5556
but the emulator returns
15555215556
so i just get the substring to get 5556
please help me. here is my code:
public static String sender;
public GroupDb info;
public String aStatus = "available";
public String nStatus = "not available";
public String addNum = "0";
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
info = new GroupDb(context);
Bundle bundle = intent.getExtras();
Object[] pdusObj = (Object[]) bundle.get("pdus");
SmsMessage[] messages = new SmsMessage[pdusObj.length];
for (int i = 0; i<pdusObj.length; i++)
{
messages[i] = SmsMessage.createFromPdu ((byte[])
pdusObj[i]);
sender = messages[i].getOriginatingAddress();
}
for (SmsMessage msg : messages) {
if (msg.getMessageBody().contains("available")) {
info.open();
String remFirstChar = sender.substring(3);
addNum += remFirstChar;
Toast.makeText(context.getApplicationContext(), "received sms from: " +addNum,
Toast.LENGTH_LONG).show();
//if starts with +639
if(sender.length() == 13)
{
info.updateStatus(addNum, aStatus);
Toast.makeText(context.getApplicationContext(), "addNum: " +addNum,
Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(context.getApplicationContext(), "sender: " +sender,
Toast.LENGTH_LONG).show();
info.updateStatus(remFirstChar, aStatus);
}
info.close();
}//end if - available
here is how i updated my status
//update status
public void updateStatus(String mNumber, String mStatus) throws SQLException
{
// TODO Auto-generated method stub
ContentValues cvUpdate = new ContentValues();
cvUpdate.put(KEY_STATUS, mStatus);
ourDatabase.update(DATABASE_TABLE, cvUpdate, KEY_NUMBER + "=" + mNumber, null);
}
update:
i even tried to enter "+63" format in listview but still, i won't update. all functions such as deletion and editing also don't work and shows force close.
You need to use PhoneNumberUtils class.
Before saving the Phone Number in database first convert it as
String formattedNumber = PhoneNumberUtils.formatNumber(phonenumber);
For comparison you can use PhoneNumberUtils.compare
This question already has answers here:
How to pass a value from one Activity to another in Android? [duplicate]
(7 answers)
Closed 9 years ago.
i would like to send the values from one activity to another but i got null pointer
exception please solve my problem.the first activity contains sms the details of that
sms is send to second activity based on these values th esecond activity search contact
no and send reply sms.
public void onReceive( Context context, Intent intent )
{
// Get SMS map from Intent
Bundle bundle = null;
Bundle extras = intent.getExtras();
String messages = "";
String address = null,body=null;
if ( extras != null )
{
// Get received SMS array
Object[] smsExtra = (Object[]) extras.get( "pdus" );
// Get ContentResolver object for pushing encrypted SMS to incoming folder
//ContentResolver contentResolver = context.getContentResolver();
for ( int i = 0; i < smsExtra.length; ++i )
{
SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
body = sms.getMessageBody().toString();
address = sms.getOriginatingAddress();
messages += "SMS from " + address + " :\n";
messages += body + "\n";
// Here you can add any your code to work with incoming SMS
// I added encrypting of all received SMS
}
// Display SMS message
Toast.makeText( context, messages, Toast.LENGTH_SHORT ).show();
Intent i=new Intent(context,AlertActivity.class);
bundle.putString("from",address);
bundle.putString("msg",body);
i.putExtras(bundle);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
Activity2:
Intent i=getIntent();
Bundle bundle=i.getExtras();
String fromAdd=bundle.getString("from");
String msgBody=bundle.getString("body");
Change this
String msgBody=bundle.getString("body");
to
String msgBody=bundle.getString("msg");
in Android Bundle we put key value pair, and it is mandatory that you pass same key, while getting data from bundle, which you are putting data. check your code you are putting two string on intent, which are:
"from", and "msg"
and you are getting values from intent by key:
"from" and "body"
so change it either in starting activity or Activity 2. so that key values would match.
try this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Bundle bundle = this.getIntent().getExtras();
if (bundle != null)
{
String fromAdd = bundle.getString("from");
String msgBody = bundle.getString("body");
}
}
Try this.....
Activity1.java
Intent intent = new Intent(getApplication(),Activity2.class);
intent.putExtra("from",from);
intent.putExtra("Body",Body);
StartActivity(intent);
Activity2.java
Intent intent = getintent();
Bundle bundle=intent.getExtras();
String Body=bundle.getString("Body");
String From=bundle.getString("From");
setResult("RESULT_OK",intent);
try with this way..
Bundle bu=getIntent().getExtras();
String title=bu.get("from").toString();
String msg=bu.get("body").toString();
Try this..... to pass value from Activity1 to Activity2.
Intent myIntent = new Intent(Activity1.this, Activity2.class);
myIntent.putExtra("UserId",UserId);
myIntent.putExtra("UserName",UserName);
myIntent.putExtra("CompanyID",CompanyID);
myIntent.putExtra("CompanyName",CompanyName);
myIntent.putExtra("ProjectId",ProjectId);
startActivity(myIntent);
Also can extract the value you can use
Intent intent = getIntent();
UserId=intent.getStringExtra("UserId");
UserName=intent.getStringExtra("UserName");
CompanyID=intent.getStringExtra("CompanyID");
CompanyName=intent.getStringExtra("CompanyName");
I have an SMSreceiver class, I am new to android, now my question is that is it possible to call any methods in other class from that class. Basically what I am trying to do is to add each received message to the linked list of strings. Here is my code...
public class SMSReceiver extends BroadcastReceiver {
/**
* #see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
*/
static List<String> recNumList = new LinkedList<String>();
static String message;
static Integer count = 0;
static String phoneNum;
static String newMessage = null;
List<String> recMsgs;
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
Object messages[] = (Object[]) bundle.get("pdus");
SmsMessage smsMessage[] = new SmsMessage[messages.length];
for (int n = 0; n < messages.length; n++) {
smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
}
phoneNum = smsMessage[0].getDisplayOriginatingAddress();
message = smsMessage[0].getMessageBody() + "\n" +
"Time Stamp:" + smsMessage[0].getTimestampMillis();
recMsgs.add(message);
}
}
But the application force closes and does not add anything. Can someone help me please?
Well, firstly, you should not be adding sms to an array in a broadcast receiver, since it will then be recycled within like 100 milliseconds, so if you're wanting to keep track of the list of sms, you need to create a service to run in the background.
Alternatively, you could save the sms to the sharedPreferences using:
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences();
// i always use default, though it isn't necessarily convention, I don't think;
SharedPreferences.editor editor = pref.edit();
editor.putString("msg", message);
editor.commit();
//issue with that is, then every time you add a new sms to the shared Preferences
// the previous one will be overridden. Resolving that is not something I will cover here
And the reason why you are getting the nullpointerexception is because your recMsgs is never initialized. do that with the following within the onReceive(), though you should really migrate it to a service if you need to maintain an array:
recMsgs = new ArrayList<String>;
then any calls to recMsgs.add(...) will work properly
I THINK that could have been the issue anyway.