Activity tutorial: Difference between revisions

From OLPC
Jump to navigation Jump to search
(dated notice with ref)
(class is deprecated; use exec = sugar-activity)
 
(122 intermediate revisions by 57 users not shown)
Line 1: Line 1:
{{OLPC}}
{{dated}}
{{dated}}
<blockquote>
Marco Pesenti Gritti on [http://mailman.laptop.org/pipermail/sugar/2007-February/001226.html Mon Feb 5 11:48:39 EST 2007] says:
:The tutorial is obsolete. Until we have an updated version your best bet is to look at an existing activity:


For up to date information on creating Activities see http://www.flossmanuals.net/make-your-own-sugar-activities/
::http://dev.laptop.org/git.do?p=journal-activity;a=tree


{{Translations}}
:Also we have a spec about activity bundles but it's not fully implemented yet:
{{Developers}}
<< [[Tutorials]]


This tutorial explains step by step how to create the Hello World Activity bundle. You can [http://divieira.googlepages.com/HelloWorld-1.xo download a completed .xo package], though the package will not exactly match the below contents.
::[[Activity bundles]]
</blockquote>
----


This tutorial assumes you have read the [[Developers|Developer's Manual]], have [[Developers/Setup|installed a Sugar development environment]] and wish to use the [[Developers/Setup#Python/PyGTK|PyGTK]] development approach (the standard approach to developing activities for the OLPC).
Here is a short tutorial about writing a sugar activity. It's a step by step guide to get you started quickly, without going in details of the activity system. Download the [http://www.snowedin.net/misc/sugar-drawing-0.2.tar.gz current example sources] (Marco's original sources are [http://www.gnome.org/~marco/sugar-drawing-0.1.tar.gz here]).


== Write the build system ==
== Getting started ==
*Create the bundle directory structure:


mkdir -p HelloWorldActivity.activity/activity
===Create the <tt>autogen.sh</tt> script===
You should only need to change the module name and activity file from this example.


*Write the <tt>activity.info</tt> file, to describe your bundle in the activity sub-directory (e.g. <tt>HelloWorldActivity.activity/activity/activity.info</tt>). The [[Activity Bundles]] specification explain in detail the meaning of each field.
#!/bin/sh
**Note: in a joyride-1525 build, sugar could not locate the icon when I tried this unless I removed the '.svg' extension from the 'icon = activity-helloworld.svg' line.
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="sugar-drawing"
(test -f $srcdir/drawing.activity) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level $PKG_NAME directory"
exit 1
}
which gnome-autogen.sh || {
echo "You need to install gnome-common from the GNOME CVS"
exit 1
}
REQUIRED_AUTOMAKE_VERSION=1.9 USE_GNOME2_MACROS=1 . gnome-autogen.sh


{{ Box File | activity.info | 2=<pre>
===Create a configure.ac file===
[Activity]
name = HelloWorld
bundle_id = org.laptop.HelloWorldActivity
exec = sugar-activity HelloWorldActivity.HelloWorldActivity
icon = activity-helloworld
activity_version = 1
host_version = 1
show_launcher = yes
</pre>
}}


*Design an icon for your activity by following the instructions on [[Making_Sugar_Icons | making icons for Sugar]] and place it in the activity sub-directory. The file name should match the icon file name specified in the info file (e.g. <tt>activity-helloworld.svg</tt>). The contents of the SVG file will look something like:
The first line of configure.ac specifies the name of the application, the version number, a bug reporting address, and the name of the module.


{{ Box File | activity-helloworld.svg | 2=<pre>
The configure.ac file contains a list of all the Makefiles in your project. You will need one Makefile for every directory in your project.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY stroke_color "#666666">
<!ENTITY fill_color "#FFFFFF">
]>
<svg xmlns="http://www.w3.org/2000/svg" width="55" height="55">
<rect x="5" y="5" width="45" height="45"
style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:3.5"/>
</svg>
</pre>
}}

*Write the <tt>setup.py</tt> script in the top level directory (e.g. <tt>HelloWorldActivity.activity/setup.py</tt>), which in most cases will look like this:

{{ Box File | setup.py | 2=<pre>
#!/usr/bin/env python
from sugar.activity import bundlebuilder
bundlebuilder.start()
</pre>
}}

A more advanced version, which supports building activity bundles without Sugar installed, looks like this:

{{ Box File | setup.py | 2=<pre>
#!/usr/bin/env python
try:
from sugar.activity import bundlebuilder
bundlebuilder.start()
except ImportError:
import os
os.system("find ./ | sed 's,^./,HelloWorldActivity.activity/,g' > MANIFEST")
os.system('rm HelloWorldActivity.xo')
os.chdir('..')
os.system('zip -r HelloWorldActivity.xo HelloWorldActivity.activity')
os.system('mv HelloWorldActivity.xo ./HelloWorldActivity.activity')
os.chdir('HelloWorldActivity.activity')
</pre>
}}

*Code your activity in Python. The name you specified in the <tt>.info</tt> file as "<tt>class</tt>" is the name of the class which runs your code. For the <tt>activity.info</tt> file above, we specify a top-level module named <tt>HelloWorldActivity.HelloWorldActivity</tt> (please note that the use of uppercase names in module names is considered poor [[Python Style Guide|Python style]], feel free to use an activity name with more standard style names).
{{ Box File | HelloWorldActivity.py | 2=<pre>
from sugar.activity import activity
import logging
import sys, os
AC_INIT([Sugar Drawing],[0.1],[],[sugar-drawing])
import gtk
AM_INIT_AUTOMAKE
class HelloWorldActivity(activity.Activity):
AM_PATH_PYTHON
def hello(self, widget, data=None):
logging.info('Hello World')
def __init__(self, handle):
AC_OUTPUT([
print "running activity init", handle
Makefile
activity.Activity.__init__(self, handle)
other_dir/Makefile
print "activity running"
])
# Creates the Toolbox. It contains the Activity Toolbar, which is the
# bar that appears on every Sugar window and contains essential
# functionalities, such as the 'Collaborate' and 'Close' buttons.
toolbox = activity.ActivityToolbox(self)
self.set_toolbox(toolbox)
toolbox.show()
# Creates a new button with the label "Hello World".
self.button = gtk.Button("Hello World")
# When the button receives the "clicked" signal, it will call the
# function hello() passing it None as its argument. The hello()
# function is defined above.
self.button.connect("clicked", self.hello, None)
# Set the button to be our canvas. The canvas is the main section of
# every Sugar Window. It fills all the area below the toolbox.
self.set_canvas(self.button)
# The final step is to display this newly created widget.
self.button.show()
print "AT END OF THE CLASS"
</pre>
}}


The above file is called <tt>HelloWorldActivity.py</tt>
=== Other required files ===
Automake checks for the existence of a few required files, you have to create them even if empty:


*Create a <tt>MANIFEST</tt> (e.g. <tt>HelloWorldActivity.activity/MANIFEST</tt>), containing the list of the files (relative to the directory that the MANIFEST is in) to include in the package. (Note: Be sure '''not''' to leave blank lines at the end of the file.) This script does that in linux (run it from within the HellowWorldActivity.activity directory):
$ touch NEWS README AUTHORS ChangeLog
cd HelloWorldActivity.activity
find . -type f | sed 's,^./,,g' > MANIFEST


*Your directory structure should now look like this:
===Makefile.am===
HelloWorldActivity.activity/
This file tells automake how to install your program.
HelloWorldActivity.activity/setup.py
HelloWorldActivity.activity/activity
HelloWorldActivity.activity/activity/activity.info
HelloWorldActivity.activity/activity/activity-helloworld.svg
HelloWorldActivity.activity/HelloWorldActivity.py
HelloWorldActivity.activity/MANIFEST


*Make sure that all your python files have the required permissions to be used.
in the Makefile.am, SUBDIRS is a space-separated list of subdirectories of the current folder, an activitydir that describes where files in the current folder will be installed, and activity_PYTHON which describes what files to install.
chmod a+x setup.py
chmod a+x HelloWorldActivity.py


*Setup your bundle for development (must be user olpc when you do this) to become user olpc, type: su - olpc
The backslash at the end of the activity_PYTHON lines indicates that more data exists on the following lines. (Note that the last line does not have a backslash).


If you are prompted for a password, trying using: su
(fixme: exactly what does EXTRA_DIST mean? -- I think it specifies non-*.py files that need to be included in the distribution)
(fixme #2: the variable datadir appears to be undefined. I received the error "make[1]: sugar-setup-activity command not found" setting the variable datadir in autogen.sh fixed it for me datadir=[sugar-jhbuild]/source)


python setup.py dev
SUBDIRS = foo bar
activitydir = $(datadir)/sugar/activities/drawing
activity_PYTHON = \
__init__.py \
DrawingActivity.py
EXTRA_DIST = drawing.activity
install-data-local:
sugar-setup-activity $(srcdir)/drawing.activity


This just creates a symlink to your activity folder in <tt>~/Activities</tt>, so that Sugar can find your activity.
== Write the activity code ==


*Restart Sugar using Ctrl-Alt-Erase and your activity will appear in the interface! (NOTE: By default, the Home view shows only the favorite activities. You should press Ctrl+2 or go the right-upper corner and change to the List View)
Write a subclass of sugar.activity.Activity. It's a GtkWindow so you can use the "add" method to insert your own widgets. The source of DrawingActivity.py demonstrates it:


*Run your activity, and if there are errors use the [[Log]] viewer activity to see what went wrong.
import gtk
from sugar.activity.Activity import Activity
class DrawingActivity(Activity):
def __init__(self):
Activity.__init__(self)
button = gtk.Button('Drawing')
self.add(button)
button.show()


== Running ==
Or if you are adapting a full application, your activity could look something like this: (I found I needed to delete the app object explicitly)
If you now run sugar the activity icon should be visible on the frame. (You have to restart sugar to get it to pick up the change if you just installed it. Hit <tt>ctrl-alt-erase</tt>.)


You can also edit the code in your bundle directory directly. Note that the first time your Activity is launched, it leaves a process around even if you close the window, so you must kill the <tt>sugar-activity-factory</tt> to get it to reload when you click again.
import gtk
from sugar.activity.Activity import Activity
from my_module.my_app import my_app
class DrawingActivity(Activity):
def __init__(self):
Activity.__init__(self)
app = my_app.my_app()
self.add(app.some_widget)
app.do_show()
self.connect('destroy',self.do_quit, app)
def do_quit(self, event, app):
app.do_quit()
del app


== Distribution ==
===create __init__.py===
Create an <tt>.xo</tt> package to distribute your bundle. (An <tt>.xo</tt> file is essentially a zip file built from the MANIFEST with some extra metadata, like a JAR file. It also has some localization ability, and in the future we expect to be able to sign these too.) The bundle name is automatically generated from the '<tt>name</tt>' and '<tt>activity_version</tt>' values found in the <tt>activity.info</tt> file, separated by a dash, with a <tt>.xo</tt> extension.
This is the package initialization file. It can be blank.


./setup.py dist_xo
$ touch __init__.py


To install the xo on a laptop you can use the installer script.
===drawing.activity===
Include the necessary information about the activity.

(fixme: what is default_type?)

[Activity]
name = Drawing
id = org.laptop.sugar.Drawing
python_module = drawing.DrawingActivity.DrawingActivity
default_type = _drawing_olpc._udp
show_launcher = yes


== Build and install ==
sugar-install-bundle HelloWorld-1.xo


== Trouble Shooting ==
Initialize the build system. The value of prefix depends on the path of sugar-jhbuild:


You can find application logs in /home/olpc/.sugar/default/logs. If the sample fails to compile, sugar will show you the icon in the circle but remain forever at the "Starting..." tag when you hover your mouse over it. You'll have to restart sugar with &lt;ctrl-alt-erase&gt; in order to remove the icon. You can find the cause of your trouble in the the log named for the "service-name" in your activity.info file, in this case "org.laptop.HelloWorldActivity".
$ ./autogen.sh --prefix=[SUGAR-JHBUILD]/build


== See also ==
Build and install:


* [[Activity bundles]]
$ [SUGAR-JHBUILD]/sugar-jhbuild shell
* [[Hacking Sugar]]
$ make
* [[Localization]] -- you will need to localize your activity to make it accessible to users of the OLPC
$ make install
* [[Game development HOWTO]]
* [[Textedit Activity]] - simple text editor to support development and testing on the Xo




[[Category:Sugar]]
[[Category:Sugar]]
[[Category:HowTo]]
[[Category:HowTo]]
[[Category:Developers]]

Latest revision as of 16:36, 17 January 2014

Emblem-warning.png The currency of this article or section may be limited by out-of-date information.
There may be relevant discussion on its talk page

For up to date information on creating Activities see http://www.flossmanuals.net/make-your-own-sugar-activities/

  english | 日本語 | 한국어 | português | español HowTo [ID# 294804]  +/-  


<< Tutorials

This tutorial explains step by step how to create the Hello World Activity bundle. You can download a completed .xo package, though the package will not exactly match the below contents.

This tutorial assumes you have read the Developer's Manual, have installed a Sugar development environment and wish to use the PyGTK development approach (the standard approach to developing activities for the OLPC).

Getting started

  • Create the bundle directory structure:
mkdir -p HelloWorldActivity.activity/activity
  • Write the activity.info file, to describe your bundle in the activity sub-directory (e.g. HelloWorldActivity.activity/activity/activity.info). The Activity Bundles specification explain in detail the meaning of each field.
    • Note: in a joyride-1525 build, sugar could not locate the icon when I tried this unless I removed the '.svg' extension from the 'icon = activity-helloworld.svg' line.
 File: activity.info
 [Activity]
 name = HelloWorld
 bundle_id = org.laptop.HelloWorldActivity
 exec = sugar-activity HelloWorldActivity.HelloWorldActivity
 icon = activity-helloworld
 activity_version = 1
 host_version = 1
 show_launcher = yes
  • Design an icon for your activity by following the instructions on making icons for Sugar and place it in the activity sub-directory. The file name should match the icon file name specified in the info file (e.g. activity-helloworld.svg). The contents of the SVG file will look something like:
 File: activity-helloworld.svg
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
   <!ENTITY stroke_color "#666666">
   <!ENTITY fill_color "#FFFFFF">
 ]>
 <svg xmlns="http://www.w3.org/2000/svg" width="55" height="55">
   <rect x="5" y="5" width="45" height="45"
   style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:3.5"/>
 </svg>
  • Write the setup.py script in the top level directory (e.g. HelloWorldActivity.activity/setup.py), which in most cases will look like this:
 File: setup.py
 #!/usr/bin/env python
 from sugar.activity import bundlebuilder
 bundlebuilder.start()

A more advanced version, which supports building activity bundles without Sugar installed, looks like this:

 File: setup.py
 #!/usr/bin/env python
 try:
 	from sugar.activity import bundlebuilder
 	bundlebuilder.start()
 except ImportError:
 	import os
 	os.system("find ./ | sed 's,^./,HelloWorldActivity.activity/,g' > MANIFEST")
 	os.system('rm HelloWorldActivity.xo')
 	os.chdir('..')
 	os.system('zip -r HelloWorldActivity.xo HelloWorldActivity.activity')
 	os.system('mv HelloWorldActivity.xo ./HelloWorldActivity.activity')
 	os.chdir('HelloWorldActivity.activity')
  • Code your activity in Python. The name you specified in the .info file as "class" is the name of the class which runs your code. For the activity.info file above, we specify a top-level module named HelloWorldActivity.HelloWorldActivity (please note that the use of uppercase names in module names is considered poor Python style, feel free to use an activity name with more standard style names).
 File: HelloWorldActivity.py
 from sugar.activity import activity
 import logging
 
 import sys, os
 import gtk
 
 class HelloWorldActivity(activity.Activity):
     def hello(self, widget, data=None):
         logging.info('Hello World')
 
     def __init__(self, handle):
         print "running activity init", handle
         activity.Activity.__init__(self, handle)
         print "activity running"
 
         # Creates the Toolbox. It contains the Activity Toolbar, which is the
         # bar that appears on every Sugar window and contains essential
         # functionalities, such as the 'Collaborate' and 'Close' buttons.
         toolbox = activity.ActivityToolbox(self)
         self.set_toolbox(toolbox)
         toolbox.show()
 
         # Creates a new button with the label "Hello World".
         self.button = gtk.Button("Hello World")
     
         # When the button receives the "clicked" signal, it will call the
         # function hello() passing it None as its argument.  The hello()
         # function is defined above.
         self.button.connect("clicked", self.hello, None)
     
         # Set the button to be our canvas. The canvas is the main section of
         # every Sugar Window. It fills all the area below the toolbox.
         self.set_canvas(self.button)
     
         # The final step is to display this newly created widget.
         self.button.show()
     
         print "AT END OF THE CLASS"

The above file is called HelloWorldActivity.py

  • Create a MANIFEST (e.g. HelloWorldActivity.activity/MANIFEST), containing the list of the files (relative to the directory that the MANIFEST is in) to include in the package. (Note: Be sure not to leave blank lines at the end of the file.) This script does that in linux (run it from within the HellowWorldActivity.activity directory):
cd HelloWorldActivity.activity
find . -type f | sed 's,^./,,g' > MANIFEST
  • Your directory structure should now look like this:
HelloWorldActivity.activity/
HelloWorldActivity.activity/setup.py
HelloWorldActivity.activity/activity
HelloWorldActivity.activity/activity/activity.info
HelloWorldActivity.activity/activity/activity-helloworld.svg
HelloWorldActivity.activity/HelloWorldActivity.py
HelloWorldActivity.activity/MANIFEST
  • Make sure that all your python files have the required permissions to be used.
chmod a+x setup.py
chmod a+x HelloWorldActivity.py
  • Setup your bundle for development (must be user olpc when you do this) to become user olpc, type: su - olpc

If you are prompted for a password, trying using: su

python setup.py dev

This just creates a symlink to your activity folder in ~/Activities, so that Sugar can find your activity.

  • Restart Sugar using Ctrl-Alt-Erase and your activity will appear in the interface! (NOTE: By default, the Home view shows only the favorite activities. You should press Ctrl+2 or go the right-upper corner and change to the List View)
  • Run your activity, and if there are errors use the Log viewer activity to see what went wrong.

Running

If you now run sugar the activity icon should be visible on the frame. (You have to restart sugar to get it to pick up the change if you just installed it. Hit ctrl-alt-erase.)

You can also edit the code in your bundle directory directly. Note that the first time your Activity is launched, it leaves a process around even if you close the window, so you must kill the sugar-activity-factory to get it to reload when you click again.

Distribution

Create an .xo package to distribute your bundle. (An .xo file is essentially a zip file built from the MANIFEST with some extra metadata, like a JAR file. It also has some localization ability, and in the future we expect to be able to sign these too.) The bundle name is automatically generated from the 'name' and 'activity_version' values found in the activity.info file, separated by a dash, with a .xo extension.

 ./setup.py dist_xo

To install the xo on a laptop you can use the installer script.

 sugar-install-bundle HelloWorld-1.xo

Trouble Shooting

You can find application logs in /home/olpc/.sugar/default/logs. If the sample fails to compile, sugar will show you the icon in the circle but remain forever at the "Starting..." tag when you hover your mouse over it. You'll have to restart sugar with <ctrl-alt-erase> in order to remove the icon. You can find the cause of your trouble in the the log named for the "service-name" in your activity.info file, in this case "org.laptop.HelloWorldActivity".

See also