can anyone explain what is this items come from sms details in android?
_id = sms id
thread_id = sms thread id
address = number
person = ?
date = date
protocol =?
read = 0 not read ,1 read
status = ?
type = ?
reply_path_present =?
subject = ?
body = sms body
service_center=?
locked=?
error_code=?
seen=?
Those look like the columns of android.provider.Telephony.TextBasedSmsColumns, which are base columns for database tables that contain text-based sms messages. If you are asking where the actual data would come from to populate the rows, that data would be present in the SMS message PDU and would be stored in the Sms.Inbox or Sms.Outbox etc.
locked means that the message cannot be deleted automatically or in a batch operation.
type likely refers to one of the MESSAGE_TYPE_XXX constants.
for status there is STATUS_COMPLETE etc.
Related
I am trying to create an sms conversation list. I am using this code to get a cursor:
Cursor cursor = activity.getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);
The problem is that when I use the cursor, I get multiple messages from one contact. I am trying to get only the most recent message from all contacts so that I can show them in a recyclerview as a list of conversations.
Thanks in advance!
Querying the "content://sms/conversations" URI (Telephony.Sms.Conversations.CONTENT_URI) will return a summary of each conversation, with the "snippet" column (Telephony.Sms.Conversations.SNIPPET) being the last message in each.
This query will also return with a "msg_count" column (Telephony.Sms.Conversations.MESSAGE_COUNT) - which is pretty self-explanatory - and a "thread_id" column (Telephony.Sms.Conversations.THREAD_ID), which can be used to retrieve a complete conversation, by querying with that ID appended to the conversations URI. For example:
String threadId = ...
Uri convoUri = Telephony.Sms.Conversations.CONTENT_URI
.buildUpon().appendPath(threadId).build();
Do note that these queries will return only SMS messages. If you want MMS as well, Telephony.Mms and Telephony.MmsSms have similar URIs.
I am trying to get the body and the sender of all unread inbox .
To get all conversation's threads with unread messages I used this query:
SELECT thread_id from unified_thread WHERE folder='inbox' AND unread=1
to get the unread message of a thread I used this query
SELECT sender,body FROM unified_message WHERE unread=1
I have tried the following nested query :
SELECT sender,body FROM unified_message WHERE thread_id IN (SELECT thread_id FROM unified_thread WHERE folder = 'inbox' AND unread=1) AND unread=1"
but I only get unread message from one thread and not all unread threads.
I also tried multiquery like this:
String query1="SELECT thread_id FROM unified_thread WHERE folder='inbox' AND unread=1";
String query2="SELECT timestamp,sender,body FROM unified_message WHERE unread=1 AND thread_id IN (SELECT thread_id FROM #query1)";
Bundle params = new Bundle();
JSONObject jsonFQL=new JSONObject();
try {
jsonFQL.put("query1",query1);
jsonFQL.put("query2",query2);
} catch (JSONException e) {
e.printStackTrace();
}
params.putString("method","fql.multiquery");
params.putString("queries", jsonFQL.toString());
new Request(session,"/fql",params,HttpMethod.GET,new Request.Callback(){
public void onCompleted(Response response) {
...
}
).executeAsync(); ....
but I got error:
errorMessage: Unsupported method, fql.multiquery
Then I tried with INNER JOIN:
SELECT unified_message.sender,unified_message.body
FROM unified_message
INNER JOIN unified_thread
ON unified_message.thread_id=unified_thread.thread_id
WHERE unified_thread.unread=1
but I got this error:
Parser error: unexpected 'INNER' at position...
I learnt JOIN is not supported in FQL
Can somebody give me a hand to do this query in FQL ??
example of needed output: I have 5 conversations with different people, but only 3 conversations have unread messages. So I would like to get
something like this:
UNREAD MESSAGES
Sender: Anna
Body: hello dude
Body: how are you?
Body: I miss you
Sender: John
Body: please help me
Sender: Erick
Body: nice
Body: buddy
This works:
SELECT sender, body FROM unified_message
WHERE thread_id IN
(SELECT thread_id FROM unified_thread WHERE folder = 'inbox' AND unread=1)
AND unread=1
ORDER BY timestamp DESC
It is important to sort the messages you retrieve in a descending order using:
ORDER BY timestamp DESC
Otherwise, only the first older messages of the conversation will be examined, whereas unread messages should be recent.
Just for your knowledge, here is the corresponding multi-query, which gives the same result:
{
"threads":"SELECT thread_id FROM unified_thread WHERE folder='inbox' AND unread=1",
"messages":"SELECT sender, body FROM unified_message WHERE thread_id IN (SELECT thread_id FROM #threads) AND unread=1 ORDER BY timestamp DESC"
}
However, you should not use FQL anymore:
Version 2.0 of the Facebook Platform API is the last version where FQL
will be available. Versions after 2.0 will not support FQL. Please
migrate your applications to use Graph API instead of FQL. Please see
our changelog for current version information.
I suggest you use the following Graph API tables:
thread
message
By the way, FQL doesn't have such INNER JOIN.
Multi-query:
Evaluates a series of FQL (Facebook Query Language) queries in one call and returns the data at one time.
This method takes a JSON-encoded dictionary called ''queries'' where the individual queries use the exact same syntax as a simple query. However, this method allows for more complex queries to be made. You can fetch data from one query and use it in another query within the same call. The WHERE clause is optional in the latter query, since it references data that’s already been fetched. To reference the results of one query in another query within the same call, specify its name in the FROM clause, preceded by #.
For example, say you want to get some data about a user attending an event. Normally, you’d have to perform two queries in a row, waiting for the results of the first query before running the second query, since the second query depends on data from the first one. But with fql.multiquery, you can run them at the same time, and get all the results you need, giving you better performance than running a series of fql.query calls. First, you need to get the user ID and RSVP status of each attendee, so you’d formulate the first query – query1 – like this:
*
"query1":"SELECT uid, rsvp_status FROM event_member WHERE
eid=12345678"
*
Then to get each attendee’s profile data (name, URL, and picture in this instance), you’d make a second query – query2 – which references the results from query1. You formulate query2 like this:
"*
query2":"SELECT name, url, pic FROM profile WHERE id IN (SELECT uid
FROM #query1)
*"
https://developers.facebook.com/docs/technical-guides/fql
I am not entirely sure if this fixes your problem, but it seems that the parameter is "q", not "queries":
params.putString("q", jsonFQL.toString());
...if you take a look at the Facebook docs:
https://developers.facebook.com/docs/technical-guides/fql
Could be possible that they changed it recently, although it is deprecated so i dont think they will put much effort into it.
This nested query you placed
SELECT sender,body FROM unified_message WHERE thread_id IN (SELECT thread_id FROM unified_thread WHERE folder = 'inbox' AND unread=1) AND unread=1
should work. If it doesn't, consider filing a bug.
Breaking it down,
SELECT thread_id FROM unified_thread WHERE folder = 'inbox' AND unread=1
Should give you the thread ids for threads with unread messages. The only catch here is that unified_thread doesn't necessarily return all threads even with LIMITapplied. So what you did here was good (as long as the unread response set is small enough)
If at this point, the numbers aren't matching what you have, it doesn't make sense to move further in the query. File a bug.
The larger query
SELECT sender,body FROM unified_message WHERE thread_id IN (SELECT thread_id FROM unified_thread WHERE folder = 'inbox' AND unread=1) AND unread=1
Checks all messages within the thread, so as long as your thread ids are valid and correctly counted then there is nothing to worry about here.
Ensure you are getting the correct count of unread threads first If not, as I said before, file a bug.
So that with this query
SELECT thread_id, participants, link FROM unified_thread WHERE folder = 'inbox' AND unread
Cross check that the participants and links match what you have in your inbox.
I have created an SMS app for all versions. I am using the cursor adapter for showing the Message and number. Things are working fine except that I am not able to differentiate the new messages?
How to fix this SMS unread part? I would like to BOLD them when I receive it. But I don't know how what is received.
What I am doing now:
In my SMS receiver I store the new numbers to local DB and then compare them with the SMS content provider. This works just fine, but then takes a lot of time to load the messages.
How to fix this up?
Thanks!
I solved the problem with a few trial and errors..
Got the Read value for particular number and corresponding message( if "0" then bold them according).
To mark read I did the following:
Uri uri = Uri.parse("content://sms/inbox");
String selection = "address = ? AND body = ? AND read = ?";
String[] selectionArgs = {from, body, "0"};
ContentValues values = new ContentValues();
values.put("read", true);
context.getContentResolver().update(uri, values, selection, selectionArgs);
Hope it helps for people who are looking for solution...
I have an sqlite database that contains all the sms messages of the user, however when you start the app I need to get all the sms's that I might not have if the user decides to use a different sms app inbetween.
I'm looking for the best way to sync my database with the base android content provider.
at the moment I do an Insert or Ignore for each sms like so :
insert or ignore into sms (smsID, smsCONID, smsMSG, smsNUM, smsREAD, smsTIMESTAMP, smsTYPE, smsSHORTMSG) values (?,?,?,?,?,?,?,?);
I load the inbox and sent messages in separate asynctasks in my splash screen activity
this takes about 10s or so.
my doInBackground :
#Override
protected Void doInBackground(Void... arg0) {
int thread_id = 0;
int _id = 0;
int read;
String number;
boolean first = true;
String msg;
long timestamp;
/**
* RECUPERATION DES MESSAGES RECUS
*/
// PREPARE CURSOR
cursorInbox.moveToFirst();
while (cursorInbox.moveToNext()) {
if(first){
cursorInbox.moveToFirst();
first = false;
}
// RECUPERE THREAD_ID + ID_SMS + NUMERO DU CONTACT
thread_id = cursorInbox.getInt(cursorInbox.getColumnIndexOrThrow("thread_id"));
_id = cursorInbox.getInt(cursorInbox.getColumnIndexOrThrow("_id"));
number = cursorInbox.getString(cursorInbox.getColumnIndexOrThrow("address"));
msg = cursorInbox.getString(cursorInbox.getColumnIndexOrThrow("body"));
read = cursorInbox.getInt(cursorInbox.getColumnIndexOrThrow("read"));
timestamp = cursorInbox.getLong(cursorInbox.getColumnIndexOrThrow("date"));
// CREER LE SMS
dataManip.insert(_id, thread_id, msg, number, read, timestamp, "received",ContactsFactory.getMessageShort(msg));
i++;
publishProgress(i);
}
Log.d(TAG,"LoadActivity - Inbox Loaded");
return null;
}
Ideas for impovement?
How about registering a ContentObserver in a separate Service to listen to changes in the Android SMS provider? I'm not sure if it notifies observers on changes. But if it does, your database will always be in sync. But don't depend solely on this, as the service may be terminated at any time due to various reasons.
For the actual sync, ensure that the "_id" column in your table is the PRIMARY KEY. Query the content provider sorted by "_id". Query your own table sorted by "_id" and read all ids. Now iterate through the two sorted lists, inserting the items missing in yours and deleting the ones missing the content provider. You do want to also remove messages that were deleted using the other SMS app, don't you? The "insert or ignore" statement won't delete the missing rows for you.
if your database is indexed, than remove/disable the indexes: the inserts will be faster. Rebuild the indexes later in a new thread/task.
solution 2: don't write to database in first step just in memory( in a collection) later you will do the writings.
How about comparing the timestamps of each of the SMSes in the inbox with the latest timestamp in your database, and then only insert SMSes with a newer timestamp.
If you also start backwards, with the last SMS in the inbox, then you can break out of your loop as soon as you get to the first SMS older than your newest SMS.
I am currently using
ContentResolver cr = getContentResolver();
Uri uri = Uri.parse("content://sms/");
Cursor messagesCursor = cr.query(uri, new String[] { "_id", "address", "body", "person" }, null, null, null);
if (messagesCursor.getCount() > 0) {
while (messagesCursor.moveToNext()) {
colName = getContactName(messagesCursor.getString(messagesCursor.getColumnIndex("address"))) + "\n";
}
}
to get all the text in the user's inbox. From there, messagesCursor.getColumnIndex("address") will get the SMS's number. Then it will be place in getContactName() where it will then get the contacts' name from their contact's list.
This method will take a long time as it goes though EVERY SINGLE text message, get number, then get the contact's name, check if name exist in array, if it doesn't put in array then from there create a ListView.
The app will take a long time to load on start up if the user's inbox contains lots of text.
Is there any special way to get UNIQUE numbers from inbox? Something in cr.query?
Thanks in advance.(:
EDIT :
I'm creating just a simple inbox application. It reads from the original inbox message and list the messages in it.
For this project, what I did was to read through ALL the "address" which is the phone number, put it in an ArrayList, and finally to the ListView. As it cycles through all the messages in inbox, it takes a long time to startup.
For example :
Inbox Messages
Person 1
Person 1
Person 1
Person 2
Person 2
Person 3
Person 3
Person 3
Person 3
What my current code does :
Read EVERY SINGLE message
Check if name in ArrayList
If it is, skip. If not, add in array.
Throw ArrayList into ListView.
What my intention was :
A code that only reads out :
Person 1
Person 2
Person 3
Try only using "address" in projection (that means, don't include even "_id") - I'm not sure about this but it may solve the case.