基于Android平臺(tái)的個(gè)人日歷的設(shè)計(jì)與開發(fā)
基于Android平臺(tái)的個(gè)人日歷的設(shè)計(jì)與開發(fā)
摘要
個(gè)人日歷是基于Android平臺(tái)開發(fā)的,運(yùn)行在Android手機(jī)平臺(tái)的個(gè)人日程管理軟件。本文是對(duì)基于Android平臺(tái)的個(gè)人日歷的設(shè)計(jì)與開發(fā)。
首先,本文介紹了軟件開發(fā)的背景與特點(diǎn)。然后,本文介紹了軟件所使用的關(guān)鍵技術(shù),包括Android、fragment、service、activity。再然后,介紹日歷的設(shè)計(jì)與開發(fā),包括系統(tǒng)需求分析、功能設(shè)計(jì)、框架設(shè)計(jì)、界面設(shè)計(jì)、數(shù)據(jù)層設(shè)計(jì)以及各部分功能的實(shí)現(xiàn)。最后本文對(duì)全文進(jìn)行總結(jié),總結(jié)設(shè)計(jì)實(shí)現(xiàn)過程中遇到的問題、系統(tǒng)的不足、優(yōu)勢與自己的收獲。
關(guān)鍵詞:個(gè)人日歷、Android、日程管理
The designationand development of personal calendar based on the Android platform
Abstract
Personal calendar is a personal schedule management software developed on the Android platform, running on the Android platform. This paper is to design and develop of personal calendar based on the Android platform.
First, this paper introduces the background and characteristics of software development. Then, this paper introduces the key technologies of software use, including Android, fragments, service, activity. Then, introduces the design and development of calendar, including system requirements analysis, functional design, framework design, interface design, the data layer design and the realization of the function of each part. Finally this paper summarizes the full text, summarizes the problems in the implementation process of design, advantages and disadvantages of the system and the deficiency of the harvest of their own.
Keyword: Personal calendar, Android, schedule management
目錄
1.緒論51.1.課題背景51.2.研發(fā)現(xiàn)狀51.3.軟件研究意義51.4.研究內(nèi)容與方法62.相關(guān)技術(shù)與知識(shí)72.1.開發(fā)平臺(tái)Android72.2.MVC開發(fā)模式72.3.局部界面fragment72.4.Web service82.5.Localservice82.7.線程92.8.開發(fā)平臺(tái)介紹93.個(gè)人日歷的設(shè)計(jì)103.1.需求分析103.2.功能設(shè)計(jì)123.3.數(shù)據(jù)層設(shè)計(jì)153.4.界面布局設(shè)計(jì)204.個(gè)人日歷的實(shí)現(xiàn)234.1.數(shù)據(jù)層實(shí)現(xiàn)234.2.界面實(shí)現(xiàn)354.3.Web服務(wù)434.4.本地服務(wù)464.5.日程同步484.6.屏幕旋轉(zhuǎn)后的Activity數(shù)據(jù)保存504.7.Activity向Fragment傳遞數(shù)據(jù)504.8.Fragment之間通信515.總結(jié)535.1.遇到的問題與解決535.2.軟件的優(yōu)勢與不足545.3.本章小結(jié)546.總結(jié)55參考文獻(xiàn)56致謝56
緒論
課題背景
在現(xiàn)代的生活中,人們每天要處理的事務(wù)越來越多。如何有效的管理自己每天的日程安排,已經(jīng)變得越來越重要。[1]尤其在團(tuán)隊(duì)工作中,更需要相互協(xié)調(diào)以提高整體效率。[2] 在生活中中重要事件多半以電話、短信、郵件的方式發(fā)送,
手機(jī)中的通訊錄、短信以及其余重要數(shù)據(jù)的丟失,影響恐怕就難以估量了,由于那意味著會(huì)丟掉一些重要的短信。[3] 因此日程管理軟件,一直深受人們的喜愛 。但是 ,傳統(tǒng)的日歷工具設(shè)計(jì)和功能千篇一律,僅能管理自己的日程。
本軟件可以定時(shí)或?qū)崟r(shí)從后臺(tái)數(shù)據(jù)庫中通過Web Services下載與個(gè)人有關(guān)的日歷信息,并能夠根據(jù)設(shè)定的提醒方式和提醒時(shí)間自動(dòng)提醒用戶注意相關(guān)日程安排。研發(fā)現(xiàn)狀
國內(nèi)外Android軟件現(xiàn)狀
Android平臺(tái)是Google公司推出的基于Linux系統(tǒng)一款移動(dòng)操作平臺(tái)。雖然只推出沒有幾年但發(fā)展迅速,尤其在國外Android更是呼聲很高,占據(jù)了相當(dāng)大的市場份額。中國是最大的消費(fèi)大國,由于3G網(wǎng)絡(luò)的推廣更加推動(dòng)了智能手機(jī)的發(fā)展,這幾年個(gè)打手機(jī)場上都對(duì)Android工程師需求量很大。未來幾年Android發(fā)展會(huì)更為迅猛,它將不再只是個(gè)手機(jī)平臺(tái),他將進(jìn)入平板、電視、車載系統(tǒng)等。日歷軟件發(fā)展現(xiàn)狀
目前許多日歷軟件,他們可以實(shí)現(xiàn)各種各樣的功能,如今日運(yùn)勢、紀(jì)錄日程、黃歷、吉日查詢、法定節(jié)假日查詢、生理周期日歷、星座查詢、生肖查詢、陰陽轉(zhuǎn)換等。外表也更加美觀,各式各樣的更能滿足人們對(duì)日歷軟件的需要。有些還提供各種美觀的小插件,是日歷使用更加方便美觀。不過這些軟件均僅能管理個(gè)人日程,不能獲得其他管理軟件的日程。
軟件研究意義
Android平臺(tái)是Google公司推出的基于Linux系統(tǒng)一款移動(dòng)操作平臺(tái)。該平臺(tái)具有開放性、不受運(yùn)營商束縛、有豐富的硬件選擇、不受限制的開發(fā)和與谷歌應(yīng)用可以無縫結(jié)合等優(yōu)勢,現(xiàn)在已漸成為主流的智能手機(jī)平臺(tái)。鑒于Android平臺(tái)仍是一個(gè)較新的開發(fā)平臺(tái),仍有很大的發(fā)展空間,國內(nèi)外很多運(yùn)營商和軟件公司都急需該平臺(tái)的開發(fā)人員。通過本次畢業(yè)設(shè)計(jì)可以很好的鍛煉學(xué)生實(shí)踐能力,同時(shí)也為學(xué)生就業(yè)創(chuàng)造條件。研究內(nèi)容與方法
研究內(nèi)容
個(gè)人日歷后臺(tái)軟件系統(tǒng)主要實(shí)現(xiàn)用戶個(gè)人日歷和企業(yè)日歷數(shù)據(jù)的存儲(chǔ)、手機(jī)日歷端、PC日歷端與后臺(tái)系統(tǒng)日歷項(xiàng)的同步、OA及項(xiàng)目管理等系統(tǒng)與日歷系統(tǒng)的接口等功能。通過后臺(tái)系統(tǒng),用戶可以隨時(shí)將手機(jī)中的日歷信息保存到后臺(tái)數(shù)據(jù)庫中,也可以隨時(shí)同步后臺(tái)數(shù)據(jù)庫中與自身相關(guān)的日歷信息;OA及項(xiàng)目管理系統(tǒng)中的日程安排也能夠自動(dòng)同步到后臺(tái)系統(tǒng)和手機(jī)端。
手機(jī)日歷客戶端主要實(shí)現(xiàn)企業(yè)日歷信息的月視圖、周視圖、日視圖、日歷列表、新增日歷、節(jié)假日、日歷同步等功能。手機(jī)日歷客戶端軟件可以定時(shí)或?qū)崟r(shí)從后臺(tái)數(shù)據(jù)庫中通過Web Services下載與個(gè)人有關(guān)的日歷信息,并能夠根據(jù)設(shè)定的提醒方式和提醒時(shí)間自動(dòng)提醒用戶注意相關(guān)日程安排。用戶也可以在手機(jī)上新建日程或工作安排,并將其發(fā)送到服務(wù)器端,然后通過后臺(tái)管理軟件自動(dòng)同步到相關(guān)人員的手機(jī)上,實(shí)現(xiàn)工作安排的自動(dòng)通知和自動(dòng)提醒。研究方法
本系統(tǒng)用軟件工程化思想和方法開發(fā)軟件,對(duì)軟件進(jìn)行了軟件計(jì)劃、需求分析、設(shè)計(jì)和實(shí)現(xiàn)。
需求分析
根據(jù)實(shí)際情況獲得需求信息并進(jìn)行總結(jié),提出軟件的功能。軟件設(shè)計(jì)
根據(jù)需求分析進(jìn)行框架設(shè)計(jì)、界面設(shè)計(jì)、數(shù)據(jù)庫設(shè)計(jì)。軟件實(shí)現(xiàn)
根據(jù)設(shè)計(jì)文檔實(shí)現(xiàn)軟件。
相關(guān)技術(shù)與知識(shí)
開發(fā)平臺(tái)Android
Android是一個(gè)基于Linux的操作系統(tǒng)。自推出以來Android平臺(tái)迅猛發(fā)展,占據(jù)了巨大的市場份額,而且發(fā)展速度越來越快。目前Android手機(jī)銷量約占全球三分之一,成為世界上最大的Android手機(jī)市場。
Android的開發(fā)語言是Java。從全球來看從事Java編程的人數(shù)一直占據(jù)著第一的位置。而iPhone應(yīng)用的開發(fā)語言是Object C,從事Object C編程的人才剛剛步入前十。并且Android上手容易,經(jīng)過幾個(gè)月的培訓(xùn)即可掌握安卓的開發(fā)技巧,并且安卓手機(jī)較為便宜,平臺(tái)免費(fèi)。
在中國Android擁有很好的學(xué)習(xí)環(huán)境和許多開發(fā)社區(qū),其中一些驚顫舉辦安卓開發(fā)者活動(dòng),一起交流技術(shù)和經(jīng)驗(yàn),并且免費(fèi)發(fā)放學(xué)習(xí)資料更課題了解到做什么養(yǎng)的安卓應(yīng)用可以賺錢,是開發(fā)者不在迷茫。。MVC開發(fā)模式
Android應(yīng)用是基于模型控制器視圖(Model-View-Controller,簡稱MVC)的架構(gòu)模式進(jìn)行設(shè)計(jì)的。 在MVC設(shè)計(jì)模式中,應(yīng)用的任何對(duì)象歸根結(jié)底都是模型對(duì)象、視圖對(duì)象以及控制對(duì)象中的一種。
模型對(duì)象存儲(chǔ)著應(yīng)用的數(shù)據(jù)和業(yè)務(wù)邏輯。模型類通常被用來映射與應(yīng)用相關(guān)的一些事物。模型對(duì)象不關(guān)心用戶界面,它存在的唯一目的就是存儲(chǔ)和管理應(yīng)用數(shù)據(jù)。
視圖對(duì)象需要知道如何繪制界面、如何處理用戶和界面的互動(dòng)。以往的經(jīng)驗(yàn)法則表明,只要是屏幕上可以看得的就是視圖對(duì)象。
控制對(duì)象包含了應(yīng)用的邏輯單元,是聯(lián)系視圖與模型對(duì)象的紐帶。控制對(duì)象被設(shè)計(jì)用來響應(yīng)由視圖對(duì)象觸發(fā)的各類事件,此外還用來管理模型對(duì)象與視圖層間的數(shù)據(jù)流動(dòng)。
局部界面fragment
自從Android3.0引入fragment概念之后,fragment被解釋為碎片或者片段。一個(gè)fragment是用戶界面的一個(gè)區(qū)域,可以再一個(gè)Activity中使用多個(gè)fragment來組合成一個(gè)多面板界面,也可以在不同的Activity中利用同一個(gè)fragment??梢园裦ragment理解為一個(gè)模塊化部分,他有自己的生命周期、可以獨(dú)立的接受用戶的操作,并可以在Activity運(yùn)行過程中添加或刪除一個(gè)fragment。
管理用戶界面的fragment又稱為UI fragment。它也可以自己產(chǎn)生布局文件。 fragment視圖包含了用戶會(huì)用到的一些的可視化UI元素。Web service
Web service是一個(gè)平臺(tái)獨(dú)立的,低耦合的,自包含的、基于可編程的web的應(yīng)用程序,可使用開放的XML標(biāo)準(zhǔn)來描述、發(fā)布、發(fā)現(xiàn)、協(xié)調(diào)和配置這些應(yīng)用程序,用于開發(fā)分布式操作的應(yīng)用程序。[1]
Web Service技術(shù), 能使得運(yùn)行在不同平臺(tái)上的不同應(yīng)用不用借助第三方軟件或硬件就可相互交換數(shù)據(jù)。更具Web Service規(guī)范發(fā)布的應(yīng)用之間, 不管他們是用什么語言開發(fā)的、運(yùn)行在什么平臺(tái)上的都能相互交換數(shù)據(jù)。Web Service減少了應(yīng)用接口的花費(fèi)。Localservice
Service是安卓四大組件之一,它是可以長時(shí)間在后臺(tái)運(yùn)行并且需要提供用戶接口的應(yīng)用組件。在啟動(dòng)一個(gè)應(yīng)用的服務(wù)后即使在啟動(dòng)其他的應(yīng)用之前的服務(wù)依舊會(huì)運(yùn)行。并且其他非service組件也可以與service綁定并進(jìn)行交互,甚至允許多線程交互。本地服務(wù)不是獨(dú)立的進(jìn)程,它依附在主進(jìn)程上這樣可以節(jié)省資源。
Service有兩種形式:
啟動(dòng)形式:通過調(diào)用startService()方法啟動(dòng)服務(wù),通過這種方式啟動(dòng)的service即使啟動(dòng)它的Activity已經(jīng)被銷毀它也會(huì)一直在后臺(tái)運(yùn)行。但是它只能執(zhí)行單一的操作不能返回結(jié)果給調(diào)用者。通過調(diào)用stopService()來停止服務(wù)。
綁定形式:通過調(diào)用bindService()方法啟動(dòng)服務(wù),通過這種方式啟動(dòng)的服務(wù)會(huì)為它所綁定的組件一個(gè)交互接口,通過這個(gè)接口應(yīng)用組件可以與service交互、請(qǐng)求結(jié)果、甚至跨進(jìn)程通信。但是當(dāng)組件被銷毀后service也就銷毀了。通過調(diào)用unbindService()停止服務(wù)。SQLite數(shù)據(jù)庫
SQlite是一種輕量級(jí)的、功能強(qiáng)大關(guān)系數(shù)據(jù)庫,它用于完成實(shí)現(xiàn)結(jié)構(gòu)化的數(shù)據(jù)存儲(chǔ)和各種復(fù)雜的數(shù)據(jù)處理。
SQlite數(shù)據(jù)庫支持多數(shù)的SQL92標(biāo)準(zhǔn),最大支持?jǐn)?shù)據(jù)到2TB。他沒有服務(wù)進(jìn)程,但是它所包含的數(shù)據(jù)庫、表等所有數(shù)據(jù)已經(jīng)被放入Android系統(tǒng)平臺(tái)的底層庫文件,因此我們可以直接通過相關(guān)的API來調(diào)用,從而實(shí)現(xiàn)數(shù)據(jù)庫的各種功能。線程
線程是進(jìn)程內(nèi)部執(zhí)行代碼的實(shí)體,他是CPU調(diào)度資源的最小單元,他沒有自己獨(dú)立的資源,他只有自己的執(zhí)行堆棧和局部變量,所以線程不能獨(dú)立執(zhí)行不許依附在一個(gè)進(jìn)程上。
Thread:重寫其run()方法,在其中實(shí)現(xiàn)我們需要線程所要完成的任務(wù)。在Activity中實(shí)例化并通過start()運(yùn)行線程。在線程運(yùn)行過程中如果需要更新UI可通過handler發(fā)消息給主線程。
AsyncTask:他是一種簡單實(shí)現(xiàn)后臺(tái)運(yùn)行事物的方式。他的任務(wù)在UI縣城之外運(yùn)行,而回調(diào)方法是在UI線程中執(zhí)行,這樣就可以有效的避免了使用Handler所帶來的麻煩。AsyncTask是一個(gè)抽象類,要使用它必須繼承這個(gè)類并重寫其中的方法。開發(fā)平臺(tái)介紹
開發(fā)工具
Eclipse,adt,Visual Studio2010,SQL Server 2008開發(fā)語言
Java,C#測試平臺(tái)
Android手機(jī),Win7
個(gè)人日歷的設(shè)計(jì)
需求分析
對(duì)功能的規(guī)定

本軟件要求將辦公自動(dòng)化平臺(tái)(OA)系統(tǒng)中涉及日程的項(xiàng)目推送到手機(jī)終端軟件中。其基本的數(shù)據(jù)相關(guān)流程如圖3-1-1所示。
圖 3-1-1 日歷系統(tǒng)結(jié)構(gòu)圖
其中“手機(jī)日歷”模塊完成在手機(jī)終端(Android平臺(tái))中的顯示日歷、新建日歷等功能,并提供手動(dòng)/定時(shí)與中心數(shù)據(jù)庫同步日歷的功能。
中心數(shù)據(jù)庫模塊完成從OA系統(tǒng)、項(xiàng)目管理系統(tǒng)中抽取與日期相關(guān)的日程項(xiàng),并整理為標(biāo)準(zhǔn)的日歷格式后向手機(jī)端推送日歷,要求使用Web服務(wù)的形式提供接口。
對(duì)性能的規(guī)定
精度
時(shí)間戳精確到1毫秒;
周視圖、日視圖日程項(xiàng)的時(shí)間精度為15分鐘。
提前提醒的時(shí)間精度為1分鐘,即不支持小于1分鐘的時(shí)間提醒;
時(shí)間特性要求
手機(jī)向中心服務(wù)器讀寫數(shù)據(jù)網(wǎng)絡(luò)超時(shí)響應(yīng)時(shí)間:10秒,若超過10秒沒有取回?cái)?shù)據(jù)則退出;
手機(jī)端本地?cái)?shù)據(jù)庫查詢超時(shí):3秒;
面之間切換延時(shí):不超過2秒;
靈活性
本軟件系統(tǒng)前臺(tái)手機(jī)端與后臺(tái)服務(wù)器端采用Web服務(wù)方式通信,可以減少防火墻的配置工作以及具有良好的可擴(kuò)充性。
手機(jī)端軟件與后臺(tái)系統(tǒng)之間通過Web Services進(jìn)行通信,只要接口信息不發(fā)生改變,手機(jī)端界面和功能的變化不影響后臺(tái)系統(tǒng)的開發(fā)和使用。輸入輸出要求
后臺(tái)服務(wù)器端提供的Web服務(wù)的參數(shù)類型包括字符串和整型兩類,結(jié)果以自定義類對(duì)象列表的形式返回。數(shù)據(jù)管理能力要求
中心數(shù)據(jù)庫采用SQL Server2008數(shù)據(jù)庫,有很強(qiáng)的數(shù)據(jù)存儲(chǔ)和管理能力,完全能夠勝任個(gè)人日歷系統(tǒng)的數(shù)據(jù)要求。另外,Web服務(wù)發(fā)布在IIS上,其并發(fā)訪問由IIS負(fù)責(zé),多人同時(shí)進(jìn)行同步不存在問題。故障處理要求
本系統(tǒng)可能在下列情況下出現(xiàn)故障,待相關(guān)問題解決后,本系統(tǒng)能夠重新正常運(yùn)行:
用戶手機(jī)不能正常聯(lián)網(wǎng)時(shí),會(huì)影響到日歷信息上傳和同步的實(shí)時(shí)性;
安裝中心數(shù)據(jù)庫的計(jì)算機(jī)出現(xiàn)故障或網(wǎng)絡(luò)連接不暢時(shí),會(huì)影響系統(tǒng)的穩(wěn)定運(yùn)行;
運(yùn)行環(huán)境規(guī)定
設(shè)備
設(shè)備需求情況將分別從前臺(tái)手機(jī)端和后臺(tái)服務(wù)端說明:
Android設(shè)備運(yùn)行要求:
支持Android2.2平臺(tái)及以上,運(yùn)行內(nèi)存大于512M,系統(tǒng)存儲(chǔ)空間大于128M(用于存數(shù)據(jù)庫),屏幕分辨率大于800*400,具備聯(lián)網(wǎng)功能的手機(jī)。服務(wù)器運(yùn)行要求:
需要一臺(tái)性能較好的服務(wù)器(操作系統(tǒng)Windows 2003 Server,內(nèi)存4G、硬盤512G、雙網(wǎng)卡),安裝數(shù)據(jù)庫服務(wù)器和IIS服務(wù)器,其上運(yùn)行后臺(tái)同步程序和Web服務(wù)。
支持軟件
服務(wù)器端開發(fā)所用到的支持軟件包括:
Windows 2003 Server
Microsoft SQL Server2008
功能設(shè)計(jì)
總體框架設(shè)計(jì)
個(gè)人日歷系統(tǒng)包含手機(jī)端(Android)和服務(wù)器端兩部分組成。
系統(tǒng)的總體結(jié)構(gòu)圖如下圖所示:
信息系統(tǒng)的內(nèi)網(wǎng)通過SOA應(yīng)用服務(wù)器的80端口連接到InterNet網(wǎng),再通過無線加密通信將信息送到Android手機(jī)上。
SOA是一種面向服務(wù)的軟件架構(gòu),是當(dāng)前先進(jìn)的軟件結(jié)構(gòu)。SOA對(duì)外以80為服務(wù)端口,易于配置防火墻。SOA架構(gòu)借用現(xiàn)有的HTTP應(yīng)用服務(wù)器的并發(fā)控制,可靠、安全。
用一覽表及框圖的形式說明本系統(tǒng)的系統(tǒng)元素(各層模塊、子程序、公用程序等)的劃分,扼要說明每個(gè)系統(tǒng)元素的標(biāo)識(shí)符和功能,分層次地給出各元素之間的控制與被控制關(guān)系.
Android端手機(jī)軟件的程序結(jié)構(gòu)圖為:
Android程序由手機(jī)界面顯示程序、手機(jī)服務(wù)程序兩部分組成。手機(jī)主程序完成主日歷視圖、新建日程視圖、日程查看視圖、假期查看視圖;手機(jī)后臺(tái)服務(wù)程序則完成狀態(tài)欄提醒、桌面插件更新、后臺(tái)數(shù)據(jù)更新等功能。
手機(jī)主視圖界面由月視圖、周視圖、日視圖、三個(gè)視圖組成。這三個(gè)視圖共享一個(gè)Android Activity,當(dāng)用戶切換視圖時(shí)動(dòng)態(tài)生成視圖單元格。
日歷信息獲取過程:
分析現(xiàn)有的信息服務(wù)系統(tǒng),找到工作項(xiàng)子系統(tǒng);
分析工作項(xiàng)子系統(tǒng)的數(shù)據(jù)庫,設(shè)計(jì)查詢?nèi)諝v項(xiàng)的存儲(chǔ)過程(SQL編寫);
將存儲(chǔ)過程映射為WebService(C#或者Java編寫);
將Web服務(wù)部署在應(yīng)用服務(wù)器上(IIS或者Tomcat);
移動(dòng)設(shè)備通過Web服務(wù)讀寫日歷信息。

功能列表
導(dǎo)航欄設(shè)計(jì)
導(dǎo)航欄由8個(gè)圓形按鈕構(gòu)成,他們的功能分別為查看月視圖、查看周視圖、查看日視圖、將日期跳到今天、查看假期、添加日程、同步日程。月視圖設(shè)計(jì)
該視圖在整個(gè)屏幕上提供整月的信息查看,并且可左右滑動(dòng)顯示上一月和下一月的日期信息,該視圖的最小操作單位為天,字體隨手機(jī)分辨率自動(dòng)設(shè)定。
月視圖分為三部分:頭部日期標(biāo)識(shí)、月主視圖、日程列表。
頭部日期標(biāo)識(shí)分為兩部分:日期顯示、農(nóng)歷陽歷轉(zhuǎn)換
月主視圖:上方為周一至周日導(dǎo)航;下方顯示一個(gè)月的日單元格,日單元格可以顯示公歷和可選顯示農(nóng)歷,單元格有日程項(xiàng)則顯示一個(gè)標(biāo)記,單擊日單元格顯示當(dāng)日日程項(xiàng),雙擊或者長按日單元格可以在當(dāng)日新建一個(gè)日程項(xiàng)。用戶可以根據(jù)日單元格的不同來判斷是否為今天(有圓圈)、假期(藍(lán)色)、所選中的日期(綠色)、是否有日程安排(右上方紅色三角)、非本月(灰色)。
日程列表:顯示所點(diǎn)擊日期的日程信息(主題、時(shí)間、地點(diǎn)、是否完成),并支持上下滑動(dòng)查看日程,點(diǎn)擊可產(chǎn)看詳細(xì)信息。周視圖設(shè)計(jì)
該視圖提供整周日程的查看功能,并且可左右滑動(dòng)顯示上一周和下一周的日期信息,字體隨手機(jī)分辨率自動(dòng)設(shè)定。
周視圖分為兩部分頭部日期標(biāo)識(shí)、周主視圖。
頭部日期標(biāo)識(shí)分為兩部分:日期顯示、農(nóng)歷陽歷轉(zhuǎn)換
周主視圖:上方為周一到周日導(dǎo)航,點(diǎn)擊可跳轉(zhuǎn)到顯示那天的日視圖;下方顯示一周七天、每天24小時(shí)的日程信息和當(dāng)日的全天日程。單擊小時(shí)單元格可查看當(dāng)時(shí)日程,雙擊或者長按小時(shí)單元格可新建一個(gè)日程項(xiàng)。日視圖設(shè)計(jì)
該視圖提供一天的日程查看功能,并且可左右滑動(dòng)顯示上一周和下一周的日期信息,字體隨手機(jī)分辨率自動(dòng)設(shè)定。
日視圖分為兩部分:日期標(biāo)識(shí)、日主視圖。
頭部日期標(biāo)識(shí)分為兩部分:日期顯示、農(nóng)歷陽歷轉(zhuǎn)換
日主視圖:顯示一天的全天任務(wù)、每天24小時(shí)的日程信息,單擊小時(shí)單元格可查看當(dāng)時(shí)日程,雙擊或者長按小時(shí)單元格可新建一個(gè)日程項(xiàng)。不同緊急程度的任務(wù)使用不同的背景顏色。日程項(xiàng)顯示主題、地點(diǎn)。每小時(shí)的任務(wù)太多,單元格太小、則盡量顯示更多的文字。列表視圖設(shè)計(jì)
列表視圖提供從今天開始的100條日歷,支持上下滑動(dòng)查看前后的日程項(xiàng)。日程項(xiàng)之間使用日歷時(shí)間欄區(qū)分,日歷時(shí)間欄要求顯示年月日和星期。默認(rèn)顯示從今天開始的100個(gè)日程,并提供主題關(guān)鍵字檢索功能。點(diǎn)擊一個(gè)日程項(xiàng)可產(chǎn)看詳細(xì)信息。新建、查看、修改、刪除日程
可以新建一個(gè)日程;查看一個(gè)日程的詳細(xì)信息,修改或者刪除日程。假期
可查看從今天開始的一年的假期。同步功能
可通過web srvice同步日程新到本地?cái)?shù)據(jù)庫。分為手動(dòng)同步和自動(dòng)同步兩種。菜單
設(shè)置:可以設(shè)置Web服務(wù)地址、同步數(shù)據(jù)的頻率、網(wǎng)絡(luò)超時(shí)時(shí)間。個(gè)人的姓名和編號(hào)的注冊(cè)和注銷。
退出:退出程序。
桌面插件
該視圖提供一個(gè)桌面查看,便于用戶快捷查看今天開始的10條日程,點(diǎn)擊后可進(jìn)入本軟件主程序。功能銜接
打開本軟件主程序顯示月視圖,點(diǎn)擊導(dǎo)航欄的“月”按鈕可由其他視圖跳轉(zhuǎn)回月視圖;點(diǎn)擊導(dǎo)航欄“周”按鈕可跳轉(zhuǎn)到周視圖;點(diǎn)擊周視圖的星期導(dǎo)航可跳轉(zhuǎn)到日視圖,點(diǎn)擊導(dǎo)航欄“日”按鈕可跳轉(zhuǎn)到日視圖。
點(diǎn)擊導(dǎo)航欄“+”按鈕可添加日程,長按或雙擊月視圖的日單元格、周視圖和日視圖的小時(shí)單元格可添加日程。
點(diǎn)擊導(dǎo)航欄“三”按鈕,可進(jìn)入列表視圖,查看今天開始的日程。
點(diǎn)擊月視圖的日程列表和列表視圖的日程項(xiàng)可進(jìn)入查看日程詳細(xì)信息界面,在查看頁面可點(diǎn)擊“刪除”按鈕刪除個(gè)人日歷信息,點(diǎn)擊“修改”按鈕修改日程信息。
按菜單鍵彈出菜單。
數(shù)據(jù)層設(shè)計(jì)
數(shù)據(jù)庫設(shè)計(jì)
手機(jī)端sqilite數(shù)據(jù)庫:
本系統(tǒng)中,設(shè)計(jì)了表:


后臺(tái)服務(wù)數(shù)據(jù)庫的結(jié)構(gòu):
本系統(tǒng)中,設(shè)計(jì)了表:Table_UserManager(人員表)、Table_CalendarManage (日歷表) 、Table_User_CalendarRelation (人員、日歷關(guān)系表)來存儲(chǔ)日歷系統(tǒng)中涉及到的相關(guān)人員、日歷項(xiàng)及日歷項(xiàng)涉及到的人員等信息。各表的結(jié)構(gòu)定義分別如下:

注:表Table_CalendarManage和表Table_User_CalendarRelation之間通過字段CalendarId來關(guān)聯(lián),是一對(duì)多的關(guān)系。生成日歷時(shí),先在日歷表Table_CalendarManage中插入日歷信息記錄,然后再在表Table_User_CalendarRelation中生成人員的關(guān)聯(lián)信息。刪除日歷時(shí),先從表Table_User_CalendarRelation中刪除有關(guān)記錄,當(dāng)不存在與CanlendarId關(guān)聯(lián)的人員信息時(shí),將日歷記錄從Table_CalendarManage中刪除。
數(shù)據(jù)緩沖
月視圖的每個(gè)單元格類中都有一個(gè)ArrayList用于保存當(dāng)天的CalendarItem(日程信息),這樣打開月視圖就把整個(gè)月的日程信息緩沖到了內(nèi)存中。模型層新增一個(gè)CalendarItemLab對(duì)象,該對(duì)象是一個(gè)數(shù)據(jù)緩沖池用來存儲(chǔ)CalendarItem。點(diǎn)擊日單元格時(shí)將ArrayList賦值給CalendarItemLab的ArrayList,之后對(duì)CalendarItem的查看均使用CalendarItemLab。個(gè)人日歷的實(shí)現(xiàn)
數(shù)據(jù)層實(shí)現(xiàn)
數(shù)據(jù)庫實(shí)現(xiàn)
手機(jī)端數(shù)據(jù)庫:
Android使用ORMLite操作數(shù)據(jù)庫
使用ormlite-android-4.41.jar和ormlite-core-4.41.jar兩個(gè)jar包,將這兩個(gè)包導(dǎo)入到Lib文件夾中。
存儲(chǔ)的數(shù)據(jù)對(duì)象實(shí)體。
代碼如下:
UpdateHistory 類
@DatabaseTable
public class UpdateHistory implements Serializable {
/**
* UID
*/
private static final long serialVersionUID = 5273337865132837182L;/**
* SqlLite自增ID
*/
@DatabaseField(generatedId = true)
Integer id = 0;
/**
* 最后同步時(shí)間
*/
@DatabaseField
String updateID = "";
/**
* 最后同步時(shí)間
*/
@DatabaseField
String AlterTime = "2000/01/01 00:00:00";
/**
* 界面點(diǎn)擊的日程項(xiàng) ID值
*/
@DatabaseField
String Click_CI_ID = "";
//一系列的get set方法
//省略
}
CalendarItem類
/**
* 日歷系統(tǒng)中的 日程項(xiàng) 基礎(chǔ)類,包含了日程項(xiàng)所有的數(shù)據(jù)信息和數(shù)據(jù)庫結(jié)構(gòu),以后可以新增日程項(xiàng)的查詢、匹配等功能
* @author GW
*/
@DatabaseTable
public class CalendarItem implements Serializable {
/**
* UID
*/
private static final long serialVersionUID = -7368152766202427185L;
}
/**
* SqlLite 自建ID
*/
@DatabaseField(generatedId = true)
Integer id = 0;
/**
* 遠(yuǎn)程數(shù)據(jù)庫中心,日歷ID,主鍵
*/
@DatabaseField(index = true)
String CalendarId = "";
/**
* 主題
*/
@DatabaseField
String Topic = "";
/**
* 起始時(shí)間
*/
@DatabaseField(index = true)
String StartTime = "";
/**
* 結(jié)束時(shí)間
*/
@DatabaseField(index = true)
String EndTime = "";
//按照設(shè)計(jì)的數(shù)據(jù)庫表寫,并注釋(此處部分省略)
//一系列的set get 方法 省略
}
ColorConfig 類
@DatabaseTable
public class ColorConfig implements Serializable{
/**
* UID
*/
private static final long serialVersionUID = 8216762882467739109L;
/**
* 本地?cái)?shù)據(jù)庫主索引ID
*/
@DatabaseField(generatedId = true)
Integer id = 0;
/**
* 是否正在使用該配置
*/
@DatabaseField
Integer isUse = 1;
@DatabaseField
public String userID = "";
@DatabaseField
public String userName = "";
//按照設(shè)計(jì)的數(shù)據(jù)庫表寫,并注釋(此處部分省略)
//一系列的set get 方法 省略
}
注:@DatabaseTable 指定類對(duì)應(yīng)的表名,@DatabaseField 對(duì)應(yīng)的字段名,
字段名注釋方法
cloumnName:指定字段名,不指定則變量名作為字段名
canBeNull:是否可以為null
dataType:指定字段的類型
defaultValue:指定默認(rèn)值
width:指定長度
id:指定字段為id
generatedId:指定字段為自增長的id,不能id,generatedIdSequence通用
foreign 指定這個(gè)字段的對(duì)象是一個(gè)外鍵,外鍵值是這個(gè)對(duì)象的id
useGetSet:指定ormlite訪問變量使用set,get方法默認(rèn)使用的是反射機(jī)制直接訪問變量
throwIfNull,如果空值拋出異常
persisted:指定是否持久化此變量,默認(rèn)true
unique:字段值唯一
uniqueCombo整列的值唯一
index:索引
uniqueIndex 唯一索引
foreignAutoRefresh 外鍵值,自動(dòng)刷新
foreignAutoCreate 外鍵不存在時(shí)是否自動(dòng)添加到外間表中需要數(shù)據(jù)DatabaseHelper類,來創(chuàng)建及管理數(shù)據(jù)庫。 DatabaseHelper類繼承OrmLiteSqliteOpenHelper,并在覆蓋實(shí)現(xiàn)onCreate, onUpgrade, close等方法。創(chuàng)建刪除數(shù)據(jù)庫應(yīng)該使用TableUtils工具類的方法.。
構(gòu)造數(shù)據(jù)訪問接口Dao類。
代碼如下:
public class DatabaseHelper extends
com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper {
//數(shù)據(jù)庫名字
private static final String DATABASE_NAME = "KD.db";
/**
* 當(dāng)數(shù)據(jù)庫表結(jié)構(gòu)修改時(shí),增加該數(shù)值即可。
* 數(shù)據(jù)庫版本號(hào)
*/
private static final int DATABASE_VERSION = 47;
private Dao<CalendarItem, Integer> calItemDao;
private Dao<ColorConfig, Integer> configDao;
private Dao <UpdateHistory, Integer> updateDao;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION,
R.raw.ormlite_config);
}
//創(chuàng)建數(shù)據(jù)庫時(shí)調(diào)用 onCreats方法
@Override
public void onCreate(SQLiteDatabase arg0, ConnectionSource arg1) {
// TODO Auto-generated method stub
try {
TableUtils.createTable(connectionSource, CalendarItem.class);
TableUtils.createTable(connectionSource, ColorConfig.class);
TableUtils.createTable(connectionSource, UpdateHistory.class);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Unable to create datbases",e);
}
}
//數(shù)據(jù)庫版本號(hào)變化時(shí)調(diào)用 onUpgrade 方法
@Override
public void onUpgrade(SQLiteDatabase sqliteDatabase,
ConnectionSource connectionSource, int oldVer, int newVer) {
// TODO Auto-generated method stub
try {
TableUtils.dropTable(connectionSource, CalendarItem.class, true);
TableUtils.dropTable(connectionSource, ColorConfig.class, true);
TableUtils.dropTable(connectionSource, UpdateHistory.class, true);
onCreate(sqliteDatabase, connectionSource);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(),
"Unable to upgrade database from version " + oldVer+ " to new " + newVer, e);
}
}
/**
* 獲取用戶信息接口DAO
* @return
* @throws SQLException
*/
public Dao<User, Integer> getUserDao() throws SQLException {
if (userDao == null) {
userDao = getDao(User.class);
}
return userDao;
}
/**
* 獲取 日程項(xiàng) 信息接口DAO
* @return
* @throws SQLException
*/
public Dao<CalendarItem, Integer> getCalItemDao() throws SQLException {
if (calItemDao == null) {
calItemDao = getDao(CalendarItem.class);
}
return calItemDao;
}
/**
* 獲取 配置項(xiàng) 的Dao
* @return
* @throws SQLException
*/
public Dao<ColorConfig, Integer> getConfigDao() throws SQLException {
if (configDao == null) {
configDao = getDao(ColorConfig.class);
}
return configDao;
}
/**
* 返回最后更新的時(shí)間
* @return
* @throws SQLException
*/
public Dao<UpdateHistory, Integer> getUpdateHistoryDao() throws SQLException {
if (updateDao == null) {
updateDao = getDao(UpdateHistory.class);
}
return updateDao;
}
}構(gòu)造數(shù)據(jù)庫操作類DbAdapter。在構(gòu)造函數(shù)中先使用getHelper()獲得數(shù)據(jù)庫DatabaseHelper,然后使用getDao()獲得數(shù)據(jù)操作接口。在析構(gòu)函數(shù)通過releseHelper()釋放數(shù)據(jù)庫,再通過Dao類的方法操作數(shù)據(jù)。這樣就可以使用DbAdapter的方法操作數(shù)據(jù),更加方便快捷。
代碼如下:
/**
* 管理底層的數(shù)據(jù)服務(wù),比如從數(shù)據(jù)庫刷新、寫回?cái)?shù)據(jù)庫數(shù)據(jù)等
* @author GW
*/
public class DbAdapter {
private DatabaseHelper databaseHelper = null;
Context parent;
/**
* 構(gòu)造函數(shù)
* @param context
*/
public DbAdapter(Context context) {
this.parent = context;
calItemList.clear();
databaseHelper = getHelper();
if (databaseHelper != null) {
try {
calItemDao = databaseHelper.getCalItemDao();
configDao = databaseHelper.getConfigDao();
updateHistoryDao = databaseHelper.getUpdateHistoryDao();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 析構(gòu)函數(shù)
*/
@Override
protected void finalize() {
releseHelper();
}
/**
* 獲取默認(rèn)的配置信息
*?@return
*/
public?ColorConfig getUsingConfig() {
try?{
List<ColorConfig> config_list;
config_list = configDao.queryForEq("isUse", 1);
if?(config_list.size() > 0) {
config = config_list.get(0);
}?else?{
config =?new?ColorConfig();
newOrUpdateColorConfig(config);
}
}?catch?(SQLException e) {
//?TODO?Auto-generated catch block
e.printStackTrace();
}
return?config;
}
public?UpdateHistory getLastUpdateTime() {
try?{
List<UpdateHistory> update_list;
update_list = updateHistoryDao.queryForEq("updateID", "888");
if?(update_list.size() > 0) {
updateHistory = update_list.get(0);
}?else?{
updateHistory =?new?UpdateHistory();
updateHistory.updateID = "888";
newOrUpdateLastUpdateTime(updateHistory);
}
}?catch?(SQLException e) {
//?TODO?Auto-generated catch block
e.printStackTrace();
}
return?updateHistory;
}
}
Dao<T,V>
包含兩個(gè)泛型,第一個(gè)泛型表DAO操作的類,第二個(gè)表示操作類的主鍵類型
主要方法:create:插入一條數(shù)據(jù)
createIfNotExists:如果不存在則插入
createOrUpdate:如果指定id則更新
queryForId:根據(jù)id查找
update 查找出數(shù)據(jù)
delte 刪除數(shù)據(jù)
queryBuilder() 創(chuàng)建一個(gè)查詢生成器:進(jìn)行復(fù)雜查詢
deleteBuilder() 創(chuàng)建一個(gè)刪除生成器,進(jìn)程復(fù)雜條件刪除
updateBuilder() 創(chuàng)建修條件生成器,進(jìn)行復(fù)雜條件修改
服務(wù)端數(shù)據(jù)庫:
使用SQL server2008圖形界面方式建立數(shù)據(jù)庫
進(jìn)入SQL server2008,右鍵“數(shù)據(jù)庫”選擇“新建數(shù)據(jù)庫”輸入輸入數(shù)據(jù)庫名然后點(diǎn)“確定”。再右鍵“表”選擇“新建表”。然后輸入每個(gè)屬性的列名、數(shù)據(jù)類型、是否允許為空等。

表dbo.Table_CalendarManage 設(shè)計(jì)如下

表 dbo.Table_IMEI設(shè)計(jì)如下
表 dbo.Table_User_CalendarRelation設(shè)計(jì)如下


表dbo.Table_UserManage設(shè)計(jì)如下
數(shù)據(jù)緩沖池
程序運(yùn)行中將CalendarItem信息緩存到CalendarItemLab中,在應(yīng)用中, CalendarItem數(shù)組對(duì)象將存儲(chǔ)在一個(gè)單例里。 單例是特殊的java類,在創(chuàng)建
實(shí)例時(shí),一個(gè)類僅允許創(chuàng)建一個(gè)實(shí)例。應(yīng)用能夠在內(nèi)存里存在多久,單例就能存在多久,因此將對(duì)象列表保存在單例里可保持CalendarItem數(shù)據(jù)的一直存在,不管activity、 fragment及它們的生命周期發(fā)生什么變化。
要?jiǎng)?chuàng)建單例,需創(chuàng)建一個(gè)帶有私有構(gòu)造方法及get()方法的類,其中g(shù)et()方法返回實(shí)例、setCalendarItems(ArrayList<CalendarItem>)方法可以設(shè)置單例的數(shù)據(jù)、getCalendarItem(String CalendarId)和deleteCalendarItem(String CalendarId)可以得到和刪除CalendarItem數(shù)組對(duì)象中的一個(gè)CalendarItem。
代碼如下:
public class CalendarItemLab {
private ArrayList<CalendarItem> mCalendarItems;
private static CalendarItemLab sCalendarItemLab;
private Context mAppContext;
private CalendarItemLab(Context appContext){
mAppContext = appContext;
mCalendarItems = new ArrayList<CalendarItem>();
}
public static CalendarItemLab get (Context c){
if(sCalendarItemLab == null){
sCalendarItemLab = new CalendarItemLab(c.getApplicationContext());
}
return sCalendarItemLab;
}
public void setCalendarItems(ArrayList<CalendarItem> CalendarItems){
if(CalendarItems!= null) this.mCalendarItems = CalendarItems;
else this.mCalendarItems=new ArrayList<CalendarItem>();
}
public void deleteCalendarItem(String CalendarId){
for (CalendarItem c : mCalendarItems){
if(c.getCalendarId().equals(CalendarId))
mCalendarItems.remove(c);
}
}
public CalendarItem getCalendarItem(String CalendarId){
for (CalendarItem c : mCalendarItems){
if(c.getCalendarId().equals(CalendarId))
return c;
}
return null;
}
}界面實(shí)現(xiàn)
自定義控件MyView
應(yīng)用中的自定義控件月視圖單元格DateWidgetDayCell、月視圖頭部DateWidgetDayHeader、日視圖的DayHourCell、DayHourIndexCell、周視圖的WeekDayHeader均繼承自MyView。MyView繼承自View類
設(shè)置自定義控件大小和顏色:
public?MyView(Context context,?int?iWidth,?int?iHeight, ColorConfig config) {
super(context);
setFocusable(true);
setLayoutParams(new?LayoutParams(iWidth, iHeight));
this.config = config;
toDrawBox =?true;
fTextSize = config.FontSize;
init(null, 0);
}
設(shè)置不透明漸變:
publicvoid?startAlphaAnimIn(View view) {
AlphaAnimation anim =?new?AlphaAnimation(0.5F, 1);
anim.setDuration(ANIM_ALPHA_DURATION);
anim.startNow();
this.startAnimation(anim);
}
根據(jù)變量重繪控件
privatevoid?init(AttributeSet attrs,?int?defStyle) {
mExampleColor = config.Calendar_WeekFontColor;
DefaultColor = config.Calendar_DayBgColor;
// Set up a default TextPaint object
mTextPaint =?new?TextPaint();
mTextPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextAlign(Paint.Align.LEFT);
// Update TextPaint and text measurements from attributes
invalidateTextPaintAndMeasurements();
}
privatevoid?invalidateTextPaintAndMeasurements() {
mTextPaint.setTextSize(mExampleDimension);
mTextPaint.setColor(mExampleColor);
mTextWidth = mTextPaint.measureText(mMsgString);
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
mTextHeight = fontMetrics.bottom;
}
繪制控件時(shí)調(diào)用
@Override
protectedvoid?onDraw(Canvas canvas) {
super.onDraw(canvas);
//控件的繪制:使用Canvas Paint RectF繪制,代碼省略
}導(dǎo)航欄MainTitleFragment
在activity_calendar_my.xml中添加
<FrameLayout
android:id="@+id/MainTitleFragmentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"?>
</FrameLayout>
在
新建MainTitleFragment.class,并設(shè)置超類為Fragment,早onCreate 方法中處理fragment要用到數(shù)據(jù),在onCreateView方法中設(shè)置視圖,R.layout.fragment_title_main是MainTitleFragment的視圖。Fragment.onCreateView(...)方法中的組件引用幾乎等同于Activity.onCreate(...)方法的處理。
在調(diào)用Fragment.onCreate(...)方法時(shí),并不能生成fragment的視圖。在Fragment.onCreate(...)方法中配置了fragment實(shí)例,通過另一個(gè)方法fragment.onCreateView()完成創(chuàng)建和配置fragment視圖(如下所示):
@Override
publicvoid?onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//數(shù)據(jù)準(zhǔn)備
}
@Override
public?View onCreateView(LayoutInflater inflater,ViewGroup parent,
Bundle savedInstanceState){
View v = inflater.inflate(R.layout.fragment_title_main, parent,false);
btn_month = (Button) v.findViewById(R.id.btn_month);
//部分省略
return View;
}
MyCalendarActivity繼承FragmentActivity,在其中的
FragmentManage fm = getSupportFragmentManager();
Fragment Headfragment = fm
.findFragmentById(R.id.MainTitleFragmentContainer);
if?(Headfragment ==?null) {
Headfragment =?new?MainTitleFragment();
fm.beginTransaction()
.add(R.id.MainTitleFragmentContainer, Headfragment)
.commit();
}

運(yùn)行結(jié)果:
頭部日期標(biāo)識(shí)MainDataBarFragment
方法同上,不同的是Fragment不同

運(yùn)行結(jié)果:
月、周、日視圖
在月、周、日這三個(gè)試圖中使用ViewPager,把一個(gè)Fragment作為一頁,這樣左右滑動(dòng)就可以查看上一個(gè)和下一個(gè)。
首先使用自定義控件構(gòu)建MonthMainFragment、WeekFragment、Dayfragment。
在MyCalendarActivity中以代碼的方式定義并產(chǎn)生布局。FragmentManager要求任何用作fragment容器的視圖都必須具有資源ID,ViewPager是一個(gè)fragment容器,因此,必須賦予其資源ID。在res/values目錄下的XML文件中創(chuàng)建一個(gè)項(xiàng)目元素。創(chuàng)建一個(gè)名為res/values/ids.xml的Android XML資源文件,用以存儲(chǔ)資源ID,并在其中新增一個(gè)名為viewPager的ID
代碼如下:
<?xml version="1.0"?encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<item type="id"?name="monthMainviewPager"?/>
<item type="id"?name="workItemPager"?/>
</resources>
以代碼方式創(chuàng)建內(nèi)容試圖:
mViewPager =?new?ViewPager(this);
mViewPager.setId(R.id.monthMainviewPager);
lin = (LinearLayout) findViewById(R.id.activity_calendar_my);
lin.addView(mViewPager);構(gòu)建ViewPager數(shù)據(jù):
List<MonthMainFragment> mMList =?new?ArrayList<MonthMainFragment>();
List<DayFragment> mDList =?new?ArrayList<DayFragment>();
List<WeekFragment> mWList =?new?ArrayList<WeekFragment>();使用FragmentStatePagerAdapter,它調(diào)用getItem(int)方法獲取Fragment數(shù)組指定位置的Fragment,getCount()獲得Pager總頁數(shù)。并且他在運(yùn)行時(shí)總是構(gòu)建當(dāng)前頁、上一頁、下一頁三頁,這樣在滑動(dòng)到下一頁時(shí)就不會(huì)因?yàn)闃?gòu)建下一頁而花費(fèi)更多的時(shí)間。
以月視圖為例 代碼如下:
mViewPager.setAdapter(new?FragmentStatePagerAdapter(fm) {
@Override
public?Fragment getItem(int?arg0) {
if?(arg0 > mMList.size()) {
returnnull;
}?else?{
return?mMList.get(arg0);
}
}
@Override
publicint?getCount() {
return?mMList.size();
}
});
// 設(shè)置顯示中間的一頁
mViewPager.setCurrentItem((int)(mMList.size()/2));ViewPager滑動(dòng)事件監(jiān)聽器:
mViewPager.setOnPageChangeListener(new?OnPageChangeListener() {
publicvoid?onPageScrollStateChanged(int?arg0) {
//?TODO?在頁面狀態(tài)改變時(shí)的處理
}
publicvoid?onPageScrolled(int?arg0,?float?arg1,?int?arg2) {
//?TODO?頁面正在滑動(dòng)時(shí)的處理
}
publicvoid?onPageSelected(int?arg0) {
//?TODO?選中某頁的處理
}
});//end of setOnPageChangeListenerViewPager頁面刷新問題:
單純的使用mViewPager.getAdapter().notifyDataSetChanged()并不能刷新頁面。在調(diào)用notifyDataSetChanged()時(shí),都會(huì)調(diào)用getItemPosition(Object object)方法,該方法會(huì)查看viewpager的所有item,為每個(gè)item返回一個(gè)狀態(tài)值,若是POSITION_NONE,那么該item會(huì)調(diào)用destroyItem(ViewGroup container, int position, Object object)方法,然后重新生成,如果是POSITION_UNCHANGED,就不會(huì)重新生成,而默認(rèn)返回值是POSITION_UNCHANGED,所以我們要想實(shí)現(xiàn)ViewPager頁面刷新就要改寫getItemPosition(Object object)方法。
解決辦法:
先為每個(gè)數(shù)組對(duì)象設(shè)置ViewIndex
// 設(shè)置顯示順序
for (int i = 0; i < mMList.size(); i++) {
mMList.get(i).viewIndex = i;
}然后在ViewPager OnPageChangeListener的onPageSelected中記錄下當(dāng)前頁的位置position_Month
重寫getItemPosition(Object object)代碼,刷新當(dāng)前三頁即可:
@Override
public int getItemPosition(Object object) {
// 刷新前 現(xiàn)在 后共三頁
if((position_Month -((MonthMainFragment)object).viewIndex)<1
&& (position_Month -((MonthMainFragment)object).viewIndex)>-1
return?POSITION_NONE;
else?return?POSITION_UNCHANGED;
}
周視圖和日視圖構(gòu)建方法同上

運(yùn)行結(jié)果:
日程查看、修改、查詢、新建
構(gòu)建方法同MainTitleFragment,日程修改和新建使用同一個(gè)Fragment
運(yùn)行結(jié)果:
菜單的實(shí)現(xiàn)
在MyCalendarActivity中重寫onCreateOptionsMenu方法添加菜單,通過調(diào)用menu.add方法添加菜單項(xiàng),menu.add方法的參數(shù)如下:
第一個(gè)參數(shù)代表的是組概念。為了能更好的管理你的菜單按鈕,我們將幾個(gè)菜單項(xiàng)歸為一組,。
第二個(gè)參數(shù)代表的是項(xiàng)目編號(hào)。Item ID與菜單選項(xiàng)一一對(duì)應(yīng),這樣在點(diǎn)選菜單項(xiàng)時(shí)可以得到唯一的item ID。
第三個(gè)參數(shù)代表的是菜單項(xiàng)的顯示順序。按照數(shù)字的大小從小到大顯示。如果是0則按照add的順序顯示菜單項(xiàng) 。
第四個(gè)參數(shù)是菜單項(xiàng)顯示的文字。
/** 創(chuàng)建菜單 */
publicboolean?onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, config.getUserStatus());
menu.add(0, 1, 1, "設(shè)置");
menu.add(0, 2, 2, "退出");
returnsuper.onCreateOptionsMenu(menu);
}
重寫onOptionsItemSelected方法處理菜單響應(yīng)。
/** 菜單響應(yīng) */
publicboolean?onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch?(item.getItemId()) {
// 退出
case?2:
MyCalendarActivity.this.finish();
break;
// 設(shè)置
case?1:
Intent i =?new?Intent();
i.setClass(MyCalendarActivity.this, config_Activity.class);
Bundle b =?new?Bundle();
imei = getMIEI();
b.putString("imei", imei);
i.putExtras(b);
startActivityForResult(i, 0);
break;
default:
break;
}
returntrue;
}Web服務(wù)
在Android平臺(tái)調(diào)用Web Service需要依賴于第三方類庫ksoap2,它是一個(gè)SOAP Web service客戶端開發(fā)包。Web Service需要完成注冊(cè)和注銷用戶、同步日程信息兩個(gè)功能。
引入下載的ksoap2-android類庫
編寫WebServiceCall.class。訪問web服務(wù)方法,使用公共屬性request來設(shè)置屬性信息:NAMESPACE:名字空間、WEBSERVICE_URL:web服務(wù)地址、METHOD_NAME:web服務(wù)方法名稱。調(diào)用web服務(wù)hts.call(null, envelope), 結(jié)果:result = (Object) envelope.getResponse()。
public class WebServiceCall {
public String NAMESPACE;
public String WEBSERVICE_URL;
public String METHOD_NAME;
public SoapObject request;
public int TimeOutMS = 2000;
public WebServiceCall(String NAMESPACE, String WEBSERVICE_URL, String METHOD_NAME, int timeOut) {
this.NAMESPACE = NAMESPACE;
this.WEBSERVICE_URL = WEBSERVICE_URL;
this.METHOD_NAME = METHOD_NAME;
TimeOutMS = timeOut;
this.request = new SoapObject(NAMESPACE, METHOD_NAME);
}
public Object callWebMethod() throws IOException, XmlPullParserException {
Object result = null;
SoapSerializationEnvelope envelope = new S oapSerializationEnvelope(SoapEnvelope.VER10);
// 設(shè)置bodyOut屬性
envelope.bodyOut = request;
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE hts = new HttpTransportSE(WEBSERVICE_URL,TimeOutMS);
hts.debug = true;
try {
hts.call(null, envelope);
result = (Object) envelope.getResponse();
} catch (IOException e) {
throw e;
} catch (XmlPullParserException e) {
throw e;
}
return result;
}
}編寫WSHelper,調(diào)用web服務(wù)更便捷。在WSHelper中寫相應(yīng)功能的web服務(wù)調(diào)用方法,首先新建WebServiceCall對(duì)象,再為WebServiceCall設(shè)置參數(shù),然后使用WebServiceCall. callWebMethod()調(diào)用web服務(wù)。這樣使用WSHelper對(duì)象的方法就可直接完成web服務(wù)的操作,不必再程序中配置調(diào)用web服務(wù)的各種參數(shù)。
public class WSHelper {
//配置項(xiàng)
ColorConfig config = new ColorConfig();
//數(shù)據(jù)管理器
DbAdapter dba = null;
//構(gòu)造函數(shù)
public WSHelper() {
if (dba == null) {
dba = new DbAdapter();
config = dba.getUsingConfig();
}
}
//從服務(wù)器獲取新的日程
public int ReadWorkItemFromServer(String LastUpdateTime, String imei) {
int ret = -1;
SoapObject result;
WebServiceCall wsCall = new WebServiceCall(config.NAMESPACE,
config.WEBSERVICE_URL, "GetCalendarByUA", config.timeOut);
wsCall.request.addProperty("IMEI", imei);
wsCall.request.addProperty("alterTime", LastUpdateTime);
try {
result = (SoapObject) wsCall.callWebMethod();
ret = dba.InsertManyCIS(result);
} catch (Exception e) {
ret = -1;
}
return ret;
}
}
本地服務(wù)
系統(tǒng)啟動(dòng)本地服務(wù)時(shí)先調(diào)用onCreate()方法,再調(diào)用 onStart()方法,最后在關(guān)閉服務(wù)時(shí)調(diào)用 onDestroy()方法。這個(gè)過程和創(chuàng)建Activity的過程類似,在啟動(dòng)時(shí)調(diào)用onCreate()方法進(jìn)行一次初始化。程序調(diào)用Context.startService()來打開服務(wù),調(diào)用 Context.stopService()來中止服務(wù)。
本系統(tǒng)實(shí)現(xiàn):
新建LocalService.class繼承Service類。
重寫onCreate()方法,在其中新建一個(gè)線程。threadDisable為線程運(yùn)行控制變量,當(dāng)threadDisable==true時(shí)線程可一直在后臺(tái)運(yùn)行。While循環(huán)中,cnt是分鐘計(jì)數(shù),每休眠一分鐘查詢是否有提醒的日程并通知欄提醒;根據(jù)colorconfig中的同步時(shí)間調(diào)用web服務(wù)同步數(shù)據(jù)。
new?Thread(new?Runnable() {
@Override
publicvoid?run() {
while?(!threadDisable) {
try?{
// 休眠1分鐘
Thread.sleep(SleepMS);
// cnt自加
cnt = (cnt + 1) % 3600;
//通知欄提醒
showNotify();
// 根據(jù)定時(shí)時(shí)間與后臺(tái)數(shù)據(jù)庫同步數(shù)據(jù)
if?(dba ==?null) {
dba =?new?DbAdapter(LocalService.this);
config = dba.getUsingConfig();
}
int?minu = config.syncMinute;
if((minu>0) && (cnt%minu == 0)){
syscFromServer();
}
}?catch?(InterruptedException e) {
}
}
}
}).start();通知欄提醒實(shí)現(xiàn)
//獲取狀態(tài)通知欄管理,
//其中創(chuàng)建的 nm 對(duì)象負(fù)責(zé)“發(fā)出”與“取消” Notification。
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification nf =?new?Notification();
//設(shè)置通知的聲音、圖標(biāo)、主題、標(biāo)記
nf.defaults |= Notification.DEFAULT_SOUND;
nf.icon = R.drawable.ic_launcher;
nf.tickerText = "日歷有提醒!";
nf.flags |= Notification.FLAG_AUTO_CANCEL;
//設(shè)置點(diǎn)擊通知頁面跳轉(zhuǎn)的數(shù)據(jù)、跳轉(zhuǎn)的頁面
b.putString(WorkItemCheckFragment.EXTRA_WORKITEM_ID, ciList.get(i).getCalendarId());
CalendarItemLab.get(this).setCalendarItems((ArrayList<CalendarItem>) ciList);
intent.setClass(LocalService.this,WorkItemCheckPagerActivity.class);
intent.putExtras(b);
pd = PendingIntent.getActivity(LocalService.this, 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
//設(shè)置顯示在通知下拉框中的信息
//參數(shù)分別為:Context,標(biāo)題,內(nèi)容,PendingIntent。
nf.setLatestEventInfo(LocalService.this, ciList.get(i)
.getTopic(), CalendarBuilder
.getHourMinuteString(ciList.get(i).getStartTime()),pd);
notifyList.add(nf);
//發(fā)送通知欄消息
nm.notify((int) ciList.get(i).notifyTime.getTimeInMillis(),nf);
日程同步
手動(dòng)同步
點(diǎn)擊導(dǎo)航欄上的同步按鈕,在點(diǎn)擊事件處理中調(diào)用web服務(wù)同步數(shù)據(jù)并保存在本地?cái)?shù)據(jù)庫中。但是web服務(wù)同步數(shù)據(jù)時(shí)間會(huì)比較長,所以在此處啟動(dòng)一個(gè)線程處理web服務(wù)。
新建一個(gè)AsyncTask,線程運(yùn)行前調(diào)用onPreExecute()在其中啟動(dòng)一個(gè)對(duì)話框,設(shè)置同步標(biāo)志is_downloading =?true;后臺(tái)運(yùn)行時(shí)調(diào)用doInBackground(String... params),在其中調(diào)用web服務(wù)并返回結(jié)果UpdateCnt;運(yùn)行結(jié)束后調(diào)用onPostExecute(String result),在其中關(guān)閉對(duì)話設(shè)置同步標(biāo)志is_downloading =false并處理結(jié)果;當(dāng)返回鍵按下時(shí)調(diào)用onCancelled()關(guān)閉對(duì)話框并設(shè)置同步標(biāo)志is_downloading =false。
//新建線程 運(yùn)行線程
wsTask =?new?WSTask();
wsTask.execute();
class?WSTask?extends?AsyncTask<String, Integer, String> {
//?TODO?后臺(tái)同步數(shù)據(jù)
@Override
protectedvoid?onCancelled() {
pupdateDialog.cancel();
is_downloading =?false;
super.onCancelled();
}
@Override
protectedvoid?onPreExecute(){
is_downloading =?true;
pupdateDialog = ProgressDialog.show(getActivity(), "請(qǐng)稍等","正在更新任務(wù)項(xiàng)...");
}
@Override
protected?String doInBackground(String... params) {
//mWsHelper.IMEIRegister("姚鵬", "73", getMIEI());
UpdateCnt = mWsHelper.ReadWorkItemFromServer(dba.getLastUpdateTime()
.getAlterTime(), imei);
dba.updataLastUpdateTime();
return?UpdateCnt+"";
}
@Override
protectedvoid?onPostExecute(String result) {
if?(pupdateDialog !=?null) {
pupdateDialog.dismiss();
}
if(result.equals("-1") || result.equals("0")){
//Handler.post(runnableUi_xml_error);
}else{
//Handler.post(runnableUi_update_ui);
myListener.updateViewPager();
}
is_downloading =?false;
super.onPostExecute(result);
}
}自動(dòng)同步
在4.4章節(jié)中已介紹。
屏幕旋轉(zhuǎn)后的Activity數(shù)據(jù)保存
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它們不同于 onCreate()、onPause()等生命周期方法,它們并不一定會(huì)被觸發(fā)。當(dāng)應(yīng)用遇到以下狀況時(shí),如:Home鍵按下時(shí)、手機(jī)內(nèi)存不足時(shí),一個(gè)Activity會(huì)由系統(tǒng)銷毀,這時(shí)Activity會(huì)調(diào)用onSaveInstanceState()保存數(shù)據(jù)。但是當(dāng)用戶在應(yīng)用中按返回鍵去主動(dòng)銷毀一個(gè)Activity時(shí),Activity不會(huì)調(diào)用onSaveInstanceState()方法,這是因?yàn)橛脩舻男袨楸砻饕顺鰬?yīng)用故不再需要存儲(chǔ)Activity的狀態(tài)。通常保存一些臨時(shí)性的狀態(tài)使用onSaveInstanceState(),而數(shù)據(jù)的持久化保存使用onPause()適。
屏幕旋轉(zhuǎn)時(shí)會(huì)調(diào)用onSaveInstanceState(),在其中保存一些臨時(shí)數(shù)據(jù)(當(dāng)前界面ID、選中的日期)
@Override
protectedvoid?onSaveInstanceState(Bundle outState){
outState.putInt("cal_ui", cal_ui);
String temp = CalendarBuilder.Calendar2LongString(calSelected);
outState.putString("calselected", temp);
super.onSaveInstanceState(outState);
}
在Activity獲取保存的臨時(shí)數(shù)據(jù)需要在onCreate()方法中使用如下代碼:
if(savedInstanceState !=?null){
cal_ui = savedInstanceState.getInt("cal_ui");
Calendar tempCalendar = CalendarBuilder.longString2Calendar(savedInstanceState.getString("calselected"));
calSelected = (Calendar) tempCalendar.clone();
}Activity向Fragment傳遞數(shù)據(jù)
利用fragment argument。在Fragment中新建newInstance()方法,在newInstance中首先需創(chuàng)建Bundle對(duì)象。然后,使用Bundle限定類型的“ put”方法(類似于Intent的方法) ,將argument放到bundle中。附加bundle給fragment,需使用Fragment.setArguments(Bundle)方法。
publicstatic?MonthMainFragment newInstance(Calendar calstartdate,ColorConfig config,int?cell_size) {
Bundle args =?new?Bundle();
args.putSerializable(CAL_START_DATE, calstartdate);
args.putSerializable(CAL_CONFIG, config);
args.putSerializable(CELL_SIZE, cell_size);
MonthMainFragment fragment =?new?MonthMainFragment();
fragment.setArguments(args);
return?fragment;
}
在Fragment中onCreate方法中通過getArguments().getSerializable();方法獲取數(shù)據(jù)。
@Override
publicvoid?onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
calStartDate = (Calendar) getArguments()
.getSerializable(CAL_START_DATE);
config = (ColorConfig) getArguments().getSerializable(CAL_CONFIG);
cell_size = (Integer) getArguments().getSerializable(CELL_SIZE);
if?(dba ==?null) {
dba =?new?DbAdapter(getActivity());
config = dba.config;
}
}
當(dāng)CrimeActivity創(chuàng)建CrimeFragment時(shí),應(yīng)調(diào)用CrimeFragment.newInstance(UUID)方法。
MonthMainFragment.newInstance((Calendar)(calTodayDate.clone()), config,cell_size)Fragment之間通信
Fragment與它所屬Activity通訊。首先在Fragment類中定義一個(gè)接口,并在它所屬的Activity中實(shí)現(xiàn)接口。Fragment在它的onAttach()方法執(zhí)行期間捕獲該接口的實(shí)現(xiàn),然后調(diào)用接口方法,這樣便可以同Activity通信。
//TODO?fragment信息交換接口
publicinterface?MainTitleClickListener
{
publicvoid?setToToday();
}
private?MainTitleClickListener myListener;
@Override
publicvoid?onAttach(Activity activity)
{
super.onAttach(activity);
myListener = (MainTitleClickListener) activity;
}在Activity中實(shí)現(xiàn)setToToday()接口類即可。這樣Fragment就可以和Activity通信了。
在Fragment中定義public的方法,在Activity中通過FragmentManager. findFragmentById()方法可獲得Fragment,在調(diào)用Fragment的public方法。這樣就可以完成Activity與Fragment的通信。
代碼如下:
FragmentManager fm = getSupportFragmentManager();
Fragment MainDateBarfragment = fm
.findFragmentById(R.id.MainDateBarContainer);
((MainDateBarFragment) MainDateBarfragment).setTopDate(calShowDate);
總結(jié)
遇到的問題與解決
ViewPager大小不能自適應(yīng)
本系統(tǒng)中多次使用ViewPager,但是他卻有個(gè)小麻煩。ViewPager的大小總是填滿整個(gè)屏幕的剩余部分,即使為它使用了android:height="wrap_content"這個(gè)屬性也是沒有效果的
解決方法:通過LayoutParmas動(dòng)態(tài)改變ViewPager的高度。計(jì)算View的大小并通過LayoutParmas設(shè)置給ViewPager。
代碼如下:
lin = (LinearLayout) findViewById(R.id.activity_calendar_my);
lin.addView(mViewPager);
LinearLayout.LayoutParams params=new?LinearLayout.LayoutParams(childViewWeight, childViewHeight);
lin.setLayoutParams(params);調(diào)用系統(tǒng)通訊錄并返回聯(lián)系人的姓名、電話號(hào)碼
打開系統(tǒng)通訊錄
Intent intent =?new?Intent(Intent.ACTION_PICK);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
startActivityForResult(intent, REQUEST_CONTACT);activity是以需返回結(jié)果的方式啟動(dòng)的,所以我們會(huì)調(diào)用onActivityResult(...)方
法來接收一個(gè)intent。該intent包括了數(shù)據(jù)URI。該數(shù)據(jù)URI是一個(gè)指向用戶所選聯(lián)系人的定位符。創(chuàng)建了一條查詢語句,要求返回全部聯(lián)系人的顯示名字。然后查詢聯(lián)系人數(shù)據(jù)庫,獲得一個(gè)可用的Cursor。因?yàn)橐呀?jīng)知道Cursor只包含一條記錄,所以將Cursor移動(dòng)到第一條記錄并獲取它的字符串形式。該字符串即為聯(lián)系人的姓名。
聯(lián)系人應(yīng)用返回包含在intent中的URI數(shù)據(jù)給父activity時(shí),它會(huì)添加一個(gè)Intent.FLAG_GRANT_READ_URI_PERMISSION標(biāo)志。該標(biāo)志向Android示意,應(yīng)用中的父activity可以使用聯(lián)系人數(shù)據(jù)一次。這種方式工作的很好,因?yàn)?,我們不需要訪問整個(gè)聯(lián)系人數(shù)據(jù)庫,只需訪問數(shù)據(jù)庫中的一條聯(lián)系人信息。
Calendar類相關(guān)計(jì)算
Calendar c = Calendar.getInstance(); //當(dāng)前時(shí)間
c.set(Calendar.DAY_OF_MONTH, 1);//設(shè)置為本月1日
System.out.println(c.getTime()); //輸出本月一號(hào)的date
//獲取本月一號(hào)是星期幾
System.out.println(c.get(Calendar.DAY_OF_WEEK));
//設(shè)置為本月日歷中的第一天
c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH)- (c.get(Calendar.DAY_OF_WEEK) - 1));
//輸出本月日歷顯示的第一天的date
System.out.println(c.getTime());
//獲取日歷上顯示的最后一天
c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) + 6 * 7 - 1);
//輸出日歷上顯示的最后一天的date
System.out.println(c.getTime());軟件的優(yōu)勢與不足
優(yōu)勢:
現(xiàn)在處于信息時(shí)代每天接受的信息太多。本軟件可以把日程信息整理到日歷上,使信息更加明朗。
使用了局部視圖Fragment,使用fragment而不是activity進(jìn)行UI管理,可繞開Android系統(tǒng)對(duì)activity規(guī)則的限制。依據(jù)應(yīng)用和用戶的需求,可結(jié)合使用fragment和activity來組織或重新組織用戶界面,這樣界面設(shè)計(jì)更加靈活。
不足:
Fragment構(gòu)建View過程中進(jìn)行查詢數(shù)據(jù)庫,導(dǎo)致頁面構(gòu)建速度慢。
手機(jī)端數(shù)據(jù)庫數(shù)據(jù)冗余較大,造成存儲(chǔ)浪費(fèi)。
總結(jié)
本軟件是基于Android平臺(tái)的個(gè)人日歷,是辦公自動(dòng)化軟件的一部分。最終本軟件完成了基本功能,運(yùn)行流暢。緒論中討論了課題背景,技術(shù)發(fā)展研究概況,課題研究意義,課題研究 內(nèi)容及方法。
第二章討論了課題開發(fā)的相關(guān)技術(shù),包括Android平臺(tái),局部視圖Fragment,web服務(wù),本地服務(wù),MVC開發(fā)模式。并簡單介紹了本軟件的開發(fā)軟件、開發(fā)語言、和運(yùn)行平臺(tái)。
第三章對(duì)系統(tǒng)做了簡單的需求分析,得到用戶的功能和界面需求。并設(shè)計(jì)軟件的功能、界面、數(shù)據(jù)層。
第四章詳細(xì)的介紹了個(gè)人日歷軟件的各個(gè)模塊的設(shè)計(jì)和實(shí)現(xiàn),包括界面的實(shí)現(xiàn)、數(shù)據(jù)層實(shí)現(xiàn)、web服務(wù)、本地服務(wù)、日程同步、屏幕旋轉(zhuǎn)后Activity數(shù)據(jù)保存、Activity向Fragment傳遞數(shù)據(jù)、Fragment之間的通信。
第五章介紹了在開發(fā)過程中遇到的問題,解決方法,以及應(yīng)用的優(yōu)勢與不足。由于之前并沒有完整的完成一個(gè)系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn),并且使用對(duì)于自己來說比較新的技術(shù)而增加了不少難度,但是在老師的幫助下完成了它。畢業(yè)設(shè)計(jì)大大提高了我對(duì)軟件的整體架構(gòu)的認(rèn)識(shí)和軟件編程能力。
參考文獻(xiàn)
[1] Bill Phillips Brian Hardy等,Android編程權(quán)威指南[M]. 北京:人民郵電出版社,2014.
[2] 李剛等.瘋狂Android講義(第2版). 北京:電子工業(yè)出版社,2013.
[3] Zigurd Mednieks等.Android程序設(shè)計(jì)(第2版). 北京:機(jī)械工業(yè)出版社,2014
[4] 明日科技. Android從入門到精通.北京:清華大學(xué)出版社,2012
[5] (美)邁耶.Android 4 高級(jí)編程(第3版). 北京:清華大學(xué)出版社,2014
[6] 何孟翰.Google AndroidSDK開發(fā)實(shí)戰(zhàn)演練[M].北京:人民郵電出版社,2012.
[7] 高凱等.Android智能手機(jī)軟件開發(fā)教程[M].北京:國防工業(yè)出版社,2012.6.
[8] 徐炳文.佳木斯大學(xué)學(xué)報(bào)(自然科學(xué)版).基于J2ME的手機(jī)教務(wù)課表查詢系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)[J/OL],2010-1(28).
[9] 徐炳文.天津師范大學(xué)學(xué)報(bào)(自然科學(xué)版).基于四層架構(gòu)J2ME移動(dòng)課表查詢系統(tǒng)的開發(fā)設(shè)計(jì) [J/OL],2011-4(31).
[10] 王中華等.宜春學(xué)院學(xué)報(bào).Android手機(jī)理財(cái)軟件的實(shí)際和實(shí)現(xiàn) [J/OL],2011-12(33).
[11] Gasolin.深入淺出Android手持設(shè)備應(yīng)用程序設(shè)計(jì).北京:電子音像出版社,2010.
[12] 張新柱等.齊齊哈爾大學(xué)學(xué)報(bào).基于Android手機(jī)終端信息查詢系統(tǒng)的設(shè)計(jì) [J/OL],2012-7(28).
[13] Marziah Karch.Android for work:productivity dor professionals[M].USA:
Apress.2010,97~114.
[14] 基于Android的課程表提醒程序.百度百科.http://wenku.baidu.com/view/83d0e6b969dc5022aaea0036.html
[16] 趙洛育,劉洪利. android開發(fā)實(shí)戰(zhàn)經(jīng)驗(yàn). 北京:清華大學(xué)出版社,2012.
[17] 王金柱,王翔,閆秀華,張雪嬌. android學(xué)習(xí)精要. 北京:清華大學(xué)出版社,2012
致謝
致謝
經(jīng)過將近兩個(gè)月的學(xué)習(xí)與實(shí)踐,本次畢業(yè)設(shè)計(jì)也接近了尾聲。通過畢業(yè)設(shè)計(jì)的鍛煉,我不僅學(xué)到了很多關(guān)于android應(yīng)用開發(fā)的知識(shí)還體會(huì)到在設(shè)計(jì)開發(fā)程序中應(yīng)有的態(tài)度。當(dāng)然這些知識(shí)經(jīng)驗(yàn)的獲得與老師和同學(xué)的熱心幫助是分不開的。在這里我向他們表示真摯的感謝。 在這里首先要感謝我的導(dǎo)師王曉輝老師。導(dǎo)師的專業(yè)水平,治學(xué)嚴(yán)謹(jǐn)?shù)膽B(tài)度和科學(xué)研究的精神深令我敬佩,并將積極 影響我以后的學(xué)習(xí)和工作。雖然老師平日工作繁忙,但是老師針對(duì)我的問題總是細(xì)心的指導(dǎo),他給我提供了很多創(chuàng)意性的想法,打開了我的思路。
最后要感謝我的母?!A北電力大學(xué),是母校給我們提供了優(yōu)良的學(xué)習(xí)環(huán) 境。感謝那些曾給我授過課的每一位老師,是你們教會(huì)我專業(yè)知識(shí)。在此,我再 說一次謝謝!謝謝大家!