android移动开发学习笔记(二)神奇的Web API
本次分两个大方向去讲解Web Api,1、如何实现Web Api?2、如何Android端如何调用Web Api?对于Web Api是什么?有什么优缺点?为什么用WebApi而不用Webservice?这些问题都不去解答,百度一下,关于这方面的资料很多,就不再去啰嗦。
一、如何在web端实现WebApi
(1)如何新建一个WebApi?
在上一章中,讲到我们项目用的是.net 4.5,开发工具是Visual Studio 2012,在Visual Studio 2012中新建MVC4项目,选择Web API,然后项目生成,如下图一、图二、图三所示, 和普通的MVC项目相比,它继承了ApiController,然后我们运行一下项目,在浏览器里输入http://localhost:56091/api/values/get?id=5,如图四所示,即成功调用了项目默认写的Get方法实例,有数据返回即表示调用成功!

(图一)

(图二)

(图三)

(图四)
(2)Get和Post数据?
(2.1) Get方法
具体什么是Get就不再啰嗦了,可以自己百度查看, 使用 [HttpGet]标识,当然也可以不用加,只需要方法名用Get开头,Get方法是使用Url参数传递的,不能接收实体参数,如:http://localhost:56091/api/values/get?id=5,id即是参数,当然也可以多参数,如:http://localhost:56091/api/values/get?id=5&name=tim ,默认参数使用[FromUri]
Get是有长度限制的,参数不能过多,而且参数暴露在外面,容易被人很方便的截取。
(2.2)Post方法
使用 [HttpPost]方式传递,当然也可以不用加,只需要方法名用Post开头,Post方法可以使用Url传递参数,也可以用Body传递参数,默认参数使用[FromUri],可以加[FromBody]接收body里传递的参数,但是有问题的是,我使用[FromBody]方式,参数为空,根本接收不动值,上网查了资料,很多人遇到问题,不知道是不是Web Api本身的问题,无奈只好使用下面最原始的方式了,获取Body的值了。
|
1
2
3
4
5
6
7
|
HttpContextBase context = (HttpContextBase)Request.Properties[MS_HttpContext];//获取传统contextHttpRequestBase request = context.Request;//定义传统request对象string name = request.Form.Keys[0];if (name == null){ name = request.Form[0];} |
另外Post的方法不能直接在浏览器里敲地址获取数据,调试起来不是很方便,所以用了一个工具,火狐浏览器可以安装一个插件,叫Poster,如下图六所示,测试起来很方便。

(图五)

(图六)
(3)Json数据格式?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。
Json数据格式传输是目前接口数据传输主流,本次我们的项目也是使用Json格式数据,我们所有的接口参数都是统一的参数名,后面跟的是Json格式字符串,如:http://localhost:8010/api/MobileInfo/Get_Welcome? params=JsonString,这是接口的调用,接口返回结果也是Json格式。
如下图七所示,使用Newtonsoft.Json类库,这是VS项目集成的类库,可以很方便的使用JsonConvert.SerializeObject(value)方法,将object对象转换为Json格式。

(图七)
|
1
2
3
|
//step2:参数反序列化T transferObj = default(T);transferObj = Newtonsoft.Json.JsonConvert.DeserializeObject<t>(JsonString);</t> |
(4) 路由的配置
如下图八所示,默认路由配置是这样,只会找到Controller,不用根据Action去分配地址,所以相同Controller下只会找到Get方法或Post方法,不管你方法名是否相同,这样很明显不能满足我们的需求,如果想以Action去标识地址,就用下面代码配置:
|
1
2
3
4
5
|
config.Routes.MapHttpRoute( name: CommonApi, routeTemplate: api/{controller}/{action}/{id}, defaults: new { id = RouteParameter.Optional }); |

(图八)
二、如何在Android端调用WebApi
(1)调用web Api的Get方法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public void getAnnouncement(final Object reqTag, final WSAnnouncementListCb cb) { //需要调用WebApi的Url地址 参数用UTF-8编码 String url = Constants.WEB_BASE_URL + MobileInfo/Get_AnnouncementList?JsonString= + Utils.getEncodingParamsString((Object) UserManager.getInstance() .getLoginedUserInfo()); //使用Request对象,请求数据 Mdthod.Get WsAnnouncementListRsp.class接收结果的对象实体类 GsonRequest<wsannouncementlistrsp> gsonRequest = new GsonRequest<wsannouncementlistrsp>( Method.GET, url, WSAnnouncementListRsp.class, new Response.Listener<wsannouncementlistrsp>() { @Override public void onResponse(WSAnnouncementListRsp rsp) { //返回的Json格式数据,经过反序列化后的对象实体 if (cb != null) { cb.onResponse(Utils.stringToInteger(rsp.message.ResultCode), rsp); } } }, errorListener(true)); gsonRequest.setRequestTag(reqTag); RequestManager.addRequest(gsonRequest, reqTag);}</wsannouncementlistrsp></wsannouncementlistrsp></wsannouncementlistrsp> |
Android反序列化Json的方法:
当然下面代码中包含判断Token是否过期,过期之后重新登录,因为判断Token是否过期是每个App接口都可能要考虑的事情,所以就没有删除,以供大家参考。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
//Response的时候,返回解析后的对象 protected Response<t> parseNetworkResponse(NetworkResponse response) { try { //接收到的Json格式数据字符串 String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); //如果有转义字符就替换她 json = json.substring(1, json.length() - 1); json = json.replace(\, ); Log.I(L, Response type: + mClazz.getName() + Parsed Json Buffer: + json); //反序列化Json数据 WSBaseResponse baseResponse = (WSBaseResponse) mGson.fromJson(json, mClazz); //判断Token是否过期 if (Utils.stringToInteger(baseResponse.message.ResultCode) == Constants.ERR_TOKEN_INVALID) {// Log.I(L, get token status: + UserManager.getInstance().getTokenStatus());// if (UserManager.getInstance().getTokenStatus() != TOKEN_STATUS.TOKEN_GETTING) {// Log.I(L,set token status: + TOKEN_STATUS.TOKEN_EXPIRED);// UserManager.getInstance().setTokenStatus(TOKEN_STATUS.TOKEN_EXPIRED);// } synchronized (GsonRequest.class) { if (UserManager.getInstance().getTokenStatus() != TOKEN_STATUS.TOKEN_GETTING) { Log.I(L, relogin ...); RequestManager.addCachedRequest(this); UserManager.getInstance().relogin(new OnLoginListener() { @Override public void onLogin(int result, String message) { if (result == UserManager.LOGIN_RESULT_OK) { Log.I(L, Login suceesss); UserManager.getInstance().setTokenStatus(TOKEN_STATUS.TOKEN_OK); } else { Log.I(L,Login failed...); // Show login activity UserManager.getInstance().setTokenStatus(TOKEN_STATUS.TOKEN_FAIL); MyActivityManager.getInstance().finishAllActivity(); showLoginActivity(); } } }); } else { // Log.I(L, prepare resend request); // reSendRequest(); RequestManager.addCachedRequest(this); } } return Response.error(new TokenExpiredError()); } else { //返回泛型对象 return Response.success((T) baseResponse/* * mGson.fromJson(json, * mClazz) */, HttpHeaderParser.parseCacheHeaders(response)); } } catch (UnsupportedEncodingException e) { Log.E(L, response parse error: + mClazz.getName()); return Response.error(new ParseError(e)); } catch (JsonSyntaxException e) { Log.E(L, response parse error: + mClazz.getName()); return Response.error(new ParseError(e)); } }</t> |
(2)调用web Api的Post方法
放在Url里的和Get方法一样调用,只是传参的时候,把Method.Get改为Method.Post方式,
因此主要讲Post的Body方法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public void updateUserInfo(final Object reqTag, final WSUpdateUserInfoReq req, final WSUpdateUserInfoCb cb) { setUserIdAndTokenForReq(req); // post Url不带任何参数 String url = Constants.WEB_BASE_URL + MobileInfo/Save_EmployeeInfo;//req是参数 GsonRequest<wscommonrsp> gsonRequest = new GsonRequest<wscommonrsp>( Method.POST, url,Utils.getEncodingParamsString((Object) req), WSCommonRsp.class, null, new Response.Listener<wscommonrsp>() { @Override public void onResponse(WSCommonRsp rsp) { if (cb != null) { cb.onResponse(Utils.stringToInteger(rsp.message.ResultCode), rsp); } } }, errorListener(true)); gsonRequest.setRequestTag(reqTag); RequestManager.addRequest(gsonRequest, reqTag);}</wscommonrsp></wscommonrsp></wscommonrsp> |
以上就是App接口的实现和接口在Android中的调用方法,我提供的都是一些伪代码,主要是讲解功能实现的思想和用到哪些重要的类方法。下章则正式学习Android开发,看一个零基础的菜鸟如何快速上手做开发的。
android移动开发学习笔记(二)神奇的Web API的更多相关文章
- python-django开发学习笔记二
1.简述 1.1 开发环境 该笔记所基于的开发环境为:windows8.python2.7.5.psycopg2-2.4.2.django1.5.4.pyCharm-2.7.3.以上所描述的软件.插件 ...
- Android Studio安卓学习笔记(二)Android项目结构
上一篇代码,我们学习了Android的功能以及如何用Android Studio开发第一个安卓程序.下面就要介绍Android项目结构.为日后学习打基础. 一:Android项目结构 打开MyFris ...
- Android应用开发学习笔记之播放音频
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android支持常用音视频格式文件的播放,本文我们来学习怎样开发Android应用程序对音视频进行操作. Andr ...
- Android应用开发学习笔记之事件处理
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android提供的事件处理机制分为两类:一是基于监听的事件处理:二是基于回调的事件处理.对于基于监听的事件处理,主 ...
- Android应用开发学习笔记之Fragment
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Fragment翻译成中文就是“碎片”.“片断”的意思,Fragment通常用来作为一个Activity用户界面的一 ...
- 软件开发学习笔记 <二>软件开发模型、Up、Rup、敏捷Up
软件开发过程(process) 是一个将用户需求转化为软件系统所需要的活动的集合. 软件生命周期(SDLC,Software Devlopment Life Cycle) 软件从孕育.诞生.成长.成熟 ...
- Android应用开发学习笔记之菜单
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android中的菜单分为选项菜单(OptionMenu)和上下文菜单(Context Menu).通常使用菜单资源 ...
- Android应用开发学习笔记之Intent
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Intent是什么呢?来看Android官网上的定义: An intent is an abstractdescri ...
- Android应用开发学习笔记之AsyncTask
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 在上一篇文章中我们学习了多线程和Handler消息处理机制,如果有计算量比较大的任务,可以创建一个新线程执行计算工作 ...
随机推荐
- mac在线恢复教程
上个周,我本来想升级一下Xcode,可是我的系统是10.8de,xcode5.0.1 最低支持10.8.4 所以就想升级一下我的mac的系统,可是因为我的appstore 是从别人的电脑上考过来的,要 ...
- C#计算两个文件的相对目录算法
C#计算两个文件的相对目录算法 楼主大菜鸟一只,第一次写技术博客,如果有概念错误或代码不规范的地方,还请各位多多批评指正.话不多说,来看题: 前一阵子开发了一个用户控件,里面调用了很多css,js等资 ...
- .NET Mvc Razor
.NET Mvc Razor也可以这样玩! 忙碌的工作总是占据了生活的大部分的时间!所以我的博客到现在还是寥寥的几篇文章,技术是用来分享和学习的,对技术有不同的见解,大家都可以分享下,如果如下文章有问 ...
- SVN中Branch的创建于合并
SVN中Branch的创建于合并 在使用源代码版本控制工具时,最佳实践是一直保持一个主干版本.但是为了应付实际开发中的各种情况,适时的开辟一些分支也是很有必要的.比如在持续开发新功能的同时,需要发布一 ...
- 11 款最好 CSS 框架
11 款最好 CSS 框架 让你的网站独领风骚 网页设计和发展领域已经成为竞争激烈的虚拟世界.想要在网络的虚拟世界中生存,仅有一堆静止的在线网络应用是远远不够的,网页必须要有很多功能,配以让人无法抗拒 ...
- img onerror事件
怪自己知道的太少,img标签有onerror这个事件,我是才刚知道,恕我愚昧,既然是第一次遇到,而且又是一个自己从没有涉及过得的东西,所以我希望通过这个随笔来是自己印象深刻,此文仅仅只是让自己印象深刻 ...
- php 数组合并方法
$new = array(); if ($relateddepartmentsnew) { foreach ($relateddepartmentsnew as $relatK=>$relatV ...
- Javascript内存泄漏
Javascript内存泄漏 原文:http://point.davidglasser.net/2013/06/27/surprising-javascript-memory-leak.html 本周 ...
- 快速构建C++项目工具Scons,结合Editplus搭建开发环境
Windows下C++开发工具用的最多的非VS莫属了(当然也有很多比如eclipse,Qt等等),便捷的项目构建向导,再加上强大的VC助手,使得开发和调试得心应手.并不是说vc就没有缺点,相反缺点也不 ...
- [置顶] 遵循Java EE标准体系的开源GIS服务平台之二:平台部署
传送门 ☞ 系统架构设计 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 传送门 ☞ GoF23种设计模式 ☞ 转载请注明 ☞ http://blog.csd ...