前 言
移動應用開發又稱App開發,是近年來的新興軟件開發行業。基于手機設備的特性,App開發與服務器開發、網頁開發等傳統軟件開發有很大不同,將App開發相關技術稱為一門新興學科也不為過。
作為一門學科,必然要求建立一套理論體系,這個理論體系應當具有普遍性與適用性,不會隨著工具的變遷而消亡。App開發就是如此,無論使用Android開發還是iOS開發,所采用的技術、要實現的功能都大同小異,區別在于需要使用不同的編程工具進行開發。對于用戶來說,華為手機上的微信與蘋果手機上的微信都是社交App,這兩個微信在功能和使用上并沒有顯著區別。
筆者從事軟件開發工作十幾年,期間經歷了多次編程方向的轉型,先從C/C++開發轉向Java開發,再從Java開發轉向Android開 發,而Android開發先用ADT后用Android Studio。在多次轉型過程中,筆者深深體會到,無論是編程語言還是開發工具,變化的都是技術實現手段,而不是人類愿景和系統原理。人類愿景是讓生活更加便捷、讓娛樂更加豐富,系統原理是讓軟件界面更加美觀、讓運行速度更加流暢。
本書的寫作目的是教會讀者Android開發,帶領讀者走進一個嶄新的學科領域。市面上的Android開發書籍林林總總,寫作風格各有千秋,不過講解的基本是編程開發,有的還會講解項目管理。本書除了介紹常規的Android開發外,還嘗試從兩方面加以拓展,一方面從產品經理的角度仔細分析App技術能幫用戶做什么事情、能帶給用戶什么收獲;另一方面從設計師的角度詳細論述如何把千篇一律的頁面變得生動活潑,如何讓某個功能實現得更合理、高效。
全書的內容編排采用由淺入深、循序漸進的章節體例,不但考慮初學者的學習連續性,而且可以建立一個統一、連貫的學科體系。這么編排的好處是顯而易見的,讀者只要按照順序學習,就能在學習過程中對已學部分不斷復習鞏固,同時提前預習后面的技術點,一方面銜接自然,另一方面提高學習效率。比如第3章末尾介紹實戰項目“登錄App”,緊接著第4章開頭介紹如何實現登錄頁面的記住密碼功能;第12章介紹“動畫”,一方面為前一章的飛掠橫幅補充動畫效果,另一方面為后一章的相冊切換動畫埋下伏筆。
全書可分為兩大部分,第一部分是第1~8章,主要介紹Android Studio的環境搭建,App開發的各種常用控件,App的數據存儲方式。如何調試App并將App發布上線,這部分囊括了App開發的基礎知識,特別詳細說明App從開發到調試再到上線的企業級開發流程。第二部分是第9~16章,主要介紹App開發的高級部分,包括設備操作、網絡通信、事件、動畫、多媒體、融合技術、第三方開發包、性能優化等,這部分涵蓋App開發的進階內容,與第一部分相比就像是“鳥槍換炮”,讓開發者完成從游擊隊到正規軍的華麗轉變。
建議初學者和在校學生完整學習第1~8章內容,因為這部分包含App開發的必備技能,只有打好基礎,才能進一步學習。至于第9~16章內容,根據前面的學習情況和個人興趣愛好選擇相應的章節學習即可。如果傾向于學習工具類App的開發,就可以選擇學習“第9章 設備操作”“第11章 事件”“第12章 動畫”“第13章 多媒體”;如果傾向于學習企業類App的開發,就可以選擇學習“第10章 網絡通信”“第14章 融合技術”“第15章 第三方開發包”“第16章 性能優化”。
對于有經驗的開發者來說,可以自行選擇不熟悉的知識點拾遺補缺。另外,本書講述的部分知識點很具特色,如衛星導航、Socket通信、多點觸控、百葉窗動畫、音樂播放器、藍牙技術、支付SDK、圖片緩存原理等,這些內容在同類Android入門書籍中鮮有論述,有興趣的讀者可重點關注。
當然,本書面向的讀者不僅是開發人員和計算機專業學生,也包括移動互聯網行業的其他從業人員。對于產品經理來說,可以了解一下某個功能使用的技術,看似簡單的功能,也許并不容易實現。對于設計師來說,“他山之石,可以改玉”,可以參考一下別人的實現方式,也許正好可以激發你的靈感,其實不無裨益。對于測試人員來說,可以熟悉一下每項技術的優缺點,從而制訂出更全面的測試方案,也許能發現更多BUG。
本書所有代碼都基于Android Studio 2.2.3開發,并使用API 25的SDK(Android 7.1.1)編譯與調試通過。讀者在閱讀本書時,若對書中內容有疑問,可在筆者的博客(http://blog.csdn.net/aqi00)留言。
本書范例的素材和代碼下載地址為:http://pan.baidu.com/s/1dFEFEhF(注意區分數字和英文字母大小寫)。如果下載有問題,請發送電子郵件至booksaga@126.com,郵件主題設置為“求從零基礎到App上線下載資源”。
最后,感謝王金柱編輯的熱情指點,感謝我的家人一直以來的支持,沒有他們的鼎力相助,本書就無法順利完成。
歐陽燊
2017年1月
歐陽燊 同濟大學計算機科學與技術專業學士,浙江大學軟件工程專業工程碩士,先后就職于福建新大陸軟件工程公司、亞信科技有限公司杭州研發中心、福建福諾移動通信技術有限公司,歷任系統分析師、高級軟件工程師。具有12年以上軟件開發經驗,熟悉C/C++、Java及相關軟件架構,兩年Android開發經驗,從事一款用戶量超千萬的App項目開發,對Android開發擁有豐富的實戰經驗。
目 錄
第1章 Android Studio環境搭建 1
1.1 Android Studio簡介 2
1.2 Android Studio的安裝 2
1.2.1 開發機配置要求 2
1.2.2 安裝依賴的軟件 3
1.2.3 安裝Android Studio 5
1.3 運行小應用Hello World 7
1.3.1 創建新項目 7
1.3.2 編譯項目/模塊 10
1.3.3 創建模擬器 10
1.3.4 在模擬器上運行App 11
1.4 App的工程結構 12
1.4.1 工程目錄說明 12
1.4.2 編譯配置文件build.gradle 13
1.4.3 App運行配置AndroidManifest.xml 15
1.4.4 在代碼中操縱控件 15
1.5 準備開始 17
1.5.1 使用快捷鍵 17
1.5.2 安裝SVN工具 18
1.5.3 安裝常用插件 19
1.5.4 導入ADT工程 21
1.6 小結 22
第2章 初級控件 23
2.1 屏幕顯示 24
2.1.1 像素 24
2.1.2 顏色 25
2.1.3 屏幕分辨率 26
2.2 簡單布局 27
2.2.1 視圖View的基本屬性 27
2.2.2 線性布局LinearLayout 30
2.2.3 滾動視圖ScrollView 32
2.3 簡單控件 34
2.3.1 文本視圖TextView 34
2.3.2 按鈕Button 38
2.3.3 圖像視圖ImageView 39
2.3.4 圖像按鈕ImageButton 43
2.4 圖形基礎 45
2.4.1 Drawable 46
2.4.2 狀態列表圖形 47
2.4.3 形狀圖形 48
2.4.4 九宮格圖片 51
2.5 實戰項目:簡單計算器 52
2.5.1 設計思路 53
2.5.2 小知識:日志Log/提示Toast 54
2.5.3 代碼示例 55
2.6 小結 58
第3章 中級控件 59
3.1 其他布局 60
3.1.1 相對布局RelativeLayout 60
3.1.2 框架布局FrameLayout 64
3.2 特殊按鈕 65
3.2.1 復選框CheckBox 65
3.2.2 開關按鈕Switch 66
3.2.3 單選按鈕RadioButton 67
3.3 適配視圖基礎 68
3.3.1 下拉框Spinner 68
3.3.2 數組適配器ArrayAdapter 69
3.3.3 簡單適配器SimpleAdapter 70
3.4 編輯框 71
3.4.1 文本編輯框EditText 72
3.4.2 自動完成編輯框AutoCompleteTextView 77
3.5 Activity基礎 78
3.5.1 Activity的生命周期 78
3.5.2 使用Intent傳遞消息 82
3.5.3 向下一個Activity傳遞參數 84
3.5.4 向上一個Activity返回參數 85
3.6 實戰項目:登錄App 88
3.6.1 設計思路 88
3.6.2 小知識:AlertDialog 89
3.6.3 代碼示例 91
3.7 小結 94
第4章 數據存儲 95
4.1 共享參數SharedPreferences 96
4.1.1 基本用法 96
4.1.2 實現記住密碼功能 97
4.2 數據庫SQLite 98
4.2.1 SQLite的基本用法 98
4.2.2 SQLiteOpenHelper 100
4.2.3 優化記住密碼功能 106
4.3 SD卡文件操作 108
4.3.1 SD卡的基本操作 108
4.3.2 文本文件讀寫 110
4.3.3 圖片文件讀寫 111
4.4 Application基礎 112
4.4.1 Application的生命周期 112
4.4.2 利用Application操作全局變量 113
4.5 實戰項目:購物車 115
4.5.1 設計思路 115
4.5.2 小知識:菜單Menu 116
4.5.3 代碼示例 119
4.6 小結 125
第5章 高級控件 126
5.1 日期時間控件 127
5.1.1 日期選擇器DatePicker 127
5.1.2 時間選擇器TimePicker 128
5.2 列表類視圖 129
5.2.1 基本適配器BaseAdapter 129
5.2.2 列表視圖ListView 133
5.2.3 網格視圖GridView 138
5.3 翻頁類視圖 142
5.3.1 翻頁視圖ViewPager 142
5.3.2 翻頁標題欄PagerTitleStrip/PagerTabStrip 145
5.3.3 簡單的啟動引導頁 147
5.4 碎片Fragment 150
5.4.1 靜態注冊 150
5.4.2 動態注冊/碎片適配器FragmentStatePagerAdapter 154
5.4.3 改進的啟動引導頁 157
5.5 Broadcast基礎 159
5.5.1 發送/接收臨時廣播 159
5.5.2 定時器AlarmManager 162
5.6 實戰項目:日歷/日程表 163
5.6.1 設計思路 163
5.6.2 小知識:震動器Vibrator 165
5.6.3 代碼示例 165
5.7 小結 170
第6章 自定義控件 171
6.1 自定義視圖 172
6.1.1 聲明屬性 172
6.1.2 構造對象 175
6.1.3 測量尺寸 176
6.1.4 繪制視圖 179
6.2 自定義動畫 184
6.2.1 任務Runnable 184
6.2.2 下拉刷新動畫 185
6.2.3 圓弧進度動畫 186
6.3 自定義對話框 190
6.3.1 對話框Dialog 190
第13章 多 媒 體
本章介紹App開發常見的多媒體技術,主要包括如何使用各種圖像控件實現自定義相冊、如何使用視頻相關控件實現視頻播放器,另外介紹四大組件之一的ContentProvider的基本概念與常見用法。最后結合本章所學的知識演示一個實戰項目“音樂播放器——浪花音樂”的設計與實現。
13.1 相 冊
本節介紹自定義相冊的實現過程,首先說明使用畫廊或循環視圖如何實現簡單相冊;接著闡述使用圖像切換器如何實現相冊的左右滑動功能;然后分別介紹卡片視圖與調色板的用法,并結合上述圖像控件完成一個圖片查看器——青青相冊。
13.1.1 畫廊Gallery
前幾章使用文件對話框打開圖片時只能看到圖片的文件名,看不到圖片的縮略圖,對用戶來說很不方便,因為光看文件名怎么知道這張圖片什么模樣呢?如果是在電腦上,就可以查看一組圖片的縮略圖列表,很容易找到想要的圖片。在手機上可以使用相應的圖像控件做出縮略圖展示的相冊效果。
畫廊Gallery是專門用于展示圖片列表的控件,左右滑動手勢即可展示內嵌的圖片列表,畫面效果類似于一個平面萬花筒。盡管Android將Gallery標記為Deprecation(表示已廢棄),建議開發者采用HorizontalScrollView或ViewPager代替,不過Gallery用來輪播圖片是一個挺好的選擇。不妨了解一下Gallery控件,并結合其他控件加深對圖像開發的理解。
下面是Gallery的常用方法說明。
? setSpacing:設置圖片之間的間隔大小,對應的XML屬性是spacing。
? setUnselectedAlpha:設置未選定圖片的透明度,對應的XML屬性是unselectedAlpha。取值范圍為0.0~1.0,0.0表示完全透明,1.0表示完全不透明。
? setAdapter:設置畫廊的適配器。
? getSelectedItemId:獲取當前選中的視圖序號。
? setSelection:設置當前選中第幾個視圖。
? setOnItemClickListener:設置單項的點擊監聽器。
使用畫廊看起來很簡單,接下來試著用Gallery結合ImageView實現觀看畫廊的相冊效果。首先在布局文件中放置一個框架布局FrameLayout,里面放一個畫廊控件與一個圖像視圖控件,ImageView設置為充滿整個屏幕,Gallery放在屏幕下方;然后監聽Gallery控件的單項點擊事件,當用戶點擊指定圖片項時,使用ImageView控件填充該圖片,也就是點小圖看大圖。
下面是通過Gallery與ImageView實現簡單相冊的代碼:
public class GalleryActivity extends AppCompatActivity implements OnItemClickListener {
private ImageView iv_gallery;
private Gallery gl_gallery;
private int[] mImageRes = { R.drawable.scene1, R.drawable.scene2, R.drawable.scene3,
R.drawable.scene4, R.drawable.scene5, R.drawable.scene6 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gallery);
iv_gallery = (ImageView) findViewById(R.id.iv_gallery);
iv_gallery.setImageResource(mImageRes[0]);
int dip_pad = Utils.dip2px(this, 20);
gl_gallery = (Gallery) findViewById(R.id.gl_gallery);
gl_gallery.setPadding(0, dip_pad, 0, dip_pad);
gl_gallery.setSpacing(dip_pad);
gl_gallery.setUnselectedAlpha(0.5f);
gl_gallery.setAdapter(new GalleryAdapter(this, mImageRes));
gl_gallery.setOnItemClickListener(this);
}
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
iv_gallery.setImageResource(mImageRes[position]);
}
}
Gallery相冊的畫面效果如圖13-1和圖13-2所示。其中,圖13-1所示為展示相冊第一張圖片時的畫面;圖13-2所示為點擊第二張小圖時,屏幕展示第二張大圖的畫面。
圖13-1 畫廊展示第一張圖片 圖13-2 畫廊展示第二張圖片
如果想用其他控件替代Gallery,就可以考慮使用功能強大的循環視圖RecyclerView。具體實現時主要是定義一個水平方向的線性布局管理器,然后通過適配器填入圖片列表。
使用RecyclerView與ImageView實現相冊的代碼很簡單,舉例如下:
public class RecyclerViewActivity extends AppCompatActivity implements OnItemClickListener {
private ImageView iv_photo;
private RecyclerView rv_photo;
private int[] mImageRes = { R.drawable.scene1, R.drawable.scene2, R.drawable.scene3,
R.drawable.scene4, R.drawable.scene5, R.drawable.scene6 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_view);
iv_photo = (ImageView) findViewById(R.id.iv_photo);
iv_photo.setImageResource(mImageRes[0]);
rv_photo = (RecyclerView) findViewById(R.id.rv_photo);
LinearLayoutManager manager = new LinearLayoutManager(this);
manager.setOrientation(LinearLayout.HORIZONTAL);
rv_photo.setLayoutManager(manager);
PhotoAdapter adapter = new PhotoAdapter(this, mImageRes);
adapter.setOnItemClickListener(this);
rv_photo.setAdapter(adapter);
rv_photo.setItemAnimator(new DefaultItemAnimator());
rv_photo.addItemDecoration(new SpacesItemDecoration(20));
}
@Override
public void onItemClick(View view, int position) {
iv_photo.setImageResource(mImageRes[position]);
rv_photo.scrollToPosition(position);
}
}
使用RecyclerView方式實現的相冊效果如圖13-3和圖13-4所示。其中,圖13-3所示為展示相冊第3張圖片時的畫面;圖13-4所示為點擊第4張小圖時,屏幕展示第4張大圖的畫面。
圖13-3 循環視圖展示第3張圖片 圖13-4 循環視圖展示第4張圖片
13.1.2 圖像切換器ImageSwitcher
可能讀者已經發現,前面Gallery相冊在切換大圖時比較生硬,前后兩張圖片閃一下就切過去了,用戶體驗不夠友好。有沒有辦法讓圖片切換自然一些呢,比如通過漸變動畫的方式?答案肯定是有的,就是把占據整個屏幕的圖像視圖ImageView換成圖像切換器ImageSwitcher,然后通過ImageSwitcher實現前后圖片的切換動畫。
ImageSwitcher繼承自視圖動畫器ViewAnimator,用于承載前后兩個圖像的變換動畫;與之對應的是,文本切換器 TextSwitcher承載前后兩個文本的變換動畫;第11章介紹的飛掠視圖ViewFlipper是從ViewAnimator派生而來,讀者已經知道它 用來承載前后兩個視圖的變換動畫。
下面介紹ImageSwitcher的常用方法。
? setFactory:設置一個視圖工廠。該視圖工廠由ViewFactory派生而來,需重寫makeView方法返回工廠的具體視圖。對于ImageSwitcher來說,工廠返回的是ImageView對象。
? setImageResource:設置當前圖像的資源ID。該方法與下面的setImageDrawable方法和setImageURI方法為三選一操作,調用了其中一個方法,就無須調用另外兩個方法。
? setImageDrawable:設置當前圖像的Drawable對象。
? setImageURI:設置當前圖像的URI地址。
? setInAnimation:設置后一個圖像的進入動畫。
? setOutAnimation:設置前一個圖像的退出動畫。
這里運用的動畫技術跟第11章和第12章的飛掠視圖類似。首先,對前后圖片的切換動畫可以事先設置好集合動畫,通過setInAnimation和setOutAnimation方法完成動畫調用;其次,前后圖片的切換操作不但可由Gallery控件的點擊操作出發,而且可由手勢的左滑和右滑操作觸發,這要借助于手勢檢測器GestureDetector,通過檢測左滑手勢和右滑手勢自動輪播 圖片。
按照以上的設計思路使用ImageSwitcher實現相冊切換動畫的代碼如下:
public void onItemClick(AdapterView parent, View view, int position, long id) {
is_switcher.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_in));
is_switcher.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_out));
is_switcher.setImageResource(mImageRes[position]);
}
public class ViewFactoryImpl implements ViewFactory {
@Override
public View makeView() {
ImageView iv = new ImageView(ImageSwitcherActivity.this);
iv.setBackgroundColor(0xFFFFFFFF);
iv.setScaleType(ScaleType.FIT_XY);
iv.setLayoutParams(new ImageSwitcher.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
return iv;
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
mGesture.onTouchEvent(event);
return true;
}