> 編寫:[awong1900](https://github.com/awong1900) - 原文:[http://developer.android.com/training/tv/discovery/searchable.html](http://developer.android.com/training/tv/discovery/searchable.html)
安卓TV使用安卓[搜索接口](http://developer.android.com/guide/topics/search/index.html)從安裝的應用中檢索內容數據并且釋放搜索結果給用戶。你的應用內容數據能被包含在這些結果中,去給用戶即時訪問應用程序中的內容。
你的應用必須提供安卓TV數據字段,它是用戶在搜索框中輸入字符生成的建議搜索結果。去做這個,你的應用必須實現[Content Provider](http://developer.android.com/guide/topics/providers/content-providers.html),在[searchable.xml](http://developer.android.com/guide/topics/search/searchable-config.html)配置文件描述content provider和其他必要的安卓TV信息。你也需要一個[activity](# "An activity represents a single screen with a user interface.")在用戶選擇一個建議的搜索結果時處理intent的觸發。所有的這些被描述在[Adding Custom Suggestions](http://developer.android.com/guide/topics/search/adding-custom-suggestions.html)。本文描述安卓TV應用搜索的關鍵點。
這節課展示安卓中搜索的知識,展示如何使你的應用在安卓TV里是可被搜索的。確信你熟悉[Search API guide](http://developer.android.com/guide/topics/search/index.html)的解釋。在下面的這節課程之前,查看[Adding Search Functionality](http://developer.android.com/training/search/index.html)訓練。
這個討論描述了一些代碼,從[安卓Leanback示例代碼](https://github.com/googlesamples/androidtv-Leanback)摘出。代碼可以在Github上找到。
### 識別列
[SearchManager](http://developer.android.com/reference/android/app/SearchManager.html)描述了數據字段,它被代表為SOLite數據庫的列。不管你的數據格式,你必須把你的數據字段填到那些列,通常用存取你的內容數據的類。更多信息,查看[Building a suggestion table()](http://developer.android.com/guide/topics/search/adding-custom-suggestions.html#SuggestionTable)。
SearchManager類為安卓TV包含了幾個列。下面是重要的一些列:
| 值 | 描述 |
|-----|-----|
| `SUGGEST_COLUMN_TEXT_1` | 內容名字 **(required)** |
| `SUGGEST_COLUMN_TEXT_2` | 內容的文本描述 |
| `SUGGEST_COLUMN_RESULT_CARD_IMAGE` | 圖片/封面 |
| `SUGGEST_COLUMN_CONTENT_TYPE` | 媒體的MIME類型 **(required)** |
| `SUGGEST_COLUMN_VIDEO_WIDTH` | 媒體的分辨率寬度`SUGGEST_COLUMN_VIDEO_HEIGHT` | 媒體的分辨率高度 |
| `SUGGEST_COLUMN_PRODUCTION_YEAR` | 內容的產品年份 **(required)** |
| `SUGGEST_COLUMN_DURATION` | 媒體的時間長度 |
搜索framework需要以下的列:
- [SUGGEST_COLUMN_TEXT_1](http://developer.android.com/reference/android/app/SearchManager.html#SUGGEST_COLUMN_TEXT_1)
- [SUGGEST_COLUMN_CONTENT_TYPE](http://developer.android.com/reference/android/app/SearchManager.html#SUGGEST_COLUMN_CONTENT_TYPE)
- [SUGGEST_COLUMN_PRODUCTION_YEAR](http://developer.android.com/reference/android/app/SearchManager.html#SUGGEST_COLUMN_PRODUCTION_YEAR)
當這些內容的列的值匹配Google服務的providers提供的的值時,系統提供一個[深鏈接](http://developer.android.com/training/app-indexing/deep-linking.html)到你的應用,用于詳情查看,以及指向應用的其他Providers的鏈接。更多討論在[在詳情頁顯示內容](http://developer.android.com/training/tv/discovery/searchable.html#details)。
你的應用的數據庫類可能定義以下的列:
~~~
public class VideoDatabase {
//The columns we'll include in the video database table
public static final String KEY_NAME = SearchManager.SUGGEST_COLUMN_TEXT_1;
public static final String KEY_DESCRIPTION = SearchManager.SUGGEST_COLUMN_TEXT_2;
public static final String KEY_ICON = SearchManager.SUGGEST_COLUMN_RESULT_CARD_IMAGE;
public static final String KEY_DATA_TYPE = SearchManager.SUGGEST_COLUMN_CONTENT_TYPE;
public static final String KEY_IS_LIVE = SearchManager.SUGGEST_COLUMN_IS_LIVE;
public static final String KEY_VIDEO_WIDTH = SearchManager.SUGGEST_COLUMN_VIDEO_WIDTH;
public static final String KEY_VIDEO_HEIGHT = SearchManager.SUGGEST_COLUMN_VIDEO_HEIGHT;
public static final String KEY_AUDIO_CHANNEL_CONFIG =
SearchManager.SUGGEST_COLUMN_AUDIO_CHANNEL_CONFIG;
public static final String KEY_PURCHASE_PRICE = SearchManager.SUGGEST_COLUMN_PURCHASE_PRICE;
public static final String KEY_RENTAL_PRICE = SearchManager.SUGGEST_COLUMN_RENTAL_PRICE;
public static final String KEY_RATING_STYLE = SearchManager.SUGGEST_COLUMN_RATING_STYLE;
public static final String KEY_RATING_SCORE = SearchManager.SUGGEST_COLUMN_RATING_SCORE;
public static final String KEY_PRODUCTION_YEAR = SearchManager.SUGGEST_COLUMN_PRODUCTION_YEAR;
public static final String KEY_COLUMN_DURATION = SearchManager.SUGGEST_COLUMN_DURATION;
public static final String KEY_ACTION = SearchManager.SUGGEST_COLUMN_INTENT_ACTION;
...
~~~
當你創建從[SearchManager](http://developer.android.com/reference/android/app/SearchManager.html)列填充到你的數據字段時,你也必須定義[_ID](http://developer.android.com/reference/android/provider/BaseColumns.html#_ID)去獲得每行的獨一無二的ID。
~~~
...
private static HashMap buildColumnMap() {
HashMap map = new HashMap();
map.put(KEY_NAME, KEY_NAME);
map.put(KEY_DESCRIPTION, KEY_DESCRIPTION);
map.put(KEY_ICON, KEY_ICON);
map.put(KEY_DATA_TYPE, KEY_DATA_TYPE);
map.put(KEY_IS_LIVE, KEY_IS_LIVE);
map.put(KEY_VIDEO_WIDTH, KEY_VIDEO_WIDTH);
map.put(KEY_VIDEO_HEIGHT, KEY_VIDEO_HEIGHT);
map.put(KEY_AUDIO_CHANNEL_CONFIG, KEY_AUDIO_CHANNEL_CONFIG);
map.put(KEY_PURCHASE_PRICE, KEY_PURCHASE_PRICE);
map.put(KEY_RENTAL_PRICE, KEY_RENTAL_PRICE);
map.put(KEY_RATING_STYLE, KEY_RATING_STYLE);
map.put(KEY_RATING_SCORE, KEY_RATING_SCORE);
map.put(KEY_PRODUCTION_YEAR, KEY_PRODUCTION_YEAR);
map.put(KEY_COLUMN_DURATION, KEY_COLUMN_DURATION);
map.put(KEY_ACTION, KEY_ACTION);
map.put(BaseColumns._ID, "rowid AS " +
BaseColumns._ID);
map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " +
SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
map.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, "rowid AS " +
SearchManager.SUGGEST_COLUMN_SHORTCUT_ID);
return map;
}
...
~~~
在上面的例子中,注意填充[SUGGEST_COLUMN_INTENT_DATA_ID](http://developer.android.com/reference/android/app/SearchManager.html#SUGGEST_COLUMN_INTENT_DATA_ID)字段。這是URI的一部分,指向獨一無二的內容到這一列的數據,那是URI描述的內容被存儲的最后部分。在URI的第一部分,與所有表格的列同樣,是設置[在searchable.xml](http://developer.android.com/guide/topics/search/searchable-config.html)文件,用[android:searchSuggestIntentData](http://developer.android.com/guide/topics/search/searchable-config.html#searchSuggestIntentData)屬性。屬性被描述在[Handle Search Suggestions](http://developer.android.com/training/tv/discovery/searchable.html#suggestions)。
如果URI的第一部分是不同于表格的每一列,你填充[SUGGEST_COLUMN_INTENT_DATA](http://developer.android.com/reference/android/app/SearchManager.html#SUGGEST_COLUMN_INTENT_DATA)字段的值。當用戶選擇這個內容時,這個intent被啟動依據[SUGGEST_COLUMN_INTENT_DATA_ID](http://developer.android.com/reference/android/app/SearchManager.html#SUGGEST_COLUMN_INTENT_DATA_ID)的混合intent數據或者`android:searchSuggestIntentData`屬性和[SUGGEST_COLUMN_INTENT_DATA](http://developer.android.com/reference/android/app/SearchManager.html#SUGGEST_COLUMN_INTENT_DATA)字段值之一。
### 提供搜索建議數據
實現一個[Content Provider](http://developer.android.com/guide/topics/providers/content-providers.html)去返回搜索術語建議到安卓TV搜索框。系統需要你的內容容器提供建議,通過調用每次一個字母類型[query()](http://developer.android.com/reference/android/content/ContentProvider.html#query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String))方法。在[query()](http://developer.android.com/reference/android/content/ContentProvider.html#query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String))的實現中,你的內容容器搜索你的建議數據并且返回一個光標指向你已經指定的建議列。
~~~
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
// Use the UriMatcher to see what kind of query we have and format the db query accordingly
switch (URI_MATCHER.match(uri)) {
case SEARCH_SUGGEST:
Log.d(TAG, "search suggest: " + selectionArgs[0] + " URI: " + uri);
if (selectionArgs == null) {
throw new IllegalArgumentException(
"selectionArgs must be provided for the Uri: " + uri);
}
return getSuggestions(selectionArgs[0]);
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
}
private Cursor getSuggestions(String query) {
query = query.toLowerCase();
String[] columns = new String[]{
BaseColumns._ID,
VideoDatabase.KEY_NAME,
VideoDatabase.KEY_DESCRIPTION,
VideoDatabase.KEY_ICON,
VideoDatabase.KEY_DATA_TYPE,
VideoDatabase.KEY_IS_LIVE,
VideoDatabase.KEY_VIDEO_WIDTH,
VideoDatabase.KEY_VIDEO_HEIGHT,
VideoDatabase.KEY_AUDIO_CHANNEL_CONFIG,
VideoDatabase.KEY_PURCHASE_PRICE,
VideoDatabase.KEY_RENTAL_PRICE,
VideoDatabase.KEY_RATING_STYLE,
VideoDatabase.KEY_RATING_SCORE,
VideoDatabase.KEY_PRODUCTION_YEAR,
VideoDatabase.KEY_COLUMN_DURATION,
VideoDatabase.KEY_ACTION,
SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID
};
return mVideoDatabase.getWordMatch(query, columns);
}
...
~~~
在你的manifest文件中,內容容器接受特殊處理。相比被標記為一個[activity](# "An activity represents a single screen with a user interface."),它是被描述為[[provider](http://developer.android.com/guide/topics/manifest/provider-element.html)](#)。provider包括`android:searchSuggestAuthority`屬性去告訴系統你的內容容器的名字空間。并且,你必須設置它的`android:exported`屬性為`"true"`,這樣安卓全局搜索能用它返回的搜索結果。
~~~
<provider android:name="com.example.android.tvleanback.VideoContentProvider"
android:authorities="com.example.android.tvleanback"
android:exported="true" />
~~~
### 處理搜索建議
你的應用必須包括[res/xml/searchable.xml](http://developer.android.com/guide/topics/search/searchable-config.html)文件去配置搜索建議設置。它包括[android:searchSuggestAuthority](http://developer.android.com/guide/topics/search/searchable-config.html#searchSuggestAuthority)屬性去告訴系統內容容器的名字空間。這必須匹配在`AndroidManifest.xml`文件的[[provider](http://developer.android.com/guide/topics/manifest/provider-element.html)](#)元素的[android:authorities](http://developer.android.com/guide/topics/manifest/provider-element.html#auth) 屬性的字符串值。
[searchable.xml](http://developer.android.com/guide/topics/search/searchable-config.html)文件必須也包含在`"android.intent.action.VIEW"`的[android:searchSuggestIntentAction](http://developer.android.com/guide/topics/search/searchable-config.html#searchSuggestIntentAction)值去定義提供自定義建議的intent action。這與提供一個搜索術語的intent action不同,下面解釋。查看[Declaring the intent action](http://developer.android.com/guide/topics/search/adding-custom-suggestions.html#IntentAction) 用另一種方式去定義建議的intent action。
同intent action一起,你的應用必須提供你定義的[android:searchSuggestIntentData](http://developer.android.com/guide/topics/search/searchable-config.html#searchSuggestIntentData)屬性的intent數據。這是指向內容的URI的第一部分。它描述在填充的內容表格中URI所有共同列的部分。URI的獨一無二的部分用 [SUGGEST_COLUMN_INTENT_DATA_ID](http://developer.android.com/reference/android/app/SearchManager.html#SUGGEST_COLUMN_INTENT_DATA_ID)字段建立每一列,以上被描述在[識別列](http://developer.android.com/training/tv/discovery/searchable.html#columns)。查看[Declaring the intent data](http://developer.android.com/guide/topics/search/adding-custom-suggestions.html#IntentData)用另一種方式去定義建議的intent數據。
并且,注意`android:searchSuggestSelection="?"`屬性為特定的值。這個值作為[query()](http://developer.android.com/reference/android/content/ContentProvider.html#query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String))方法`selection`參數。方法的問題標記(?)值被代替為請求文本。
最后,你也必須包含[android:includeInGlobalSearch](http://developer.android.com/guide/topics/search/searchable-config.html#includeInGlobalSearch)屬性值為`"true"`。這是一個[searchable.xml](http://developer.android.com/guide/topics/search/searchable-config.html)文件的例子:
~~~
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/search_label"
android:hint="@string/search_hint"
android:searchSettingsDescription="@string/settings_description"
android:searchSuggestAuthority="com.example.android.tvleanback"
android:searchSuggestIntentAction="android.intent.action.VIEW"
android:searchSuggestIntentData="content://com.example.android.tvleanback/video_database_leanback"
android:searchSuggestSelection=" ?"
android:searchSuggestThreshold="1"
android:includeInGlobalSearch="true"
>
</searchable>
~~~
### 處理搜索術語
一旦搜索框有一個字匹配到了應用列中的一個(被描述在上文的[識別列](http://developer.android.com/training/tv/discovery/searchable.html#identifying)),系統啟動[ACTION_SEARCH](http://developer.android.com/reference/android/content/Intent.html#ACTION_SEARCH) intent。你應用的[activity](# "An activity represents a single screen with a user interface.")處理intent搜索列的給定的字段資源,并且返回一個那些內容項的列表。在你的`AndroidManifest.xml`文件中,你指定的[activity](# "An activity represents a single screen with a user interface.")處理[ACTION_SEARCH](http://developer.android.com/reference/android/content/Intent.html#ACTION_SEARCH) intent,像這樣:
~~~
...
<activity
android:name="com.example.android.tvleanback.DetailsActivity"
android:exported="true">
<!-- Receives the search request. -->
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<!-- No category needed, because the Intent will specify this class component -->
</intent-filter>
<!-- Points to searchable meta data. -->
<meta-data android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
...
<!-- Provides search suggestions for keywords against video meta data. -->
<provider android:name="com.example.android.tvleanback.VideoContentProvider"
android:authorities="com.example.android.tvleanback"
android:exported="true" />
...
~~~
[activity](# "An activity represents a single screen with a user interface.")必須參考[searchable.xml](http://developer.android.com/guide/topics/search/searchable-config.html)文件描述可搜索的設置。用[全局搜索框](http://developer.android.com/guide/topics/search/search-dialog.html),manifest必須描述[activity](# "An activity represents a single screen with a user interface.")應該收到的搜索請求。manifest必須描述[[provider](http://developer.android.com/guide/topics/manifest/provider-element.html)](#)元素,詳細被描述在[searchable.xml](http://developer.android.com/guide/topics/search/searchable-config.html)文件。
### 深鏈接到應用的詳情頁
如果你有設置[處理搜索建議](http://developer.android.com/training/tv/discovery/searchable.html#suggestions)描述的搜索配置和填充 [SUGGEST_COLUMN_TEXT_1](http://developer.android.com/reference/android/app/SearchManager.html#SUGGEST_COLUMN_TEXT_1),[SUGGEST_COLUMN_CONTENT_TYPE](http://developer.android.com/reference/android/app/SearchManager.html#SUGGEST_COLUMN_CONTENT_TYPE)和[SUGGEST_COLUMN_PRODUCTION_YEAR](http://developer.android.com/reference/android/app/SearchManager.html#SUGGEST_COLUMN_PRODUCTION_YEAR)字段到[識別列](http://developer.android.com/training/tv/discovery/searchable.html#columns),一個[深鏈接](http://developer.android.com/training/app-indexing/deep-linking.html)去查看詳情頁的內容。當用戶選擇一個搜索結果時,詳情頁將打開。如圖1。

**圖1** 詳情頁顯示一個深鏈接為Google(Leanback)的視頻代碼。Sintel: ? copyright Blender Foundation, www.sintel.org.
當用戶選擇你的應用鏈接,`“Available On”`按鈕被標識在詳情頁,系統啟動[activity](# "An activity represents a single screen with a user interface.")處理[ACTION_VIEW](http://developer.android.com/reference/android/content/Intent.html#ACTION_VIEW)(在[searchable.xml](http://developer.android.com/guide/topics/search/searchable-config.html#searchSuggestIntentAction)文件設置[android:searchSuggestIntentAction](http://developer.android.com/guide/topics/search/searchable-config.html#searchSuggestIntentAction)值為`"android.intent.action.VIEW"`)。
你也能設置用戶intent去啟動你的[activity](# "An activity represents a single screen with a user interface."),這個在[在安卓Leanback示例代碼應用](https://github.com/googlesamples/androidtv-Leanback)中演示。注意示例應用啟動它自己的`LeanbackDetailsFragment`去顯示被選擇媒體的詳情,但是你應該啟動[activity](# "An activity represents a single screen with a user interface.")去播放媒體。立即去保存用戶的另一次或兩次點擊。
[下一節: 使TV應用是可被搜索的](#)
- 序言
- Android入門基礎:從這里開始
- 建立第一個App
- 創建Android項目
- 執行Android程序
- 建立簡單的用戶界面
- 啟動其他的Activity
- 添加ActionBar
- 建立ActionBar
- 添加Action按鈕
- 自定義ActionBar的風格
- ActionBar的覆蓋層疊
- 兼容不同的設備
- 適配不同的語言
- 適配不同的屏幕
- 適配不同的系統版本
- 管理Activity的生命周期
- 啟動與銷毀Activity
- 暫停與恢復Activity
- 停止與重啟Activity
- 重新創建Activity
- 使用Fragment建立動態的UI
- 創建一個Fragment
- 建立靈活動態的UI
- Fragments之間的交互
- 數據保存
- 保存到Preference
- 保存到文件
- 保存到數據庫
- 與其他應用的交互
- Intent的發送
- 接收Activity返回的結果
- Intent過濾
- Android分享操作
- 分享簡單的數據
- 給其他App發送簡單的數據
- 接收從其他App返回的數據
- 給ActionBar增加分享功能
- 分享文件
- 建立文件分享
- 分享文件
- 請求分享一個文件
- 獲取文件信息
- 使用NFC分享文件
- 發送文件給其他設備
- 接收其他設備的文件
- Android多媒體
- 管理音頻播放
- 控制音量與音頻播放
- 管理音頻焦點
- 兼容音頻輸出設備
- 拍照
- 簡單的拍照
- 簡單的錄像
- 控制相機硬件
- 打印
- 打印照片
- 打印HTML文檔
- 打印自定義文檔
- Android圖像與動畫
- 高效顯示Bitmap
- 高效加載大圖
- 非UI線程處理Bitmap
- 緩存Bitmap
- 管理Bitmap的內存
- 在UI上顯示Bitmap
- 使用OpenGL ES顯示圖像
- 建立OpenGL ES的環境
- 定義Shapes
- 繪制Shapes
- 運用投影與相機視圖
- 添加移動
- 響應觸摸事件
- 添加動畫
- View間漸變
- 使用ViewPager實現屏幕側滑
- 展示卡片翻轉動畫
- 縮放View
- 布局變更動畫
- Android網絡連接與云服務
- 無線連接設備
- 使得網絡服務可發現
- 使用WiFi建立P2P連接
- 使用WiFi P2P服務
- 執行網絡操作
- 連接到網絡
- 管理網絡
- 解析XML數據
- 高效下載
- 為網絡訪問更加高效而優化下載
- 最小化更新操作的影響
- 避免下載多余的數據
- 根據網絡類型改變下載模式
- 云同步
- 使用備份API
- 使用Google Cloud Messaging
- 解決云同步的保存沖突
- 使用Sync Adapter傳輸數據
- 創建Stub授權器
- 創建Stub Content Provider
- 創建Sync Adpater
- 執行Sync Adpater
- 使用Volley執行網絡數據傳輸
- 發送簡單的網絡請求
- 建立請求隊列
- 創建標準的網絡請求
- 實現自定義的網絡請求
- Android聯系人與位置信息
- Android聯系人信息
- 獲取聯系人列表
- 獲取聯系人詳情
- 使用Intents修改聯系人信息
- 顯示聯系人頭像
- Android位置信息
- 獲取最后可知位置
- 獲取位置更新
- 顯示位置地址
- 創建和監視地理圍欄
- Android可穿戴應用
- 賦予Notification可穿戴特性
- 創建Notification
- 在Notifcation中接收語音輸入
- 為Notification添加顯示頁面
- 以Stack的方式顯示Notifications
- 創建可穿戴的應用
- 創建并運行可穿戴應用
- 創建自定義的布局
- 添加語音功能
- 打包可穿戴應用
- 通過藍牙進行調試
- 創建自定義的UI
- 定義Layouts
- 創建Cards
- 創建Lists
- 創建2D-Picker
- 創建確認界面
- 退出全屏的Activity
- 發送并同步數據
- 訪問可穿戴數據層
- 同步數據單元
- 傳輸資源
- 發送與接收消息
- 處理數據層的事件
- Android TV應用
- 創建TV應用
- 創建TV應用的第一步
- 處理TV硬件部分
- 創建TV的布局文件
- 創建TV的導航欄
- 創建TV播放應用
- 創建目錄瀏覽器
- 提供一個Card視圖
- 創建詳情頁
- 顯示正在播放卡片
- 幫助用戶在TV上探索內容
- TV上的推薦內容
- 使得TV App能夠被搜索
- 使用TV應用進行搜索
- 創建TV游戲應用
- 創建TV直播應用
- TV Apps Checklist
- Android企業級應用
- Ensuring Compatibility with Managed Profiles
- Implementing App Restrictions
- Building a Work Policy Controller
- Android交互設計
- 設計高效的導航
- 規劃屏幕界面與他們之間的關系
- 為多種大小的屏幕進行規劃
- 提供向下和橫向導航
- 提供向上和歷史導航
- 綜合:設計樣例 App
- 實現高效的導航
- 使用Tabs創建Swipe視圖
- 創建抽屜導航
- 提供向上的導航
- 提供向后的導航
- 實現向下的導航
- 通知提示用戶
- 建立Notification
- 當啟動Activity時保留導航
- 更新Notification
- 使用BigView風格
- 顯示Notification進度
- 增加搜索功能
- 建立搜索界面
- 保存并搜索數據
- 保持向下兼容
- 使得你的App內容可被Google搜索
- 為App內容開啟深度鏈接
- 為索引指定App內容
- Android界面設計
- 為多屏幕設計
- 兼容不同的屏幕大小
- 兼容不同的屏幕密度
- 實現可適應的UI
- 創建自定義View
- 創建自定義的View類
- 實現自定義View的繪制
- 使得View可交互
- 優化自定義View
- 創建向后兼容的UI
- 抽象新的APIs
- 代理至新的APIs
- 使用舊的APIs實現新API的效果
- 使用版本敏感的組件
- 實現輔助功能
- 開發輔助程序
- 開發輔助服務
- 管理系統UI
- 淡化系統Bar
- 隱藏系統Bar
- 隱藏導航Bar
- 全屏沉浸式應用
- 響應UI可見性的變化
- 創建使用Material Design的應用
- 開始使用Material Design
- 使用Material的主題
- 創建Lists與Cards
- 定義Shadows與Clipping視圖
- 使用Drawables
- 自定義動畫
- 維護兼容性
- Android用戶輸入
- 使用觸摸手勢
- 檢測常用的手勢
- 跟蹤手勢移動
- Scroll手勢動畫
- 處理多觸摸手勢
- 拖拽與縮放
- 管理ViewGroup中的觸摸事件
- 處理鍵盤輸入
- 指定輸入法類型
- 處理輸入法可見性
- 兼容鍵盤導航
- 處理按鍵動作
- 兼容游戲控制器
- 處理控制器輸入動作
- 支持不同的Android系統版本
- 支持多個控制器
- Android后臺任務
- 在IntentService中執行后臺任務
- 創建IntentService
- 發送工作任務到IntentService
- 報告后臺任務執行狀態
- 使用CursorLoader在后臺加載數據
- 使用CursorLoader執行查詢任務
- 處理查詢的結果
- 管理設備的喚醒狀態
- 保持設備的喚醒
- 制定重復定時的任務
- Android性能優化
- 管理應用的內存
- 代碼性能優化建議
- 提升Layout的性能
- 優化layout的層級
- 使用include標簽重用layouts
- 按需加載視圖
- 使得ListView滑動順暢
- 優化電池壽命
- 監測電量與充電狀態
- 判斷與監測Docking狀態
- 判斷與監測網絡連接狀態
- 根據需要操作Broadcast接受者
- 多線程操作
- 在一個線程中執行一段特定的代碼
- 為多線程創建線程池
- 啟動與停止線程池中的線程
- 與UI線程通信
- 避免出現程序無響應ANR
- JNI使用指南
- 優化多核處理器(SMP)下的Android程序
- Android安全與隱私
- Security Tips
- 使用HTTPS與SSL
- 為防止SSL漏洞而更新Security
- 使用設備管理條例增強安全性
- Android測試程序
- 測試你的Activity
- 建立測試環境
- 創建與執行測試用例
- 測試UI組件
- 創建單元測試
- 創建功能測試
- 術語表