×
Namespaces

Variants
Actions

Archived:Python on Symbian/12. Platform Services

From Nokia Developer Wiki
Jump to: navigation, search

Archived.pngAquivado: Este artigo foi arquivado, pois o conteúdo não é mais considerado relevante para se criar soluções comerciais atuais. Se você achar que este artigo ainda é importante, inclua o template {{ForArchiveReview|escreva a sua justificativa}}.

All PySymbian articles have been archived. PySymbian is no longer maintained by Nokia and is not guaranteed to work on more recent Symbian devices. It is not possible to submit apps to Nokia Store.

Article Metadata
Article
Created: hamishwillee (30 Nov 2010)
Last edited: hamishwillee (08 May 2013)

Original Authors: Pankaj Nathani and Bogdan Galiceanu

This chapter explains how to access platform services through the generic scriptext API. The services provided include:

  • Application manager
  • Calendar
  • Contacts
  • Landmarks
  • Location
  • Logging
  • Messaging
  • Media management
  • Sensors
  • System information.

Contents

Introduction

Python on Symbian provides access to many platform services through platform specific modules. In earlier chapters we showed how to use modules including calendar, messaging, logs, location, positioning, sensor and others.

Python on Symbian also provides access to platform services through a simple generic API defined in the scriptext module. These services include the application manager, calendar, contacts, landmarks, location, logging, messaging, media management, sensors and system information.

The functionality provided by each of these mechanisms has considerable overlap, and in many cases it is possible for developers to choose which API better suits their programming style. In other cases the APIs are complementary - for example, the logs module can only read log entries while the scriptext API can also be used to create and delete log entries. Therefore, both the platform services (scriptext) and individual platform service modules are required to gain full access to all of the platform service functionality offered by Symbian devices.

Figure 12.1 shows the range of services offered.

Figure 12.1: Platform services

Loading and calling platform services

Platform services can be accessed in PySymbian using the scriptext module. Scriptext uses two simple methods load() and call() to initiate and using the services respectively.

Load

A service object can be instantiated using the load() method. The syntax for using the API is as follows:

import scriptext
scriptext_handle = scriptext.load(<provider>, <interface>)

Here, <provider> is a string specifying the name of the service provider (for example 'Service.AppManager') and <interface> is a string specifying one of the names of supported interfaces of the <provider> (e.g. 'IAppManager')

For example, to load the messaging service with its supported interface IMessaging we do the following:

import scriptext
messaging_handle = scriptext.load("Service.Messaging", "IMessaging")

Call

The call() method is used to request a service or operation from a service provider. The request may be synchronous or asynchronous. The syntax for requesting synchronous services is:

result = service_instance_object.call(<operation>, parameters)

where <operation> specifies the requested service and parameters is a dictionary specifying input parameters for the requested service. In the following code, GetList is the <operation> and {'Type': u'Inbox'} represents the parameters.

sms_iter = messaging_handle.call('GetList', {'Type': u'Inbox'})

GetList is the name of the request and Inbox is the argument for the services. The code returns all of the SMS in the inbox in a map, which may be iterated and can be used for retrieving more details.

The syntax of the call() method for requesting asynchronous services is:

 result = service_instance_object.call(<operation>, parameters, callback=callback_function)

In addition to operation and parameter arguments, an asynchronous service also needs a callback function that is called when the the service completes the asynchronous request. The callback function can be any user-defined function, for example:

import scriptext
 
def media_callback(trans_id, event_id, output_params):
print trans_id
print event_id
print output_params
 
media_handle = scriptext.call('Service.MediaManagement', 'IDataSource')
 
media_trans_id = media_handle.call('GetList', {'Type': u'FileInfo', u'FileExtension', 'StartRange': u'.mp3'},'Sort': {'Key': u'FileName', 'Order': u'Ascending'}}, callback=media_callback)

The preceding code requests the list of mp3 files from the media player in an ascending order and then prints them. The callback function media_callback is called for every mp3 file that is found.

The callback function that is called after an asynchronous service request has three arguments (you must define your callback to take three parameters!):

  • transactionID - the unique transaction ID associated with the particular asynchronous request. It is returned as part of the result of the initial asynchronous call.
  • eventID - the status of the asynchronous operation. The values of an event id can include
  • outParam - contains the output of the asynchronous call in a dictionary object.
    • outParam['ReturnValue'] - information requested by the asynchronous call that initiated the callback. Not all asynchronous calls return this property. The existence of 'ReturnValue' depends on the platform service API and the method that was called. If ReturnValue is not present, the outParam would only contain ErrorCode and ErrorMessage.
    • outParam['ErrorCode'] - Specifies an error code. A complete list of pre-defined error codes is available here.
    • outParam['ErrorMessage'] - describes the error message.

To cancel an outstanding asynchronous request, Cancel is passed as an argument to the call function as illustrated in the following code fragment:

serviceInstance.call('Cancel', {'TransactionID': serviceTransactionID})

For example, the following line shows how we cancel the asynchronous request made in the preceding code snippet.

media_handle.call('Cancel', {'TransactionID': media_trans_id })

Application manager

The application manager service allows us to retrieve information about the installed applications and to launch applications and specific documents. The basic services GetList, LaunchApp and LaunchDoc are illustrated in Figure 12.2.

Figure 12.2: Application manager services

The application manager API has to be loaded before using any of the services it provides:

import scriptext
appmanager_handle = scriptext.load('Service.AppManager', 'IAppManager')

GetList

GetList can be used in synchronous mode to retrieve information about the all applications, user installed packages and handler applications. The following code example shows how GetList is used.

import scriptext
 
#initialize empty list for application info
application_info= []
#Load the Application Manager API
appmanager_handle = scriptext.load('Service.AppManager', 'IAppManager')
# Call the GetList function
appmanager_info = appmanager_handle.call('GetList', {'Type': u'Application'})
# Populate the empty list with information of installed applications
for item in appmanager_info:
application_info= .append(item['UID'])
application_info= .append(item['Path'])
application_info= .append(item['Caption'])
application_info= .append(item['ShortCaption'])
print application_info

LaunchApp

LaunchApp can be used both synchronously and asynchronously to launch an application. It takes the UID of the application as an argument.

The code fragment shows how to use LaunchApp to synchronously launch the application with UID 0xE674C90B:

appmanager_id = appmanager_handle.call('LaunchApp', {'ApplicationID': u's60uid:// 0xE674C90B'})

The same application can be launched asynchronously by doing this:

appmanager_id = appmanager_handle.call('LaunchApp', {'ApplicationID': u's60uid:// 0xE674C90B'},  callback= callback_function)

In this case, callback_function is called once the application has launched.

LaunchDoc

Like LaunchApp, LaunchDoc can also be used either synchronously or asynchronously to launch a document in embedded mode. It takes the document path, MimeType (optional) and options (optional) as an argument.

The next code fragment shows how to call LaunchDoc synchronously, specifying a JPG image to be displayed.

appmanager_id = appmanager_handle.call('LaunchDoc', {'Document': {'DocumentPath': u'C:\\data\\Image.jpg'}})

The following line of code would launches the jpg image viewer asynchronously to display Image.jpg. When the image has launched the callback_function is called.

appmanager_id = appmanager_handle.call('LaunchDoc', {'Document': {'DocumentPath': u'C:\\data\\Image.jpg'}}, callback= callback_function)

Calendar

The calendar service API enables Python developers to access, create, and manage calendars and their entries stored on a device. As shown in Figure 12.3, calendar services API provides 6 services: GetList, Add, Delete, Import, Export and RequestNotification.

Figure 12.3: Calendar services

The Calendar API has to be loaded before using any of the services it provides. Use Service.Calendar to identify the service provider and IDataSource to identify the supported interface, as illustrated in the following code.

import scriptext
calendar_handle = scriptext.load('Service.Calendar', 'IDataSource')

GetList

The GetList service can be used synchronously to retrieve a list of available calendars or a list of calendar entries. The information to be retrieved can filtered by the arguments passed when using the service. Entries in the calendar can be of type Meeting, ToDo, Anniversary, DayEvent and Reminder.

For example, the following code can be used to list all the ToDo entries in the calendar.

ToDo_list = calendar_handle.call('GetList', {'Type': u'CalendarEntry', 'Filter': {'CalendarName': u'C:Calendar', 'Type': u'ToDo'}})

Once a list of events is retrieved using GetList, various attributes of the events can be queried.

For example, the following code snippet retrieves a list of ToDo events and prints some of its attributes. Please refer to the http://pys60.garage.maemo.org/doc/s60/node128.html for more information on attributes of event types.

import scriptext
 
# Load Calendar service
calendar_handle = scriptext.load('Service.Calendar', 'IDataSource')
ToDo_list = calendar_handle.call('GetList', {'Type': u'CalendarEntry', 'Filter': {'CalendarName': u'C:Calendar', 'Type': u'ToDo'}})
for ToDo in ToDo_list:
print 'Id = ' + ToDo['id']
print 'Summary = ' + ToDo[‘Summary’]
 
value = ToDo['EndTime']
print "ToDo End time is ", value.day, value.month, value.year, value.hour, ":", value.minute, ":", value.second
 
value = meeting['AlarmTime']
print "ToDo Alarm time is ", value.day, value.month, value.year, value.hour, ":", value.minute, ":", value.second
 
print ‘Status =’ + ToDo[‘Status’]

Add

Add is used synchronously to add a new calendar, new calendar entries, or to modify an existing calendar entry on the device.

For example, the following code adds a To Do entry to the calendar:

alarm_time = datetime.datetime(2009,12,12,13,0,0)
end_time = datetime.datetime(2009,12,12,14,0,0)
 
calendar_handle.call('Add', {'Type': u'CalendarEntry', 'Item': {'Type': u'ToDo', 'Summary': u'This is the ToDo Summary', 'EndTime': end_time, 'AlarmTime': end_time}})

Other event entries, such as Meeting, Anniversary, DayEvent and Reminder can be added to the calendar in a similar manner. The attributes specified may vary for different event type entries. Please refer to http://pys60.garage.maemo.org/doc/s60/node121.html for more information on the attributes of event types.

An existing entry may be modified by specifying the id as an argument.

Delete

Delete can be used either synchronously or asynchronously to remove/delete a calendar or a calendar entry from the device. The default calendar of the device cannot be deleted.

Using Delete synchronously:

event_id = calendar_handle.call('Delete', {'Type': u'CalendarEntry', 'id': del_id_list})

Using Delete asynchronously,

event_id = calendar_handle.call('Delete', {'Type': u'CalendarEntry', 'id': del_id_list}, callback= callback_function)

where del_id_list is the list of the entries to be deleted and callback_function is the user defined callback function.

For example, the following code asynchronously deletes all ToDo entries from the calendar:

import scriptext
 
# Load Calendar service
calendar_handle = scriptext.load('Service.Calendar', 'IDataSource')
 
# Populate ToDo_list with all the ToDo entries in the calendar
ToDo_list = calendar_handle.call('GetList', {'Type': u'CalendarEntry', 'Filter': {'CalendarName': u'C:Calendar', 'Type': u'ToDo'}})
 
# Callback function will be called when the requested service is complete
def callback_function(trans_id, event_id, input_params):
print “Entry Deleted”
 
# Delete the entries in ToDo_list
event_id = calendar_handle.call('Delete', {'Type': u'CalendarEntry', 'IdList': ToDo_list}, callback= callback_function)
 
print “Waiting for the request to be completed”
lock.wait()
print “Request Complete”

Import

The Import service can be used synchronously or asynchronously to import entries into the calendar from a file. Currently, the file formats supported by import service are ICal or VCal.

The following code fragment shows how to use Import synchronously:

calendar_handle.call('Import', {'Type': u'CalendarEntry', 'FileName': u'C:\\data\\Imported.txt', 'Format': u'ICal'})

The code imports calendar entries in ICal format from Imported.txt. The same format must be used while exporting the entries to the calendar using the Export service.

To use Import asynchronously:

calendar_handle.call('Import', {'Type': u'CalendarEntry', 'FileName': u'C:\\data\\ Imported.txt', 'Format': u'VCal'}, callback= callback_function))

This code will import the calendar entries from Imported.txt to the calendar and call callback_function when the operation completes.

Export

Export service can be used synchronously or asynchronously to export entries from the calendar to a file. Like the Import service, ICal and VCal are the supported file formats for Export service.

The code below shows how to use Import synchronously to export all the calendar entries to the Exported.txt file using VCal file format.

calendar_handle.call('Export', {'Type': u'CalendarEntry', 'FileName': u'C:\\Data\\Exported.txt', 'Format': u'VCal'})

Similarly, we can call Import asynchronously to perform the same task; again, callback_function is called when the export is finished:

calendar_handle.call('Export', {'Type': u'CalendarEntry', 'FileName': u'C:\\data\\Exported.txt', 'Format': u'VCal'}, callback= callback_function))

RequestNotification

Applications can use the RequestNotification service to be notified (asynchronously) when the calendar entries are added, modified or deleted.

For example, the following code requests calendar entry notifications. Whenever a calendar entry is modified, edited or deleted, the callback function is called with arguments trans_id, event_id and input_params.

import scriptext
import e32
 
lock = e32.Ao_lock()
calendar_handle = scriptext.load('Service.Calendar', 'IDataSource')
 
def calendar_callback(trans_id, event_id, input_params):
if event_id != scriptext.EventCompleted:
# Check the event status
print "Error in retrieving required info"
print "Error code is: " + str(input_params["ReturnValue"]["ErrorCode"])
if "ErrorMessage" in input_params["ReturnValue"]:
print "Error message is: " + input_params["ReturnValue"]["ErrorMessage"]
else:
print "Modification is: " + str(input_params["ReturnValue"]["ChangeType"])
lock.signal()
 
# Make a request to get notification
event_id = calendar_handle.call("RequestNotification", {'Type': u'CalendarEntry'}, callback=calendar_callback)
 
lock.wait()

Contacts

The contacts service allows you to manage the contacts list on the device. Using the API you can retrieve contact or group information, add a contact or group, edit a particular contact or group, import and export a contact and delete a contact or a group item. These services are illustrated in figure 12.4.

File:PythonOnSymbian PySymbian PS Contacts.png
Figure 12.4: Contacts services

The Contacts API has to be loaded before using any of the services it provides. Use Service.Contact to identify the service provider and IDataSource to identify the supported interface, as illustrated by the following code.

import scriptext
contact_handle = scriptext.load('Service.Contact', 'IDataSource')

GetList

The GetList service is very similar to the one offered by the calendar service. The only difference is GetList for contacts can be used synchronously as well as asynchronously. GetList service can be used to retrieve list of contacts, contact groups, or contacts databases.

The list of contacts and contact groups can be retrieved from the specified contact database. If no database is specified, the default database is used.

The following code code uses GetList synchronously. It populates the list list_contacts with the list of contacts with ‘Pankaj’ in their First Name and Last Name fields:

list_contacts = contacts_handle.call('GetList', {'Type': u'Contact', 'Filter': {'SearchVal': u'Pankaj'}})

The following code performs the same GetList operation asynchronously, the main difference being that the callback_function is called after the contacts are retrieved.

event_id = contacts_handle.call('GetList', {'Type': u'Contact', 'Filter':{'SearchVal': u'Pankaj'}}, callback=callback_function)

Note: In S60 3rd Edition and S60 3rd Edition FP1, SearchVal searches in all the contact fields. However in S60 3rd edition FP2 onwards, SearchVal searches only in First Name and Last Name field.

Add

Add can be used synchronously or asynchronously to add or edit a contact or contact group to a contacts database. If the contact or contact group already exists in the database, it is replaced with the new entry.

For example, the following code adds the contact details for Jeremy Burton to the contacts database.

contacts_handle.call('Add', {'Type': u'Contact', 'Data':
{'FirstName': {'Label': u'first name', 'Value': u'Burton'},
'LastName': {'Label': u'last name', 'Value': u'Jeremy'},
'MobilePhoneGen': {'Label': u'mobile', 'Value': u'9009132813'},
'EmailHome': {'Label': u'email', 'Value': u'Burton@Jeremy.com'}}})

Delete

The Delete service can be used synchronously or asynchronously to delete one or more contacts or contact groups from a given contact database. If no database is given, the default database is used.

The following example shows how to delete the contact with the req_id and calls the callback_function when this is done.

event_id = contacts_handle.call('Delete', {'Type': u'Contact', 'Data': {'IdList': [req_id]}}, callback=callback_function)

Import

Import can be used synchronously or asynchronously to import contacts from a vCard file.

Using Import synchronously:

event_id = contacts_handle.call('Import', {'Type': u'Contact','Data':{'SourceFile':u'c:\\Data\\contacts.txt'}})

Using Import asynchronously:

event_id = contacts_handle.call('Import', {'Type': u'Contact','Data':{'SourceFile':u'c:\\Data\\ contacts.txt'}},callback=callback_function)

Export

Export can be used synchronously or asynchronously to export contacts to a vCard file.

Using Export synchronously:

event_id = contacts_handle.call('Export', {'Type': u'Contact','Data':{'SourceFile':u'c:\\Data\\contacts.txt'}})

Using Export asynchronously:

event_id = contacts_handle.call('Export', {'Type': u'Contact','Data':{'SourceFile':u'c:\\Data\\contacts.txt'}},callback=callback_function)

Organize

Organize can be used synchronously or asynchronously, to add contacts to a contact group or remove contacts from a contact group.

Using Organize asynchronously:

event_id = contacts_handle.call('Organise', {'Type': u'Group','Data': {'id': unicode(req_groupid[0]),'IdList': [req_id]}, 'OperationType': u'Associate'},callback=export_contact)

Landmarks

Landmarks are used to record positions of interest as GPS coordinates. It is possible to sort the saved locations into different categories, such as businesses, and add other information to them, such as addresses. Landmarks can be used in other compatible applications like GPS Data and Nokia Maps. GPS coordinates are expressed in the degrees and decimal degrees format using the international WGS-84 coordinate system.

Scriptext provides the Landmarks service API for handling landmark information. Using this API, developers can read, add, delete, import, export and organize the landmarks on a local database, as shown in figure 12.5. Note that Python only supports operations associated with local databases - remote server-based databases are not supported.

Figure 12.5: Landmarks services

A category is a characteristic of a landmark. Categories are used to classify the landmarks on the basis of geographical or architectural interest, attraction or activity-related types of objects.

The Landmarks API can be loaded by the following code:

import scriptext
landmark_handle = scriptext.load('Service.Landmarks', 'IDataSource')

New

New can be used synchronously to add a landmark or a landmark category. It should be noted that the landmark created by the New service is supposed to be an empty landmark.

For example, to create a new empty landmark:

new_landmark = landmark_handle.call('New', {'Type': u'Landmark'})

To create a new landmark category:

new_category = landmark_handle.call('New', {'Type': u'Category'})

GetList

GetList can be used synchronously or asynchronously to retrieve information about existing landmarks, landmark categories, or landmark databases. The target landmark database may be specified. If no database is specified, the default database is used.

Using GetList synchronously:

Landmarks_info = landmark_handle.call('GetList', {'Type': u'Landmark', 'Filter':{'uDatabaseURI':  u'dataBaseUri', 'LandmarkName': landmark_name}, 'Sort' :{'Key': u'LandmarkName', 'Order': order_of_list}})

where landmark_name (Unicode) is the name of the landmark and order_of_list is u’Ascending’ or u’Decending’.

Using GetList asynchronously:

event_id = landmark_handle.call('GetList', {'Type': u'Landmark','Filter':{'uDatabaseURI':u'dataBaseUri','LandmarkName': },'Sort':{'Key':u'LandmarkName','Order': order_of_list}}, callback=callback_function)

where order_of_list is u’Ascending’ or u’Decending’ and callback_function is the user defined callback function.

Add

Add can be used synchronously to add or modify a landmark.

The following example adds the landmark landmark_name (Unicode) to the database.

add_output = landmark_handle.call('Add', {'Type': u'Landmark', 'Data': {'LandmarkName':  landmark_name}})

Delete

Delete can be used synchronously to delete the specified landmark from the specified database. If no database is specified, the active/default database is used.

For example, the following code opens the default or active database for reading landmarks and categories. A default database is created (if it does not exist) and is set as active. The landmark land1 is deleted from the active or specified database.

delete_output = landmark_handle.call(’Delete’, {’Type’: u’Landmark’,’Filter’: {’LandmarkName’: u’land1’}})

Import

Import can be used synchronously to import a set of landmarks from a file.

For example, the following code will import landmarks from the landmarks_import.txt file to the database. Since the database is not specified, landmarks are imported to the default database. The only supported MimeType is application/vnd.nokia.landmarkcollection+xml.

import_output = landmark_handle.call(’Import’, {’Type’: u’Landmark’, ’Data’: {’SourceFile’: u’c:\data\landmarks_import.txt, ’MimeType’: u’application/vnd.nokia.landmarkcollection+xml}})

Export

Export can be used synchronously to export a set of specified landmarks to a file.

For example, the following code exports the landmark "land1" to export_landmarks.txt.

getlist_output = landmark_handle.call(’GetList’, {’Type’: u’Landmark’, ’Filter’: {’LandmarkName’: u’land1’}})
 
retval = getlist_output[’ReturnValue’]
id_val = retval[id]
 
export_output = landmark_handle.call(’Export’, {’Type’: u’Landmark’, ’Data’: {’DestinationFile’: u’c:\data\export_landmarks.txt, ’idList’: [id_val], ’MimeType’: u’application/vnd.nokia.landmarkcollection+xml}})

Organise

Organise can be used synchronously to associate or disassociate a list of landmarks from a category.

For example, the following code will associate the landmarks land1 and land2 with all the available categories in the active/default database. The Operation Type can be 'Associate' or 'Disassociate'.

getlist_category_output = landmark_handle.call('GetList', {'Type': u'Category'})
retval_category = getlist_category_output['ReturnValue']
cat_id = retval_category['id']
 
getlist_output1 = landmark_handle.call(’GetList’, {’Type’: u’Landmark’, ’Filter’: {’LandmarkName’: u’land1’}})
retval1 = getlist_output1[’ReturnValue’]
id_val1 = retval1[id]
 
getlist_output2 = landmark_handle.call(’GetList’, {’Type’: u’Landmark’, ’Filter’: {’LandmarkName’: u’land2’}})
retval2 = getlist_output2[’ReturnValue’]
id_val2 = retval2[id]
 
organise_output = landmark_handle.call(’Organise’, {’Type’: u’Landmark’,’Data’: {id’: unicode(cat_id), ’idList’: [id_val1,id_val2]}, ’Operation Type’: ’Associate’})

Location

Through the Location service API, scriptext not only gives you access to the physical location of the device but also allows you to track the movements of the device and perform calculations based on location information. Refer to Chapter 10 for information on how the physical location of the device can be interpreted.

Figure 12.6: Location services

The Location API can be loaded using the following code:

import scriptext
location_handle = scriptext.load('Service.Location', 'IDataSource')

Note that use of the Location API requires the Location platform security capability.

GetList

GetList can be used synchronously or asynchronously to retrieve the current location of the device.

The fragment below shows how to call GetList synchronously:

Location_List = location_handle.call('GetList', {'LocationInformationClass': u'BasicLocationInformation', 'Updateoptions': {'UpdateInterval':u'1', 'UpdateTimeOut': u'15', 'UpdateMaxAge' :u'0', 'PartialUpdates': u'False'}})

The asynchronous operation is similar GetList, except that callback_function is called after the location is retrieved:

event_id = location_handle.call('GetList', {'LocationInformationClass':  u'BasicLocationInformation', 'Updateoptions': {'UpdateInterval': u'1', 'UpdateTimeOut': u'15', 'UpdateMaxAge': u'0', 'PartialUpdates': u'False'}}, callback= callback_function)

Trace

Trace can be used to track the movement of the device - it gives updates on the location of the device based on a predefined update interval, and it can only be used asynchronously.

event_id = location_handle.call('Trace', {'LocationInformationClass': u'GenericLocationInfo', 'Updateoptions': {'UpdateInterval': u'10', 'UpdateTimeOut': u'50', 'UpdateMaxAge': u'5', 'PartialUpdates': u'True'}})

CancelNotification

CancelNotification can be used synchronously to cancel asynchronous calls – for example – Add and Trace, as shown by the following code.

cancel_output = location_handle.call('CancelNotification', {'CancelRequestType': u'GetLocCancel'})

MathOperations

MathOperations is used to perform calculations on retrieved or user-provided location information.

The mathematical operations provided by MathOperations include finding distance between two given locations, finding the bearing between two given locations and calculating a new location based on movement from a source location.

For example, the following code is used to find the distance (in metres) between two provided locations:

distance = location_handle.call('MathOperations', {'MathRequest': u'FindDistance', 'DistanceParamSource': {'Longitude': u'10', 'Latitude': u'15', 'Altitude': u'20'}, 'DistanceParamDestination': {'Longitude': u'40', 'Latitude': u'55', 'Altitude': u'20'}})

Logging

Logs are a useful way of monitoring communication on Symbian devices. Calls, messages and data are recorded in the device's Logs engine.

The logging service API offers greater control over the information in the device's logs than the logs module because it also gives you the ability to add and delete events, not just read them.

As shown in figure 12.7, logging provides 4 services: Add, GetList, Delete, and RequestNotification.

Figure 12.7: Logging services

The Logging API is loaded as follows:

import scriptext
logging_handle = scriptext.load('Service.Logging', 'IDataSource')

Add

This service is used to create events to the phone's Logs application. The general form of the handle's call() method is call('Add', {'Type': , 'Item': {'EventType': , 'Direction': , 'EventDuration': , 'DeliveryStatus': , 'PhoneNumber': )}}, where appropriate values are to be associated with each parameter. A table containing possible values and descriptions for the parameters is available at http://pys60.garage.maemo.org/doc/s60/node150.html. The method returns a unique identifier for the event in the logs database.

Here is an example of how to add a dialed call and a received SMS to the device's logs:

import scriptext
 
logging_handle = scriptext.load('Service.Logging', 'IDataSource')
 
#The call
log_id = logging_handle.call('Add', {'Type': u'Log', 'Item': {'EventType': 0, 'Direction': 1, 'EventDuration': 20, 'PhoneNumber': u'1234567890'}})
#The line above reads: add a log item consisting of an outgoing (Direction 1) call (EventType 0) that lasted 20 seconds (EventDuration 20) towards the number 1234567890 (PhoneNumber 1234567890)
 
#The SMS
log_id = logging_handle.call('Add', {'Type': u'Log', 'Item': {'EventType': 3, 'Direction': 0, 'DeliveryStatus': 1, 'PhoneNumber': u'1234567890'}})
#This line reads: add a log item consisting of an incoming (Direction 0) SMS (EventType 3) that was successfully sent (DeliveryStatus 1) to the number 1234567890 (PhoneNumber 1234567890)

GetList

The GetList service retrieves all the events from the phone's logs as a list of dictionaries. The information in each dictionary can then be accessed by using the name of its field as a key, as follows:

import scriptext
 
logging_handle = scriptext.load('Service.Logging', 'IDataSource')
 
#Get all the entries of type Log
logging_info = logging_handle.call('GetList', {'Type': u'Log',})
#Display their information
for entry in logging_info:
print entry['EventType']
print entry['RemoteParty']
print entry['Direction']
print entry['EventTime']
print entry['Subject']
print entry['PhoneNumber']
print entry['Description']
print entry['EventData']

GetList can be used synchronously as well as asynchronously (in this case by adding a callback function as the last paramater of the call method).

Delete

Delete can be used to remove events from the log:

logging_handle.call('Delete', {'Type': u'Log', 'Data': {'id': log_id,}})
#log_id is the ID of the entry we wish to delete

RequestNotification

The RequestNotification service can be used to provide asynchronous notification when log entries are added or deleted. This is useful to ensure your application information remains up to date when it is not the only application that is manipulating log data.

import scriptext, e32
 
app_lock = e32.Ao_lock()
 
def logging_callback(trans_id, event_id, input_params):
#We anticipate the situation in which the request cannot be serviced
if trans_id != logging_id and event_id != scriptext.EventCompleted:
print "Error in servicing the request"
print "Error code is: " + str(input_params["ReturnValue"]["ErrorCode"])
if "ErrorMessage" in input_params["ReturnValue"]:
print "Error message is: " + input_params["ReturnValue"]["ErrorMessage"]
else:
print "Changes notified accordingly"
 
#Continue executing the rest of the script after the request is processed
app_lock.signal()
 
logging_handle = scriptext.load('Service.Logging', 'IDataSource')
logging_id = logging_handle.call('RequestNotification', {'Type': u'Log', 'Filter': {'DelayTime': 600000}}, callback=logging_callback)
 
print "Waiting for the request to be processed"
app_lock.wait()
 
print "Request complete!"

Messaging

The messaging service offers functionality that combines much of what is offered in the messaging and inbox modules. It allows you to access and delete messages, change their status and register for new message notifications.

Figure 12.8: Messaging services

Send

The Send service allows you to send SMS and MMS messages. It can be used both synchronously and asynchronously.

Here is an example of Send being used synchronously to send an SMS and an MMS with an attachment:

import scriptext
 
#Load the provider
messaging_handle = scriptext.load('Service.Messaging', 'IMessaging')
 
#Send the SMS
messaging_handle.call('Send', {'MessageType': u'SMS', 'To': u'1234567890', 'BodyText': u'This is the message'})
 
#Send the MMS
messaging_handle.call('Send', {'MessageType': u'MMS', 'To': u'1234567890', 'BodyText': u'This is the message', 'Attachment': u'C:\\Data\\photo.jpg'})

As with all the other services, a complete list of parameters for the call method, possible error codes, and their interpretations is available at http://pys60.garage.maemo.org/doc/s60/node156.html.

GetList

GetList is used to get a list of messaging objects from the messaging center, where an object contains information about one message. This service can only be used synchronously. The following code shows how to display the the SMS 'Sender' IDs from all the messages in the inbox:

import scriptext
 
messaging_handle = scriptext.load('Service.Messaging', 'IMessaging')
 
# This 'GetList' request returns all the SMS in the inbox as an iterable map
sms_iter = messaging_handle.call('GetList', {'Type': u'Inbox'})
 
#Create an empty list which will be populated with the sender IDs
sender_list = []
 
#For every SMS in the inbox, add the sender ID to the list
for sms_dict in sms_iter:
if sms_dict['MessageType'] == 'SMS':
sender_list.append(sms_dict['Sender'])
 
#Display the result
print "ID list :", sender_list

RegisterNotification and CancelNotification

RegisterNotification is used to receive notifications for new messages. It can only be use asynchronously, as shown below.

import scriptext, e32
 
app_lock = e32.Ao_lock()
messaging_handle = scriptext.load('Service.Messaging', 'IMessaging')
 
def new_sms_callback(trans_id, event_id, output_params):
if trans_id == sms_id and event_id == scriptext.EventCompleted:
print "SMS received from" + output_params['ReturnValue']['Sender'])
else:
print "Error in callback"
#Cancel notification request
messaging_handle.call('CancelNotification', {'Type': u'NewMessage'})
app_lock.signal()
 
#The callback 'new_sms_callback' will be called when an SMS is received
sms_id = messaging_handle.call('RegisterNotification', {'Type': u'NewMessage'}, callback=new_sms_callback)
 
app_lock.wait()

The CancelNotification service is used when we wish to stop receiving notifications about new messages.

ChangeStatus

It is sometimes useful to manipulate the status of the messages in the inbox (read/unread). In order to do this, the messaging service offers ChangeStatus, which can only be used synchronously.

The following code displays a list of all the messages in the inbox (their text) and, once the user selects one, changes its status to unread, if possible.

import scriptext, appuifw
 
messaging_handle = scriptext.load('Service.Messaging', 'IMessaging')
 
sms_iter = messaging_handle.call('GetList', {'Type': u'Inbox'})
id_list = []
body_list = []
#Populate the lists with the IDs and bodies of all the SMS messages
for sms_dict in sms_iter:
if sms_dict['MessageType'] == 'SMS':
id_list.append(sms_dict['MessageId'])
body_list.append(sms_dict['BodyText'])
 
message_index = appuifw.selection_list(body_list)
 
try:
messaging_handle.call('ChangeStatus', {'MessageId': id_list[message_index], 'Status': u'Unread'})
except scriptext.ScriptextError, err:
print "Error setting message status to unread"
else:
print "Message status changed to unread"

Delete

Delete can be used synchronously to remove a certain message from the inbox:

import scriptext, appuifw, e32
 
app_lock = e32.Ao_lock()
 
messaging_handle = scriptext.load('Service.Messaging', 'IMessaging')
 
sms_iter = messaging_handle.call('GetList', {'Type': u'Inbox'})
 
id_list = []
body_list = []
for sms_dict in sms_iter:
if sms_dict['MessageType'] == 'SMS':
id_list.append(sms_dict['MessageId'])
body_list.append(sms_dict['BodyText'])
 
#Select the message to be deleted
message_index = appuifw.selection_list(body_list)
 
try:
messaging_handle.call('Delete', {'MessageId': id_list[message_index]})
except scriptext.ScriptextError, err:
print "Error deleting SMS :", err
else:
print "Message deleted successfully"

Media management

The media management service provides an application with information about the media files in the device's media management applications (including gallery and music player).

GetList

The GetList service returns the metadata of the media files based on the input parameters. It is only available in asynchronous mode.

The following code snippet shows how to get a list of all MP3 files:

import scriptext, e32
 
def media_callback(trans_id, event_id, output_params):
if trans_id == media_trans_id:
if event_id == scriptext.EventCompleted:
song_list = []
for item in output_params['ReturnValue']:
song_list.append(item['FileName'])
print "List of files retrieved:", song_list
else:
print "Event ID was not EventCompleted"
else:
print "Invalid Transaction ID"
app_lock.signal()
 
app_lock = e32.Ao_lock()
media_handle = scriptext.load('Service.MediaManagement', 'IDataSource')
 
#Request for the list of MP3s in ascending order
media_trans_id = media_handle.call('GetList', {'Type': u'FileInfo',
'Filter': {'FileType': u'Music',
'Key': u'FileExtension',
'StartRange': u'.mp3'},
'Sort': {'Key': u'FileName',
'Order': u'Ascending'}},
callback=media_callback)

A complete list of key values that can be used to filter information is available in at http://pys60.garage.maemo.org/doc/s60/node163.html.

Sensors

The data provided by sensors on the device allow you to capture user actions and gestures and handle them in your applications.

Let's familiarize ourselves with the following terminologies to start with:

  • Sensor is a physical sensor on a device (a piece of hardware combined with a software plug-in). A single sensor can provide multiple sensor channels, such as a raw data channel and event channels, or incorporate multiple sensor readings into a single sensor channel.
  • Channel is an abstraction of a physical sensor. Data from one physical sensor can be mapped to multiple sensor channels.
  • Channel property is a configuration value of a sensor channel. The property affects all clients listening to the channel.

The Sensor service provides access to data provided by various physical sensors that exist in the device. The data from a given sensor is mapped to one or more sensor channels, which the API can listen to. With the sensor service you can:

  • FindSensorChannel: Search for sensor channels available on a device
  • RegisterForNotification: Listen for data provided by one or more sensor channels
  • GetChannelProperty: Retrieve information about sensor channel properties
Figure 12.9: Sensor services

The API can be loaded by the following code:

import scriptext
sensor_handle = scriptext.load('Service.Sensor', 'ISensor')

FindSensorChannel

FindSensorChannel can be used synchronously to search for sensor channels available in the device.

The following code performs a search operation for sensor channels available in the device, based on the specified criteria Rotation. The other search criteria which can be used are All, AccelerometerAxis, AccelerometerDoubleTapping, Orientation and Rotation.

sensor_handle.call('FindSensorChannel', {'SearchCriterion': u'Rotation '})

RegisterForNotification

RegisterForNotification can be used asynchronously to register for notification with a sensor channel to receive channel data or channel property changes. This is associated with the transaction ID of an asynchronous request.

The notifications are continuous in nature and are stopped by invoking the Cancel command on the retrieved transaction ID.

For example:

sensor_handle.call('RegisterForNotification',
{'ListeningType': u'ChannelData',
'ChannelInfoMap': {'ChannelId': result['ChannelId'],
'ContextType': result['ContextType'],
'Quantity': result['Quantity'],
'ChannelType': result['ChannelType'],
'Location': result['Location'],
'VendorId': result['VendorId'],
'DataItemSize': result['DataItemSize'],
'ChannelDataTypeId': result['ChannelDataTypeId']}},
callback=callback_function)

where callback_function is the user defined callback function.

GetChannelProperty

GetChannelProperty can be used synchronously to get the channel property of the specified sensor channel.

For example, the following code is used to receive the requested property details in result.

 result = sensor_handle.call('GetChannelProperty', 
{'ChannelInfoMap':{'ChannelId': result['ChannelId'],
'ContextType': result['ContextType'],
'Quantity': result['Quantity'],
'ChannelType': result['ChannelType'],
'Location': result['Location'],
'VendorId': result['VendorId'],
'DataItemSize': result['DataItemSize'],
'ChannelDataTypeId': result['ChannelDataTypeId']},
'propertyId': u'DataRate'})

Sys Info

This service allows you to read and, in some cases, modify system parameters on the device. It is also possible to register to system events in order to receive notifications when changes occur.

Figure 12.10: Sys Info services

GetInfo

The GetInfo service retrieves the value of a system attribute. For example, we define a function that will be called after the system query is made and that is passed the returned values as arguments. If all goes well (meaning there is no error), the battery strength is displayed.

import scriptext, e32
 
#Using e32.Ao_lock() so that the main function can wait until the callback is hit.
lock = e32.Ao_lock()
 
#Callback function will be called when the requested service is complete
def print_battery_strength(trans_id, event_id, input_params):
#Check the event status
if event_id != scriptext.EventCompleted:
print "Error in retrieving required info"
print "Error code is: " + str(input_params["ReturnValue"]["ErrorCode"])
if "ErrorMessage" in input_params["ReturnValue"]:
print "Error message is: " + input_params["ReturnValue"]["ErrorMessage"]
else:
print "Battery strength is: ", input_params["ReturnValue"]["Status"]
 
lock.signal()
 
#Load sysinfo service
sysinfo_handle = scriptext.load("Service.SysInfo", "ISysInfo")
 
#Make a request to query the required information
event_id = sysinfo_handle.call("GetInfo", {"Entity": u"Battery", "Key": u"BatteryStrength"}, callback=print_battery_strength)
 
print "Waiting for the request to be processed!"
lock.wait()
print "Request complete!"

SetInfo

Some system attributes can be changed. As an example, the following snippet sets vibration as active:

import scriptext
 
#Load sysinfo service
sysinfo_handle = scriptext.load('Service.SysInfo', 'ISysInfo')
 
#Make a request to set vibra mode
try:
sysinfo_handle.call("SetInfo", {"Entity": u"General", "Key": u"VibraActive", "SystemData": {"Status": 1}})
print "Request complete!"
except scriptext.ScriptextError:
print 'Error in servicing the request'

GetNotification

The GetNotification service provides notification when changes occur in certain system parameters.

The following code registers to receive a message when the battery's charging status changes.

import scriptext, e32
 
lock = e32.Ao_lock()
sysinfo_handle = scriptext.load('Service.SysInfo', 'ISysInfo')
 
def battery_status_callback(trans_id, event_id, input_params):
#Check the event status
if event_id != scriptext.EventCompleted:
print "Error in retrieving required info"
print "Error code is: " + str(input_params["ReturnValue"]["ErrorCode"])
if "ErrorMessage" in input_params["ReturnValue"]:
print "Error message is: " + input_params["ReturnValue"]["ErrorMessage"]
else:
print "Current battery charging status: " + str(input_params["ReturnValue"]["Status"])
lock.signal()
 
#Make a request to get notification
event_id = sysinfo_handle.call("GetNotification", {"Entity": u"Battery", "Key": u"ChargingStatus"}, callback=battery_status_callback)
lock.wait()

Summary

This chapter introduced the platform services APIs. These provide a consistent interface for deep access to a wide range of different services.

We hope that you are inspired by the plethora of features that are offered to Python on Symbian applications. Feel free to dip into this chapter and come back whenever you need to use/apply the information in practice.

In the next chapter, we provide an overview of how to extend the functionality of Python on Symbian using native Symbian C++, and also how to call Python scripts from C++ code.

Licence icon cc-by-sa 3.0-88x31.png© 2010 Symbian Foundation Limited. Portions copyright Bogdan Galiceanu, Hamish Willee, Marcelo Barros de Almeida, Mike Jipping, Pankaj Nathani and others in wiki document history list. This document is licensed under the Creative Commons Attribution-Share Alike 2.0 license. See http://creativecommons.org/licenses/by-sa/2.0/legalcode for the full terms of the license.
Note that this content was originally hosted on the Symbian Foundation developer wiki.

This page was last modified on 8 May 2013, at 09:11.
84 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×