当前位置:首页 >> 计算机软件及应用 >>

基于android操作系统的软件开发


基于 android 操作系统的软件开发

摘要:本文首先地分析了 Android 系统相对于其他操作系统的优势和具备的潜力。论 述了 Android 系统开发的流程, 并搭建了 Android 系统的开发平台: android SDK 和 ADT。 接下来进行了新浪微博客户端的自主研发,主要从 UI 和功能两个方向进行了设计和 开发,并着重论述了 UI 的设计和实现。在客户端开发的基础上又实现了微博服务端 API 的 OAuth 认证,使客户端可以投入使用。 关键词: Android;Android 开发平台;新浪微博客户端;UI ;OAuth 认证

The software development based on the Android mobile system

I

基于 android 操作系统的软件开发

Abstract :This paper first briefly introduces the important component of the Androi d system: operating system (Linux), middleware and composed of the core applications software stack (software stack);And introduce the Android system development platform Android SDK provides API and the corresponding development tool.The next level of A ndroid in from systematic research.Mainly in its runtime, environmental layer and Andro id application framework layer of research. Finally, through the Android platform on the application development, realize the Android system of the use of Intent mechanism. Key Words :Android;Android Kernel ;UI;OAuth ;Android SDK ;Android Development





II

基于 android 操作系统的软件开发

第一章 绪论 ................................................................. 1 1.1 智能手机平台 .......................................................... 1 1.2 ANDROID 平台介绍 .................................................... 2 第二章 ANDROID 开发环境的搭建 ............................................. 3 2.1 开发包及其工具的安装和配置 ............................................ 2.1.1 安装 JDK 和配置 Java 开发环境............................................ 2.1.2 Eclipse 的安装与汉化 ................................................... 2.1.3 SDK 和 ADT 的安装和配置 .............................................. 2.2 创建第一个 ANDROID 项目——HELLOANDROID .......................... 2.2.1 创建 HelloAndroid 项目 ................................................. 2.2.2 运行 HelloAndroid 及模拟器的使用 ......................................... 3 3 4 5 8 8 9

第三章 新浪微博客户端的开发 ................................................ 12 3.1 载入页面 ............................................................. 3.1.1 UI 篇 .............................................................. 3.1.2 sqlite 篇 ............................................................ 3.2 OAUTH 授权认证 ...................................................... 3.3 用户授权页面 ......................................................... 3.3.1 用户授权页面 UI 篇 ................................................... 3.3.2 用户授权页面功能篇 .................................................. 3.4 登录页面 ............................................................. 3.4.1 登陆页面 UI 篇 ...................................................... 3.4.2 登录页面功能篇 ...................................................... 3.5 用户首页面 ........................................................... 3.5.1 用户首页面 UI 篇 ..................................................... 3.5.2 用户首页面功能篇 .................................................... 3.6 阅读微博 ............................................................. 3.6.1 阅读微博 UI 篇 ...................................................... 3.6.2 阅读微博功能篇 ...................................................... 3.7 大图浏览以及保存篇 ................................................... 总 12 12 15 16 17 17 19 22 22 23 25 25 27 27 27 28 29

结 ..................................................................... 31

参考文献 ................................................................... 32 致 谢 ..................................................................... 33

附录 核心代码 .............................................................. 34

III

基于 Android 手机操作系统软件开发

第一章
1.1 智能手机平台

绪论

说起手机,没有一个人会感到陌生。近几年来一个名词一直影响着许许多多的 手机用户,它就是智能手机。智能手机凭借其强大的功能吸引住了许多用户的眼球, 因为有了广大的用户基础,智能手机也风靡一时。说起智能手机,除了他有一颗强大 的 CPU 和其他一些较高配置的硬件外,其真正的智能还要归功于其不可缺少的智能 操作系统。 当今,智能手机所搭载的智能手机操作系统平台大致如下: (1)Symbian OS。搭载在具有广泛群众基础的 Nokia 手机上,并以此占据了智 能手机的半壁江山,其主要的智能平台为大部分诺基亚手机搭载的的 S60 系列和索 尼爱立信手机搭载的 UIQ 系列; (2)Windows Mobile。Microsoft 在桌面系统获得成功之后,觊觎手机的巨大市 场开发的智能手机系统,因其界面和桌面 windows 系统较为接近和其强大的微软后 台,成为国内市场占有率紧跟 Symbian 之后成为国人比较喜欢的操作系统; (3)Mac OS X(iPhone OS) 。苹果一直都是个性和时尚的代名词,受广大中高 层次手机用户的喜欢。iPhone,以其酷炫的 UI 和独特的操作方式,给传统手机带来 一场革命,同时也给 Symbian 和 Windows Mobile 带来巨大冲击的; (4)Blackberry。以商务应用为主,在国外尤其是欧美等地,受到商务人士欢迎 的 Black Barry 占据了近一半的无线商务电子邮件业务市场,就连美国总统奥巴马也 使用该品牌的手机。但是在国内还是受到一些基础设施的制约,所以在国内市场不是 太好; (5)Palm OS。专门为 PDA 开发,一度占据了 90%的 PDA 市场的份额,虽然其 并不专门针对于手机设计, 但是以其优秀性和对移动设备的支持同样使其能够成为一 个优秀的手机操作系统。 (6)Linux。对于 Linux 系统,想必很多人都不会太陌生,桌面系统中以其开源 的特性,赢得了不少用户的喜爱。智能手机平台的 Linux 同样具有源代码开放、软件 授权费用低、应用开发人才资源丰富等优点,便于开发个人和行业应用。但是因为其 平台上的应用少而不被国人所接受。 (7)Google Android。自 2007 年推出,2008 年第一部搭载 Android 系统的 G1 上市至今不到短短三年时间,他已被许多人接受并且认可及 欢迎。 虽然如今的智能手机系统市场仍被 Symbian、 Windows Mobile 的占领, 但是 iPhone
1

基于 Android 手机操作系统软件开发

的革命以后,以及后起之秀 Android 的推出,在将来,智能手机市场将发生翻天覆地 的变化。

1.2 Android 平台介绍
Android 从诞生到现在也不过 3 年的时间, 但是也就是在这短短的 3 年内 Android 创造了一个迅速被人们知晓并追捧的奇迹。 2007 年 11 月 5 日, Google 与其他 33 家 手机制造商(包含摩托罗拉、宏达电、三星、LG)、手机晶片供应商、软硬体供应商、 电 信 业 者 所 联 合 组 成 的 开 放 手 持 装 置 联 盟 (Open Handset Alliance) , 发 布 了 名 为 Android 的开放手机软硬体平台。该联盟的成员宣布日后都会在 Android 平台上开发 他们的新的业务。不久之后的 2008 年 9 月 24 日,T-Mobile 公司首度公布第一台 Android 手机(G1)的细节,同日 Google 也放出了 Android SDK 1.0 rc1。这样 Android 进入了人们的视线。 Android 以其特有的开放性优势越来越受到人们和智能手机厂商的关注。 对于第三放软件开发商来说, Android 是一个真正意义上的开放性移动设备综合 平台,Android 系统是免费向开发人员提供的,这样就避免了开发中专利权的障碍。 因此,就能够为第三方软件开发商省下大笔资金。 对于设备制造商来说,Android 是一个免费的平台。当设备制造商每制造一台手 机时,那些支付给手机系统制造商的费用也省去了,这样也降低了每台手机的生产费 用,同时就降低了手机的价格,这样在市场上也提高了竞争力。 对硬体开发厂商来说,Android 也是个开放的平台。使用 Android 平台的厂商可 以更具自己的需求以及能力为 Android 开发具有该厂商特色的功能, 但是这样的增加 完全不用考虑版权的问题。 同时 Android 平台支持各种先进的网络、绘图、3D 处理能力,可以用来提供更 好的使用者体验。 Google Android 系统作为一个完全开源的操作系统,是由操作系统(Linux)、中 间件以及核心应用程序组成的软件栈(software stack)。 通过 android SDK 提供的 API 以及相应的开发工具, 程序员可以很方便的开发 android 平台上的应用程序。其整 个系统由应用程序(Application) ,应用程序框架(Application Framework) ,应用程 序库(Libraries) ,Android 运行库(Android Runtime) ,Linux 内核(Linux Kernel) 五个部分组成。Android 操作系统内置了一部分应用程序, 包括电子邮件客户端、 SMS 程序、日历、地图、浏览器、通讯录以及其他的程序,值得一提的是这些所有 的程序都是用 java 编写的。 因为应用程序框架使得组件更易于重用,所以开发者的应用程序可以很容易的
2

基于 Android 手机操作系统软件开发

调用 API 函数实现我们想要的功能。在遵守应用程序框架的安全机制约束的前提下, 开发者开发的一个应用程序可以使用其他程序所开发的功能。 虽然 Android 的应用程 序是用 Java 语言开发的, 但是 Android 给应用程序开发者提供了一系列的 C/C++ 程 序库,通过 Android 的一些特殊的设计,我们开发者可以使用这些库,这在后面的叙 述中将看到。 现今,Android 操作系统已成为许多手机制造商的宠儿,其中包括 HTC、索尼爱 立信、Samsung、摩托罗拉以及国内的联想、华为、海尔、华禹等。其中值得一提的 是摩托罗拉公司,就在 2009 年 11 月凭借其一款搭载 Android 平台的 Droid 手机,两 个月内就突破百万台,击败了苹果的 iPhone 3GS,被《时代》杂志评选为“年度最 佳科技产品” 。因此告别了两年多的低迷态势,走出了泥潭。

第二章

Android 开发环境的搭建

2.1 开发包及其工具的安装和配置
2.1.1 安装 JDK 和配置 Java 开发环境 (1)安装 JDK,安装包中包含了 JDK 和 JRE 两部分,建议将它们安装在同一个盘符 下。双击安装程序,选择安装的目录,点击“下一步”,等待安装程序自动完成安装即可。 (2)右键单击“我的电脑”,选择“属性”菜单项,选择“高级”选项卡,选择“环境变量”, 找到“Path”变量名(如果没有就新建一个名为“Path”的变量),点击“编辑”按钮,添加 JDK 安 装 目 录 中 “bin” 文 件 夹 路 径 , 如 图 2-1 所示 。 然 后 点 击 “ 确 定 ” 按 钮 完 成 。 再 找 到 “ClASSPATH”变量(如果没有,同样可以新建),输入 JDK 安装目录中“lib”以及“demo” 的路径,如图 2-2 所示,单击“确定”按钮完成。

图 2-1 “Path”变量配置

图 2-2 “ClASSPATH”变量配置

3

基于 Android 手机操作系统软件开发

(3)安装配置完成之后,要测试是否安装成功。点击开始→运行,输入“CMD”,打开 命令行模式。键入命令“java -version”,检测 JDK 是否安装成功,如果运行结果如图 2-3 所 示,即表示安装成功。

图 2-3 “java -version”测试命令

2.1.2 Eclipse 的安装与汉化 Babel 的安装方法和步骤如下所示: (1)启动 Eclipse 开发工具,依次点击“Help ” →选择“Software Update ...”菜单命令,打 开“Software Updates and Add-ons”对话框,选择“Avaliable Software”项。接着点击“Add Site...”按钮,在“Location”文本框中输入 Babel 更新地址:http://download.eclipse.org/technology/babel/update-site/ganymede,然后点击 OK 按钮,如图 2-4 所示。

图 2-4 添加语言包更新地址

(2) “Avaliable Software”表中会多出一项 http://download.eclipse.org/technology/babel/update-site/ganymede/,点击该项左边的箭头,就会出现网络更新软件列表,如图 2-5 所示。

图 2-5 Avaliable Software 选择框

4

基于 Android 手机操作系统软件开发

(3)选择“Simplified Chinese”语言包后,点击 “Install... ”按钮,等待 Eclipse 处理。 处理完成后会出现“Install”对话框,这时会提示你选择要安装的语言包。安装完毕后, 重新启动 Eclipse 即可完成全部汉化过程。如果重启 Eclipse 后不显示中文,请用命令行 “eclipse.exe -nl zh_CN”重新启动 Eclipse。 2.1.3 SDK 和 ADT 的安装和配置 安装了 JDK 和 Eclipse 后,现在就要安装 Android SDK 和 ADT 插件了。 1.Android SDK 安装 (1)解压缩下载好的 SDK 安装包到要安装 SDK 的路径,然后运行“SDK Setup.exe”。 (2)如果遇到了消息为“Failed to fetch URL…”的错误提示,那么需要将 HTTPS 方式改 为 HTTP 方式, 在“Android SDK and AVD Manager”窗口的左侧选择 “Settings”, 选中 “Force https://…”选项(如图 2-6 所示),点击“Save & Apply”并重新运行 SDK Setup.exe。

图 2-6 更改 HTTP 方式

(3)点击“Available Packages”,选择要安装的 API 版本及 USB 驱动和 SDK 文档,如图 2-7 所示。这里为了测试方便,所以全部选择了。

图 2-7 选择 API 版本

5

基于 Android 手机操作系统软件开发

(4)选择好之后点击“Install Selected”按钮,安装选中的软件包,在接下来出现的界面 中依次点击“Accept All”单选按钮和“Install Accepted”按钮,开始下载所选择的安装包。下 载完成之后,根据提示即可完成后续的安装操作。 2.Android SDK 配置 需要将 Android SDK 安装目录中的 tools 文件夹路径添加到环境变量中以便使用,操 作步骤如下: (1) 右键点击“我的电脑”, 依次选择“属性”→“高级”→“环境变量”选项, 如图 2-8 所示。 (2)选择“系统变量”中变量名为“Path”的项,点击“编辑”按钮,将 Android SDK 安装 文件夹下的 tools 文件夹的路径加入到“Path”变量中,注意用“、”隔开,如图 2-9 所示。

图 2-8 环境变量

图 2-9 编辑系统环境变量

(3)依次点击“确定”,完成环境变量配置。 3.安装和配置 ADT 下面我们来安装和配置 ADT 插件,步骤如下: (1)启动 Eclipse,点击“Help”菜单,依次选择“Software Update...”项和“Avaiable Software”选项卡, 点击“Add Site...”按钮, 输入地址 https://dl-ssl.google.com/android/eclipse/, 结果如图 2-10 所示。 (2)点击“OK”,这时可能会出现如图 2-11 所示的错误。

6

基于 Android 手机操作系统软件开发

图 2-10 添加 ADT 的更新地址

图 2-11

更新地址错误

解决这个问题的方法是: 将“https://dl-ssl.google.com/android/eclipse/”中的“https”更改为 “http”,在接下来的对话框中选中“Name”下的所有选项,根据提示即可完成后续的安装过 程。 (3)打开菜单“Windows”,依次选择“Preferences”→“Android”,点击“Browse...”按钮, 选择 Android SDK 的安装路径,如图 2-12 所示。

图 2-12 Eclipse 首选项

(4)点击“OK”按钮 ,开打菜单“File”,依次选择“NEW” → “Project...”菜单命令,出现 如图 2-13 所示的“Android Projest”选项,则表示安装配置成功。

图 2-13 新建工程界面

7

基于 Android 手机操作系统软件开发

2.2 创建第一个 Android 项目——HelloAndroid
2.2.1 创建 HelloAndroid 项目 ADT 提供了简单的生成 Andriod 应用框架的功能,我们现在使用 ADT 通过 Eclipse 创 建一个 Android 工程,其步骤如下。 (1)打开 Eclipse 开发工具,新建一个项目,在弹出的“New Project”对话框的列表中展 开“Android”项,然后选择“Android Project”子项,如图 2-14 所示。

图 2-14 新建一个 Android 工程

(2)点击“Next”按钮,在“Project name”文本框中输入“HelloAndroid”,然后在“Build Target”选项框中选择“Android SDK 1.5”,在 Application name 文本框中输入这个应用程序 的名字(HelloAndroid),在 Package name 文本框中输入应用程序包的名字 (com.yarin.Android.HelloAndroid),在 Create Activity 文本框中输入 Activity 的名字 (HelloAndroid),如图 2-15 所示。

图 2-15 新建 HelloAndroid 工程
8

基于 Android 手机操作系统软件开发

(3)单击“Finish”按钮,此时 Eclipse 会自动完成 Android 项目的创建,这时 Eclipse 开 发平台左边的导航器中显示了刚才创建的项目“HelloAndroid”。 如果没有出现导航器, 则可 以通过单击“Window”→“Show View” →“Package Explorer”菜单命令来显示导航器,如图 2-16 所示。 2.2.2 运行 HelloAndroid 及模拟器的使用 从 Android 1.5 开始引入了 AVD(Android Virtual Device)这个概念。AVD 是一个经 过配置的模拟器。在创建 AVD 时可以配置的选项有:模拟器影像大小、触摸屏、轨迹球、 摄像头、屏幕分辨率、键盘、GSM 、GPS、Audio 录放、SD 卡支持、缓存区大小等。配 置 Android 模拟器的具体步骤如下所示。 (1)首先打开“Android SDK and AVD Manager”,如图 2-17 所示。

图 2-16 显示项目管理器

图 2-17 Android SDK and AVD Manager 菜单

(2)点击左边的“Virtual Devices”选项,再点击右边的“New...”按钮,新建一个 AVD。 (3)在“Name”标签处填写 AVD 的名字,在“Target”标签处选择 API 等级,在“Size”标 签处填写要创建的 SD 卡的大小,在“Skin”标签中设置模拟器的风格,如图 2-18 所示。 (4)到这里,我们便可以运行第一个 Android 项目了吗?还是不行,还需要配置模拟 器运行的 AVD。操作步骤为:点击“Run”,选择“Run Configurations”菜单命令,打开“Run Configurations”对话框,如图 2-19 所示。 (5)双击“Run Configurations”对话框左边的导航器中的“Android Application”菜单命 令,创建一个 Android 项目运行配置。在右边的“Name”文本框中输入 Android 项目运行配 置的名字 (HelloAndroid) 在“Android”选项卡中的“Project”文本框中输入要运行的 Android , 项目,同样可以点击右边的“Browse...”按钮来选择 Android 项目,如图 2-20 所示。

9

基于 Android 手机操作系统软件开发

图 2-18 创建 AVD

图 2-19 运行配置界面

图 2-20 配置要运行的 HelloAndroid 项目

(6)点击“Target”选项卡,选择“Automatic”单选框,然后在 AVD 列表框中选择我们刚 才创建的 AVD,如图 2-21 所示。

10

基于 Android 手机操作系统软件开发

图 2-21 制定运行 HelloAndroid 项目的 AVD

(7)点击“Run”按钮,这样便可以运行 HelloAndroid 项目了,不过 Android 模拟器启动 非常慢,慢慢等吧。但是 Android 的模拟器做得非常漂亮,终于可以看到第一个 Android 项目的运行效果了,如图 2-22 所示。

图 2-22HelloAndroid 项目在模拟器中的运行效果

图 2-23 Android 模拟器显示中文界面

从 Android SDK 1.5 版本开始,Android 模拟器开始支持中文了,也内置了中文输入法 (谷歌拼音输入法),下面我们就将模拟器改为中文环境。操作步骤为:启动 Android 模 拟器,进入 Android 模拟器菜单,选择“Settings”菜单项,开打“Settings”菜单,选择 “Locale&text”菜单项, 打开“Locale&text”菜单, 依次选择“Select locale”项和“Chinese(China)” 项,这样就设置为中文了,然后返回桌面,如图 2-23 所示。

11

基于 Android 手机操作系统软件开发

第三章
3.1 载入页面
3.1.1 UI 篇

新浪微博客户端的开发

本软件设定用户第一个接触到的功能就是页面载入等待功能,这个功能对使用者来说 就是一个持续 1、2 秒钟的等待页面,在用户等待的同时程序做一些必要的检查以及数据 准备工作,载入页面分为 UI 篇和功能篇,从表及里首先是 UI 的实现,一个软件除功能之 外还得有一个光鲜的外表也是非常重要的,先用 ps 做了一下设计效果图如下:

图 3-1 载入页面制作

一、接下来的任务就是在 android 中实现这样的效果显示,从这个效果的设计分别把 图片分成背景、版本号部分、软件名称和图标、作者名称和 blog 四个部分,按照这样的思 路把分别生成 4 张 png 的图片,背景部分考虑实现横屏和竖屏切换额外添加一张横屏背景 图,然后新建 android 工程,我这里的名称为 MySinaWeibo,android 版本勾选 2.2,并且创 建名为 MainActivity 的 Activity 作为整个软件的起始页面,然后把上面的这些图片保存到 项目的 res/drawable-mdpi 文件夹下,关于 res 目录下的 drawable-mdpi、drawable-ldpi、 drawable-hdpi 三 个 文 件 夹 的 区 别 , mdpi 里 面 主 要 放 中 等 分 辨 率 的 图 片 , 如 HVGA (320x480)。ldpi 里面主要放低分辨率的图片,如 QVGA (240x320)。hdpi 里面主要放高分辨

12

基于 Android 手机操作系统软件开发

率的图片,如 WVGA (480x800),FWVGA (480x854)。android 系统会根据机器的分辨率来分 别到这几个文件夹里面去找对应的图片,在开发程序时为了兼容不同平台不同屏幕,建议 各自文件夹根据需求均存放不同版本图片。 二、完成图片资源的准备后接下就是 layout 文件的编写, 在 res/layout 文件夹下新建 main.xml 文件,这个 layout 采用 LinearLayout 控件作为顶层控件,然后用 ImageView 控件 分别实现版本号图片顶部靠左对齐显示、软件名称和图标图片居中对齐。注意在版本号图 片显示 ImageView 控件下面添加一个 RelativeLayout 控件作为软件名称和图标图片 ImageVIew 和作者名称和 blog 图片 ImageView 的父控件用来控制居中对齐已经底部对齐的 实现。 三、在 ec 打开名为 MainActivity 的 Activity 源代码文件进行编辑,onCreate 部分代码 如下: public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); }

然后运行项目可以在模拟器中显示,上面的几个图片都按照设计的位置和效果进行显示只 是整个页面的背景还是黑色的,接下来就是背景部分的显示实现,由于为了实现横竖屏切 换显示,背景图的显示采用代码进行控制显示,首先用如下方法获取当前手机是横屏还是 竖屏: //获取屏幕方向 public static int ScreenOrient(Activity activity) { int orient = activity.getRequestedOrientation(); if(orient != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE && orient != ActivityIn fo.SCREEN_ORIENTATION_PORTRAIT) { //宽>高为横屏,反正为竖屏 WindowManager windowManager = activity.getWindowManager(); Display display = windowManager.getDefaultDisplay(); int screenWidth = display.getWidth(); int screenHeight = display.getHeight(); orient = screenWidth < screenHeight ? ActivityInfo.SCREEN_ORIENTATION_PORTR
13

基于 Android 手机操作系统软件开发

AIT : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; } return orient; } 然后编写一个名为 AutoBackground 的公共方法用来实现屏幕背景的自动切换, 后面的 几乎每一个功能页面都需要用到这个方法: public static void AutoBackground(Activity activity,View view,int Background_v, int Backgroun d_h) { int orient=ScreenOrient(activity); if (orient == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { //纵向 view.setBackgroundResource(Background_v); }else{ //横向 view.setBackgroundResource(Background_h); } } 完成上述两方法后在 MainActivity 的 onCreate 方法中调用 AutoBackground 方法进行屏 幕自动切换: LinearLayout layout=(LinearLayout)findViewById(R.id.layout); //背景自动适应 AndroidHelper.AutoBackground(this, layout, R.drawable.bg_v, R.drawable.bg_h); 到此完成了载入页面的 UI 部分的实现,测试运行模拟器中查看效果,基本上跟最上面 的设计效果图相符,测试效果图如下:

14

基于 Android 手机操作系统软件开发

图 3-2 载入页面测试效果图

3.1.2 sqlite 篇 通过上一节已经完成了载入页面的 UI 部分的实现,接下来在上面的基础上完成载入 页面的功能代码。 首先说明一下新浪微博提供了 OAuth 和 Base OAuth 两种认证方式,本项目是采用 OAuth 认证方式,采用这种方式就需要有用户的新浪 UserID、Access Token、Access Secret 这 3 样东西才能自由便利的调用新浪的开放接口,本项目是这样做的当用户第一次使用软 件时进行授权认证获取这 3 样东西的时候存储到 sqlite 库中以便用户下次使用时不需要重 新进行繁琐的授权认证操作直接从 sqlite 库中读取出来即可,由于这样的需求载入页面的 功能设定是这样:当用户打开软件显示载入页面时开始检查 sqlite 库中是否已经保存有用 户的新浪微博的 UserID 号、Access Token、Access Secret 的记录,如果一条记录都没有那 就说明用户是第一次使用本软件那么跳到认证授权页面进行授权认证操作(认证授权功能 在接下来的两篇中进行实现讲解)获取这 3 个值保存到 sqlite 库中,如果已经包括了记录, 那么读取这些记录的 UserID 号、Access Token、Access Secret 值然后根据这 3 个值调用新 浪的 api 接口获取这些记录对应的用户昵称和用户头像图标等信息。 上面功能设定中涉及到 sqlite 数据库的创建、数据表的创建、数据记录的添加、数据 记录的读取等操作,这里新建名为 SqliteHelper.java 类文件提供 sqlite 数据表的创建、更新 等。 接下来新建名为 DataHelper.java 类文件实现用户记录的创建、更新、删除等。

15

基于 Android 手机操作系统软件开发

完成上面的代码后,我们需要在载入页面中调用上面的方法实现 sqlite 库中是否已经 保存有用户的新浪微博的 UserID 号、Access Token、Access Secret 的记录的功能在 MainActivity 的 onCreate。

3.2 OAuth 授权认证

图 3-3 OAuth 授权认证示意图

本篇说说关于 OAuth 授权认证的事情,新浪开放 api 都必须在这个基础上才能调用, 所以有必要专门来讲讲,前面的文章中已经提到过关于新浪微博提供了 OAuth 和 Base OAuth 两种认证方式, 并且本项目采用 OAuth 认证方式, 至于为什么采用这个 OAuth 认证 而不采用 Base OAuth 认证原因很简单,自从 Twitter 只支持 OAuth 认证方式以来,各大应 用都纷纷转向 OAuth 认证方式,而新浪微博的开放平台也将在近日停止 Base OAuth 的认 证方式。 OAuth 的基本概念,OAUTH 协议为用户资源的授权提供了一个安全的、开放而又简 易的标准。与以往的授权方式不同之处是 OAUTH 的授权不会使第三方触及到用户的帐号 信息(如用户名与密码) ,即第三方无需使用用户的用户名与密码就可以申请获得该用户 资源的授权,因此 OAUTH 是安全的。同样新浪微博提供 OAuth 认证也是为了保证用户账 号和密码的安全,在这里通过 OAuth 建立普通新浪微博用户、客户端程序(我们正在开发 的这个 android 客户端程序) 、新浪微博三者之间的相互信任关系,让客户端程序(我们正 在开发的这个 android 客户端程序)不需要知道用户的账号和密码也能浏览、发布微博,
16

基于 Android 手机操作系统软件开发

这样有效的保护了用户账号的安全性不需要把账号密码透露给客户端程序又达到了通过 客户端程序写微博看微博目的。这个是 OAuth 的作用。 结合新浪微博的 OAuth 认证来说说具体的功能实现,首先罗列一下关键字组,下面四 组关键字跟我们接下来 OAuth 认证有非常大的关系。 第一组: (App Key 和 App Secret) ,这组参数就是本系列文本第一篇提到的建一个新 的应用获取 App Key 和 App Secret。 第二组: (Request Token 和 Request Secret) 第三组: (oauth_verifier) 第四组: (user_id、Access Token 和 Access Secret) 新浪微博的 OAuth 认证过程,当用户第一次使用本客户端软件时,客户端程序用第一 组作为参数向新浪微博发起请求,然后新浪微博经过验证后返回第二组参数给客户端软件 同时表示新浪微博信任本客户端软件,当客户端软件获取第二组参数时作为参数引导用户 浏览器跳至新浪微博的授权页面,然后用户在新浪的这个授权页面里输入自己的微博账号 和密码进行授权,完成授权后根据客户端设定的回调地址把第三组参数返回给客户端软件 并表示用户也信任本客户端软件,接下客户端软件把第二组参数和第三组参数作为参数再 次向新浪微博发起请求,然后新浪微博返回第四组参数给客户端软件,第四组参数需要好 好的保存起来这个就是用来代替用户的新浪账号和密码用的,在后面调用 api 时都需要。 从这个过程来看用户只是在新浪微博的认证网页输入过账户和密码并没有在客户端软件 里输入过账户和密码,客户端软件只保存了第四组数据并没有保存用户的账户和密码,这 样有效的避免了账户和密码透露给新浪微博之外的第三方应用程序,保证了安全性。 本项目用为了方便开发采用了 oauth-signpost 开源项目进行 OAuth 认证开发,新建 OAuth.java 类 文 件 对 OA 进 行 简 单的 封 装, OAuth 类 主 要有 RequestAccessToken 、 GetAccessToken、SignRequest 三个方法,第一个方法 RequestAccessToken 就是上面过程中 用来获取第三组参数用的,GetAccessToken 方法是用来获取第四组参数用,SignRequest 方法是用来调用 api 用。由于采用了 oauth-signpost 开源项目简单了很多。 这样就完成了 OAuth 功能类的开发,后面都会用到这个类相关的方法。

3.3 用户授权页面
3.3.1 用户授权页面 UI 篇 上一篇讲了讲 OAuth 授权认证的事情,大概的介绍了 OAuth 的原理,并且完成了一个 OAuth.java 的类库,提供了几个 OAuth 认证必要的方法,本篇开始具体讲本项目的用户授

17

基于 Android 手机操作系统软件开发

权功能,用户授权页面是当用户第一次使用本软件的时候自动从载入页面跳转过来的显示 的页面,涉及 OAuth 认证相关都是在上一篇的 OAuth.java 的类基础上开发。用户授权页面 分为 UI 篇和功能篇两篇,本篇先来讲讲 UI 的实现,这次就不贴 PS 的效果图了直接贴实 现后的功能截图如下:

图 3-4 UI 实现图

看上面的图,其实这个页面的 UI 实现不复杂,重点来讲讲这个半透明的弹出对话框 窗 口 是 如 何 实 现 的 , 首 先 新 建 名 为 AuthorizeActivity.java 的 Activity , 并 且 在 AndroidManifest.xml 文件中添加这个 Activity,这样这个 Activity 才能被使用,接下来为这 个 Activity 新建名为 authorize.xml 的 Layout,这个 Layout 很简单只负责 logo 小图标显示, 背景部分和透明窗口都是有代码来实现。 完 成 Layout 建立后在 AuthorizeActivity 的 onCreate 方法 添加如下代码,设置 authorize.xml 为 AuthorizeActivity 的页面 Layout: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.authorize); ....... } 接下来是本节的重点部分,半透明弹窗用 Dialog 控件进行实现,首先为这个半透明弹 窗新建一个名为 dialog.xml 的 Layout,这个 Layout 主要是对 4 个元素进行布局, 如图所示分
18

基于 Android 手机操作系统软件开发

别为 i 小图标、信息提示、中间文字、开始按钮,首先用 LinearLayout 对 i 小图标和信息 提示进行水平布局, 中间文字以一个 TextView 跟在下面, 对于开始按钮是用 RelativeLayout 进行底部对齐显示。 完成了半透明弹窗的 Layout 定义接下来我们要做的就是为它写一个自定义样式来实 现我们想要的显示效果,首先我们需准备一个圆角的半透明 png 图片名为 dia_bg.png 并且 添加到 drawable 中,接下来再 res/values 文件夹新建名为 dialogStyle.xml 的 resources 样式 文件。 这个样式文件的说明如下 parent="@android:style/Theme.Dialog" :在系统 Dialog 样式基础上,相当于继承系统样式 <item name="android:windowFrame">@null</item> :Dialog 的 windowFrame 框为无 <item name="android:windowIsFloating">true</item>:是否浮现在 activity 之上 <item name="android:windowIsTranslucent">false</item>:是否半透明 <item name="android:windowNoTitle">true</item>:是否显示 title <item name="android:windowBackground">@drawable/dia_bg</item>:设置 dialog 的背景 <item name="android:backgroundDimEnabled">false</item>: 背景是否模糊显示 接下来写 java 代码把这个半透明弹窗显示出来,在 AuthorizeActivity 的 onCreate 方法 添加如下代码: ...... View diaView=View.inflate(this, R.layout.dialog, null); dialog=new Dialog(AuthorizeActivity.this,R.style.dialog); dialog.setContentView(diaView); dialog.show(); ...... 最后运行查看效果,到这里我们的任务已经完成了。 3.3.2 用户授权页面功能篇

19

基于 Android 手机操作系统软件开发

图 3-5 用户授权页面的 UI

在上一篇实现了用户授权页面的 UI,如上图,接下来要做的就是在这个基础上完成功 能部分真正实现用户的授权认证, 这一篇是 android 开发我的新浪微博客户端-OAuth 篇(2.1) 的具体应用篇原理就不多解释了不懂的看 OAuth 篇即可。 认证过程从点击开始按钮然后跳 转到新浪的授权页面,接着用户在新浪的页面里输入自己的账户和密码确定后返回用户授 权页面。首先给开始按钮添加点击事件代码,代码中主要是调用我们前面 android 开发我 的新浪微博客户端-OAuth 篇(2.1)完成的 OAuth 类的 RequestAccessToken 方法用来获取 oauth_verifier,具体代码如下: ImageButton stratBtn=(ImageButton)diaView.findViewById(R.id.btn_start); stratBtn.setOnClickListener(new OnClickListener(){

@Override public void onClick(View arg0) { auth=new OAuth(); auth.RequestAccessToken(AuthorizeActivity.this, CallBackUrl); }

}); 上面的代码中重点来说明一下 RequestAccessToken 方法的第二参数 CallBackUrl, 这个 参数是用户在新浪的页面中输入账户密码后完成认证后返回的地址,我这里是这样设置的
20

基于 Android 手机操作系统软件开发

CallBackUrl="myapp://AuthorizeActivity",在 AndroidManifest.xml 中配置 AuthorizeActivity 添加如下配置把 myapp://AuthorizeActivity 指向到 AuthorizeActivity,这样当页面返回到 AuthorizeActivity 中就可以获取到传过来的 oauth_verifier 参数。 <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="myapp" android:host="AuthorizeActivity" /> </intent-filter> 再 AuthorizeActivity 如果来接收返回的 oauth_verifier 参数呢?接下来 AuthorizeActivity 添加如下方法: @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); //在这里处理获取返回的 oauth_verifier 参数 } 关于 onNewIntent 的说明是这样的,onCreate 是用来创建一个 Activity 也就是创建一个 窗体,但一个 Activty 处于任务栈的顶端,若再次调用 startActivity 去创建它,则不会再次 创建。 若你想利用已有的 Acivity 去处理别的 Intent 时, 你就可以利用 onNewIntent 来处理。 在 onNewIntent 里面就会获得新的 Intent,在这里 AuthorizeActivity 是属于已有的 Acivity, 所以需要 onNewIntent 来处理接收返回的参数,获取 oauth_verifier 参数后 OAuth 还没有结 束从 OAuth 篇描述来看还需要进行根据这个参数继续向新浪微博请求获取 User_id、 Access Token 和 Access Secret,在这里我把这些操作全部写在了 GetAccessToken 方法中。在 onNewIntent 添加如下代码: UserInfo user= auth.GetAccessToken(intent); if(user!=null){ DataHelper helper=new DataHelper(this); String uid=user.getUserId(); if(helper.HaveUserInfo(uid)) { helper.UpdateUserInfo(user); Log.e("UserInfo", "update");

21

基于 Android 手机操作系统软件开发

}else { helper.SaveUserInfo(user); Log.e("UserInfo", "add"); } } 通过上面的代码完成了 User_id、 Access Token 和 Access Secret 获取并且保存到了 sqlite 库中,这样就完成了用户的 OAuth 认证,当需要调用新浪的 api 时只需要去 sqlite 库中找 该用户的 User_id、Access Token 和 Access Secret 即可。

3.4 登录页面
3.4.1 登陆页面 UI 篇

图 3-6 用户登陆首页

首先回顾一下功能流程当用户开启软件显示载入页面时程序首先去 sqlite 库查询是否 已经保存有用户的新浪微博的 UserID 号、Access Token、Access Secret 的记录如果没有一 条记录那么跳转到用户授权功能页面,这个已经由上面两篇文章实现了,如果有记录那么 页面跳转到用户登录页面,也就是本篇以及下篇要实现的功能,本篇讲 UI 的实现,本项 目支持多微博账号了,也就是用户可以设置多个微博账号,登录的时候选择其中的一个登

22

基于 Android 手机操作系统软件开发

录, 具体效果如上图,新建名 LoginActivity.java 的 Activity 并且在 AndroidManifest.xml 中进 行相应配置,这个页面就是我们要实现的用户登录页面。 看上面的效果,首先页面分 3 部分实现,背景部分、底部菜单部分、用户选择以及头 像显示部分,首先在 res/layout 的目录下新建名为 login.xml 的 layout,然后根据页面显示 要求编写如下的布局控制。 正对上面的 login.xml 的 layout 进行一下说明, 背景部分前面已经讲过了这里也就不重 复。 底部菜单实现,原本我是采用 GridView 实现的非常的方便但是后来由于显示位置不 好控制改成了用 RelativeLayout 和 LinearLayout 嵌套的方式,实现的比较土但是达到了显 示需求,首先是一个最外面的 RelativeLayout 目的是用来实现底部对齐显示,并且把这个 RelativeLayout 的 背 景 设 置 为 浅 蓝 色 半 透 明 的 效 果 , 关 键 这 2 行 : android:layout_alignParentBottom="true" 和 android:background="#BB768e95" 。 然 后 是 在 RelativeLayout 内部添加 3 个 LinearLayout 分别是用来显示添加账号、退出软件、删除账号 3 个功能按钮菜单,并且分别设置为左对齐、居中对齐、右对齐,3 个 LinearLayout 都设置 为垂直布局 android:orientation="vertical",然后每 LinearLayout 添加相应的图片和文字。 用户选择以及头像显示部分,这块分成 3 小块,用来显示用户头像的 ImageView、 用来显示用户名字并且点击可以出现选择列表的 EditText、用来点击进入当前选择用户首 页的功能按钮 ImageButton,这 3 小块的布局实现也是采用 elativeLayout 和 LinearLayout 相互嵌套配合的方式实现的具体参考 login.xml。这里重点说说这个账号选择列表弹出窗口 的实现,当点击下拉箭头按钮的时候弹出并显示,这个是用 Dialog 控件实现,首先准备好 圆角的半透明背景图 mask_bg.png 然后添加到 res/drawable-mdpi 文件夹下,接着自定义一 个 Dialog 样式文件,在 res/values 目录下新建名为 dialogStyles2.xml 的 resources 文件,在 用户授权验证页面的时候我们也自定义过类似的 Dialog 的样式, 具体解释可以参考前面的 户授权验证页面功能, 接下来还需要定义选择列表的 layout, 新建名为 dialog2.xml 的 layout 文件。 完成了 layout 和样式文件的编写,接下来就是把 dialogStyles2.xml 样式文件和 dialog2.xml 的列表 layout 用起来,当点击 id 为 iconSelectBtn 的 ImageButton 时显示用户选 择窗口,在 LoginActivity 的 onCreate 方法中添加代码。 到这里登录的 UI 部分就实现的差不多了,剩下的都是一些功能部分代码用来实现从 sqlite 中账号列表的获取,以及点击选择等交互操作等。 3.4.2 登录页面功能篇

23

基于 Android 手机操作系统软件开发

上一篇中完成了如上图的 UI 部分的实现,现在继续来讲功能的实现,用户登录操作 主要就是账号列表显示和选择账号登录两个功能其他的都是些简单的辅助功能,首先是点 击 id 为 iconSelectBtn 的 ImageButton 时显示用户选择窗口,这个时候去数据库中获取账号 记录然后在选择窗口中以列表方式显示出来,通过上一篇已经知道 Id 为 list 的 ListView 控件 来显示账号列表,首先是从数据库中获取所有的账户记录然后设置默认选中的用户账号。 这个 initUser() 初始账号的方法在 LoginActivity 的 onCreate 中调用,主要完成两件事情, 第 一 件 获 取 通 过 userList = dbHelper.GetUserList(false); 获 取 所 有 的 账 户 记 录 , 关 于 DataHelper 前面已经有说过了,如果获取的用户记录为空那么就跳转到用户授权功能页面 让用户添加账号,如果不为空那么通过 SharedPreferences 去读取用户上一次选择的账号名 称,如果没有或者数据库里账号记录不包括这个账户名称那么默认显示记录的第一个账号 和头像,如果有那么显示这个账户的名称和头像。关于 SharedPreferences,是 android 提供 给开发者用来存储一些简单的数据用的,非常方便类似于网站的 Cookie,在这里我就是用 这个来保存上一次用户选择的是哪个账号,非常实用。 接下类首先为 Id 为 list 的 ListView 控件准备数据 Adapter,这个 Adapter 非常简 单就是普通的 adapter 继承 BaseAdapter 即可。 接下就是为这个 ListView 设定数据源 Adapter, 在账号选择窗口显示的时候进行设置, 添加到 id 为 iconSelectBtn 的 ImageButton 的 OnClickListener 中。 通过上面代码完成了账号选择的功能,接下来给 id 为 login 的 ImageButton 添加 OnClickListener,使得点击后以当前选择账号进入微博首页,在上面的 GoHome 方法中 ConfigHelper.nowUser 是类型为 UserInfo 的 static 类型用来保存当前登录账号的信息, 替代 web 中 session 使用。 最后添加如下方法,用来当这个登录 LoginActivity 结束的时候保存当前选择的账户名 称到 SharedPreferences 中,以便帮用户记住登录账号的功能,就是前面的 initUser() 初始账 号的方法中会获取保存在 SharedPreferences 中的账户名称代码如下: @Override protected void onStop() { //获得 SharedPreferences 对象 SharedPreferences MyPreferences = getSharedPreferences(Select_Name, Activity.MODE_ PRIVATE); //获得 SharedPreferences.Editor 对象 SharedPreferences.Editor editor = MyPreferences.edit(); //保存组件中的值

24

基于 Android 手机操作系统软件开发

editor.putString("name", iconSelect.getText().toString()); editor.commit(); super.onStop(); }

3.5 用户首页面
3.5.1 用户首页面 UI 篇

图 3-7 用户首页

在前篇完成了用户登录功能后开始用户首页的开发,用户的首页主要的内容是当前登 录用户关注的微博列表,本篇先来讲讲 UI 的实现,效果如上图,整个页面分为上、中、 下三部分,上面部分是工具条,显示当前登录用户的昵称以及写微博、刷新两个功能按钮; 中间部分是当前用户关注的最新微博列表,下面部分是功能切换栏,用来进行各个功能之 间的切换。 首先新建名为 HomeActivity.java 的 Activity 作为用户首页, 然后在 res/layout 目录下新 建名为 home.xml 的 Layout。 这个布局首先是一个竖直的根 LinearLayout,在这个根 LinearLayout 里面分别是两个 RelativeLayout, 第一个 RelativeLayout 用来显示页面的工具条,第二个 RelativeLayout 用

25

基于 Android 手机操作系统软件开发

来显示列表以及底部的功能栏,特别主要在这第二个 RelativeLayout 中有一个 id 为 loadingLayout 的 LinearLayout 是用来显示数据载入中的动画, 它的 android:visibility 属性为 invisible(也可以设置成 gone,区别:invisible 这个 View 在 ViewGroupt 中仍保留它的位置, 不重新 layout gone>不可见,但这个 View 在 ViewGroupt 中不保留位置,重新 layout,那后 面的 view 就会取代他的位置。 ),也就是一开始不显示的意思,接下来看看 <ProgressBar android:id="@+id/loading" android:layout_width="31px" android:layout_height="31px" android:layout_gravity="center" style="@style/progressStyle"> </ProgressBar> 这个 ProgressBar 控件就是用来显示动画用的,关键就是 style="@style/progressStyle", 在 res/values 目录下新建名为 loadingstyles.xml,内容如下: <?xml version="1.0" encoding="UTF-8"?> <resources> <style name="progressStyle" width="38" height="38" parent="@android:style/Widget.Progre ssBar.Small"> <item name="android:indeterminateDrawable">@anim/loading</item> </style> </resources> 接着准备好 r1.png - r8.png, 八张不同的小图片分

别代表每旋转 45 度图片,八张刚好是 360 度。把这些图片添加到 res/drawable-mdpi 目录 中。然后在 res/anim 目录下新建名为 loading.xml 动画文件,内容如下: <?xml version="1.0" encoding="UTF-8"?> <animation-list android:oneshot="false" xmlns:android="http://schemas.android.com/apk/res/android"> <item android:duration="200" android:drawable="@drawable/r1" /> <item android:duration="200" android:drawable="@drawable/r2" /> <item android:duration="200" android:drawable="@drawable/r3" /> <item android:duration="200" android:drawable="@drawable/r4" /> <item android:duration="200" android:drawable="@drawable/r5" />

26

基于 Android 手机操作系统软件开发

<item android:duration="200" android:drawable="@drawable/r6" /> <item android:duration="200" android:drawable="@drawable/r7" /> <item android:duration="200" android:drawable="@drawable/r8" /> </animation-list> 3.5.2 用户首页面功能篇 本篇接下来讲功能部分的实现,本页面主要的功能就用户关注的最新微博列表,从上 一篇中知道本列表是用 ID 为 Msglist 的 ListView 控件来实现, 本篇的主要就讲解如果获取 微博列表数据给这个 ListView 提供显示数据。ListView 每一条子数据分别由用户头像、用 户昵称、发布时间、是否包含照片、微博内容这五部分组成,根据这五部分定义一个名为 WeiBoInfo.java 实体类。然后在 res/layout 目录下新建名为 weibo.xml 的 Layout 用来控制 ListView 子项的显示部件,接下来为列表控件定义一个数据 Adapter,这个 Adapter 实现没 有什么特别的很普通, 不过这个中使用了 AsyncImageLoader 的方法, 这个是用来实现用户 头像图标的异步载入显示,这样能提高列表显示的速度,提高用户体验,完成上述的工作 后,接下来就是显示微薄列表, 在 HomeActivity 的 onCreate 方法中调用 loadList();上面的 loadList() 方法通过新浪 Api 接口 http://api.t.sina.com.cn/statuses/friends_timeline.json 获取当 前登录用户及其所关注用户的最新微博消息,然后显示到列表中。

3.6 阅读微博
3.6.1 阅读微博 UI 篇

图 3-8 阅读微博

27

基于 Android 手机操作系统软件开发

上一篇完成了微博列表的功能,本篇接着做预读微博的功能,本篇主要讲讲 UI 部分的 实现,最终实现的效果如上图所示。整个显示页面从上往下分为四部分,第一部分顶部工 具条、第二部分作者头像和名称、第三部分微博正文、第四部分功能按钮区。 新建名为 ViewActivity.java 作为阅读微博的页面,再 res/layout 目录下新建名为 view.x ml 的 Layout, 上面这个布局实现起来并不复杂, 主要看看功能按钮区的 4 个按钮的点击上去的切 换背景的效果,以关注按钮为例子看这行设置,android:background="@drawable/lt_selector ", res/drawable-mdpi 目录下新建名为 lt_selector.xml 用来实现点击上去切换图片的效果, 在 本篇虽然看 layout 文件非常的长,其实仔细看看非常的简单了没有什么难和复杂的了,就 是按照前面的经验控制好图片以及控件的显示位置和样式即可,本篇中用了一个 ScrollVie w 控件这个是前面没有用到过的,主要是用来当微博的内容超出显示区域的时候出现滚动 条用的这个非常容易使用 3.6.2 阅读微博功能篇 在上面一篇中已经实现了预读微博的 UI 界面,效果如上图,接下来完成功能部分的 代码,当用户在上一个列表界面的列表中点击某一条微博的时候显示这个阅读微博的界 面,在这个界面中根据传来的微博 ID,然后根据这个 ID 通过 api 获取微博的具体内容进 行显示。 接下来就是 view 方法具体获取微博内容的方法,在这个方法中如果获取的本条微博 如果包含图片那么就用前面 AsyncImageLoader 的方法异步载入图片并且进行显示, 同时在 这个方法中还要获取本条微博被转发的次数以及评论的次数, 在上面的方法中对于微博中包含的图片显示尺寸进行了特别的处理, 如果直接把获取 的图片显示在 ImageView 中,因为当图片宽高超过手机屏幕的时候,系统会自动按照手机 的屏幕按比例缩放图片进行显示,但是我发现一个现象图片的高虽然是按照比例缩小了, 但是图片占据的高仍旧是原来图片的高度照成真实图片和文字内容之间多了很高的一块 空白,这个现象非常的奇怪,所以我写了如下方法进行处理: private void showImg(ImageView view,Drawable img){ int w=img.getIntrinsicWidth(); int h=img.getIntrinsicHeight(); Log.e("w", w+"/"+h); if(w>300) {

28

基于 Android 手机操作系统软件开发

int hh=300*h/w; Log.e("hh", hh+""); LayoutParams para=view.getLayoutParams(); para.width=300; para.height=hh; view.setLayoutParams(para); } view.setImageDrawable(img); }

3.7 大图浏览以及保存篇

图 3-9 查看图片

在阅读微博的功能篇中,如果微博包含了图片就会在微博正文下面显示该张图片,但 是这个图片只是张缩略图,这样就需要提供一个能放大缩小查看这张图片的功能,当点击 正文中的缩略图的时候显示一个简单的图片浏览器功能,提供图片的放大、缩小、拖拽操 作方便用户查看图片,同时也提供保存图片到手机的功能。本功能的 UI 比较简单就不单 独分篇讲了,具体的实现效果如上图。 新建 ImageActivity.java 作为图片浏览 Activity,在 res/layout 下新建 image.xml 的 Layout

29

基于 Android 手机操作系统软件开发

作为图片浏览的布局文件,image.xml 布局代码很简单了就不详细解释了直接贴代码。代 码中用到了一个自定义控件 MySinaWeiBo.ui.ImageZoomView, 这个就是整个功能的核心部 分,用来实现图片的放大、缩小、拖拽的一个图片显示控件。 接下要做的就是用这个 ImageZoomView 来显示图片,在阅读微博内容的页面中当点 击 内 容 中 的 缩 略 图 片 的 时 候 会 把 这 个 缩 略 图 对 应 的 原 图 的 url 传 给 当 前 的 这 个 ImageActivity,那么在 ImageActivity 的 onCreate 方法中根据这个 url 获取图片并且设置给 ImageZoomView。在 onCreate 方法中代码。 接下来就是 ZoomControls 的放大缩小事件代码: ZoomControls zoomCtrl = (ZoomControls) findViewById(R.id.zoomCtrl); zoomCtrl.setOnZoomInClickListener(new OnClickListener(){ @Override public void onClick(View view) { float z= mZoomState.getZoom()+0.25f; mZoomState.setZoom(z); mZoomState.notifyObservers(); }

}); zoomCtrl.setOnZoomOutClickListener(new OnClickListener(){

@Override public void onClick(View v) { float z= mZoomState.getZoom()-0.25f; mZoomState.setZoom(z); mZoomState.notifyObservers(); }

}); 这样一个简单的图片浏览器功能就完成了,支持放大缩小并且还能拖拽,基本上达到 应用需求。

30

基于 Android 手机操作系统软件开发





这次毕业设计是通过对 Android 手机操作系统的学习, 自主设计开发新浪微博客户端。 首先,搭建了 Android 系统开发平台。主要步骤包括:1.安装 JDK 和配置 Java 开发环 境;2. Eclipse 的安装与汉化;3. SDK 和 ADT 的安装和配置。并创建了一个 HelloAndroid 项目。 客户端的开发过程主要包括:1.载入页面;2.用户授权页面;3.登陆页面;4.用户首页 面;5.阅读微博;6 大图的浏览和保存;7.OAuth 授权认证。开发过程主要从 UI 和功能两 个方面进行设计和开发。并通过微博服务端 API 的 OAuth 认证使客户端与新浪进行连 接。 通过这次毕业设计,使我对 Android 系统有了深入的了解,掌握其简单的系统架 构,移植开发结构,应用程序开发过程,培养了我对其浓厚的兴趣。同时自主开发的新浪 客户端具有鲜明的个性化。 由于自己知识和时间的限制,在开发过程中还有很多不尽人意的地方。客户端还有 许多细节可以进行美化,功能也有待丰富。在以后的学习和生活中,本人会对 Android 系 统进行更深的学习和研究,争取做出更新颖、更丰富、更实用的软件和工具。

31

基于 Android 手机操作系统软件开发

参考文献
[1] 陈昱,江兰帆.基于 Google Android 平台的应用程序开发和研究[J].福建电脑,2008 (11):156-157. [2] 杨丰盛,Android 应用开发揭秘[M] 第一版.北京:机械工业出版社,2010 年.7 页 [3] 姚昱旻,刘卫国.Android 的架构与应用开发研究[J].计算机系统应用,2008(11):110-1 [4] 姚昱旻,刘卫国.Android 与 J2ME 平台间即时通信的研究与实现[J].计算机系统应 用,2008(12):118-120 [5] 公 磊 , 周 聪 . 基 于 Android 的 移 动 终 端 应 用 程 序 开 发 与 研 究 [J]. 计 算 机 与 现 代 化,2008(8):86-89 [6] 差沙,地狱男爵.用 Android 开发手机应用[J].程序员,2008(1):25-27 [7] 叶达峰.Eclipse 编程技术与实例[M ].北京:人民邮电出版社, 2006 年 [8] 张超,王阿川,王智.基于 J2ME 和 J2EE 的手机软件的研究[J].黑龙江科技信息,2007 (3) : 21,201 [9] 刘向辉.基于 Java 的移动终端中间件的研究与设计[D].华东师范大学硕士学位论文, 2005 年 [10] 刁扣锁.短信息在嵌入式 L inux 系统中的设计与实现[D].东南大学硕士学位论文, 2005

32

基于 Android 手机操作系统软件开发

年 [11] Android 帮助文档





33

基于 Android 手机操作系统软件开发

附录 核心代码
public class DataHelper { //数据库名称 private static String DB_NAME = "mysinaweibo.db"; //数据库版本 private static int DB_VERSION = 2; private SQLiteDatabase db; private SqliteHelper dbHelper; public DataHelper(Context context){ dbHelper=new SqliteHelper(context,DB_NAME, null, DB_VERSION); db= dbHelper.getWritableDatabase(); } public void Close() { db.close(); dbHelper.close(); } //获取 users 表中的 UserID、Access Token、Access Secret 的记录 public List<UserInfo> GetUserList(Boolean isSimple) { List<UserInfo> userList = new ArrayList<UserInfo>(); Cursor cursor=db.query(SqliteHelper.TB_NAME, null, null, null, null, null, UserInfo.ID+ " DESC"); cursor.moveToFirst(); while(!cursor.isAfterLast()&& (cursor.getString(1)!=null)){ UserInfo user=new UserInfo(); user.setId(cursor.getString(0)); user.setUserId(cursor.getString(1)); user.setToken(cursor.getString(2)); user.setTokenSecret(cursor.getString(3)); if(!isSimple){ user.setUserName(cursor.getString(4));

34

基于 Android 手机操作系统软件开发

ByteArrayInputStream stream = new ByteArrayInputStream(cursor.getBlob(5)); Drawable icon= Drawable.createFromStream(stream, "image"); user.setUserIcon(icon); } userList.add(user); cursor.moveToNext(); } cursor.close(); return userList; } //判断 users 表中的是否包含某个 UserID 的记录 public Boolean HaveUserInfo(String UserId) { Boolean b=false; Cursor cursor=db.query(SqliteHelper.TB_NAME, null, UserInfo.USERID + "=" + UserI d, null, null, null,null); b=cursor.moveToFirst(); Log.e("HaveUserInfo",b.toString()); cursor.close(); return b; } //更新 users 表的记录,根据 UserId 更新用户昵称和用户图标 public int UpdateUserInfo(String userName,Bitmap userIcon,String UserId) { ContentValues values = new ContentValues(); values.put(UserInfo.USERNAME, userName); // BLOB 类型 final ByteArrayOutputStream os = new ByteArrayOutputStream(); // 将 Bitmap 压缩成 PNG 编码,质量为 100%存储 userIcon.compress(Bitmap.CompressFormat.PNG, 100, os); // 构造 SQLite 的 Content 对象,这里也可以使用 raw values.put(UserInfo.USERICON, os.toByteArray()); int id= db.update(SqliteHelper.TB_NAME, values, UserInfo.USERID + "=" + UserId, null); Log.e("UpdateUserInfo2",id+""); return id; } //更新 users 表的记录 public int UpdateUserInfo(UserInfo user) { ContentValues values = new ContentValues(); values.put(UserInfo.USERID, user.getUserId());

35

基于 Android 手机操作系统软件开发

values.put(UserInfo.TOKEN, user.getToken()); values.put(UserInfo.TOKENSECRET, user.getTokenSecret()); int id= db.update(SqliteHelper.TB_NAME, values, UserInfo.USERID + "=" + user.getUserI d(), null); Log.e("UpdateUserInfo",id+""); return id; } //添加 users 表的记录 public Long SaveUserInfo(UserInfo user) { ContentValues values = new ContentValues(); values.put(UserInfo.USERID, user.getUserId()); values.put(UserInfo.TOKEN, user.getToken()); values.put(UserInfo.TOKENSECRET, user.getTokenSecret()); Long uid = db.insert(SqliteHelper.TB_NAME, UserInfo.ID, values); Log.e("SaveUserInfo",uid+""); return uid; } //删除 users 表的记录 public int DelUserInfo(String UserId){ int id= db.delete(SqliteHelper.TB_NAME, UserInfo.USERID +"="+UserId, null); Log.e("DelUserInfo",id+""); return id; } } public class OAuth { private CommonsHttpOAuthConsumer httpOauthConsumer; private OAuthProvider httpOauthprovider; public String consumerKey; public String consumerSecret; public OAuth() { // 第一组: (App Key 和 App Secret) // 这组参数就是本系列文本第一篇提到的建一个新的应用获取 App Key 和 App Secret。 this("3315495489","e2731e7grf592c0fd7fea32406f86e1b"); } public OAuth(String consumerKey,String consumerSecret) { this.consumerKey=consumerKey; this.consumerSecret=consumerSecret;

36

基于 Android 手机操作系统软件开发

} public Boolean RequestAccessToken(Activity activity,String callBackUrl){ Boolean ret=false; try{ httpOauthConsumer = new CommonsHttpOAuthConsumer(consumerKey,consumerSecr et); httpOauthprovider = new DefaultOAuthProvider("http://api.t.sina.com.cn/oauth/request_t oken","http://api.t.sina.com.cn/oauth/access_token","http://api.t.sina.com.cn/oauth/authorize"); String authUrl = httpOauthprovider.retrieveRequestToken(httpOauthConsumer, callBack Url); activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl))); ret=true; }catch(Exception e){ } return ret; } public UserInfo GetAccessToken(Intent intent){ UserInfo user=null; Uri uri = intent.getData(); String verifier = uri.getQueryParameter(oauth.signpost.OAuth.OAUTH_VERIFIER); try { httpOauthprovider.setOAuth10a(true); httpOauthprovider.retrieveAccessToken(httpOauthConsumer,verifier); } catch (OAuthMessageSignerException ex) { ex.printStackTrace(); } catch (OAuthNotAuthorizedException ex) { ex.printStackTrace(); } catch (OAuthExpectationFailedException ex) { ex.printStackTrace(); } catch (OAuthCommunicationException ex) { ex.printStackTrace(); } SortedSet<String> user_id= httpOauthprovider.getResponseParameters().get("user_id"); String userId=user_id.first(); String userKey = httpOauthConsumer.getToken(); String userSecret = httpOauthConsumer.getTokenSecret(); user=new UserInfo(); user.setUserId(userId); user.setToken(userKey); user.setTokenSecret(userSecret); return user; }

37

基于 Android 手机操作系统软件开发

public HttpResponse SignRequest(String token,String tokenSecret,String url,List params) { HttpPost post = new HttpPost(url); //HttpClient httpClient = null; try{ post.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } //关闭 Expect:100-Continue 握手 //100-Continue 握手需谨慎使用,因为遇到不支持 HTTP/1.1 协议的服务器或者代理时 会引起问题 post.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINU E, false); return SignRequest(token,tokenSecret,post); } public HttpResponse SignRequest(String token,String tokenSecret,HttpPost post){ httpOauthConsumer = new CommonsHttpOAuthConsumer(consumerKey,consumerSecret); httpOauthConsumer.setTokenWithSecret(token,tokenSecret); HttpResponse response = null; try { httpOauthConsumer.sign(post); } catch (OAuthMessageSignerException e) { e.printStackTrace(); } catch (OAuthExpectationFailedException e) { e.printStackTrace(); } catch (OAuthCommunicationException e) { e.printStackTrace(); } //取得 HTTP response try { response = new DefaultHttpClient().execute(post); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return response; } }

38

基于 Android 手机操作系统软件开发

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/logo_s" android:layout_marginTop="5dip" android:layout_marginLeft="5dip"> </ImageView> <RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent"> <RelativeLayout android:id="@+id/iconBtn" android:layout_width="90px" android:layout_height="80px" android:background="@drawable/icon_selector" android:layout_above="@+id/selectLayout" android:layout_centerHorizontal="true" android:layout_marginBottom="20dip"> <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"> </ImageView> </RelativeLayout> <RelativeLayout android:id="@+id/selectLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"> <EditText android:id="@+id/iconSelect" android:layout_width="200px" android:layout_height="wrap_content" android:maxLength="10" android:paddingLeft="20px"

39

基于 Android 手机操作系统软件开发

android:editable="false" android:enabled="false" android:textSize="13px" android:background="@drawable/input_over" > </EditText> <ImageButton android:id="@+id/iconSelectBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="1.0dip" android:layout_alignTop="@+id/iconSelect" android:layout_alignRight="@+id/iconSelect" android:layout_alignBottom="@+id/iconSelect" android:background="@drawable/more_selector" > </ImageButton> <ImageButton android:id="@+id/login" android:layout_width="40px" android:layout_height="40px" android:layout_marginLeft="5dip" android:layout_alignTop="@+id/iconSelectBtn" android:layout_toRightOf="@+id/iconSelectBtn" android:layout_alignBottom="@+id/iconSelectBtn" android:background="@drawable/btn_in_selector" > </ImageButton> </RelativeLayout> <RelativeLayout android:layout_width="fill_parent" android:layout_height="44dip" android:layout_alignParentBottom="true" android:background="#BB768e95"> <LinearLayout android:id="@+id/addLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_alignParentLeft="true" android:gravity="center" android:layout_marginTop="3px"> <ImageButton android:id="@+id/addIcon" android:layout_width="wrap_content" android:layout_height="wrap_content"

40

基于 Android 手机操作系统软件开发

android:background="@drawable/add_selector"> </ImageButton> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:textSize="12px" android:text="添加账号"> </TextView> </LinearLayout> <LinearLayout android:id="@+id/exitLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_centerInParent="true" android:gravity="center" android:layout_marginTop="3px"> <ImageButton android:id="@+id/exitIcon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/exit_selector"> </ImageButton> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:textSize="12px" android:text="退出软件"> </TextView> </LinearLayout> <LinearLayout android:id="@+id/delLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_alignParentRight="true" android:gravity="center" android:layout_marginTop="3px"> <ImageButton android:id="@+id/delIcon" android:layout_width="wrap_content" android:layout_height="wrap_content"

41

基于 Android 手机操作系统软件开发

android:background="@drawable/del_selector"> </ImageButton> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:textSize="12px" android:text="删除账号"> </TextView> </LinearLayout> </RelativeLayout> </RelativeLayout> </LinearLayout> <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="3px"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/logo_ss"> </ImageView> <TextView android:id="@+id/showName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="#343434" android:textSize="15px"> </TextView> <ImageButton android:id="@+id/writeBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@+id/refreshBtn"

42

基于 Android 手机操作系统软件开发

android:background="@drawable/btn_write_selector"> </ImageButton> <ImageButton android:id="@+id/refreshBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginLeft="12px" android:background="@drawable/btn_refresh_selector"> </ImageButton> </RelativeLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/hr"> </LinearLayout> <RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent"> <ListView android:id="@+id/Msglist" android:layout_width="fill_parent" android:layout_height="match_parent" android:divider="@drawable/divider" android:dividerHeight="2px" android:layout_margin="0px" android:background="#BBFFFFFF" android:cacheColorHint="#00000000" android:layout_above="@+id/toolbarLayout" android:fastScrollEnabled="true" android:focusable="true"> </ListView> <LinearLayout android:id="@+id/loadingLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:visibility="invisible" android:layout_centerInParent="true"> <ProgressBar

43

基于 Android 手机操作系统软件开发

android:id="@+id/loading" android:layout_width="31px" android:layout_height="31px" android:layout_gravity="center" style="@style/progressStyle"> </ProgressBar> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="正在载入" android:textSize="12px" android:textColor="#9c9c9c" android:layout_gravity="center" android:layout_below="@+id/loading"> </TextView> </LinearLayout>

<LinearLayout android:id="@+id/toolbarLayout" android:layout_width="fill_parent" android:layout_height="44dip" android:layout_alignParentBottom="true"> </LinearLayout> </RelativeLayout> </LinearLayout> public class WeiBoInfo { //文章 id private String id; public String getId(){ return id; } public void setId(String id){ this.id=id; } //发布人 id private String userId; public String getUserId(){ return userId; } public void setUserId(String userId){ this.userId=userId; }

44

基于 Android 手机操作系统软件开发

//发布人名字 private String userName; public String getUserName(){ return userName; } public void setUserName(String userName){ this.userName=userName; } //发布人头像 private String userIcon; public String getUserIcon(){ return userIcon; } public void setUserIcon(String userIcon){ this.userIcon=userIcon; } //发布时间 private String time; public String getTime(){ return time; } public void setTime(String time) { this.time=time; } //是否有图片 private Boolean haveImage=false; public Boolean getHaveImage(){ return haveImage; } public void setHaveImage(Boolean haveImage){ this.haveImage=haveImage; } //文章内容 private String text; public String getText(){ return text; } public void setText(String text){ this.text=text;

45

基于 Android 手机操作系统软件开发

} }

46


相关文章:
基于Android考试系统软件开发设计
基于Android考试系统软件开发设计_工学_高等教育_教育专区。关于Android客户端考试...集,它包括一个底层 Linux 操作系统,中间 层的中间件和上层的 java 应用程序。...
基于Android系统电子词典的设计与开发
基于Android系统电子词典的设计与开发_计算机软件及应用_IT/计算机_专业资料。基于...1.绪论在 21 世纪初期,Andy Rubin(安迪·鲁宾)创立了手机操作系统--Android。...
基于Android系统的手机语音识别软件开发
基于Android系统的手机语音识别软件开发 - 基于 Android 系统的手机语音识别软件开发 摘要 随着科学技术和社会经济的发展,移动互联网发展越来越快,这期间出现了 许多...
基于Android的仪器管理系统App设计与实现_图文
基于Android的仪器管理系统App设计与实现 - 开发一款基于Android的实验室仪器管理系统APP,在移动平台实现对实验室仪器共享的管理。
一个基于Android的系统开发
如若在地震发生之前,人们可以通过一种基于 android 的 地震异常信息采集系统软件...可以在任何支持网络通信的 操作系统中实施运行;它是一种新的 Web 应用程序分支...
基于Android平台的开发
系统软件基于 android 平台开发,Android 是一种基于 Linux 的自由 及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由 Google 公司和开放手机...
基于Android平台软件开发技术研究
龙源期刊网 http://www.qikan.com.cn 基于 Android 平台软件开发技术研究 作者...(a)-0021-02 在科技持续发展的浪潮下,移动式操作系统应运而生,移动终端传统...
基于Android系统的手机卫士开发
基于Android系统的手机卫士开发_计算机软件及应用_IT/计算机_专业资料。东北石油...与之同步发展的还有支持手机 运行的手机操作系统 ,从当初的单片机系统到后来的...
android软件开发论文
android软件开发论文_计算机软件及应用_IT/计算机_专业资料。这是一款是关于手机...Android基于 Linux 内核的操作系统, 是 Google 公司在 2007 年 11 月 5 ...
基于Android的原生程序设计与实现
基于Android的原生程序设计与实现_计算机软件及应用_...学生通过这次毕业设计了解针对 Android 系统编程的基本...1. 所完成的软件功能较为丰富,操作方便,UI 设计合理...
更多相关标签: