Android基础知识精简版(转)
1.?前言
裁剪了下轉(zhuǎn)載內(nèi)容,只保留我認為有用的知識點。2.?搭建開發(fā)環(huán)境
http://tools.android-studio.org/3.?開發(fā)一個 Android 程序
3.1.?創(chuàng)建 Android 程序
??創(chuàng)建 Android?Project
??Project?name :項目名
??Build?Target : Android 版本
??Application?name :程序名,顯示在程序列表中,以及程序啟動后的標(biāo)題欄
??Package?name :包名,程序的唯一標(biāo)識
??Create?Activity :選擇程序啟動時是否創(chuàng)建一個窗體,設(shè)置主窗體名字
??Min?SDK?Version :設(shè)置運行該程序所需的最低版本
3.2.?安裝、卸載程序
??Eclipse 安裝
右鍵點擊工程?–?Run?as?–?Android?Application
??虛擬機卸載
設(shè)置?–?應(yīng)用程序?–?管理應(yīng)用程序?–?選中要卸載的程序?–?卸載
3.3.?了解項目目錄結(jié)構(gòu)
??src :源代碼
??gen :系統(tǒng)自動生成的文件
R.java?中記錄了項目中各種資源 ID
??res :系統(tǒng)資源,所有文件都會在 R 文件生成資源 ID
drawable :圖片
layout :界面布局
values :數(shù)據(jù)
anim :定義動畫的 XML
raw :原生文件
??assets :資源路徑,不會在 R 文件注冊
??project.properties :供 Eclipse 使用,讀取該項目使用 Android 版本號。早期版本名為: default.properties
??AndroidManifest.xml :清單文件,在軟件安裝的時候被讀取
Android 中的四大組件( Activity 、 ContentProvider 、 BroadcastReceiver 、 Service )都需要在該文件中注冊
程序所需的權(quán)限也需要在此文件中聲明,例如:電話、短信、互聯(lián)網(wǎng)、訪問 SD 卡
??bin :二進制文件,包括 class 、資源文件、 dex 、 apk 等
??proguard.cfg:用來混淆代碼的配置文件,防止別人反編譯
3.4.?程序啟動過程
??Eclipse 將 .java 源文件編譯成 .class
??使用 dx 工具將所有 .class 文件轉(zhuǎn)換為 .dex 文件
??再將 .dex 文件和所有資源打包成 .apk 文件
??將 .apk 文件安裝到虛擬機完成程序安裝
??啟動程序?–?開啟進程?–?開啟主線程
??創(chuàng)建 Activity 對象? –?執(zhí)行 OnCreate() 方法
??按照 main.xml 文件初始化界面
4.?演示案例
41.?查看程序錯誤信息
??Android 程序中如果出錯,錯誤不會顯示在 Console 中,而是顯示在 LogCat 界面下。可以從 window? –?show?view 中打開
??日志信息分為 5 個級別: verbose?>?debug?>?info?>?warn?>?error? 高級的包含低級的
??可以創(chuàng)建過濾器對日志進行過濾顯示,點擊綠色加號,可以按照 tag 、 pid 、 level 進行篩選
4.2.?布局
??RelativeLayout (相對布局)
??android-sdk-windows/docs/guide/topics/ui/layout-objects.html#relativelayout
??TableLayout (表格布局)
android-sdk-windows/docs/guide/topics/ui/layout-objects.html#tablelayout
??FrameLayout (幀布局)
android-sdk-windows/docs/guide/topics/ui/layout-objects.html#framelayout
setRequestedOrientation(ActivityInfo. SCREEN_ORIENTATION_LANDSCAPE );
setRequestedOrientation(ActivityInfo. SCREEN_ORIENTATION_PORTRAIT );
4.3.?Junit
??項目中添加測試類
??在 AndroidManifest.xml 清單文件中添加配置
< instrumentation? android:targetPackage = "cn.itcast.junit"? android:name = "android.test.InstrumentationTestRunner"? />
< uses-library? android:name = "android.test.runner"? />
??定義一個類繼承 AndroidTestCase ,定義測試方法
??在 Outline 視圖下右鍵點擊測試方法? –?Run?as?–?Android?Junit?Test
??創(chuàng)建測試項目
??創(chuàng)建 Android?Test?Project
??輸入項目名,選擇一個已存在的工程, Eclipse 可以自動配置 Junit 環(huán)境
5.?文件操作( File 、 XML 、 SharedPreferences )
5.1.?讀寫文件
??寫入文件到 SD 卡
??需要在清單文件中注冊權(quán)限
< uses-permission? android:name = "android.permission.WRITE_EXTERNAL_STORAGE"? />
??2.1 版本以下的 SDCard 位置和 2.2 之后版本不同
可以通過Environment.getExternalStorageDirectory()獲取當(dāng)前 SDCard 位置,兼容所有版本
??獲取 SDCard 狀態(tài)
通過Environment.getExternalStorageState()方法獲取 SDCard 當(dāng)前狀態(tài)
常量?Environment.MEDIA_MOUNTED?為已安裝
??寫入文件
??通過 Context. openFileOutput(String?name,? int ?mode)可以獲取一個文件輸入流
name 為文件名, mode 為文件模式,有 4 種模式
輸出流指向路徑為: /data/data/ 包名 /files/?
??文件模式在 Context 中有定義常量
MODE_PRIVATE 私有
MODE_WORLD_READABLE 其他程序可讀(不可寫)
MODE_WORLD_WRITEABLE 其他程序可寫(不可讀)
模式可以組合使用,例如:MODE_WORLD_READABLE?+?MODE_WORLD_WRITEABLE
MODE_APPEND 追加
??讀取文件
??通過 Context. openFileInput(String?name)可以獲取一個文件輸入流
該輸入流可以讀取? /data/data/ 包名 /files/? 路徑下的文件
??獲取當(dāng)前程序 Files 文件路徑
ContextWrapper.getFilesDir()
5.2.?XML
??Pull 簡介
??常見的 XML 解析方式有三種, DOM 、 SAX 、 Pull , Android 系統(tǒng)中推薦使用 Pull
??Pull 解析器是一個開源的 Java 項目, Android 系統(tǒng)內(nèi)部解析 XML 文件均為此種方式,也可用于 JavaEE 項目
??Android?SDK 中已經(jīng)集成了 Pull 解析器,無需添加任何 jar 文件
??Pull 解析器運行方式與 SAX 類似,提供各種事件的判斷
??官方網(wǎng)站: http://xmlpull.org/
??使用 Pull 解析器解析 XML 文件
??Xml.newPullParser()?獲得解析器
??parser.setInput(in,? "UTF-8" )?設(shè)置輸入流以及編碼
??parser.next()?獲取下一個解析事件,得到一個事件代碼
??XmlPullParser中定義了常量來標(biāo)識各種解析事件
START_DOCUMENT 、 END_DOCUMENT? 、 START_TAG? 、END_TAG? 、 TEXT?
??使用XmlSerializer寫出 XML
??使用以下方法生成 XML ,和 XML 文檔順序類似
startDocument
startTag
attribute
text
endTag
endDocument
5.3.?偏好設(shè)定( SharedPreferences )?
??在程序中保存一些配置參數(shù)的時候我們經(jīng)常使用 SharedPreferences
Context.getSharedPreferences(String?name, int ?mode)
該方法可以在 /data/data/<package>/shared_pref/ 目錄下創(chuàng)建一個以 name 命名的 xml 文件, mode 文件為模式
??存儲偏好
調(diào)用edit()方法可以獲取一個 Editor 對象,對數(shù)據(jù)進行存儲,存儲之后需要調(diào)用 commit()保存到文件
??讀取偏好
獲得SharedPreferences之后調(diào)用 getString() 、 getInt() 等方法獲取其中設(shè)置的值
??在 Activity 中獲取 SharedPreferences
在 Activity 中可以調(diào)用 getPreferences( int ?mode)方法獲得一個SharedPreferences,文件名和 Activity 名一致
6.?數(shù)據(jù)庫( SQLite )
6.1.?SQLite 特點
??Android 平臺中嵌入了一個關(guān)系型數(shù)據(jù)庫 SQLite ,和其他數(shù)據(jù)庫不同的是 SQLite 存儲數(shù)據(jù)時不區(qū)分類型
例如一個字段聲明為 Integer 類型,我們也可以將一個字符串存入,一個字段聲明為布爾型,我們也可以存入浮點數(shù)。
除非是主鍵被定義為 Integer ,這時只能存儲 64 位整數(shù)
??創(chuàng)建數(shù)據(jù)庫的表時可以不指定數(shù)據(jù)類型,例如:
CREATE?TABLE?person(id?INTEGER?PRIMARY?KEY?AUTOINCREMENT,?name?VARCHAR(20))
CREATE?TABLE?person(id?INTEGER?PRIMARY?KEY?AUTOINCREMENT,?name)
??SQLite 支持大部分標(biāo)準(zhǔn) SQL 語句,增刪改查語句都是通用的,分頁查詢語句和 MySQL 相同
SELECT?*?FROM?person?LIMIT?20?OFFSET?10
SELECT?*?FROM?person?LIMIT?10,20
6.2.?創(chuàng)建數(shù)據(jù)庫
??定義類繼承SQLiteOpenHelper
??聲明構(gòu)造函數(shù), 4 個參數(shù)
??重寫 onCreate ()方法
??重寫 upGrade() 方法
??注意: SQLite 數(shù)據(jù)庫中列一旦創(chuàng)建不能修改,如果一定要修改,需要重新創(chuàng)建表,拷貝數(shù)據(jù)
6.3.?CRUD操作
??和 JDBC 訪問數(shù)據(jù)庫不同,操作 SQLite 數(shù)據(jù)庫無需加載驅(qū)動,不用獲取連接,直接可以使用
獲取 SQLiteDatabase 對象之后通過該對象直接可以執(zhí)行 SQL 語句
SQLiteDatabase.execSQL()
SQLiteDatabase.rawQuery()
??getReadableDatabase()和getWritableDatabase()的區(qū)別
查看源代碼后我們發(fā)現(xiàn)getReadableDatabase()在通常情況下返回的就是getWritableDatabase() 拿到的數(shù)據(jù)庫
只有在拋出異常的時候才會以只讀方式打開
??數(shù)據(jù)庫對象緩存
getWritableDatabase() 方法最后會使用一個成員變量記住這個數(shù)據(jù)庫對象,下次打開時判斷是否重用
??SQLiteDatabase 封裝了 insert() 、 delete ()、 update ()、 query ()四個方法也可以對數(shù)據(jù)庫進行操作
這些方法封裝了部分 SQL 語句,通過參數(shù)進行拼接
6.4.?事務(wù)管理
??在使用 SQLite 數(shù)據(jù)庫時可以用 SQLiteDatabase類中定義的相關(guān)方法控制事務(wù)
beginTransaction()? 開啟事務(wù)
setTransactionSuccessful()? 設(shè)置事務(wù)成功標(biāo)記
endTransaction()? 結(jié)束事務(wù)
??endTransaction() 需要放在 finally 中執(zhí)行,否則事務(wù)只有到超時的時候才自動結(jié)束,會降低數(shù)據(jù)庫并發(fā)效率
7.?內(nèi)容提供者( ContentProvider )
7.1.?什么是內(nèi)容提供者
??內(nèi)容提供者是 Android 中的四大組件之一,可以將應(yīng)用中的數(shù)據(jù)對外進行共享
??內(nèi)容提供者將數(shù)據(jù)的訪問方式統(tǒng)一,不必針對不同數(shù)據(jù)類型采取不同的訪問策略
??內(nèi)容提供者將數(shù)據(jù)封裝,只暴露出我們希望提供給其他程序的數(shù)據(jù)
??內(nèi)容提供者中數(shù)據(jù)更改可被監(jiān)聽
7.2.?創(chuàng)建內(nèi)容提供者
??定義類繼承 ContentProvider ,根據(jù)需要重寫內(nèi)部方法
??在清單文件的 <application> 節(jié)點下進行配置, <provider> 標(biāo)簽中需要指定 name 和 authorities 屬性
name 為類名,包名從程序 Package 開始,以“ . ”開始
authorities :是訪問 Provider 時的路徑,要唯一
??URI 代表要操作的數(shù)據(jù),由 scheme 、 authorites 、 path 三部分組成
content:// cn.itcast. sqlite . provider / person
scheme :固定為 content ,代表訪問內(nèi)容提供者
authorites : <provider> 節(jié)點中的 authorites 屬性
path :程序定義的路徑,可根據(jù)業(yè)務(wù)邏輯定義
7.3.?完成 CRUD 方法
??當(dāng)程序調(diào)用 CRUD 方法時會傳入 Uri
??我們通過 Uri 判斷調(diào)用者要操作的數(shù)據(jù)
可以使用工具類 UriMatcher 來判斷 Uri
addURI 方法可以添加 Uri
match 方法可以匹配一個 Uri 判斷其類型
??根據(jù)業(yè)務(wù)邏輯操作數(shù)據(jù)
7.4.?訪問內(nèi)容提供者
??通過 Context 獲得 ContentResolver 對象
??調(diào)用 ContentResolver 對象的方法即可訪問內(nèi)容提供者
7.5.?完成 getType 方法
??如果返回數(shù)據(jù)是單條數(shù)據(jù):vnd.android.cursor.item?
??如果返回數(shù)據(jù)是多條數(shù)據(jù):vnd.android.cursor.dir
7.6.?監(jiān)聽內(nèi)容提供者數(shù)據(jù)變化
??在內(nèi)容提供者中可以通知其他程序數(shù)據(jù)發(fā)生變化
通過 Context 的 getContentResolver() 方法獲取 ContentResolver
調(diào)用其notifyChange() 方法發(fā)送數(shù)據(jù)修改通知
??在其他程序中可以通過ContentObserver監(jiān)聽數(shù)據(jù)變化
通過 Context 的 getContentResolver() 方法獲取 ContentResolver
調(diào)用其registerContentObserver() 方法指定對某個 Uri 注冊 ContentObserver
自定義ContentObserver,重寫 onChange() 方法獲取數(shù)據(jù)
7.7.?GIT 獲取源代碼
??資源地址
??Git
http://code.google.com/p/msysgit/
??源碼
https://github.com/android
注意:
GIT1.7.7 安裝后不能卸載,可以用其他版本覆蓋后再卸載。
使用 GIT 時不要使用中文目錄,否則 GIT?GUI 會報錯無法啟動。刪除 C 盤中 .gitconfig文件可以解決。
8.?網(wǎng)絡(luò)通信
8.1.?獲取文本數(shù)據(jù)
??通過 URL 對象封裝地址,打開一個 HttpURLConnection
??設(shè)置頭信息之后獲取響應(yīng)碼,如果成功返回 200 即可從 HttpURLConnection 中獲取輸入流讀取數(shù)據(jù)
??代碼過長屏幕顯示不全可以使用 <ScrollView> 進行顯示
??需要訪問網(wǎng)絡(luò)的權(quán)限
< uses-permission? android:name = "android.permission.INTERNET"? />
8.2.?獲取網(wǎng)絡(luò)圖片
??通過 BitmapFactory 的 decodeByteArray(byte[]?data,?int?offset,?int?length)方法將數(shù)據(jù)轉(zhuǎn)換為圖片對象
8.3.?獲取 XML
??使用 URL 封裝路徑,打開一個 HttpURLConnection
??設(shè)置頭信息之后獲取相應(yīng)碼,從輸入流中獲取數(shù)據(jù)
??使用 XmlPullPaser 解析
8.4.?獲取 JSON
??使用 URL 封裝路徑,打開一個 HttpURLConnection
??設(shè)置頭信息之后獲取相應(yīng)碼,從輸入流中獲取數(shù)據(jù)
??將數(shù)據(jù)轉(zhuǎn)為 String ,封裝成 JSONArray 對象
??遍歷 JSONArray 對象,調(diào)用獲取其中的 JSONObject
??再從 JSONObject 中獲取每個字段的信息
8.5.?發(fā)送 GET 請求
??拼接路徑和參數(shù),通過 URL 進行封裝,打開一個 HttpURLConnection ,發(fā)送請求
??如果參數(shù)是中文會出現(xiàn)亂碼
??URL 中包含的中文參數(shù)需要使用 URLEncoder 進行編碼
??服務(wù)器端如果是 TOMCAT ,其默認使用 ISO8859-1 編碼,接收時需要處理編碼問題
8.6.?發(fā)送 POST 請求
??通過 URL 打開一個 HttpURLConnection
??頭信息中除了超時時間和請求方式之外還必須設(shè)置Content-Type和Content-Length
??從 HttpURLConnection 獲得輸出流輸出參數(shù)數(shù)據(jù)
??服務(wù)端可以使用 request 對象的 setCharacterEncoding方法設(shè)置編碼
8.7.?發(fā)送 XML ,訪問 WebService
??發(fā)送 XML
??通過 URL 封裝路徑打開一個 HttpURLConnection
??設(shè)置請求方式,Content-Type和Content-Length
XML 文件的 Content-Type為:text/xml;?charset=UTF-8
??使用 HttpURLConnection 獲取輸出流輸出數(shù)據(jù)
??WebService
??WebService 是發(fā)布在網(wǎng)絡(luò)上的 API ,可以通過發(fā)送 XML 調(diào)用, WebService 返回結(jié)果也是 XML 數(shù)據(jù)
??WebService 沒有語言限制,只要可以發(fā)送 XML 數(shù)據(jù)和接收 XML 數(shù)據(jù)即可
?? http://www.webxml.com.cn ?網(wǎng)站上提供了一些 WebService 服務(wù),我們可以對其進行調(diào)用
 ??  http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?op=getMobileCodeInfo  ?中提供了電話歸屬地查詢的使用說明 
8.8.?HTTP 協(xié)議上傳文件
??搭建服務(wù)器,完成上傳功能
??使用瀏覽器上傳,查看請求信息
??HttpURLConnection
??通過 URL 封裝路徑打開一個 HttpURLConnection
??設(shè)置請求方式以及頭字段:Content-Type、Content-Length、Host
??拼接數(shù)據(jù)發(fā)送
??Socket
??使用 HttpURLConnection 發(fā)送時內(nèi)部有緩存機制,如果上傳較大文件會導(dǎo)致內(nèi)存溢出
??我們可以使用 Socket 發(fā)送 TCP 請求,將上傳數(shù)據(jù)分段發(fā)送
??HttpClient
public ? void ?upload(String?name,?String?password,?String?path)? throws ?Exception?{
//? 創(chuàng)建 HttpClient 對象
HttpClient?client?=? new ?HttpClient();
//? 設(shè)置超時事件
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
//? 創(chuàng)建一個 Post 請求 ,? 指定路徑
PostMethod?postMethod?=? new ?PostMethod( "http://192.168.1.102:8080/14.Web/LoginServlet" );
//? 封裝每個表單項
Part[]?parts?=?{? new ?StringPart( "name" ,?name),? new ?StringPart( "password" ,?password),? new ?FilePart( "file" ,? new ?File(path))?};
//? 給 Post 請求設(shè)置實體
postMethod.setRequestEntity( new ?MultipartRequestEntity(parts,?postMethod.getParams()));
//? 執(zhí)行 Post 請求
client.executeMethod(postMethod);
//?Post 請求是釋放資源
postMethod.releaseConnection();
}
8.9.?多線程斷點續(xù)傳下載器
??在下載的時候多個線程并發(fā)可以占用服務(wù)器端更多資源,從而加快下載速度
??手機端下載數(shù)據(jù)時難免會出現(xiàn)無信號斷線、電量不足等情況,所以需要斷點續(xù)傳功能
??根據(jù)下載數(shù)據(jù)長度計算每個線程下載的數(shù)據(jù)位置,程序中開啟多個線程并發(fā)下載
在請求頭中設(shè)置 Range 字段就可以獲取指定位置的數(shù)據(jù),例如: Range:?bytes=100-200
??在下載過程中記錄每個線程已拷貝數(shù)據(jù)的數(shù)量,如果下載中斷,下次啟動時從記錄位置繼續(xù)下載
??多線程下載
??進度條使用 <Progress> 進行配置
默認為圓形進度條,水平進度條需要配置 style 屬性, ?android:attr/progressBarStyleHorizontal
使用 android.R.attr. progressBarStyleHorizontal作為樣式
??當(dāng)點擊下載按鈕時開啟多線程下載,下載過程中修改進度條進度
設(shè)置最大刻度:setMax()
設(shè)置當(dāng)前進度:setProgress()
??斷點續(xù)傳
??斷點續(xù)傳需要在下載過程中記錄每條線程的下載進度
??每次下載開始之前先讀取數(shù)據(jù)庫,查詢是否有未完成的記錄,有就繼續(xù)下載,沒有則創(chuàng)建新記錄插入數(shù)據(jù)庫
??在每次向文件中寫入數(shù)據(jù)之后,在數(shù)據(jù)庫中更新下載進度
??下載完成之后刪除數(shù)據(jù)庫中下載記錄
??Handler 傳輸數(shù)據(jù)
??主線程中創(chuàng)建的 View 只能在主線程中修改,其他線程只能通過和主線程通信,在主線程中改變 View 數(shù)據(jù)
??我們使用 Handler 可以處理這種需求
主線程中創(chuàng)建 Handler ,重寫 handleMessage() 方法
新線程中使用 Handler 發(fā)送消息,主線程即可收到消息,并且執(zhí)行 handleMessage() 方法
??動態(tài)生成新 View
??創(chuàng)建 XML 文件,將要生成的 View 配置好
??獲取系統(tǒng)服務(wù) LayoutInflater ,用來生成新的 View
LayoutInflater?inflater?=?(LayoutInflater)?getSystemService( LAYOUT_INFLATER_SERVICE );
??使用inflate( int ?resource,?ViewGroup?root)方法生成新的 View
??調(diào)用當(dāng)前頁面中某個容器的 addView ,將新創(chuàng)建的 View 添加進來
9.?活動( Activity )
9.1.?創(chuàng)建 Activity
??定義 Activity
??定義類繼承 Activity
??在 AndroidManifest.xml 的 <application> 節(jié)點中聲明 <activity>
??顯式意圖創(chuàng)建方式
??構(gòu)造函數(shù),代碼少
new ?Intent( this ,?NewActivity. class );
??類名形式,靈活,可擴展性強
intent.setClassName( this ,? "cn.itcast.activity.NewActivity" );
??包名類名形式,可啟動其他程序中的 Activity
intent.setClassName( "cn.itcast.downloader" ,? "cn.itcast.downloader.MainActivity" );
??創(chuàng)建 Activity 并傳遞數(shù)據(jù)
??在意圖對象中封裝了一個 Bundle 對象,可以用來攜帶數(shù)據(jù)
??在新 Activity 中可以獲得意圖對象以獲取其中 Bundle 保存的數(shù)據(jù)
??創(chuàng)建 Activity 獲取返回數(shù)據(jù)
??使用startActivityForResult(Intent?intent,? int ?requestCode)?方法打開 Activity
??重寫onActivityResult( int ?requestCode,? int ?resultCode,?Intent?data)?方法
??新 Activity 中調(diào)用 setResult( int ?resultCode,?Intent?data)?設(shè)置返回數(shù)據(jù)之后,關(guān)閉 Activity 就會調(diào)用 onActivityResult方法
??隱式意圖創(chuàng)建 Activity
??顯式意圖是指在創(chuàng)建意圖時指定了組件,而隱式意圖則不指定組件,通過動作、類型、數(shù)據(jù)匹配對應(yīng)的組件
??在清單文件中定義 <activity> 時需要定義 <intent-filter> 才能被隱式意圖啟動
??<intent-filter> 中至少配置一個 <action> 和一個 <category> ,否則無法被啟動
??Intent 對象中設(shè)置的 action 、 category 、 data 在 <intent-filter> 必須全部包含才能啟動
??<intent-filter> 中的 <action> 、 <category> 、 <data> 都可以配置多個, Intent 對象中不用全部匹配,每樣匹配一個即可啟動
??如果一個意圖可以匹配多個 Activity , Android 系統(tǒng)會提示選擇
9.2.?生命周期
??Acitivity 三種狀態(tài)
運行: activity 在最前端運行
暫停: activity 可見,但前端還有其他 acti vity ,被覆蓋一部分,或者前端 activity 透明
停止: activity 不可見,完全被覆蓋
??生命周期相關(guān)方法
onCreate :創(chuàng)建時調(diào)用,或者程序在暫停、停止?fàn)顟B(tài)下被殺死之后重新打開時也會調(diào)用
onStart : onCreate 之后或者從停止?fàn)顟B(tài)恢復(fù)時調(diào)用
onResume : onStart 之后或者從暫停狀態(tài)恢復(fù)時調(diào)用,從停止?fàn)顟B(tài)恢復(fù)時由于調(diào)用 onStart ,也會調(diào)用 onResume
onPause:進入暫停、停止?fàn)顟B(tài),或者銷毀時會調(diào)用
onStop:進入停止?fàn)顟B(tài),或者銷毀時會調(diào)用
onDestroy:銷毀時調(diào)用
onRestart :從停止?fàn)顟B(tài)恢復(fù)時調(diào)用
??保存信息相關(guān)方法
onSaveInstanceState:在 Activity 被動的摧毀或停止的時候調(diào)用,用于保存運行數(shù)據(jù),可以將數(shù)據(jù)存在在 Bundle 中
onRestoreInstanceState:該方法在 Activity 被重新繪制的時候調(diào)用,例如改變屏幕方向, savedInstanceState為onSaveInstanceState保存的數(shù)據(jù)
9.3.?啟動模式
??在 AndroidManifest.xml 中的 <activity> 標(biāo)簽中可以配置 android:launchMode 屬性,用來控制 Actvity 的啟動模式
??在 Android 系統(tǒng)中我們創(chuàng)建的 Acitivity 是以棧的形式呈現(xiàn)的
standard :每次調(diào)用 startActivity() 啟動時都會創(chuàng)建一個新的 Activity 放在棧頂
singleTop :如果啟動的 Activity 時,指定 Activity 不在棧頂就創(chuàng)建,如在棧頂,則不再創(chuàng)建
singleTask :如果啟動的 Activity 不存在就創(chuàng)建,如果存在直接跳轉(zhuǎn)到指定的 Activity 所在位置
singleInstance :如果啟動的 Activity 不存在就創(chuàng)建,如果存在就將指定的 Activity 移動到棧頂
9.4.?內(nèi)存管理
??Android 系統(tǒng)在運行多個進程時,如果系統(tǒng)資源不足,會強制結(jié)束一些進程。優(yōu)先選擇哪個進程來結(jié)束是有優(yōu)先級的。以下順序靠上的優(yōu)先結(jié)束
空:進程中所有 Activity 都已銷毀
后臺:進程中有一個停止?fàn)顟B(tài)的 Activity
可見:進程中有一個暫停狀態(tài)的 Activity
前臺:進程中正在運行一個 Activity
10.?廣播接收者 (BroadcastReceiver)
10.1.?定義廣播接收者
??定義類繼承 BroadcastReceiver ,重寫 onReceive 方法
??清單文件中聲明<receiver>,需要在其中配置<intent-filter>指定接收廣播的動作
??當(dāng)接收到匹配廣播之后就會執(zhí)行 onReceive 方法
??BroadcastReceiver 除了在清單文件中聲明,也可以在代碼中聲明,使用 registerReceiver方法注冊 Receiver
10.2.?發(fā)送廣播
??無序廣播
??使用sendBroadcast方法發(fā)送
??被所有廣播接收者接收,無序,不可中斷
??廣播時可設(shè)置接收者權(quán)限,僅當(dāng)接收者含有權(quán)限才能接收
??接收者的<receiver>也可設(shè)置發(fā)送方權(quán)限,只接收含有權(quán)限應(yīng)用的廣播
??有序廣播
??使用sendOrderedBroadcast方法發(fā)送
??接收者可以在<intent-filter>中定義android:priority定義優(yōu)先級,數(shù)字越大優(yōu)先級越高
??被各個廣播接收者逐個接收,中途可以中斷或者添加數(shù)據(jù)
abortBroadcast()??
getResultExtras( true ).putString( "data" ,? " 新增數(shù)據(jù) " );
10.3.?監(jiān)聽短信接收
??Android 系統(tǒng)在收到短信的時候會發(fā)送一條有序廣播,我們?nèi)绻x一個接收者接收這個廣播,就可以得到短信內(nèi)容,也可以攔截短信
??定義廣播接收者接收廣播 android.provider.Telephony.SMS_RECEIVED
??在 onReceive 方法內(nèi)部調(diào)用 Intent 的 getExtras() 再調(diào)用 get(String) 獲取其中 pdus 字段,得到一個 Object[],其中每一個元素都是一個 byte[]
??通過SmsMessage類的createFromPdu方法創(chuàng)建 SmsMessage 對象
??從 SmsMessage 對象中即可獲取發(fā)送者號碼、短信內(nèi)容、發(fā)送時間等信息
??需要接收短信權(quán)限: < uses-permission? android:name ="android.permission.RECEIVE_SMS" />
??Android 系統(tǒng)中收到短信的通知是一個有序通知,我們?nèi)缧钄r截垃圾短信,可以配置較高的 priority,收到信息進行判斷是否abortBroadcast()
10.4.?監(jiān)聽呼出電話
??定義廣播接收者接收? android.intent.action.NEW_OUTGOING_CALL
??需要權(quán)限? < uses-permission? android:name = "android.permission.PROCESS_OUTGOING_CALLS" />
??在 onReceive 方法中使用 getResultData()?和? setResultData()? 方法獲取和設(shè)置電話號碼
10.5.?生命周期
??廣播接收者的生命周期是非常短暫的,在接收到廣播的時候創(chuàng)建, onReceive() 方法結(jié)束之后銷毀
??廣播接收者中不要做一些耗時的工作,否則會彈出 Application?No?Response 錯誤對話框
??最好也不要在廣播接收者中創(chuàng)建子線程做耗時的工作,因為廣播接收者被銷毀后進程就成為了空進程,很容易被系統(tǒng)殺掉
??耗時的較長的工作最好放在服務(wù)中完成
11.?服務(wù) (Service)
11.1.?基本概念
??Service 是一種在后臺運行,沒有界面的組件,由其他組件調(diào)用開始。
??創(chuàng)建 Service ,定義類繼承 Service , AndroidManifest.xml 中定義 <service>
??開啟 Service ,在其他組件中調(diào)用 startService方法
??停止 Service ,調(diào)用 stopService方法
11.2.?電話錄音
需要權(quán)限: android.permission.READ_PHONE_STATE
TelephonyManager?manager?=?(TelephonyManager)?getSystemService( TELEPHONY_SERVICE );
manager.listen( new ?MyListener(),?PhoneStateListener. LISTEN_CALL_STATE );
private ? final ? class ?MyListener? extends ?PhoneStateListener?{
private ?String? num ;
private ?MediaRecorder? recorder ;
public ? void ?onCallStateChanged( int ?state,?String?incomingNumber)?{
switch ?(state)?{
case ?TelephonyManager. CALL_STATE_RINGING :
num ?=?incomingNumber;
break ;
case ?TelephonyManager. CALL_STATE_OFFHOOK :
try ?{
File? file ?=? new ?File(Environment.getExternalStorageDirectory(),? num ?+? "_" ?+?System.currentTimeMillis()?+? ".3gp" );
recorder ?=? new ?MediaRecorder();
recorder .setAudioSource(AudioSource. MIC );
recorder .setOutputFormat(OutputFormat. THREE_GPP );
recorder .setAudioEncoder(AudioEncoder. AMR_NB );
recorder .setOutputFile( file .getAbsolutePath());
recorder .prepare();
recorder .start();
}? catch ?(Exception?e)?{
e.printStackTrace();
}
break ;
case ?TelephonyManager. CALL_STATE_IDLE :
if ?( recorder ?!=? null )?{
recorder .stop();
recorder .release();
}
break ;
}
}
}
11.3.?綁定本地服務(wù)
??使用bindService綁定服務(wù),傳入一個自定義的ServiceConnection用來接收 IBinder
??定義一個業(yè)務(wù)接口,其中定義需要的使用的方法
??服務(wù)中自定義一個 IBinder 繼承 Binder 并實現(xiàn)業(yè)務(wù)接口,在 onBind方法中返回
??調(diào)用端將 IBinder 轉(zhuǎn)為接口類型,調(diào)用接口中的方法即可調(diào)用到服務(wù)中的方法
11.4.?綁定遠程服務(wù)
??遠程綁定服務(wù)時無法通過同一個接口來調(diào)用方法,這時就需要使用 AIDL 技術(shù)
??將接口擴展名改為“.aidl”
??去掉權(quán)限修飾符
??gen 文件夾下會生成同名接口
??將服務(wù)中自定義的 IBinder 類改為繼承接口中的 S tub
??ServiceConnection中返回的 IBinder 是代理對象,不能使用強轉(zhuǎn),改用 S tub.asInterface()
11.5.?AIDL 使用自定義類型
??AIDL 默認只能使用 Java 中基本數(shù)據(jù)類型和 String 、 List 、 Map , List 和 Map 中的元素類型也只能是這些類型。
??如果需要使用其他類型數(shù)據(jù),使用的類必須實現(xiàn) Parcelable 接口以完成序列化和反序列化工作
重寫?public?void?writeToParcel(Parcel?dest,?int?flags)
定義?public?static?final?Parcelable.Creator<Person>? CREATOR
??定義該類對應(yīng)的 AIDL
package? 包名
parcelable? 類名
??在接口 AIDL 中導(dǎo)入該類,注意:即使是同一個包也需要導(dǎo)入
12.?多媒體
12.1.?音頻播放器
12.2.?視頻播放器
screenSV .getHolder().setType(SurfaceHolder. SURFACE_TYPE_PUSH_BUFFERS );? //? 設(shè)置緩沖區(qū)數(shù)據(jù)
screenSV .getHolder().setKeepScreenOn( true );? //? 設(shè)置屏幕保持
screenSV .getHolder().addCallback( new ?MyCallback());? //? 設(shè)置回調(diào)函數(shù)
player .reset();
player .setDisplay( screenSV .getHolder()); //? 設(shè)置顯式
player .setDataSource( "/mnt/sdcard/1.mp4" ); //? 設(shè)置數(shù)據(jù)源
player .prepare(); //? 準(zhǔn)備
player .seekTo(position); //? 跳轉(zhuǎn)到指定位置
player .start();
12.3.?拍照
??需要權(quán)限
< uses-permission? android:name = "android.permission.CAMERA"? />
??打開攝像頭
Camera.open()
SDK2.3 之后支持前置攝像頭, open 方法可以接收一個 int 參數(shù),用來指定哪個攝像頭
??設(shè)置預(yù)覽顯示位置
setPreviewDisplay(SurfaceHolder?holder)
注意 SurfaceView 不在前端顯示的時候會被銷毀,恢復(fù)之后會重繪
??開始預(yù)覽?
startPreview()
將攝像頭拍攝畫面顯示在 SurfaceView 中,在此之前可對攝像頭進行參數(shù)配置
getParameters()?方法可以獲取攝像頭的相關(guān)參數(shù)Parameters,調(diào)用其內(nèi)部方法即可進行配置
??自動對焦
autoFocus(AutoFocusCallback?cb)
自動對焦是一個異步操作,如果我們向等待自動對焦結(jié)束之后才開始拍照,需要傳入一個回調(diào)對象,在其回調(diào)函數(shù)中調(diào)用拍照方法
??拍照?
takePicture(ShutterCallback?shutter,?PictureCallback?raw,?PictureCallback?jpeg)
拍照也是異步操作,需要通過回調(diào)函數(shù)來得到拍照之后的數(shù)據(jù)
注意拍照之后攝像頭不回自動回到預(yù)覽狀態(tài),需要重寫調(diào)用startPreview()方法
12.4.?錄像
??需要權(quán)限
< uses-permission? android:name = "android.permission.RECORD_AUDIO" />
< uses-permission? android:name = "android.permission.CAMERA" />
??創(chuàng)建MediaRecorder
new ?MediaRecorder()
??設(shè)置音頻輸入源
setAudioSource( int ?audio_source)
??設(shè)置視頻輸入源
setVideoSource( int ?video_source)
??設(shè)置輸出格式
setOutputFormat( int ?output_format)
??設(shè)置音頻編碼器
setAudioEncoder( int ?audio_encoder)
??設(shè)置視頻編碼器
setVideoEncoder( int ?video_encoder)
??設(shè)置預(yù)覽顯示位置
setPreviewDisplay(Surface?sv)
??設(shè)置輸出文件
setOutputFile(String?path)
??準(zhǔn)備錄制
prepare()
??開始錄制
start()
開始錄制之前需要結(jié)束攝像頭的預(yù)覽
??結(jié)束錄制釋放資源
stop()
release()
13.?通知
13.1.?吐司通知
??創(chuàng)建通知
Toast.makeText(Context?context,?CharSequence?text,? int ?duration)
Toast.makeText(Context?context,? int ?resId,? int ?duration)
??發(fā)送通知
show()
13.2.?狀態(tài)欄通知
??獲取系統(tǒng)通知服務(wù)?
NotificationManager?nm?=?(NotificationManager)?getSystemService( NOTIFICATION_SERVICE )
??創(chuàng)建通知
通過構(gòu)造函數(shù)創(chuàng)建 :? Notification( int ?icon,?CharSequence?tickerText,? long ?when)
icon:? 通知的圖片資源 ID
tickerText:? 狀態(tài)欄中顯示的消息內(nèi)容
when:? 時間
??創(chuàng)建PendingIntent以供點擊時發(fā)送
PendingIntent.getActivity(Context?context,? int ?requestCode,?Intent?intent,? int ?flags)
context:? 當(dāng)前上下文
requestCode:? 請求碼
intent:? 點擊時要發(fā)送的意圖
flags:? 類型 ,? PendingIntent中提供了常量選擇
??設(shè)置通知點擊事件
調(diào)用Notification?對象方法 :? setLatestEventInfo(Context?context,?CharSequence?contentTitle,?CharSequence?contentText,?PendingIntent?contentIntent)
context:? 當(dāng)前上下文
contentTitle:? 標(biāo)題
contentText:?內(nèi)容
contentIntent:? 點擊時觸發(fā)的意圖
??設(shè)置通知點擊后清除
設(shè)置Notification?對象屬性?n. flags ?=?Notification. FLAG_AUTO_CANCEL ;
??發(fā)送消息
調(diào)用Notification對象方法 :? notify( int ?id,?Notification?notification)
13.3.?對話框通知
??普通對話框
new ?AlertDialog.Builder( this )? //
.setTitle( " 普通對話框 " )? //
.setMessage( " 普通內(nèi)容 " )? //
.setCancelable( false )? //
.setPositiveButton( "YES" ,?listener)? // ? listener?為 OnClickListener? 監(jiān)聽器對象 ,? 監(jiān)聽按鈕被選中
.setNeutralButton( "CANCEL" ,?listener)? //
.setNegativeButton( "NO" ,?listener)? //
.show();
??列表對話框
new ?AlertDialog.Builder( this )? //
.setTitle( " 列表對話框 " )? //
.setCancelable( false )? //
.setItems( items ,?listener)? // ? listener?為 OnClickListener? 監(jiān)聽器對象 ,? 監(jiān)聽列表項被選中
.show();
??單選對話框
new ?AlertDialog.Builder( this )? //
.setTitle( " 單選對話框 " )? //
.setCancelable( false )? //
.setSingleChoiceItems( items ,?0,?choiceLinstener)? // ? 0,? 為默認選中索引 ,? choiceLinstener?為? OnClickListener? 監(jiān)聽器對象 ,? 監(jiān)聽單選按鈕被選中
.setPositiveButton( " 確定 " ,?positiveLinstener)? // ? positiveLinstener?為? OnClickListener? 監(jiān)聽器對象 ,? 監(jiān)聽確定按鈕點擊
.show();
??多選對話框
new ?AlertDialog.Builder( this )? //
.setTitle( " 多選對話框 " )? //
.setCancelable( false )? //
.setMultiChoiceItems( items ,?checkedArr,?choiceListener)? // ? checkedArr?為默認選中 ,? choiceListener?為? OnMultiChoiceClickListener? 監(jiān)聽器對象 ,? 監(jiān)聽多選按鈕被選中
.setPositiveButton( " 確定 " ,?positiveLinstener)? // ? positiveLinstener?為? OnClickListener? 監(jiān)聽器對象 ,? 監(jiān)聽確定按鈕點擊
.show();
??進度對話框
ProgressDialog?dialog?=? new ?ProgressDialog( this );
dialog.setProgressStyle(ProgressDialog. STYLE_HORIZONTAL ); //?設(shè)置進度條樣式
dialog.setTitle( " 下載中 " );
dialog.setMessage( " 請稍候 ..." );
dialog.setCancelable( false );
dialog.setMax(100);
dialog.show();
dialog.setProgress(10); //? 設(shè)置進度
dialog.dismiss(); //? 對話框結(jié)束
關(guān)于通知的文檔位置: android-sdk-windows/docs/guide/topics/ui/notifiers/index.html
14.?常用 UI
14.1.?列表視圖 (ListView)
??XML 配置
??在主界面中配置 <ListView> 標(biāo)簽
??在 res/layout/ 文件夾下創(chuàng)建一個新的 xml 文件指定每個條目的布局
??Java 代碼構(gòu)建 ListView
??獲取 ListView 對象
??設(shè)置一個 Adapter
BaseAdapter :實現(xiàn)內(nèi)部抽象方法
SimpleAdapter:以 List<Map<String,??>> 形式封裝數(shù)據(jù)
SimpleCursorAdapter:以 Cursor 對象封裝數(shù)據(jù), Cursor 中需要有“ _id ”一列
??添加 OnItemClickListener
調(diào)用 ListView 的 getItemAtPosition(int) 方法可以獲取封裝數(shù)據(jù)的容器
如果傳入的是 BaseAdapter ,獲取到的就是我們自定義方法中返回的內(nèi)容
如果傳入的是SimpleAdapter,獲取到的就是一個 Map<String,??>
如果傳入的是SimpleCursorAdapter,獲得到的就是一個 Cursor ,并且 Cursor 以指向選中的一條記錄
14.2.?單選 (RadioGroup)
??定義 <RadioGroup>
??在 <RadioGroup> 中定義 <RadioButton> 和 <Button>
??處理 Button 的點擊事件
??根據(jù) ID 獲取 RadioGroup 對象,調(diào)用其 getCheckedRadioButtonId()方法可以獲取其中被選中的RadioGroup 的 ID
??代碼
< RadioGroup
???? android:id = "@+id/lessonsRG"
???? android:layout_width = "fill_parent"
???? android:layout_height = "wrap_content"
???? android:orientation = "horizontal" ? >
???? < RadioButton
???????? android:id = "@+id/javaRB"
???????? android:layout_width = "fill_parent"
???????? android:layout_height = "wrap_content"
???????? android:layout_weight = "1"
???????? android:text = "Java" ? />
???? < RadioButton
???????? android:id = "@+id/netRB"
???????? android:layout_width = "fill_parent"
???????? android:layout_height = "wrap_content"
???????? android:layout_weight = "1"
???????? android:text = ".Net" ? />
???? < RadioButton
???????? android:id = "@+id/phpRB"
???????? android:layout_width = "fill_parent"
???????? android:layout_height = "wrap_content"
???????? android:layout_weight = "1"
???????? android:text = "PHP" ? />
???? < Button
???????? android:layout_width = "fill_parent"
???????? android:layout_height = "wrap_content"
???????? android:layout_weight = "1"
???????? android:onClick = " onR radioClick"
???????? android:text = " 確定 " ? />
</ RadioGroup >
public ? void ?onRradioClick(View?view)?{
RadioGroup?lessonRG?=?(RadioGroup)?findViewById(R.id. lesson s RG );
int ?id?=?lessonRG.getCheckedRadioButtonId();? //? 獲取選中的 id
String?msg?=? null ;
switch ?(id)?{
case ?R.id. javaRB :
msg?=? "Java" ;
break ;
case ?R.id. netRB :
msg?=? ".Net" ;
break ;
case ?R.id. phpRB :
msg?=? "PHP" ;
break ;
}
Toast.makeText( this ,?msg,?0).show();
}
14.3.?多選 (CheckBox)
??定義若干 <CheckBox> 和一個 <Button>
??處理 Button 的點擊事件
??根據(jù) ID 獲取每個 CheckBox ,調(diào)用其 isChecked()方法判斷是否被選中
??代碼
< LinearLayout
???? android:layout_width = "fill_parent"
???? android:layout_height = "wrap_content" ? >
???? < CheckBox
???????? android:id = "@+id/javaCB"
???????? android:layout_width = "fill_parent"
???????? android:layout_height = "wrap_content"
???????? android:layout_weight = "1"
???????? android:text = "Java" ? />
???? < CheckBox
???????? android:id = "@+id/netCB"
???????? android:layout_width = "fill_parent"
???????? android:layout_height = "wrap_content"
???????? android:layout_weight = "1"
???????? android:text = ".Net" ? />
???? < CheckBox
???????? android:id = "@+id/phpCB"
???????? android:layout_width = "fill_parent"
???????? android:layout_height = "wrap_content"
???????? android:layout_weight = "1"
???????? android:text = "PHP" ? />
???? < Button
???????? android:layout_width = "fill_parent"
???????? android:layout_height = "wrap_content"
???????? android:layout_weight = "1"
???????? android:onClick = "checkboxOnClick"
???????? android:text = " 確定 " ? />
</ LinearLayout >
public ? void ?checkboxOnClick(View?view)?{
CheckBox?javaCB?=?(CheckBox)?findViewById(R.id. javaCB );
CheckBox?netCB?=?(CheckBox)?findViewById(R.id. netCB );
CheckBox?phpCB?=?(CheckBox)?findViewById(R.id. phpCB );
StringBuilder?sb?=? new ?StringBuilder();
sb.append(javaCB.isChecked()???javaCB.getText()?+? "?" ?:? "" );
sb.append(netCB.isChecked()???netCB.getText()?+? "?" ?:? "" );
sb.append(phpCB.isChecked()???phpCB.getText()?+? "?" ?:? "" );
Toast.makeText( this ,?sb,?0).show();
}
14.4.?下拉列表 ( Spinner )
??定義 <Spinner> 標(biāo)簽
??創(chuàng)建一個適配器
??獲取 Spinner 標(biāo)簽,調(diào)用 setAdapter(SpinnerAdapter?adapter)方法設(shè)置一個適配器
??調(diào)用setOnItemSelectedListener(OnItemSelectedListener?listener)方法設(shè)置監(jiān)聽器監(jiān)聽選中事件
??XML 配置
< Spinner
???? android:id = "@+id/spinner"
???? android:layout_width = "fill_parent"
???? android:layout_height = "wrap_content" ? />
??使用字符串構(gòu)建適配器
private ? void ?setSpinnerByString()?{
final ?Spinner?spinner?=?(Spinner)?findViewById(R.id. spinner );
ArrayAdapter<String>?adapter?=? new ?ArrayAdapter<String>( this ,?android.R.layout. simple_spinner_item );? // ? 設(shè)置樣式
adapter.setDropDownViewResource(android.R.layout. simple_spinner_dropdown_item ); //? 設(shè)置下拉后樣式
adapter.add( "Java" );
adapter.add( ".Net" );
adapter.add( "PHP" );
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener( new ?OnItemSelectedListener()?{
public ? void ?onItemSelected(AdapterView<?>?parent,?View?view,? int ?position,? long ?id)?{
String?selection?=?(String)?spinner.getItemAtPosition(position);
Toast.makeText(getApplicationContext(),?selection,?0).show();
}
public ? void ?onNothingSelected(AdapterView<?>?parent)?{
}
});
}
??使用 JavaBean 構(gòu)建適配器
private ? void ?setSpinnerByJavaBean()?{
final ?Spinner?spinner?=?(Spinner)?findViewById(R.id. spinner );
ArrayAdapter<User>?adapter?=? new ?ArrayAdapter<User>( this ,?android.R.layout. simple_spinner_item );
adapter.setDropDownViewResource(android.R.layout. simple_spinner_dropdown_item );
adapter.add( new ?User(1,? "lhm" ,? "lhm@itcast.cn" ));
adapter.add( new ?User(2,? "yzk" ,? "yzk@itcast.cn" ));
adapter.add( new ?User(3,? "hsp" ,? "hsp@itcast.cn" ));
spinner .setAdapter(adapter);
spinner .setOnItemSelectedListener( new ?OnItemSelectedListener()?{
public ? void ?onItemSelected(AdapterView<?>?parent,?View?view,? int ?position,? long ?id)?{
User?selection?=?(User)? spinner .getItemAtPosition(position);
Toast.makeText(getApplicationContext(),?selection.getName(),?0).show();
}
public ? void ?onNothingSelected(AdapterView<?>?parent)?{
}
});
}
??使用資源文件構(gòu)建適配器
< string-array ? name = "items" >
???? < item > Java </ item >
???? < item > .Net </ item >
???? < item > PHP </ item >
</ string-array >
private ? void ?setSpinnerByResource()?{
final ?Spinner?spinner?=?(Spinner)?findViewById(R.id. spinner );
ArrayAdapter<CharSequence>?adapter?=?ArrayAdapter.createFromResource( this ,?R.array. items ,?android.R.layout. simple_spinner_item );
adapter.setDropDownViewResource(android.R.layout. simple_spinner_dropdown_item );
spinner .setAdapter(adapter);
spinner .setOnItemSelectedListener( new ?OnItemSelectedListener()?{
public ? void ?onItemSelected(AdapterView<?>?parent,?View?view,? int ?position,? long ?id)?{
CharSequence?selection?=?(CharSequence)? spinner .getItemAtPosition(position);
Toast.makeText(getApplicationContext(),?selection,?0).show();
}
public ? void ?onNothingSelected(AdapterView<?>?parent)?{
}
});
}
??自定義適配器樣式
<? xml ? version = "1.0" ? encoding = "utf-8" ?>
< LinearLayout ? xmlns:android = "http://schemas.android.com/apk/res/android"
???? android:layout_width = "match_parent"
???? android:layout_height = "match_parent"
???? android:orientation = "horizontal" ? >
???? < ImageView
???????? android:layout_width = "50dp"
???????? android:layout_height = "50dp"
???????? android:src = "@android:drawable/ic_delete" ? />
???? < TextView
???????? android:id = "@+id/content"
???????? android:layout_width = "fill_parent"
???????? android:layout_height = "wrap_content"
???????? android:textSize = "50sp" ? />
</ LinearLayout >
private ? void ?setSpinnerByCustom()?{
final ?Spinner?spinner?=?(Spinner)?findViewById(R.id. spinner );
ArrayAdapter<CharSequence>?adapter?=? new ?ArrayAdapter<CharSequence>( this ,?R.layout. item ,?R.id. content );
adapter.add( "Java" );
adapter.add( ".Net" );
adapter.add( "PHP" );
spinner .setAdapter(adapter);
spinner .setOnItemSelectedListener( new ?OnItemSelectedListener()?{
public ? void ?onItemSelected(AdapterView<?>?parent,?View?view,? int ?position,? long ?id)?{
String?selection?=?(String)? spinner .getItemAtPosition(position);
Toast.makeText(getApplicationContext(),?selection,?0).show();
}
public ? void ?onNothingSelected(AdapterView<?>?parent)?{
}
});
}
14.5.?菜單 (Menu)
??添加菜單項
??重寫 Actvity 的 onCreateOptionsMenu(Menu?menu)方法
??添加菜單項
調(diào)用方法中參數(shù) menu 的 add(CharSequence?title)?方法
??添加子菜單
調(diào)用 menu 對象的 addSubMenu( final ?CharSequence?title)
該方法返回一個SubMenu對象
??添加子菜單的菜單項
調(diào)用SubMenu對象的add(CharSequence?title)?方法
??處理菜單點擊事件
??重寫 Activity 的 onOptionsItemSelected(MenuItem?item)?方法
參數(shù) item 即為被選中的菜單項
??代碼
public ? boolean ?onCreateOptionsMenu(Menu?menu)?{
menu.add( " 增加 " );
menu.add( " 修改 " );
menu.add( " 刪除 " );
SubMenu?subMenu?=?menu.addSubMenu( " 查詢 " );
subMenu.add( " 按照序號查詢 " );
subMenu.add( " 按照姓名查詢 " );
subMenu.add( " 按照郵箱查詢 " );
return ? super .onCreateOptionsMenu(menu);
}
public ? boolean ?onOptionsItemSelected(MenuItem?item)?{
Toast.makeText( this ,?item.getTitle(),?0).show();
return ? super .onOptionsItemSelected(item);
}
14.6.?內(nèi)容提示文本框 ( AutoCompleteTextView)
??單次提示
??代碼
< AutoCompleteTextView
???? android:id = "@+id/actv"
???? android:layout_width = "fill_parent"
???? android:layout_height = "wrap_content"
???? android:completionThreshold = "1" ? />
private ? void ?setAutoCompleteTextView()?{
AutoCompleteTextView?actv?=?(AutoCompleteTextView)?findViewById(R.id. actv );
String[]?items?=?{? "tom" ,? "tony" ,? "terry" ,? " 張孝祥 " ,? " 張海軍 " ,? " 張澤華 " ?};
ArrayAdapter<String>?adapter?=? new ?ArrayAdapter<String>( this ,?android.R.layout. simple_dropdown_item_1line ,?items);
actv.setAdapter(adapter);
}
??多次提示
??代碼
< MultiAutoCompleteTextView
???? android:id = "@+id/mactv"
???? android:layout_width = "fill_parent"
???? android:layout_height = "wrap_content"
android:completionThreshold = "1" ? />
private ? void ?setMultiAutoCompleteTextView()?{
MultiAutoCompleteTextView?mactv?=?(MultiAutoCompleteTextView)?findViewById(R.id. mactv );
String[]?items?=?{? "tom" ,? "tony" ,? "terry" ,? " 張孝祥 " ,? " 張海軍 " ,? " 張澤華 " ?};
ArrayAdapter<String>?adapter?=? new ?ArrayAdapter<String>( this ,?android.R.layout. simple_dropdown_item_1line ,?items);
mactv.setAdapter(adapter);
mactv.setTokenizer( new ?MultiAutoCompleteTextView.CommaTokenizer());
}
14.7.?手勢識別 ( GestureOverlayView)
??創(chuàng)建手勢庫
??導(dǎo)入 SDK 中的工程
android-sdk-windows\samples\android-8\GestureBuilder
這個工程不能直接導(dǎo)入,需要添加三個配置文件:.classpath、.project、default.properties
??將工程部署到手機中,創(chuàng)建手勢庫
手勢庫會存儲在手機 SD 卡的根目錄,文件名為: gestures
??代碼
將gestures放入 res/raw 文件夾下
< android.gesture.GestureOverlayView
???? android:id = "@+id/gov"
???? android:layout_width = "fill_parent"
???? android:layout_height = "fill_parent"
android:gestureStrokeType = "multiple" ? />
GestureOverlayView?gov?=?(GestureOverlayView)?findViewById(R.id. gov );
final ?GestureLibrary?library?=?GestureLibraries.fromRawResource( this ,?R.raw. gestures );
library.load();
gov.addOnGesturePerformedListener( new ?OnGesturePerformedListener()?{
public ? void ?onGesturePerformed(GestureOverlayView?overlay,?Gesture?gesture)?{
ArrayList<Prediction>?list?=?library.recognize(gesture);
for ?(Prediction?p?:?list)
System. out .println(p. name ?+? ":?" ?+?p. score );
}
});
14.8.?網(wǎng)頁視圖 (WebView)
??代碼
< WebView
???? android:id = "@+id/webView"
???? android:layout_width = "fill_parent"
???? android:layout_height = "fill_parent" ? />
WebView?webView?=?(WebView)?findViewById(R.id. webView );
webView.getSettings().setBuiltInZoomControls( true ); //? 放大縮小按鈕
webView.getSettings().setJavaScriptEnabled( true ); //?JS 允許?
webView.setWebChromeClient( new ?WebChromeClient()); //?Chrome 內(nèi)核
webView.loadUrl( "http://192.168.1.10 0 :8080" );
15.?樣式與主題
15.1.?樣式
??定義樣式
??設(shè)置樣式,在 values 文件夾下的任意文件中的 <resources>中配置 <style> 標(biāo)簽
< style? name = " style 1" >
< item? name = "android:layout_width" > fill_parent </ item >
< item? name = "android:layout_height" > wrap_content </ item >
</ style >
??繼承樣式,在 <style> 標(biāo)簽中配置屬性 parent
< style? name = " style2 "? parent = "@style/ style 1" >
< item? name = "android:textColor" > #FF0000 </ item >
</ style >
??繼承樣式,在 name 中引用其他樣式
< style? name = " style 2. style 3" >
< item? name = "android:textSize" > 30sp </ item >
</ style >
??使用樣式
??在 layout 文件的標(biāo)簽中配置 style 屬性
< Button??
style = "@style/ style2.style3 "
???? android:text = " 這是 一個按鈕 "
/>
15.2.?主題
??定義過的樣式也可以應(yīng)用在 <activity> 和 <application> 標(biāo)簽中,使用 theme屬性盡心配置
< style? name = "theme" >
< item? name = "android:windowNoTitle" > true </ item >
< item? name = "android:windowFullscreen" > ?android:windowNoTitle </ item >
</ style >
< activity? android:name = ".MainActivity"
?????????????????? android:label = "@string/app_name"
?????????????????? android:theme = "@style/theme"
>
???? 表示引用其他屬性的值
??@? 表示訪問資源文件
??如果使用 android 內(nèi)置的樣式, IDE 自動提示的“ _ ”要替換成“ . ”
16.?國際化與屏幕適配
16.1.?國際化
??在 values 和 drawable 文件夾后加上語言以及地區(qū)名,程序中需要國際化的部分使用資源 ID
values-en-rUK
values-en-rUS
values-zh-rCN
values-zh-rTW
??匹配規(guī)則
在匹配資源時先會找語言、地區(qū)完全匹配的
如果沒有地區(qū)匹配的,則查找語言匹配的
如果沒有語言匹配的則找默認 values
16.2.?屏幕適配
??在 layout 文件夾后加上分辨率,系統(tǒng)會根據(jù)屏幕尺寸自動選擇
注意分辨率中的乘號是“ x ”不是“ * ”
??如果沒有匹配的分辨率會找默認 layout 文件夾
17.?動畫特效
17.1.?Frame
??通過多個畫面連續(xù)播放實現(xiàn)動畫效果
??詳見文檔?android-sdk-windows/docs/guide/topics/resources/animation-resource.html
17.2.?Tween
??將某個組件以漸變的方式實現(xiàn)透明、縮放、移動、旋轉(zhuǎn)等動畫效果
??詳見文檔?android-sdk-windows/docs/guide/topics/resources/animation-resource.html
17.3.?使用動畫切換 Activity
??在 startActivity() 方法調(diào)用之后調(diào)用 overridePendingTransition( int ?enterAnim,? int ?exitAnim)方法
enterAnim?進入的動畫資源 id
exitAnim?退出的動畫 資源 id
17.4.?使用動畫翻頁
??XML 配置
< ViewFlipper
android:id = "@+id/viewFlipper"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
>
??? < ImageView
???? android:layout_width = "wrap_content"
???? android:layout_height = "wrap_content"
??? android:src = "@drawable/bb2"
??? />
??? < ImageView
???? android:layout_width = "wrap_content"
???? android:layout_height = "wrap_content"
??? android:src = "@drawable/bb3"
??? />
</ ViewFlipper >
??Java 代碼
public ? boolean ?onTouchEvent(MotionEvent?event)?{
ViewFlipper?viewFlipper?=?(ViewFlipper)?findViewById(R.id. viewFlipper );
switch ?(event.getAction())?{
case ?MotionEvent. ACTION_DOWN :
start ?=?event.getX();
break ;
case ?MotionEvent. ACTION_UP :
float ?end?=?event.getX();
if ?(end?>? start )?{
viewFlipper .setInAnimation( this ,?R.anim. previous_enter );
viewFlipper .setOutAnimation( this ,?R.anim. previous_exit );
viewFlipper .showPrevious();
}? else ? if ?(end?<? start )?{
viewFlipper .setInAnimation( this ,?R.anim. next_enter );
viewFlipper .setOutAnimation( this ,?R.anim. next_exit );
viewFlipper .showNext();
}
break ;
}
return ? super .onTouchEvent(event);
}
18.?其他
18.1.?傳感器
??傳感器參數(shù)
??傳感器類型
方向 Sensor. TYPE_ORIENTATION
加速 Sensor. TYPE_ACCELEROMETER
光線 Sensor. TYPE_LIGHT
磁場 Sensor. TYPE_MAGNETIC_FIELD
距離 Sensor. TYPE_PROXIMITY
溫度 Sensor. TYPE_TEMPERATURE
??傳感器反應(yīng)速度
SensorManager. SENSOR_DELAY_FASTEST
SensorManager. SENSOR_DELAY_GAME
SensorManager. SENSOR_DELAY_UI
SensorManager. SENSOR_DELAY_NORMAL
??使用方向傳感器
??獲得傳感器管理器
SensorManager?manager?=?(SensorManager)?getSystemService( SENSOR_SERVICE );
??獲得方向傳感器
Sensor?sensor?=?manager.getDefaultSensor(Sensor. TYPE_ORIENTATION );
??注冊監(jiān)聽器
manager .registerListener( listener ,? sensor ,?SensorManager. SENSOR_DELAY_NORMAL );
??監(jiān)聽器
private ? final ? class ?MySensorEventListener? implements ?SensorEventListener?{
public ? void ?onSensorChanged(SensorEvent?event)?{
System. out .println(event. values [0]);
}
public ? void ?onAccuracyChanged(Sensor?sensor,? int ?accuracy)?{
}
}
??取消監(jiān)聽器
manager .unregisterListener( listener ,? sensor );
18.2.?觸摸事件
??拖拽
??XML 配置
< ImageView
???? android:id = "@+id/image"
???? android:layout_width = "wrap_content"
???? android:layout_height = "wrap_content"
???? android:scaleType = "matrix"
???? android:src = "@drawable/image" ? />
??Java代碼
ImageView?imageView?=?(ImageView)?findViewById(R.id. image );
imageView.setOnTouchListener( new ?MyOnTouchListener());
private ? class ?MyOnTouchListener? implements ?OnTouchListener?{
private ? float ? x ;
private ? float ? y ;
private ?Matrix? currentMatrix ?=? new ?Matrix(); //? 用來操作圖片的矩陣
private ?Matrix? oldMatrix ?=? new ?Matrix();
public ? boolean ?onTouch(View?v,?MotionEvent?event)?{
switch ?(event.getAction())?{
case ?MotionEvent. ACTION_DOWN :? //? 按下時
x ?=?event.getX();? //? 獲取 x 軸坐標(biāo)
y ?=?event.getY(); //? 獲取 y 軸坐標(biāo)
oldMatrix .set( imageView .getImageMatrix()); //? 記住位置
break ;
case ?MotionEvent. ACTION_MOVE :? //? 移動時
currentMatrix .set( oldMatrix );? //? 設(shè)置成按下時記住的位置
currentMatrix .postTranslate(event.getX()?-? x ,?event.getY()?-? y ); //? 改變位置
break ;
}
imageView .setImageMatrix( currentMatrix ); //? 移動圖片
return ? true ;
}
}
??多點觸摸
private ? class ?MyOnTouchListener? implements ?OnTouchListener?{
private ? float ? x ; //? 圖片移動前的 x 軸坐標(biāo)
private ? float ? y ; //? 圖片移動前的 y 軸坐標(biāo)
private ?Matrix? currentMatrix ?=? new ?Matrix();? //? 用來移動圖片的矩陣
private ?Matrix? oldMatrix ?=? new ?Matrix(); //? 圖片移動前的矩陣
private ? int ? type ; //? 操作類型 ,? 一根手指觸摸還是兩根手指觸摸
private ? float ? start ; //? 第二根手指按下時的距離
private ? float ? end ; //? 兩根手指移動后的距離
private ?PointF? point ; //? 放大時的中心點
public ? boolean ?onTouch(View?v,?MotionEvent?event)?{
switch ?(event.getAction()?&?MotionEvent. ACTION_MASK )?{
case ?MotionEvent. ACTION_DOWN :
type ?=?1;
x ?=?event.getX();
y ?=?event.getY();
oldMatrix .set( imageView .getImageMatrix());
break ;
case ?MotionEvent. ACTION_MOVE :
currentMatrix .set( oldMatrix );
if ?( type ?==?1)?{? //?1 根手指觸摸
currentMatrix .postTranslate(event.getX()?-? x ,?event.getY()?-? y );
}? else ?{? //?2 跟手指觸摸
end ?=?countDistance(event);? //? 計算結(jié)束時距離
float ?scale?=? end ?/? start ;? //? 計算縮放比例
currentMatrix .postScale(scale,?scale,? point . x ,? point . y );? //? 設(shè)置縮放
}
break ;
case ?MotionEvent. ACTION_POINTER_DOWN :
type ?=?2;
start ?=?countDistance(event);? //? 計算開始時距離
point ?=?countPoint(event);? //? 計算中心點
oldMatrix .set( imageView .getImageMatrix());
break ;
}
imageView .setImageMatrix( currentMatrix );? //? 改變圖片
return ? true ;
}
}
public ? float ?countDistance(MotionEvent?event)?{
float ?a?=?event.getX(1)?-?event.getX(0);? //?x 軸距離
float ?b?=?event.getY(1)?-?event.getY(0);? //?y 軸距離
return ?( float )?Math.sqrt(a?*?a?+?b?*?b);? //? 勾股定理
}
public ?PointF?countPoint(MotionEvent?event)?{
float ?x?=?(event.getX(0)?+?event.getX(1))?/?2;? //?x 軸中間點
float ?y?=?(event.getY(0)?+?event.getY(1))?/?2;? //?y 軸中間點
return ? new ?PointF(x,?y);
}
18.3.?讀取 SIM 卡
??電話號碼、運營商信息
??需要權(quán)限
< uses-permission? android:name = "android.permission.READ_PHONE_STATE"? />
< uses-permission? android:name = "android.permission.ACCESS_COARSE_LOCATION"? />
??Java 代碼
TelephonyManager?manager?=?(TelephonyManager)?getContext().getSystemService(Context. TELEPHONY_SERVICE );
System. out .println( " 電話號碼 :?" ?+?manager.getLine1Number());
System. out .println( " 運營商編號 :?" ?+?manager.getNetworkOperator());
System. out .println( " 運營商名字 :?" ?+?manager.getNetworkOperatorName());
??聯(lián)系人
??需要權(quán)限
< uses-permission? android:name = "android.permission.READ_ CONTACTS "? />
< uses-permission? android:name = "android.permission. WRITE _ CONTACTS "? />
??Java 代碼
Uri?uri?=?Uri.parse( "content://icc/adn" );
Cursor?c?=?getContentResolver().query(uri,? null ,? null ,? null ,? null );
while ?(c.moveToNext())
System. out .println(c.getString(c.getColumnIndex( "name" ))?+? ":?" ?+?c.getString(c.getColumnIndex( "number" )));
??通話記錄
??需要權(quán)限
< uses-permission? android:name = "android.permission.READ_ CONTACTS "? />
< uses-permission? android:name = "android.permission. WRITE _ CONTACTS "? />
??Java 代碼
Uri?uri?=?CallLog.Calls. CONTENT_URI ;
Cursor?c?=?getContentResolver().query(uri,? null ,? null ,? null ,? null );
while ?(c.moveToNext())
System. out .println(c.getString(c.getColumnIndex( "number" ))?+? ":?" ?+?c.getString(c.getColumnIndex( "type" )));
??源代碼
ContactsProvider\src\com\android\providers\contacts\?CallLogProvider.java
18.4.?安裝程序
??需要權(quán)限
< uses-permission? android:name = "android.permission. INSTALL_PACKAGES "? />
??Java 代碼
File?file?=? new ?File(Environment.getExternalStorageDirectory(),? " test .apk" );
Intent?intent?=? new ?Intent();
intent.setAction(Intent. ACTION_VIEW );
intent.setDataAndType(Uri.fromFile(file),? "application/vnd.android.package-archive" );
startActivity(intent);
18.5.?關(guān)閉程序
??殺死當(dāng)前進程
Process.killProcess(Process.myPid());
??退出虛擬機
System.exit(0);
??根據(jù)包名關(guān)閉后臺進程
ActivityManager?manager?=?(ActivityManager)?getSystemService( ACTIVITY_SERVICE );
manager.restartPackage( "cn.itcast.test" );
< uses-permission? android:name = "android.permission.RESTART_PACKAGES"? />
18.6.?使用 HTML 構(gòu)建界面
??HTML
<! DOCTYPE ? html ? PUBLIC ? "-//W3C//DTD?HTML?4.01?Transitional//EN" ? "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta ? http-equiv = "Content-Type" ? content = "text/html;?charset=UTF-8" >
< title > Insert?title?here </ title >
< script ? type = "text/javascript" >
function ?show(jsondata)?{
var ?jsonobjs?=?eval(jsondata);
var ?table?=?document.getElementById( "personTable" );
for ?(? var ?y?=?0;?y? < ?jsonobjs.length;?y++)?{
var ?tr?=?table.insertRow(table.rows.length);
var ?td1?=?tr.insertCell(0);
var ?td2?=?tr.insertCell(1);
td2.align?=? "center" ;
var ?td3?=?tr.insertCell(2);
td3.align?=? "center" ;
td1.innerHTML?=?jsonobjs[y].name;
td2.innerHTML?=?jsonobjs[y].amount;
td3.innerHTML?=? "<a?href='javascript:contact.call(\"" ?+?jsonobjs[y].phone?+? "\")'>" ?+?jsonobjs[y].phone?+? "</a>" ;
}
}
</ script >
</ head >
< body ? onload = "javascript:contact.show C ontacts()" >
< table ? border = "0" ? width = "100%" ? id = "personTable" ? cellspacing = "0" >
< tr >
< td ? width = "30%" > 姓名 </ td >
< td ? width = "30%" ? align = "center" > 存款 </ td >
< td ? align = "center" > 電話 </ td >
</ tr >
</ table >
</ body >
</ html >
??XML 代碼
< WebView
???????? android:id = "@+id/webView"
???????? android:layout_width = "fill_parent"
???????? android:layout_height = "fill_parent" ? />
??Java 代碼
public ? class ?MainActivity? extends ?Activity?{
private ?WebView? webView ;
public ? void ?onCreate(Bundle?savedInstanceState)?{
super .onCreate(savedInstanceState);
setContentView(R.layout. main );
webView ?=?(WebView)?findViewById(R.id. webView );
webView .getSettings().setJavaScriptEnabled( true );
webView .loadUrl( "file:///android_asset/index.html" );
webView .addJavascriptInterface( new ?Contact(),? "contact" );
}
private ? final ? class ?Contact?{
public ? void ?showContacts()?{
String?json?=? "[{\"name\":\"zxx\",?\"amount\":\"99999\",?\"phone\":\"18600012345\"}]" ;
webView .loadUrl( "javascript:show('" ?+?json?+? "')" );
}
public ? void ?call(String?phone)?{
startActivity( new ?Intent(Intent. ACTION_CALL ,?Uri.parse( "tel:" ?+?phone)));
}
}
}
18.7.?apk 文件反編譯
??使用解壓縮工具打開 apk 文件,找到其中 dex 文件
??創(chuàng)建 Java 工程,導(dǎo)入 dex2jar中的所有 jar 文件
??創(chuàng)建運行環(huán)境運行其中pxb.android.dex2jar.v3.Main?類,?指定 dex 文件地址,會在同目錄下生成 jar 文件
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/xxr2015/p/7462579.html
總結(jié)
以上是生活随笔為你收集整理的Android基础知识精简版(转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: STM32使用HAL库编写SHT2x温湿
- 下一篇: 3.线程安全之可见性、有序性、原子性是什
