android forensic
<p>I would like to retrieve the browser history from the com.android.browser and save it into a file in sdcard. I am able to do soo for the contacts but not the browser history.Don't know what went wrong. They only prompt the error <strong><em>bind or column index out of range: handle 0x27a6d0</em></strong>.</p>

<p>What would be the best format for the file to be xml, txt or??</p>

<p><strong>These are my codes</strong></p>

<pre><code>package fypj.ReadContacts;

import android.app.Activity;
import android.os.Bundle;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;

import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Browser;
import android.provider.Browser.BookmarkColumns;
import android.provider.ContactsContract;
import android.util.Log;
import android.widget.TextView;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;

public class ReadContacts extends Activity {

   // To suppress notational clutter and make structure clearer, define some shorthand constants.

   private static final Uri URI = ContactsContract.Contacts.CONTENT_URI;
   private static final Uri PURI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
   private static final Uri EURI = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
   private static final Uri AURI = ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI;
   private static final String ID = ContactsContract.Contacts._ID;
   private static final String DNAME = ContactsContract.Contacts.DISPLAY_NAME;
   private static final String HPN = ContactsContract.Contacts.HAS_PHONE_NUMBER;
   private static final String LOOKY = ContactsContract.Contacts.LOOKUP_KEY;
   private static final String CID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;

   private static final String EID = ContactsContract.CommonDataKinds.Email.CONTACT_ID;
   private static final String AID = ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID;
   private static final String PNUM = ContactsContract.CommonDataKinds.Phone.NUMBER;
   private static final String PHONETYPE = ContactsContract.CommonDataKinds.Phone.TYPE;
   private static final String EMAIL = ContactsContract.CommonDataKinds.Email.DATA;
   private static final String EMAILTYPE = ContactsContract.CommonDataKinds.Email.TYPE;
   private static final String STREET = ContactsContract.CommonDataKinds.StructuredPostal.STREET;
   private static final String CITY = ContactsContract.CommonDataKinds.StructuredPostal.CITY;
   private static final String STATE = ContactsContract.CommonDataKinds.StructuredPostal.REGION;
   private static final String POSTCODE = ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE;
   private static final String COUNTRY = ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY;

   private static final Uri URI1 = android.provider.Browser.BOOKMARKS_URI;
   private static final String bHistoryTITLE = Browser.BookmarkColumns.TITLE;
   private static final String bHistoryURL = Browser.BookmarkColumns.URL;
   private static final String bHistoryBOOKMARK = Browser.BookmarkColumns.BOOKMARK;
   private static final String bHistoryVISITS = Browser.BookmarkColumns.VISITS;
   private static final String ID1 = Browser.BookmarkColumns._ID    ;
   //private static final String BID = Browser.BookmarkColumns.
   //private static final String DNAME = Browser.BookmarkColumns.DISPLAY_NAME;
   //private static final String HPN = ContactsContract.Contacts.HAS_PHONE_NUMBER;
   //private static final String LOOKY = Browser.BookmarkColumns.LOOKUP_KEY;

   private String id;
   private String lookupKey;
   private String name;
   private String street;
   private String city;
   private String state;
   private String postcode;
   private String country;
   private String ph[];
   private String phType[];
   private String em[];
   private String emType[];

   private String id1;
   private String URL;
   private String BTitle;
   private String BURL;
   private String BBOOKMARK;
   private String BVISITS;
   private String browserTITLE[];
   private String browserURL[];
   private String browserBOOKMARK[];
   private String browserVISITS[];

   private File root;
   private int emcounter;
   private int phcounter;
   private int addcounter;



   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);




      // Check that external media available and writable
      checkExternalMedia();
      Contacts();
      browser();

   }


   /**  Method to check whether external media available and writable and to find the
      root of the external file system. */   

   private void checkExternalMedia () {
      // Check external media availability.  This is adapted from
      // http://developer.android.com/guide/topics/data/data-storage.html#filesExternal
      boolean mExternalStorageAvailable = false;
      boolean mExternalStorageWriteable = false;
      String state = Environment.getExternalStorageState();

      if (Environment.MEDIA_MOUNTED.equals(state)) {
         // We can read and write the media
         mExternalStorageAvailable = mExternalStorageWriteable = true;
      } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
         // We can only read the media
         mExternalStorageAvailable = true;
         mExternalStorageWriteable = false;
      } else {
         // Can't read or write
         mExternalStorageAvailable = mExternalStorageWriteable = false;
      }

      // Find the root of the external storage and output external storage info to screen   
      root = android.os.Environment.getExternalStorageDirectory(); 

   }
   public void Contacts(){
    // Allow for up to 5 email and phone entries for a contact
          em = new String[5];
          emType = new String[5];
          ph = new String[5];
          phType = new String[5];

          /** Open a PrintWriter wrapping a FileOutputStream so that we can send output from a
          query of the Contacts database to a file on the SD card.  Must wrap the whole thing 
          in a try-catch to catch file not found and i/o exceptions. Note that since we are writing
          to external media we must add a WRITE_EXTERNAL_STORAGE permission to the 
          manifest file.  Otherwise  a FileNotFoundException will be thrown. */

          // This will set up output to /sdcard/download/phoneData.txt if /sdcard is the root of
          // the external storage.  See the project WriteSDCard for more information about
          // writing to a file on the SD card.

          File dir = new File (root.getAbsolutePath() + "/download");
          dir.mkdirs();
          //File file = new File(dir, "phoneData.rtf");
          File file = new File(dir, "phoneData.accdb");


          try{
             FileOutputStream f = new FileOutputStream(file);
             PrintWriter pw = new PrintWriter(f);

             // Main loop to query the contacts database, extracting the information.  See
             // http://www.higherpass.com/Android/Tutorials/Working-With-Android-Contacts/

             ContentResolver cr = getContentResolver();
             Cursor cu = cr.query(URI, null, null, null, null);
             if (cu.getCount() &gt; 0) {   

                // Loop over all contacts
                while (cu.moveToNext()) {   

                   // Initialize storage variables for the new contact
                   street = "";
                   city = "";
                   state = "";
                   postcode = "";
                   country = "";

                   // Get ID information (id, name and lookup key) for this contact. id is an identifier
                   // number, name is the name associated with this row in the database, and
                   // lookupKey is an opaque value that contains hints on how to find the contact 
                   // if its row id changed as a result of a sync or aggregation.

                   id = cu.getString(cu.getColumnIndex(ID));
                   name = cu.getString(cu.getColumnIndex(DNAME));          
                   lookupKey = cu.getString(cu.getColumnIndex(LOOKY));              
                   // Append list of contacts to the scrollable TextView on the screen.



                   // Query phone numbers for this contact (may be more than one), so use a 
                   // while-loop to move the cursor to the next row until moveToNext() returns
                   // false, indicating no more rows. Store the results in arrays since there may
                   // be more than one phone number stored per contact. The if-statement
                   // enclosing everything ensures that the contact has at least one phone 
                   // number stored in the Contacts database.

                   phcounter = 0;
                   if (Integer.parseInt(cu.getString(cu.getColumnIndex(HPN))) &gt; 0) {                
                      Cursor pCur = cr.query(PURI,  null, CID + " = ?",  new String[]{id}, null);
                      while (pCur.moveToNext()) {
                         ph[phcounter] = pCur.getString(pCur.getColumnIndex(PNUM));
                         phType[phcounter]  = pCur.getString(pCur.getColumnIndex(PHONETYPE)); 
                         phcounter ++;
                      } 
                      pCur.close();
                   }

                   // Query email addresses for this contact (may be more than one), so use a 
                   // while-loop to move the cursor to the next row until moveToNext() returns
                   // false, indicating no more rows. Store the results in arrays since there may
                   // be more than one email address stored per contact.

                   emcounter = 0;
                   Cursor emailCur = cr.query(EURI, null, EID + " = ?",  new String[]{id}, null); 
                   while (emailCur.moveToNext()) { 
                      em[emcounter] =  emailCur.getString(emailCur.getColumnIndex(EMAIL));
                      emType[emcounter] =  emailCur.getString(emailCur.getColumnIndex(EMAILTYPE));
                      emcounter ++;
                   } 
                   emailCur.close();

                   // Query Address (assume only one address stored for simplicity). If there is
                   // more than one address we loop through all with the while-loop but keep
                   // only the last one.

                   addcounter = 0;
                   Cursor addCur = cr.query(AURI, null, AID + " = ?",  new String[]{id}, null); 
                   while (addCur.moveToNext()) { 
                      street = addCur.getString(addCur.getColumnIndex(STREET));
                      city = addCur.getString(addCur.getColumnIndex(CITY));
                      state = addCur.getString(addCur.getColumnIndex(STATE));
                      postcode = addCur.getString(addCur.getColumnIndex(POSTCODE));
                      country = addCur.getString(addCur.getColumnIndex(COUNTRY));
                      addcounter ++;
                   } 
                   addCur.close();

                   // Write identifiers for this contact to the SD card file
                        //pw.println(name+" ID="+id+" LOOKUP_KEY="+lookupKey);
                   pw.println(name);
                   // Write list of phone numbers for this contact to SD card file
                   for(int i=0; i&lt;phcounter; i++){
                      //pw.println("   phone="+ ph[i]+" type="+phType[i] + " ("
                         //+ getPhoneType(phType[i]) + ") ");
                       pw.println("   phone="+ ph[i]+" ("
                               + getPhoneType(phType[i]) + ") ");
                   }
                   // Write list of email addresses for this contact to SD card file
                   for(int i=0; i&lt;emcounter; i++){
                      pw.println("   email="+ em[i]+" type="+emType[i] + " ("
                         + getEmailType(emType[i]) + ") ");
                   }
                   // If street address is stored for contact, write it to SD card file
                   if(addcounter &gt; 0){
                      if(street != null) pw.println("   street="+street);
                      if(city != null) pw.println("   city="+city);
                      if(state != null) pw.println("   state/region="+state);
                      if(postcode != null) pw.println("   postcode="+postcode);
                      if(country != null) pw.println("   country="+country);
                   }
                }
             }       
             // Flush the PrintWriter to ensure everything pending is output before closing
             pw.flush();
             pw.close();
             f.close();       
          } catch (FileNotFoundException e) {
             e.printStackTrace();
             Log.i("MEDIA", "*************** File not found. Did you" +
                " add a WRITE_EXTERNAL_STORAGE permission to the manifest file? ");
          } catch (IOException e) {
                e.printStackTrace();
          } 
   }

   /** Method to return label corresponding to phone type code. Data for correspondence from
      http://developer.android.com/reference/android/provider/ContactsContract.CommonDataKinds.Phone.html */

   private String getPhoneType(String index){
      if(index.trim().equals( "1")){
         return "home";
      } else if (index.trim().equals("2")){
         return "mobile";
      } else if (index.trim().equals("3")){
         return "work";
      } else if (index.trim().equals("7")){
         return "other";
      } else {
         return "?";
      }
   }  

   /** Method to return label corresponding to email type code. Data for correspondence from
      http://developer.android.com/reference/android/provider/ContactsContract.
      CommonDataKinds.Email.html  */

   private String getEmailType(String index){
      if(index.trim().equals( "1")){
         return "home";
      } else if (index.trim().equals("2")){
         return "work";
      } else if (index.trim().equals("3")){
         return "other";
      } else if (index.trim().equals("4")){
         return "mobile";
      } else {
         return "?";
      }
   }

   public void browser(){
       //create file
       File dir = new File (root.getAbsolutePath() + "/DATASTOREAGE");
          dir.mkdirs();
          File file = new File(dir, "browserHistory.rtf");

          try{
             FileOutputStream f = new FileOutputStream(file);
             PrintWriter pw = new PrintWriter(f);

             // Main loop to query the contacts database, extracting the information.  See
             // http://www.higherpass.com/Android/Tutorials/Working-With-Android-Contacts/

             ContentResolver cr = getContentResolver();
             Cursor cu = cr.query(URI1, null, null, null, null);
             if (cu.getCount() &gt; 0) {   

                // Loop over all contacts
                while (cu.moveToNext()) {   

                   // Initialize storage variables for the new contact
                   BTitle = "";
                   BURL = "";
                   BBOOKMARK = "";
                   BVISITS = "";

                   // Get ID information (id, name and lookup key) for this contact. id is an identifier
                   // number, name is the name associated with this row in the database, and
                   // lookupKey is an opaque value that contains hints on how to find the contact 
                   // if its row id changed as a result of a sync or aggregation.

                   id1 = cu.getString(cu.getColumnIndex(ID1));
                   URL = cu.getString(cu.getColumnIndex(BookmarkColumns.TITLE));          
                   //lookupKey = cu.getString(cu.getColumnIndex(LOOKY));            
                   // Append list of contacts to the scrollable TextView on the screen.



                   // Query phone numbers for this contact (may be more than one), so use a 
                   // while-loop to move the cursor to the next row until moveToNext() returns
                   // false, indicating no more rows. Store the results in arrays since there may
                   // be more than one phone number stored per contact. The if-statement
                   // enclosing everything ensures that the contact has at least one phone 
                   // number stored in the Contacts database.

                   phcounter = 0;

                      Cursor bCur = cr.query(URI1,  null, ID1,  new String[]{id1}, null);
                      while (bCur.moveToNext()) {
                         browserTITLE[phcounter] = bCur.getString(bCur.getColumnIndex(bHistoryTITLE));
                         browserURL[phcounter]  = bCur.getString(bCur.getColumnIndex(bHistoryURL));
                         browserBOOKMARK[phcounter]  = bCur.getString(bCur.getColumnIndex(bHistoryBOOKMARK));
                         browserVISITS[phcounter]  = bCur.getString(bCur.getColumnIndex(bHistoryVISITS));
                         phcounter ++;
                      } 
                      bCur.close();
                   }





                   // Write identifiers for this contact to the SD card file
                        //pw.println(name+" ID="+id+" LOOKUP_KEY="+lookupKey);
                   pw.println(BTitle+" ID="+id1+" LOOKUP_KEY="+lookupKey);
                   pw.println(BURL);
                   pw.println(BBOOKMARK);
                   pw.println(BVISITS);
                }

             // Flush the PrintWriter to ensure everything pending is output before closing
             pw.flush();
             pw.close();
             f.close();       
          } catch (FileNotFoundException e) {
             e.printStackTrace();
             Log.i("MEDIA", "*************** File not found. Did you" +
                " add a WRITE_EXTERNAL_STORAGE permission to the manifest file? ");
          } catch (IOException e) {
                e.printStackTrace();
          } 
   }

}
</code></pre>
