原文: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、定位:

 private LocationRange range = null;
private CancellationTokenSource cts = null;
private Geolocator geolocator = null; private async void locateButton_Click(object sender, RoutedEventArgs e)
{
// 根据定位按钮的标签判定是“定位”或“取消定位”
if (locateButton.Label == "定位")
{
locateButton.Label = "取消定位";
try
{
// 获得cancellation token
cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
this.infoBlock.Text = "正在定位"; // 获得位置
Geoposition pos = await geolocator.GetGeopositionAsync().AsTask(token);
this.infoBlock.Text = "定位成功";
// App.location是在App.xaml.cs中用于保存定位位置的全局变量
App.location = new Location(pos.Coordinate.Point.Position.Latitude, pos.Coordinate.Point.Position.Longitude); // 设置默认地图缩放等级
double zoomLevel = 13.0f;
// range是一个自定义控件,用一个大圆来涵盖定位区域
MapLayer.SetPosition(range, App.location);
rangeLayer.Children.Add(range);
zoomLevel = 15.0f; // 设置地图视野到给定的位置和缩放等级
map.SetView(App.location, zoomLevel);
}
catch (System.UnauthorizedAccessException)
{
this.infoBlock.Text = "定位请求被拒绝";
}
catch (TaskCanceledException)
{
this.infoBlock.Text = "定位被取消";
}
catch (System.Exception)
{
this.infoBlock.Text = "暂时无法获得您的位置";
}
finally
{
cts = null;
}
// 重置按钮
locateButton.Label = "定位";
//locateButton.Icon = ;
}
else
{
// 取消定位
if (cts != null)
{
cts.Cancel();
cts = null;
}
// 重置按钮
locateButton.Label = "定位";
//locateButton.Icon = ;
}
}

locateButton_Click

  2、添加图钉:

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

AddPinButton_Click

  3、拖动图钉:

 private bool isDragging = false;        // pin正在拖拽标志

         // 当pin被拖动时激活
public Action<Location> drag;
// 当pin开始被拖动时激活
public Action<Location> dragStart;
// 当pin停止拖动时激活
public Action<Location> dragEnd;
// 当pin被按下时,得到被按下pin的ID,判断是否可拖动,执行操作
protected override void OnPointerPressed(PointerRoutedEventArgs e)
{
base.OnPointerPressed(e); // 如果可以被拖动则开始拖动
if (draggable)
{
if (map != null)
{
center = map.Center;
// 为map的下列方面重写
map.ViewChanged += map_ViewChanged;
map.PointerReleasedOverride += map_PointerReleased;
map.PointerMovedOverride += map_PointerMoved;
}
// 得到当前鼠标位置
var pointerPosition = e.GetCurrentPoint(map);
Location location = null;
// 开始拖动
if (dragStart != null)
{
dragStart(location);
} this.isDragging = true;
}
} // 当pin被移动时
private void map_PointerMoved(object sender, PointerRoutedEventArgs e)
{
// 检查是否正在被拖动
if (this.isDragging)
{
// 随着鼠标移动图标
var pointerPosition = e.GetCurrentPoint(map); Location location = null; if (map.TryPixelToLocation(pointerPosition.Position, out location))
{
// 将图钉(this)移到到当前鼠标的位置(location)
MapLayer.SetPosition(this, location);
}
if (drag != null)
{
drag(location);
}
}
} // 当pin被松开时
private void map_PointerReleased(object sender, PointerRoutedEventArgs e)
{
if (this.isDragging)
{
if (map != null)
{
map.ViewChanged -= map_ViewChanged;
map.PointerReleasedOverride -= map_PointerReleased;
map.PointerMovedOverride -= map_PointerMoved;
} var pointerPosition = e.GetCurrentPoint(map);
Location location;
map.TryPixelToLocation(pointerPosition.Position, out location);
// 得到最终的经纬度
latitude = location.Latitude;
longitude = location.Longitude; location = null; if (dragEnd != null)
{
dragEnd(location);
} this.isDragging = false;
this.draggable = false;
}
}

PinDrag

二、BING TRANSLATE API

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

  翻译:

 private HttpClient client = null;            // 用于通信的HTTP客户端

         private async void translateButton_Click(object sender, RoutedEventArgs e)
{
// 根据translateButton的标签判定是“翻译”或“取消翻译”
if (translateButton.Label == "翻译")
{
// 进行网络检查(方法见 五、UTILITIES)
if (!App.CheckNetwork())
{
//this.infoBlock.Text = "无网络连接,请检查网络";
}
else
{
try
{
this.infoBlock.Text = "正在检查网络连接...";
string clientID = "你的clientID";
string clientSecret = "你的clientSecret";
//AzureDataMarket可以从网上找到,是一个已经写好的用于在Azure进行验证的类
var _Authentication = new AzureDataMarket(clientID, clientSecret);
AzureDataMarket.Token m_Token = await _Authentication.GetTokenAsync();
string auth = m_Token.Header;
//实例化该类,以便于后面发送Http请求获取网络数据
client = new HttpClient();
//设置读取响应内容时缓冲区的最大字节数
client.MaxResponseContentBufferSize = ;
//设置请求头部
client.DefaultRequestHeaders.Add("Authorization", auth);
}
catch
{
//this.infoBlock.Text = "连接到服务器失败";
}
}
}
else
{
this.translateButton.Label = "翻译";
}
} // 将descriptionBlock中的内容翻译成language所表示的语言
private async void translate(String language)
{
//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
string url = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=" + System.Net.WebUtility.UrlEncode(this.descriptionBlock.Text) + "&to=" + language;
//try
{
string strTranslated = await client.GetStringAsync(url);
XDocument xTranslation = XDocument.Parse(strTranslated);
string strTransText = xTranslation.Root.FirstNode.ToString();
this.titleTranslateBlock.Text = strTransText; this.translateButton.Label = "取消翻译";
}
//catch (Exception ex)
{
// this.infoBlock.Text = "不能访问Bing Translate API,错误原因:" + ex.Message.ToString();
} }
// 当englishButton按下时,翻译成英语
private void englishButton_Click(object sender, RoutedEventArgs e)
{
translate("en");
}
// 当simChineseButton按下时,翻译成简体中文
private void simChineseButton_Click(object sender, RoutedEventArgs e)
{
translate("zh-CHS");
}

translateButton_Click

三、BING AD API

  待应用......

四、LIVE SDK

  1、登入和登出live帐号:

             // live SDK使用范围:登入、获得用户基本信息、使用onedrive上传功能
private readonly string[] scopes = new string[] {
"wl.signin", "wl.basic", "wl.photos", "wl.skydrive", "wl.skydrive_update"};
private LiveAuthClient authClient = null;
private LiveConnectClient liveClient = null; private void loginButton_Click(object sender, RoutedEventArgs e)
{
// 根据loginButton判定是“登入”或“登出”
if (this.loginButton.Label == "登出")
{
this.authClient.Logout();
this.loginButton.Label = "Live帐号登入";
this.loginBlock.Text = "未登入";
}
else
{
login();
}
} private async void login()
{
try
{
this.loginButton.IsEnabled = false; this.authClient = new LiveAuthClient();
this.loginBlock.Text = "登入中";
// 登入时显示进度的进度环
this.loginProgress.IsActive = true;
// 检验网络状态
if (App.CheckNetwork())
{
// 得到登入结果
LiveLoginResult loginResult = await this.authClient.LoginAsync(this.scopes);
if (loginResult.Status == LiveConnectSessionStatus.Connected)
{
App.Session = loginResult.Session;
this.liveClient = new LiveConnectClient(loginResult.Session);
LiveOperationResult operationResult = await this.liveClient.GetAsync("me"); // 当用户登入后
dynamic meResult = operationResult.Result;
this.loginButton.Label = "登出";
if (meResult.first_name != null && meResult.last_name != null)
{
//显示用户的登录信息
this.loginBlock.Text = "欢迎! " + meResult.first_name + " " + meResult.last_name;
}
else
{
this.loginBlock.Text = "欢迎! ";
}
}
else
{
this.loginBlock.Text = "未登入";
}
}
else
{
this.infoBlock.Text = "无网络连接,请检查网络";
this.loginBlock.Text = "未登入";
}
}
catch (LiveAuthException)
{
this.infoBlock.Text = "登入请求被拒绝";
}
finally
{
// CanLogout为false的情况:应用使用windows已登入的账号时
if (this.loginButton.Label == "登出" && this.authClient != null && !this.authClient.CanLogout)
{
this.loginButton.IsEnabled = false;
}
else
{
this.loginButton.IsEnabled = true;
}
this.loginProgress.IsActive = false;
}
}

loginButton_Click

  2、上传图片至OneDrive:

 private async void syncButton_Click(object sender, RoutedEventArgs e)
{
// App.Session是用来记录当前登入账户的一次会话,登入live帐号之后产生
if (App.Session != null)
{
// 得到本地的photo文件夹
IReadOnlyList<StorageFolder> folders = await App.photosFolder.GetFoldersAsync();
// 在Onedrive中新建一个文件夹,名字为“新建文件夹”
string skyDriveFolder = await CreateDirectoryAsync("新建文件夹", "me/skydrive");
// 对photo文件夹中的子文件夹进行遍历
foreach (StorageFolder folder in folders)
{
// 获得子文件夹下的所有文件
IReadOnlyList<StorageFile> files = await folder.GetFilesAsync();
foreach (StorageFile file in files)
{
// 将文件上传
LiveOperationResult result = await liveClient.BackgroundUploadAsync(skyDriveFolder, file.DisplayName + ".jpg", file, OverwriteOption.Overwrite);
}
}
}
} private async Task<string> CreateDirectoryAsync(string folderName, string parentFolder)
{
string folderId = null;
// 查询OneDrive中是否含有folderName文件夹
var queryFolder = parentFolder + "/files?filter=folders,albums";
var opResult = await liveClient.GetAsync(queryFolder);
dynamic result = opResult.Result; foreach (dynamic folder in result.data)
{
// 如果存在这个文件夹,则返回文件夹名
if (folder.name == folderName)
{
folderId = folder.id;
break;
}
} if (folderId == null)
{
// 不存在则创建
var folderData = new Dictionary<string, object>();
folderData.Add("name", folderName);
opResult = await liveClient.PostAsync(parentFolder, folderData);
result = opResult.Result;
folderId = result.id;
} return folderId;
}

syncButton_Click

五、微博 SDK

  1、连接微博帐号:

 private void shareButton_Click(object sender, RoutedEventArgs e)
{
// 检查网络状态
if (App.CheckNetwork())
{
// 检查该应用是否已和微博连接
if (App.oauthClient.IsAuthorized == false)
{
App.oauthClient.LoginCallback += (isSucces, err, response) =>
{
if (isSucces) // 如果成功
{
// TODO: deal the OAuth result.
}
else
{
this.titleBox.Text = err.errMessage;
}
};
App.oauthClient.BeginOAuth(); // 开始验证
}
}
else
{
// no internet.
}
if (App.oauthClient.IsAuthorized == true) // 验证成功,开始分享
{
// TODO SHARE
}
else
{
this.titleBox.Text = "验证失败";
}
}

shareButton_Click

  2、发布(带图片)微博

 private async void shareWithPhoto(String path)
{
var engine = new SdkNetEngine();
// 微博sdk提供的方法,实例化一个cmd类
ISdkCmdBase cmdBase = new CmdPos MsgWithPic()
{
// 发布的文本消息
Status = shareTextBox.Text,
// 发布的图片绝对路径
PicPath = path
};
// 发布微博
var result = await engine.RequestCmd(SdkRequestType.POST_MESSAGE_PIC, cmdBase); if (result.errCode == SdkErrCode.SUCCESS)
{
// 发布成功
}
// 发布失败
else
{
// TODO: deal the error.
// 失败的状态码
switch (result.errCode)
{
case SdkErrCode.NET_UNUSUAL: this.descriptionBox.Text = "NET_UNUSUAL"; break;
case SdkErrCode.SERVER_ERR: this.descriptionBox.Text = "SERVER_ERR"; break;
case SdkErrCode.TIMEOUT: this.descriptionBox.Text = "TIMEOUT"; break;
case SdkErrCode.USER_CANCEL: this.descriptionBox.Text = "USER_CANCEL"; break;
case SdkErrCode.XPARAM_ERR: this.descriptionBox.Text = "XPARAM_ERR"; break;
}
this.descriptionBox.Text = result.specificCode;
}
}

shareWithPhoto

六、UTILITIES

  1、检查网络状态

 public static Boolean CheckNetwork()
{
bool isOnline = false;
//获得当前的网络连接状态(using Windows.Networking.Connectivity
ConnectionProfile connectionProfile = NetworkInformation.GetInternetConnectionProfile(); if (connectionProfile == null)
{
//TODO No net work
}
else
{
isOnline = true;
}
return isOnline;
}

CheckNetwork

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

 private readonly static String url = "请求地址";

         private static async Task<string> postData(String data)
{
String result = String.Empty;
// 设置字符编码
Encoding encoding = Encoding.UTF8;
// 将请求的数据转换为字节流
Byte[] bytes = encoding.GetBytes(data);
// 实例化请求对象,有多种请求对象可以使用
WebRequest req = WebRequest.Create(url);
// 请求方式和类型
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
using (Stream outputStream = await req.GetRequestStreamAsync())
{
// 发送字节流信息
outputStream.Write(bytes, , bytes.Length);
}
using (WebResponse webResponse = await req.GetResponseAsync())
{
// 得到响应信息
StreamReader sr = new StreamReader(webResponse.GetResponseStream());
result = sr.ReadToEnd();
} return result;
}

七、总结

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

Windows 8.1 store app 开发笔记的更多相关文章

  1. Android移动APP开发笔记——最新版Cordova 5.3.1(PhoneGap)搭建开发环境

    引言 简单介绍一下Cordova的来历,Cordova的前身叫PhoneGap,自被Adobe收购后交由Apache管理,并将其核心功能开源改名为Cordova.它能让你使用HTML5轻松调用本地AP ...

  2. 手机web app开发笔记

    各位朋友好,最近自学开发了一个手机Web APP,“编程之路”,主要功能包括文章的展示,留言,注册登录,音乐播放等.为了记录学习心得,提高自己的编程水平,也许对其他朋友有点启发,特整理开发笔记如下. ...

  3. Android移动APP开发笔记——Cordova(PhoneGap)通过CordovaPlugin插件调用 Activity 实例

    引言 Cordova(PhoneGap)采用的是HTML5+JavaScript混合模式来开发移动手机APP,因此当页面需要获取手机内部某些信息时(例如:联系人信息,坐标定位,短信等),程序就需要调用 ...

  4. Android APP开发笔记

    环境搭建 windows系统上需要以下软件: android SDK -- app开发工具包, 开发运行环境(包括SDK管理工具,和虚拟设备管理). JDK -- java 开发工具包, 负责app代 ...

  5. 小学英语课文朗读APP开发笔记(一):创建Win7虚拟机

    1 缘起 以小米盒子为代表的OTT机顶盒.智能电视的快速普及,快速推动了Android技术在机顶盒.智能电视领域的普及.既然都是用的Android操作系统,那么从技术上来说应该是大同小异的,当然和手机 ...

  6. 安卓app开发笔记

    移动app应用开发也是信息技术课程科技创新的范畴,所以在个人开发app时候记录一些笔记,可能会很乱,所以选择按点来写. 首先是一些入门的资料,有很多需要自己学习的 https://www.oschin ...

  7. Android Studio配置 AndroidAnnotations——Hi_博客 Android App 开发笔记

    以前用Eclicps 用习惯了现在 想学学 用Android Studio 两天的钻研终于 在我电脑上装了一个Android Studio 并完成了AndroidAnnotations 的配置. An ...

  8. Android请求网络共通类——Hi_博客 Android App 开发笔记

    今天 ,来分享一下 ,一个博客App的开发过程,以前也没开发过这种类型App 的经验,求大神们轻点喷. 首先我们要创建一个Andriod 项目 因为要从网络请求数据所以我们先来一个请求网络的共通类. ...

  9. 默认文档接卸--手机web app开发笔记(二)

    首先我们启动HBuilderX2.0 ,界面如图2-1所示 图2-1 软件开发界面 单击“文件—新建—项目”,弹出新建项目管理界面,我们在里面进行了项目类型选择“5+APP”.项目名称填写“编程之路” ...

随机推荐

  1. 第一pga 畸形消费分析

     第一pga 畸形消费分析 os: aix 6 db:10205 ------使用os 命令观察oracle 存消耗情况 #ps gv ......                         ...

  2. iOS开发- 隐藏状态栏(电池栏)

    分为两种情况: 1. 想要隐藏某个视图的状态栏, 比方说, 从界面A, push 到界面B的时候, 界面A原本显示状态栏, 然而我们须要界面B不显示状态栏. 这时候, 能够这样做: 在B中实现: - ...

  3. spring 整合quartz的方式——简单介绍

    一.继承QuartzJobBean,重写executeInternal方法 <bean name="statQuartzJob" class="org.spring ...

  4. JUnit实战(1) - JUnit起步(Parameterized参数化测试)

    创建Java Project项目,项目名称:ch01-jumpstart Calculator.java public class Calculator { public double add(dou ...

  5. python 3.4.0 简单的print &#39;hello world&#39;,出错--SyntaxError: invalid syntax

    问题描写叙述: win7下安装的python 3.4.0版本号, 在命令行里写入简单的输出语句: print 'hello world' 然后enter,结果返回结果为: SyntaxError: i ...

  6. VS2008让自己掌控的定义编译项目后,自己主动添加到工具箱

    在VS2008中,假设在项目里写了一个用户控件.编译后这个控件是不会自己主动出现到工具箱的.按例如以下设置就能够解决问题 工具=>选项=>Windows窗口设计器=>常规=>A ...

  7. ExecutorService invokeAll 实例(转)

    10个班级,每个班级20名学生,在指定的时间内查询每个班级学生的集合. package cn.com.ld.study.thread; import java.util.ArrayList; impo ...

  8. 百度地图 Android SDK - 个性化地图

    什么是百度个性化地图Android SDK? 百度个性化地图Android SDK是一套基于Android 2.2及以上版本号设备的应用程序接口,您能够通过该套接口实现主要的地图功能,而且能够定制地图 ...

  9. 通过管道进行线程间通信:字节流。字符流的用法及API类似

    管道流(PipedStream)可以用于不同线程间直接传送数据.一个线程发送数据到输出管道,另一个线程从输入管道中读取数据.通过使用管道,实现不同线程间的通信,而无须借助于类似临时文件之类的东西. p ...

  10. JavaScript中五种常见运算符

    一. in运算符 in运算符希望它的左操作数是一个字符串或可以转换为字符串,希望它的右操作数是一个对象.如果右侧的对象拥有一个名为左操作数值的属性名,那么表达式返回true.例如: var point ...