Update ListView every second with Handler not working - android

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.

Related

How can I check whether response is came within one minute after sending SMS in android?

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.

SMS Receiving broadcast receiver does not seem to work

I am preparing an app which requires me to have user's phone number and then send a hashcode the user programatically as SMS so that it will be used as their token afterwards.
I am making the user enter the number in the MainActivty and have my receiver which listens to SMS_RECEIVED so that it will notiy the user, first of all I want to make sure I am sending and receiving the user's number correctly and receving it. However my receiver does not seems to listen to the trigger. I can see the received sms on notification as well as I can hear the sound but broadcast receiver does not listens to it.
My Code for MainActivity is
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 View.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;
}
MyCode for SMSReceiver is
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)
{
Log.v("ONMESSAGE", "RECEIVED");
mContext = context;
mIntent = intent;
String action = intent.getAction();
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;
}
}
*My entries in Manifest is *
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.getphonenumber"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.getphonenumber.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.example.getphonenumber.SMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
Give a priority value for the intent..
change your <intent-filter> as following
<intent-filter android:priority="999" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
Have a try..
Also add permission to receive sms
<uses-permission android:name="android.permission.RECEIVE_SMS" />
After spending most of a day stuck here, figured I'd share my experience in case anyone is stuck in the same boat. I spent several hours troubleshooting a failure to get any sms notifications which I finally resolved with calls to acquire permissions. I believe it is related to the changes in permissions in recent sdk versions.
I set up receiver in androidmanifest.xml as stated above, and I also added it programmatically without any luck.
I had permissions in androidmanifest.xml:
<uses-feature android:name="android.permission.RECEIVE_SMS" android:required="true"></uses-feature>
<uses-feature android:name="android.permission.READ_SMS" android:required="true"></uses-feature>
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
I had the same issue whether I put the receiver in the androidmanifest.xml (in the receiver block under the application block) or if I did it programmatically as follows:
private void InstallFunction () {
final YourActivity activity = this;
this.smsReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
activity.onReceiveIntent(context, intent);
}
};
filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); // tried 0, 999, Integer.MaxValue, etc.
filter.addAction(Telephony.Sms.Intents.SMS_RECEIVED_ACTION); // SMS
this.registerReceiver(smsReceiver, filter);
It gave no error nor logged any warnings, but the onReceive was never called using sms on emulator or on my phone.
A call to check if I had the permissions as per the one below said I had both.
canReadSMS = ActivityCompat.checkSelfPermission(this,
Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED;
canReceiveSMS = ActivityCompat.checkSelfPermission(this,
Manifest.permission.Manifest.permission.RECEIVE_SMS) == PackageManager.PERMISSION_GRANTED);
canReadSMS and canReceiveSMS were both true.
Despite that, no events ever arrived. After rewriting it several times, and trying everything a million ways, I finally decided to ignore the permissions responses and ask for permission anyway.
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.RECEIVE_SMS) ||
ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_SMS)) {
new AlertDialog.Builder(this)
.setMessage("Would you like TheApp to handle confirmation codes text messages for you to make registration easier?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(activity,
new String[]{
Manifest.permission.RECEIVE_SMS,
Manifest.permission.READ_SMS
},
SMS_PERMISSIONS_REQUEST_ID);
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create()
.show();
After running this, the notifications started arriving and I was very excited. Originally, I did not have the calls to 'shouldShowRequestPermissionRationale' which seemed to lead to problems with crashing or ending up at an activity where the input wouldn't let me enter data. After some research, I came across the ActivityCompat.shouldShowRequestPermissionRationale(... as per the code above. After the user has given the app permissions for sms, that function seems to no longer return true. The end result is that they are asked a single time for the permission for the app. The other complication I think brought about by the new permissions scheme was that if I asked for permission on the confirmation page, they could be responding to the permissions query when the text arrived -- in which case the text would not arrive to the message handler. I resorted to asking for permissions on the registration page prior to opening up the confirmation page. This worked nicely.
Note: SMS_PERMISSIONS_REQUEST_ID is a just variable with a particular integer value assigned. Assign it any reasonable name and number you like.
In general, you implement the override "onRequestPermissionsResult" function to determine if you got permissions or not, but in my case the permission was optional -- if the app cannot read the sms, the user can still manually type or past the code. That being the case, I was able to omit that override. Depending on your implementation, you might need it -- many samples are available for that handler. The ID defined above is used in that handler to determine that you are getting the result for the permissions request you just made.
There are also numerous examples of processing the sms messages, but in case anyone lands here, I'll include my code that processed incoming SMS. It's intentionally written a bit wordy and easy to digest as I was hunting problems.
private void onReceiveIntent (Context context, Intent intent) {
if (context == this &&
intent != null) {
if (intent.getAction ().toString ().equals (Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
Bundle bundle;
bundle = intent.getExtras ();
if (bundle != null) {
Object[] pdus;
String format;
format = bundle.getString ("format");
pdus = (Object[]) bundle.get("pdus");
if (pdus != null &&
pdus.length > 0) {
StringBuilder body;
SmsMessage header;
SmsMessage sms;
body = new StringBuilder();
header = SmsMessage.createFromPdu((byte[]) pdus[0],
format);
for (Object pdu : pdus) {
//sms = SmsMessage.createFromPdu ((byte[]) pdu); <-- has been deprecated
sms = SmsMessage.createFromPdu ((byte[]) pdu,
format); // <-- the new way -- get the format as per above.
if (sms != null) {
body.append (sms.getDisplayMessageBody());
}
}
ProcessSmsMessage (header,
body.toString ());
}
}
}
}
}
private void ProcessSmsMessage(SmsMessage header,
String message) {
if (header != null &&
message != null) {
String originator;
originator = header.getOriginatingAddress();
ProcessSmsMessage(originator,
message);
}
}
private void ProcessSmsMessage(String originator,
String message) {
if (originator != null &&
originator.equals ("##########")) { // does it come from my twilio sms number?
if (message.startsWith("$TheApp$ Device Verification Code:")) {
final DeviceConfirmationActivity confirmationActivity = this;
final String code;
code = message.substring (##); // past the name and text message above
this.mConfirmationCodeView.setText (code); // <-- the manual entry box now filled for them
// now you can do some work. I use a custom timer to do this work on main thread
// per much research, you should avoid doing lengthy operation in this thread
// You can also set up a job.
confirmationActivity.DoDeviceConfirmation(code);
}
}
}
As mentioned in the code, the
sms = SmsMessage.createFromPdu ((byte[]) pdu);
used in most sample code is now deprecated. Fortunately, found some samples that showed the new version:
sms = SmsMessage.createFromPdu ((byte[]) pdu,
format);
and that the format comes from: bundle.getString ("format"); as per code above.
Thanks a lot to Shirish Herwade especially: SmsMessage.createFromPdu is deprecated in android API level 23
Hope that helps someone stuck the way I was. I am fairly new to Android programming having resorted to cordova in the past, so someone else may be able to provide better insight on why that permissions call had to be made before getting notifications even though permissions checks return values that would make one think I already had said permission.
Add permission :
<uses-permission android:name="android.permission.RECEIVE_SMS" />
Write in manifest:
<receiver
android:name="yourpackagename.SmsReceive"
android:enabled="true" >
<intent-filter android:priority="1000" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
SmsReceive class:
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
if (bundle != null) {
str = "";
substr = null;
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]);
str += "SMS from " + msgs[i].getOriginatingAddress();
sender=msgs[i].getOriginatingAddress();
str += msgs[i].getMessageBody().toString();
if(str.length()!=0)
{
//write the logic
}
}
}
}

Android: pass variables from Activity to BroadcastReceiver

I have some problem with passing throught my variable from Activity to the BroadcastReceiver...
Here is my code:
here is my Broadcast receiver code... I try to catch SMS from one phone number which I have got from my Activity...
public class SMSMonitor extends BroadcastReceiver
{
private static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";
public static String phone_number = "";
public static String msg_body = "";
public static final String SMS_EXTRA_NAME = "pdus";
#Override
public void onReceive(Context context, Intent intent)
{
String phone = intent.getExtras().getString("trusted_num");
if (intent != null && intent.getAction() != null && ACTION.compareToIgnoreCase(intent.getAction()) == 0)
{
Object[] pduArray = (Object[]) intent.getExtras().get("pdus");
SmsMessage[] messages = new SmsMessage[pduArray.length];
for (int i = 0; i < pduArray.length; i++)
{
messages[i] = SmsMessage.createFromPdu((byte[]) pduArray[i]);
}
phone_number = messages[0].getDisplayOriginatingAddress();
msg_body = messages[0].getMessageBody();
System.out.println("Phone number: "+phone_number);
System.out.println("Phone entered: "+phone);
}
}
}
Here is my Activity code:
public class Settings extends Activity implements OnClickListener{
private Button btn_save;
private EditText txt_phone;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
//set Save button
btn_save = (Button)findViewById(R.id.btn_save);
txt_phone = (EditText)findViewById(R.id.et_phone);
btn_save.setOnClickListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_settings, menu);
return true;
}
#Override
public void onClick(View v)
{
if (v == btn_save)
{
try
{
String phone_num = txt_phone.getText().toString();
Intent i = new Intent(Settings.this, SMSMonitor.class);
i.putExtra("trusted_num", phone_num);
sendBroadcast(i);
}
catch(Exception e)
{
System.out.println("Error: "+e.getLocalizedMessage());
}
}
}
}
In this code I have text field for entering the phone number, which I need to pass to the BroadcastReceiver with intent.putExtra() method, but in LogCat I see, that variable didnot pass:
07-25 18:43:57.382: I/System.out(14245): Phone number: +37129690449
07-25 18:43:57.382: I/System.out(14245): Phone entered: null
So what I am doing wrong here?
UPD
Maybe code is not correct, but it works for me...
public void onReceive(Context context, Intent intent)
{
phone = intent.getExtras().getString("trusted_num");//get trusted phone number from Settings screen
//receive SMS
if (intent != null && intent.getAction() != null && ACTION.compareToIgnoreCase(intent.getAction()) == 0)
{
Object[] pduArray = (Object[]) intent.getExtras().get("pdus");
SmsMessage[] messages = new SmsMessage[pduArray.length];
for (int i = 0; i < pduArray.length; i++)
{
messages[i] = SmsMessage.createFromPdu((byte[]) pduArray[i]);
}
phone_number = messages[0].getDisplayOriginatingAddress();
msg_body = messages[0].getMessageBody();
System.out.println("Phone number: "+phone_number);
}
//check if number is not null
if (phone != null && phone != "")
{
System.out.println("Phone entered: "+phone);
}
}
}
You can't pass an intent to a broadcast receiver. "There is no way for a BroadcastReceiver to see or capture Intents used with startActivity()"
https://developer.android.com/reference/android/content/BroadcastReceiver.html
I had a similar issue a while back and solved it by using a combination of IntentServices and Activities. You have to restructure your program to fit these guidlines
Well, there are some things not that don't match:
You're sending an intent with no action in the first place, but you're specifying Broadcastreceiver's class; don't do like that:
Intent i = new Intent(Settings.this, SMSMonitor.class);
i.putExtra("trusted_num", phone_num);
sendBroadcast(i);
But try instead:
Intent i = new Intent("my_package_name.Some_general_constant");
i.putExtra("trusted_num", phone_num);
sendBroadcast(i);
Then, your BroadcastReceiver is supposed to know that it can also handle "Some_general_constant" action. For this reason, register an extra action in your Manifest file for your SMSMonitor:
<receiver android:name=".package_to_bla_bla.SMSMonitor">
<intent-filter>
<action android:name="my_package_name.Some_general_constant"/>
</intent-filter>
</receiver>
Then in your SMSMonitor you need to add an else if statement to handle this broadcast:
else if("my_package_name.Some_general_constant".equals(intent.getAction())
{
// get the data from intent and use it
}

Updating a listview in Fragment

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.

Android - how to use broadcast receiver to read SMS?

In my android project I need to detect and read SMS texts as they come in, then call a function from another class.
How can I put the below code in a class and define it properly in the manifest. If I put this on another Java file, then I don't know how to call a function from another Java file.
I tried putting this code in my main class but in my app, it just crashed.
public class SMSReceiverActivity extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Parse the SMS.
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null)
{
// Retrieve the SMS.
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]);
// In case of a particular App / Service.
//if(msgs[i].getOriginatingAddress().equals("+91XXX"))
//{
//str += "SMS from " + msgs[i].getOriginatingAddress();
//str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
//}
}
if (str != "") { // remove the last \n
str = str.substring(0, str.length()-1);
}
Reusable_CodeActivity.alert(my_ViewActivity.this, "AAAAAAAAAAA");
try {
//my_ViewActivity.this.handle_incoming_message(str);
} catch(Exception e) {
}
}
}
}
Your code for receiving SMS is correct. but when you are using BroadCastReceiver in Activity class you need to unregister it as follows in onStop() method. I think this is the reason your activity was crushing.
#Override
protected void onStop()
{
unregisterReceiver(mReceiver);
super.onStop();
}
If I understand your question correctly you want to receive broadcasts (when an SMS arrives) while your Activity is showing.
If so I found a nice pattern to do this a while back (Cant remember where I got it from, would be nice to give credit to the original author).
First, create an interface:
public interface Receiver {
public void onReceive(Context context, Intent intent);
}
Now create a subclass of BroadcastReceiver which we can dynamically register at runtime:
public class PortableReceiver extends BroadcastReceiver {
private Receiver mReceiver;
public void setReceiver(Receiver receiver) {
mReceiver = receiver;
}
public Receiver getReceiver() {
return mReceiver;
}
#Override
public void onReceive(Context context, Intent intent) {
if (mReceiver != null)
mReceiver.onReceive(context, intent);
else
Log.w("PortableReceiver", "Dropping received Result");
}
}
Now we can use a PortableReceiver in the activity class:
public class MyActivity implements Receiver {
private PortableReceiver mReceiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReceiver = new PortableReceiver();
mReceiver.setReceiver(this);
}
#Override
public void onResume() {
super.onResume();
// Register the receiver
IntentFilter filter = new IntentFilter();
filter.addAction("_my_intent_action"); //TODO: add actions to filter just as you would in your AndroidManifest
registerReceiver(mReceiver, filter, null, null);
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
#Override
public void onReceive(Context context, Intent intent) {
//TODO: Your code goes here!
}
}
Now you have your Activity class directly handling the Broadcast, so you can access all the functionality it has available.
Note that if you want to start an activity from a BroadcastReceiver, thats a little different. If thats the case, I recommend you check out http://www.vogella.com/articles/AndroidServices/article.html#pre_broadcastreceiver

Categories

Resources