I want to select only latest inbox SMS on button click. Here is my code.
btnGet = (Button) findViewById(R.id.btnGet);
btnGet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
if (fetchInbox() != null) {
ArrayList sms1 = fetchInbox();
for (int i = 0; i < sms1.size(); i++) {
String st = sms1.get(i).toString();
String[] sArr = st.split("\\$");
mobile = sArr[0];
sms = sArr[1];
useGet(mobile, sms);
}
} else {
textView1.setText("no sms");
}
} catch (Exception ex) {
textView1.setText("Exception" + ex.getMessage());
}
}
});
And here is my function to fetch SMS.
public ArrayList fetchInbox()
{
ArrayList sms = new ArrayList();
Uri uriSms = Uri.parse("content://sms/inbox");
Cursor cursor = getContentResolver().query(uriSms, new String[]{"_id", "address", "date", "body"},null,null,null);
cursor.moveToFirst();
while (cursor.moveToNext()) {
String id = cursor.getString(0);
String address = cursor.getString(1);
String body = cursor.getString(3);
sms.add(address + "$" + body + "$" + id);
}
return sms;
}
I am able get all inbox SMS by this code, but I want to select only before 5 minutes inbox SMS. I am new with android apps.
Cursor cursor = getContentResolver().query (Uri uri,
String[] projection,
String selection,
String[] selectionArgs,
String sortOrder)
selection : A filter declaring which rows to return. Passing null will
return all rows for the given URI.
As you can see, you can specifies the criteria for selecting rows.
First get the current date time.
Calendar date = Calendar.getInstance();
long t = date.getTimeInMillis();
Then subtract 5 mins from current time.
static final long ONE_MINUTE_IN_MILLIS = 60000;
Date afterSubtractingFiveMins = new Date(t - (5 * ONE_MINUTE_IN_MILLIS));
Now create the filter and query the messages.
String filter = "date>=" + afterSubtractingFiveMins.getTime();
Cursor cursor = getContentResolver().query(uriSms, new String[]{"_id", "address", "date", "body"},filter,null,null);
PS: I didn't check the code. You may have to optimize.
Related
I am trying to read latest SMS from All contacts but the procedure Currently I am using seems to be very slow. How can I improve it?
public Map<String, SMS> getLatestMsgs(){
Uri uriSMSURI = Uri.parse("content://sms/");
String[] projection = {_id, address, body,
read, date, subscriptionId, type};
String selection = "";
String[] selectionArgs = {};
String sortOrder = Telephony.Sms.DATE +" desc";
Cursor c = context.getContentResolver()
.query(uriSMSURI, projection, selection, selectionArgs, sortOrder);
LinkedHashMap<String, SMS> smsMap = new LinkedHashMap<>();
log.info(methodName, "Reading Messages..");
if(c==null){
log.info(methodName, "Query returned null cursor");
return smsMap;
}
while (c.moveToNext()) {
String id = c.getString(c.getColumnIndexOrThrow(this._id));
String from = c.getString(c.getColumnIndexOrThrow(this.address));
String body = c.getString(c.getColumnIndexOrThrow(this.body));
int serviceCenter = c.getInt(c.getColumnIndexOrThrow(this.subscriptionId));
boolean readState = c.getInt(c.getColumnIndex(this.read)) == 1;
long time = c.getLong(c.getColumnIndexOrThrow(this.date));
long type = c.getLong(c.getColumnIndexOrThrow(this.type));
if(!smsMap.containsKey(from)) {
SMS sms = new SMS();
sms.setId(id);
sms.setFrom(from);
sms.setBody(body);
sms.setRead(readState);
sms.setDateTime(time);
sms.setType(type);
sms.setSubscription(serviceCenter);
smsMap.put(from, sms);
}
}
c.close();
return smsMap;
}
This method has following steps:
Read all sms in decreasing order of timestamp
Start Iterating over fetched rows
If sms address already in map then ignore
else put SMS into LinkedHashMap
I want user to select a number from calllog and that number get selected and come in the activity. So I created custom calllog list. I used this code but it is not showing the call log list in right order
first thing it is showing the callhistory of the first number fully that it gets in the calllog list
second I wnt to show the name also, I tried a lot but I am not able to do
Can anyone tell what amendments i make in this code to make it right
The code I used is:
String[] callLogFields = { android.provider.CallLog.Calls._ID,
android.provider.CallLog.Calls.NUMBER,
android.provider.CallLog.Calls.CACHED_NAME };
String viaOrder = android.provider.CallLog.Calls.DATE + " DESC";
String WHERE = android.provider.CallLog.Calls.NUMBER + " >0"; /*filter out private/unknown numbers */
final Cursor callLog_cursor = this.getContentResolver().query(
android.provider.CallLog.Calls.CONTENT_URI, callLogFields,
WHERE, null, viaOrder);
AlertDialog.Builder myversionOfCallLog = new AlertDialog.Builder(this);
android.content.DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int item) {
callLog_cursor.moveToPosition(item);
Log.v("number", callLog_cursor.getString(callLog_cursor
.getColumnIndex(android.provider.CallLog.Calls.NUMBER)));
callLog_cursor.close();
}
};
myversionOfCallLog.setCursor(callLog_cursor, listener,
android.provider.CallLog.Calls.NUMBER);
myversionOfCallLog.setTitle("Choose from Call Log");
myversionOfCallLog.create().show();
You can add the Contact Numbers in a Set, which will prevent adding duplicate contact numbers. Then add the Set's data to listview as you want.
Set<String> setNumbers = new HashSet<String>();
String callNumber = cursor.getString(cursor.getColumnIndex(
android.provider.CallLog.Calls.NUMBER));
setNumbers.add(callNumber);
Hope this helps.
For saving numbers without duplicates, as MysticMagic suggested, use 'Set' as per the link given in the comment.
For getting the contact name from the phone number, use code :
(Reference)
private String getContactName(Context context, String number) {
String name = null;
// define the columns I want the query to return
String[] projection = new String[] {
ContactsContract.PhoneLookup.DISPLAY_NAME,
ContactsContract.PhoneLookup._ID};
// encode the phone number and build the filter URI
Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
// query time
Cursor cursor = context.getContentResolver().query(contactUri, projection, null, null, null);
if(cursor != null) {
if (cursor.moveToFirst()) {
name = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
Log.v(TAG, "Started uploadcontactphoto: Contact Found # " + number);
Log.v(TAG, "Started uploadcontactphoto: Contact name = " + name);
} else {
Log.v(TAG, "Contact Not Found # " + number);
}
cursor.close();
}
return name;
}
Also refer here for another method to fetch name in phone call history
Uri allCalls = Uri.parse("content://call_log/calls");
Cursor c = managedQuery(allCalls, null, null, null, null);
String num= c.getString(c.getColumnIndex(CallLog.Calls.NUMBER));// for number
String name= c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME));// for name
String duration = c.getString(c.getColumnIndex(CallLog.Calls.DURATION));// for duration
int type = Integer.parseInt(c.getString(c.getColumnIndex(CallLog.Calls.TYPE)));// for call type, Incoming or out going
Finally this is the code that worked with the help of MysticMagic and Nishanthi Grashia
Set setA;
setA = new HashSet();
public void getCallLog() {
try {
final String[] projection = null;
final String selection = null;
final String[] selectionArgs = null;
final String sortOrder = "DATE DESC";
final Cursor cursor = this.getContentResolver().query(
Uri.parse("content://call_log/calls"), projection,
selection, selectionArgs, sortOrder);
if (cursor != null) {
// Loop through the call log.
while (cursor.moveToNext()) {
// Common Call Log Items
String callNumber = cursor
.getString(cursor
.getColumnIndex(android.provider.CallLog.Calls.NUMBER));
setA.add(callNumber);
}
generateList();
}
} catch (Exception e) {
}
}
#SuppressLint("NewApi")
private void generateList() {
// TODO Auto-generated method stub
try {
Object[] calllist = new String[setA.size()];
calllist = setA.toArray();
String scalllist[] = Arrays.copyOf(calllist, calllist.length,
String[].class);
for (int i = 0; i < scalllist.length; i++) {
scalllist[i] = scalllist[i] + " "
+ getContactName(this, scalllist[i]);
}
final Dialog d = new Dialog(this);
d.setContentView(R.layout.dialog1);
d.setTitle("Choose from Call Log...");
final ListView lv1 = (ListView) d.findViewById(R.id.listView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1,
scalllist);
lv1.setAdapter(adapter);
lv1.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
// TODO Auto-generated method stub
String clickednumber[] = (lv1.getItemAtPosition(arg2)
.toString()).split(" ");
usernumber.setText(clickednumber[0]);
try {
username.setText(clickednumber[1]);
} catch (ArrayIndexOutOfBoundsException e) {
username.setText(" ");
}
d.dismiss();
}
});
d.show();
} catch (Exception e) {
}
}
private String getContactName(Context context, String number) {
String name = null;
try {
// define the columns I want the query to return
String[] projection = new String[] {
ContactsContract.PhoneLookup.DISPLAY_NAME,
ContactsContract.PhoneLookup._ID };
// encode the phone number and build the filter URI
Uri contactUri = Uri.withAppendedPath(
ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(number));
// query time
Cursor cursor = context.getContentResolver().query(contactUri,
projection, null, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
name = cursor
.getString(cursor
.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
} else {
name = " ";
}
cursor.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return name;
}
I have implemented the code to get sms from inbox to my app.It gets all messages.But I want to load messages from specific number.I followed the tutorial from [Read all SMS from a particular sender it shows empty view.I worked out this code.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.inbox);
ListView list = (ListView) findViewById(R.id.listView1);
List<String> msgList = getSMS();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, msgList);
list.setAdapter(adapter);
}
public List<String> getSMS() {
List<String> sms = new ArrayList<String>();
// StringBuilder smsBuilder = new StringBuilder();
final String SMS_URI_INBOX = "content://sms/inbox";
final String SMS_URI_ALL = "content://sms/";
try {
Uri uri = Uri.parse(SMS_URI_INBOX);
String[] projection = new String[] { "_id", "address", "person", "body", "date", "type" };
Cursor cur = getContentResolver().query(uri, projection, "address='5558'", null, null);
if (cur.moveToFirst()) {
int index_Address = cur.getColumnIndex("address");
int index_Person = cur.getColumnIndex("person");
int index_Body = cur.getColumnIndex("body");
int index_Date = cur.getColumnIndex("date");
int index_Type = cur.getColumnIndex("type");
do {
String strAddress = cur.getString(index_Address);
int intPerson = cur.getInt(index_Person);
String strbody = cur.getString(index_Body);
long longDate = cur.getLong(index_Date);
int int_Type = cur.getInt(index_Type);
sms.add("Number: " + strAddress + " .Message: " + strbody);
// smsBuilder.append("[ ");
// smsBuilder.append(strAddress + ", ");
// smsBuilder.append(intPerson + ", ");
// smsBuilder.append(strbody + ", ");
// smsBuilder.append(longDate + ", ");
//smsBuilder.append(int_Type);
// smsBuilder.append(" ]\n\n");
} while (cur.moveToNext());
if (!cur.isClosed()) {
cur.close();
cur = null;
}
else {
// smsBuilder.append("no result!");
} // end if
}} catch (SQLiteException ex) {
Log.d("SQLiteException", ex.getMessage());
}
return sms;
}
I passed address as my another emulator.If I gave null replacing address field of getContentResolver()it will load all sms in inbox.Can anyone help me where I have to modify ?
Use following code,
Uri uri = Uri.parse("content://sms/");
ContentResolver contentResolver = getContentResolver();
String phoneNumber = "+911234567890";
String sms = "address='"+ phoneNumber + "'";
Cursor cursor = contentResolver.query(uri, new String[] { "_id", "body" }, sms, null, null);
System.out.println ( cursor.getCount() );
while (cursor.moveToNext())
{
String strbody = cursor.getString( cursor.getColumnIndex("body") );
System.out.println ( strbody );
}
Following permission is required,
<uses-permission android:name="android.permission.READ_SMS"/>
100% working code :
String[] projection = new String[] { "_id", "thread_id","address", "person", "body", "date", "type" };
Uri uri = Uri.parse("content://sms/");
Cursor c = cr.query(uri, projection,"address='9876543210'",null, "date desc");
int totalSMS = 0;
if (c != null) {
totalSMS = c.getCount();
if (c.moveToFirst()) {
for (int j = 0; j < totalSMS; j++) {
String id = c.getString(c.getColumnIndexOrThrow(Telephony.Sms._ID));
String thread_id = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.THREAD_ID));
String smsDate = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.DATE));
String number = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.ADDRESS));
String body = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.BODY));
String type;
switch (Integer.parseInt(c.getString(c.getColumnIndexOrThrow(Telephony.Sms.TYPE)))) {
case Telephony.Sms.MESSAGE_TYPE_INBOX:
type = "inbox";
messageList.add(new Message(id, thread_id, number, body, smsDate, type));
break;
case Telephony.Sms.MESSAGE_TYPE_SENT:
type = "sent";
messageList.add(new Message(id, thread_id, number, body, smsDate, type));
break;
case Telephony.Sms.MESSAGE_TYPE_OUTBOX:
break;
default:
break;
}
c.moveToNext();
}
}
c.close();
I am using contentobserver to monitor SMS. It all works fine. When I try to save these SMS to a database, it shows an error error near "t" syntax error for a particular SMS. When I delete this particular SMS there is no problem. After installing, it shows all the messages correctly in order. But the error is sent to the end of my arraylist. Also the SMS sent from my phone after this are updated in between the list, not on the last position. Please help.
adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1,list);
setListAdapter(adapter);
data = Incoming_outgoing_smsActivity.this.openOrCreateDatabase("Messages", MODE_PRIVATE, null);
data.execSQL("CREATE TABLE IF NOT EXISTS recor(text varchar(300));");
Cursor cur = data.rawQuery("SELECT * FROM recor", null);
while(cur.moveToNext()) {
String content = cur.getString(cur.getColumnIndex("text"));
backward_list.add(content);
list.add(content);
}
adapter.notifyDataSetChanged();
Cursor cursor = getContentResolver().query(Uri.parse("content://sms"), null, null, null, null);
while(cursor.moveToNext()) {
String number = cursor.getString(cursor.getColumnIndex("address"));
String[] projection = new String[] {ContactsContract.PhoneLookup.DISPLAY_NAME};
Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
Cursor cursor_name = getContentResolver().query(contactUri, projection, null, null, null);
String body = cursor.getString(cursor.getColumnIndex("body"));
String type = cursor.getString(cursor.getColumnIndex("type"));
long date1= cursor.getLong(cursor.getColumnIndex("date"));
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss.SSS");
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(date1);
try {
int n = cursor.getInt(cursor.getColumnIndex("type"));
switch (n) {
case 1:
String message = "FROM "+number+"\n"+formatter.format(calendar.getTime())+"\n"+"Message:-"+body;
if(backward_list.contains(message)) {
continue;
} else {
list.add(message);
backward_list.add(message);
data.execSQL("INSERT INTO recor VALUES('"+message+"')");
}
break;
case 2:
String messag = "TO "+number+"\n"+formatter.format(calendar.getTime())+"\n"+"Message:-"+body;
if(backward_list.contains(messag)) {
continue;
} else {
list.add(messag);
backward_list.add(messag);
data.execSQL("INSERT INTO recor VALUES('"+messag+"')");
}
break;
default:
break;
}
}
catch (Exception e) {
// TODO: handle exception
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
continue;
}
}
The above code saves the current SMS in your inbox to the database. The code below is used to update your inbox when a new SMS arrives. It does toast the arrived messages but doesn't insert them into the database.
data = Incoming_outgoing_smsActivity.this.openOrCreateDatabase("Messages", MODE_PRIVATE, null);
data.execSQL("CREATE TABLE IF NOT EXISTS recor(text varchar(300));");
super.onChange(selfChange);
Cursor cursor = getContentResolver().query(Uri.parse("content://sms"), null, null, null, null);
while(cursor.moveToNext()) {
String number = cursor.getString(cursor.getColumnIndex("address"));
String[] projection = new String[] {
ContactsContract.PhoneLookup.DISPLAY_NAME};
Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
Cursor cursor_name = getContentResolver().query(contactUri, projection, null, null, null);
if(cursor_name.moveToFirst()) {
name = cursor_name.getString(cursor_name.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
}
String body = cursor.getString(cursor.getColumnIndex("body"));
String type = cursor.getString(cursor.getColumnIndex("type"));
long date1= cursor.getLong(cursor.getColumnIndex("date"));
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss.SSS");
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(date1);
int n = cursor.getInt(cursor.getColumnIndex("type"));
switch (n) {
case 1:
String message = "FROM "+number+"\n"+formatter.format(calendar.getTime())+"\n"+"Message:-"+body;
if(backward_list.contains(message)) {
continue;
} else {
list.add(message);
backward_list.add(message);
data.execSQL("INSERT INTO recor VALUES('"+message+"')");
}
break;
case 2:
String messag = "TO "+number+"\n"+formatter.format(calendar.getTime())+"\n"+"Message:-"+body;
if(backward_list.contains(messag)) {
continue;
} else {
list.add(messag);
backward_list.add(messag);
data.execSQL("INSERT INTO recor VALUES('"+messag+"')");
}
break;
default:
break;
}
At a guess there was some sort of restricted character/word in the one SMS.
You should use prepared statements to take care of the issue.
See this SO Answer for an example.
For your second issue about the order of display, change/use an ORDER BY in your query to set the proper order.
I'm trying to create a "select-multiple" contact list where I can allow a user to check more than one contact. What I'm looking for is effectively the same thing as the native activity that appears when composing a message to multiple contacts. Thanks!
At first you need to get a list of contacts and then display it on ListView element. For example I'm using following code to display all users contacts on a ListView:
// Run query on all contacts id
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME};
String selection = null;//ContactsContract.Contacts.HAS_PHONE_NUMBER + " = '" + ("1") + "'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC";
ContentResolver contectResolver = getContentResolver();
Cursor cursor = contectResolver.query(uri, projection, selection, selectionArgs,
sortOrder);
//Create buffer
final ArrayList<ContactData> bufferContacts = new ArrayList<ContactData>();
//Load contacts one by one
if(cursor.moveToFirst()) {
while(!cursor.isAfterLast()) {
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String[] emailProj = new String[]{Email.DATA};
Cursor cursorEmail = contectResolver.query(Email.CONTENT_URI, emailProj,Email.CONTACT_ID + " = ? ", new String[] { id }, null);
String[] phoneProj = new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME};
Cursor cursorPhone = contectResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, phoneProj,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id }, null);
String firstName = "";
String lastName = "";
String email = "";
String displayname = "";
String phoneNmb = "";
if(cursorPhone.moveToFirst()) {
///displayname = cursorPhone.getString(cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
phoneNmb = cursorPhone.getString(cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
cursorPhone.close();
if(cursorEmail.moveToFirst()) {
email = cursorEmail.getString(cursorEmail.getColumnIndex(Email.DATA));
}
cursorEmail.close();
displayname = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
//Divide display name to first and last
String[] names = displayname.split("\\s+");
firstName = displayname;
if(names.length >= 1) {
firstName = names[0];
}
if(names.length >= 2) {
firstName = names[1];
}
final ContactData contactData = new ContactData(id, firstName, lastName, phoneNmb, email, allChecked);
bufferContacts.add(contactData);
//Set list view initialy
runOnUiThread(new Runnable() {
public void run() {
if(contactsAdapter == null) {
ArrayList<ContactData> contacts = new ArrayList<ContactData>();
contactsAdapter = new ContactAdapter(ContactPickerActivity.this, contacts);
lvContacts.setAdapter(contactsAdapter);
}
if(bufferContacts.size() >= BUFFER_INTERVAL) {
addBuffer(bufferContacts);
}
}
});
cursor.moveToNext();
}
}
cursor.close();
runOnUiThread(new Runnable() {
public void run() {
addBuffer(bufferContacts);
}
});
If you don't want to bother yourself with making everything out of scratch then feel free to use my ready library for selecting multiple contacts:
https://github.com/kgadzinowski/Android-Multiple-Contacts-Picker-Library