Windows Phone 8 蓝牙应用开发教程及实例

开发者可以利用蓝牙的相关API来创建应用程序,在应用程序里面使用手机的蓝牙技术来进行近距离的文件传输和发送接收消息,创造出更加有趣和方便的应用软件。

    在Windows Phone 8里面可以在应用程序里面利用蓝牙进行通信,使用蓝牙相关的API,可以让应用程序连接到另外的一个应用程序,也可以让应用程序连接到一个设备上。Windows Phone 8的蓝牙技术支持两个蓝牙方案:一个是应用程序到应用程序的通信,另外一个是应用程序到设备的通信。

    1.应用程序到应用程序的通信

    应用程序到应用程序的通信的过程是,应用程序使用蓝牙去查找正在广播蓝牙服务的对等的应用程序,如果在应用程序提供服务的范围内发现一个应用程序,那么该应用程序可以发起连接请求。当这两个应用程序接受连接,它们之间就可以进行通信了,通信的过程是使用socket的消息发送接收机制。在Windows Phone 8中使用到应用程序到应用程序的蓝牙通讯技术,需要在项目的WMAppManifest.xml文件中添加ID_CAP_PROXIMITY的功能选项,表示支持临近的设备通信能力,否则程序会出现异常。

    2.应用程序到设备的通信

    在应用程序到设备的通信过程时,应用程序使用蓝牙去查找提供服务的设备,如果提供的服务范围之内发现一个可以连接的蓝牙设备,那么该应用程序可以发起连接请求。当应用程序和设备同时接受该连接,它们之间就可以进行通信了,通信的过程也是使用socket的消息发送接收机制,类似于应用程序到应用程序的通信。在Windows Phone 8中使用到应用程序到设备的蓝牙通讯技术,需要在项目的WMAppManifest.xml文件中添加ID_CAP_PROXIMITY和ID_CAP_NETWORKING的功能选项,表示支持临近的设备通信能力和网络通信能力,否则程序会出现异常。

蓝牙编程类

    在Windows Phone 8里面使用到蓝牙编程主要会用到PeerFinder类,PeerInformation类,StreamSocket类和ConnectionRequestedEventArgs类,这些类的说明如表19.1所示。因为蓝牙也是基于TCP协议进行消息传递了,所以需要用到Socket的相关的编程知识,以及StreamSocket类。PeerFinder类是蓝牙查找类,它的主要成员如表19.2所示。

表19.1 蓝牙编程类的说明

类名  说明

PeerFinder  
    
用于去查找附近的设备是否有运行和当前应用程序相同的应用程序,并且可以在两个应用程序之间建立起socket连接,从而可以进行通信。对等应用程序是在其他设备上运行的应用程序的另一个实例。

PeerInformation  
    
包含对等应用程序或设备的识别信息。

StreamSocket  
    
支持使用一个TCP的Socket流的网络通信。

ConnectionRequestedEventArgs  
    
表示传递到一个应用程序的ConnectionRequested事件的属性

表 19.2 PeerFinder类的成员

成员   说明

bool AllowBluetooth
    
指定 PeerFinder 类的此实例是否可以通过使用 Bluetooth 来连接   ProximityStreamSocket 对象。如果PeerFinder 的此实例可以通过使用   Bluetooth 来连接 ProximityStreamSocket 对象,则为   true;否则为false。默认为   true。

bool AllowInfrastructure
    
是否使用TCP/IP协议连接到StreamSocket

bool AllowWiFiDirect
    
指定 PeerFinder 类的此实例是否可以通过使用 Wi-Fi Direct 来连接   ProximityStreamSocket 对象。如果 PeerFinder 的此实例可以通过使用   Wi-Fi Direct 来连接 ProximityStreamSocket 对象,则为   true;否则为false。默认为   true。

IDictionary<string,  string> AlternateIdentities

获取要与其他平台上的对等应用程序匹配的备用 AppId 值列表。返回要与其他平台的对等类应用程序匹配的备用 AppId 值列表。

string DisplayName
    
获取或设置标识计算机到远程对等类的名称。

PeerDiscoveryTypes SupportedDiscoveryTypes
    
获取一个值,该值指示哪些发现选项可与 PeerFinder 类一同使用

event TypedEventHandler<object, ConnectionRequestedEventArgs>   ConnectionRequested
    
远程对等类使用 ConnectAsync 方法请求连接时发生。

event TypedEventHandler<object, TriggeredConnectionStateChangedEventArgs>   TriggeredConnectionStateChanged
    
在远程对等类的轻击笔势期间发生。

IAsyncOperation<   StreamSocket> ConnectAsync(PeerInformation peerInformation)
    
连接已发现了对 FindAllPeersAsync 方法的调用的对等类。peerInformation:表示连接到的对等类的对等类信息对象。返回通过使用所提供的临近StreamSocket 对象连接远程对等类的异步操作。

IAsyncOperation<IReadOnlyList<PeerInformation>>   FindAllPeersAsync()
    
适用于无线范围内运行相同应用程序的对等计算机的异步浏览。返回通过使用 Wi-Fi直连技术浏览对等类的异步操作。

void  Start(string peerMessage)
    
向临近设备上的对等类应用程序传递消息。

void   Stop()

停止查找对等类应用程序或广播对等类连接的过程

查找蓝牙设备和对等项

    查找在服务范围内的蓝牙设备和对等项是蓝牙编程的第一步,查找蓝牙设备和对等项中会使用到PeerFinder类的FindAllPeersAsync方法去进行查找,然后以异步的方式返回查找到的对等项列表的信息IReadOnlyList<PeerInformation>,注意要使查找对等的应用程序时,在调用FindAllPeersAsync方法前必须先调用PeerFinder类的Start方法,主要的目的是启动广播服务,让对方的应用程序也能查找到自己。PeerInformation包含三个属性:一个是DisplayName表示对等项的名字,这个名字一般都是由对方的设备的名称或者查找到的应用程序自身设置的现实名字,一个是HostName表示主机名字或者IP地址,还有一个属性是ServiceName表示服务名称或者TCP协议的端口号。然后可以利用查找到的PeerInformation信息进行连接和通信。

    查找对等的应用程序的代码示例:

async void AppToApp()
{
    // 启动查找服务
    PeerFinder.Start();
    //开始查找
    ObservableCollection<PeerInformation> peers = await PeerFinder.FindAllPeersAsync();
    if (peers.Count == 0)
    {
        //未找到任何的对等项
    }
    else
    {
        //处理查找到的对等项,可以使用PeerFinder类的ConnectAsync方法来连接选择的要进行通信的对等项
    }
}

查找蓝牙设备的代码示例:

 

private async void AppToDevice()
{
    // 设置查找所匹配的蓝牙设备
    PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
    // 开始查找
    ObservableCollection<PeerInformation> pairedDevices = await PeerFinder.FindAllPeersAsync();
    if (pairedDevices.Count == 0)
    {
        // 没有找到可用的蓝牙设备
    }
    else
    {
        //处理查找到的蓝牙设备,可以新建一个StreamSocket对象,然后使用StreamSocket类的ConnectAsync方法通过HostName和ServiceName来连接蓝牙设备
    }
}

 
蓝牙发送消息

    蓝牙编程的发送消息机制使用的是TCP的StreamSocket的方式,原理与Socket的一致。在蓝牙连接成功后,可以获取到一个StreamSocket类的对象,然后我们使用该对象的OutputStream属性来初始化一个DataWriter对象,通过DataWriter对象来进行发送消息。OutputStream属性表示的是Socket的输出流,用于发送消息给对方。下面来看一下发送消息的示例:

async void SendMessage(string message)
{
    // 连接选中的对等项,selectedPeer为查找到的PeerInformation对象
    StreamSocket _socket= = await PeerFinder.ConnectAsync(selectedPeer);
    // 创建DataWriter
    DataWriter _dataWriter = new DataWriter(_socket.OutputStream);
    // 先写入发送消息的长度
     _dataWriter.WriteInt32(message.Length);
     await _dataWriter.StoreAsync();
    // 最后写入发送消息的内容
     _dataWriter.WriteString(message);
     await _dataWriter.StoreAsync();
}

蓝牙接收消息

    蓝牙编程的接收消息机制同样也是使用的是TCP的StreamSocket的方式,原理与Socket的一致。在蓝牙连接成功后,可以获取到一个StreamSocket类的对象,然后我们使用该对象的InputStream属性来初始化一个DataReader对象,通过DataReader对象来进行接收消息。InputStream属性表示的是Socket的输入流,用于接收对方的消息。下面来看一下接收消息的示例:

async Task<string> GetMessage()
{
    // 连接选中的对等项,selectedPeer为查找到的PeerInformation对象
    StreamSocket _socket= = await PeerFinder.ConnectAsync(selectedPeer);
    // 创建DataReader
    DataReader _dataReader = new DataReader(_socket.InputStream);
    // 先读取消息的长度
    await _dataReader.LoadAsync(4);
    uint messageLen = (uint)_dataReader.ReadInt32();
    // 最后读取消息的内容
    await _dataReader.LoadAsync(messageLen);
    return _dataReader.ReadString(messageLen);
}

实例:实现蓝牙程序对程序的传输

下面给出蓝牙程序对程序传输的示例:通过使用蓝牙功能查找周边也要使用改应用的手机,互相建立起连接和发送测试消息。
代码清单19-1:蓝牙程序对程序传输(源代码:第19章\Examples_19_1)

 

MainPage.xaml文件主要代码

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
          <StackPanel>
            <Button x:Name="btFindBluetooth" Content="通过蓝牙查找该应用设备" Click="btFindBluetooth_Click"/>
            <ListBox x:Name="lbBluetoothApp"  ItemsSource="{Binding}" >
              <ListBox.ItemTemplate >
                <DataTemplate>
                  <StackPanel>
                    <TextBlock  Text="{Binding DisplayName}" />
                    <TextBlock  Text="{Binding ServiceName}" />     
                    <Button Content="连接" HorizontalAlignment="Left" Width="308" Height="91" Click="btConnect_Click"/>
                  </StackPanel>
                </DataTemplate>
              </ListBox.ItemTemplate>
            </ListBox>
          </StackPanel>
        </Grid>

MainPage.xaml.cs文件主要代码

using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using Windows.Networking.Proximity;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
namespace BluetoothDemo
{
    public partial class MainPage : PhoneApplicationPage
    {
        private StreamSocket _socket = null;  // Socket数据流对象
        private DataWriter _dataWriter;  // 数据写入对象
        private DataReader _dataReader; // 数据读取对象
        public MainPage()
        {
            InitializeComponent();      
            Loaded += MainPage_Loaded;//页面加载事件
        }
        // 查找蓝牙对等项按钮事件处理
        private async void btFindBluetooth_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                //开始查找对等项
                PeerFinder.Start();    
                // 等待找到的对等项
                var peers = await PeerFinder.FindAllPeersAsync();
                if (peers.Count == 0)
                {
                    MessageBox.Show("没有发现对等的蓝牙应用");
                }
                else
                {
                    // 把对等项目绑定到列表中
                    lbBluetoothApp.ItemsSource = peers;                
                }
            }
            catch(Exception ex)
            {
                if ((uint)ex.HResult == 0x8007048F)
                {
                    MessageBox.Show("Bluetooth已关闭请打开手机的蓝牙开关");
                }
                else
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
        // 连接蓝牙对等项的按钮事件处理
        private async void btConnect_Click(object sender, RoutedEventArgs e)
        {
            Button deleteButton = sender as Button;
            PeerInformation selectedPeer = deleteButton.DataContext as PeerInformation;
            // 连接到选择的对等项
            _socket = await PeerFinder.ConnectAsync(selectedPeer);
            // 使用输出输入流建立数据读写对象
            _dataReader = new DataReader(_socket.InputStream);
            _dataWriter = new DataWriter(_socket.OutputStream);
            // 开始读取消息
            PeerFinder_StartReader();
        }
        // 读取消息
        async void PeerFinder_StartReader()
        {
            try
            {
                uint bytesRead = await _dataReader.LoadAsync(sizeof(uint));
                if (bytesRead > 0)
                {
                    // 获取消息内容的大小
                    uint strLength = (uint)_dataReader.ReadUInt32();
                    bytesRead = await _dataReader.LoadAsync(strLength);
                    if (bytesRead > 0)
                    {
                        String message = _dataReader.ReadString(strLength);
                        MessageBox.Show("获取到消息:" + message);
                        // 开始下一条消息读取
                        PeerFinder_StartReader();
                    }
                    else
                    {
                        MessageBox.Show("对方已关闭连接");
                    }
                }
                else
                {
                    MessageBox.Show("对方已关闭连接");
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("读取失败: " + e.Message);
            }
        }
        // 页面加载事件处理
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            // 订阅连接请求事件
            PeerFinder.ConnectionRequested += PeerFinder_ConnectionRequested;
        }
        // 连接请求事件处理
        void PeerFinder_ConnectionRequested(object sender, ConnectionRequestedEventArgs args)
        {
            // 连接并且发送消息
            ConnectToPeer(args.PeerInformation);
        }
        // 连接并发送消息给对方
        async void ConnectToPeer(PeerInformation peer)
        {
            _socket = await PeerFinder.ConnectAsync(peer);
            _dataReader = new DataReader(_socket.InputStream);
            _dataWriter = new DataWriter(_socket.OutputStream);
            string message = "测试消息";
            uint strLength = _dataWriter.MeasureString(message);
            _dataWriter.WriteUInt32(strLength);//写入消息的长度
            _dataWriter.WriteString(message);//写入消息的内容
            uint numBytesWritten = await _dataWriter.StoreAsync();
        }
    }
}

程序的运行效果如图19.2所示。


实例:实现蓝牙程序对设备的连接

下面给出蓝牙程序对设备连接的示例:查找蓝牙设备,并对找到的第一个蓝牙设备进行连接。
代码清单19-2:蓝牙程序对设备连接(源代码:第19章\Examples_19_2)

MainPage.xaml文件主要代码

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <StackPanel>
        <Button x:Name="btFindBluetooth" Content="连接周围的蓝牙设备" Click="btFindBluetooth_Click"/>
    </StackPanel>
</Grid>

MainPage.xaml.cs文件主要代码

// 查找蓝牙设备事件处理
private async void btFindBluetooth_Click(object sender, RoutedEventArgs e)
{
    try
    {
        // 配置PeerFinder蓝牙服务的GUID去搜索设备
        PeerFinder.AlternateIdentities["Bluetooth:SDP"] = "5bec6b8f-7eba-4452-bf59-1a510745e99d";
        var peers = await PeerFinder.FindAllPeersAsync();
        if (peers.Count == 0)
        {
            Debug.WriteLine("没发现蓝牙设备");
        }
        else
        {
            // 连接找到的第一个蓝牙设备
            PeerInformation selectedPeer = peers[0];
            StreamSocket socket = new StreamSocket();
            await socket.ConnectAsync(selectedPeer.HostName, selectedPeer.ServiceName);
            MessageBox.Show("连接上了HostName:" + selectedPeer.HostName + "ServiceName:" + selectedPeer.ServiceName);
        }
    }
    catch (Exception ex)
    {
        if ((uint)ex.HResult == 0x8007048F)
        {
            MessageBox.Show("Bluetooth is turned off");
        }
    }
}

程序的运行效果如图19.3所示

window phone 8蓝牙详细开发案例说明

WP8蓝牙支持对等方应用连接,也支持其他蓝牙设备,下面我们看看如何连接到对等方应用和设备。

1)连接到对等方

[C#代码]

    //已经搜索到的对等方列表
    IReadOnlyList<PeerInformation> peers;

    // 开始连接到对等应用
    async void AppToApp()
    {
        // 开始查找对等项,如果有这句话,即可使自己能够被其他蓝牙设备搜索到
        PeerFinder.Start();

        peers = await PeerFinder.FindAllPeersAsync();

        if (peers.Count == 0)
        {
           // 没有发现
        }
        else
        {
            // 选择第一个对等应用
            PeerInformation selectedPeer = peers[0];
            // 连接到第一个对等方应用
            var streamSocket = await PeerFinder.ConnectAsync(selectedPeer);
        }
    }

2)连接到设备

PeerFinder.AlternateIdentities["Bluetooth:Paired"] = ""; 查找所有已配对的设备。这样连接找到的设备对应的PeerInformation.ServiceName将为空,所以我们不能通过PeerFinder.ConnectAsync(selectedPeer);的方式去连接,具体示例如下:

[C#代码]

    //搜寻全部蓝牙设备并连接第一个
    private async void AppToDevice()
    {
        // 搜索所有配对的设备
        PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
        var pairedDevices = await PeerFinder.FindAllPeersAsync();

        if (pairedDevices.Count == 0)
        {
            //没有发现设备
        }
        else
        {
            // 选择第一个连接的设备,此时selectedDevice.ServiceName为空
            PeerInformation selectedDevice = pairedDevices[0];

            // 主动创建一个StreamSocket
            StreamSocket socket = new StreamSocket();
            // 第二个参数是一个RFCOMM端口号,范围是1-30
            await socket.ConnectAsync(selectedDevice.HostName, "1");
        }
    }

PeerFinder.AlternateIdentities["Bluetooth:SDP"] = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";查找使用服务发现协议 (SDP) 并通过既定 GUID 播发服务的设备

[C#代码]

    //搜寻特定GUID的设备
    private async void AppToDevice2()
    {
        PeerFinder.AlternateIdentities["Bluetooth:SDP"] = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
        var pairedDevices = await PeerFinder.FindAllPeersAsync();

        if (pairedDevices.Count == 0)
        {
            //没有发现设备
        }
        else
        {
            // 选择第一个连接的设备
            PeerInformation selectedDevice = pairedDevices[0];

            // 主动创建一个StreamSocket
            StreamSocket socket = new StreamSocket();
            // 这种情况下selectedDevice.ServiceName等于您指定的GUID
            await socket.ConnectAsync(selectedDevice.HostName, selectedDevice.ServiceName);
        }
    }

3)侦听连接请求

[C#代码]

    public Page1()
    {
        InitializeComponent();
        //侦听连接请求需要先添加事件
        Loaded += MainPage_Loaded;
    }

    void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        //远程对等类异步连接时触发
        PeerFinder.ConnectionRequested += PeerFinder_ConnectionRequested;
    }
    async void PeerFinder_ConnectionRequested(object sender, ConnectionRequestedEventArgs args)
    {
        // 获取到请求连接的对等方
        var peer = args.PeerInformation;
        // 回应连接
        var streamSocket = await PeerFinder.ConnectAsync(peer);
    }

4)发送消息

[C#代码]

    /// <summary>
    /// 在已连接的情况下发送消息
    /// </summary>
    /// <param name="socket"></param>
    public async void Send(StreamSocket socket, string msg)
    {
        var _dataWriter = new DataWriter(socket.OutputStream);

        //写入消息的长度
        uint strLength = _dataWriter.MeasureString(msg);
        _dataWriter.WriteUInt32(strLength);

        //写入消息的内容
        _dataWriter.WriteString(msg);
        uint numBytesWritten = await _dataWriter.StoreAsync();
    }

5)接收消息

[C#代码]

    /// <summary>
    /// 在已连接的情况下读取消息
    /// </summary>
    /// <param name="socket"></param>
    public async Task<string> Read(StreamSocket socket)
    {
        var _dataReader = new DataReader(socket.InputStream);
        // 读取消息长度
        await _dataReader.LoadAsync(sizeof(uint));
        uint msgLength = (uint)_dataReader.ReadUInt32();
        // 读取消息的内容
        await _dataReader.LoadAsync(msgLength);
        return _dataReader.ReadString(msgLength);
    }

时间: 2024-09-18 22:39:21

Windows Phone 8 蓝牙应用开发教程及实例的相关文章

php版微信公众平台接口开发之智能回复开发教程_php实例

本文实例讲述了php版微信公众平台接口开发之智能回复功能实现方法.分享给大家供大家参考,具体如下: 智能回复是根据用户输入的条件来反馈结果用用户了,这个小编以前有做过信整理了一些例子供各位参考,比较完整主要是介绍在开发端了. 微信自推出后,着实火了一把,而支付功能的推出,又把微信推到了一个无可比拟的高度,然后申请微信订阅号或者服务号的人也开始比肩接踵.下面我将给大家简单讲解下微信公众平台开发接口. 先去 微信公众平台 申请账号,然后按照提示一步步.在选择订阅号和服务号上,个人只能申请订阅号,而且

iOS10推送通知开发教程_php实例

虽然通知经常被过度使用,但是通知确实是一种获得用户关注和通知他们需要更新或行动的有效方式.iOS 10有了新的通知,如新消息.商业信息和时间表的变化.在本教程中,我将向你展示如何使用通知在你的iOS应用程序,并且显示iOS 10引入了新特性.开发iOS 10推送通知你需要最新版本的Xcode,Xcode 8测试版,这些目前都是可下载的,在下载页面. 你可以去Github下载本教程的整个工程. 开始 在Xcode中启用推送通知是很容易的,但你需要几个步骤. 创建一个新的工程,给它起一个唯一的Bun

windows下apache搭建php开发环境_php实例

本文详细介绍了在Windows2003下使用Apache2.2.21/PHP5.3.5/Mysql5.5.19/phpMyAdmin3.4.9搭建php开发环境. 第一步:下载安装的文件 1. Apache 版本 httpd-2.2.21-win32-x86-no_ssl.msi 2. MySQL 版本 mysql-5.5.19-win32.msi 3. PHP 版本 php-5.3.5-Win32-VC6-x86.zip 4. phpMyadmin 版本 phpMyAdmin-3.4.9-al

PHP实现微信网页授权开发教程_php实例

微信网页授权是服务号才有的高级功能,开发者可以通过授权后获取用户的基本信息:在此之前,想要获取消息信息只能在用户和公众号交互时根据openid获取用户信息:而微信网页授权可在不需要消息交互,也不需要关注的情况下获取用户的基本信息. 微信网页授权时通过OAuth2.0完成的,整个过程分为三步: 用户授权,获取code: 根据code获取access_token[可通过refresh_token刷新获取较长有效期] 通过access_token和openid获取用户信息 对微信网页授权过程做了简单封

php支付宝在线支付接口开发教程_php实例

1.什么是第三方支付 所谓第三方支付,就是一些和各大银行签约.并具备一定实力和信誉保障的第三方独立机构提供的交易支持平台.在通过第三方支付平台的交易中,买方选购商品后,使用第三方平台提供的账户进行货款支付,由第三方通知卖家货款到达. 目前提供第三方支付的机构很多,常见的有支付宝.财付通.快钱.网银在线.易宝支付.云网等各大支付平台.网站如果需要实现第三方支付首先应该向第三方支付平台申请一个账号并签署协议,协议生效后第三方支付平台将为其开通在线支付功能,通过程序将接口集成到网站中. 为什么要使用第

Windows Phone 7开发教程(4)——XNA显示中文字体

我最近勤快地连自己都有些不可思议.昨天有朋友在上一篇文章里留言,批 评Windows Phone 7暂时没有支持中文版的问题.凡事都有个过程,在中文版出 来前,咱们想自己想点办法吧.Silverlight for Windows Phone那边就不管了 ,肯定会有人想出办法来的.如何让Windows Phone 7游戏显示中文?把说"贴 图"的那个人拖出去打死!因为XNA 4.0中支持中文的办法倒是现成的,这与XNA 字体支持的方式有很大关系. 示例代码下载地址: http://fil

windows下的蓝牙开发环境搭建

问题描述 windows下的蓝牙开发环境搭建 求sdk安装包或下载网址,其中包含了蓝牙开发必须的库和头文件 解决方案 从MSDN查找,相关API估计也可以不需要特定sdk支持,在基础sdk下动态调用 解决方案二: windows下 搭建 wxWidgets 开发环境[转]Windows下搭建Android开发环境 解决方案三: 蓝牙开发环境怎么搭建,初学者.恳请大神的相助!!!

Windows下Ruby on Rails开发环境安装配置图文教程_ruby专题

本文详细介绍如何在Windows配置Ruby on Rails 开发环境,希望对ROR初学者能有帮助. 一.下载并安装Ruby Windows下安装Ruby最好选择 RubyInstaller(一键安装包). 下载地址: http://rubyforge.org/frs/?group_id=167 . 我们这里下载目前较新的rubyinstaller-1.9.3-p0.exe 一键安装包.这个安装包除了包含ruby本身,还有许多有用的扩展(比如gems)和 帮助文档. 双击安装,安装过程出现如下

Android简明开发教程十二:引路蜂二维图形库简介及颜色示例

AndroidGraphics2DTutorial定义了应用的主Activity,下面就可以开始写每个具体的二维绘图示例.不同的例子将尽量采用 不同的UI控件:Menu,Content Menu,Dialog,Custom Dialog,Button等等.例子采用了引路蜂二维图形库,引路蜂二维图形 库Graphics 2D API实现了移动平台(Java ME,Blackberry,iPhone,Android,Windows Phone)上图形引擎,它能够以一种统一的方 式处理各种基本图形(S