First of all, sorry for my bad grammar. I am developing Auto Reply Message Application using broadcastreceiver i have problem with when I can receive value from activity to broadcastreceiver, the Auto Reply won't work. But if I'm not receive value from Activity, it's working. this is my activity code, I put it in onSensorChanged()
Intent i = new Intent("my.action.string");
i.putExtra("apaan", lala);
sendBroadcast(i);
and this is my broadcastreceiver class
public class AutoReply extends BroadcastReceiver{
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("message", "Broadcast Received: " +action);
if (action.equals(SMS_RECEIVED) && action.equals("my.action.string")) {
Bundle bundle = intent.getExtras();
String state = bundle.getString("apaan");
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
final SmsMessage[] sms = new SmsMessage[pdus.length];
String isiSMS = "", noPengirim = "";
for (int i = 0; i < pdus.length; i++) {
sms[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
isiSMS = sms[i].getMessageBody();//mengambil isi pesan dari pengirim
noPengirim = sms[i].getOriginatingAddress();//mengambil no pengirim
}
String message = state;//isi balasan autoreplay
SmsManager smsSend = SmsManager.getDefault();
smsSend.sendTextMessage(noPengirim, null, message, null, null);
}
}
}
and this is my manifest
<receiver android:name=".AutoReply" android:enabled="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="my.action.string" />
</intent-filter>
</receiver>
The action will never be both android.provider.Telephony.SMS_RECEIVED and my.action.string.
Change this:
if (action.equals(SMS_RECEIVED) && action.equals("my.action.string")) {
To this:
if (action.equals(SMS_RECEIVED) || action.equals("my.action.string")) {
In addition, you're not sending pdus in the manually created Intent, so when you call bundle.get("pdus") it will return null. Then when you call pdus.length it will throw a NullPointerException.
Related
I'm developing a SMS based chat application using some Telco APIS.
I am receiving SMS only from a particular number and I want to know how I can prevent SMS being sent to the the default inbox of android.
Following is the code of my SMS receiver.
Compile SDK: 27
public void onReceive(Context context, Intent intent) {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
this.intent = new Intent(BROADCAST_ACTION);
this.context = context;
chatlogDBAdapter = new ChatlogDBAdapter(context);
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;
if(senderNum.equals("77100")){
String message = currentMessage.getDisplayMessageBody();
Log.i("SmsReceiver", "senderNum: "+ senderNum + "; message: " + message);
String timestamp = String.valueOf(System.currentTimeMillis());
String[] messagearray = message.split(",", -1);
String username = messagearray[0];
String messagebody = messagearray[1];
chatlogDBAdapter.addMessage(username,username,"username",messagebody,timestamp);
msgusername = username;
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 10);
}
}
abortBroadcast();
return;
}
} catch (Exception e) {
Log.e("SmsReceiver", "Exception smsReceiver" +e);
}
}
And the manifest
<receiver
android:name=".IncomingSms"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.provider.Telephony.SMS_DELIVER" />
<action android:name="android.provider.Telephony.SMS_DELIVER_ACTION" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
As of KitKat only one app can consume received sms directly with SMS_DELIVER_ACTION: changelog blog here.
Any filters for the SMS_RECEIVED_ACTION broadcast in existing apps will continue to work the same on Android 4.4, but only as an observer of new messages, because unless your app also receives the SMS_DELIVER_ACTION broadcast, you cannot write to the SMS Provider on Android 4.4.
how I can prevent SMS being sent to the the default inbox of android.
Its not possible unless you make your app default SMS app. Starting from Andriod Kitkat only SMS default app has capability to Write data to the provider.
You can send/receive Binary SMS which won't be visible in the Inbox/Sent box
So i'm working on a WhatsApp like verification system where user inputs the code received via sms and code is sent back to the server..yada yada ..all that basic stuff.
My dilemma is that i have received and read the sms correctly. How do i filter the body so that that it passes the number (not phone number but verification code) to the editText automatically. I'm trying to avoid users having to enter the verification code manually. Lemme show some code below.
public void processReceive(Context context, Intent intent){
Bundle bundle = intent.getExtras();
if(bundle == null){
return;
}
Object[] objectArray = (Object[])bundle.get("pdus");
for(int i = 0; i < objectArray.length; i++){
SmsMessage smsMsg = SmsMessage.createFromPdu((byte[])objectArray[i]);
String smsBody = smsMsg.getMessageBody();
Toast.makeText(context, smsBody, Toast.LENGTH_SHORT).show();
}
}
//In the code above, my broadcastReceiver receives the sms and i can display the body in a toast. The sms goes something like this: "Your verification code: 12345".
How do i get just the code from the sms and send its value to and editText programmatically like WhatsApp does.
number = (EditText) findViewById(R.id.number);
Thank you. You input is greatly appreciated
Try this it may be help to you
public static String GENERAL_OTP_TEMPLATE = "Your verification code: (.*).";
SmsMessage[] message = new SmsMessage[objectArray.length];
for (int i = 0; i < objectArray.length; i++) {
message[i] = SmsMessage.createFromPdu((byte[]) objectArray[i]);
}
Pattern generalOtpPattern = Pattern.compile(GENERAL_OTP_TEMPLATE);
Matcher generalOtpMatcher = generalOtpPattern.matcher(message[0].getMessageBody().toString());
if (generalOtpMatcher.find()) {
String otp = generalOtpMatcher.group(1);
number.setText(otp);
}
You can just use Split function to get your last 5 numbers :
String[] splited = body.split(":");
String mylastnum= splited[1];
number.settext(mylastnum);
hope it help !
register Broad cast Receiver in android manifest using below mention code.
<!-- SMS Receiver -->
<receiver android:name=".receiver.SmsReceiver">
<intent-filter android:priority="99999">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
Create Broad Cast Receiver using below mention code.
#Override
public void onReceive(Context context, Intent intent) {
final Bundle bundle = intent.getExtras();
try {
if (bundle != null) {
Object[] pdusObj = (Object[]) bundle.get("pdus");
for (Object aPdusObj : pdusObj) {
SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) aPdusObj);
String senderAddress = currentMessage.getDisplayOriginatingAddress();
String message = currentMessage.getDisplayMessageBody();
Log.e(TAG, "Received SMS: " + message + ", Sender: " + senderAddress);
// if the SMS is not from our gateway, ignore the message
if (!senderAddress.toLowerCase().contains(Config.SMS_ORIGIN.toLowerCase())) {
Log.e(TAG, "SMS is not for our app!");
return;
}
// verification code from sms
String verificationCode = getVerificationCode(message);
Log.e(TAG, "OTP received: " + verificationCode);
Intent hhtpIntent = new Intent(context, HttpService.class);
hhtpIntent.putExtra("otp", verificationCode);
context.startService(hhtpIntent);
}
}
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
Parse Verification Code that come through SMS.
private String getVerificationCode(String message) {
String code = null;
int index = message.indexOf(Config.OTP_DELIMITER);
if (index != -1) {
int start = index + 2;
int length = 6;
code = message.substring(start, start + length);
return code;
}
return code;
}
I have following code
<receiver android:name=".SMSListener">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.provider.Telephony.SMS_SENT"/>
</intent-filter>
</receiver>
public class SMSListener extends BroadcastReceiver
{
private SharedPreferences customSharedPreference;
#Override
public void onReceive(Context context, Intent intent)
{
customSharedPreference = context.getSharedPreferences("UserSharedPrefs", Activity.MODE_PRIVATE);
if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED"))
{
Bundle bundle = intent.getExtras(); //---get the SMS message passed in---
SmsMessage[] msgs = null;
if (bundle != null)
{
//---retrieve the SMS message received---
try{
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]);
}
Editor editor = customSharedPreference.edit();
editor.putString("lastSmsReceived", String.valueOf(System.currentTimeMillis()));
editor.commit();
}catch(Exception e){
// Log.d("Exception caught",e.getMessage());
}
}
}
else if(intent.getAction().equals("android.provider.Telephony.SMS_SENT"))
{
Editor editor = customSharedPreference.edit();
editor.putString("lastSmsSent", String.valueOf(System.currentTimeMillis()));
editor.commit();
Log.d("SMS Sent", "SMS Sent");
}
}
}
With permissions
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
It detects SMS READ But SMS Sent is not detected. What else am I missing
There is no such action android.provider.Telephony.SMS_SENT. Android does not broadcast sent messages.
There is an alternative solution described here:
Android Broadcast Receiver for Sent SMS messages?
I am creating an app that receives SMS text messages, I have created a class that extends BroadcastReceiver to receive and display SMS messagesin a toast within the app. I have also added permissions too my manifest along with the declaration of the receiver. The problem is it still does not seem to display the message. It will only appear on the top bar as a notification. Hopefully someone will be able to see where i am going wrong. Do i have to have some code in my mainactivity in order to display the message?? or should it display in my all my activities straight from the receiver clas?? code below:
UPDATE
I ended up deleting my receiver and recreating everything, now it seems to work fine
SmsReceiver.java:
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras ==null)
return;
//toast
Toast.makeText(context, "Received", Toast.LENGTH_LONG).show();
Object[] pdus = (Object[]) extras.get("pdus");
for (int i = 0; i < pdus.length; i++) {
SmsMessage SMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = SMessage.getOriginatingAddress();
String body = SMessage.getMessageBody().toString();
Intent in = new Intent("SmsMessage.intent.MAIN").putExtra("get_msg", sender+":"+body);
context.sendBroadcast(in);
this.abortBroadcast();
}
}
}
The problem is it still does not seem to display the message. It will only appear on the top bar as a notification
do you know what is - Ordered Broadcast?
in case you don't know - it's a broadcast that receives synchronously (one after another) by all receivers that registered for this broadcast. you can set in the manifest receiver deceleration a priority , and each one of the receivers can control if the broadcast will pass on in the priorities chain to additional registered receivers by using the aboartBroadcast() method.
what's to this and receiving SMS? - the system sends ordered broadcast when SMS receives. if your receivers priority is lower then the "default SMS app" priority - then what usually happens is that the application that got the broadcast first will cancel the broadcast, and you'll never receives it.
to get the broadcast before the default SMS application you have to declare your receiver with high priority (providing priority = 1000 should do the trick).
without providing priority - it's automatically set to zero.
you can have a look on this example - How Can i INTERCEPT an Incoming SMS With A specific Text
also make sure you declared the permission to RECEIVE_SMS in the manifest
Try starting again and setting up your receiver like so....
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras ==null)
return;
//toast
Toast.makeText(context, "Received", Toast.LENGTH_LONG).show();
Object[] pdus = (Object[]) extras.get("pdus");
for (int i = 0; i < pdus.length; i++) {
SmsMessage SMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = SMessage.getOriginatingAddress();
String body = SMessage.getMessageBody().toString();
Intent in = new Intent("SmsMessage.intent.MAIN").putExtra("get_msg", sender+":"+body);
context.sendBroadcast(in);
this.abortBroadcast();
}
}
}
#Override
public void onReceive(Context context, Intent arg1) {
SmsMessage msgs[] = getMessagesFromIntent(arg1);
for (int i = 0; i < msgs.length; i++) {
SmsMessage mesg = msgs[i];
Toast toast = Toast.makeText(context, mesg.getDisplayMessageBody(), Toast.LENGTH_LONG);
toast.show();
}
}
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
// retrieve the SMS message received ::
Object[] pdus = (Object[]) extras.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();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
// Toast to display SMS ::
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
// Send SMS ::
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage("put your phoneNumber(emulatorPort)", null, str, null, null);
}
}
}
--
Have nice time !
Don't forget to add permissions !
I am implementing CreateNdefMessageCallback and OnNdefPushCompleteCallback. For some reason the callback methods are NEVER touched, no errors on the log either.
I do hear the sound from the API though, the phone that I am debugging on is a Nexus S running version 4.0.4.
Here is my activity:
public class TestActivity extends Activity implements CreateNdefMessageCallback, OnNdefPushCompleteCallback
{
private static SoundHelper soundHelper;
private PowerManager.WakeLock wakeLock;
private NfcAdapter nfcAdapter;
private PendingIntent pendingIntent = null;
private IntentFilter[] intentFiltersArray;
private String[][] techListsArray;
private TextView onScreenLog;
private List<String> uniqueTagsRead = new ArrayList<String>();
/** handler stuff */
private static final int MESSAGE_SENT = 1;
private final Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case MESSAGE_SENT:
if (soundHelper != null)
{
soundHelper.playSound(R.raw.smw_coin);
}
updateTagCount();
break;
}
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
soundHelper = new SoundHelper(this);
onScreenLog = (TextView) findViewById(R.id.log);
// nfc adapter
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter != null)
{
// callbacks
nfcAdapter.setNdefPushMessageCallback(this, this);
nfcAdapter.setOnNdefPushCompleteCallback(this, this);
// other stuff
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try
{
ndef.addDataType("*/*");
}
catch (MalformedMimeTypeException e)
{
throw new RuntimeException("fail", e);
}
intentFiltersArray = new IntentFilter[] {ndef, };
techListsArray = new String[][] {
new String[] { IsoDep.class.getName() },
new String[] { NfcA.class.getName() },
new String[] { NfcB.class.getName() },
new String[] { NfcF.class.getName() },
new String[] { NfcV.class.getName() },
new String[] { Ndef.class.getName() },
new String[] { NdefFormatable.class.getName() },
new String[] { MifareClassic.class.getName() },
new String[] { MifareUltralight.class.getName() },
};
}
else
{
onScreenLog.setText("NFC is not available on this device. :(");
}
}
public void onPause()
{
super.onPause();
// end wake lock
wakeLock.release();
nfcAdapter.disableForegroundDispatch(this);
}
public void onResume()
{
super.onResume();
// start wake lock
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "DoNotDimScreen");
wakeLock.acquire();
nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
}
private void updateTagCount()
{
String newCount = String.valueOf(uniqueTagsRead.size());
String text = getString(R.string.format_count);
text = getString(R.string.format_count).replace("0", newCount);
onScreenLog.setText(text);
}
#Override
public NdefMessage createNdefMessage(NfcEvent event)
{
String message = "This is NFC message";
NdefRecord mimeRecord = createMimeRecord("application/param.android.sample.beam",
message.getBytes());
NdefRecord appRecord = NdefRecord.createApplicationRecord("param.android.sample.beam");
NdefRecord[] ndefRecords = new NdefRecord[] {
mimeRecord,
appRecord
};
NdefMessage ndefMessage = new NdefMessage(ndefRecords);
return ndefMessage;
/*
String mimeType = "text/plain"; // "text/plain";
NdefRecord[] data = {createMimeRecord(mimeType, TEXT_TO_WRITE.getBytes())};
// data[data.length - 1] = NdefRecord.createApplicationRecord(); // com.test.nfc.application.activities.
return new NdefMessage(data);
*/
}
/**
* Creates a custom MIME type encapsulated in an NDEF record
*
* #param mimeType
*/
public NdefRecord createMimeRecord(String mimeType, byte[] payload)
{
byte[] mimeBytes = mimeType.getBytes(Charset.forName("US-ASCII"));
NdefRecord mimeRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, mimeBytes, new byte[0], payload);
return mimeRecord;
}
#Override
public void onNdefPushComplete(NfcEvent event)
{
handler.obtainMessage(MESSAGE_SENT).sendToTarget();
}
}
manifest:
<uses-sdk android:minSdkVersion="14" />
<supports-screens android:anyDensity="true" />
<uses-permission android:name="android.permission.NFC"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-feature android:name="android.hardware.nfc" />
<application android:name="com.test.nfc.application.Application"
android:icon="#drawable/icon_launcher_nfc_droid_hdpi"
android:theme="#android:style/Theme.Light"
android:label="#string/app_name">
<activity
android:label="#string/app_name"
android:name=".application.activities.MainActivity"
android:configChanges="orientation|keyboardHidden">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:label="#string/test"
android:name=".application.activities.TestActivity"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="#xml/nfc_tech_list" />
</activity>
</application>
</manifest>
techlist
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.NfcF</tech>
<tech>android.nfc.tech.NfcV</tech>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.NdefFormatable</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>
From your question and example code it is not entirely clear to me whether you want to receive NDEF messages, send them or both.
When using NfcAdapter.enableForegroundDispatch(), your Activity will be notified about new NFC intents by a call to onNewIntent(), so you should override that method in your Activity to receive the intents.
NfcAdapter.CreateNdefMessageCallback and NfcAdapter.OnNdefPushCompleteCallback are used to send NDEF data via Android Beam to another NFC device. The user needs to tap the screen to activate sending the NDEF message, which will cause calls to createNdefMessage() and onNdefPushComplete().
One more remark: if you pass null for the filters and techLists parameters to NfcAdapter.enableForegroundDispatch() that will act as a wild card (so you don't need to declare a complete list of technologies, as you are doing now).
It looks like you are getting the default NFC adapter twice?
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
You do it once before your check for null on nfcAdapter, then in your if statement you do it again. This might have some weird effects. I'm not sure though. Also it looks like you are declaring intent filters at runtime. Do this in the manifest to debug if you still have problems. It's just easier to be certain something is filtering intents correctly that way.
See this sample code and the Android Beam sample in the SDK for more examples:
http://developer.android.com/guide/topics/nfc/nfc.html#p2p