Android基础知识精简版(转)
1.?前言
裁剪了下轉(zhuǎn)載內(nèi)容,只保留我認(rèn)為有用的知識(shí)點(diǎn)。2.?搭建開發(fā)環(huán)境
http://tools.android-studio.org/3.?開發(fā)一個(gè) Android 程序
3.1.?創(chuàng)建 Android 程序
??創(chuàng)建 Android?Project
??Project?name :項(xiàng)目名
??Build?Target : Android 版本
??Application?name :程序名,顯示在程序列表中,以及程序啟動(dòng)后的標(biāo)題欄
??Package?name :包名,程序的唯一標(biāo)識(shí)
??Create?Activity :選擇程序啟動(dòng)時(shí)是否創(chuàng)建一個(gè)窗體,設(shè)置主窗體名字
??Min?SDK?Version :設(shè)置運(yùn)行該程序所需的最低版本
3.2.?安裝、卸載程序
??Eclipse 安裝
右鍵點(diǎn)擊工程?–?Run?as?–?Android?Application
??虛擬機(jī)卸載
設(shè)置?–?應(yīng)用程序?–?管理應(yīng)用程序?–?選中要卸載的程序?–?卸載
3.3.?了解項(xiàng)目目錄結(jié)構(gòu)
??src :源代碼
??gen :系統(tǒng)自動(dòng)生成的文件
R.java?中記錄了項(xiàng)目中各種資源 ID
??res :系統(tǒng)資源,所有文件都會(huì)在 R 文件生成資源 ID
drawable :圖片
layout :界面布局
values :數(shù)據(jù)
anim :定義動(dòng)畫的 XML
raw :原生文件
??assets :資源路徑,不會(huì)在 R 文件注冊(cè)
??project.properties :供 Eclipse 使用,讀取該項(xiàng)目使用 Android 版本號(hào)。早期版本名為: default.properties
??AndroidManifest.xml :清單文件,在軟件安裝的時(shí)候被讀取
Android 中的四大組件( Activity 、 ContentProvider 、 BroadcastReceiver 、 Service )都需要在該文件中注冊(cè)
程序所需的權(quán)限也需要在此文件中聲明,例如:電話、短信、互聯(lián)網(wǎng)、訪問 SD 卡
??bin :二進(jìn)制文件,包括 class 、資源文件、 dex 、 apk 等
??proguard.cfg:用來混淆代碼的配置文件,防止別人反編譯
3.4.?程序啟動(dòng)過程
??Eclipse 將 .java 源文件編譯成 .class
??使用 dx 工具將所有 .class 文件轉(zhuǎn)換為 .dex 文件
??再將 .dex 文件和所有資源打包成 .apk 文件
??將 .apk 文件安裝到虛擬機(jī)完成程序安裝
??啟動(dòng)程序?–?開啟進(jìn)程?–?開啟主線程
??創(chuàng)建 Activity 對(duì)象? –?執(zhí)行 OnCreate() 方法
??按照 main.xml 文件初始化界面
4.?演示案例
41.?查看程序錯(cuò)誤信息
??Android 程序中如果出錯(cuò),錯(cuò)誤不會(huì)顯示在 Console 中,而是顯示在 LogCat 界面下。可以從 window? –?show?view 中打開
??日志信息分為 5 個(gè)級(jí)別: verbose?>?debug?>?info?>?warn?>?error? 高級(jí)的包含低級(jí)的
??可以創(chuàng)建過濾器對(duì)日志進(jìn)行過濾顯示,點(diǎn)擊綠色加號(hào),可以按照 tag 、 pid 、 level 進(jìn)行篩選
4.2.?布局
??RelativeLayout (相對(duì)布局)
??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
??項(xiàng)目中添加測(cè)試類
??在 AndroidManifest.xml 清單文件中添加配置
< instrumentation? android:targetPackage = "cn.itcast.junit"? android:name = "android.test.InstrumentationTestRunner"? />
< uses-library? android:name = "android.test.runner"? />
??定義一個(gè)類繼承 AndroidTestCase ,定義測(cè)試方法
??在 Outline 視圖下右鍵點(diǎn)擊測(cè)試方法? –?Run?as?–?Android?Junit?Test
??創(chuàng)建測(cè)試項(xiàng)目
??創(chuàng)建 Android?Test?Project
??輸入項(xiàng)目名,選擇一個(gè)已存在的工程, Eclipse 可以自動(dòng)配置 Junit 環(huán)境
5.?文件操作( File 、 XML 、 SharedPreferences )
5.1.?讀寫文件
??寫入文件到 SD 卡
??需要在清單文件中注冊(cè)權(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)可以獲取一個(gè)文件輸入流
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)可以獲取一個(gè)文件輸入流
該輸入流可以讀取? /data/data/ 包名 /files/? 路徑下的文件
??獲取當(dāng)前程序 Files 文件路徑
ContextWrapper.getFilesDir()
5.2.?XML
??Pull 簡(jiǎn)介
??常見的 XML 解析方式有三種, DOM 、 SAX 、 Pull , Android 系統(tǒng)中推薦使用 Pull
??Pull 解析器是一個(gè)開源的 Java 項(xiàng)目, Android 系統(tǒng)內(nèi)部解析 XML 文件均為此種方式,也可用于 JavaEE 項(xiàng)目
??Android?SDK 中已經(jīng)集成了 Pull 解析器,無需添加任何 jar 文件
??Pull 解析器運(yùn)行方式與 SAX 類似,提供各種事件的判斷
??官方網(wǎng)站: http://xmlpull.org/
??使用 Pull 解析器解析 XML 文件
??Xml.newPullParser()?獲得解析器
??parser.setInput(in,? "UTF-8" )?設(shè)置輸入流以及編碼
??parser.next()?獲取下一個(gè)解析事件,得到一個(gè)事件代碼
??XmlPullParser中定義了常量來標(biāo)識(shí)各種解析事件
START_DOCUMENT 、 END_DOCUMENT? 、 START_TAG? 、END_TAG? 、 TEXT?
??使用XmlSerializer寫出 XML
??使用以下方法生成 XML ,和 XML 文檔順序類似
startDocument
startTag
attribute
text
endTag
endDocument
5.3.?偏好設(shè)定( SharedPreferences )?
??在程序中保存一些配置參數(shù)的時(shí)候我們經(jīng)常使用 SharedPreferences
Context.getSharedPreferences(String?name, int ?mode)
該方法可以在 /data/data/<package>/shared_pref/ 目錄下創(chuàng)建一個(gè)以 name 命名的 xml 文件, mode 文件為模式
??存儲(chǔ)偏好
調(diào)用edit()方法可以獲取一個(gè) Editor 對(duì)象,對(duì)數(shù)據(jù)進(jìn)行存儲(chǔ),存儲(chǔ)之后需要調(diào)用 commit()保存到文件
??讀取偏好
獲得SharedPreferences之后調(diào)用 getString() 、 getInt() 等方法獲取其中設(shè)置的值
??在 Activity 中獲取 SharedPreferences
在 Activity 中可以調(diào)用 getPreferences( int ?mode)方法獲得一個(gè)SharedPreferences,文件名和 Activity 名一致
6.?數(shù)據(jù)庫( SQLite )
6.1.?SQLite 特點(diǎn)
??Android 平臺(tái)中嵌入了一個(gè)關(guān)系型數(shù)據(jù)庫 SQLite ,和其他數(shù)據(jù)庫不同的是 SQLite 存儲(chǔ)數(shù)據(jù)時(shí)不區(qū)分類型
例如一個(gè)字段聲明為 Integer 類型,我們也可以將一個(gè)字符串存入,一個(gè)字段聲明為布爾型,我們也可以存入浮點(diǎn)數(shù)。
除非是主鍵被定義為 Integer ,這時(shí)只能存儲(chǔ) 64 位整數(shù)
??創(chuàng)建數(shù)據(jù)庫的表時(shí)可以不指定數(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 個(gè)參數(shù)
??重寫 onCreate ()方法
??重寫 upGrade() 方法
??注意: SQLite 數(shù)據(jù)庫中列一旦創(chuàng)建不能修改,如果一定要修改,需要重新創(chuàng)建表,拷貝數(shù)據(jù)
6.3.?CRUD操作
??和 JDBC 訪問數(shù)據(jù)庫不同,操作 SQLite 數(shù)據(jù)庫無需加載驅(qū)動(dòng),不用獲取連接,直接可以使用
獲取 SQLiteDatabase 對(duì)象之后通過該對(duì)象直接可以執(zhí)行 SQL 語句
SQLiteDatabase.execSQL()
SQLiteDatabase.rawQuery()
??getReadableDatabase()和getWritableDatabase()的區(qū)別
查看源代碼后我們發(fā)現(xiàn)getReadableDatabase()在通常情況下返回的就是getWritableDatabase() 拿到的數(shù)據(jù)庫
只有在拋出異常的時(shí)候才會(huì)以只讀方式打開
??數(shù)據(jù)庫對(duì)象緩存
getWritableDatabase() 方法最后會(huì)使用一個(gè)成員變量記住這個(gè)數(shù)據(jù)庫對(duì)象,下次打開時(shí)判斷是否重用
??SQLiteDatabase 封裝了 insert() 、 delete ()、 update ()、 query ()四個(gè)方法也可以對(duì)數(shù)據(jù)庫進(jìn)行操作
這些方法封裝了部分 SQL 語句,通過參數(shù)進(jìn)行拼接
6.4.?事務(wù)管理
??在使用 SQLite 數(shù)據(jù)庫時(shí)可以用 SQLiteDatabase類中定義的相關(guān)方法控制事務(wù)
beginTransaction()? 開啟事務(wù)
setTransactionSuccessful()? 設(shè)置事務(wù)成功標(biāo)記
endTransaction()? 結(jié)束事務(wù)
??endTransaction() 需要放在 finally 中執(zhí)行,否則事務(wù)只有到超時(shí)的時(shí)候才自動(dòng)結(jié)束,會(huì)降低數(shù)據(jù)庫并發(fā)效率
7.?內(nèi)容提供者( ContentProvider )
7.1.?什么是內(nèi)容提供者
??內(nèi)容提供者是 Android 中的四大組件之一,可以將應(yīng)用中的數(shù)據(jù)對(duì)外進(jìn)行共享
??內(nèi)容提供者將數(shù)據(jù)的訪問方式統(tǒng)一,不必針對(duì)不同數(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é)點(diǎn)下進(jìn)行配置, <provider> 標(biāo)簽中需要指定 name 和 authorities 屬性
name 為類名,包名從程序 Package 開始,以“ . ”開始
authorities :是訪問 Provider 時(shí)的路徑,要唯一
??URI 代表要操作的數(shù)據(jù),由 scheme 、 authorites 、 path 三部分組成
content:// cn.itcast. sqlite . provider / person
scheme :固定為 content ,代表訪問內(nèi)容提供者
authorites : <provider> 節(jié)點(diǎn)中的 authorites 屬性
path :程序定義的路徑,可根據(jù)業(yè)務(wù)邏輯定義
7.3.?完成 CRUD 方法
??當(dāng)程序調(diào)用 CRUD 方法時(shí)會(huì)傳入 Uri
??我們通過 Uri 判斷調(diào)用者要操作的數(shù)據(jù)
可以使用工具類 UriMatcher 來判斷 Uri
addURI 方法可以添加 Uri
match 方法可以匹配一個(gè) Uri 判斷其類型
??根據(jù)業(yè)務(wù)邏輯操作數(shù)據(jù)
7.4.?訪問內(nèi)容提供者
??通過 Context 獲得 ContentResolver 對(duì)象
??調(diào)用 ContentResolver 對(duì)象的方法即可訪問內(nèi)容提供者
7.5.?完成 getType 方法
??如果返回?cái)?shù)據(jù)是單條數(shù)據(jù):vnd.android.cursor.item?
??如果返回?cái)?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() 方法指定對(duì)某個(gè) Uri 注冊(cè) ContentObserver
自定義ContentObserver,重寫 onChange() 方法獲取數(shù)據(jù)
7.7.?GIT 獲取源代碼
??資源地址
??Git
http://code.google.com/p/msysgit/
??源碼
https://github.com/android
注意:
GIT1.7.7 安裝后不能卸載,可以用其他版本覆蓋后再卸載。
使用 GIT 時(shí)不要使用中文目錄,否則 GIT?GUI 會(huì)報(bào)錯(cuò)無法啟動(dòng)。刪除 C 盤中 .gitconfig文件可以解決。
8.?網(wǎng)絡(luò)通信
8.1.?獲取文本數(shù)據(jù)
??通過 URL 對(duì)象封裝地址,打開一個(gè) HttpURLConnection
??設(shè)置頭信息之后獲取響應(yīng)碼,如果成功返回 200 即可從 HttpURLConnection 中獲取輸入流讀取數(shù)據(jù)
??代碼過長(zhǎng)屏幕顯示不全可以使用 <ScrollView> 進(jìn)行顯示
??需要訪問網(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)換為圖片對(duì)象
8.3.?獲取 XML
??使用 URL 封裝路徑,打開一個(gè) HttpURLConnection
??設(shè)置頭信息之后獲取相應(yīng)碼,從輸入流中獲取數(shù)據(jù)
??使用 XmlPullPaser 解析
8.4.?獲取 JSON
??使用 URL 封裝路徑,打開一個(gè) HttpURLConnection
??設(shè)置頭信息之后獲取相應(yīng)碼,從輸入流中獲取數(shù)據(jù)
??將數(shù)據(jù)轉(zhuǎn)為 String ,封裝成 JSONArray 對(duì)象
??遍歷 JSONArray 對(duì)象,調(diào)用獲取其中的 JSONObject
??再?gòu)?JSONObject 中獲取每個(gè)字段的信息
8.5.?發(fā)送 GET 請(qǐng)求
??拼接路徑和參數(shù),通過 URL 進(jìn)行封裝,打開一個(gè) HttpURLConnection ,發(fā)送請(qǐng)求
??如果參數(shù)是中文會(huì)出現(xiàn)亂碼
??URL 中包含的中文參數(shù)需要使用 URLEncoder 進(jìn)行編碼
??服務(wù)器端如果是 TOMCAT ,其默認(rèn)使用 ISO8859-1 編碼,接收時(shí)需要處理編碼問題
8.6.?發(fā)送 POST 請(qǐng)求
??通過 URL 打開一個(gè) HttpURLConnection
??頭信息中除了超時(shí)時(shí)間和請(qǐng)求方式之外還必須設(shè)置Content-Type和Content-Length
??從 HttpURLConnection 獲得輸出流輸出參數(shù)數(shù)據(jù)
??服務(wù)端可以使用 request 對(duì)象的 setCharacterEncoding方法設(shè)置編碼
8.7.?發(fā)送 XML ,訪問 WebService
??發(fā)送 XML
??通過 URL 封裝路徑打開一個(gè) HttpURLConnection
??設(shè)置請(qǐng)求方式,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ù),我們可以對(duì)其進(jìn)行調(diào)用
?? http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?op=getMobileCodeInfo ?中提供了電話歸屬地查詢的使用說明
8.8.?HTTP 協(xié)議上傳文件
??搭建服務(wù)器,完成上傳功能
??使用瀏覽器上傳,查看請(qǐng)求信息
??HttpURLConnection
??通過 URL 封裝路徑打開一個(gè) HttpURLConnection
??設(shè)置請(qǐng)求方式以及頭字段:Content-Type、Content-Length、Host
??拼接數(shù)據(jù)發(fā)送
??Socket
??使用 HttpURLConnection 發(fā)送時(shí)內(nèi)部有緩存機(jī)制,如果上傳較大文件會(huì)導(dǎo)致內(nèi)存溢出
??我們可以使用 Socket 發(fā)送 TCP 請(qǐng)求,將上傳數(shù)據(jù)分段發(fā)送
??HttpClient
public ? void ?upload(String?name,?String?password,?String?path)? throws ?Exception?{
//? 創(chuàng)建 HttpClient 對(duì)象
HttpClient?client?=? new ?HttpClient();
//? 設(shè)置超時(shí)事件
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
//? 創(chuàng)建一個(gè) Post 請(qǐng)求 ,? 指定路徑
PostMethod?postMethod?=? new ?PostMethod( "http://192.168.1.102:8080/14.Web/LoginServlet" );
//? 封裝每個(gè)表單項(xiàng)
Part[]?parts?=?{? new ?StringPart( "name" ,?name),? new ?StringPart( "password" ,?password),? new ?FilePart( "file" ,? new ?File(path))?};
//? 給 Post 請(qǐng)求設(shè)置實(shí)體
postMethod.setRequestEntity( new ?MultipartRequestEntity(parts,?postMethod.getParams()));
//? 執(zhí)行 Post 請(qǐng)求
client.executeMethod(postMethod);
//?Post 請(qǐng)求是釋放資源
postMethod.releaseConnection();
}
8.9.?多線程斷點(diǎn)續(xù)傳下載器
??在下載的時(shí)候多個(gè)線程并發(fā)可以占用服務(wù)器端更多資源,從而加快下載速度
??手機(jī)端下載數(shù)據(jù)時(shí)難免會(huì)出現(xiàn)無信號(hào)斷線、電量不足等情況,所以需要斷點(diǎn)續(xù)傳功能
??根據(jù)下載數(shù)據(jù)長(zhǎng)度計(jì)算每個(gè)線程下載的數(shù)據(jù)位置,程序中開啟多個(gè)線程并發(fā)下載
在請(qǐng)求頭中設(shè)置 Range 字段就可以獲取指定位置的數(shù)據(jù),例如: Range:?bytes=100-200
??在下載過程中記錄每個(gè)線程已拷貝數(shù)據(jù)的數(shù)量,如果下載中斷,下次啟動(dòng)時(shí)從記錄位置繼續(xù)下載
??多線程下載
??進(jìn)度條使用 <Progress> 進(jìn)行配置
默認(rèn)為圓形進(jìn)度條,水平進(jìn)度條需要配置 style 屬性, ?android:attr/progressBarStyleHorizontal
使用 android.R.attr. progressBarStyleHorizontal作為樣式
??當(dāng)點(diǎn)擊下載按鈕時(shí)開啟多線程下載,下載過程中修改進(jìn)度條進(jìn)度
設(shè)置最大刻度:setMax()
設(shè)置當(dāng)前進(jìn)度:setProgress()
??斷點(diǎn)續(xù)傳
??斷點(diǎn)續(xù)傳需要在下載過程中記錄每條線程的下載進(jìn)度
??每次下載開始之前先讀取數(shù)據(jù)庫,查詢是否有未完成的記錄,有就繼續(xù)下載,沒有則創(chuàng)建新記錄插入數(shù)據(jù)庫
??在每次向文件中寫入數(shù)據(jù)之后,在數(shù)據(jù)庫中更新下載進(jìn)度
??下載完成之后刪除數(shù)據(jù)庫中下載記錄
??Handler 傳輸數(shù)據(jù)
??主線程中創(chuàng)建的 View 只能在主線程中修改,其他線程只能通過和主線程通信,在主線程中改變 View 數(shù)據(jù)
??我們使用 Handler 可以處理這種需求
主線程中創(chuàng)建 Handler ,重寫 handleMessage() 方法
新線程中使用 Handler 發(fā)送消息,主線程即可收到消息,并且執(zhí)行 handleMessage() 方法
??動(dòng)態(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)前頁面中某個(gè)容器的 addView ,將新創(chuàng)建的 View 添加進(jìn)來
9.?活動(dòng)( Activity )
9.1.?創(chuàng)建 Activity
??定義 Activity
??定義類繼承 Activity
??在 AndroidManifest.xml 的 <application> 節(jié)點(diǎn)中聲明 <activity>
??顯式意圖創(chuàng)建方式
??構(gòu)造函數(shù),代碼少
new ?Intent( this ,?NewActivity. class );
??類名形式,靈活,可擴(kuò)展性強(qiáng)
intent.setClassName( this ,? "cn.itcast.activity.NewActivity" );
??包名類名形式,可啟動(dòng)其他程序中的 Activity
intent.setClassName( "cn.itcast.downloader" ,? "cn.itcast.downloader.MainActivity" );
??創(chuàng)建 Activity 并傳遞數(shù)據(jù)
??在意圖對(duì)象中封裝了一個(gè) Bundle 對(duì)象,可以用來攜帶數(shù)據(jù)
??在新 Activity 中可以獲得意圖對(duì)象以獲取其中 Bundle 保存的數(shù)據(jù)
??創(chuàng)建 Activity 獲取返回?cái)?shù)據(jù)
??使用startActivityForResult(Intent?intent,? int ?requestCode)?方法打開 Activity
??重寫onActivityResult( int ?requestCode,? int ?resultCode,?Intent?data)?方法
??新 Activity 中調(diào)用 setResult( int ?resultCode,?Intent?data)?設(shè)置返回?cái)?shù)據(jù)之后,關(guān)閉 Activity 就會(huì)調(diào)用 onActivityResult方法
??隱式意圖創(chuàng)建 Activity
??顯式意圖是指在創(chuàng)建意圖時(shí)指定了組件,而隱式意圖則不指定組件,通過動(dòng)作、類型、數(shù)據(jù)匹配對(duì)應(yīng)的組件
??在清單文件中定義 <activity> 時(shí)需要定義 <intent-filter> 才能被隱式意圖啟動(dòng)
??<intent-filter> 中至少配置一個(gè) <action> 和一個(gè) <category> ,否則無法被啟動(dòng)
??Intent 對(duì)象中設(shè)置的 action 、 category 、 data 在 <intent-filter> 必須全部包含才能啟動(dòng)
??<intent-filter> 中的 <action> 、 <category> 、 <data> 都可以配置多個(gè), Intent 對(duì)象中不用全部匹配,每樣匹配一個(gè)即可啟動(dòng)
??如果一個(gè)意圖可以匹配多個(gè) Activity , Android 系統(tǒng)會(huì)提示選擇
9.2.?生命周期
??Acitivity 三種狀態(tài)
運(yùn)行: activity 在最前端運(yùn)行
暫停: activity 可見,但前端還有其他 acti vity ,被覆蓋一部分,或者前端 activity 透明
停止: activity 不可見,完全被覆蓋
??生命周期相關(guān)方法
onCreate :創(chuàng)建時(shí)調(diào)用,或者程序在暫停、停止?fàn)顟B(tài)下被殺死之后重新打開時(shí)也會(huì)調(diào)用
onStart : onCreate 之后或者從停止?fàn)顟B(tài)恢復(fù)時(shí)調(diào)用
onResume : onStart 之后或者從暫停狀態(tài)恢復(fù)時(shí)調(diào)用,從停止?fàn)顟B(tài)恢復(fù)時(shí)由于調(diào)用 onStart ,也會(huì)調(diào)用 onResume
onPause:進(jìn)入暫停、停止?fàn)顟B(tài),或者銷毀時(shí)會(huì)調(diào)用
onStop:進(jìn)入停止?fàn)顟B(tài),或者銷毀時(shí)會(huì)調(diào)用
onDestroy:銷毀時(shí)調(diào)用
onRestart :從停止?fàn)顟B(tài)恢復(fù)時(shí)調(diào)用
??保存信息相關(guān)方法
onSaveInstanceState:在 Activity 被動(dòng)的摧毀或停止的時(shí)候調(diào)用,用于保存運(yùn)行數(shù)據(jù),可以將數(shù)據(jù)存在在 Bundle 中
onRestoreInstanceState:該方法在 Activity 被重新繪制的時(shí)候調(diào)用,例如改變屏幕方向, savedInstanceState為onSaveInstanceState保存的數(shù)據(jù)
9.3.?啟動(dòng)模式
??在 AndroidManifest.xml 中的 <activity> 標(biāo)簽中可以配置 android:launchMode 屬性,用來控制 Actvity 的啟動(dòng)模式
??在 Android 系統(tǒng)中我們創(chuàng)建的 Acitivity 是以棧的形式呈現(xiàn)的
standard :每次調(diào)用 startActivity() 啟動(dòng)時(shí)都會(huì)創(chuàng)建一個(gè)新的 Activity 放在棧頂
singleTop :如果啟動(dòng)的 Activity 時(shí),指定 Activity 不在棧頂就創(chuàng)建,如在棧頂,則不再創(chuàng)建
singleTask :如果啟動(dòng)的 Activity 不存在就創(chuàng)建,如果存在直接跳轉(zhuǎn)到指定的 Activity 所在位置
singleInstance :如果啟動(dòng)的 Activity 不存在就創(chuàng)建,如果存在就將指定的 Activity 移動(dòng)到棧頂
9.4.?內(nèi)存管理
??Android 系統(tǒng)在運(yùn)行多個(gè)進(jìn)程時(shí),如果系統(tǒng)資源不足,會(huì)強(qiáng)制結(jié)束一些進(jìn)程。優(yōu)先選擇哪個(gè)進(jìn)程來結(jié)束是有優(yōu)先級(jí)的。以下順序靠上的優(yōu)先結(jié)束
空:進(jìn)程中所有 Activity 都已銷毀
后臺(tái):進(jìn)程中有一個(gè)停止?fàn)顟B(tài)的 Activity
可見:進(jìn)程中有一個(gè)暫停狀態(tài)的 Activity
前臺(tái):進(jìn)程中正在運(yùn)行一個(gè) Activity
10.?廣播接收者 (BroadcastReceiver)
10.1.?定義廣播接收者
??定義類繼承 BroadcastReceiver ,重寫 onReceive 方法
??清單文件中聲明<receiver>,需要在其中配置<intent-filter>指定接收廣播的動(dòng)作
??當(dāng)接收到匹配廣播之后就會(huì)執(zhí)行 onReceive 方法
??BroadcastReceiver 除了在清單文件中聲明,也可以在代碼中聲明,使用 registerReceiver方法注冊(cè) Receiver
10.2.?發(fā)送廣播
??無序廣播
??使用sendBroadcast方法發(fā)送
??被所有廣播接收者接收,無序,不可中斷
??廣播時(shí)可設(shè)置接收者權(quán)限,僅當(dāng)接收者含有權(quán)限才能接收
??接收者的<receiver>也可設(shè)置發(fā)送方權(quán)限,只接收含有權(quán)限應(yīng)用的廣播
??有序廣播
??使用sendOrderedBroadcast方法發(fā)送
??接收者可以在<intent-filter>中定義android:priority定義優(yōu)先級(jí),數(shù)字越大優(yōu)先級(jí)越高
??被各個(gè)廣播接收者逐個(gè)接收,中途可以中斷或者添加數(shù)據(jù)
abortBroadcast()??
getResultExtras( true ).putString( "data" ,? " 新增數(shù)據(jù) " );
10.3.?監(jiān)聽短信接收
??Android 系統(tǒng)在收到短信的時(shí)候會(huì)發(fā)送一條有序廣播,我們?nèi)绻x一個(gè)接收者接收這個(gè)廣播,就可以得到短信內(nèi)容,也可以攔截短信
??定義廣播接收者接收廣播 android.provider.Telephony.SMS_RECEIVED
??在 onReceive 方法內(nèi)部調(diào)用 Intent 的 getExtras() 再調(diào)用 get(String) 獲取其中 pdus 字段,得到一個(gè) Object[],其中每一個(gè)元素都是一個(gè) byte[]
??通過SmsMessage類的createFromPdu方法創(chuàng)建 SmsMessage 對(duì)象
??從 SmsMessage 對(duì)象中即可獲取發(fā)送者號(hào)碼、短信內(nèi)容、發(fā)送時(shí)間等信息
??需要接收短信權(quán)限: < uses-permission? android:name ="android.permission.RECEIVE_SMS" />
??Android 系統(tǒng)中收到短信的通知是一個(gè)有序通知,我們?nèi)缧钄r截垃圾短信,可以配置較高的 priority,收到信息進(jìn)行判斷是否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è)置電話號(hào)碼
10.5.?生命周期
??廣播接收者的生命周期是非常短暫的,在接收到廣播的時(shí)候創(chuàng)建, onReceive() 方法結(jié)束之后銷毀
??廣播接收者中不要做一些耗時(shí)的工作,否則會(huì)彈出 Application?No?Response 錯(cuò)誤對(duì)話框
??最好也不要在廣播接收者中創(chuàng)建子線程做耗時(shí)的工作,因?yàn)閺V播接收者被銷毀后進(jìn)程就成為了空進(jìn)程,很容易被系統(tǒng)殺掉
??耗時(shí)的較長(zhǎng)的工作最好放在服務(wù)中完成
11.?服務(wù) (Service)
11.1.?基本概念
??Service 是一種在后臺(tái)運(yùn)行,沒有界面的組件,由其他組件調(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ù),傳入一個(gè)自定義的ServiceConnection用來接收 IBinder
??定義一個(gè)業(yè)務(wù)接口,其中定義需要的使用的方法
??服務(wù)中自定義一個(gè) IBinder 繼承 Binder 并實(shí)現(xiàn)業(yè)務(wù)接口,在 onBind方法中返回
??調(diào)用端將 IBinder 轉(zhuǎn)為接口類型,調(diào)用接口中的方法即可調(diào)用到服務(wù)中的方法
11.4.?綁定遠(yuǎn)程服務(wù)
??遠(yuǎn)程綁定服務(wù)時(shí)無法通過同一個(gè)接口來調(diào)用方法,這時(shí)就需要使用 AIDL 技術(shù)
??將接口擴(kuò)展名改為“.aidl”
??去掉權(quán)限修飾符
??gen 文件夾下會(huì)生成同名接口
??將服務(wù)中自定義的 IBinder 類改為繼承接口中的 S tub
??ServiceConnection中返回的 IBinder 是代理對(duì)象,不能使用強(qiáng)轉(zhuǎn),改用 S tub.asInterface()
11.5.?AIDL 使用自定義類型
??AIDL 默認(rèn)只能使用 Java 中基本數(shù)據(jù)類型和 String 、 List 、 Map , List 和 Map 中的元素類型也只能是這些類型。
??如果需要使用其他類型數(shù)據(jù),使用的類必須實(shí)現(xiàn) Parcelable 接口以完成序列化和反序列化工作
重寫?public?void?writeToParcel(Parcel?dest,?int?flags)
定義?public?static?final?Parcelable.Creator<Person>? CREATOR
??定義該類對(duì)應(yīng)的 AIDL
package? 包名
parcelable? 類名
??在接口 AIDL 中導(dǎo)入該類,注意:即使是同一個(gè)包也需要導(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 方法可以接收一個(gè) int 參數(shù),用來指定哪個(gè)攝像頭
??設(shè)置預(yù)覽顯示位置
setPreviewDisplay(SurfaceHolder?holder)
注意 SurfaceView 不在前端顯示的時(shí)候會(huì)被銷毀,恢復(fù)之后會(huì)重繪
??開始預(yù)覽?
startPreview()
將攝像頭拍攝畫面顯示在 SurfaceView 中,在此之前可對(duì)攝像頭進(jìn)行參數(shù)配置
getParameters()?方法可以獲取攝像頭的相關(guān)參數(shù)Parameters,調(diào)用其內(nèi)部方法即可進(jìn)行配置
??自動(dòng)對(duì)焦
autoFocus(AutoFocusCallback?cb)
自動(dòng)對(duì)焦是一個(gè)異步操作,如果我們向等待自動(dòng)對(duì)焦結(jié)束之后才開始拍照,需要傳入一個(gè)回調(diào)對(duì)象,在其回調(diào)函數(shù)中調(diào)用拍照方法
??拍照?
takePicture(ShutterCallback?shutter,?PictureCallback?raw,?PictureCallback?jpeg)
拍照也是異步操作,需要通過回調(diào)函數(shù)來得到拍照之后的數(shù)據(jù)
注意拍照之后攝像頭不回自動(dòng)回到預(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:? 時(shí)間
??創(chuàng)建PendingIntent以供點(diǎn)擊時(shí)發(fā)送
PendingIntent.getActivity(Context?context,? int ?requestCode,?Intent?intent,? int ?flags)
context:? 當(dāng)前上下文
requestCode:? 請(qǐng)求碼
intent:? 點(diǎn)擊時(shí)要發(fā)送的意圖
flags:? 類型 ,? PendingIntent中提供了常量選擇
??設(shè)置通知點(diǎn)擊事件
調(diào)用Notification?對(duì)象方法 :? setLatestEventInfo(Context?context,?CharSequence?contentTitle,?CharSequence?contentText,?PendingIntent?contentIntent)
context:? 當(dāng)前上下文
contentTitle:? 標(biāo)題
contentText:?內(nèi)容
contentIntent:? 點(diǎn)擊時(shí)觸發(fā)的意圖
??設(shè)置通知點(diǎn)擊后清除
設(shè)置Notification?對(duì)象屬性?n. flags ?=?Notification. FLAG_AUTO_CANCEL ;
??發(fā)送消息
調(diào)用Notification對(duì)象方法 :? notify( int ?id,?Notification?notification)
13.3.?對(duì)話框通知
??普通對(duì)話框
new ?AlertDialog.Builder( this )? //
.setTitle( " 普通對(duì)話框 " )? //
.setMessage( " 普通內(nèi)容 " )? //
.setCancelable( false )? //
.setPositiveButton( "YES" ,?listener)? // ? listener?為 OnClickListener? 監(jiān)聽器對(duì)象 ,? 監(jiān)聽按鈕被選中
.setNeutralButton( "CANCEL" ,?listener)? //
.setNegativeButton( "NO" ,?listener)? //
.show();
??列表對(duì)話框
new ?AlertDialog.Builder( this )? //
.setTitle( " 列表對(duì)話框 " )? //
.setCancelable( false )? //
.setItems( items ,?listener)? // ? listener?為 OnClickListener? 監(jiān)聽器對(duì)象 ,? 監(jiān)聽列表項(xiàng)被選中
.show();
??單選對(duì)話框
new ?AlertDialog.Builder( this )? //
.setTitle( " 單選對(duì)話框 " )? //
.setCancelable( false )? //
.setSingleChoiceItems( items ,?0,?choiceLinstener)? // ? 0,? 為默認(rèn)選中索引 ,? choiceLinstener?為? OnClickListener? 監(jiān)聽器對(duì)象 ,? 監(jiān)聽單選按鈕被選中
.setPositiveButton( " 確定 " ,?positiveLinstener)? // ? positiveLinstener?為? OnClickListener? 監(jiān)聽器對(duì)象 ,? 監(jiān)聽確定按鈕點(diǎn)擊
.show();
??多選對(duì)話框
new ?AlertDialog.Builder( this )? //
.setTitle( " 多選對(duì)話框 " )? //
.setCancelable( false )? //
.setMultiChoiceItems( items ,?checkedArr,?choiceListener)? // ? checkedArr?為默認(rèn)選中 ,? choiceListener?為? OnMultiChoiceClickListener? 監(jiān)聽器對(duì)象 ,? 監(jiān)聽多選按鈕被選中
.setPositiveButton( " 確定 " ,?positiveLinstener)? // ? positiveLinstener?為? OnClickListener? 監(jiān)聽器對(duì)象 ,? 監(jiān)聽確定按鈕點(diǎn)擊
.show();
??進(jìn)度對(duì)話框
ProgressDialog?dialog?=? new ?ProgressDialog( this );
dialog.setProgressStyle(ProgressDialog. STYLE_HORIZONTAL ); //?設(shè)置進(jìn)度條樣式
dialog.setTitle( " 下載中 " );
dialog.setMessage( " 請(qǐng)稍候 ..." );
dialog.setCancelable( false );
dialog.setMax(100);
dialog.show();
dialog.setProgress(10); //? 設(shè)置進(jìn)度
dialog.dismiss(); //? 對(duì)話框結(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)建一個(gè)新的 xml 文件指定每個(gè)條目的布局
??Java 代碼構(gòu)建 ListView
??獲取 ListView 對(duì)象
??設(shè)置一個(gè) Adapter
BaseAdapter :實(shí)現(xiàn)內(nèi)部抽象方法
SimpleAdapter:以 List<Map<String,??>> 形式封裝數(shù)據(jù)
SimpleCursorAdapter:以 Cursor 對(duì)象封裝數(shù)據(jù), Cursor 中需要有“ _id ”一列
??添加 OnItemClickListener
調(diào)用 ListView 的 getItemAtPosition(int) 方法可以獲取封裝數(shù)據(jù)的容器
如果傳入的是 BaseAdapter ,獲取到的就是我們自定義方法中返回的內(nèi)容
如果傳入的是SimpleAdapter,獲取到的就是一個(gè) Map<String,??>
如果傳入的是SimpleCursorAdapter,獲得到的就是一個(gè) Cursor ,并且 Cursor 以指向選中的一條記錄
14.2.?單選 (RadioGroup)
??定義 <RadioGroup>
??在 <RadioGroup> 中定義 <RadioButton> 和 <Button>
??處理 Button 的點(diǎn)擊事件
??根據(jù) ID 獲取 RadioGroup 對(duì)象,調(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> 和一個(gè) <Button>
??處理 Button 的點(diǎn)擊事件
??根據(jù) ID 獲取每個(gè) 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)建一個(gè)適配器
??獲取 Spinner 標(biāo)簽,調(diào)用 setAdapter(SpinnerAdapter?adapter)方法設(shè)置一個(gè)適配器
??調(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)
??添加菜單項(xiàng)
??重寫 Actvity 的 onCreateOptionsMenu(Menu?menu)方法
??添加菜單項(xiàng)
調(diào)用方法中參數(shù) menu 的 add(CharSequence?title)?方法
??添加子菜單
調(diào)用 menu 對(duì)象的 addSubMenu( final ?CharSequence?title)
該方法返回一個(gè)SubMenu對(duì)象
??添加子菜單的菜單項(xiàng)
調(diào)用SubMenu對(duì)象的add(CharSequence?title)?方法
??處理菜單點(diǎn)擊事件
??重寫 Activity 的 onOptionsItemSelected(MenuItem?item)?方法
參數(shù) item 即為被選中的菜單項(xiàng)
??代碼
public ? boolean ?onCreateOptionsMenu(Menu?menu)?{
menu.add( " 增加 " );
menu.add( " 修改 " );
menu.add( " 刪除 " );
SubMenu?subMenu?=?menu.addSubMenu( " 查詢 " );
subMenu.add( " 按照序號(hào)查詢 " );
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.?手勢(shì)識(shí)別 ( GestureOverlayView)
??創(chuàng)建手勢(shì)庫
??導(dǎo)入 SDK 中的工程
android-sdk-windows\samples\android-8\GestureBuilder
這個(gè)工程不能直接導(dǎo)入,需要添加三個(gè)配置文件:.classpath、.project、default.properties
??將工程部署到手機(jī)中,創(chuàng)建手勢(shì)庫
手勢(shì)庫會(huì)存儲(chǔ)在手機(jī) 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 = " 這是 一個(gè)按鈕 "
/>
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 自動(dòng)提示的“ _ ”要替換成“ . ”
16.?國(guó)際化與屏幕適配
16.1.?國(guó)際化
??在 values 和 drawable 文件夾后加上語言以及地區(qū)名,程序中需要國(guó)際化的部分使用資源 ID
values-en-rUK
values-en-rUS
values-zh-rCN
values-zh-rTW
??匹配規(guī)則
在匹配資源時(shí)先會(huì)找語言、地區(qū)完全匹配的
如果沒有地區(qū)匹配的,則查找語言匹配的
如果沒有語言匹配的則找默認(rèn) values
16.2.?屏幕適配
??在 layout 文件夾后加上分辨率,系統(tǒng)會(huì)根據(jù)屏幕尺寸自動(dòng)選擇
注意分辨率中的乘號(hào)是“ x ”不是“ * ”
??如果沒有匹配的分辨率會(huì)找默認(rèn) layout 文件夾
17.?動(dòng)畫特效
17.1.?Frame
??通過多個(gè)畫面連續(xù)播放實(shí)現(xiàn)動(dòng)畫效果
??詳見文檔?android-sdk-windows/docs/guide/topics/resources/animation-resource.html
17.2.?Tween
??將某個(gè)組件以漸變的方式實(shí)現(xiàn)透明、縮放、移動(dòng)、旋轉(zhuǎn)等動(dòng)畫效果
??詳見文檔?android-sdk-windows/docs/guide/topics/resources/animation-resource.html
17.3.?使用動(dòng)畫切換 Activity
??在 startActivity() 方法調(diào)用之后調(diào)用 overridePendingTransition( int ?enterAnim,? int ?exitAnim)方法
enterAnim?進(jìn)入的動(dòng)畫資源 id
exitAnim?退出的動(dòng)畫 資源 id
17.4.?使用動(dòng)畫翻頁
??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
磁場(chǎng) 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 );
??注冊(cè)監(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 :? //? 按下時(shí)
x ?=?event.getX();? //? 獲取 x 軸坐標(biāo)
y ?=?event.getY(); //? 獲取 y 軸坐標(biāo)
oldMatrix .set( imageView .getImageMatrix()); //? 記住位置
break ;
case ?MotionEvent. ACTION_MOVE :? //? 移動(dòng)時(shí)
currentMatrix .set( oldMatrix );? //? 設(shè)置成按下時(shí)記住的位置
currentMatrix .postTranslate(event.getX()?-? x ,?event.getY()?-? y ); //? 改變位置
break ;
}
imageView .setImageMatrix( currentMatrix ); //? 移動(dòng)圖片
return ? true ;
}
}
??多點(diǎn)觸摸
private ? class ?MyOnTouchListener? implements ?OnTouchListener?{
private ? float ? x ; //? 圖片移動(dòng)前的 x 軸坐標(biāo)
private ? float ? y ; //? 圖片移動(dòng)前的 y 軸坐標(biāo)
private ?Matrix? currentMatrix ?=? new ?Matrix();? //? 用來移動(dòng)圖片的矩陣
private ?Matrix? oldMatrix ?=? new ?Matrix(); //? 圖片移動(dòng)前的矩陣
private ? int ? type ; //? 操作類型 ,? 一根手指觸摸還是兩根手指觸摸
private ? float ? start ; //? 第二根手指按下時(shí)的距離
private ? float ? end ; //? 兩根手指移動(dòng)后的距離
private ?PointF? point ; //? 放大時(shí)的中心點(diǎn)
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);? //? 計(jì)算結(jié)束時(shí)距離
float ?scale?=? end ?/? start ;? //? 計(jì)算縮放比例
currentMatrix .postScale(scale,?scale,? point . x ,? point . y );? //? 設(shè)置縮放
}
break ;
case ?MotionEvent. ACTION_POINTER_DOWN :
type ?=?2;
start ?=?countDistance(event);? //? 計(jì)算開始時(shí)距離
point ?=?countPoint(event);? //? 計(jì)算中心點(diǎn)
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 軸中間點(diǎn)
float ?y?=?(event.getY(0)?+?event.getY(1))?/?2;? //?y 軸中間點(diǎn)
return ? new ?PointF(x,?y);
}
18.3.?讀取 SIM 卡
??電話號(hào)碼、運(yùn)營(yíng)商信息
??需要權(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( " 電話號(hào)碼 :?" ?+?manager.getLine1Number());
System. out .println( " 運(yùn)營(yíng)商編號(hào) :?" ?+?manager.getNetworkOperator());
System. out .println( " 運(yùn)營(yíng)商名字 :?" ?+?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)前進(jìn)程
Process.killProcess(Process.myPid());
??退出虛擬機(jī)
System.exit(0);
??根據(jù)包名關(guān)閉后臺(tái)進(jì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)建運(yùn)行環(huán)境運(yùn)行其中pxb.android.dex2jar.v3.Main?類,?指定 dex 文件地址,會(huì)在同目錄下生成 jar 文件
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/xxr2015/p/7462579.html
總結(jié)
以上是生活随笔為你收集整理的Android基础知识精简版(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STM32使用HAL库编写SHT2x温湿
- 下一篇: Androidstudio通过无线连接进