当前访客身份:游客 [ 登录 | 加入开源中国 ]

代码分享

当前位置:
代码分享 » WPF/SliverLight  » 手机App开发
分享到: 
收藏 +0
1

Windows Phone 8 SDK 中让人兴奋的一个 API 就是 Proximity API(接近API)。这个 API 可以让应用程序通过蓝牙连接、Wi-Fi Direct 和 NFC 来分享数据。下面这个例子非常简单,没有实际用途,但可作为入门。

这个例子中,使用 PeerFinder 来处理连接的等待和接收,以及异步搜索对等连接点,一旦连接建立就可以通过 socket 来读写二进制数据。相当简单!

标签: Windows Phone 蓝牙

代码片段(3) [全屏查看所有代码]

1. [文件] PhoneApp1.zip ~ 221KB     下载(138)     [全屏预览]

2. [代码]MainPage.xaml.cs     跳至 [2] [3] [全屏预览]

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Windows.Foundation;
using Windows.Networking.Proximity;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

namespace PhoneApp1
{
    public partial class MainPage : PhoneApplicationPage
    {
        private IReadOnlyList<PeerInformation> _peerInformationList;
        private PeerInformation _requestingPeer;
        private StreamSocket _socket = null;
        private bool _socketClosed = true;
        private DataWriter _dataWriter;
        private DataReader _dataReader;
        private bool _triggeredConnectSupported = false;

        bool _isLaunchedByTap = false;
        private bool _browseConnectSupported = false;
        // Constructor
        public MainPage()
        {
            InitializeComponent();
            Loaded += MainPage_Loaded;
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            _triggeredConnectSupported = (PeerFinder.SupportedDiscoveryTypes & PeerDiscoveryTypes.Triggered) ==
                             PeerDiscoveryTypes.Triggered;
            _browseConnectSupported = (PeerFinder.SupportedDiscoveryTypes & PeerDiscoveryTypes.Browse) ==
                                      PeerDiscoveryTypes.Browse;
            if (_triggeredConnectSupported || _browseConnectSupported)
            {
                // This scenario demonstrates "PeerFinder" to browse for peers to connect to using a StreamSocket
                PeerFinder_StartFindingPeersButton.Click += new RoutedEventHandler(PeerFinder_StartFindingPeers);
                PeerFinder_BrowsePeersButton.Click += new RoutedEventHandler(PeerFinder_BrowsePeers);
                PeerFinder_ConnectButton.Click += new RoutedEventHandler(PeerFinder_Connect);
                PeerFinder_AcceptButton.Click += new RoutedEventHandler(PeerFinder_Accept);
                PeerFinder_SendButton.Click += new RoutedEventHandler(PeerFinder_Send);
                PeerFinder_StartFindingPeersButton.Visibility = Visibility.Visible;
            }
        }
        string[] rgConnectState = {"PeerFound", 
                                   "Listening",
                                   "Connecting",
                                   "Completed",
                                   "Canceled",
                                   "Failed"};
        public void NotifyUser(string strMessage, NotifyType type)
        {
            Dispatcher.BeginInvoke( () =>
            {
                switch (type)
                {
                    // Use the status message style.
                    case NotifyType.StatusMessage:
                        MessageBox.Show(strMessage,"Status",MessageBoxButton.OK);
                        break;
                    // Use the error message style.
                    case NotifyType.ErrorMessage:
                        MessageBox.Show(strMessage,"Error",MessageBoxButton.OK);
                        break;
                }
            });
        }
         private void TriggeredConnectionStateChangedEventHandler(object sender, TriggeredConnectionStateChangedEventArgs eventArgs)
        {
            
            if (eventArgs.State == TriggeredConnectState.PeerFound)
            {
                // Use this state to indicate to users that the tap is complete and
                // they can pull there devices away.
                NotifyUser("Tap complete, socket connection starting!", NotifyType.StatusMessage);
            }

            if (eventArgs.State == TriggeredConnectState.Completed)
            {
                NotifyUser("Socket connect success!", NotifyType.StatusMessage);
                // Grab the socket that just connected.
                _socket = eventArgs.Socket;
                Dispatcher.BeginInvoke(() =>
                {
                    this.PeerFinder_StartSendReceive();
                });

            }

            if (eventArgs.State == TriggeredConnectState.Failed)
            {
                NotifyUser("Socket connect failed!", NotifyType.ErrorMessage);
            }
        }

        private bool _peerFinderStarted = false;

        private void SocketError(String errMessage)
        {
            NotifyUser(errMessage, NotifyType.ErrorMessage);
            PeerFinder_StartFindingPeersButton.Visibility = Visibility.Visible;
            if (_browseConnectSupported)
            {
                PeerFinder_BrowsePeersButton.Visibility = Visibility.Visible;
            }
            PeerFinder_SendButton.Visibility = Visibility.Collapsed;
            PeerFinder_MessageBox.Visibility = Visibility.Collapsed;
            if (!_socketClosed)
            {
                _socketClosed = true;
                _socket.Dispose();

                _socket = null;
            }
        }

        async private void PeerFinder_Send(object sender, RoutedEventArgs e)
        {
            NotifyUser("", NotifyType.ErrorMessage);
            String message = PeerFinder_MessageBox.Text;
            PeerFinder_MessageBox.Text = ""; // clear the input now that the message is being sent.
            if (!_socketClosed)
            {
                if (message.Length > 0)
                {
                    try
                    {
                        uint strLength = _dataWriter.MeasureString(message);
                        _dataWriter.WriteUInt32(strLength);
                        _dataWriter.WriteString(message);
                        uint numBytesWritten = await _dataWriter.StoreAsync();
                        if (numBytesWritten > 0)
                        {
                            NotifyUser("Sent message: " + message + ", number of bytes written: " + numBytesWritten, NotifyType.StatusMessage);

                        }
                        else
                        {
                            SocketError("The remote side closed the socket");
                        }
                    }
                    catch (Exception err)
                    {
                        if (!_socketClosed)
                        {
                            SocketError("Failed to send message with error: " + err.Message);
                        }
                    }
                }
                else
                {
                    NotifyUser("Please type a message", NotifyType.ErrorMessage);
                }
            }
            else
            {
                SocketError("The remote side closed the socket");
            }
        }

        async private void PeerFinder_Accept(object sender, RoutedEventArgs e)
        {
            NotifyUser("Connecting to " + _requestingPeer.DisplayName + "....", NotifyType.StatusMessage);
            PeerFinder_AcceptButton.Visibility = Visibility.Collapsed;
            try
            {
                _socket = await PeerFinder.ConnectAsync(_requestingPeer);
                NotifyUser("Connection succeeded", NotifyType.StatusMessage);
                PeerFinder_StartSendReceive();
            }
            catch (Exception err)
            {
                NotifyUser("Connection to " + _requestingPeer.DisplayName + " failed: " + err.Message, NotifyType.ErrorMessage);
            }
        }

        private void PeerConnectionRequested(object sender, ConnectionRequestedEventArgs args)
        {
            _requestingPeer = args.PeerInformation;
             Dispatcher.BeginInvoke( () =>
            {
                NotifyUser("Connection requested from peer " + args.PeerInformation.DisplayName, NotifyType.StatusMessage);

                this.PeerFinder_AcceptButton.Visibility = Visibility.Visible;
                this.PeerFinder_SendButton.Visibility = Visibility.Collapsed;
                this.PeerFinder_MessageBox.Visibility = Visibility.Collapsed;
            });
        }

        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);
                        NotifyUser("Got message: " + message, NotifyType.StatusMessage);
                        PeerFinder_StartReader(); // Start another reader
                    }
                    else
                    {
                        SocketError("The remote side closed the socket");
                    }
                }
                else
                {
                    SocketError("The remote side closed the socket");
                }
            }
            catch (Exception e)
            {
                if (!_socketClosed)
                {
                    SocketError("Reading from socket failed: " + e.Message);
                }
            }
        }

        // Start the send receive operations
        void PeerFinder_StartSendReceive()
        {
            PeerFinder_SendButton.Visibility = Visibility.Visible;
            PeerFinder_MessageBox.Visibility = Visibility.Visible;

            // Hide the controls related to setting up a connection
            PeerFinder_ConnectButton.Visibility = Visibility.Collapsed;
            PeerFinder_AcceptButton.Visibility = Visibility.Collapsed;
            PeerFinder_FoundPeersList.Visibility = Visibility.Collapsed;
            PeerFinder_BrowsePeersButton.Visibility = Visibility.Collapsed;
            PeerFinder_StartFindingPeersButton.Visibility = Visibility.Collapsed;
            _dataReader = new DataReader(_socket.InputStream);
            _dataWriter = new DataWriter(_socket.OutputStream);
            _socketClosed = false;
            PeerFinder_StartReader();
        }

        async void PeerFinder_Connect(object sender, RoutedEventArgs e)
        {
            NotifyUser("", NotifyType.ErrorMessage);
            PeerInformation peerToConnect = null;
            try
            {
                // If nothing is selected, select the first peer
                if (PeerFinder_FoundPeersList.SelectedIndex == -1)
                {
                    peerToConnect = _peerInformationList[0];
                }
                else
                {
                    peerToConnect = _peerInformationList[PeerFinder_FoundPeersList.SelectedIndex];
                }

               NotifyUser("Connecting to " + peerToConnect.DisplayName + "....", NotifyType.StatusMessage);
                _socket = await PeerFinder.ConnectAsync(peerToConnect);
                NotifyUser("Connection succeeded", NotifyType.StatusMessage);
                PeerFinder_StartSendReceive();
            }
            catch (Exception err)
            {
                NotifyUser("Connection to " + peerToConnect.DisplayName + " failed: " + err.Message, NotifyType.ErrorMessage);
            }
        }

        async void PeerFinder_BrowsePeers(object sender, RoutedEventArgs e)
        {
            NotifyUser("Finding Peers...", NotifyType.StatusMessage);
            try
            {
                _peerInformationList = await PeerFinder.FindAllPeersAsync();
            }
            catch (Exception ex)
            {
                Debug.WriteLine("FindAll throws exception" + ex.Message);
            }
            Debug.WriteLine("Async operation completed");
            NotifyUser("No peers found", NotifyType.StatusMessage);
            try{
            if (_peerInformationList.Count > 0)
            {
                PeerFinder_FoundPeersList.Items.Clear();
                for (int i = 0; i < _peerInformationList.Count; i++)
                {
                    ListBoxItem item = new ListBoxItem();
                    item.Content = _peerInformationList[i].DisplayName;
                    PeerFinder_FoundPeersList.Items.Add(item);
                }
                PeerFinder_ConnectButton.Visibility = Visibility.Visible;
                PeerFinder_FoundPeersList.Visibility = Visibility.Visible;
                NotifyUser("Finding Peers Done", NotifyType.StatusMessage);
            }}
            catch
            {
                NotifyUser("No peers found", NotifyType.StatusMessage);
                PeerFinder_ConnectButton.Visibility = Visibility.Collapsed;
                PeerFinder_FoundPeersList.Visibility = Visibility.Collapsed;
            }
        }

        void PeerFinder_StartFindingPeers(object sender, RoutedEventArgs e)
        {
            NotifyUser("", NotifyType.ErrorMessage);
            if (!_peerFinderStarted)
            {
                // attach the callback handler (there can only be one PeerConnectProgress handler).
                PeerFinder.TriggeredConnectionStateChanged += new TypedEventHandler<object, TriggeredConnectionStateChangedEventArgs>(TriggeredConnectionStateChangedEventHandler);
                // attach the incoming connection request event handler
                PeerFinder.ConnectionRequested += new TypedEventHandler<object, ConnectionRequestedEventArgs>(PeerConnectionRequested);
                // start listening for proximate peers
                PeerFinder.Start();
                _peerFinderStarted = true;
                if (_browseConnectSupported && _triggeredConnectSupported)
                {
                    NotifyUser("Tap another device to connect to a peer or click Browse for Peers button.", NotifyType.StatusMessage);
                    PeerFinder_BrowsePeersButton.Visibility = Visibility.Visible;
                }
                else if (_triggeredConnectSupported)
                {
                    NotifyUser("Tap another device to connect to a peer.", NotifyType.StatusMessage);
                }
                else if (_browseConnectSupported)
                {
                    NotifyUser("Click Browse for Peers button.", NotifyType.StatusMessage);
                }
            }
        }

        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.  The Parameter
        /// property is typically used to configure the page.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (_triggeredConnectSupported || _browseConnectSupported)
            {
                // Initially only the advertise button should be visible.
                PeerFinder_StartFindingPeersButton.Visibility = Visibility.Visible;
                PeerFinder_BrowsePeersButton.Visibility = Visibility.Collapsed;
                PeerFinder_ConnectButton.Visibility = Visibility.Collapsed;
                PeerFinder_FoundPeersList.Visibility = Visibility.Collapsed;
                PeerFinder_SendButton.Visibility = Visibility.Collapsed;
                PeerFinder_AcceptButton.Visibility = Visibility.Collapsed;
                PeerFinder_MessageBox.Visibility = Visibility.Collapsed;
                PeerFinder_MessageBox.Text = "Hello World";
                if (IsLaunchedByTap())
                {
                    NotifyUser("Launched by tap", NotifyType.StatusMessage);
                    PeerFinder_StartFindingPeers(null, null);
                }
                else
                {
                    if (!_triggeredConnectSupported)
                    {
                        NotifyUser("Tap based discovery of peers not supported", NotifyType.ErrorMessage);
                    }
                    else if (!_browseConnectSupported)
                    {
                        NotifyUser("Browsing for peers not supported", NotifyType.ErrorMessage);
                    }
                }
            }
            else
            {
                NotifyUser("Tap based discovery of peers not supported \nBrowsing for peers not supported", NotifyType.ErrorMessage);
            }
        }

        // Invoked when the main page navigates to a different scenario
        protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            if (_peerFinderStarted)
            {
                // detach the callback handler (there can only be one PeerConnectProgress handler).
PeerFinder.TriggeredConnectionStateChanged -= new TypedEventHandler<object, TriggeredConnectionStateChangedEventArgs>(TriggeredConnectionStateChangedEventHandler);
                // detach the incoming connection request event handler
                PeerFinder.ConnectionRequested -= new TypedEventHandler<object, ConnectionRequestedEventArgs>(PeerConnectionRequested);
                PeerFinder.Stop();
                if (_socket != null)
                {
                    _socketClosed = true;
                    _socket.Dispose();

                    _socket = null;
                }
                _peerFinderStarted = false;
            }
        }
        public bool IsLaunchedByTap()
        {
            bool isLaunchedByTap = _isLaunchedByTap;
            _isLaunchedByTap = false;
            return isLaunchedByTap;
        }
        public enum NotifyType
        {
            StatusMessage,
            ErrorMessage
        };
    }
}

3. [代码]MainPage.xaml     跳至 [2] [3] [全屏预览]

<phone:PhoneApplicationPage
    x:Class="PhoneApp1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="{Binding Path=LocalizedResources.ApplicationTitle, Source={StaticResource LocalizedStrings}}" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock Text="{Binding Path=LocalizedResources.PageTitle, Source={StaticResource LocalizedStrings}}" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <StackPanel Orientation="Vertical" Margin="0,10,0,0" Grid.Row="0">
                <Button x:Name="PeerFinder_StartFindingPeersButton" Content="Advertise" Visibility="Collapsed" Margin="0,0,10,0"/>
                <Button x:Name="PeerFinder_BrowsePeersButton" Content="Browse for Peers" Visibility="Collapsed" Margin="0,0,10,0"/>
                <Button x:Name="PeerFinder_ConnectButton" Content="Connect To a Peer" Visibility="Collapsed" Margin="0,0,10,0"/>
                <ListBox x:Name="PeerFinder_FoundPeersList" Visibility="Collapsed">
                </ListBox>
            </StackPanel>
            <StackPanel Orientation="Vertical" Margin="0,10,0,0" Grid.Row="1">
                <Button x:Name="PeerFinder_AcceptButton" Content="Accept Connection Request" Visibility="Collapsed" Margin="0,0,10,0"/>
                <Button x:Name="PeerFinder_SendButton" Content="Send Message" Visibility="Collapsed" Margin="0,0,10,0"/>
                <TextBox x:Name="PeerFinder_MessageBox" Visibility="Collapsed" Width="400" Margin="0,0,10,0"/>
            </StackPanel>
        </Grid>

        <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
            <TextBlock x:Name="PeerFinderOutputText" TextWrapping="Wrap" />

        </Grid>


        <!--Uncomment to see an alignment grid to help ensure your controls are
            aligned on common boundaries.  Remove or comment out before shipping
            your application.-->
        <!--<Image Margin="0" Source="/Assets/AlignmentGrid.png" Stretch="None" IsHitTestVisible="False" />-->
    </Grid>

</phone:PhoneApplicationPage>


开源中国-程序员在线工具:Git代码托管 API文档大全(120+) JS在线编辑演示 二维码 更多»

发表评论 回到顶部 网友评论(5)

  • 1楼:李恒哲 发表于 2012-08-24 09:08 回复此评论

    红薯也开始研究WP的代码了,我们WPer的一大福音啊

  • 2楼:省委书记沙瑞金 发表于 2012-08-24 12:39 回复此评论
    在哪儿搞得8.的SDK啊
  • 3楼:hy86 发表于 2012-08-25 11:11 回复此评论

    引用来自“李恒哲”的评论

    红薯也开始研究WP的代码了,我们WPer的一大福音啊

    红薯的文章涉及从前台到后台,移动等几乎所有领域了,而且还对众多框架的源码有研究,还要写出文章,还要管理网站,还要开会,还要参加源创会,还要睡觉吃饭……红薯不可能是超人吧,他招的人是干嘛的,肯定就是收录或翻译最新IT文章及写一些研究技术源码的文章吧
  • 4楼:fys 发表于 2012-08-28 13:12 回复此评论

    引用来自“yangzy666”的评论

    引用来自“李恒哲”的评论

    红薯也开始研究WP的代码了,我们WPer的一大福音啊

    红薯的文章涉及从前台到后台,移动等几乎所有领域了,而且还对众多框架的源码有研究,还要写出文章,还要管理网站,还要开会,还要参加源创会,还要睡觉吃饭……红薯不可能是超人吧,他招的人是干嘛的,肯定就是收录或翻译最新IT文章及写一些研究技术源码的文章吧
    大哥适合去说相声,大喘气,挺搞笑!
  • 5楼:寒光悲秋 发表于 2013-09-27 14:16 回复此评论
    为什么我的wp8就不能运行这个呢,蓝牙不能调用。
开源从代码分享开始 分享代码