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也是要仔细看的)查谷歌的负担,共同进步。

 

目录
相关文章
|
1月前
|
API 数据安全/隐私保护 iOS开发
利用uni-app 开发的iOS app 发布到App Store全流程
利用uni-app 开发的iOS app 发布到App Store全流程
87 3
|
1月前
|
iOS开发 UED
解决提交到App Store时的ITMS-90478和ITMS-90062错误
解决提交到App Store时的ITMS-90478和ITMS-90062错误
20 0
|
1月前
|
Android开发 开发者 UED
个人开发 App 成功上架手机应用市场的关键步骤
个人开发 App 成功上架手机应用市场的关键步骤
|
1月前
|
iOS开发 开发者
一键制作 iOS 上架 App Store 描述文件教程
一键制作 iOS 上架 App Store 描述文件教程
|
1月前
|
开发工具 数据安全/隐私保护 Android开发
【教程】APP 开发后如何上架?
【教程】APP 开发后如何上架?
|
1月前
|
API
uni-app 146朋友圈列表api开发
uni-app 146朋友圈列表api开发
18 0
|
1月前
|
Java Android开发 开发者
【Uniapp开发】APP的真机调试指南,从开发到上架全过程
【Uniapp开发】APP的真机调试指南,从开发到上架全过程
36 3
游戏直播APP平台开发多少钱成本:定制与成品源码差距这么大
开发一款游戏直播APP平台所需的费用是多少?对于计划投身这一领域的投资者来说,首要关心的问题之一就是。本文将探讨两种主要的开发模式——定制开发与成品源码二次开发的成本差异及其优劣势。
|
1月前
|
开发框架 移动开发 JavaScript
SpringCloud微服务实战——搭建企业级开发框架(四十六):【移动开发】整合uni-app搭建移动端快速开发框架-环境搭建
正如优秀的软件设计一样,uni-app把一些移动端常用的功能做成了独立的服务或者插件,我们在使用的时候只需要选择使用即可。但是在使用这些服务或者插件时一定要区分其提供的各种服务和插件的使用场景,例如其提供的【uni-starter快速开发项目模版】几乎集成了移动端所需的所有基础功能,使用非常方便,但是其许可协议只允许对接其uniCloud的JS开发服务端,不允许对接自己的php、java等其他后台系统。
145 2
|
1月前
|
数据可视化 数据库 C++
Qt 5.14.2揭秘高效开发:如何用VS2022快速部署Qt 5.14.2,打造无与伦比的Windows应用
Qt 5.14.2揭秘高效开发:如何用VS2022快速部署Qt 5.14.2,打造无与伦比的Windows应用