In my application i want to get sms/mms from device and display the messages in listview.By using the following code to get the all sms from device.
public void readSmsFromDevice() {
preferences = PreferenceManager
.getDefaultSharedPreferences(BackgroundService.this);
final_msg_time = preferences.getLong("msgtime", 0);
Uri uriSMSURI = Uri.parse("content://sms/");
String[] projection = { "address", "body", "date", "type" };
String where = "date" + ">" + final_msg_time;
Cursor cur = getContentResolver().query(uriSMSURI, projection, where,null, "date");
while (cur.moveToNext()) {
if(ProfileFragment.stop)
{
break;
}else{
try {
//
Message mess1=new Message();
try{
String _id = cur.getString(cur.getColumnIndex("_id"));
mess1.setId(_id);
}catch(Exception e)
{
mess1.setId("null");
}
try{
String number = cur.getString(cur.getColumnIndex("address"));
number = number.replaceAll("[\\W]", "");
if (number.trim().length() > 10) {
mess1.setNumber(number.substring(number.length() - 10,
number.length()));
mess1.setAddress(number.substring(number.length() - 10,
number.length()));
} else {
mess1.setNumber(number);
mess1.setAddress(number);
}
}
catch(Exception e){}
mess1.setBody(cur.getString(cur.getColumnIndex("body")));
String type = cur.getString(cur.getColumnIndex("type"));
Long millisecond = Long.parseLong(cur.getString(cur
.getColumnIndex("date")));
String dateString = DateFormat.format("yyyy/MM/dd hh:mm:ss a",
new Date(millisecond)).toString();
mess1.setDate_millis(millisecond);
mess1.setDate(dateString);
mess1.setType(type);
mess1.setmessagetype("sms");
messages.add(mess1);
} catch (Exception e) {}
}
}
cur.close();
}
By using this method i am getting all sms from device.But my question is how to differenciate group message.In group message one message sent different contact numbers(senders).So in normal message application group message displayed in separate column and single message displayed in separate column.So my application also i have to display the messages like message application.So in this cursor how to identify group message?Is there any column is available to identify group message?So please suggest me how to do taht.Thanks In Advance.....
the thread THREAD_ID column will give you all the messages in the same conversation. You can then use the address column to differentiate the senders of the messages in the group message.
You should also use the Telephony class that was introduced in API 19 instead of the content resolver. https://developer.android.com/reference/android/provider/Telephony.html
Related
The android default Email is filter by subject, sender or receiver. But how to filter by content? The message body is not saved to database, which is saved to the file in after Android 5.0. Should I put the message body to the database, which do like before Android 5.0? And then filter the content according the keyword? Please give me some advice, Thanks!
case BODY:
final ContentValues dbValues = new ContentValues(values);
// Prune out the content we don't want in the DB
dbValues.remove(BodyColumns.HTML_CONTENT);
dbValues.remove(BodyColumns.TEXT_CONTENT);
// TODO: move this to the message table
longId = db.insert(Body.TABLE_NAME, "foo", dbValues);
resultUri = ContentUris.withAppendedId(uri, longId);
// Write content to the filesystem where appropriate
// This will look less ugly once the body table is folded into the message table
// and we can just use longId instead
if (!values.containsKey(BodyColumns.MESSAGE_KEY)) {
throw new IllegalArgumentException(
"Cannot insert body without MESSAGE_KEY");
}
final long messageId = values.getAsLong(BodyColumns.MESSAGE_KEY);
// Ensure that no pre-existing body files contaminate the message
deleteBodyFiles(context, messageId);
writeBodyFiles(getContext(), messageId, values);
break;
public static String buildLocalSearchSelection(Context context, long mailboxId,
String queryFilter, String queryFactor) {
StringBuilder selection = new StringBuilder();
selection.append(" (");
queryFilter = queryFilter.replaceAll("\\\\", "\\\\\\\\")
.replaceAll("%", "\\\\%")
.replaceAll("_", "\\\\_")
.replaceAll("'", "''");
String[] queryFilters = queryFilter.split(" +");
boolean isAll = false;
if (queryFactor.contains(SearchParams.SEARCH_FACTOR_ALL)) {
isAll = true;
}
if (queryFactor.contains(SearchParams.SEARCH_FACTOR_SUBJECT) || isAll) {
selection.append(buildSelectionClause(queryFilters, MessageColumns.SUBJECT));
}
if (queryFactor.contains(SearchParams.SEARCH_FACTOR_SENDER) || isAll) {
selection.append(buildSelectionClause(queryFilters, MessageColumns.FROM_LIST));
}
if (queryFactor.contains(SearchParams.SEARCH_FACTOR_RECEIVER) || isAll) {
selection.append(buildSelectionClause(queryFilters, null));
}
selection.delete(selection.length() - " or ".length(), selection.length());
selection.append(")");
return selection.toString();
}
it can use the ' MessageColumns.SNIPPET' to filter the email content.
I want to get an int with the number of unread emails in the accounts of the device. I have seen that there is a new way to do this using the "Gmail Labels Public API"
http://android-developers.blogspot.in/2012/04/gmail-public-labels-api.html
I have read the documentation and downloaded the sample application and it really works. But I have two problems: (
My intention is to get an int with the number of unread conversations, i try this:
public static int getUnreadGmailCount(Context context) {
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(GmailContract.Labels.getLabelsUri("ensisinfo102#gmail.com"),
null,
null, null,
null);
if (cursor == null || cursor.isAfterLast()) {
Log.d(TAG, "No Gmail inbox information found for account.");
if (cursor != null) {
cursor.close();
}
return 0;
}
int count = 0;
while (cursor.moveToNext()) {
if (CANONICAL_NAME_INBOX_CATEGORY_PRIMARY.equals(cursor.getString(cursor.getColumnIndex(CANONICAL_NAME)))) {
count = cursor.getInt(cursor.getColumnIndex(NUM_UNREAD_CONVERSATIONS));
System.out.println("count is====>"+count);
break;
}
}
cursor.close();
return count;
}
but not works, always returns "0",But in gmail i have 3 unread messages
really appreciate any help
thanks and regards
You can get a label and check the messagesUnread. The INBOX label is probably what you want:
Request
GET https://www.googleapis.com/gmail/v1/users/me/labels/INBOX?access_token={ACCESS_TOKEN}
Response
{
"id": "INBOX",
"name": "INBOX",
"messageListVisibility": "hide",
"labelListVisibility": "labelShow",
"type": "system",
"messagesTotal": 4527,
"messagesUnread": 4498,
"threadsTotal": 4168,
"threadsUnread": 4154
}
Please read carefully this document and also check this one
I am developing an android app which backs up and restores the messages/conversations from device. It backup the messages, export file in the form of xml, and then later restore it. The only problem I am facing is the date/times of conversations. It is changed to current time at the time of restoration, but when I open any conversation, there time is correct. Have a look at photos.
Before backup:
After backup:
Code I am using for backup:
Uri uri = Uri.parse("content://sms/inbox");
//Uri uri = Uri.parse("content://mms-sms/conversations/");
ContentResolver contentResolver = getContentResolver();
final String[] projection = new String[]{"*"};
Cursor SMSL = contentResolver.query(Telephony.Sms.Inbox.CONTENT_URI, projection, null, null, null);
int msgscount = SMSL.getCount();
if (msgscount>0) {
msgs = new String[SMSL.getCount()][5];
int i = 0;
while (SMSL.moveToNext()) {
address = SMSL.getString(SMSL.getColumnIndex("address"));
body = SMSL.getString(SMSL.getColumnIndex("body"));
read = SMSL.getString(SMSL.getColumnIndex("read"));
date = SMSL.getString(SMSL.getColumnIndex("date"));
type = SMSL.getString(SMSL.getColumnIndex("type"));
msgs[i][0] = address;
msgs[i][1] = body;
msgs[i][2] = date;
msgs[i][3] = read;
msgs[i][4] = type;
Log.i("Date: ", String.valueOf(SMSL.getLong(SMSL.getColumnIndex("date"))));
i++;
}
SMSL.close();
}else{
msgs = new String[0][0];
Toast.makeText(getApplicationContext(),"No messages found!",Toast.LENGTH_LONG).show();
}
Code for restoring:
ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.parse("content://sms/inbox");
//Uri uri = Uri.parse("content://mms-sms/conversations/");
ContentValues values = new ContentValues();
for (int i = 0; i < readMsgsFromFile.length; i++) {
values.put("address",readMsgsFromFile[i][0]);
values.put("body",readMsgsFromFile[i][1]);
values.put("date",readMsgsFromFile[i][2]);
values.put("read",readMsgsFromFile[i][3]);
values.put("type",readMsgsFromFile[i][4]);
contentResolver.insert(Telephony.Sms.Inbox.CONTENT_URI, values);
Log.i("Restoring: ",readMsgsFromFile[i][2]);
}
Thanks Mike M. I did find a solution and you are right, the conversation table is updated whenever a new message is received or sent by a user and the time of conversation is same as that message's (whether received or sent) time. But in case of writing messages through contentresolver query it does not work and the conversation time is current time at the time of writing. So what I did is add a temporary message in all of the conversations, right after messages are restored. And after that delete all the temporary messages, this will update the conversations time to last message time.
HashSet hs = new HashSet();
hs.addAll(list);
//list is the ArrayList<String> which contains the addressess of all the messages and
//through hashset we remove all the duplicates to get only the addressess once and hence we know the number of conversations and their addressess.
list.clear();
list.addAll(hs);
//Add some dummy message to each conversation
ContentValues values2 = new ContentValues();
for (int i = 0; i < list.size(); i++) {
values2.put("address",list.get(i));
values2.put("date_sent",readMsgsFromFile[0][1]);
values2.put("date",readMsgsFromFile[0][2]);
values2.put("type",readMsgsFromFile[0][3]);
values2.put("body","temp"); //this should be more unique
values2.put("read",readMsgsFromFile[0][5]);
values2.put("service_center","01010101");
contentResolver.insert(Telephony.Sms.CONTENT_URI, values2);
}
//Now deleting that message with body 'temp' from each conversation
Cursor c = contentResolver.query(Telephony.Sms.CONTENT_URI,null,null,null,null);
while (c.moveToNext()){
String body = c.getString(c.getColumnIndex("body"));
String mid = c.getString(0);
if (body.equals("temp")){
Log.i("Deleting ",mid);
getContentResolver().delete(Uri.parse(Telephony.Sms.CONTENT_URI+"/"+mid),null,null);
}
}
c.close();
This word 'temp' could be and should be more unique so that it is not mixed with actual message.
So I am working on a project where I need to get the user's contact list (Specifically the Name, email address, and location of the contact details), put that into a list, and then use that list in an autocomplete view so they can start typing a name and it will filter it out.
My code works just fine, it all compiles and all runs without error. The problem is that it is VERY slow. For someone who has 10 contacts, this will likely not take long, but my phone holds 1700 contacts in it so this entire process takes upwards of 2 minutes to complete... which is horrendous!
Here is the current working code below (I cut out the code for the location adding as it was wordy):
public static List<MyObject> getContactList(){
List<MyObject> contactList = new ArrayList<>();
Cursor people = MyApplication.getAppContext().getContentResolver().
query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
while (people.moveToNext()) {
String email = "";
String location = "";
String phone = "";
String contactName = people.getString(people.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME));
String contactId = people.getString(people.getColumnIndex(
ContactsContract.Contacts._ID));
if(contactId != null){
Cursor contactsEmails = getSpecificEmailsCursor(contactId);
while (contactsEmails.moveToNext()){
//For now, just setting it to the last email
email = contactsEmails.getString(contactsEmails.getColumnIndex(
ContactsContract.CommonDataKinds.Email.DATA));
phone = contactsEmails.getString(contactsEmails.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
}
contactsEmails.close();
MyObject person = new MyObject();
try{
person.setEmail(email);
person.setName(contactName);
person.setPhone(phone);
} catch (NullPointerException e){
L.m("Null pointer hit on person");
}
if(contactName != null && email != null){
contactList.add(person);
}
}
}
people.close();
return contactList;
}
Does anyone have any recommendations on how to either speed this process up, or, a better way to go about what I am trying to accomplish? Thanks!
-Sil
sir, i have a problem in updating my database. i've made a listview containing this data
name
phone number
status
i would like to update the status of person if he sent a message with a keyword "available" in it and would update my listview like this
name
phone number
available
so i decided to make the phone number as the trigger. if the phone number of the person who sent the message is in my listview, it will update the database. but here is my problem, if i saved the phone number in my listview in this format
09211234567
the sender will return their phone number as
+639211234567
so i worked around this by getting the substring and cut the phone number into "9211234567", and then add 0 to transform it into "09211234567".
however, the database status still doesn't update. but when i used the same technique in sending sms from emulator to emulator, it works just fine.
i saved the number of emulator in my listview as
5556
but the emulator returns
15555215556
so i just get the substring to get 5556
please help me. here is my code:
public static String sender;
public GroupDb info;
public String aStatus = "available";
public String nStatus = "not available";
public String addNum = "0";
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
info = new GroupDb(context);
Bundle bundle = intent.getExtras();
Object[] pdusObj = (Object[]) bundle.get("pdus");
SmsMessage[] messages = new SmsMessage[pdusObj.length];
for (int i = 0; i<pdusObj.length; i++)
{
messages[i] = SmsMessage.createFromPdu ((byte[])
pdusObj[i]);
sender = messages[i].getOriginatingAddress();
}
for (SmsMessage msg : messages) {
if (msg.getMessageBody().contains("available")) {
info.open();
String remFirstChar = sender.substring(3);
addNum += remFirstChar;
Toast.makeText(context.getApplicationContext(), "received sms from: " +addNum,
Toast.LENGTH_LONG).show();
//if starts with +639
if(sender.length() == 13)
{
info.updateStatus(addNum, aStatus);
Toast.makeText(context.getApplicationContext(), "addNum: " +addNum,
Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(context.getApplicationContext(), "sender: " +sender,
Toast.LENGTH_LONG).show();
info.updateStatus(remFirstChar, aStatus);
}
info.close();
}//end if - available
here is how i updated my status
//update status
public void updateStatus(String mNumber, String mStatus) throws SQLException
{
// TODO Auto-generated method stub
ContentValues cvUpdate = new ContentValues();
cvUpdate.put(KEY_STATUS, mStatus);
ourDatabase.update(DATABASE_TABLE, cvUpdate, KEY_NUMBER + "=" + mNumber, null);
}
update:
i even tried to enter "+63" format in listview but still, i won't update. all functions such as deletion and editing also don't work and shows force close.
You need to use PhoneNumberUtils class.
Before saving the Phone Number in database first convert it as
String formattedNumber = PhoneNumberUtils.formatNumber(phonenumber);
For comparison you can use PhoneNumberUtils.compare