In order to see the code convenient, while on the internet Google data, while looking at the Android Java source code.
Accidentally found a class Mmssmsdatabasehelper.java, originally Android will all the text messages are stored in the mmssms.db.
This class is not available in the public SDK and cannot be used directly. So I wrote a sqliteopenhelper, but a SQL exception occurred while querying.
I can't seem to do anything, but according to the information on the Internet can copy the DB file to achieve SMS data backup.
Now that each DB is related to the package name, build a project for Com.android.providers.telephony to try and see if it can be successful.
Result output please execute ' adb uninstall Com.android.providers.telephony ' in a shell,android security is very strong.
Cannot access the database directly, only through the protocol to access the database,
First put out the relevant agreement:
Content://sms/inbox Inbox
Content://sms/sent has been sent
Content://sms/draft Draft
Content://sms/outbox Outbox
content://sms/failed Send failed
content://sms/queued to send list
In the simulator Outbox no query to the data, in the simulator found long time also did not find the Outbox, very depressed.
The SMS related fields in the database are as follows:
_idOne self-increment field, starting from 1
thread_idSerial number, same sender's ID
AddressSender's mobile number
PersonOrdinal of the contact list, null for strangers
DateDate of shipment
ProtocolAgreement, divided into: 0 sms_rpoto, 1 mms_proto
ReadRead 0 unread, 1 read
StatusStatus-1 Receive, 0 complete, pending, failed
type
all = 0;
INBOX = 1;
SENT = 2;
DRAFT = 3;
OUTBOX = 4;
FAILED = 5;
QUEUED = 6;
BodySMS Content
Service_centerSMS Service Center Number
subjectThe subject of SMS
reply_path_presentTp-reply-path
locked
Retrieving the data method is simple:
Uri uri = uri.parse ("Content://sms/inbox");
Cursor cur = this.managedquery (URI, NULL, NULL, NULL, or NULL);
if (Cur.movetofirst ()) {
do{
for (int j = 0; J < Cur.getcolumncount (); j + +) {
info = "Name:" + cur.getcolumnname (j) + "=" + cur.getstring (j);
LOG.I ("====>", info);
}
}while (Cur.movetonext ());
}
Managedquery will eventually convert the arguments to SQL statements to send messages to SQLite, so the parameters are similar to SQL statements, so you can add SQL functions to the query fields.
such as new string[] projection = new string[]{"Count (*) as Count"} and so on.
The arguments in the managedquery are in turn URI,
query FieldsQuery the field array, or you can put all the fields you want to query into one word characters
For example new projection[]{"_id", "thread_id"} and New projection[]{"_id,thread_id"} are consistent.
As with SQL, field names are case insensitive
conditionsThe SQL conditional character without where, and if there are parameters? Alternative, such as "_id=?" and thread_id =? Or type = ' 1 ' "
parameters in the conditionAn array of parameter numbers corresponding to the above conditions
Sortstring without order by sort, such as _id desc, type
If the query field in Parameter Null,sql is "*", the related condition is blank
You can also use Getcontentresolver () to get a contentresolver,
Getcontentresolver (). Query () also returns a cursor object, with parameters that are consistent with managedquery.
But use Contentresolver object to update, delete and insert a data times SecurityException. There appears to be no permission to add permissions in Manifest.xml:
<uses-permission android:name= "Android.permission.WRITE_SMS" ></uses-permission>
Then delete the SMS:
This.getcontentresolver (). Delete (Uri.parse ("content://sms"), "_id=?", New string[]{"3"});
Delete succeeded.
The URL content://sms replaced with content://sms/ also succeeded, but the other URL when the program error, such as Content://sms/inbox
Looking at the source code of Android, SMS supports the following protocols:
Surlmatcher.adduri ("SMS", NULL, Sms_all);
Surlmatcher.adduri ("SMS", "#", sms_all_id);
Surlmatcher.adduri ("SMS", "Inbox", Sms_inbox);
Surlmatcher.adduri ("SMS", "inbox/#", sms_inbox_id);
Surlmatcher.adduri ("SMS", "sent", sms_sent);
Surlmatcher.adduri ("SMS", "sent/#", sms_sent_id);
Surlmatcher.adduri ("SMS", "Draft", Sms_draft);
Surlmatcher.adduri ("SMS", "draft/#", sms_draft_id);
Surlmatcher.adduri ("SMS", "Outbox", Sms_outbox);
Surlmatcher.adduri ("SMS", "outbox/#", sms_outbox_id);
Surlmatcher.adduri ("SMS", "undelivered", sms_undelivered);
Surlmatcher.adduri ("SMS", "failed", sms_failed);
Surlmatcher.adduri ("SMS", "failed/#", sms_failed_id);
Surlmatcher.adduri ("SMS", "queued", sms_queued);
Surlmatcher.adduri ("SMS", "Conversations", sms_conversations);
Surlmatcher.adduri ("SMS", "conversations/*", sms_conversations_id);
Surlmatcher.adduri ("SMS", "raw", sms_raw_message);
Surlmatcher.adduri ("SMS", "attachments", sms_attachment);
Surlmatcher.adduri ("SMS", "attachments/#", sms_attachment_id);
Surlmatcher.adduri ("SMS", "ThreadID", sms_new_thread_id);
Surlmatcher.adduri ("SMS", "threadid/*", sms_query_thread_id);
Surlmatcher.adduri ("SMS", "status/#", sms_status_id);
Surlmatcher.adduri ("SMS", "sr_pending", sms_status_pending);
Surlmatcher.adduri ("SMS", "Sim", Sms_all_sim);
Surlmatcher.adduri ("SMS", "sim/#", Sms_sim);
Among these, the protocols supported in the Delete method are:
Sms_all Delete SMS table Data According to the conditions in the parameters;
sms_all_id by _ ID Delete SMS table data
sms_conversations_id Delete SMS table data based on thread_id, with additional criteria
sms_raw_message Delete Raw table according to the conditions in the parameter;
sms_status_pending Delete sr_pending table According to the conditions in the parameter;
sms_sim remove data from the SIM card
Try sms_conversations_id: "content://sms/conversations/3 ", delete thread_id= "3", _id= "5" Data
In emulator control in Eclipse, send three data to the simulator with 13800, and then send a message with 13900
This.getcontentresolver (). Delete (Uri.parse ("CONTENT://SMS/CONVERSATIONS/3"), "_id=?", New string[]{"5"});
A piece of data was successfully deleted.
In the database each sender's thread_id is the same, but not fixed, if the entire data of a sender is deleted,
And then change to a new number when sending a text message, thread_id is assigned with the largest id+1 in the database.
The update supports a number of protocols:
sms_raw_message
sms_status_pending
SMS_ALL
sms_failed
sms_queued
SMS_ inbox
sms_sent
sms_draft
SMS_ outbox
sms_conversations
sms_all_id
sms_inbox_id
sms_failed_id
SMS_SENT_ID
sms_draft_id
sms_outbox_id
SMS_ conversations_id
sms_status_id
Test with sms_inbox_id:
Contentvalues CV = new Contentvalues ();
Cv.put ("thread_id", "2");
Cv.put ("Address", "00000");
Cv.put ("Person", "11");
Cv.put ("date", "11111111");
This.getcontentresolver (). Update (Uri.parse ("CONTENT://SMS/INBOX/4"), CV, NULL, NULL);
Too strong, even thread_id can be modified.
Insert-supported protocols:
Sms_all
Sms_inbox
Sms_failed
sms_queued
Sms_sent
Sms_draft
Sms_outbox
Sms_raw_message
Sms_status_pending
Sms_attachment
sms_new_thread_id
When inserting data into an SMS table, the type is automatically set according to the protocol.
If date is not set in the incoming data, it is automatically set to the current system time; The read flag is set to 1 when the Sms_inbox protocol is not
Sms_inbox protocol, the system automatically queries and sets the person
ThreadID is null or 0 o'clock, the system is automatically set
has been worrying about making "send failed" messages, now to do one:
Content://sms/failed
Contentvalues CV = new Contentvalues ();
Cv.put ("_id", "99");
Cv.put ("thread_id", "0");
Cv.put ("Address", "9999");
Cv.put ("Person", "888");
Cv.put ("date", "9999");
Cv.put ("protocol", "0");
Cv.put ("read", "1");
Cv.put ("Status", "1");
Cv.put ("type", "0");
Cv.put ("Body", "");
This.getcontentresolver (). Insert (Uri.parse ("content://sms/failed"), CV);
The type is set to 5,thread_id set to 1
The system even the minimum data check did not do Ah, Google is too kind to the programmer.
See if you can dig up the SMS functionality again. Let's make a bad query first:
Getcontentresolver (). Query (Uri.parse ("content://sms/"), New string[]{"A"}, "B", NULL, NULL);
Log output of the wrong SQL statement:
SELECT A from SMS WHERE (b) ORDER by date DESC
There is no group by in the Query method, and if you want to do statistics on text messages, it is too slow to traverse the cursor.
In the SQL language, group by is behind the where, so try to find a way in the condition parameter:
Android organization SQL statement when the conditions are added (), then spell a group by come out:
Getcontentresolver (). Query (Uri.parse ("content://sms/"), New string[]{"count (*) as Count, thread_id"}, "1=1") Group by (t HREAD_ID ", NULL, NULL);
Then the output of sql= SELECT count (*) as Count, thread_id from SMS WHERE (1=1) group BY (thread_id) ORDER by date DESC
What if you want to query the URI without a corresponding table, for example, to know which tables are in the MMSSMS.DB database,
The query table is URI-bound, and it is not possible to cobble together in the condition parameters.
So let's move forward and see if we can get out of the field parameters.
To query other tables, the key is to remove the system-fixed added from SMS,
Use the comments in SQL,
Getcontentresolver (). Query (Uri.parse ("content://sms/"), New string[]{"* from sqlite_master WHERE type = ' table ' --< /c0> "}, NULL, NULL, and NULL);
Then the output of the sql=select * from sqlite_master WHERE type = ' table ' -- from the SMS ORDER by date DESC
Incredibly able to run.
And then further, if you join the ";" can also run, haha, then build the table, delete the table, update the table can do whatever it is.
Getcontentresolver (). Query (Uri.parse ("content://sms/"), New string[]{"* from Sms;select * from Thrreads; -- "}, NULL, NULL, NULL);
Unfortunately, only the first SQL statement was run, and Android seems to have some control over the key issues.
But support--also very good, so you can query all the tables in the database, but also can be multi-table