We want to intercept the outgoing call hangup state in a broadcast receiver. We are listening to android.intent.action.PHONE_STATE and do get notified on IDLE state, that is when the call finishes.
Unfortunately, we do not get the called number from the call log content provider. It always returns the last call. Interestingly the incoming call do send a number in the intent but nothing for outgoing call.
If we use android.intent.action.NEW_OUTGOING_CALL, the phone number is coming through the intent when the call starts, but this stage is too early for us to do any processing as we want to wait for the call to complete.
public class InterceptOutgoingCall extends BroadcastReceiver {
Boolean isOutGoingCall = true;
private static final String LOG_TAG = "InterceptOutgoingCall";
#Override
public void onReceive(Context context, Intent intent) {
//1. Logging the intent params
String state = null;
StringBuffer buf = new StringBuffer();
if (intent.getAction() != null)
buf.append("Intent action: " + intent.getAction());
if (intent.getCategories() != null) {
Set<String> categories = intent.getCategories();
if (categories != null) {
Iterator<String> it = categories.iterator();
buf.append("; categories: ");
int ctr = 0;
for (; it.hasNext();) {
String category = (String) it.next();
if (ctr != 0)
buf.append("/");
buf.append(category);
++ctr;
}
}
}
if (intent.getData() != null) {
buf.append("; intent data: " + intent.getData().toString());
}
Bundle extras = intent.getExtras();
if (extras != null) {
buf.append("; extras: ");
int ctr = 0;
Set keys = extras.keySet();
for (Iterator it = keys.iterator(); it.hasNext();) {
String key = (String) it.next();
Object value = extras.get(key);
if (ctr != 0)
buf.append("/");
String strvalue = value == null ? "null" : value.toString();
if (key.equals("state"))
state = strvalue;
buf.append(key + "=" + strvalue);
++ctr;
}
Log.i(LOG_TAG, buf.toString());
if ("IDLE".equals(state)) {
Log.i(LOG_TAG, "Number of the other party: "
+ getLastCallLogEntry(context));
}
}
String outgoingCall = CallLog.Calls.getLastOutgoingCall(context);
Log.i(LOG_TAG, "Last call:" + outgoingCall);
}
private String getLastCallLogEntry(Context context) {
String[] projection = new String[] { BaseColumns._ID,
CallLog.Calls.NUMBER, CallLog.Calls.TYPE };
ContentResolver resolver = context.getContentResolver();
Cursor cur = resolver.query(CallLog.Calls.CONTENT_URI, projection,
null, null, CallLog.Calls.DEFAULT_SORT_ORDER);
int numberColumn = cur.getColumnIndex(CallLog.Calls.NUMBER);
int typeColumn = cur.getColumnIndex(CallLog.Calls.TYPE);
if (!cur.moveToNext()) {
cur.close();
return "";
}
String number = cur.getString(numberColumn);
String type = cur.getString(typeColumn);
String dir = null;
try {
int dircode = Integer.parseInt(type);
switch (dircode) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
} catch (NumberFormatException ex) {
}
if (dir == null)
dir = "Unknown, code: " + type;
cur.close();
return dir + "," + number;
}
Log cat
*When call starts, NEW_OUTGOING_CALL is broadcast*
04-27 13:07:16.756: INFO/InterceptOutgoingCall(775): Intent action: android.intent.action.NEW_OUTGOING_CALL; extras: android.phone.extra.ALREADY_CALLED=false/android.intent.extra.PHONE_NUMBER=999222/android.phone.extra.ORIGINAL_URI=tel:999-222
Result data
04-27 13:07:16.876: INFO/InterceptOutgoingCall(775): Result Data:999222
Call Logs last call
04-27 13:07:17.156: INFO/InterceptOutgoingCall(775): Last call:809090
*Next, PHONE_STATE is broadcast, No number in extras*
04-27 13:07:19.495: INFO/InterceptOutgoingCall(775): Intent action: android.intent.action.PHONE_STATE; extras: state=OFFHOOK
No Result Data
04-27 13:07:19.636: INFO/InterceptOutgoingCall(775): No result data
When call is complete, No number in extras
04-27 13:08:09.306: INFO/InterceptOutgoingCall(775): Intent action: android.intent.action.PHONE_STATE; extras: state=IDLE
Call log last entry is the previously called number
04-27 13:08:09.627: INFO/InterceptOutgoingCall(775): Number of the other party: OUTGOING,809090
04-27 13:08:09.675: INFO/InterceptOutgoingCall(775): No result data
04-27 13:08:10.336: INFO/InterceptOutgoingCall(775): Last call:809090
Use a broadcast listener with an intent android.intent.action.NEW_OUTGOING_CALL string parametrer for the IntentFilter and don't forget to give permission in AndroidMenifest to PROCESS_OUTGOING_CALLS. This will work.
public static final String outgoing = "android.intent.action.NEW_OUTGOING_CALL" ;
IntentFilter intentFilter = new IntentFilter(outgoing);
BroadcastReceiver OutGoingCallReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
// TODO Auto-generated method stub
String outgoingno = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Toast.makeText(context, "outgoingnum =" + outgoingno,Toast.LENGTH_LONG).show();
}
};
registerReceiver(brForOutgoingCall, intentFilter);
You can the outgoing call number like below:
String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
I think you can store the number using public static variable and then refer it.
Related
Hey guys im testing NFC and i have an issue with i think it is formating..
I added a string value in the tag with an app to write.
when i scan it with that same store app it shows ok...
when i scan with my app it shows the correct name in the app but adds a "en" before the message..
and a white space.. so if i add a name in the tag then scan and get a API it shows 404 cause there is an en and white space..
http://myapisite.com/API/getdevice.php?id= enTagString
before the = space and then en before the id or even name i put..
i tried a few ways..
public class MainActivity extends Activity {
// list of NFC technologies detected:
private final String[][] techList = new String[][]{
new String[]{
NfcA.class.getName (),
NfcB.class.getName (),
NfcF.class.getName (),
NfcV.class.getName (),
IsoDep.class.getName (),
MifareClassic.class.getName (),
MifareUltralight.class.getName (), Ndef.class.getName ()
}
};
private TextView mTextView;
private ImageView mImageView;
private String ID, machineName, MachineImg, MachinePart, level;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_main);
mImageView = findViewById (R.id.imageView);
mTextView = findViewById (R.id.textView_explanation);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater ().inflate (R.menu.menu, menu);
return true;
}
#Override
protected void onResume() {
super.onResume ();
PendingIntent pendingIntent = PendingIntent.getActivity (this, 0, new Intent (this, getClass ()).addFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
// creating intent receiver for NFC events:
IntentFilter filter = new IntentFilter ();
filter.addAction (NfcAdapter.ACTION_TAG_DISCOVERED);
filter.addAction (NfcAdapter.ACTION_NDEF_DISCOVERED);
filter.addAction (NfcAdapter.ACTION_TECH_DISCOVERED);
// enabling foreground dispatch for getting intent from NFC event:
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter (this);
nfcAdapter.enableForegroundDispatch (this, pendingIntent, new IntentFilter[]{filter}, this.techList);
}
#Override
protected void onPause() {
super.onPause ();
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter (this);
nfcAdapter.disableForegroundDispatch (this);
}
void parseNdefMessage(Intent intent) {
Parcelable[] ndefMessageArray = intent.getParcelableArrayExtra (
NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage ndefMessage = (NdefMessage) ndefMessageArray[0];
String text = new String (ndefMessage.getRecords ()[0].getPayload ());
Log.d (TAG, "PAYLOAD MESS" + text);
ID = text;
getApiInfos ();
}
#Override
protected void onNewIntent(Intent intent) {
parseNdefMessage (intent);
if (intent.getAction ().equals (NfcAdapter.ACTION_TAG_DISCOVERED)) {
mTextView.setText ("NFC Tag\n" + ByteArrayToHexString (intent.getByteArrayExtra (NfcAdapter.EXTRA_ID)));
Parcelable tagN = intent.getParcelableExtra (NfcAdapter.EXTRA_TAG);
if (tagN != null) {
NdefMessage[] msgs;
byte[] empty = new byte[0];
byte[] id = intent.getByteArrayExtra (NfcAdapter.EXTRA_ID);
byte[] payload = dumpTagData (tagN).getBytes ();
NdefRecord record = new NdefRecord (NdefRecord.TNF_UNKNOWN, empty, id, payload);
NdefMessage msg = new NdefMessage (new NdefRecord[]{record});
msgs = new NdefMessage[]{msg};
Log.d (TAG, msgs[0].toString ());
} else {
Log.d (TAG, "Parcelable NULL");
}
Parcelable[] messages1 = intent.getParcelableArrayExtra (NfcAdapter.EXTRA_NDEF_MESSAGES);
if (messages1 != null) {
Log.d (TAG, "Found " + messages1.length + " NDEF messages");
for (int i = 0; i < messages1.length; ++i) {
Log.d (TAG, "Found M " + messages1[i].toString ());
}
} else {
Log.d (TAG, "Not EXTRA_NDEF_MESSAGES");
}
Tag tag = intent.getParcelableExtra (NfcAdapter.EXTRA_TAG);
Ndef ndef = Ndef.get (tag);
if (ndef != null) {
Parcelable[] messages = intent.getParcelableArrayExtra (NfcAdapter.EXTRA_NDEF_MESSAGES);
if (messages != null) {
Log.d (TAG, "Found " + messages.length + " NDEF messages");
}
} else {
Log.d (TAG, "Write to an unformatted tag not implemented");
}
}
}
private String dumpTagData(Parcelable p) {
StringBuilder sb = new StringBuilder ();
Tag tag = (Tag) p;
byte[] id = tag.getId ();
sb.append ("Tag ID (hex): ").append (getHex (id)).append ("\n");
sb.append ("Tag ID (dec): ").append (getDec (id)).append ("\n");
sb.append ("ID (reversed): ").append (getReversed (id)).append ("\n");
String prefix = "android.nfc.tech.";
sb.append ("Technologies: ");
for (String tech : tag.getTechList ()) {
sb.append (tech.substring (prefix.length ()));
sb.append (", ");
}
sb.delete (sb.length () - 2, sb.length ());
for (String tech : tag.getTechList ()) {
if (tech.equals (MifareClassic.class.getName ())) {
sb.append ('\n');
MifareClassic mifareTag = MifareClassic.get (tag);
String type = "Unknown";
switch (mifareTag.getType ()) {
case MifareClassic.TYPE_CLASSIC:
type = "Classic";
break;
case MifareClassic.TYPE_PLUS:
type = "Plus";
break;
case MifareClassic.TYPE_PRO:
type = "Pro";
break;
}
sb.append ("Mifare Classic type: ");
sb.append (type);
sb.append ('\n');
sb.append ("Mifare size: ");
sb.append (mifareTag.getSize () + " bytes");
sb.append ('\n');
sb.append ("Mifare sectors: ");
sb.append (mifareTag.getSectorCount ());
sb.append ('\n');
sb.append ("Mifare blocks: ");
sb.append (mifareTag.getBlockCount ());
}
if (tech.equals (MifareUltralight.class.getName ())) {
sb.append ('\n');
MifareUltralight mifareUlTag = MifareUltralight.get (tag);
String type = "Unknown";
switch (mifareUlTag.getType ()) {
case MifareUltralight.TYPE_ULTRALIGHT:
type = "Ultralight";
break;
case MifareUltralight.TYPE_ULTRALIGHT_C:
type = "Ultralight C";
break;
}
sb.append ("Mifare Ultralight type: ");
sb.append (type);
}
}
DateFormat TIME_FORMAT = SimpleDateFormat.getDateTimeInstance ();
Date now = new Date ();
mTextView.setText (TIME_FORMAT.format (now) + '\n' + sb.toString ());
return sb.toString ();
}
private String getHex(byte[] bytes) {
StringBuilder sb = new StringBuilder ();
for (int i = bytes.length - 1; i >= 0; --i) {
int b = bytes[i] & 0xff;
if (b < 0x10)
sb.append ('0');
sb.append (Integer.toHexString (b));
if (i > 0) {
sb.append (" ");
}
}
return sb.toString ();
}
private long getDec(byte[] bytes) {
long result = 0;
long factor = 1;
for (int i = 0; i < bytes.length; ++i) {
long value = bytes[i] & 0xffl;
result += value * factor;
factor *= 256l;
}
return result;
}
private long getReversed(byte[] bytes) {
long result = 0;
long factor = 1;
for (int i = bytes.length - 1; i >= 0; --i) {
long value = bytes[i] & 0xffl;
result += value * factor;
factor *= 256l;
}
return result;
}
private String ByteArrayToHexString(byte[] inarray) {
int i, j, in;
String[] hex = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
String out = "";
for (j = 0; j < inarray.length; ++j) {
in = (int) inarray[j] & 0xff;
i = (in >> 4) & 0x0f;
out += hex[i];
i = in & 0x0f;
out += hex[i];
}
Log.d ("ByteArrayToHexString", String.format ("%0" + (inarray.length * 2) + "X", new BigInteger (1, inarray)));
return out;
}
enter code here
Most likely this is because the App writing is storing it as a "WELL_KNOWN" type of text/plain
The specs for NFC Text format can be found at NFCForum-TS-RTD_Text_1.0.pdf.
The extra characters in the payload are as below:
language length (1 byte) + language (n bytes) + Text
So the space is the actually a non printable size of the language.
The "en" is defining that the text is English.
https://developer.android.com/reference/android/nfc/NdefRecord#getPayload()
returns a byte array.
So below should work to trim it (tested) as there don't seem to be nice helper methods to decode it, only create this format.
// Create Test Record
NdefRecord record = NdefRecord.createTextRecord("en", "Hello");
//Get Bytes of payload
// byte[] payload = ndefMessage.getRecords ()[0].getPayload ();
// Get Bytes of test NDEF Record
byte[] payload = record.getPayload ();
// Read First Byte and then trim off the right length
byte[] textArray = Arrays.copyOfRange(payload, (int) payload[0] + 1 , payload.length);
// Convert to Text
String text = new String(textArray);
UPDATE:
As the code given in the question is a bit of a mess and you do things you don't need to do and don't do things you do need to do (e.g. you have asked to be sent data from cards that won't have NDef data in them and then you parse for Ndef data without checking there is some data to parse)
I've simplified the code just to read a text NDEF record (Note not tested, but based on how I used to read NDEF data, I now use a better method to read cards that is more reliable especially if you want to write to cards as well)
public class MainActivity extends Activity {
private TextView mTextView;
private ImageView mImageView;
private String ID, machineName, MachineImg, MachinePart, level;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = findViewById(R.id.imageView);
mTextView = findViewById(R.id.textView_explanation);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
#Override
protected void onResume() {
super.onResume();
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
// creating intent receiver for NFC events:
IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
// enabling foreground dispatch for getting intent from NFC event:
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
nfcAdapter.enableForegroundDispatch(this, pendingIntent, new IntentFilter[]{filter}, null);
}
#Override
protected void onPause() {
super.onPause();
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
nfcAdapter.disableForegroundDispatch(this);
}
void parseNdefMessage(Intent intent) {
Parcelable[] ndefMessageArray = intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES);
// Test if there is actually a NDef message passed via the Intent
if (ndefMessageArray != null) {
NdefMessage ndefMessage = (NdefMessage) ndefMessageArray[0];
//Get Bytes of payload
byte[] payload = ndefMessage.getRecords()[0].getPayload();
// Read First Byte and then trim off the right length
byte[] textArray = Arrays.copyOfRange(payload, (int) payload[0] + 1, payload.length);
// Convert to Text
String text = new String(textArray);
ID = text;
getApiInfos();
}
}
#Override
protected void onNewIntent(Intent intent) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
parseNdefMessage(intent);
}
}
}
Ok thx to #Andrew i used part of your code and adapted it to my tests.. it works great now i can clean it up and removed what is not used or needed.Thx happy holidays!:)
void parseNdefMessage(Intent intent) {
Parcelable[] ndefMessageArray = intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES);
// Test if there is actually a NDef message passed via the Intent
if (ndefMessageArray != null) {
NdefMessage ndefMessage = (NdefMessage) ndefMessageArray[0];
//Get Bytes of payload
byte[] payload = ndefMessage.getRecords()[0].getPayload();
// Read First Byte and then trim off the right length
byte[] textArray = Arrays.copyOfRange(payload, (int) payload[0] + 1, payload.length);
// Convert to Text
String text = new String(textArray);
ID = text;
getApiInfos();
}
}
If anyone is facing the same issue in React Native, here's my solution. Here, the react-native-nfc-manager package is used
// register for the NFC tag with NDEF in it
await NfcManager.requestTechnology(NfcTech.Ndef);
// the resolved tag object will contain `ndefMessage` property
const tag = await NfcManager.getTag();
// access the payload
const payload = tag?.ndefMessage[0].payload;
//remove the language code from payload
const subPayload = payload?.slice(3, payload.length);
const decoded = Ndef.util.bytesToString(subPayload);
How do i can read data from received mms.
I receive an mms but I can't take any data from it to save it
public class MmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String type = intent.getType();
Utils.PrintInfo("Action : "+action+", Type : "+type);
Bundle bundle = intent.getExtras();
Utils.PrintDebug("bundle " + bundle);
if (bundle != null) {
for(String k:bundle.keySet()) {
Utils.PrintInfo(k);
}
byte[] buffer = bundle.getByteArray("data");
Utils.PrintDebug("buffer " + buffer);
String incomingNumber = new String(buffer);
int indx = incomingNumber.indexOf("/TYPE");
if (indx > 0 && (indx - 15) > 0) {
int newIndx = indx - 15;
incomingNumber = incomingNumber.substring(newIndx, indx);
indx = incomingNumber.indexOf("+");
if (indx > 0) {
incomingNumber = incomingNumber.substring(indx);
Utils.PrintDebug("Mobile Number: " + incomingNumber);
}
}
int transactionId = bundle.getInt("transactionId");
Utils.PrintDebug("transactionId " + transactionId);
int pduType = bundle.getInt("pduType");
Utils.PrintDebug("pduType " + pduType);
byte[] buffer2 = bundle.getByteArray("header");
String header = new String(buffer2);
Utils.PrintDebug("header " + header);
}
}
}
data from that mms looks like
data : ???1351504361#mms2??????+48668822862/TYPE=PLMN???????????????http://mmsc.play.pl/?id=1351504361B??
how can I get any image from it? - i have send image from other device to that one
I am receiving SMS.I want ListView to be updated as soon as SMS is received or when Activity is in the foreground.I have done this successfully as I have registered and unregistered receiver in OnResume and OnPause respectively as shown in the Code.:
BroadcastReceiver IncomingSMS = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
try {
final Bundle bundle = intent.getExtras();
if (bundle != null) {
//—retrieve the SMS message received—
Object messages[] = (Object[]) bundle.get("pdus");
SmsMessage smsMessage[] = new SmsMessage[messages.length];
for (int n = 0; n < messages.length; n++) {
smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
timestamp = smsMessage[n].getTimestampMillis();
number = smsMessage[n].getOriginatingAddress();
body += smsMessage[n].getDisplayMessageBody();
display_name = Util.getContactName(context, number);
DBmanager = new DbManager(context);
cursor = DBmanager.Return_All_Contacts();
String [] contactArr = showcontactsInfo(cursor);
Toast.makeText(context, contactArr[0]+"", 3000).show();
if(contactArr.length==0)
{}
else{
for(int i= 0;i<=contactArr.length;i++)
{
abortBroadcast();
}
blockMessage(context);
}
}
}
}
catch (Exception e) {
Log.e("SmsReceiver", "Exception smsReceiver" +e);
}
}};
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(IncomingSMS);
}
#Override
protected void onResume() {
//registerReceiver(IncomingSMS, null);
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(IncomingSMS, filter);
updateList();
}
I have also registered Receiver in the Manifest file to receive SMS when Activity is in the background.If Activity is in the background and I switch to that Activity then ListView is updated normally but if Activity is in the foreground then ListView has updated data twice. Its most probably that when Activity is in foreground two Receivers are triggered i.e the one in the foreground and second that in the manifest. How can I handle it ???? I want foreground Activity to update to receive SMS only once.
This is how I have registered Receiver in manifest and utilized in java class :
public class IncomingSMS extends BroadcastReceiver {
Context context;
DbManager DBmanager;
private long timestamp;
private String number;
static String body = "";
String msg="";
Cursor cursor;
String display_name;
String flag;
ChatActivity obj_chat;
#Override
public void onReceive(Context context, Intent intent) {
try {
final Bundle bundle = intent.getExtras();
if (bundle != null) {
//—retrieve the SMS message received—
Object messages[] = (Object[]) bundle.get("pdus");
SmsMessage smsMessage[] = new SmsMessage[messages.length];
for (int n = 0; n < messages.length; n++) {
smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
timestamp = smsMessage[n].getTimestampMillis();
number = smsMessage[n].getOriginatingAddress();
body += smsMessage[n].getDisplayMessageBody();
display_name = Util.getContactName(context, number);
DBmanager = new DbManager(context);
cursor = DBmanager.Return_All_Contacts();
String [] contactArr = showcontactsInfo(cursor);
Toast.makeText(context, contactArr[0]+"", 3000).show();
if(contactArr.length==0)
{}
else{
for(int i= 0;i<=contactArr.length;i++)
{
abortBroadcast();
}
blockMessage(context);
}
}
}
}
catch (Exception e) {
Log.e("SmsReceiver", "Exception smsReceiver" +e);
}
} // end for loop
// bundle is null
private String[] showcontactsInfo(Cursor cursor) {
String[] contact = new String [cursor.getCount()];
int i= 0;
while(cursor.moveToNext()){
contact[i] = cursor.getString(1);
i++;
}
return contact;
}
private void blockMessage(Context context) {
// instantiate DbMNager object to insert sms in database
//formating receiving time:
//SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-hh.mm.ss");
SimpleDateFormat formatter = new SimpleDateFormat("EEEE, MMMM d HH:mm:ss a");
String formatedTime = formatter.format(timestamp);
flag = "0";
DBmanager= new DbManager(context);
DBmanager.open();
DBmanager.Insert_sms_data(formatedTime ,display_name,body,flag);
DBmanager.close();
obj_chat = new ChatActivity();
obj_chat.updateList();
msg+= "SMS from " + number + " \n";
msg += body + " \n";
msg += formatedTime + " \n";
msg += flag + " \n";
Log.i("SmsReceiver", "senderNum: "+ display_name + "; message: " + body);
Toast.makeText(context,msg, Toast.LENGTH_LONG).show();
//Toast.makeText(context, "New message received in Discrete", Toast.LENGTH_LONG).show();
}
}
I have near about six Activities and a service class with BroadcastReceiver that run in background for receiving SMS. I receive SMS on OnReceive Method of BroadcastReceiver now I would like to store incomming sms data in database for that I have made a SMSSync Class for smsProcess which pass data to dbase now I call this smsProcess on OnReceive method this work fine but I think when more sms received at same time the I got found problem I think it was due to database. Sir please tell me what is best method to store sms data after receiving it On receive and then show in activities. Sory for my bad English or if not understand. Thanks in advance sir pl revert back answer I will wait for..I tag code for On Receive method
thanks
Om Parkash Kaushik
public SMSReceiver(Context ctx){
this.context = ctx;
sync = new SMSSync(context);
dba = new DataBaseAdapter(ctx);
}
#Override
public void onReceive(Context context,final Intent intents){
if (intents.getAction().equals(ConstantClass.SMS_RECEIVED)) {
try{
Bundle bundle = intents.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++)
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
String msg=null;
String temp = null;
for (SmsMessage message : messages) {
msg = message.getMessageBody();
temp = message.getOriginatingAddress();
}
if(msg.length()>5 && msg.startsWith("<") && msg.contains(">")){
String len = msg.substring(1, 3);
int tl = temp.length();
int l = tl - no;
address = temp.substring(l,tl);
int value =Integer.valueOf(len, 16).intValue();
int index = msg.indexOf(">");
if(value == index+1){
dba.Open();
int id = dba.getCordiId(address);
Cursor cur = dba.getCoord(id);
if(cur!=null)
cur.moveToFirst();
final String Phnumber = cur.getString(cur.getColumnIndex(DataBaseAdapter.Key_MbNo));
if(Phnumber.equals(address)){
int count = dba.getDeviceCount(ConstantClass.dbName[1]);
if(count<=0){
dba.InsertCurrentCoord(id,id);
}else{
Strsql = new String("UPDATE " + ConstantClass.dbName[1] + " SET " + DataBaseAdapter.Key_ReceiverCoord + " = " +
Integer.toString(id) + " WHERE " + DataBaseAdapter.Key_ID + " = ?");
dba.UpdateQuery(Strsql, Integer.toString(1));
}
dba.Close();
sync.smsProcess(msg);
abortBroadcast();
/************Now deleting the SMS from the Inbox*********************/
removeMessage(SMSReceiver.this.context, Phnumber);
if(msg.substring(3, 4).equals("2"))
ConstantClass.isAuditrequestSend = false;
/*******after receiving the sms opening the Main Screen.*****************/
if(ConstantClass.Clear_Main_Screen==true){
Intent intent = new Intent(context,ZigbeeActivity.class);
context.startActivity(intent);
}
}else{
Toast.makeText(SMSReceiver.this.context, address, Toast.LENGTH_LONG).show();
}
}else{
Toast.makeText(SMSReceiver.this.context, "message Corrupt" + address, Toast.LENGTH_LONG).show();
}
}
}
}catch(Exception e){
dlg = new ExceptionDialog(SMSReceiver.this.context,"On Sms Receiver" + address ,e.getMessage());
dlg.show();
}
}
}
I have done the same application related to yours. But instead of saving all received sms i want to save only bank transaction related sms. I hope the following code will helps you..
ReceiveSms.java
if(smsg.contains("credit") /***********/ || msg.contains("amount"))
{
Toast.makeText(context, "message related to transcation", Toast.LENGTH_SHORT).show();
dbh.smsservice(smsg);
}
DbHandler.java
public void smsservice(String sms)
{
// TODO Auto-generated method stub
String smessg="INSERT INTO SMSDETAILS(SMSMESS) VALUES('"+sms+"') ";
sdb.execSQL(smessg);
System.out.println("values of sms inserted"+smessg);
}
Actually I have written a method for updatiing server database using webservice from my application installed in the device using two IP Address.If one IP failed then it usess the second IP for upadting the data at server.
If Both the IP address failed i am saving the data to one of my sqllite database table tblTransaction.The code for that is given below.
private void Delay15Minute() throws IOException {
String server1IPAddress = "";
String server2IPAddress = "";
String deviceId = "";
Cursor cursorAdmin;
Cursor cursorTransaction;
adminhelper = new admin_helper(this);
cursorAdmin = adminhelper.GetAdminDetails();
if (cursorAdmin.moveToFirst())
server1IPAddress = cursorAdmin.getString(cursorAdmin
.getColumnIndex("RemoteServer1IPAddress"));
server2IPAddress = cursorAdmin.getString(cursorAdmin
.getColumnIndex("RemoteServer2IPAddress"));
deviceId = cursorAdmin.getString(cursorAdmin
.getColumnIndex("DeviceID"));
cursorAdmin.close();
ContentValues initialDelay15 = new ContentValues();
ContentValues initialTransaction = new ContentValues();
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
String RevisedEstimatedDate = sdf.format(date);
manifest_helper = new manifest_helper(this);
cursor = manifest_helper.GetDeliveries(pkManifest);
cursor.moveToFirst();
dbAdapter = new DatabaseAdapter(this);
dbAdapter.open();
for (int i = 0; i < cursor.getCount(); i++) {
cursor.getString(cursor.getColumnIndex("PKDelivery"));
String RevisedTime=cursor.getString(cursor.getColumnIndex("RevisedEstimatedDeliveryTime"));
// get hour and minute from time string
StringTokenizer st1 = new StringTokenizer(RevisedTime, ":");
int j = 0;
int[] val = new int[st1.countTokens()];
// iterate through tokens
while (st1.hasMoreTokens()) {
val[j] = Integer.parseInt(st1.nextToken());
j++;
}
// call time add method with current hour, minute and minutesToAdd,
// return added time as a string
String dateRevisedEstimatedDeliveryTime = addTime(val[0], val[1], 15);
initialDelay15.put("RevisedEstimatedDeliveryTime",
dateRevisedEstimatedDeliveryTime);
dbAdapter.UpdateRecord("tblDelivery", initialDelay15, "PKDelivery"
+ "=" + cursor.getString(cursor.getColumnIndex("PKDelivery")), null);
}
dbAdapter.close();
dataXmlExporter=new DataXmlExporter(this);
dataXmlExporter.StartDataSet();
cursor = manifest_helper.GetDeliveries(pkManifest);
dataXmlExporter.AddRowandColumns(cursor,"tblDelivery");
String sqlTransaction = "Select 6 as TransactionType,'Update Revised Estimated Delivery Time' as Description,"
+ " deviceId as DeviceID ,date() as TransactionUploadDate,time() as TransactionUploadTime from tblAdmin where PKAdmin > ?";
dbAdapter = new DatabaseAdapter(this);
dbAdapter.open();
cursorTransaction = dbAdapter.ExecuteRawQuery(sqlTransaction, "-1");
dataXmlExporter.AddRowandColumns(cursorTransaction, "Transaction");
String XMLTransactionData=dataXmlExporter.EndDataSet();
try {
if ((server1IPAddress != "") && (server2IPAddress != "")) {
try {
if (server1IPAddress != "") {
InsertUploadedTrancasctionDetails(server1IPAddress,
deviceId, XMLTransactionData);
}
} catch (Exception exception) {
if ((server1IPAddress != server2IPAddress)
&& (server2IPAddress != "")) {
InsertUploadedTrancasctionDetails(server2IPAddress,
deviceId, XMLTransactionData);
}
}
}
} catch (Exception exception) {
initialTransaction.put("ReceivedDate",
RevisedEstimatedDate);
initialTransaction.put("TransactionData",
XMLTransactionData);
dbAdapter.InsertRecord("tblTransaction", "",
initialTransaction);
}
dbAdapter.close();
LoadDeliveries(pkManifest);
}
The Problem is that i need to update the data to the server that stored in the tbltransaction automatically when we get connection to the serverIP along with my running application.I think it is possible by means of establishing backround running process along with my application that will check whethere data is there in the tbltransaction and connection with server is there.
So will any one have an idea for this ...if so please help meee...........
Here are a couple of methods that together will do just this. This is all within a Service, you could use a Handler instead and do this within an activity, but a Service is a wiser choice.
First, we need to be able to tell if we're online, this requires Network State and Wifi State Permissions:
public boolean isOnline() {
try {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo().isConnectedOrConnecting();
} catch (Exception e) {
return false;
}
}
Next we need to be able to set an alarm to retry. Add these variables:
private static AlarmManager am;
private static PendingIntent pIntent;
public static final int MSG_UPDATE = 0;
public static final String PENDING_REQ_KEY = "request";
And a set alarm method:
private synchronized void setAlarm() {
if (am == null) am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
if (Constants.LOG_DEBUG) Log.d(TAG,"Setting Alarm for 5 mins");
long delay = 300000L; //5 Mins
Intent i = new Intent(this,Service.class); //Reference the Service this method is in
i.putExtra(PENDING_REQ_KEY, MSG_UPDATE);
pIntent = PendingIntent.getService(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
am.set(AlarmManager.RTC,System.currentTimeMillis()+delay,pIntent);
}
Next, Override the onStartCommand method, to capture the update request:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getExtras() != null && intent.getExtras().containsKey(PENDING_REQ_KEY)) {
int request = intent.getExtras().getInt(PENDING_REQ_KEY);
if (request == MSG_UPDATE) update();
}
return START_STICKY;
}
finally, your update method:
public void update() {
if (isOnline()) {
/** Push data to server here */
}
else {
setAlarm();
}
}