Export Contacts Example

This example shows how to export contacts on a suitably equipped device.

A screenshot of the application.

We begin by importing the classes and modules needed by our application.

from java.io import File, FileWriter
from java.util import HashMap
from android.content import Context
from android.net import Uri
from android.os import Environment
from android.provider import ContactsContract
from android.view import View, ViewGroup
from android.widget import Button, ScrollView, TextView

We also use a custom activity class and a convenience widget from the serpentine package.

from serpentine.activities import Activity
from serpentine.widgets import VBox

We define a class based indirectly on the standard Activity class. This represents the application, and will be used to present a graphical interface to the user.

class ExportContactsActivity(Activity):

    __interfaces__ = [View.OnClickListener]

The initialisation method only needs to call the corresponding method in the base class.

    def __init__(self):
    
        Activity.__init__(self)

The onCreate method is called when the activity is created. Our implementation calls the onCreate method of the base class, queries the available telephony features and displays them in a graphical layout.

    def onCreate(self, bundle):
    
        Activity.onCreate(self, bundle)
        
        self.exportButton = Button(self)
        self.exportButton.setText("Export contacts")
        self.exportButton.setEnabled(True)
        self.exportButton.setOnClickListener(self)
        
        scrollView = ScrollView(self)
        self.textView = TextView(self)
        scrollView.addView(self.textView)

The widgets are added to a convenience widget from the serpentine package.

        vbox = VBox(self)
        vbox.addView(self.exportButton)
        vbox.addView(scrollView)

The VBox widget is used as the main user interface in the activity.

        self.setContentView(vbox)

We implement the following method to implement the View.OnClickListener interface. The method is called when the user clicks the send button.

    def onClick(self, view):
    
        self.exportButton.setEnabled(False)
        
        resolver = self.getContentResolver()
        cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI,
                                None, None, None, None)
        
        l = cursor.getCount()
        
        i = 0
        while i < l:
            cursor.moveToPosition(i)
            columns = cursor.getColumnCount()
            
            d = {}
            
            j = 0
            while j < columns:
                name = cursor.getColumnName(j)
                value = cursor.getString(j)
                
                # Avoid storing null values in the dictionary to prevent later
                # problems extracting them.
                if value != None:
                    d[name] = value
                
                j += 1
            i += 1
            
            d["phone number"] = self.getContact(d["lookup"],
                ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
                ContactsContract.CommonDataKinds.Phone.NUMBER)
            
            d["company"] = self.getContact(d["lookup"],
                ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE,
                ContactsContract.CommonDataKinds.Organization.COMPANY)
            
            self.saveFile(d["sort_key"], d)
    
        self.exportButton.setEnabled(True)
    
    @args(str, [str, str, str])
    def getContact(self, key, mimetype, column):
    
        resolver = self.getContentResolver()
        cursor = resolver.query(ContactsContract.Data.CONTENT_URI,
            array([column]),
            ContactsContract.ContactsColumns.LOOKUP_KEY + "='" + key + "'"
            " AND " + ContactsContract.Data.MIMETYPE + "='" + mimetype + "'",
            None, None)
        
        if not cursor.moveToFirst():
            return ""
        
        if cursor.getColumnCount() < 1:
            return ""
        
        return str(cursor.getString(0))

The saveFile method is a simple utility method that creates and writes a file in the device's external storage area, creating a directory to hold the file if required.

    @args(void, [str, HashMap(str, str)])
    def saveFile(self, name, data):
    
        if Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED:
            return
        
        storageDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_DOWNLOADS)

Create a directory for this example and subdirectories for the message threads.

        dir = File(storageDir, "ExportContacts")
        if not dir.exists():
            if not dir.mkdirs():
                return
        
        f = File(dir, name)
        
        stream = FileWriter(f, False)
        
        for key in data.keySet().toArray():
            
            stream.write(key + "\n")
            value = data[key]
            if value != None:
                stream.write(value + "\n\n")
        
        stream.flush()
        stream.close()
        
        text = str(self.textView.getText())
        self.textView.setText(text + "\nSaved " + f.getAbsolutePath())

Files