> 編寫:[jdneo](https://github.com/jdneo) - 原文:[http://developer.android.com/training/printing/custom-docs.html](http://developer.android.com/training/printing/custom-docs.html)
對于有些應用,比如繪圖應用,頁面布局應用和其它一些關注于圖像輸出的應用,創造出精美的打印頁面將是它的核心功能。在這種情況下,僅僅打印一幅圖片或一個HTML文檔就不夠了。這類應用的打印輸出需要精確地控制每一個會在頁面中顯示的對象,包括字體,文本流,分頁符,頁眉,頁腳和一些圖像元素等等。
想要創建一個完全自定義的打印文檔,需要投入比之前討論的方法更多的編程精力。我們必須構建可以和打印框架相互通信的組件,調整打印參數,繪制頁面元素并管理多個頁面的打印。
這節課將展示如何連接打印管理器,創建一個打印適配器以及如何構建出需要打印的內容。
### 連接打印管理器
當我們的應用直接管理打印進程時,在收到來自用戶的打印請求后,第一步要做的是連接Android打印框架并獲取一個[PrintManager](http://developer.android.com/reference/android/print/PrintManager.html)類的實例。該類允許我們初始化一個打印任務并開始打印任務的生命周期。下面的代碼展示了如何獲得打印管理器并開始打印進程。
~~~
private void doPrint() {
// Get a PrintManager instance
PrintManager printManager = (PrintManager) getActivity()
.getSystemService(Context.PRINT_SERVICE);
// Set job name, which will be displayed in the print queue
String jobName = getActivity().getString(R.string.app_name) + " Document";
// Start a print job, passing in a PrintDocumentAdapter implementation
// to handle the generation of a print document
printManager.print(jobName, new MyPrintDocumentAdapter(getActivity()),
null); //
}
~~~
上面的代碼展示了如何命名一個打印任務以及如何設置一個[PrintDocumentAdapter](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html)類的實例,它負責處理打印生命周期的每一步。打印適配器的實現會在下一節中進行討論。
> **Note:**[print()](http://developer.android.com/reference/android/print/PrintManager.html#print(java.lang.String, android.print.PrintDocumentAdapter, android.print.PrintAttributes))方法的最后一個參數接收一個[PrintAttributes](http://developer.android.com/reference/android/print/PrintAttributes.html)對象。我們可以使用這個參數向打印框架進行一些打印設置,以及基于前一個打印周期的預設,從而改善用戶體驗。我們也可以使用這個參數對打印內容進行一些更符合實際情況的設置,比如當打印一幅照片時,設置打印的方向與照片方向一致。
### 創建打印適配器
打印適配器負責與Android打印框架交互并處理打印過程的每一步。這個過程需要用戶在創建打印文檔前選擇打印機和打印選項。由于用戶可以選擇不同性能的打印機,不同的頁面尺寸或不同的頁面方向,因此這些選項可能會影響最終的打印效果。當這些選項配置好之后,打印框架會尋求適配器進行布局并生成一個打印文檔,以此作為打印的前期準備。一旦用戶點擊了打印按鈕,框架會將最終的打印文檔傳遞給Print Provider進行打印輸出。在打印過程中,用戶可以選擇取消打印,所以打印適配器必須監聽并響應取消打印的請求。
[PrintDocumentAdapter](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html)抽象類負責處理打印的生命周期,它有四個主要的回調方法。我們必須在打印適配器中實現這些方法,以此來正確地和Android打印框架進行交互:
- [onStart()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onStart()):一旦打印進程開始,該方法就將被調用。如果我們的應用有任何一次性的準備任務要執行,比如獲取一個要打印數據的快照,那么讓它們在此處執行。在你的適配器中,這個回調方法不是必須實現的。
- [onLayout()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle)):每當用戶改變了影響打印輸出的設置時(比如改變了頁面的尺寸,或者頁面的方向)該函數將會被調用,以此給我們的應用一個機會去重新計算打印頁面的布局。另外,該方法必須返回打印文檔包含多少頁面。
- [onWrite()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onWrite(android.print.PageRange[], android.os.ParcelFileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback)):該方法調用后,會將打印頁面渲染成一個待打印的文件。該方法可以在[onLayout()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle))方法被調用后調用一次或多次。
- [onFinish()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onFinish()):一旦打印進程結束后,該方法將會被調用。如果我們的應用有任何一次性銷毀任務要執行,讓這些任務在該方法內執行。這個回調方法不是必須實現的。
下面將介紹如何實現`onLayout()`以及`onWrite()`方法,他們是打印適配器的核心功能。
> **Note:**這些適配器的回調方法會在應用的主線程上被調用。如果這些方法的實現在執行時可能需要花費大量的時間,那么應該將他們放在另一個線程里執行。例如:我們可以將布局或者寫入打印文檔的操作封裝在一個[AsyncTask](http://developer.android.com/reference/android/os/AsyncTask.html)對象中。
### 計算打印文檔信息
在實現[PrintDocumentAdapter](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html)類時,我們的應用必須能夠指定出所創建文檔的類型,計算出打印任務所需要打印的總頁數,并提供打印頁面的尺寸信息。在實現適配器的[onLayout()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle))方法時,我們執行這些計算,并提供與理想的輸出相關的一些信息,這些信息可以在[PrintDocumentInfo](http://developer.android.com/reference/android/print/PrintDocumentInfo.html)類中獲取,包括頁數和內容類型。下面的例子展示了[PrintDocumentAdapter](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html)中[onLayout()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle))方法的基本實現:
~~~
@Override
public void onLayout(PrintAttributes oldAttributes,
PrintAttributes newAttributes,
CancellationSignal cancellationSignal,
LayoutResultCallback callback,
Bundle metadata) {
// Create a new PdfDocument with the requested page attributes
mPdfDocument = new PrintedPdfDocument(getActivity(), newAttributes);
// Respond to cancellation request
if (cancellationSignal.isCancelled() ) {
callback.onLayoutCancelled();
return;
}
// Compute the expected number of printed pages
int pages = computePageCount(newAttributes);
if (pages > 0) {
// Return print information to print framework
PrintDocumentInfo info = new PrintDocumentInfo
.Builder("print_output.pdf")
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
.setPageCount(pages);
.build();
// Content layout reflow is complete
callback.onLayoutFinished(info, true);
} else {
// Otherwise report an error to the print framework
callback.onLayoutFailed("Page count calculation failed.");
}
}
~~~
[onLayout()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle))方法的執行結果有三種:完成,取消或失敗(計算布局無法順利完成時會失敗)。我們必須通過調用[PrintDocumentAdapter.LayoutResultCallback](http://developer.android.com/reference/android/print/PrintDocumentAdapter.LayoutResultCallback.html)對象中的適當方法來指出這些結果中的一個。
> **Note:**[onLayoutFinished()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.LayoutResultCallback.html#onLayoutFinished(android.print.PrintDocumentInfo, boolean))方法的布爾類型參數明確了這個布局內容是否和上一次打印請求相比發生了改變。恰當地設定了這個參數將避免打印框架不必要地調用[onWrite()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onWrite(android.print.PageRange[], android.os.ParcelFileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback))方法,緩存之前的打印文檔,提升執行性能。
[onLayout()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle))的主要任務是計算打印文檔的頁數,并將它作為打印參數交給打印機。如何計算頁數則高度依賴于應用是如何對打印頁面進行布局的。下面的代碼展示了頁數是如何根據打印方向確定的:
~~~
private int computePageCount(PrintAttributes printAttributes) {
int itemsPerPage = 4; // default item count for portrait mode
MediaSize pageSize = printAttributes.getMediaSize();
if (!pageSize.isPortrait()) {
// Six items per page in landscape orientation
itemsPerPage = 6;
}
// Determine number of print items
int printItemCount = getPrintItemCount();
return (int) Math.ceil(printItemCount / itemsPerPage);
}
~~~
### 將打印文檔寫入文件
當需要將打印內容輸出到一個文件時,Android打印框架會調用[PrintDocumentAdapter](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html)類的[onWrite()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onWrite(android.print.PageRange[], android.os.ParcelFileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback))方法。這個方法的參數指定了哪些頁面要被寫入以及要使用的輸出文件。該方法的實現必須將每一個請求頁的內容渲染成一個含有多個頁面的PDF文件。當這個過程結束以后,你需要調用callback對象的[onWriteFinished()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.WriteResultCallback.html#onWriteFinished(android.print.PageRange[]))方法。
> **Note:** Android打印框架可能會在每次調用[onLayout()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle))后,調用[onWrite()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onWrite(android.print.PageRange[], android.os.ParcelFileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback))方法一次甚至更多次。請務必牢記:當打印內容的布局沒有變化時,可以將[onLayoutFinished()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.LayoutResultCallback.html#onLayoutFinished(android.print.PrintDocumentInfo, boolean))方法的布爾參數設置為“false”,以此避免對打印文檔進行不必要的重寫操作。
> **Note:**[onLayoutFinished()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.LayoutResultCallback.html#onLayoutFinished(android.print.PrintDocumentInfo, boolean))方法的布爾類型參數明確了這個布局內容是否和上一次打印請求相比發生了改變。恰當地設定了這個參數將避免打印框架不必要的調用[onLayout()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle))方法,緩存之前的打印文檔,提升執行性能。
下面的代碼展示了使用[PrintedPdfDocument](http://developer.android.com/reference/android/print/pdf/PrintedPdfDocument.html)類創建了PDF文件的基本原理:
~~~
@Override
public void onWrite(final PageRange[] pageRanges,
final ParcelFileDescriptor destination,
final CancellationSignal cancellationSignal,
final WriteResultCallback callback) {
// Iterate over each page of the document,
// check if it's in the output range.
for (int i = 0; i < totalPages; i++) {
// Check to see if this page is in the output range.
if (containsPage(pageRanges, i)) {
// If so, add it to writtenPagesArray. writtenPagesArray.size()
// is used to compute the next output page index.
writtenPagesArray.append(writtenPagesArray.size(), i);
PdfDocument.Page page = mPdfDocument.startPage(i);
// check for cancellation
if (cancellationSignal.isCancelled()) {
callback.onWriteCancelled();
mPdfDocument.close();
mPdfDocument = null;
return;
}
// Draw page content for printing
drawPage(page);
// Rendering is complete, so page can be finalized.
mPdfDocument.finishPage(page);
}
}
// Write PDF document to file
try {
mPdfDocument.writeTo(new FileOutputStream(
destination.getFileDescriptor()));
} catch (IOException e) {
callback.onWriteFailed(e.toString());
return;
} finally {
mPdfDocument.close();
mPdfDocument = null;
}
PageRange[] writtenPages = computeWrittenPages();
// Signal the print framework the document is complete
callback.onWriteFinished(writtenPages);
...
}
~~~
代碼中將PDF頁面遞交給了drawPage()方法,這個方法會在下一部分介紹。
就布局而言,[onWrite()](http://developer.android.com/reference/android/print/PrintDocumentAdapter.html#onWrite(android.print.PageRange[], android.os.ParcelFileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback))方法的執行可以有三種結果:完成,取消或者失敗(內容無法被寫入)。我們必須通過調用[PrintDocumentAdapter.WriteResultCallback](http://developer.android.com/reference/android/print/PrintDocumentAdapter.WriteResultCallback.html)對象中的適當方法來指明這些結果中的一個。
> **Note:**渲染打印文檔是一個可能耗費大量資源的操作。為了避免阻塞應用的主UI線程,我們應該考慮將頁面的渲染和寫操作放在另一個線程中執行,比如在[AsyncTask](http://developer.android.com/reference/android/os/AsyncTask.html)中執行。關于更多異步任務線程的知識,可以閱讀:[Processes and Threads](http://developer.android.com/guide/components/processes-and-threads.html)。
### 繪制PDF頁面內容
當我們的應用進行打印時,應用必須生成一個PDF文檔并將它傳遞給Android打印框架以進行打印。我們可以使用任何PDF生成庫來協助完成這個操作。本節將展示如何使用[PrintedPdfDocument](http://developer.android.com/reference/android/print/pdf/PrintedPdfDocument.html)類將打印內容生成為PDF頁面。
[PrintedPdfDocument](http://developer.android.com/reference/android/print/pdf/PrintedPdfDocument.html)類使用一個[Canvas](http://developer.android.com/reference/android/graphics/Canvas.html)對象來在PDF頁面上繪制元素,這一點和在[activity](# "An activity represents a single screen with a user interface.")布局上進行繪制很類似。我們可以在打印頁面上使用[Canvas](http://developer.android.com/reference/android/graphics/Canvas.html)類提供的相關繪圖方法繪制頁面元素。下面的代碼展示了如何使用這些方法在PDF頁面上繪制一些簡單的元素:
~~~
private void drawPage(PdfDocument.Page page) {
Canvas canvas = page.getCanvas();
// units are in points (1/72 of an inch)
int titleBaseLine = 72;
int leftMargin = 54;
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(36);
canvas.drawText("Test Title", leftMargin, titleBaseLine, paint);
paint.setTextSize(11);
canvas.drawText("Test paragraph", leftMargin, titleBaseLine + 25, paint);
paint.setColor(Color.BLUE);
canvas.drawRect(100, 100, 172, 172, paint);
}
~~~
當使用[Canvas](http://developer.android.com/reference/android/graphics/Canvas.html)在一個PDF頁面上繪圖時,元素通過單位“點(point)”來指定大小,一個點相當于七十二分之一英寸。在編寫程序時,請確保使用該測量單位來指定頁面上的元素大小。在定位繪制的元素時,坐標系的原點(即(0,0)點)在頁面的最左上角。
> **Tip:**雖然[Canvas](http://developer.android.com/reference/android/graphics/Canvas.html)對象允許我們將打印元素放置在一個PDF文檔的邊緣,但許多打印機無法在紙張的邊緣打印。所以當我們使用這個類構建一個打印文檔時,需要考慮到那些無法打印的邊緣區域。
- 序言
- 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組件
- 創建單元測試
- 創建功能測試
- 術語表