65.9K
CodeProject 正在变化。 阅读更多。
Home

为 XO 笔记本开发 Mono 应用程序

starIconstarIconstarIconstarIconstarIcon

5.00/5 (18投票s)

2009年4月21日

CPOL

10分钟阅读

viewsIcon

124341

downloadIcon

191

了解如何使用Sugar OS上的Mono为XO笔记本(OLPC项目的机器)开发应用程序。

摘要

本文将教你如何为Sugar和XO(OLPC项目机器)开发应用程序。更准确地说,在本文中,我将使用C#和Mono创建一个新的“活动”,它可以在XO和可下载虚拟机中包含的Sugar模拟器上运行。

引言

关于OLPC项目和XO

One Laptop per Child

“每个孩子一台笔记本”协会开发了一种低成本笔记本电脑——“XO笔记本”——旨在彻底改变我们教育世界儿童的方式。OLPC项目的使命是通过为每个孩子提供一台坚固、低成本、低功耗、联网的笔记本电脑,并配有为协作、快乐、自主学习而设计的学习内容和软件,从而为世界上最贫困的儿童提供教育机会。

The XO laptop

简而言之,XO是一台上网本。XO具有创新的硬件设计,带有双模显示屏——全彩透射模式和黑白反射模式(阳光下可读)。这些笔记本电脑配备433 MHz处理器和256 MB DRAM,以及1GB NAND闪存(没有硬盘)。这些笔记本电脑具有无线宽带功能,可与标准接入点配合使用,也可作为网状网络使用——每台笔记本电脑都能与其最近的邻居进行通信,创建一个临时局域网(基于802.11s标准)。这些笔记本电脑使用各种直流电源输入(包括发条和太阳能)。

内置Sugar

Sugar是XO笔记本的操作系统。Sugar学习平台促进协作和批判性思维学习。它已在全球800,000台分发给发展中国家的XO笔记本上使用。Sugar得到全球庞大的开发人员和教师社区的支持。Sugar不仅适用于XO笔记本,也适用于所有其他笔记本电脑。

从技术上讲,Sugar基于Fedora Core Linux和Gnome用户界面。然而,Sugar也可以在其他Linux发行版(Debian、Fedora、Mandriva等)上使用。

Sugar Architecture

Sugar拥有独特的窗口管理器,概念简化,每个孩子都能很快理解。更重要的是,大部分界面可以由尚未学会阅读的儿童操作。

Sugar desktop

Mono

Mono项目是一个开放式开发倡议,旨在开发Microsoft .NET开发平台的开源版本。其目标是使Linux开发人员能够构建和部署跨平台.NET应用程序。该项目实现了Microsoft开发并提交给ECMA组织进行标准化的技术。

Mono

Mono不仅仅是一个“.NET克隆”。Mono带有一些独特的基于C#的组件、库和框架。其中最重要的是Gtk#,它允许用C#构建Gnome应用程序。Gtk#是Gtk+ GUI工具包的“绑定”。“绑定”一词意味着它允许直接从C#源代码调用本地库。

以下屏幕截图显示了一个使用命令行编译器的Mono基本示例。

A sample in Mono

如果你是一名.NET开发人员,这个示例应该看起来很熟悉。与.NET唯一的区别是,生成的*.EXE*文件不能直接在Linux上执行,因此你应该在命令行调用前加上*mono*。

创建你的第一个活动

Sugar化C#

Sugar主要用Python编写。Python是一种脚本语言,因此它是一个很好的工具,可以帮助用户自定义系统。如果你想创建新的应用程序(称为“活动”),Sugar将为你提供大量的Python API。

Torello Querci是Mono项目的贡献者。Torello一年前编写了一个C#/Sugar绑定,让你可以使用Mono创建Sugar活动。这个绑定被打包成一个名为*Sugar.dll*的.NET程序集。大多数Sugar API都可以从这个程序集调用。当然,这里描述的示例需要*Sugar.dll*程序集。

创建项目

要创建我们的第一个活动,我们将使用MonoDevelop。MonoDevelop是一个类似于Visual Studio的IDE。MonoDevelop允许你编辑和打包Mono应用程序。

开始吧

  • 启动MonoDevelop(应用程序/编程/MonoDevelop)。
  • 创建一个新解决方案(文件/新解决方案...),选择“C# / Gtk# 2.0项目”模板。
  • 在表单中填写“LabActivity”作为名称。

Choose a template in MonoDevelop

我们使用Gtk#模板是因为Sugar基于Gtk。现在让我们配置这个解决方案以添加Sugar绑定。

我们只需要添加*Sugar.dll*程序集。右键单击引用,“编辑引用...”,选择“.NET程序集”选项卡,然后选择正确的程序集。

Add the Sugar assembly as reference

就这样,解决方案现在准备好了。

创建主窗口

以下是为活动创建主窗口的源代码

using System;
using System.Collections;
using Gtk;
using Sugar;

namespace LabActivity
{ 
   public class MainWindow : Sugar.Window
   { 
        public new static string activityId = "";
        public new static string bundleId = ""; 

        public MainWindow(string activityId, string bundleId) 
            : base("Lab", activityId, bundleId) 
        { 
            this.SetDefaultSize(400, 400); 
            this.Maximize(); 
            this.DeleteEvent += new DeleteEventHandler(OnMainWindowDelete); 
            VBox vbox = new VBox(); 
            vbox.BorderWidth = 8; 
            Label _text = new Label("Hello Lab Activity"); 
            vbox.Add(_text); 
            Button _button = new Button(); 
            _button.Label = "Quit"; 
            _button.Clicked += new EventHandler(OnClick); 
            vbox.Add(_button); 
            this.Add(vbox); 
            ShowAll(); 
        } 

        void OnMainWindowDelete(object sender, DeleteEventArgs a) 
        { 
            Application.Quit(); 
            a.RetVal = true; 
        } 

        void OnClick(object sender, EventArgs a) 
        { 
            Application.Quit(); 
        } 
    }
}

如果你是一名.NET WinForms开发人员,Gtk框架应该会让你感到熟悉。

MainWindow的构造函数负责窗口初始化:它创建控件并设置事件处理程序。Sugar绑定增加了继承自Sugar.Window类的需求,以便访问与Sugar API的底层通信。更准确地说,主窗口应该处理活动的标识符和实例的标识符。这两个值都发送给窗口管理器,并且应该从活动的入口点检索。具体方法如下

public static void Main(string[] args)
{
    if (args.Length > 0)
    {
        IEnumerator en = args.GetEnumerator();
        while (en.MoveNext())
        {
            if (en.Current.ToString().Equals("-sugarActivityId"))
            {
                if (en.MoveNext())
                {
                    activityId = en.Current.ToString();
                }
            }
            if (en.Current.ToString().Equals("-sugarBundleId"))
            {
                if (en.MoveNext())
                {
                    bundleId = en.Current.ToString();
                }
            }
        }
    }

    Application.Init();
    new MainWindow(activityId, bundleId);
    Application.Run();
}

现在我们可以构建并运行新应用程序:点击“项目/运行”。你应该得到这个

Our sample activity on Ubuntu

这是第一次成功:我们得到了第一个符合Sugar的C# Gtk应用程序。

Mono捆绑包

运行.NET应用程序的先决条件是必须安装.NET Framework。当然,Mono也是如此,你的机器上必须安装Mono。不幸的是,Mono不是XO上的标准软件包,我们不能强迫每个用户预安装它来运行我们的应用程序。

幸运的是,Mono在.NET中提供了一个独特的功能:将Mono打包成可执行文件的能力。这就是我们所说的“捆绑包”。

捆绑包允许您生成一个可执行文件,其中嵌入了执行它所需的所有内容:.NET Framework的程序集、用户程序集以及用于将MSIL翻译成适合处理器的机器代码指令的JIT编译器。

A Mono bundle

上一个图表显示了Hello World应用程序的捆绑包。在左侧,*.EXE*文件只是一个标准程序集。该程序集仅包含应用程序的MSIL代码,并在运行时使用JIT编译器和.NET Framework。在右侧,我们创建了一个Mono捆绑包。该捆绑包嵌入了JIT编译器,并且只需要.NET Framework程序集。运行时不再需要其他任何东西。

以下是您如何使用`mkbundle2`命令为Hello World应用程序创建Mono捆绑包的方法

Our sample activity on Ubuntu

当然,*hello.exe*程序集和*hello*捆绑包做的是同样的事情。请注意,*hello*捆绑包不再需要*mono*前缀,并且非常庞大(4MB,而初始程序集只有3KB!)。

我们示例活动的Mono捆绑包未在此处显示,但可以以相同的方式构建。

构建.XO文件

在OLPC Wiki的活动页面上,您可以找到所有可在XO笔记本上下载的活动。

以下屏幕截图显示了此页面的一小部分。如您所见,下载新活动意味着下载一个*.XO*文件。让我们看看什么是“.xo”文件以及我们如何生成此类文件。

Activities on OLPC wiki

像其他常见文件格式(*.JAR*、*.DOCX*等)一样,*.XO*文件是一个zip文件,其中包含活动所需的所有文件:二进制文件和资源文件。我们将在下面描述它。

*.XO*文件中最重要的文件是清单。清单应位于文件的根目录。以下是活动清单(名为`MANIFEST`)的内容

activity/activity-labactivity.svg
activity/activity.info
bin/libgdksharpglue-2.so
bin/libgladesharpglue-2.so
bin/libglibsharpglue-2.so
bin/libgtksharpglue-2.so
bin/libMonoPosixHelper.so
bin/libpangosharpglue-2.so
bin/labactivity-activity
bin/labactivity.exe
bin/uiX11Util.so

清单文件描述了*.XO*文件中的所有文件。*.XO*文件有两个目录:*activity*用于存放活动的属性,*bin*用于存放二进制文件。

二进制文件包括:活动的Mono捆绑包(*labactivity.exe*)、Gtk#共享库(*.so*文件)以及一个启动活动的Python脚本(*labactivity-activity*)。

Activity目录中的第一个文件是Activity的图标。此文件使用SVG格式。SVG是一种基于XML的矢量格式。此处使用的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" 
       stroke="&stroke_color;" fill="&fill_color;" stroke-width="3.5"/>
</svg>

另一个重要的文件是*activity.info*文件。此文件包含活动的所有属性。这是我们的文件

[Activity]
name = LabActivity
activity_version = 1
host_version = 1
service_name = org.olpcfrance.LabActivity
icon = activity-labactivity
exec = labactivity-activity
mime_types =

*activity.info*文件只是一个文本文件,包含每个属性的值:名称、ID、图标文件的链接、启动脚本的链接等。

因此,总而言之,要创建*.xo*文件,您应该

  • 启动Mono应用程序的构建
  • 创建一个Mono捆绑包
  • 构建一个包含所有二进制文件和配置文件的*.zip*文件
  • 将文件从*.zip*重命名为*.xo*

项目源文件中包含的*deploy*脚本会自动构建*.XO*文件。您应该在每次构建结束时运行它。在脚本结束时,会生成一个*LabActivity-1.xo*文件

Generating XO file

运行活动

我们的活动可以安装在Sugar模拟器上。本文随附的虚拟机中提供的Ubuntu桌面上有此模拟器的快捷方式。

Sugar emulator shortcut

一旦启动,Sugar模拟器将显示Sugar主页

Sugar homepage in the emulator

要安装新的活动,首先点击终端活动(带美元符号的方块图标)。然后,在“.xo”文件上启动命令行*sugar-install-bundle*。此系统命令会解压软件包并添加活动。

Installing activity

活动的图标现在在桌面顶部可见(小白方块)。

Sample activity on the desktop

点击图标启动我们的活动

Our activity in Sugar

请注意,Gtk控件在Sugar上与在Ubuntu上略有不同:按钮是圆角的。

如果您有幸获得了一台XO机器,您可以使用USB密钥安装活动,事先将*.XO*文件放入其中,或者如果您之前已将*.XO*文件部署到网站上,则使用浏览活动。结果窗口与模拟器中的完全相同。

让你的应用程序“Sugar化”

本文的前一部分展示了如何从头开始编写一个新的活动。或者,您可能对移植现有应用程序感兴趣。这就是我们所说的“Sugar化”应用程序。Torello Querci在将现有Mono Gbrainy应用程序“Sugar化”方面做得非常出色。Gbrainy是基于记忆的小游戏合集。以下屏幕截图展示了XO上的应用程序。

Gbrainy in Sugar

Gbrainy最初是用纯Gtk编写的。Gbrainy也是一个有趣的应用程序,因为它使用了两个高级Mono特性:Glade和Gettext。

Glade 是Gtk的窗口设计工具。Glade带有一个专门的设计工具,并使用基于XML的文件格式来存储资源。

Gettext 是 Gnome 的本地化工具。`Mono.Unix` 命名空间允许从您的 C# 应用程序调用 Gettext。请注意,Gettext 和 .NET 的标准本地化机制都可以从 Mono 中使用。Gettext 的主要优点是得到了庞大的开发人员社区的支持,并且与许多常见工具兼容,例如 Pootle 服务器或 Poedit 编辑器。

以下源代码来自Sugar化的Gbrainy应用程序。您可以看到Sugar特性、Glade属性的使用(`[Glade.Widget]`)以及对本地化方法的一些调用(`Catalog.GetString(...)`)。

public class gbrainy
{
    [Glade.Widget("gbrainy")] Gtk.Window app_window;
    [Glade.Widget] Box drawing_vbox;
    [Glade.Widget] Gtk.Label question_label;
    [Glade.Widget] Gtk.Label solution_label;
    [Glade.Widget] Gtk.Entry answer_entry;
    [Glade.Widget] Gtk.Button answer_button;
    [Glade.Widget] Gtk.Button tip_button;
    [Glade.Widget] Gtk.Button next_button;
    [Glade.Widget] Gtk.Statusbar statusbar;
    [Glade.Widget] Gtk.Toolbar toolbar;
    GameDrawingArea drawing_area;
    GameSession session;
    const int ok_buttonid = -5;
    ToolButton pause_tbbutton;    
    string activityId="";
    string bundleId="";

    public gbrainy (string [] args, params object [] props) 
    {
        Catalog.Init ("gbrainy", Defines.GNOME_LOCALE_DIR);
        IconFactory icon_factory = new IconFactory ();
        AddIcon (icon_factory, "math-games", "math-games-32.png");
        AddIcon (icon_factory, "memory-games", "memory-games-32.png");
        AddIcon (icon_factory, "pause", "pause-32.png");
        AddIcon (icon_factory, "resume", "resume-32.png");
        AddIcon (icon_factory, "endgame", "endgame-32.png");
        AddIcon (icon_factory, "allgames", "allgames-32.png");
        AddIcon (icon_factory, "endprogram", "endprogram-32.png");
        icon_factory.AddDefault ();

        Glade.XML gXML = new Glade.XML (null, "gbrainy.glade", 
                                        "gbrainy", null);
        gXML.Autoconnect (this);
        Sugar.Activity activity = 
              new Sugar.Activity(app_window, activityId, bundleId);
        activity.SetActiveEvent += activeChanged;

        app_window.Show();

        toolbar.IconSize = Gtk.IconSize.Dnd;
            
        Tooltips tooltips = new Tooltips ();

        ToolButton button = new ToolButton ("allgames");
        button.SetTooltip (tooltips, 
           Catalog.GetString ("Play all the games"), null);
        button.Label = Catalog.GetString ("All");
        button.Clicked += OnAllGames;
        toolbar.Insert (button, -1);

        // ...
    }
    // ...
}

结论

本文是使用Mono进行Sugar开发的入门。Mono允许您利用您的.NET和C#技能为XO笔记本创建软件,为OLPC项目做出贡献,从而为世界上最贫困的儿童提供教育材料。何不抓住这个机会呢?

链接

本文来自SugarLabs wiki上的完整教程。法文版本也可在TechHead Brothers网站上获取。有关OLPC项目的更多信息,请随时与我联系。

© . All rights reserved.