(a) Foreword
Android defaults to provide contact backup to SD card functions (code in the Com.android.vcard package), we can export the contact to a. vcf file exists in SD card; If you change the phone, we can import the contact from the SD card file. So, can we do the same thing with the phone records? The answer is YES!
(ii) export of call records
Since it is a backup call record, it will certainly include the export and import functions, here we start with the export call records.
1. According to the specifications derived from the call records, the exported files generally end with the. VCL suffix, the middle content is
Copy Code code as follows:
Begin:vcall
slot:0//Card slot No. 0: Tanka mobile phone 1: SIM card slot 1 2: Dual sim Mobile card slot 2
TYPE:1//Telephone type 1: Access telephone, 2: Outgoing call 3: not answering the phone
DATE:2013/02/12 14:11:12 GMT//Call or go to point time backup to GMT time record, show mobile time zone corresponding
NUMBER:+86134XXXXX//Offset number
Duration:5//Duration, number of seconds
End:vcall
So here's the storage format for a call record, ending with Begin:vcall start End:vcall. Represents the meaning of the field, but is not imported into the actual file to make it understandable. So let's see how we actually export it.
2. Query Call record list
Ok.. Now that you're saving your call logs, you first need to check the call history.
Android provides a calllogprovider to meet this need, it is configured in the system name is "Call_log", so you can only provide a URI such as the query, such as:
Copy Code code as follows:
Uri uri = uri.parse ("Context://call_log/calls");
Cursor C = mcontext.getcontentresolver (). Query (URI, xxx, xxx);
This allows you to query all the phone records and get the cursor.
3. Peel out the fields and data you want to save from the cursor and write to the file
Now that the cursor is found, the next step is to find the field data from the cursor that we want to write to the file, for example, basically as follows:
Copy Code code as follows:
Protected object Doinbackground (Object ... params) {//Background asynchronous task, background query data and write file, each export a record, update progress bar
Super.doinbackground (params);
String path = (string) params[0];
Uri Queryuri = Uri.parse ("Content://call_log/calls");
Cursor queryedcursor = Mcontext.getcontentresolver (). Query (Queryuri,
Null
Null
Null
NULL);
if (queryedcursor = null | | queryedcursor.getcount () = 0) {
return-1;
}
object[] message = new OBJECT[1];
Message[0] = Queryedcursor.getcount ();
publishprogress (message);
StringBuilder sb = new StringBuilder ();
OutputStream outputstream = null;
Writer Writer = null;
try {
OutputStream = new FileOutputStream (path);
writer = new BufferedWriter (new OutputStreamWriter (OutputStream));
For (Queryedcursor.movetofirst ();!queryedcursor.isafterlast ();
Queryedcursor.movetonext ()) {
if (mcancel) {
Break
}
Sb.setlength (0);
Sb.append ("Begin:vcall"). Append ("\ n");
int subId = Queryedcursor.getint (Queryedcursor.getcolumnindex ("sub_id"));
int CallType = Queryedcursor.getint (
Queryedcursor.getcolumnindex ("type")); Incall/outcall/missed Call
Long date = Queryedcursor.getlong (Queryedcursor.getcolumnindex ("date"));
String Gmtdata = getgtmdatetimestring (date);
String number = queryedcursor.getstring (Queryedcursor.getcolumnindex ("Formatted_number"));
String Duration = queryedcursor.getstring (Queryedcursor.getcolumnindex ("duration"));
Sb.append ("SLOT:"). Append (SubId). Append ("\ n");
Sb.append ("TYPE:"). Append (CallType). Append ("\ n");
Sb.append ("DATE:"). Append (Gmtdata). Append ("\ n");
Sb.append ("Number:"). Append (number) append ("\ n");
Sb.append ("DURATION:"). Append (DURATION). Append ("\ n");
Sb.append ("End:vcall"). Append ("\ n");
Writer.write (Sb.tostring ()); Write a record to a file
Message[0] =-1;
publishprogress (message); Publish message, let main thread update progress bar
}
catch (Exception e) {
LOG.D (TAG, "", e);
return 0;
}finally{
try {
if (writer!= null) {
Writer.close ();
}
if (OutputStream!= null) {
Outputstream.close ();
}
catch (Exception E2) {
LOG.D (TAG, "", E2);
return 0;
}
}
return 1;
}
This is just the general code, if you have future needs, you can arbitrarily modify the above without the need to know the author. No need to copyright ha ~ ~ ~
(iii) Import call log to Database
1. Well, if you import it, you first have to search for a file in the SD card that ends with a. vcl suffix, hmm! Start a thread, iterate the search. As follows:
Copy Code code as follows:
Private class Vclscanthread extends thread implements Oncancellistener, Onclicklistener {//boot thread to search, and pop-up progress bar to the user
Private Boolean mcanceled; Variable flag whether the user has cancel the search process
Private Boolean mgotioexception;
Private File mrootdirectory;
private static final String Log_tag = "Vclscanthread";
To avoid recursive link.
Private set<string> mcheckedpaths;
Private class Canceledexception extends Exception {
}
Public Vclscanthread (File sdcarddirectory, String scantype) {
mcanceled = false;
Mgotioexception = false;
Mrootdirectory = sdcarddirectory;
Mcheckedpaths = new hashset<string> ();
Mprogressdialogforscanvcard = new ProgressDialog (main.this);
Mprogressdialogforscanvcard.settitle (R.string.dialog_scan_calllist_progress_title);
Mprogressdialogforscanvcard.show (); Pop-up Search progress bar
}
@Override
public void Run () {
if (mallvclfilelist = = null) {
Mallvclfilelist = new vector<vclfile> (); To start the search, first clear the list, which is used to save the found. vcl file (including file name, file path, etc.)
}else{
Mallvclfilelist.clear ();
}
try {
Getvcardfilerecursively (mrootdirectory); Iterate through all the. vcl files in the SD card
catch (Canceledexception e) {
Mcanceled = true;
catch (IOException e) {
Mgotioexception = true;
}
if (mcanceled) {
Mallvclfilelist = null;
}
Mprogressdialogforscanvcard.dismiss ();
Mprogressdialogforscanvcard = null;
if (mgotioexception) {
Runonuithread (New Dialogdisplayer (r.id.dialog_io_exception));
else if (mcanceled) {
Finish ();
} else {
int size = Mallvclfilelist.size ();
if (size = = 0) {
Toast.maketext (Main.this, R.string.error_scan_vcl_not_found,
Toast.length_short). Show ();
} else {
Runonuithread (New Runnable () {
@Override
public void Run () {
Startvcardselectandimport (); After the search is complete, the pop-up dialog lets the user choose to import those files
}
});
}
}
}
private void getvcardfilerecursively (File directory)
Throws Canceledexception, IOException {
if (mcanceled) {
throw new Canceledexception ();
}
e.g. secured directory may return null toward Listfiles ().
Final file[] files = directory.listfiles ();
if (files = null) {
Final String Currentdirectorypath = Directory.getcanonicalpath ();
Final String Securedirectorypath =
Mrootdirectory.getcanonicalpath (). Concat (Secure_directory_name);
if (! Textutils.equals (Currentdirectorypath, Securedirectorypath)) {
LOG.W (Log_tag, "listfiles () returned null (directory: + directory +)");
}
Return
}
For (File file:directory.listFiles ()) {
if (mcanceled) {
throw new Canceledexception ();
}
String Canonicalpath = File.getcanonicalpath ();
if (Mcheckedpaths.contains (Canonicalpath)) {
Continue
}
Mcheckedpaths.add (Canonicalpath);
String endfix = ". VCL";
if (File.isdirectory ()) {
getvcardfilerecursively (file); If it is a directory, continue with the iterative search
else if (Canonicalpath.tolowercase (). EndsWith (Endfix) &&//If it is a file, determine whether the filename ends with a. VCL, if it is, and is readable, into the search list.
File.canread ()) {
String fileName = File.getname ();
Vclfile vclfile = new Vclfile (
FileName, Canonicalpath, file.lastmodified ());
Mallvclfilelist.add (Vclfile);
}
}
}
public void OnCancel (Dialoginterface dialog) {
Mcanceled = true;
}
public void OnClick (Dialoginterface dialog, int which) {
if (which = = dialoginterface.button_negative) {
Mcanceled = true;
}
}
}
2. Select Good to import the file, that is, parsing the file, parsing a begin:vcall and End:vcall, after a database (you can also parse a number of articles after a one-time deposit in the database)
Copy Code code as follows:
private void Parseiteminter (string name, String value) throws exception{
if ("SLOT". Equalsignorecase (name)) {
Mvalues.put ("sub_id", value);
}else if ("TYPE". Equalsignorecase (name)) {
Mvalues.put ("type", value);
}else if ("DATE". Equalsignorecase (name)) {
Mvalues.put ("Date", Getgtmdatetime (value));
}else if ("number". Equalsignorecase (name)) {
Mvalues.put ("Formatted_number", value);
Mvalues.put ("number", value);
}else if ("DURATION". Equalsignorecase (name)) {
Mvalues.put ("duration", value);
}else{
throw new Exception ("Unknown type, Name:" + name + "Value:" + value);
}
}
Submit a call log information to the database
Uri uri = uri.parse ("Content://call_log");
Mcontext.getcontentresolver (). Insert (URI, mvalues);
This is the meaning of the general, but the specific details, but also to control. For example, the file is illegal, not the beginning of the Begin:vcall, and so on. We also need control.
Generally so much, I hope to be able to do this in the future when a little reference ...