In my application where the app receives a new sms message, I want the listview to update it it immediately with the new message shown in the listview. I tried using the example code of the broadcast receiver code but it didn't work, so I'm now trying to use a timer to update the listview every second and show the latest message received but this isn't working either.
final Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
inboxArrayAdapter.notifyDataSetChanged();
((BaseAdapter)inboxmessages.getAdapter()).notifyDataSetChanged();
handler.postDelayed(this, 1000 );
}
}, 1000);
return view;
Original attempt of using BroadcastReceiver to update listview when new SMS message recieved.
SmSBroadcastReceiver.java
public class SmsBroadcastReceiver extends BroadcastReceiver
{
public static final String SMS_BUNDLE = "pdus";
// https://javapapers.com/android/android-receive-sms-tutorial/
public void onReceive(Context context, Intent intent)
{
Bundle intentExtras = intent.getExtras();
if (intentExtras != null)
{
Object[] sms = (Object[]) intentExtras.get(SMS_BUNDLE);
String smsMessageStr = "";
for (int i = 0; i < sms.length; i++)
{
// Get sms message
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) sms[i]);
// Get content and number
String smsBody = smsMessage.getMessageBody().toString();
String address = smsMessage.getOriginatingAddress();
// Create display message
smsMessageStr += "SMS From: " + address + "\n";
smsMessageStr += smsBody + "\n";
// Add it to the list
CommandsFragment inst = CommandsFragment.instance();
inst.updateList(smsMessageStr);
}
CommandsFragment inst = CommandsFragment.instance();
inst.updateList(smsMessageStr);
}
}
}
CommandsFragment.java
public static CommandsFragment instance()
{
return inst;
}
#Override
public void onStart() {
super.onStart();
inst = this;
}
public static CommandsFragment newInstance()
{
CommandsFragment fragment = new CommandsFragment();
return fragment;
}
public void updateList(final String smsMessage)
{
inboxArrayAdapter.insert(smsMessage, 0);
inboxArrayAdapter.notifyDataSetChanged();
}
Put the listview update code inside a method in the Activity where the listview belongs, and call that method from broadcast receiver's onReceive. It would definitely work. Also check the code for whether you are updating the list view properly.
public class SmsBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context paramContext, Intent intent) { // change the parameters depending upon your requirements
// do something here with the sms received if necessary
// then call the listview update method here
}
}
Also to add to the answer don't forget to have this below in the AndroidManifest.xml file
</activity>
<receiver android:name=".SmsBroadcastReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
This above also fixed the solution for me. Thanks for your help guys.
I am creating an application in which I am sending SMS automatically on button click.When SMS is sent I get a response from server in form of SMS.I read that message and perform task on it. Now problem is that when I receive SMS I want to consider only messages received within one minute after button click. What to do.?
public class IncomingSms extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Global mApplication = ((Global)context.getApplicationContext());
String getPPN=mApplication.getPPN();
String getStatus=mApplication.getvStatus();
String ClientId=mApplication.getvClientId();
String MobileNo=mApplication.getvStrMobile();
String LocationId=mApplication.getVstrLocation();
String IMEI=mApplication.getVstrIMEI();
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();
mApplication.setvSenderNumber(senderNum);
mApplication.setvMessageBody(message);
String IsBroadCast=mApplication.getvAuthenticatedUser();
try
{
if(IsBroadCast=="1")
{
context.sendBroadcast(new Intent("Message_Recived"));
}
}
catch(Exception e){}
}
}
} catch (Exception e)
{
}
}
}
This class is called when SMS received and take me to Arming Activity's on receive method.
But I need that..Broadcast receiver only receive message only within 1 minute after sendinf SMS
ArmingActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_arming);
registerReceiver(broadcastReceiver, new IntentFilter("Message_Recived"));}
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// internet lost alert dialog method call from here...
// if(strPPN.equals())
Global globalVariable = (Global) getApplicationContext();
String vvSenderNumber=globalVariable.getvSenderNumber();
String vvMessageBody=globalVariable.getvMessageBody();
String vvPPN=strPPN;
};
public void sendSms(String PPN, String smsBody) {
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(PPN, null, smsBody, null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
if (strActionText.equals("1"))
{
sendSms(strPPN, MsgBody);
}
Here when send SMS start Broadcast receiver to start receiving SMS for 1 minute.
What to do?
you can do this with the Handler
for that start/register receiver and also start the Handler for the one minute
//start your broadcast here.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// write code to stop/unregister receiver.
}
}, 60*1000);
for further display time you can use CountDownTimer class.
Mobile number will be entered in an edittext by user on registration page in my Android application. How can I check that user entered his/her mobile number not other's ?
I've tried this :
TelephonyManager tMgr =(TelephonyManager)mAppContext.getSystemService(Context.TELEPHONY_SERVICE);
mPhoneNumber = tMgr.getLine1Number();
And compare this variable with edittext's text. But mPhoneNumber returns NULL in my case. Is there any other options? How to solve this ?
Any help would be appreciable.
I have tried this : Check source code :
public class MainActivity extends Activity{
Button submit;
EditText contact;
String phNo;
ProgressDialog progress;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contact = (EditText)findViewById(R.id.mobileNumber);
submit = (Button) findViewById(R.id.button1);
submit.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
phNo = contact.getText().toString();
new CheckOwnMobileNumber().execute();
Toast.makeText(getApplicationContext(), phNo, Toast.LENGTH_LONG).show();
}
});
}
private class CheckOwnMobileNumber extends AsyncTask<String, Void, String>
{
#Override
protected void onPostExecute(String result)
{
// TODO Auto-generated method stub
if(progress.isShowing())
{
progress.dismiss();
// Check SMS Received or not after that open dialog date
/*if(SMSReceiver.str.equals(phNo))
{
Toast.makeText(getApplicationContext(), "Thanks for providing your number.", Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(getApplicationContext(), "Provide your own mobile number please.", Toast.LENGTH_LONG).show();
return;
}*/
}
}
#Override
protected String doInBackground(String... params)
{
// TODO Auto-generated method stub
String msg = phNo;
try
{
sendSMS(phNo, msg);
}
catch(Exception ex)
{
Log.v("Exception :", ""+ex);
}
return null;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
progress = ProgressDialog.show(MainActivity.this, "","Checking Mobile Number...");
progress.setIndeterminate(true);
progress.getWindow().setLayout(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
super.onPreExecute();
}
}
private void sendSMS(String phoneNumber, String message)
{
//PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, new Intent(getApplicationContext(), MainActivity.class), 0);
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, null, null);
}
}
Receiver to listen SMS received or not ?
public class SMSReceiver extends BroadcastReceiver
{
private static final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
Context mContext;
private Intent mIntent;
static String address, str = null;
// Retrieve SMS
public void onReceive(Context context, Intent intent) {
mContext = context;
mIntent = intent;
String action = intent.getAction();
if(action.equals(ACTION_SMS_RECEIVED))
{
SmsMessage[] msgs = getMessagesFromIntent(mIntent);
if (msgs != null)
{
for (int i = 0; i < msgs.length; i++)
{
address = msgs[i].getOriginatingAddress();
str = msgs[i].getMessageBody().toString();
}
}
// ---send a broadcast intent to update the SMS received in the
// activity---
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("SMS_RECEIVED_ACTION");
broadcastIntent.putExtra("sms", str);
context.sendBroadcast(broadcastIntent);
}
}
public static SmsMessage[] getMessagesFromIntent(Intent intent)
{
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
byte[][] pduObjs = new byte[messages.length][];
for (int i = 0; i < messages.length; i++)
{
pduObjs[i] = (byte[]) messages[i];
}
byte[][] pdus = new byte[pduObjs.length][];
int pduCount = pdus.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
for (int i = 0; i < pduCount; i++)
{
pdus[i] = pduObjs[i];
msgs[i] = SmsMessage.createFromPdu(pdus[i]);
}
return msgs;
}
}
LOGCAT :
03-13 17:31:02.049: E/ActivityManager(161): ANR in com.example.test
03-13 17:31:02.049: E/ActivityManager(161): Reason: Broadcast of Intent { act=android.provider.Telephony.SMS_RECEIVED cmp=com.example.test/.SMSReceiver (has extras) }
03-13 17:31:02.049: E/ActivityManager(161): 54% 3732/com.example.test: 54% user + 0% kernel / faults: 21 minor
03-13 17:31:02.049: E/ActivityManager(161): 40% 3732/com.example.test: 40% user + 0% kernel / faults: 2 minor
03-13 17:31:30.699: I/ActivityManager(161): Killing com.example.test (pid=3732): user's request
03-13 17:31:30.799: I/ActivityManager(161): Process com.example.test (pid 3732) has died.
03-13 17:31:30.799: I/WindowManager(161): WIN DEATH: Window{40992f50 com.example.test/com.example.test.MainActivity paused=false}
03-13 17:31:30.819: E/InputDispatcher(161): channel '40818670 com.example.test/com.example.test.MainActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x8
03-13 17:31:30.819: E/InputDispatcher(161): channel '40818670 com.example.test/com.example.test.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
03-13 17:34:59.649: I/ActivityManager(161): Start proc com.example.test for broadcast com.example.test/.SMSReceiver: pid=4037 uid=10098 gids={}
Its not guaranteed that tMgr.getLine1Number(); will always return your SIM card's number. Because it depends on the availability of number in SIM card. Like in my case, my Tre-Sweden SIM card doesn't contain my phone number.
But if you put the SIM card into an old SonyEricsson or Nokia phone, then you would get an option to edit this number (on SIM). Once its done, the android device will recognize the number and will show you.
Besides, if you do get your phone number through the code, then the best way to compare two numbers is:
boolean isSame = PhoneNumberUtils.compare(num1, num2);
Alternatively, you may implement some sort of pin-code verification logic (like Viber, WhatsApp or other application does) in which you ask the user to enter their phone number during registration. Later, that phone number is sent to the server and a pin-code is generated against that number which is sent to the user via SMS. Finally, the user has to enter that pin-code (received in SMS) to complete the registration.
Or
Simply send an SMS from user's device (with a consent) to your server/device and get to know their phone number.
Getting the phone number using getLine1Number() is not secure nor certain.
It is generally accepted because this whole "getting the phone number" is clash of multiple issues such as user's privacy, carrier's branding, and even the vendor's.
Anyway, unlike ios, android's android.provider.Telephony.SMS_RECEIVED makes the whole process very convenient and seemless to the user: You get to capture the sms and read it without any need of the user's intervention.
What is one way of doing it?
On your server, upon receiving the request to verify a phone number, you should generate a secret code, tokenSent, and send it to the app. Now, your server should send this code by sms to the specified phone number. The app by now should have a registered receiver listening for the android.provider.Telephony.SMS_RECEIVED intent. Once received, the app verifies that the tokenSent is identical to what it received from the server. At this point, phone registration is done and the server can be notified.
What could go wrong?
Generally, such apps are usually paid apps and it is not the user's good to attempt anything. Still, the user might enter a wrong number which he right now has. Then upon receiving the sms, he could forward it to the mobile where the app is registering. The app will then receive the tokenSent and wrongly verify the phone number.
How can we tackle this?
The feasibility of the solution depends on whether the sms provider allows your server to know the sender's phone number. This is probably (AFAIK) not gonna happen but if it does then you're in luck. That way, the app can, upon receiving the tokenSent, send it back to the server along with the sender of the sms. The server then can verify that this is the sms that was originated from your service provider.
Any more feasible solution? (If I am really paranoid)
In this case, the best solution, I believe, would be to request a tokenSent from your server. The server saves a generated tokenSent along with the phone number entered and sends this token to the app. The app notifies the user that registration will cost him 1 sms. Once the user accepts, you can easily send an sms in the background containing this tokenSent to a certain service. The server, once receives this tokenSent verifies the user using the token and the sender of the sms. Of course, this may seem a bit harassing and infringing to the user but it is the most secure way especially for such a paranoid (reading this part).
Formalities :P
Add Permissions in Manifest
<uses-permission android:name="android.permission.RECEIVE_SMS">
Register the receiver (Do this just before you send the sms to the phone)
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getExtras() != null)
{
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
SmsMessage[] msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
String from = msgs[i].getOriginatingAddress();
String body = msgs[i].getMessageBody().toString();
//here is the body
//...
unregisterReceiver(this); //If you are done with verification
}
}
}
}, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
I solved it my self. Here is my working code.
MainActivity Class :
public class MainActivity extends Activity
{
Button submit;
EditText contact;
static String phNo;
ProgressDialog progress;
static Boolean wasMyOwnNumber;
static Boolean workDone;
final static int SMS_ROUNDTRIP_TIMOUT = 30000;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contact = (EditText)findViewById(R.id.mobileNumber);
submit = (Button) findViewById(R.id.button1);
wasMyOwnNumber = false;
workDone = false;
submit.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
phNo = contact.getText().toString();
new CheckOwnMobileNumber().execute();
}
});
}
private class CheckOwnMobileNumber extends AsyncTask<String, Void, String>
{
#Override
protected void onPostExecute(String result)
{
// TODO Auto-generated method stub
if(progress.isShowing())
{
progress.dismiss();
if(wasMyOwnNumber)
{
Toast.makeText(getApplicationContext(), "Number matched.", Toast.LENGTH_LONG).show();
wasMyOwnNumber = false;
workDone = false;
}
else
{
Toast.makeText(getApplicationContext(), "Wrong number.", Toast.LENGTH_LONG).show();
wasMyOwnNumber = false;
workDone = false;
return;
}
}
super.onPostExecute(result);
}
#Override
protected String doInBackground(String... params)
{
// TODO Auto-generated method stub
String msg = phNo;
try
{
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phNo, null, msg, null, null);
timeout();
}
catch(Exception ex)
{
Log.v("Exception :", ""+ex);
}
return null;
}
#Override
protected void onPreExecute()
{
// TODO Auto-generated method stub
progress = ProgressDialog.show(MainActivity.this, "","Checking Mobile Number...");
progress.setIndeterminate(true);
progress.getWindow().setLayout(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
super.onPreExecute();
}
}
private boolean timeout()
{
int waited = 0;
while (waited < SMS_ROUNDTRIP_TIMOUT)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
waited += 100;
if(phoneNumberConfirmationReceived())
{
waited=SMS_ROUNDTRIP_TIMOUT;
workDone = true;
}
}
/*Log.v("MainActivity:timeout2: Waited: " , ""+waited);
Log.v("MainActivity:timeout2:Comparision: ", ""+ phoneNumberConfirmationReceived());
Log.v("MainActivity:timeout2: WorkDone value after wait complete : ", ""+workDone);*/
return workDone;
}
private boolean phoneNumberConfirmationReceived()
{
if(wasMyOwnNumber)
{
workDone = true;
}
return workDone;
}
}
SMSReceiver Code :
public class SMSReceiver extends BroadcastReceiver
{
private static final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
Context mContext;
private Intent mIntent;
static String address, str = null;
boolean isSame;
// Retrieve SMS
public void onReceive(Context context, Intent intent)
{
mContext = context;
mIntent = intent;
String action = intent.getAction();
if(action.equals(ACTION_SMS_RECEIVED))
{
SmsMessage[] msgs = getMessagesFromIntent(mIntent);
if (msgs != null)
{
for (int i = 0; i < msgs.length; i++)
{
address = msgs[i].getOriginatingAddress();
str = msgs[i].getMessageBody().toString();
}
}
Log.v("Originating Address : Sender :", ""+address);
Log.v("Message from sender :", ""+str);
isSame = PhoneNumberUtils.compare(str, MainActivity.phNo);
Log.v("Comparison :", "Yes this true. "+isSame);
if(isSame)
{
MainActivity.wasMyOwnNumber = isSame;
MainActivity.workDone=true;
}
// ---send a broadcast intent to update the SMS received in the
// activity---
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("SMS_RECEIVED_ACTION");
broadcastIntent.putExtra("sms", str);
context.sendBroadcast(broadcastIntent);
}
}
public static SmsMessage[] getMessagesFromIntent(Intent intent)
{
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
byte[][] pduObjs = new byte[messages.length][];
for (int i = 0; i < messages.length; i++)
{
pduObjs[i] = (byte[]) messages[i];
}
byte[][] pdus = new byte[pduObjs.length][];
int pduCount = pdus.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
for (int i = 0; i < pduCount; i++)
{
pdus[i] = pduObjs[i];
msgs[i] = SmsMessage.createFromPdu(pdus[i]);
}
return msgs;
}
}
No ANR found.
public class MainActivity extends Activity{
Button submit;
EditText contact;
String phNo;
ProgressDialog progress;
Boolean wasMyOwnNumber = false;
Boolean workDone = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contact = (EditText)findViewById(R.id.mobileNumber);
submit = (Button) findViewById(R.id.button1);
submit.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
phNo = contact.getText().toString();
new CheckOwnMobileNumber().execute();
Toast.makeText(getApplicationContext(), phNo, Toast.LENGTH_LONG).show();
}
});
}
private class CheckOwnMobileNumber extends AsyncTask<String, Void, String>
{
#Override
protected void onPostExecute(String result)
{
// TODO Auto-generated method stub
if(progress.isShowing())
{
progress.dismiss();
// Check SMS Received or not after that open dialog date
/*if(SMSReceiver.str.equals(phNo))
{
Toast.makeText(getApplicationContext(), "Thanks for providing your number.", Toast.LENGTH_LONG).show();
wasMyOwnNumber=true;workDone=true;
}
else
{
Toast.makeText(getApplicationContext(), "Provide your own mobile number please.", Toast.LENGTH_LONG).show();
wasMyOwnNumber=false;workDone=true;
return;
}*/
}
}
#Override
protected String doInBackground(String... params)
{
// TODO Auto-generated method stub
String msg = phNo;
try
{
sendSMS(phNo, msg);
int count=0;
while(!workDone)
{count++;}
}
catch(Exception ex)
{
Log.v("Exception :", ""+ex);
}
return null;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
progress = ProgressDialog.show(MainActivity.this, "","Checking Mobile Number...");
progress.setIndeterminate(true);
progress.getWindow().setLayout(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
super.onPreExecute();
}
}
private void sendSMS(String phoneNumber, String message)
{
//PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, new Intent(getApplicationContext(), MainActivity.class), 0);
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, null, null);
}
public class SMSReceiver extends BroadcastReceiver
{
private static final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
Context mContext;
private Intent mIntent;
static String address, str = null;
// Retrieve SMS
public void onReceive(Context context, Intent intent) {
mContext = context;
mIntent = intent;
String action = intent.getAction();
if(action.equals(ACTION_SMS_RECEIVED))
{
SmsMessage[] msgs = getMessagesFromIntent(mIntent);
if (msgs != null)
{
for (int i = 0; i < msgs.length; i++)
{
address = msgs[i].getOriginatingAddress();
str = msgs[i].getMessageBody().toString();
}
}
// ---send a broadcast intent to update the SMS received in the
// activity---
workDone=true;
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("SMS_RECEIVED_ACTION");
broadcastIntent.putExtra("sms", str);
context.sendBroadcast(broadcastIntent);
}
}
public static SmsMessage[] getMessagesFromIntent(Intent intent)
{
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
byte[][] pduObjs = new byte[messages.length][];
for (int i = 0; i < messages.length; i++)
{
pduObjs[i] = (byte[]) messages[i];
}
byte[][] pdus = new byte[pduObjs.length][];
int pduCount = pdus.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
for (int i = 0; i < pduCount; i++)
{
pdus[i] = pduObjs[i];
msgs[i] = SmsMessage.createFromPdu(pdus[i]);
}
return msgs;
}
}
}
Just want to add a bit here to above explanations in the above answers. Which will save time for others as well.
In my case this method didn't returned any mobile number, an empty string was returned. It was due to the case that I had ported my number on the new sim. So if I go into the Settings>About Phone>Status>My Phone Number it shows me "Unknown".
This is probably because you have ported the number from one network to other.
If you are not able to check the number from API Then:
One way of doing that is you generate a text message to the Number and send a Random Generated no to the Mobile Number. You will have to ask the user to enter this Random generated number into your Application. Once it is entered in the application then you can send it onto the server to check whether the number passed in the text is correct or not (Which you have already saved on server against that mobile number).
I hope this makes sense.
I'm fairly new to programming for android and programming in general. I searched the web and stackoverflow for a solution, but can't seem to find one.
I have an app with different tabs handled in fragments. One of my fragments contains a listview. However, the listview won't updat or refresh. It should refresh when I get an incoming sms. Here is the fragment code:
public class SmsSectionFragment extends Fragment {
#SuppressWarnings("null")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View listView = inflater.inflate(R.layout.fragment_section_sms, container, false);
ListView mListData = (ListView) listView.findViewById(R.id.lvData);
TextView aantalSms = (TextView) listView.findViewById(R.id.aantalSms);
ArrayList<SmsInfo> listSms = getIntent().getParcelableArrayListExtra("ListSMS");
// check condition
if(listSms != null && listSms.size() > 0) {
// set data to list
SmsInfoAdapter adapter = new SmsInfoAdapter(getActivity(), listSms);
mListData.setAdapter(adapter);
adapter.setNotifyOnChange(true);
int count = listSms.size();
aantalSms.setText(String.valueOf(count));
}
return listView;
}
The receiving of sms is handled in three other classes, the Receiver code is:
package com.example.android.effectivenavigation;
import... etc
public class SmsReceiver extends BroadcastReceiver {
static ArrayList<SmsInfo> listSms = new ArrayList<SmsInfo>();
#Override
public void onReceive(Context context, Intent intent) {
// get SMS map from intent
Bundle extras = intent.getExtras();
// a notification message
String messages = "";
if ( extras != null ) {
// get array data from SMS
Object[] smsExtra = (Object[]) extras.get( "pdus" ); // "pdus" is the key
for ( int i = 0; i < smsExtra.length; ++i ) {
// get sms message
SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
// get content and number
String body = sms.getMessageBody();
String adition = " SMS:: ";
String einde = " ::SMS";
String sendme = adition + body + einde;
String address = sms.getOriginatingAddress();
// create display message
messages += "SMS from " + address + " :\n";
messages += body + "\n";
//Send to Arduino
Amarino.sendDataToArduino(context, DEVICE_ADDRESS, 'T', sendme);
// store in the list
listSms.add(new SmsInfo(address, body));
}
// better check size before continue
if(listSms.size() > 0) {
// notify new arriving message
//Toast.makeText( context, messages, Toast.LENGTH_SHORT ).show();
// set data to send
Intent data = new Intent(context, MainActivity.class);
// new activity
data.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
data.putParcelableArrayListExtra("ListSMS", listSms);
// start
context.startActivity(data);
}
}
}
Could someone shine some light on my problem?
Many thanks in advance!
It looks to me like you have nothing that actually updates the fragment. Your broadcast receiver is receiving information but you never add this to the fragment.
Do something like in your fragment declaration add:
private SMSReceiver receiver;
private IntentFilter filter;
In your onCreateView add:
receiver = new SMSReceiver();
filter = new IntentFilter(SMSReceiver.YOUR_STRING_FILTER);
registerReceiver(receiver, filter);
And then in your onReceive in the SMSReceiver class add something like:
adapter = new SmsInfoAdapter (this, yourData);
list.setAdapter(adapter);
Having this all in the Fragment class is what I do.
I have an ArrayList of contacts that contains a phone number and a status field. I want to update the status field on a successful send result.
I even tried passing the index of the ArrayList item in to the Pending Intent with contacts.indexOf(c.getPhoneNumber()) as the int requestCode. I just cant' figure out how to tell which message is reporting back as successful and update my contact item.
package com.example.SMS;
public class SendSMSActivity extends SMSActivity {
private EditText smsMessageBody;
private Button send_button;
private SmsManager sms;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sendsmsactivity);
setupViews();
}
private void setupViews() {
smsMessageBody = (EditText) findViewById(R.id.smsText_editText1);
broadcast_button = (Button) findViewById(R.id.sendsms_button);
send_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (smsMessageBody.getText().toString().length() > 0 ) {
if (!getSendSMSApplication().getCurrentContacts().isEmpty()) {
sendSMSLoop();
Toast.makeText(getBaseContext(), R.string.messages_sent, Toast.LENGTH_SHORT).show();
getSendSMSApplication().setCurrentContacts(null); // Clear existing contacts after send
finish();
} else {
Toast.makeText(getBaseContext(), R.string.error_no_numbers, Toast.LENGTH_SHORT).show();
} // there are phone numbers to send to?
} else {
Toast.makeText(getBaseContext(), R.string.error_no_message, Toast.LENGTH_SHORT).show();
} // user entered a message?
}
});
}
protected void sendSMSLoop() {
ArrayList<ContactItem> contacts = getSendSMSApplication().getCurrentContacts();
for (ContactItem c:contacts) {
sendSMS(c.getPhoneNumber().toString(), smsMessageBody.getText().toString(), contacts.indexOf(c.getPhoneNumber()));
}
}
public void sendSMS(String phoneNumber, String message, int messageIndex)
{
String SENT = "SMS_SENT";
PendingIntent sentPI = PendingIntent.getBroadcast(this, messageIndex, new Intent(SENT), 0);
registerReceiver(new BroadcastReceiver(){
#Override
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode())
{
case Activity.RESULT_OK:
Toast.makeText(getBaseContext(), R.string.sms_sent, Toast.LENGTH_SHORT).show();
break;
}
}
}, new IntentFilter(SENT));
sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, sentPI, null);
}
}
I am trying to do this myself at the moment. I guess you have got the same problem as me and if you are sending more than 1 message, they are all returning the same sent code for all 3 messages. I think the trick here is to 'thread' each message so that each 'thread' will have a different return code. I can't guarantee this is the solution but it is the path I am next going to go down for solving this issue.
Hope this helps, if you work it out please let me know too.
This is some code taken from my actual code:
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++)
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
if (messages.length > -1) {
//The 2 variables you need (from and body)
messages[0].getOriginatingAddress();
messages[0].getMessageBody();
...
Try passing the received/delivered intent to this function (complete the function to add the functionality you need), I will be trying it in a few weeks time so let me know how it goes if you beat me to it.
Just re-looked over your code...
sms.sendTextMessage(phoneNumber, null, message, sentPI, null);
My code looks more like:
sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI);
You need to add the extra intent to work with the pdus, as far as I am aware.