開題:手機衛士這樣的一個項目能夠很好的複習基礎所學的知識點,由於它覆蓋面廣,用來作安卓深刻學習是一個很好的選擇.java
1,開始一個項目android
寫一個好的代碼不只是看功能是否實現,並且代碼具備較高的可讀性程序員
1.1 代碼組織方式:web
①採用業務邏輯模塊組織代碼,以小米閱讀爲例:數據庫
功能一:閱讀器reader com.xiaomi.readerjson
功能二:分享 share com.xiaomi.sharewindows
功能三:便籤 note com.xiaomi.note數組
按功能劃分包,即便一部分功能被移除了,另外的功能也不會受太大影響.通常用在OA類型的網站,自動化辦公的小應用上,各自模塊獨立安全
②根據代碼的類型組織包結構,以安全衛士爲例:服務器
1,界面相關 com.zzx.mobliesafe.activitys
2,服務相關 com.zzx.mobilesafe.service
3,業務邏輯 com.zzx.mobilesafe.engine(引擎)
4,數據庫 com.zzx.mobilesafe.db
5,數據庫操做包 com.zzx.mobilesafe.db.dao
6工具類 com.zzx.mobilesafe.utils
7自定義view包 com.zzx.mobilesafe.ui
2,_splash(濺,飛灑,賣弄)界面
①展示產品的Logo,提升產品知名度(也能夠用做廣告頁面,打開APP的廣告:知乎)
②初始化應用程序的數據
③連接服務器,查找可更新的版本,自動更新
④用戶操做指南,新版本特性提醒
佈局文件的命名規則:activity_對應的java文件名便可
2.2,
設置界面爲全屏更美觀:
Android:style/Theme.black.NoTitleBar.FullScreen //黑色全屏沒有標題欄的界面
在主界面顯示版本號
①獲取本地APP的版本號,在清單文件中獲取
packageInfo = getPackageManager().getPackageInfo(getPackageName()(獲取當前APP的文件包名),flags(0,可選標示));
String code = packageInfo.versionName;//清單文件的版本號
這個 API不只能夠得到本APP的,也能夠獲取別的APP的,經過這個特性能夠告知用戶更新哪些APP.因此能夠把這個API獲取版本號抽取出來作成一個工具類
抽取出來的時候要注意,getPackageManager()和getPackageName()都是context調用的,因此抽取的方法須要傳入一個上下文,其實也須要傳入一個包名.
若是一個方法沒有使用類的成員變量就加靜態方便調用.
②在界面上顯示版本號,定義一個textView(ID命名要規範,控件名_Activity名_用處)
最後把版本號賦值給TextView;
3,源代碼的版本控制
3.1 Android項目中不須要被管理的文件夾:
.settings,bin,gen,.project,這些是須要ignore忽視的
須要添加的:
assets(須要原樣封裝到apk裏面的文件),libs(外部引入的jar 包),res(資源),src(源代碼),.classpath,AndroidManifest.xml清單文件 ,ic_launcher-web.png圖片
proguard-project.text,project.properties(混淆編譯的東西)
4.軟件自動更新
4.1原理:拿到服務器版本號,跟本地版本號作比較,若是服務器版本號大於本地版本號,就彈出一個對話框,提示用戶是否須要更新.
若是須要更新:下載更新信息,替換安裝
若是不須要更新,那麼能夠選擇讓用戶繼續訪問,或者直接退出程序
若是本地版本號與服務器版本號一致或更高,就進入主界面
4.2 獲取服務器的版本號
在splash界面中,onCreate()方法裏,連接網絡,獲取服務器版本號,由於須要訪問網絡,因此須要放到子線程中,在這裏就定義一個類去實現runable
CheckVersionTask類實現 Runable,重寫run()方法.
額外:①在tomact服務器中放置一個json文件,保存版本信息:{「version」:」2.0」}
②訪問網絡路徑不要寫死了,定義在values中的config.xml文件中String字符串
繼續網絡訪問
一.建立url對象,經過url獲取網絡連接,設置請求方式,超時時間.
二,獲取返回的狀態碼,判斷是否=200.
獲取輸入流轉換成字符串,經過之前的工具類,或者再經過ByteArrayOutputStream,內存輸出流把輸入流中的信息保存在內存中,最後經過toString方法轉換成字符串.(這裏有須要對字符串進行轉碼的操做)
三,對json字符串進行解析JsonObject(大括號就是json對象,中括號就是json數組)
jsonobject.getString(「鍵的名稱」);
額外:須要添加權限.
5,應用程序的錯誤提醒
當本地版本號小於服務器版本號的時候就須要提示用戶更新版本.
提示用戶更新版本是在主線程中更新ui,若是在子線程中更新,須要經過handler發送消息.
①建立Message對象 message mes = Message.obtain();
②區分消息mes.what=XXXX;
hanlder.sendMessage(mes);
③在主線程中判斷髮送過來的消息,若是符合就建立一個對話框,另外還有一些問題也須要通知用戶(看需求來,不要把全部的異常所有刪掉,通常互聯網公司要求都比較多,不一樣的錯誤異常須要不一樣的提示)
實際開發中,主要是把錯誤代碼提示出來(用戶不懂什麼是異常,可是用戶能夠把錯誤代碼提交給程序員或者是客服,根據不一樣的錯誤代碼來區分不一樣的代碼)
④升級提醒的對話框(這裏能夠考慮抽取一個方法,讓handler顯得更簡潔)
AlertDialog.Builder buider = new Builder(上下文);
指定標題,文本(這裏的文本能夠在JSON中添加數據,在獲取服務器返回的JSON中,解析出來更新的描述內容),確認和取消按鈕.
最後記得builder.show();//顯示對話框在頁面上.
額外:解析出來的中文字符串亂碼,windows系統默認GBK(改他就能夠),android默認utf-8.
6爲了測試splash界面,建立一個主界面.配置清單文件,建立對應的佈局文件,在onCreate()中記得 set指定對應的佈局文件(能夠直接建立Activity文件,eclipse會自動配置好)
6.1在提醒的對話框中,取消升級按鈕的點擊事件中,經過顯示意圖(速度快)開啓界面,同時關閉splash界面finsh();把它銷燬掉.
6.2 確認按鈕,在解析的JSON中添加一個path,把新版本的apk下載路徑放進去便可.解析到須要更新的時候,把這個路徑獲取出來,若是用戶點了確認,就打開這個路徑下載
額外:使用開源框架進行下載,直接經過輸入流獲取也行(多線程下載便可).
這裏就用xUtils框架,順便練習一下使用.
①得到解析的apk下載路徑
②建立httpUtils http = new httpUtis();對象
http.download(下載路徑,存放路徑,下載狀態回調)
③在回調中三個方法,一個成功,一個失敗,另外一個onLoding()顯示下載的進度,顯示一個進度條對話框(ProgressDialog),setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)//設置水平方向的進度條,在onLoading中設置最大值和進度數值.最後記得pd.show()
不論是下載成功仍是下載失敗都記得要dismiss();關閉對話框.
④放到存儲卡中記得判斷 SD卡的狀態:Environment.getExtrnalStorangeDirectory()
若是SD卡不存在就直接進行主界面,並關閉頁面,關閉以前提示SD卡不存在
額外:最後還要添加權限,在服務器配置資源文件
項目生成的apk 在bin目錄下
7,替換安裝應用程序:模板代碼
①定義一個意圖對象intent = new intent()//須要激活系統的包安裝器packageInstaller.
②在上層服務的源碼中能夠找到它.經過查找清單文件packageInstallerActivity中的意圖過濾器,將setcategory(類別),setaction添加到意圖對象中,指定data數據類型.
注意:若是同時有scheme和mimeType就要用setDataAndType(scheme(uri.parsefile(file)便可),mimetype).(這裏的file並非文件對象,要經過file.result獲取)
③最後開啓意圖
8,自動更新的細節問題.
①若是版本是最新的,進入主界面速度太快,因此須要讓splash界面暫停一段時間(套路)
SystemClock.sleep(xxxx);測試這個的時候,記得服務器版本和本地APP版本的區別
②若是用戶沒有點擊對話框,點擊別的地方,系統會默認關閉對話框,這時候界面就卡了,經過builder.setCancelable(false);//設置對話框不能被自動關閉.返回鍵也無效
③彈出了錯誤代碼以後界面又卡了,這裏須要讓用戶能夠進入默認的主界面
④網絡太差的時候,再睡兩秒就不太合適了,這時候要去動態的獲取時間,最開始獲取一次時間,最後finally裏再獲取一次時間,判斷兩次時間的間隔,若是小於必定時間就睡眠必定時間(兩秒減去間隔時間,若是大於兩秒就直接進入主界面).
⑤代碼優化,Message建立放到外面去,把handler.handlerMessage()放到finally裏面必須執行.
9,應用程序的簽名問題
直接從項目中拷貝的apk文件,是不能發佈到應用市場的,由於沒有進行簽名,打開這個apk文件,能夠看到META-INF,這個簽名文件若是被修改,或資源文件被修改,都會致使應用程序的完整性得不到校驗,沒法再次安裝,它的主要做用就是校驗應用程序完整性.
eclipse會自動給一個調試debug的簽名,它不能發佈到市場上去,在應用程序的\META-INF\CERT.RSA文件中能夠看到debug的字符串
創造一個簽名,通常叫工程名.keystore,在導出項目的時候能夠設置簽名,設置的密碼要保密,不讓別人知道,點擊next能夠配置有效時間(最好大於25年),不少額外信息之類.
在導出項目的時候選擇簽名,輸入密碼便可
若是一個應用程序想要完成替換安裝
簽名一致,包名一致,必定要保存好keystore文件
10,製做主界面ui
預覽的時候能夠選擇沒有標題欄,和全屏的預覽.
①TextView:但願文本一行顯示:singleLine.
但願文本滾動,ellipsize設置marquee,可是直接定義這個屬性是沒效果的,它的底層能夠看作是相似Web裏字符串拼接截取達到的滾動效果,會消耗必定的資源,因此谷歌默認設置它沒有焦點的時候就會生效.
作法:建立一個FocusTextView繼承TextView,繼承的時候最好繼承全部的構造.
重寫, isFocused(),返回一個ture便可.
使用自定義控件要在佈局文件裏寫全路徑名,框架才能找到它.
②記得給圖標添加動畫效果
③shimmer 土豪金文字效果