Testing a Android Broadcast Receiver for SMS - android

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).

Related

Android incoming sms popup

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.

Is it possible to compare my received msg with resource in xml or textview and edittext

I can start another activity when i receive a sms. what I want to know is how to compare the text message with the content in my resources(xml string) and also the textview, editText. Is it possible to get reference from textview and edittext value in broadcast receiver class? Below is the code starting an activity without comparing any value.
public class SMSReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
String phonenumber = "";
if (bundle != null)
{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
phonenumber=msgs[i].getOriginatingAddress();
str += msgs[i].getMessageBody().toString();
str += "\n";
}
//=======launch the ShowMap1 when recieve SMS==============//
Intent mainActivityIntent = new Intent(context, ShowMap2.class);
mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mainActivityIntent.putExtra("phn", phonenumber);
mainActivityIntent.putExtra("sms", str);
context.startActivity(mainActivityIntent);
//========================END=============================//
}
}
}
as far as I understood that will be a global receiver that will get SMS.
So it means that the device can be on sleep, on the home screen, on the some game, on the gmail, or any other app; so that means that the Activity and the EditText do not exist at the moment that this receiver is being fired.
You can save a previously entered value from the activity on the SharedPreferences for example, and compare from those values.
To compare from an XML resource is very simple, you're receiving a reference to your application context with this receiver, just use it to get the value with this code:
String compare = context.getString(R.string.___);

The "From" tag of a sms sent via tmomail.net

It appears the true "From" tag of a message sent from an email service ex. 7135192435#tmomail.net has a diffrent "From" tag then what the message details reveal once the message is recieved through SMS. I want to be able to recieve SMS message via tmomail.net but the missing link lies in what exactly the phone sees as the "From" tag.
I have successfully recieved SMS from other cell phones, and my broadcast reciever catches them. However I can not properly set the "From" filter in order to recieve these texts via tmomail.net. Thank you in advance for all nobel android wizards, who may take time from their projects to help. What follows is the code...
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// ---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
Log.d("SMS_Project", "Beginning fired!");
if (bundle != null) {
// ---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
String mFrom = msgs[i].getOriginatingAddress();
String mBody = msgs[i].getMessageBody().toString();
Log.d("SMS_Project", "The From tag follows this line");
if (mFrom.equals("JimJohanson#JollyRanchers.com")) {
Log.d("SMS_Project", "above is the from tag");
if (mBody.indexOf("1") == 0) {
str += "SMS from '" + mFrom + "'";
str += " :";
str += mBody;
str += "\n";
// ---display the new SMS message---
Log.d("SMS_Project", "Toast anyone?");
Toast.makeText(context, str, Toast.LENGTH_LONG).show();
this.abortBroadcast();
}
}
}
}
Log.d("SMS_Project", "No toast yet");}
Manifest Information:
<receiver android:name=".SmsReceiver" >
<intent-filter android:priority="99999999" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
These are my permissions:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
I suspect the propblem to be the phones lack of abilty to translate the email into a legit SMS. Perhaps it is a Multimedia Message type instead? Im going to keep combing the blue nowhere until I get this going. If you have any questions about what I have so far. Please let me know. Thanks.
Im going to try and check via the mFrom string and Log.d. For anyone else encountering this Im
//inserting...
Log.d("SMS_Project", mFrom);
//right above...
(mFrom.equals("JimJohanson#JollyRanchers.com"))
hopefully this will give me an accurate and consistent "from" tag in order to accuratley trap for a result. Can't believe its taken me this long to come up with such a simple test. Tip, learning how to properly debug and utilize LogCat is a neccessity for anyone above a copy/paste pro.
Alright disregard all of my past jaw jacking... The answer to this one is to use the getEmailFrom() function.
Example :
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
String mFrom = msgs[i].getOriginatingAddress();
String mBody = msgs[i].getMessageBody().toString();
String mEmail = msgs[i].getEmailFrom().toString();
*Boolean mSomething = msgs[i].isEmail();*
Log.d("SMS_Project_From", mFrom);
Log.d("SMS_Project_mBody", mBody);
*Log.d("SMS_Project_Email", mEmail);*
This includes the Logcat so that you can identify exactly where the email is from.

Android:: Calling methods form Broadcasr Receiver class?

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.

Create PDU for Android

I am currently writing and application, that is sending/receiving SMS messages.
For unit-testing purposes I need to create PDU programmatically. Decoding is quite easy:
Bundle bundle = intent.getExtras();
if (bundle != null) {
/* Get all messages contained in the Intent*/
Object[] pdusObj = (Object[]) bundle.get("pdus");
for (int i = 0; i < pdusObj.length; i++) {
SmsMessage msg = SmsMessage.createFromPdu((byte[])pdusObj[i]);
}
}
Is there any appropriate way to create PDU programamtically?
Typically PDUs are hardcoded in the code. Similar to this:
String pdu = "07914151551512f2040B916105551511f100006060605130308A04D4F29C0E";
SmsMessage sms = SmsMessage.createFromPdu(HexDump.hexStringToByteArray(pdu));
Here's a complete example on how to do this.
Now, you're gonna ask me "where can I find a PDU for testing?" You generate it. For example, you can use this online service.
I hope this helps!!

Categories

Resources