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.
Related
My project is a checklist of phone numbers in a recyclerView/cardView. The phone numbers/businesses can be added or subtracted by a checkBox to make individual groups. I want to be able to send a group multi-text to the selected individuals.
My problem is that only the first phone number (recipient) in a group receives the message while the rest receive nothing, but the numbers still display in the edit text (the first is the only functioning number).
I have tried a lot of different ways but nothing has worked, I am about to give up.
No one seems to know how to fix this problem. If this problem can be solved please let me know.
I don't want to loop the numbers and text individually, that was a suggested fix.
This is the phone activity:
public class ACPhone extends AppCompatActivity {
private static final String SEPARATOR = ";";
EditText txtPhoneNo;
EditText txtMessage;
TextView txtView;
Button btnsend;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_acphone);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
txtPhoneNo = (EditText) findViewById(R.id.txtPhoneNo);
txtMessage = (EditText) findViewById(R.id.txtMessage);
txtView = (TextView)findViewById(R.id.txtMessageMass);
btnsend = (Button) findViewById(R.id.btnSend);
Intent intent = getIntent();
if (intent != null){
ArrayList<CharSequence> selectedNumbers =
intent.getCharSequenceArrayListExtra(SELECTED_NUMBERS);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < selectedNumbers.size(); i++) {
sb.append(selectedNumbers.get(i));
if (i != selectedNumbers.size() - 1){
sb.append(SEPARATOR);
}
}
txtPhoneNo.setText(sb.toString());
}
btnsend.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
String phoneNo = txtPhoneNo.getText().toString();
String message = txtMessage.getText().toString();
String messageView = txtView.getText().toString();
if (phoneNo.length() > 0 && message.length() > 0) {
sendMessage(phoneNo, message, messageView);
} else {
Toast.makeText(getBaseContext(), "Please enter message",
Toast.LENGTH_SHORT).show();
}
}
});
}
private void sendMessage(String phoneNo,String message, String staticMessage){
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phoneNo,null,message + "\n" +
staticMessage,null,null);
Toast.makeText(getApplicationContext(), "Message Sent",
Toast.LENGTH_SHORT).show();
}
catch (Exception e){
Toast.makeText(getApplicationContext(), "Unable to send. Please try again", Toast.LENGTH_SHORT).show();
}
}
}
You could create a list of all the numbers and do a for loop through the list in your onclick or in a method and call it in onclick. That's how I would do it anyway.
Following are the some steps to send one single message to multiple contact when it is checked.
Step 1 : In your MainActivity.class like this,
public class MainActivity extends AppCompatActivity {
ListView listView;
EditText editMessage;
ProgressDialog progressDialog;
Handler progresshandler;
boolean isThreadRunning;
int i;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.contactsView);
editMessage = (EditText) findViewById(R.id.editMessage);
listView.setAdapter(new ContactAdapter(this, contacts));
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Sending Messages.. Please wait!");
progresshandler = new Handler() {
public void handleMessage(Message msg) {
progressDialog.dismiss();
Toast.makeText(MainActivity.this, "Messages Sent",
Toast.LENGTH_LONG).show();
}
};
}
}
Step 2 : Create one class within this MainActivity.class(Put this class below onCreate() method)
class SendMessagesThread extends Thread {
Handler handler;
public SendMessagesThread(Handler handler) {
this.handler = handler;
}
public void run() {
SmsManager smsManager = SmsManager.getDefault();
// Find out which contacts are selected
for (int i = 0; i < listView.getCount(); i++) {
View item = (View) listView.getChildAt(i);
boolean selected = ((CheckBox) item.findViewById(R.id.selected)).isChecked();
if (selected) {
String mobile = ((TextView) item.findViewById(R.id.mobile)).getText().toString();
try {
smsManager.sendTextMessage(mobile, null, editMessage.getText().toString(), null, null);
} catch (Exception ex) {
Log.d("Mobile", "Could not send message to " + mobile);
}
}
}
Message m = handler.obtainMessage();
handler.sendMessage(m);
} // run
} // Thread
Step 3: Create one method(put this method below step - 2)
public void sendMessages(View v) {
if (editMessage.getText().toString().length() > 0) {
SendMessagesThread thread = new SendMessagesThread(progresshandler);
thread.start();
progressDialog.show();
} else {
Toast.makeText(this, "Please enter message!", Toast.LENGTH_LONG)
.show();
}
}
Note : According to my project, I am not using any SQLite database or webservice.Basically, I am fetching all the contact from device contact book and displaying that contact to listview. So, Try to understand and modify.
public class TextActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<CharSequence> selectedNumbers
=getIntent().getCharSequenceArrayListExtra(SELECTED_NUMBERS);;
String phNumbers = "";
for (CharSequence s: selectedNumbers) {
phNumbers += s + ";";
}
// for (int i = 0; i < selectedNumbers.size(); i++) {
// phNumbers += selectedNumbers.get(i);
// if (i != selectedNumbers.size()-1){
// phNumbers += ";";
// }
// }
phNumbers = phNumbers.substring(0, phNumbers.length() - 1);
String message = "";
Intent smsIntent = new Intent(Intent.ACTION_VIEW);
smsIntent.setType("vnd.android-dir/mms-sms");
smsIntent.putExtra("address", phNumbers);
smsIntent.putExtra("sms_body",message);
startActivity(smsIntent);
}
}
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.
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
}
I'm developing an Android app to block incoming SMS messages and release them after do some process.
What I want to do is, When a SMS received that message need to be blocked and push it to an online server. After that an administrator can view those messages pushed to the server through a website and he/she can approve or reject. If the admin approve the message it need to be release to the phone inbox else discard the message.
I complete everything except one thing. What I did is after the message pushed to the server a scheduled timer task will be started and read the online server in every 5min and check weather the message is approved. I'm using a "BroadcastReceiver" to track incoming messages and I know that to relese a blocked message I should use "clearAbortBroadcast()" method before "onReceive" method end. BUT my timer act as a thread. So if I call "clearAbortBroadcast()" method inside the timer the "onReceive" method is already finished execution and message doesn't get released.
Can some one help me to overcome this problem.
my BroadcastReceiver class
public class SmsReceiver extends BroadcastReceiver{
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
public static long NOTIFY_INTERVAL = 15000;
int id;
Context context;
SmsReceiver sr;
GetMsgStatus status;
Bundle bundle;
#Override
public void onReceive(Context context, Intent intent)
{
//this stops notifications to others
this.abortBroadcast();
this.context = context;
//create a instance of GetMsgStatus class
status = new GetMsgStatus(context);
//---get the SMS message passed in---
bundle = intent.getExtras();
SmsMessage[] msgs = null;
String from = null;
String to = null;
String msg= null;
String str = "";
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]);
str += "SMS from " + msgs[i].getOriginatingAddress();
from = msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
msg = msgs[i].getMessageBody().toString();
str += "\n";
}
System.out.println("from "+from);
System.out.println("msg "+msg);
Toast.makeText(context, "SMS Received : ",Toast.LENGTH_LONG).show();
TelephonyManager mTelephonyMgr;
mTelephonyMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
to = mTelephonyMgr.getLine1Number();
//push msg to the server
SendMsgToServer send = new SendMsgToServer(context, to, from, msg);
//get the msg id of the pushed msg
id = send.getId();
// cancel if already existed
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run()
{
status.getDataFromServer(id);
//if status is 0 means msg rejected
if(status.getStatus()==0)
{
mTimer.cancel();
}
//if status is 1 means msg approved
else if(status.getStatus()==1)
{
sr.clearAbortBroadcast();
mTimer.cancel();
}
//pending
else
{
System.out.println("pending");
}
}
});
}
}
}
A BroadcastReceiver is not supposed to live that much, so you can't depend on clearAbortBroadcast().
In your case I think your flow would be:
Receive broadcast and send to server.
Abort the broadcast and delete SMS from cellphone (user should be warned about this)
Wait for approval from server.
If approved, save the message to SMS and notify the user.
I don't think this kind of censor is good, but you may have your reasons, just make sure the user who install this knows what it does.
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.