Ø 建立 Android Project javascript
Ÿ Project name :項目名 php
Ÿ Build Target : Android 版本 html
Ÿ Application name :程序名,顯示在程序列表中,以及程序啓動後的標題欄 前端
Ÿ Package name :包名,程序的惟一標識 java
Ÿ Create Activity :選擇程序啓動時是否建立一個窗體,設置主窗體名字 android
Ÿ Min SDK Version :設置運行該程序所需的最低版本 git
Ÿ Eclipse 安裝 github
右鍵點擊工程 – Run as – Android Applicationweb
Ÿ 虛擬機卸載sql
設置 – 應用程序 – 管理應用程序 – 選中要卸載的程序 – 卸載
Ÿ src :源代碼
Ÿ gen :系統自動生成的文件
R.java 中記錄了項目中各類資源 ID
Ÿ res :系統資源,全部文件都會在 R 文件生成資源 ID
drawable :圖片
layout :界面佈局
values :數據
anim :定義動畫的 XML
raw :原生文件
Ÿ assets :資源路徑,不會在 R 文件註冊
Ÿ project.properties :供 Eclipse 使用,讀取該項目使用 Android 版本號。早期版本名爲: default.properties
Ÿ AndroidManifest.xml :清單文件,在軟件安裝的時候被讀取
Android 中的四大組件( Activity 、 ContentProvider 、 BroadcastReceiver 、 Service )都須要在該文件中註冊
程序所需的權限也須要在此文件中聲明,例如:電話、短信、互聯網、訪問 SD 卡
Ÿ bin :二進制文件,包括 class 、資源文件、 dex 、 apk 等
Ÿ proguard.cfg:用來混淆代碼的配置文件,防止別人反編譯
Ÿ Eclipse 將 .java 源文件編譯成 .class
Ÿ 使用 dx 工具將全部 .class 文件轉換爲 .dex 文件
Ÿ 再將 .dex 文件和全部資源打包成 .apk 文件
Ÿ 將 .apk 文件安裝到虛擬機完成程序安裝
Ÿ 啓動程序 – 開啓進程 – 開啓主線程
Ÿ 建立 Activity 對象 – 執行 OnCreate() 方法
Ÿ 按照 main.xml 文件初始化界面
Ÿ Android 程序中若是出錯,錯誤不會顯示在 Console 中,而是顯示在 LogCat 界面下。能夠從 window – show view 中打開
Ÿ 日誌信息分爲 5 個級別: verbose > debug > info > warn > error 高級的包含低級的
Ÿ 能夠建立過濾器對日誌進行過濾顯示,點擊綠色加號,能夠按照 tag 、 pid 、 level 進行篩選
Ø 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 );
Ø 項目中添加測試類
Ÿ 在 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
Ø 建立測試項目
Ÿ 建立 Android Test Project
Ÿ 輸入項目名,選擇一個已存在的工程, Eclipse 能夠自動配置 Junit 環境
Ø 寫入文件到 SD 卡
Ÿ 須要在清單文件中註冊權限
< uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
Ÿ 2.1 版本如下的 SDCard 位置和 2.2 以後版本不一樣
能夠經過Environment.getExternalStorageDirectory()獲取當前 SDCard 位置,兼容全部版本
Ÿ 獲取 SDCard 狀態
經過Environment.getExternalStorageState()方法獲取 SDCard 當前狀態
常量 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/ 路徑下的文件
Ÿ 獲取當前程序 Files 文件路徑
ContextWrapper.getFilesDir()
Ø Pull 簡介
Ÿ 常見的 XML 解析方式有三種, DOM 、 SAX 、 Pull , Android 系統中推薦使用 Pull
Ÿ Pull 解析器是一個開源的 Java 項目, Android 系統內部解析 XML 文件均爲此種方式,也可用於 JavaEE 項目
Ÿ Android SDK 中已經集成了 Pull 解析器,無需添加任何 jar 文件
Ÿ Pull 解析器運行方式與 SAX 相似,提供各類事件的判斷
Ÿ 官方網站: http://xmlpull.org/
Ø 使用 Pull 解析器解析 XML 文件
Ÿ Xml.newPullParser() 得到解析器
Ÿ parser.setInput(in, "UTF-8" ) 設置輸入流以及編碼
Ÿ parser.next() 獲取下一個解析事件,獲得一個事件代碼
Ÿ XmlPullParser中定義了常量來標識各類解析事件
START_DOCUMENT 、 END_DOCUMENT 、 START_TAG 、END_TAG 、 TEXT
Ø 使用XmlSerializer寫出 XML
Ÿ 使用如下方法生成 XML ,和 XML 文檔順序相似
startDocument
startTag
attribute
text
endTag
endDocument
Ÿ 在程序中保存一些配置參數的時候咱們常用 SharedPreferences
Context.getSharedPreferences(String name, int mode)
該方法能夠在 /data/data/<package>/shared_pref/ 目錄下建立一個以 name 命名的 xml 文件, mode 文件爲模式
Ÿ 存儲偏好
調用edit()方法能夠獲取一個 Editor 對象,對數據進行存儲,存儲以後須要調用 commit()保存到文件
Ÿ 讀取偏好
得到SharedPreferences以後調用 getString() 、 getInt() 等方法獲取其中設置的值
Ÿ 在 Activity 中獲取 SharedPreferences
在 Activity 中能夠調用 getPreferences( int mode)方法得到一個SharedPreferences,文件名和 Activity 名一致
Ÿ Android 平臺中嵌入了一個關係型數據庫 SQLite ,和其餘數據庫不一樣的是 SQLite 存儲數據時不區分類型
例如一個字段聲明爲 Integer 類型,咱們也能夠將一個字符串存入,一個字段聲明爲布爾型,咱們也能夠存入浮點數。
除非是主鍵被定義爲 Integer ,這時只能存儲 64 位整數
Ÿ 建立數據庫的表時能夠不指定數據類型,例如:
CREATE TABLE person(id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20))
CREATE TABLE person(id INTEGER PRIMARY KEY AUTOINCREMENT, name)
Ÿ SQLite 支持大部分標準 SQL 語句,增刪改查語句都是通用的,分頁查詢語句和 MySQL 相同
SELECT * FROM person LIMIT 20 OFFSET 10
SELECT * FROM person LIMIT 10,20
Ÿ 定義類繼承SQLiteOpenHelper
Ÿ 聲明構造函數, 4 個參數
Ÿ 重寫 onCreate ()方法
Ÿ 重寫 upGrade() 方法
Ÿ 注意: SQLite 數據庫中列一旦建立不能修改,若是必定要修改,須要從新建立表,拷貝數據
Ÿ 和 JDBC 訪問數據庫不一樣,操做 SQLite 數據庫無需加載驅動,不用獲取鏈接,直接可使用
獲取 SQLiteDatabase 對象以後經過該對象直接能夠執行 SQL 語句
SQLiteDatabase.execSQL()
SQLiteDatabase.rawQuery()
Ÿ getReadableDatabase()和getWritableDatabase()的區別
查看源代碼後咱們發現getReadableDatabase()在一般狀況下返回的就是getWritableDatabase() 拿到的數據庫
只有在拋出異常的時候纔會以只讀方式打開
Ÿ 數據庫對象緩存
getWritableDatabase() 方法最後會使用一個成員變量記住這個數據庫對象,下次打開時判斷是否重用
Ÿ SQLiteDatabase 封裝了 insert() 、 delete ()、 update ()、 query ()四個方法也能夠對數據庫進行操做
這些方法封裝了部分 SQL 語句,經過參數進行拼接
Ÿ 在使用 SQLite 數據庫時能夠用 SQLiteDatabase類中定義的相關方法控制事務
beginTransaction() 開啓事務
setTransactionSuccessful() 設置事務成功標記
endTransaction() 結束事務
Ÿ endTransaction() 須要放在 finally 中執行,不然事務只有到超時的時候才自動結束,會下降數據庫併發效率
Ÿ 內容提供者是 Android 中的四大組件之一,能夠將應用中的數據對外進行共享
Ÿ 內容提供者將數據的訪問方式統一,沒必要針對不一樣數據類型採起不一樣的訪問策略
Ÿ 內容提供者將數據封裝,只暴露出咱們但願提供給其餘程序的數據
Ÿ 內容提供者中數據更改可被監聽
Ÿ 定義類繼承 ContentProvider ,根據須要重寫內部方法
Ÿ 在清單文件的 <application> 節點下進行配置, <provider> 標籤中須要指定 name 和 authorities 屬性
name 爲類名,包名從程序 Package 開始,以「 . 」開始
authorities :是訪問 Provider 時的路徑,要惟一
Ÿ URI 表明要操做的數據,由 scheme 、 authorites 、 path 三部分組成
content:// cn.itcast. sqlite . provider / person
scheme :固定爲 content ,表明訪問內容提供者
authorites : <provider> 節點中的 authorites 屬性
path :程序定義的路徑,可根據業務邏輯定義
Ÿ 當程序調用 CRUD 方法時會傳入 Uri
Ÿ 咱們經過 Uri 判斷調用者要操做的數據
可使用工具類 UriMatcher 來判斷 Uri
addURI 方法能夠添加 Uri
match 方法能夠匹配一個 Uri 判斷其類型
Ÿ 根據業務邏輯操做數據
Ÿ 經過 Context 得到 ContentResolver 對象
Ÿ 調用 ContentResolver 對象的方法便可訪問內容提供者
Ÿ 若是返回數據是單條數據:vnd.android.cursor.item
Ÿ 若是返回數據是多條數據:vnd.android.cursor.dir
Ÿ 在內容提供者中能夠通知其餘程序數據發生變化
經過 Context 的 getContentResolver() 方法獲取 ContentResolver
調用其notifyChange() 方法發送數據修改通知
Ÿ 在其餘程序中能夠經過ContentObserver監聽數據變化
經過 Context 的 getContentResolver() 方法獲取 ContentResolver
調用其registerContentObserver() 方法指定對某個 Uri 註冊 ContentObserver
自定義ContentObserver,重寫 onChange() 方法獲取數據
Ø 資源地址
Ÿ Git
http://code.google.com/p/msysgit/
Ÿ 源碼
注意:
GIT1.7.7 安裝後不能卸載,能夠用其餘版本覆蓋後再卸載。
使用 GIT 時不要使用中文目錄,不然 GIT GUI 會報錯沒法啓動。刪除 C 盤中 .gitconfig文件能夠解決。
Ÿ 經過 URL 對象封裝地址,打開一個 HttpURLConnection
Ÿ 設置頭信息以後獲取響應碼,若是成功返回 200 便可從 HttpURLConnection 中獲取輸入流讀取數據
Ÿ 代碼過長屏幕顯示不全可使用 <ScrollView> 進行顯示
Ÿ 須要訪問網絡的權限
< uses-permission android:name = "android.permission.INTERNET" />
Ÿ 經過 BitmapFactory 的 decodeByteArray(byte[] data, int offset, int length)方法將數據轉換爲圖片對象
Ÿ 使用 URL 封裝路徑,打開一個 HttpURLConnection
Ÿ 設置頭信息以後獲取相應碼,從輸入流中獲取數據
Ÿ 使用 XmlPullPaser 解析
Ÿ 使用 URL 封裝路徑,打開一個 HttpURLConnection
Ÿ 設置頭信息以後獲取相應碼,從輸入流中獲取數據
Ÿ 將數據轉爲 String ,封裝成 JSONArray 對象
Ÿ 遍歷 JSONArray 對象,調用獲取其中的 JSONObject
Ÿ 再從 JSONObject 中獲取每一個字段的信息
Ÿ 拼接路徑和參數,經過 URL 進行封裝,打開一個 HttpURLConnection ,發送請求
Ÿ 若是參數是中文會出現亂碼
Ÿ URL 中包含的中文參數須要使用 URLEncoder 進行編碼
Ÿ 服務器端若是是 TOMCAT ,其默認使用 ISO8859-1 編碼,接收時須要處理編碼問題
Ÿ 經過 URL 打開一個 HttpURLConnection
Ÿ 頭信息中除了超時時間和請求方式以外還必須設置Content-Type和Content-Length
Ÿ 從 HttpURLConnection 得到輸出流輸出參數數據
Ÿ 服務端可使用 request 對象的 setCharacterEncoding方法設置編碼
Ø 發送 XML
Ÿ 經過 URL 封裝路徑打開一個 HttpURLConnection
Ÿ 設置請求方式,Content-Type和Content-Length
XML 文件的 Content-Type爲:text/xml; charset=UTF-8
Ÿ 使用 HttpURLConnection 獲取輸出流輸出數據
Ø WebService
Ÿ WebService 是發佈在網絡上的 API ,能夠經過發送 XML 調用, WebService 返回結果也是 XML 數據
Ÿ WebService 沒有語言限制,只要能夠發送 XML 數據和接收 XML 數據便可
Ÿ http://www.webxml.com.cn 網站上提供了一些 WebService 服務,咱們能夠對其進行調用
Ÿ http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?op=getMobileCodeInfo 中提供了電話歸屬地查詢的使用說明
Ÿ 搭建服務器,完成上傳功能
Ÿ 使用瀏覽器上傳,查看請求信息
Ø HttpURLConnection
Ÿ 經過 URL 封裝路徑打開一個 HttpURLConnection
Ÿ 設置請求方式以及頭字段:Content-Type、Content-Length、Host
Ÿ 拼接數據發送
Ø Socket
Ÿ 使用 HttpURLConnection 發送時內部有緩存機制,若是上傳較大文件會致使內存溢出
Ÿ 咱們可使用 Socket 發送 TCP 請求,將上傳數據分段發送
Ø HttpClient
public void upload(String name, String password, String path) throws Exception {
// 建立 HttpClient 對象
HttpClient client = new HttpClient();
// 設置超時事件
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
// 建立一個 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 請求設置實體
postMethod.setRequestEntity( new MultipartRequestEntity(parts, postMethod.getParams()));
// 執行 Post 請求
client.executeMethod(postMethod);
// Post 請求是釋放資源
postMethod.releaseConnection();
}
Ÿ 在下載的時候多個線程併發能夠佔用服務器端更多資源,從而加快下載速度
Ÿ 手機端下載數據時不免會出現無信號斷線、電量不足等狀況,因此須要斷點續傳功能
Ÿ 根據下載數據長度計算每一個線程下載的數據位置,程序中開啓多個線程併發下載
在請求頭中設置 Range 字段就能夠獲取指定位置的數據,例如: Range: bytes=100-200
Ÿ 在下載過程當中記錄每一個線程已拷貝數據的數量,若是下載中斷,下次啓動時從記錄位置繼續下載
Ø 多線程下載
Ÿ 進度條使用 <Progress> 進行配置
默認爲圓形進度條,水平進度條須要配置 style 屬性, ?android:attr/progressBarStyleHorizontal
使用 android.R.attr. progressBarStyleHorizontal做爲樣式
Ÿ 當點擊下載按鈕時開啓多線程下載,下載過程當中修改進度條進度
設置最大刻度:setMax()
設置當前進度:setProgress()
Ø 斷點續傳
Ÿ 斷點續傳須要在下載過程當中記錄每條線程的下載進度
Ÿ 每次下載開始以前先讀取數據庫,查詢是否有未完成的記錄,有就繼續下載,沒有則建立新記錄插入數據庫
Ÿ 在每次向文件中寫入數據以後,在數據庫中更新下載進度
Ÿ 下載完成以後刪除數據庫中下載記錄
Ø Handler 傳輸數據
Ÿ 主線程中建立的 View 只能在主線程中修改,其餘線程只能經過和主線程通訊,在主線程中改變 View 數據
Ÿ 咱們使用 Handler 能夠處理這種需求
主線程中建立 Handler ,重寫 handleMessage() 方法
新線程中使用 Handler 發送消息,主線程便可收到消息,而且執行 handleMessage() 方法
Ø 動態生成新 View
Ÿ 建立 XML 文件,將要生成的 View 配置好
Ÿ 獲取系統服務 LayoutInflater ,用來生成新的 View
LayoutInflater inflater = (LayoutInflater) getSystemService( LAYOUT_INFLATER_SERVICE );
Ÿ 使用inflate( int resource, ViewGroup root)方法生成新的 View
Ÿ 調用當前頁面中某個容器的 addView ,將新建立的 View 添加進來
Ø 定義 Activity
Ÿ 定義類繼承 Activity
Ÿ 在 AndroidManifest.xml 的 <application> 節點中聲明 <activity>
Ø 顯式意圖建立方式
Ÿ 構造函數,代碼少
new Intent( this , NewActivity. class );
Ÿ 類名形式,靈活,可擴展性強
intent.setClassName( this , "cn.itcast.activity.NewActivity" );
Ÿ 包名類名形式,可啓動其餘程序中的 Activity
intent.setClassName( "cn.itcast.downloader" , "cn.itcast.downloader.MainActivity" );
Ø 建立 Activity 並傳遞數據
Ÿ 在乎圖對象中封裝了一個 Bundle 對象,能夠用來攜帶數據
Ÿ 在新 Activity 中能夠得到意圖對象以獲取其中 Bundle 保存的數據
Ø 建立 Activity 獲取返回數據
Ÿ 使用startActivityForResult(Intent intent, int requestCode) 方法打開 Activity
Ÿ 重寫onActivityResult( int requestCode, int resultCode, Intent data) 方法
Ÿ 新 Activity 中調用 setResult( int resultCode, Intent data) 設置返回數據以後,關閉 Activity 就會調用 onActivityResult方法
Ø 隱式意圖建立 Activity
Ÿ 顯式意圖是指在建立意圖時指定了組件,而隱式意圖則不指定組件,經過動做、類型、數據匹配對應的組件
Ÿ 在清單文件中定義 <activity> 時須要定義 <intent-filter> 才能被隱式意圖啓動
Ÿ <intent-filter> 中至少配置一個 <action> 和一個 <category> ,不然沒法被啓動
Ÿ Intent 對象中設置的 action 、 category 、 data 在 <intent-filter> 必須所有包含才能啓動
Ÿ <intent-filter> 中的 <action> 、 <category> 、 <data> 均可以配置多個, Intent 對象中不用所有匹配,每樣匹配一個便可啓動
Ÿ 若是一個意圖能夠匹配多個 Activity , Android 系統會提示選擇
Ÿ Acitivity 三種狀態
運行: activity 在最前端運行
暫停: activity 可見,但前端還有其餘 acti vity ,被覆蓋一部分,或者前端 activity 透明
中止: activity 不可見,徹底被覆蓋
Ÿ 生命週期相關方法
onCreate :建立時調用,或者程序在暫停、中止狀態下被殺死以後從新打開時也會調用
onStart : onCreate 以後或者從中止狀態恢復時調用
onResume : onStart 以後或者從暫停狀態恢復時調用,從中止狀態恢復時因爲調用 onStart ,也會調用 onResume
onPause:進入暫停、中止狀態,或者銷燬時會調用
onStop:進入中止狀態,或者銷燬時會調用
onDestroy:銷燬時調用
onRestart :從中止狀態恢復時調用
Ÿ 保存信息相關方法
onSaveInstanceState:在 Activity 被動的摧毀或中止的時候調用,用於保存運行數據,能夠將數據存在在 Bundle 中
onRestoreInstanceState:該方法在 Activity 被從新繪製的時候調用,例如改變屏幕方向, savedInstanceState爲onSaveInstanceState保存的數據
Ÿ 在 AndroidManifest.xml 中的 <activity> 標籤中能夠配置 android:launchMode 屬性,用來控制 Actvity 的啓動模式
Ÿ 在 Android 系統中咱們建立的 Acitivity 是以棧的形式呈現的
standard :每次調用 startActivity() 啓動時都會建立一個新的 Activity 放在棧頂
singleTop :若是啓動的 Activity 時,指定 Activity 不在棧頂就建立,如在棧頂,則再也不建立
singleTask :若是啓動的 Activity 不存在就建立,若是存在直接跳轉到指定的 Activity 所在位置
singleInstance :若是啓動的 Activity 不存在就建立,若是存在就將指定的 Activity 移動到棧頂
Ÿ Android 系統在運行多個進程時,若是系統資源不足,會強制結束一些進程。優先選擇哪一個進程來結束是有優先級的。如下順序靠上的優先結束
空:進程中全部 Activity 都已銷燬
後臺:進程中有一箇中止狀態的 Activity
可見:進程中有一個暫停狀態的 Activity
前臺:進程中正在運行一個 Activity
Ÿ 定義類繼承 BroadcastReceiver ,重寫 onReceive 方法
Ÿ 清單文件中聲明<receiver>,須要在其中配置<intent-filter>指定接收廣播的動做
Ÿ 當接收到匹配廣播以後就會執行 onReceive 方法
Ÿ BroadcastReceiver 除了在清單文件中聲明,也能夠在代碼中聲明,使用 registerReceiver方法註冊 Receiver
Ø 無序廣播
Ÿ 使用sendBroadcast方法發送
Ÿ 被全部廣播接收者接收,無序,不可中斷
Ÿ 廣播時可設置接收者權限,僅當接收者含有權限才能接收
Ÿ 接收者的<receiver>也可設置發送方權限,只接收含有權限應用的廣播
Ø 有序廣播
Ÿ 使用sendOrderedBroadcast方法發送
Ÿ 接收者能夠在<intent-filter>中定義android:priority定義優先級,數字越大優先級越高
Ÿ 被各個廣播接收者逐個接收,中途能夠中斷或者添加數據
abortBroadcast()
getResultExtras( true ).putString( "data" , " 新增數據 " );
Ÿ Android 系統在收到短信的時候會發送一條有序廣播,咱們若是定義一個接收者接收這個廣播,就能夠獲得短信內容,也能夠攔截短信
Ÿ 定義廣播接收者接收廣播 android.provider.Telephony.SMS_RECEIVED
Ÿ 在 onReceive 方法內部調用 Intent 的 getExtras() 再調用 get(String) 獲取其中 pdus 字段,獲得一個 Object[],其中每個元素都是一個 byte[]
Ÿ 經過SmsMessage類的createFromPdu方法建立 SmsMessage 對象
Ÿ 從 SmsMessage 對象中便可獲取發送者號碼、短信內容、發送時間等信息
Ÿ 須要接收短信權限: < uses-permission android:name ="android.permission.RECEIVE_SMS" />
Ÿ Android 系統中收到短信的通知是一個有序通知,咱們如需攔截垃圾短信,能夠配置較高的 priority,收到信息進行判斷是否abortBroadcast()
Ÿ 定義廣播接收者接收 android.intent.action.NEW_OUTGOING_CALL
Ÿ 須要權限 < uses-permission android:name = "android.permission.PROCESS_OUTGOING_CALLS" />
Ÿ 在 onReceive 方法中使用 getResultData() 和 setResultData() 方法獲取和設置電話號碼
Ÿ 廣播接收者的生命週期是很是短暫的,在接收到廣播的時候建立, onReceive() 方法結束以後銷燬
Ÿ 廣播接收者中不要作一些耗時的工做,不然會彈出 Application No Response 錯誤對話框
Ÿ 最好也不要在廣播接收者中建立子線程作耗時的工做,由於廣播接收者被銷燬後進程就成爲了空進程,很容易被系統殺掉
Ÿ 耗時的較長的工做最好放在服務中完成
Ÿ Service 是一種在後臺運行,沒有界面的組件,由其餘組件調用開始。
Ÿ 建立 Service ,定義類繼承 Service , AndroidManifest.xml 中定義 <service>
Ÿ 開啓 Service ,在其餘組件中調用 startService方法
Ÿ 中止 Service ,調用 stopService方法
須要權限: 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 ;
}
}
}
Ÿ 使用bindService綁定服務,傳入一個自定義的ServiceConnection用來接收 IBinder
Ÿ 定義一個業務接口,其中定義須要的使用的方法
Ÿ 服務中自定義一個 IBinder 繼承 Binder 並實現業務接口,在 onBind方法中返回
Ÿ 調用端將 IBinder 轉爲接口類型,調用接口中的方法便可調用到服務中的方法
Ÿ 遠程綁定服務時沒法經過同一個接口來調用方法,這時就須要使用 AIDL 技術
Ÿ 將接口擴展名改成「.aidl」
Ÿ 去掉權限修飾符
Ÿ gen 文件夾下會生成同名接口
Ÿ 將服務中自定義的 IBinder 類改成繼承接口中的 S tub
Ÿ ServiceConnection中返回的 IBinder 是代理對象,不能使用強轉,改用 S tub.asInterface()
Ÿ AIDL 默認只能使用 Java 中基本數據類型和 String 、 List 、 Map , List 和 Map 中的元素類型也只能是這些類型。
Ÿ 若是須要使用其餘類型數據,使用的類必須實現 Parcelable 接口以完成序列化和反序列化工做
重寫 public void writeToParcel(Parcel dest, int flags)
定義 public static final Parcelable.Creator<Person> CREATOR
Ÿ 定義該類對應的 AIDL
package 包名
parcelable 類名
Ÿ 在接口 AIDL 中導入該類,注意:即便是同一個包也須要導入
screenSV .getHolder().setType(SurfaceHolder. SURFACE_TYPE_PUSH_BUFFERS ); // 設置緩衝區數據
screenSV .getHolder().setKeepScreenOn( true ); // 設置屏幕保持
screenSV .getHolder().addCallback( new MyCallback()); // 設置回調函數
player .reset();
player .setDisplay( screenSV .getHolder()); // 設置顯式
player .setDataSource( "/mnt/sdcard/1.mp4" ); // 設置數據源
player .prepare(); // 準備
player .seekTo(position); // 跳轉到指定位置
player .start();
Ÿ 須要權限
< uses-permission android:name = "android.permission.CAMERA" />
Ÿ 打開攝像頭
Camera.open()
SDK2.3 以後支持前置攝像頭, open 方法能夠接收一個 int 參數,用來指定哪一個攝像頭
Ÿ 設置預覽顯示位置
setPreviewDisplay(SurfaceHolder holder)
注意 SurfaceView 不在前端顯示的時候會被銷燬,恢復以後會重繪
Ÿ 開始預覽
startPreview()
將攝像頭拍攝畫面顯示在 SurfaceView 中,在此以前可對攝像頭進行參數配置
getParameters() 方法能夠獲取攝像頭的相關參數Parameters,調用其內部方法便可進行配置
Ÿ 自動對焦
autoFocus(AutoFocusCallback cb)
自動對焦是一個異步操做,若是咱們向等待自動對焦結束以後纔開始拍照,須要傳入一個回調對象,在其回調函數中調用拍照方法
Ÿ 拍照
takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg)
拍照也是異步操做,須要經過回調函數來獲得拍照以後的數據
注意拍照以後攝像頭不回自動回到預覽狀態,須要重寫調用startPreview()方法
Ÿ 須要權限
< uses-permission android:name = "android.permission.RECORD_AUDIO" />
< uses-permission android:name = "android.permission.CAMERA" />
Ÿ 建立MediaRecorder
new MediaRecorder()
Ÿ 設置音頻輸入源
setAudioSource( int audio_source)
Ÿ 設置視頻輸入源
setVideoSource( int video_source)
Ÿ 設置輸出格式
setOutputFormat( int output_format)
Ÿ 設置音頻編碼器
setAudioEncoder( int audio_encoder)
Ÿ 設置視頻編碼器
setVideoEncoder( int video_encoder)
Ÿ 設置預覽顯示位置
setPreviewDisplay(Surface sv)
Ÿ 設置輸出文件
setOutputFile(String path)
Ÿ 準備錄製
prepare()
Ÿ 開始錄製
start()
開始錄製以前須要結束攝像頭的預覽
Ÿ 結束錄製釋放資源
stop()
release()
Ÿ 建立通知
Toast.makeText(Context context, CharSequence text, int duration)
Toast.makeText(Context context, int resId, int duration)
Ÿ 發送通知
show()
Ÿ 獲取系統通知服務
NotificationManager nm = (NotificationManager) getSystemService( NOTIFICATION_SERVICE )
Ÿ 建立通知
經過構造函數建立 : Notification( int icon, CharSequence tickerText, long when)
icon: 通知的圖片資源 ID
tickerText: 狀態欄中顯示的消息內容
when: 時間
Ÿ 建立PendingIntent以供點擊時發送
PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags)
context: 當前上下文
requestCode: 請求碼
intent: 點擊時要發送的意圖
flags: 類型 , PendingIntent中提供了常量選擇
Ÿ 設置通知點擊事件
調用Notification 對象方法 : setLatestEventInfo(Context context, CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent)
context: 當前上下文
contentTitle: 標題
contentText: 內容
contentIntent: 點擊時觸發的意圖
Ÿ 設置通知點擊後清除
設置Notification 對象屬性 n. flags = Notification. FLAG_AUTO_CANCEL ;
Ÿ 發送消息
調用Notification對象方法 : notify( int id, Notification notification)
Ø 普通對話框
new AlertDialog.Builder( this ) //
.setTitle( " 普通對話框 " ) //
.setMessage( " 普通內容 " ) //
.setCancelable( false ) //
.setPositiveButton( "YES" , listener) // listener 爲 OnClickListener 監聽器對象 , 監聽按鈕被選中
.setNeutralButton( "CANCEL" , listener) //
.setNegativeButton( "NO" , listener) //
.show();
Ø 列表對話框
new AlertDialog.Builder( this ) //
.setTitle( " 列表對話框 " ) //
.setCancelable( false ) //
.setItems( items , listener) // listener 爲 OnClickListener 監聽器對象 , 監聽列表項被選中
.show();
Ø 單選對話框
new AlertDialog.Builder( this ) //
.setTitle( " 單選對話框 " ) //
.setCancelable( false ) //
.setSingleChoiceItems( items , 0, choiceLinstener) // 0, 爲默認選中索引 , choiceLinstener 爲 OnClickListener 監聽器對象 , 監聽單選按鈕被選中
.setPositiveButton( " 肯定 " , positiveLinstener) // positiveLinstener 爲 OnClickListener 監聽器對象 , 監聽肯定按鈕點擊
.show();
Ø 多選對話框
new AlertDialog.Builder( this ) //
.setTitle( " 多選對話框 " ) //
.setCancelable( false ) //
.setMultiChoiceItems( items , checkedArr, choiceListener) // checkedArr 爲默認選中 , choiceListener 爲 OnMultiChoiceClickListener 監聽器對象 , 監聽多選按鈕被選中
.setPositiveButton( " 肯定 " , positiveLinstener) // positiveLinstener 爲 OnClickListener 監聽器對象 , 監聽肯定按鈕點擊
.show();
Ø 進度對話框
ProgressDialog dialog = new ProgressDialog( this );
dialog.setProgressStyle(ProgressDialog. STYLE_HORIZONTAL ); // 設置進度條樣式
dialog.setTitle( " 下載中 " );
dialog.setMessage( " 請稍候 ..." );
dialog.setCancelable( false );
dialog.setMax(100);
dialog.show();
dialog.setProgress(10); // 設置進度
dialog.dismiss(); // 對話框結束
關於通知的文檔位置: android-sdk-windows/docs/guide/topics/ui/notifiers/index.html
Ø XML 配置
Ÿ 在主界面中配置 <ListView> 標籤
Ÿ 在 res/layout/ 文件夾下建立一個新的 xml 文件指定每一個條目的佈局
Ø Java 代碼構建 ListView
Ÿ 獲取 ListView 對象
Ÿ 設置一個 Adapter
BaseAdapter :實現內部抽象方法
SimpleAdapter:以 List<Map<String, ?>> 形式封裝數據
SimpleCursorAdapter:以 Cursor 對象封裝數據, Cursor 中須要有「 _id 」一列
Ÿ 添加 OnItemClickListener
調用 ListView 的 getItemAtPosition(int) 方法能夠獲取封裝數據的容器
若是傳入的是 BaseAdapter ,獲取到的就是咱們自定義方法中返回的內容
若是傳入的是SimpleAdapter,獲取到的就是一個 Map<String, ?>
若是傳入的是SimpleCursorAdapter,得到到的就是一個 Cursor ,而且 Cursor 以指向選中的一條記錄
Ÿ 定義 <RadioGroup>
Ÿ 在 <RadioGroup> 中定義 <RadioButton> 和 <Button>
Ÿ 處理 Button 的點擊事件
Ÿ 根據 ID 獲取 RadioGroup 對象,調用其 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();
}
Ÿ 定義若干 <CheckBox> 和一個 <Button>
Ÿ 處理 Button 的點擊事件
Ÿ 根據 ID 獲取每一個 CheckBox ,調用其 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();
}
Ÿ 定義 <Spinner> 標籤
Ÿ 建立一個適配器
Ÿ 獲取 Spinner 標籤,調用 setAdapter(SpinnerAdapter adapter)方法設置一個適配器
Ÿ 調用setOnItemSelectedListener(OnItemSelectedListener listener)方法設置監聽器監聽選中事件
Ø XML 配置
< Spinner
android:id = "@+id/spinner"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content" />
Ø 使用字符串構建適配器
private void setSpinnerByString() {
final Spinner spinner = (Spinner) findViewById(R.id. spinner );
ArrayAdapter<String> adapter = new ArrayAdapter<String>( this , android.R.layout. simple_spinner_item ); // 設置樣式
adapter.setDropDownViewResource(android.R.layout. simple_spinner_dropdown_item ); // 設置下拉後樣式
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 構建適配器
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) {
}
});
}
Ø 使用資源文件構建適配器
< 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) {
}
});
}
Ø 添加菜單項
Ÿ 重寫 Actvity 的 onCreateOptionsMenu(Menu menu)方法
Ÿ 添加菜單項
調用方法中參數 menu 的 add(CharSequence title) 方法
Ÿ 添加子菜單
調用 menu 對象的 addSubMenu( final CharSequence title)
該方法返回一個SubMenu對象
Ÿ 添加子菜單的菜單項
調用SubMenu對象的add(CharSequence title) 方法
Ø 處理菜單點擊事件
Ÿ 重寫 Activity 的 onOptionsItemSelected(MenuItem item) 方法
參數 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);
}
Ø 單次提示
Ø 代碼
< 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());
}
Ø 建立手勢庫
Ÿ 導入 SDK 中的工程
android-sdk-windows\samples\android-8\GestureBuilder
這個工程不能直接導入,須要添加三個配置文件:.classpath、.project、default.properties
Ÿ 將工程部署到手機中,建立手勢庫
手勢庫會存儲在手機 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 );
}
});
Ø 代碼
< 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 內核
webView.loadUrl( "http://192.168.1.10 0 :8080" );
Ø 定義樣式
Ÿ 設置樣式,在 values 文件夾下的任意文件中的 <resources>中配置 <style> 標籤
< style name = " style 1" >
< item name = "android:layout_width" > fill_parent </ item >
< item name = "android:layout_height" > wrap_content </ item >
</ style >
Ÿ 繼承樣式,在 <style> 標籤中配置屬性 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 文件的標籤中配置 style 屬性
< Button
style = "@style/ style2.style3 "
android:text = " 這是 一個按鈕 "
/>
Ÿ 定義過的樣式也能夠應用在 <activity> 和 <application> 標籤中,使用 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 內置的樣式, IDE 自動提示的「 _ 」要替換成「 . 」
Ÿ 在 values 和 drawable 文件夾後加上語言以及地區名,程序中須要國際化的部分使用資源 ID
values-en-rUK
values-en-rUS
values-zh-rCN
values-zh-rTW
Ÿ 匹配規則
在匹配資源時先會找語言、地區徹底匹配的
若是沒有地區匹配的,則查找語言匹配的
若是沒有語言匹配的則找默認 values
Ÿ 在 layout 文件夾後加上分辨率,系統會根據屏幕尺寸自動選擇
注意分辨率中的乘號是「 x 」不是「 * 」
Ÿ 若是沒有匹配的分辨率會找默認 layout 文件夾
Ÿ 經過多個畫面連續播放實現動畫效果
Ÿ 詳見文檔 android-sdk-windows/docs/guide/topics/resources/animation-resource.html
Ÿ 將某個組件以漸變的方式實現透明、縮放、移動、旋轉等動畫效果
Ÿ 詳見文檔 android-sdk-windows/docs/guide/topics/resources/animation-resource.html
Ÿ 在 startActivity() 方法調用以後調用 overridePendingTransition( int enterAnim, int exitAnim)方法
enterAnim 進入的動畫資源 id
exitAnim 退出的動畫 資源 id
Ÿ 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);
}
Ø 傳感器參數
Ÿ 傳感器類型
方向 Sensor. TYPE_ORIENTATION
加速 Sensor. TYPE_ACCELEROMETER
光線 Sensor. TYPE_LIGHT
磁場 Sensor. TYPE_MAGNETIC_FIELD
距離 Sensor. TYPE_PROXIMITY
溫度 Sensor. TYPE_TEMPERATURE
Ÿ 傳感器反應速度
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 );
Ÿ 註冊監聽器
manager .registerListener( listener , sensor , SensorManager. SENSOR_DELAY_NORMAL );
Ÿ 監聽器
private final class MySensorEventListener implements SensorEventListener {
public void onSensorChanged(SensorEvent event) {
System. out .println(event. values [0]);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
Ÿ 取消監聽器
manager .unregisterListener( listener , sensor );
Ø 拖拽
Ÿ 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 軸座標
y = event.getY(); // 獲取 y 軸座標
oldMatrix .set( imageView .getImageMatrix()); // 記住位置
break ;
case MotionEvent. ACTION_MOVE : // 移動時
currentMatrix .set( oldMatrix ); // 設置成按下時記住的位置
currentMatrix .postTranslate(event.getX() - x , event.getY() - y ); // 改變位置
break ;
}
imageView .setImageMatrix( currentMatrix ); // 移動圖片
return true ;
}
}
Ø 多點觸摸
private class MyOnTouchListener implements OnTouchListener {
private float x ; // 圖片移動前的 x 軸座標
private float y ; // 圖片移動前的 y 軸座標
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); // 計算結束時距離
float scale = end / start ; // 計算縮放比例
currentMatrix .postScale(scale, scale, point . x , point . y ); // 設置縮放
}
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);
}
Ø 電話號碼、運營商信息
Ÿ 須要權限
< 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());
Ø 聯繫人
Ÿ 須要權限
< 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" )));
Ø 通話記錄
Ÿ 須要權限
< 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
Ÿ 須要權限
< 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);
Ÿ 殺死當前進程
Process.killProcess(Process.myPid());
Ÿ 退出虛擬機
System.exit(0);
Ÿ 根據包名關閉後臺進程
ActivityManager manager = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
manager.restartPackage( "cn.itcast.test" );
< uses-permission android:name = "android.permission.RESTART_PACKAGES" />
Ÿ 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)));
}
}
}
Ÿ 使用解壓縮工具打開 apk 文件,找到其中 dex 文件
Ÿ 建立 Java 工程,導入 dex2jar中的全部 jar 文件
Ÿ 建立運行環境運行其中pxb.android.dex2jar.v3.Main 類, 指定 dex 文件地址,會在同目錄下生成 jar 文件