Windows 8.1 store app 开发笔记

简介: 原文:Windows 8.1 store app 开发笔记零、简介   一切都要从博彦之星比赛说起。今年比赛的主题是使用Bing API(主要提到的有Bing Map API、Bing Translate API和Bing AD API)设计移动应用(Windows store app和Windows phone app)。
原文: Windows 8.1 store app 开发笔记

零、简介

  一切都要从博彦之星比赛说起。今年比赛的主题是使用Bing API(主要提到的有Bing Map API、Bing Translate API和Bing AD API)设计移动应用(Windows store app和Windows phone app)。从7月初开始设计到现在,应用的功能已经基本完成,就差美工来给界面优化一下。下面是我设计的应用的功能和实现的方法,

一、BING MAP API

  作为一个以Bing Map API为主的应用,主要有以下的功能:

  1、定位:

 1 private LocationRange range = null;
 2         private CancellationTokenSource cts = null;
 3         private Geolocator geolocator = null;
 4 
 5 private async void locateButton_Click(object sender, RoutedEventArgs e)
 6         {
 7             // 根据定位按钮的标签判定是“定位”或“取消定位”
 8             if (locateButton.Label == "定位")
 9             {
10                 locateButton.Label = "取消定位";
11                 try
12                 {
13                     // 获得cancellation token
14                     cts = new CancellationTokenSource();
15                     CancellationToken token = cts.Token;
16                     this.infoBlock.Text = "正在定位";
17 
18                     // 获得位置
19                     Geoposition pos = await geolocator.GetGeopositionAsync().AsTask(token);
20                     this.infoBlock.Text = "定位成功";
21                     // App.location是在App.xaml.cs中用于保存定位位置的全局变量
22                     App.location = new Location(pos.Coordinate.Point.Position.Latitude, pos.Coordinate.Point.Position.Longitude);
23 
24                     // 设置默认地图缩放等级
25                     double zoomLevel = 13.0f;
26                     // range是一个自定义控件,用一个大圆来涵盖定位区域
27                     MapLayer.SetPosition(range, App.location);
28                     rangeLayer.Children.Add(range);
29                     zoomLevel = 15.0f;
30 
31                     // 设置地图视野到给定的位置和缩放等级
32                     map.SetView(App.location, zoomLevel);
33                 }
34                 catch (System.UnauthorizedAccessException)
35                 {
36                     this.infoBlock.Text = "定位请求被拒绝";
37                 }
38                 catch (TaskCanceledException)
39                 {
40                     this.infoBlock.Text = "定位被取消";
41                 }
42                 catch (System.Exception)
43                 {
44                     this.infoBlock.Text = "暂时无法获得您的位置";
45                 }
46                 finally
47                 {
48                     cts = null;
49                 }
50                 // 重置按钮
51                 locateButton.Label = "定位";
52                 //locateButton.Icon = ;
53             }
54             else
55             {
56                 // 取消定位
57                 if (cts != null)
58                 {
59                     cts.Cancel();
60                     cts = null;
61                 }
62                 // 重置按钮
63                 locateButton.Label = "定位";
64                 //locateButton.Icon = ;
65             }
66         }            
locateButton_Click

  2、添加图钉:

 1 private async void AddPinButton_Click(object sender, RoutedEventArgs e)
 2         {
 3             // 实例化一个图钉类(这个图钉类是我自定义的)
 4             pin = new MapediaPin(map);
 5             // 为图钉添加Drag和Tap触发方法(当然还有Hold等)
 6             pin.drag += pin_Dragged;
 7             pin.Tapped += pin_Tapped;
 8             //将图钉显示到地图的中央
 9             MapLayer.SetPosition(pin, map.Center);
10             pinLayer.Children.Add(pin);
11         }
AddPinButton_Click

  3、拖动图钉:

 1 private bool isDragging = false;        // pin正在拖拽标志
 2 
 3         // 当pin被拖动时激活
 4         public Action<Location> drag;
 5         // 当pin开始被拖动时激活
 6         public Action<Location> dragStart;
 7         // 当pin停止拖动时激活
 8         public Action<Location> dragEnd;
 9         // 当pin被按下时,得到被按下pin的ID,判断是否可拖动,执行操作
10         protected override void OnPointerPressed(PointerRoutedEventArgs e)
11         {
12             base.OnPointerPressed(e);
13 
14             // 如果可以被拖动则开始拖动
15             if (draggable)
16             {
17                 if (map != null)
18                 {
19                     center = map.Center;
20                     // 为map的下列方面重写
21                     map.ViewChanged += map_ViewChanged;
22                     map.PointerReleasedOverride += map_PointerReleased;
23                     map.PointerMovedOverride += map_PointerMoved;
24                 }
25                 // 得到当前鼠标位置
26                 var pointerPosition = e.GetCurrentPoint(map);
27                 Location location = null;
28                 // 开始拖动
29                 if (dragStart != null)
30                 {
31                     dragStart(location);
32                 }
33 
34                 this.isDragging = true;
35             }
36         }
37 
38         // 当pin被移动时
39         private void map_PointerMoved(object sender, PointerRoutedEventArgs e)
40         {
41             // 检查是否正在被拖动
42             if (this.isDragging)
43             {
44                 // 随着鼠标移动图标
45                 var pointerPosition = e.GetCurrentPoint(map);
46 
47                 Location location = null;
48 
49                 if (map.TryPixelToLocation(pointerPosition.Position, out location))
50                 {
51                     // 将图钉(this)移到到当前鼠标的位置(location)
52                     MapLayer.SetPosition(this, location);
53                 }
54                 if (drag != null)
55                 {
56                     drag(location);
57                 }
58             }
59         }
60 
61         // 当pin被松开时
62         private void map_PointerReleased(object sender, PointerRoutedEventArgs e)
63         {
64             if (this.isDragging)
65             {
66                 if (map != null)
67                 {
68                     map.ViewChanged -= map_ViewChanged;
69                     map.PointerReleasedOverride -= map_PointerReleased;
70                     map.PointerMovedOverride -= map_PointerMoved;
71                 }
72 
73                 var pointerPosition = e.GetCurrentPoint(map);
74                 Location location;
75                 map.TryPixelToLocation(pointerPosition.Position, out location);
76                 // 得到最终的经纬度
77                 latitude = location.Latitude;
78                 longitude = location.Longitude;
79 
80                 location = null;
81 
82                 if (dragEnd != null)
83                 {
84                     dragEnd(location);
85                 }
86 
87                 this.isDragging = false;
88                 this.draggable = false;
89             }
90         }
PinDrag

二、BING TRANSLATE API

  用的这个API的地方,是在对图钉上面的信息进行翻译的时候:

  翻译:

 1 private HttpClient client = null;            // 用于通信的HTTP客户端
 2 
 3         private async void translateButton_Click(object sender, RoutedEventArgs e)
 4         {
 5             // 根据translateButton的标签判定是“翻译”或“取消翻译”
 6             if (translateButton.Label == "翻译")
 7             {
 8                 // 进行网络检查(方法见 五、UTILITIES)
 9                 if (!App.CheckNetwork())
10                 {
11                     //this.infoBlock.Text = "无网络连接,请检查网络";
12                 }
13                 else
14                 {
15                     try
16                     {
17                         this.infoBlock.Text = "正在检查网络连接...";
18                         string clientID = "你的clientID";
19                         string clientSecret = "你的clientSecret";
20                         //AzureDataMarket可以从网上找到,是一个已经写好的用于在Azure进行验证的类
21                         var _Authentication = new AzureDataMarket(clientID, clientSecret);
22                         AzureDataMarket.Token m_Token = await _Authentication.GetTokenAsync();
23                         string auth = m_Token.Header;
24                         //实例化该类,以便于后面发送Http请求获取网络数据
25                         client = new HttpClient();
26                         //设置读取响应内容时缓冲区的最大字节数
27                         client.MaxResponseContentBufferSize = 256000;
28                         //设置请求头部
29                         client.DefaultRequestHeaders.Add("Authorization", auth);
30                     }
31                     catch
32                     {
33                         //this.infoBlock.Text = "连接到服务器失败";
34                     }
35                 }
36             }
37             else
38             {
39                 this.translateButton.Label = "翻译";
40             }
41         }
42 
43         // 将descriptionBlock中的内容翻译成language所表示的语言
44         private async void translate(String language)
45         {
46             //language可表示的语言:ar bg ca zh-CHS zh-CHT cs da nl en et fi fr de el ht he hi mww hu id it ja tlh tlh-Qaak ko lv lt ms mt no fa pl pt ro ru sk sl es sv th tr uk ur vi
47             string url = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=" + System.Net.WebUtility.UrlEncode(this.descriptionBlock.Text) + "&to=" + language;
48             //try
49             {
50                 string strTranslated = await client.GetStringAsync(url);
51                 XDocument xTranslation = XDocument.Parse(strTranslated);
52                 string strTransText = xTranslation.Root.FirstNode.ToString();
53                 this.titleTranslateBlock.Text = strTransText;
54 
55                 this.translateButton.Label = "取消翻译";
56             }
57             //catch (Exception ex)
58             {
59                 //     this.infoBlock.Text = "不能访问Bing Translate API,错误原因:" + ex.Message.ToString();
60             }
61 
62         }
63         // 当englishButton按下时,翻译成英语
64         private void englishButton_Click(object sender, RoutedEventArgs e)
65         {
66             translate("en");
67         }
68         // 当simChineseButton按下时,翻译成简体中文
69         private void simChineseButton_Click(object sender, RoutedEventArgs e)
70         {
71             translate("zh-CHS");
72         }
translateButton_Click

三、BING AD API

  待应用......

四、LIVE SDK

  1、登入和登出live帐号:

 1             // live SDK使用范围:登入、获得用户基本信息、使用onedrive上传功能       
 2  private readonly string[] scopes = new string[] { 
 3             "wl.signin", "wl.basic", "wl.photos", "wl.skydrive", "wl.skydrive_update"};
 4         private LiveAuthClient authClient = null;
 5         private LiveConnectClient liveClient = null;
 6 
 7 private void loginButton_Click(object sender, RoutedEventArgs e)
 8         {
 9             // 根据loginButton判定是“登入”或“登出”
10             if (this.loginButton.Label == "登出")
11             {
12                 this.authClient.Logout();
13                 this.loginButton.Label = "Live帐号登入";
14                 this.loginBlock.Text = "未登入";
15             }
16             else
17             {
18                 login();
19             }
20         }
21 
22 private async void login()
23         {
24             try
25             {
26                 this.loginButton.IsEnabled = false;
27 
28                 this.authClient = new LiveAuthClient();
29                 this.loginBlock.Text = "登入中";
30                 // 登入时显示进度的进度环
31                 this.loginProgress.IsActive = true;
32                 // 检验网络状态
33                 if (App.CheckNetwork())
34                 {
35                     // 得到登入结果
36                     LiveLoginResult loginResult = await this.authClient.LoginAsync(this.scopes);
37                     if (loginResult.Status == LiveConnectSessionStatus.Connected)
38                     {                      
39                         App.Session = loginResult.Session;
40                         this.liveClient = new LiveConnectClient(loginResult.Session);
41                         LiveOperationResult operationResult = await this.liveClient.GetAsync("me");
42 
43                         // 当用户登入后
44                         dynamic meResult = operationResult.Result;
45                         this.loginButton.Label = "登出";
46                         if (meResult.first_name != null && meResult.last_name != null)
47                         {
48                             //显示用户的登录信息
49                             this.loginBlock.Text = "欢迎! " + meResult.first_name + " " + meResult.last_name;
50                         }
51                         else
52                         {
53                             this.loginBlock.Text = "欢迎! ";
54                         }
55                     }
56                     else
57                     {
58                         this.loginBlock.Text = "未登入";
59                     }
60                 }
61                 else
62                 {
63                     this.infoBlock.Text = "无网络连接,请检查网络";
64                     this.loginBlock.Text = "未登入";
65                 }
66             }
67             catch (LiveAuthException)
68             {
69                 this.infoBlock.Text = "登入请求被拒绝";
70             }
71             finally
72             {
73                 // CanLogout为false的情况:应用使用windows已登入的账号时
74                 if (this.loginButton.Label == "登出" && this.authClient != null && !this.authClient.CanLogout)
75                 {
76                     this.loginButton.IsEnabled = false;
77                 }
78                 else
79                 {
80                     this.loginButton.IsEnabled = true;
81                 }
82                 this.loginProgress.IsActive = false;
83             }
84         }
loginButton_Click

  2、上传图片至OneDrive:

 1 private async void syncButton_Click(object sender, RoutedEventArgs e)
 2         {
 3             // App.Session是用来记录当前登入账户的一次会话,登入live帐号之后产生
 4             if (App.Session != null)
 5             {
 6                 // 得到本地的photo文件夹
 7                 IReadOnlyList<StorageFolder> folders = await App.photosFolder.GetFoldersAsync();
 8                 // 在Onedrive中新建一个文件夹,名字为“新建文件夹”
 9                 string skyDriveFolder = await CreateDirectoryAsync("新建文件夹", "me/skydrive");   
10                  // 对photo文件夹中的子文件夹进行遍历
11                 foreach (StorageFolder folder in folders)
12                 {
13                     // 获得子文件夹下的所有文件
14         IReadOnlyList<StorageFile> files = await folder.GetFilesAsync();
15                     foreach (StorageFile file in files)
16                     {
17                         // 将文件上传
18         LiveOperationResult result = await liveClient.BackgroundUploadAsync(skyDriveFolder, file.DisplayName + ".jpg", file, OverwriteOption.Overwrite);
19                     }
20                 }
21             }
22         }
23 
24 private async Task<string> CreateDirectoryAsync(string folderName, string parentFolder)
25         {
26             string folderId = null;
27             // 查询OneDrive中是否含有folderName文件夹
28             var queryFolder = parentFolder + "/files?filter=folders,albums";
29             var opResult = await liveClient.GetAsync(queryFolder);
30             dynamic result = opResult.Result;
31 
32             foreach (dynamic folder in result.data)
33             {
34                 // 如果存在这个文件夹,则返回文件夹名
35                 if (folder.name == folderName)
36                 {
37                     folderId = folder.id;
38                     break;
39                 }
40             }
41 
42             if (folderId == null)
43             {
44                 // 不存在则创建
45                 var folderData = new Dictionary<string, object>();
46                 folderData.Add("name", folderName);
47                 opResult = await liveClient.PostAsync(parentFolder, folderData);
48                 result = opResult.Result;
49                 folderId = result.id;
50             }
51 
52             return folderId;
53         }
syncButton_Click

五、微博 SDK

  1、连接微博帐号:

 1 private void shareButton_Click(object sender, RoutedEventArgs e)
 2         {
 3             // 检查网络状态
 4             if (App.CheckNetwork())
 5             {
 6                 // 检查该应用是否已和微博连接
 7                 if (App.oauthClient.IsAuthorized == false)
 8                 {
 9                     App.oauthClient.LoginCallback += (isSucces, err, response) =>
10                     {
11                         if (isSucces)                   // 如果成功
12                         {
13                             // TODO: deal the OAuth result.
14                         }
15                         else
16                         {
17                             this.titleBox.Text = err.errMessage;
18                         }
19                     };
20                     App.oauthClient.BeginOAuth();    // 开始验证
21                 }
22             }
23             else
24             {
25                 // no internet.
26             }
27             if (App.oauthClient.IsAuthorized == true)       // 验证成功,开始分享
28             {
29                 // TODO SHARE
30             }
31             else
32             {
33                 this.titleBox.Text = "验证失败";
34             }
35         }
shareButton_Click

  2、发布(带图片)微博

 1 private async void shareWithPhoto(String path)
 2         {
 3             var engine = new SdkNetEngine();
 4             // 微博sdk提供的方法,实例化一个cmd类
 5             ISdkCmdBase cmdBase = new CmdPos    MsgWithPic()
 6             {
 7                 // 发布的文本消息
 8                 Status = shareTextBox.Text,
 9                 // 发布的图片绝对路径
10                 PicPath = path
11             };
12             // 发布微博
13             var result = await engine.RequestCmd(SdkRequestType.POST_MESSAGE_PIC, cmdBase);
14            
15  if (result.errCode == SdkErrCode.SUCCESS)
16             {
17                  // 发布成功
18             }
19             // 发布失败
20             else
21             {
22                 // TODO: deal the error.
23                 // 失败的状态码
24                 switch (result.errCode)
25                 {
26                     case SdkErrCode.NET_UNUSUAL: this.descriptionBox.Text = "NET_UNUSUAL"; break;
27                     case SdkErrCode.SERVER_ERR: this.descriptionBox.Text = "SERVER_ERR"; break;
28                     case SdkErrCode.TIMEOUT: this.descriptionBox.Text = "TIMEOUT"; break;
29                     case SdkErrCode.USER_CANCEL: this.descriptionBox.Text = "USER_CANCEL"; break;
30                     case SdkErrCode.XPARAM_ERR: this.descriptionBox.Text = "XPARAM_ERR"; break;
31                 }
32                 this.descriptionBox.Text = result.specificCode;
33             }
34         }
shareWithPhoto

六、UTILITIES

  1、检查网络状态

 1 public static Boolean CheckNetwork()
 2         {
 3             bool isOnline = false;
 4             //获得当前的网络连接状态(using Windows.Networking.Connectivity
 5             ConnectionProfile connectionProfile = NetworkInformation.GetInternetConnectionProfile();
 6 
 7             if (connectionProfile == null)
 8             {
 9                 //TODO No net work
10             }
11             else
12             {
13                 isOnline = true;
14             }
15             return isOnline;
16         }
CheckNetwork

  2、向服务器post请求(服务器端我用的是Servlet+Tomcat+MySQL来接收和处理)

 1 private readonly static String url = "请求地址";
 2 
 3         private static async Task<string> postData(String data)
 4         {
 5             String result = String.Empty;
 6             // 设置字符编码
 7             Encoding encoding = Encoding.UTF8;
 8             // 将请求的数据转换为字节流
 9             Byte[] bytes = encoding.GetBytes(data);
10             // 实例化请求对象,有多种请求对象可以使用
11             WebRequest req = WebRequest.Create(url);
12             // 请求方式和类型
13             req.Method = "POST";
14             req.ContentType = "application/x-www-form-urlencoded";
15             using (Stream outputStream = await req.GetRequestStreamAsync())
16             {
17                 // 发送字节流信息
18                 outputStream.Write(bytes, 0, bytes.Length);
19             }
20             using (WebResponse webResponse = await req.GetResponseAsync())
21             {
22                 // 得到响应信息
23                 StreamReader sr = new StreamReader(webResponse.GetResponseStream());
24                 result = sr.ReadToEnd();
25             }
26 
27             return result;
28         }
View Code

七、总结

  第一次上手C#和xaml,而且是在这略浩大的工程中(对我而言),在开发过程中不免会遇到各种困难,当然也积累了各种经验。经历了多次Visual Studio 2013的安装(从Update1到Update3,从vs安装时写临时文件夹拒绝访问到designer安装失败),各种神奇的、离奇的失败最后都在谷歌和MSDN上找到了答案,也锻炼了我查找和阅读答案的能力。希望以上我的分享能给刚上手win8 app开发的同行们减轻一些查api(当然api也是要仔细看的)查谷歌的负担,共同进步。

 

目录
相关文章
|
6天前
|
Linux C++ Windows
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
|
6天前
|
Java 应用服务中间件 开发工具
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
|
6天前
|
Java 应用服务中间件 Windows
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
|
6天前
|
PHP Windows
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
|
7天前
|
PHP 开发工具 git
【Azure 应用服务】在 App Service for Windows 中自定义 PHP 版本的方法
【Azure 应用服务】在 App Service for Windows 中自定义 PHP 版本的方法
|
4天前
|
Java 程序员 Android开发
探索安卓开发:构建你的第一个App
【8月更文挑战第27天】在数字化时代的浪潮中,移动应用成为人们生活不可或缺的一部分。对于渴望进入软件开发领域的新手而言,掌握如何构建一款简单的安卓App是开启技术之旅的关键一步。本文旨在通过浅显易懂的语言和步骤分解,引导初学者了解安卓开发的基础知识,并跟随示例代码,一步步实现自己的第一个安卓App。从环境搭建到界面设计,再到功能实现,我们将一同揭开编程的神秘面纱,让每个人都能体会到创造软件的乐趣。
|
6天前
|
网络安全 API 数据安全/隐私保护
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
|
6天前
|
Shell PHP Windows
【Azure App Service】Web Job 报错 UNC paths are not supported. Defaulting to Windows directory.
【Azure App Service】Web Job 报错 UNC paths are not supported. Defaulting to Windows directory.
|
6天前
|
存储 Linux Windows
【应用服务 App Service】App Service For Windows 如何挂载Storage Account File Share 示例
【应用服务 App Service】App Service For Windows 如何挂载Storage Account File Share 示例
|
6天前
|
应用服务中间件 nginx Windows
【Azure 应用服务】在App Service for Windows中实现反向代理
【Azure 应用服务】在App Service for Windows中实现反向代理
下一篇
云函数