如何在Android中實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能
1. 項(xiàng)目簡介
隨著移動(dòng)端用戶越來越依賴視頻、文件下載以及大文件傳輸,斷點(diǎn)續(xù)傳作為一種有效節(jié)省帶寬和提高用戶體驗(yàn)的技術(shù)應(yīng)運(yùn)而生。所謂斷點(diǎn)續(xù)傳,就是指在下載過程中如果網(wǎng)絡(luò)發(fā)生中斷或用戶取消下載,再次啟動(dòng)下載時(shí)能從上一次結(jié)束的地方繼續(xù),而不必從頭開始,節(jié)省下載時(shí)間和數(shù)據(jù)流量。本項(xiàng)目旨在實(shí)現(xiàn)一個(gè)基于 Android 的斷點(diǎn)續(xù)傳功能,通過 HTTP Range 請求下載文件,并對部分下載數(shù)據(jù)進(jìn)行存儲與管理,實(shí)現(xiàn)斷點(diǎn)續(xù)傳效果。項(xiàng)目可以應(yīng)用于視頻、軟件更新、圖片大文件下載等場景。
2. 背景與需求分析
2.1 項(xiàng)目背景
在實(shí)際開發(fā)中,下載大文件時(shí)網(wǎng)絡(luò)波動(dòng)、連接中斷等問題經(jīng)常發(fā)生,如果從頭開始下載,用戶體驗(yàn)大打折扣。實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能能夠:
提高文件下載的效率;
節(jié)省用戶數(shù)據(jù)流量;
改善用戶體驗(yàn),特別是在網(wǎng)絡(luò)不穩(wěn)定環(huán)境下。
常見實(shí)現(xiàn)方式通常利用 HTTP 協(xié)議中的 Range 頭字段請求下載指定位置的數(shù)據(jù),再將分段下載的數(shù)據(jù)合并成完整文件。同時(shí)需要對下載過程中可能出現(xiàn)的錯(cuò)誤進(jìn)行處理,并保存當(dāng)前下載狀態(tài),便于下次繼續(xù)。
2.2 需求分析
本項(xiàng)目主要需要滿足以下功能需求:
斷點(diǎn)續(xù)傳下載
支持當(dāng)下載中斷后,下次啟動(dòng)能從上一次下載結(jié)束處繼續(xù);
利用 HTTP Range 請求方式,指定請求數(shù)據(jù)的起始位置;
對服務(wù)器返回的響應(yīng)進(jìn)行解析,校驗(yàn)下載數(shù)據(jù)的完整性,并將分段數(shù)據(jù)合并成完整文件。
下載狀態(tài)管理
保存當(dāng)前下載位置和已下載的數(shù)據(jù)大小到本地存儲(例如 SharedPreferences 或數(shù)據(jù)庫);
在重新啟動(dòng)下載時(shí),從保存的斷點(diǎn)開始繼續(xù)下載。
異常處理
處理網(wǎng)絡(luò)中斷、超時(shí)等異常情況;
能夠進(jìn)行多次重試和錯(cuò)誤提示;
避免因下載過程中的異常導(dǎo)致文件損壞。
用戶界面及反饋
提供簡潔直觀的用戶界面顯示下載進(jìn)度和斷點(diǎn)狀態(tài);
當(dāng)下載完成或失敗時(shí)給出明確的提示信息;
支持暫停、恢復(fù)、取消下載操作。
性能與擴(kuò)展性
下載過程盡量在子線程中執(zhí)行,避免阻塞 UI 線程;
模塊化設(shè)計(jì),便于在不同項(xiàng)目中復(fù)用(如視頻下載、文件更新等);
提供對接第三方網(wǎng)絡(luò)庫(如 OkHttp、Retrofit)的擴(kuò)展方案。
3. 關(guān)鍵技術(shù)與實(shí)現(xiàn)原理
3.1 斷點(diǎn)續(xù)傳的原理
斷點(diǎn)續(xù)傳依賴于 HTTP 協(xié)議中 Range 請求頭,它允許客戶端請求資源的某個(gè)部分,例如 “Range: bytes=xxx-” 表示從指定字節(jié)開始下載。服務(wù)端收到請求后,會返回狀態(tài)碼 206(Partial Content),同時(shí)返回響應(yīng)頭中包含 Content-Range 信息??蛻舳耸盏綌?shù)據(jù)后,只保存這部分?jǐn)?shù)據(jù),并在后續(xù)請求中指定下一個(gè)起點(diǎn),從而實(shí)現(xiàn)文件的分段下載與合并。
3.2 HTTP Range 頭與響應(yīng)解析
Range 頭
格式:Range: bytes=起始位置-結(jié)束位置
。
在斷點(diǎn)續(xù)傳中,通常只指定起始位置,服務(wù)器根據(jù)文件大小自動(dòng)返回后續(xù)數(shù)據(jù)。Content-Range 響應(yīng)頭
格式:Content-Range: bytes 起始位置-結(jié)束位置/文件總大小
。
通過這個(gè)頭信息,客戶端可以核對下載數(shù)據(jù)是否完整,并計(jì)算下次請求的起始位置。
3.3 文件讀寫與狀態(tài)管理
文件寫入
使用 RandomAccessFile 可以指定寫入位置,非常適用于斷點(diǎn)續(xù)傳。
打開文件后,將下載數(shù)據(jù)從當(dāng)前的斷點(diǎn)開始寫入,并不斷更新寫入位置。狀態(tài)管理
通過 SharedPreferences、數(shù)據(jù)庫或本地文件保存當(dāng)前下載位置和文件總大小,確保在斷點(diǎn)續(xù)傳時(shí)能夠正確讀取上次下載狀態(tài)。
3.4 網(wǎng)絡(luò)請求與異常處理
網(wǎng)絡(luò)請求庫
可以使用 OkHttp 等網(wǎng)絡(luò)庫發(fā)送 GET 請求,并在請求頭中加入 Range 字段。異常處理
對網(wǎng)絡(luò)中斷、HTTP 狀態(tài)碼異常、文件寫入異常等進(jìn)行捕獲和重試策略設(shè)計(jì),確保下載過程魯棒性。
4. 項(xiàng)目實(shí)現(xiàn)思路與架構(gòu)設(shè)計(jì)
4.1 整體架構(gòu)設(shè)計(jì)
項(xiàng)目大致分為以下幾個(gè)模塊:
網(wǎng)絡(luò)請求模塊
負(fù)責(zé)構(gòu)造 HTTP 請求,并在請求頭中設(shè)置 Range;
接收服務(wù)器返回的 206 部分內(nèi)容響應(yīng),并將數(shù)據(jù)傳遞給文件寫入模塊。
文件管理模塊
利用 RandomAccessFile 對下載文件進(jìn)行寫入;
每次下載時(shí)記錄當(dāng)前寫入位置,并保存至本地持久化存儲;
文件合并與校驗(yàn),確保下載數(shù)據(jù)完整無誤。
狀態(tài)管理模塊
保存和讀取斷點(diǎn)續(xù)傳狀態(tài)(下載進(jìn)度、總文件大小等),便于斷點(diǎn)續(xù)傳的實(shí)現(xiàn);
提供暫停、恢復(fù)、取消等功能接口。
用戶界面模塊
展示下載進(jìn)度、剩余時(shí)間和狀態(tài)提示;
提供暫停、恢復(fù)、取消等交互按鈕,便于用戶控制下載進(jìn)程。
4.2 下載流程與斷點(diǎn)續(xù)傳實(shí)現(xiàn)
初始化
獲取文件總大?。梢酝ㄟ^ HEAD 請求獲取或第一次完整請求獲取);
檢查本地是否存在部分下載文件,并讀取已經(jīng)下載的字節(jié)數(shù)。
開始下載
通過網(wǎng)絡(luò)請求發(fā)送 Range 請求,起始位置為已下載的字節(jié)數(shù);
將返回的數(shù)據(jù)寫入文件,并實(shí)時(shí)更新當(dāng)前下載字節(jié)數(shù);
更新 UI 顯示進(jìn)度。
異常與重試
當(dāng)網(wǎng)絡(luò)中斷或其它異常發(fā)生時(shí),通過狀態(tài)管理保存當(dāng)前進(jìn)度;
用戶恢復(fù)網(wǎng)絡(luò)后,可再次啟動(dòng)下載,從斷點(diǎn)繼續(xù)。
完成處理
下載完成后進(jìn)行文件校驗(yàn)(例如 MD5 校驗(yàn)),確保數(shù)據(jù)正確;
更新狀態(tài),通知用戶下載完成,并清除保存的斷點(diǎn)狀態(tài)。
4.3 斷點(diǎn)續(xù)傳狀態(tài)管理
采用 SharedPreferences 或本地?cái)?shù)據(jù)庫存儲當(dāng)前下載的進(jìn)度信息;
每次寫入文件時(shí)更新當(dāng)前已下載字節(jié)數(shù),方便下次啟動(dòng)時(shí)繼續(xù)下載;
提供接口方便用戶手動(dòng)重置或取消斷點(diǎn)狀態(tài)。
5. 詳細(xì)代碼示例與注釋
下面給出基于 OkHttp 的斷點(diǎn)續(xù)傳示例代碼。代碼中利用 HTTP Range 請求、RandomAccessFile 寫入以及 SharedPreferences 保存進(jìn)度。同時(shí)提供完整注釋,詳細(xì)解釋每個(gè)步驟。
5.1 基于 OkHttp 實(shí)現(xiàn)斷點(diǎn)續(xù)傳示例代碼
package com.example.breakpointdownload; import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; import android.util.Log; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; public class DownloadManager { private static final String TAG = "DownloadManager"; private static final String PREFS_NAME = "download_prefs"; private static final String KEY_DOWNLOAD_PROGRESS = "download_progress"; private OkHttpClient client; private Context context; public DownloadManager(Context context) { this.context = context; client = new OkHttpClient(); } /** * 開始下載文件,實(shí)現(xiàn)斷點(diǎn)續(xù)傳。 * * @param fileUrl 文件下載地址 * @param destFilePath 本地文件保存路徑 */ public void downloadFile(String fileUrl, String destFilePath) { // 讀取已下載的字節(jié)數(shù) SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); long downloadedBytes = prefs.getLong(KEY_DOWNLOAD_PROGRESS, 0); Request request = new Request.Builder() .url(fileUrl) // 設(shè)置 Range 請求頭,從斷點(diǎn)位置開始下載 .addHeader("Range", "bytes=" + downloadedBytes + "-") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e(TAG, "下載失?。? + e.getMessage()); } @Override public void onResponse(Call call, Response response) throws IOException { // 下載成功后寫入文件 if (response.code() == 206 || response.code() == 200) { File file = new File(destFilePath); // 使用 RandomAccessFile 從指定位置寫入數(shù)據(jù) RandomAccessFile raf = new RandomAccessFile(file, "rw"); raf.seek(downloadedBytes); byte[] buffer = new byte[1024 * 4]; int len; long currentBytes = downloadedBytes; while ((len = response.body().byteStream().read(buffer)) != -1) { raf.write(buffer, 0, len); currentBytes += len; // 保存當(dāng)前下載進(jìn)度 saveProgress(currentBytes); } raf.close(); Log.d(TAG, "下載完成:" + currentBytes + " 字節(jié)"); } else { Log.e(TAG, "服務(wù)器響應(yīng)異常:" + response.code()); } } }); } /** * 保存當(dāng)前下載進(jìn)度到 SharedPreferences 中 * * @param bytes 當(dāng)前已下載的字節(jié)數(shù) */ private void saveProgress(long bytes) { SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); prefs.edit().putLong(KEY_DOWNLOAD_PROGRESS, bytes).apply(); } /** * 重置下載進(jìn)度(例如取消或重新開始下載時(shí)調(diào)用) */ public void resetProgress() { SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); prefs.edit().putLong(KEY_DOWNLOAD_PROGRESS, 0).apply(); } }
5.2 使用示例 Activity
package com.example.breakpointdownload; import android.os.Bundle; import android.os.Environment; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; public class DownloadActivity extends AppCompatActivity { private DownloadManager downloadManager; // 下載目標(biāo)文件 URL(示例 URL,請?zhí)鎿Q為實(shí)際文件地址) private String fileUrl = "https://example.com/path/to/your/file.apk"; // 本地保存路徑 private String destFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/download/file.apk"; private Button btnDownload; private Button btnReset; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_download); downloadManager = new DownloadManager(this); btnDownload = findViewById(R.id.btn_download); btnReset = findViewById(R.id.btn_reset); btnDownload.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { downloadManager.downloadFile(fileUrl, destFilePath); } }); btnReset.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { downloadManager.resetProgress(); } }); } }
5.3 XML 布局文件示例
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll_container" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:padding="24dp"> <Button android:id="@+id/btn_download" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="開始下載" /> <Button android:id="@+id/btn_reset" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="重置斷點(diǎn)" android:layout_marginTop="16dp" /> </LinearLayout>
6. 代碼解析與講解
6.1 核心模塊與關(guān)鍵方法詳解
DownloadManager 類
該類封裝了斷點(diǎn)續(xù)傳的核心邏輯。在下載開始前,通過 SharedPreferences 獲取已下載的字節(jié)數(shù)。
構(gòu)造 HTTP 請求時(shí),在請求頭中添加 Range 字段,實(shí)現(xiàn)從斷點(diǎn)續(xù)傳。
使用 OkHttp 發(fā)送網(wǎng)絡(luò)請求,響應(yīng)狀態(tài)碼 206(Partial Content)表示服務(wù)端支持?jǐn)帱c(diǎn)續(xù)傳。
利用 RandomAccessFile 將下載數(shù)據(jù)寫入指定位置,并不斷更新已下載的字節(jié)數(shù)保存至 SharedPreferences 中。
若下載中斷后重新啟動(dòng)下載,可從 SharedPreferences 中讀取上次進(jìn)度,繼續(xù)下載剩余數(shù)據(jù)。
DownloadActivity 類
作為 UI 層,提供兩個(gè)按鈕,分別觸發(fā)“開始下載”和“重置斷點(diǎn)”操作,演示斷點(diǎn)續(xù)傳功能。用戶點(diǎn)擊“開始下載”后,DownloadManager 開始執(zhí)行下載任務(wù);若需要重新下載,則可以點(diǎn)擊重置按鈕。
6.2 數(shù)據(jù)分段讀取與文件合并邏輯
隨機(jī)文件訪問
通過 RandomAccessFile.seek() 方法調(diào)整寫入位置,可將每次下載的數(shù)據(jù)拼接到文件末尾,實(shí)現(xiàn)斷點(diǎn)續(xù)傳。數(shù)據(jù)更新與持久化
每次寫入操作后,調(diào)用 saveProgress() 方法更新 SharedPreferences 中存儲的下載進(jìn)度,確保發(fā)生中斷時(shí)能準(zhǔn)確恢復(fù)數(shù)據(jù)下載。
7. 項(xiàng)目測試與運(yùn)行效果
7.1 測試方案與流程
功能測試
在真實(shí)設(shè)備上測試下載功能,檢查當(dāng)下載中斷(例如網(wǎng)絡(luò)斷開)后再次啟動(dòng)下載時(shí)能否繼續(xù)從上次斷點(diǎn)繼續(xù)。
驗(yàn)證 HTTP Range 請求是否正確返回部分內(nèi)容,以及下載文件是否完整拼接。
穩(wěn)定性測試
模擬網(wǎng)絡(luò)異常、服務(wù)器響應(yīng)異常的情況,檢測 DownloadManager 是否能夠捕獲異常并提示錯(cuò)誤。
檢查文件寫入過程中是否出現(xiàn) I/O 異常,并確保相關(guān)資源及時(shí)釋放。
用戶體驗(yàn)測試
檢查“重置斷點(diǎn)”按鈕是否能正確清除已下載狀態(tài),確保下次下載從頭開始;
觀察下載過程中的日志輸出,確認(rèn)斷點(diǎn)數(shù)據(jù)正確記錄與恢復(fù)。
7.2 性能與兼容性測試
網(wǎng)絡(luò)測試:
在不同網(wǎng)絡(luò)環(huán)境下測試下載速度和斷點(diǎn)續(xù)傳效果,確保在高延遲、弱信號等情況下也能正常工作。設(shè)備兼容性:
在不同 Android 系統(tǒng)版本和設(shè)備型號上進(jìn)行測試,確保文件操作和 SharedPreferences 的讀寫表現(xiàn)一致,無兼容性問題。
8. 項(xiàng)目總結(jié)與經(jīng)驗(yàn)分享
8.1 項(xiàng)目優(yōu)缺點(diǎn)分析
項(xiàng)目優(yōu)勢
通過 HTTP Range 請求與 RandomAccessFile 實(shí)現(xiàn)斷點(diǎn)續(xù)傳效果,充分利用了標(biāo)準(zhǔn)協(xié)議與 API;
采用 SharedPreferences 存儲下載進(jìn)度,簡單易用;
支持暫停、斷點(diǎn)恢復(fù)等常見下載場景,可擴(kuò)展性較強(qiáng)。
項(xiàng)目不足
僅針對單個(gè)文件進(jìn)行斷點(diǎn)續(xù)傳,未涉及多任務(wù)并發(fā)下載;
對于大文件下載時(shí),可能需要引入更高效的 I/O 緩存機(jī)制;
異常處理和錯(cuò)誤重試機(jī)制可進(jìn)一步完善,增加日志記錄與用戶友好提示。
8.2 開發(fā)心得與改進(jìn)建議
斷點(diǎn)續(xù)傳原理
關(guān)鍵在于正確使用 HTTP Range 頭和 RandomAccessFile,實(shí)現(xiàn)文件分段拼接與狀態(tài)保存。確保每次寫入前將指針定位在合適的偏移量。資源管理
在下載任務(wù)過程中,注意關(guān)閉網(wǎng)絡(luò)流和 RandomAccessFile,防止內(nèi)存泄露。異常與重試機(jī)制
需要根據(jù)實(shí)際網(wǎng)絡(luò)狀況加入重試機(jī)制,增加健壯性,并實(shí)時(shí)反饋錯(cuò)誤信息給用戶。擴(kuò)展應(yīng)用
未來可結(jié)合多線程和分塊下載,進(jìn)一步提升大文件下載速度,同時(shí)加入下載管理界面顯示多任務(wù)下載進(jìn)度。
9. 后續(xù)優(yōu)化與拓展思考
多線程分塊下載
將文件切分為多個(gè)塊,并利用線程池同時(shí)下載不同塊,最后合并成完整文件。
提高下載速度和網(wǎng)絡(luò)利用效率,適用于大型資源下載。
進(jìn)度提示與通知功能
使用通知欄顯示下載進(jìn)度,提升用戶體驗(yàn);
支持暫停、繼續(xù)、取消下載的綜合下載管理。
斷點(diǎn)續(xù)傳狀態(tài)保存改進(jìn)
將下載狀態(tài)存儲到數(shù)據(jù)庫中,適用于多任務(wù)下載,便于管理和展示狀態(tài)。
提供下載記錄,便于用戶查詢歷史下載記錄。
擴(kuò)展到視頻、圖片等多媒體文件
針對不同類型文件,優(yōu)化緩存處理機(jī)制。
借助 MD5 校驗(yàn)或其他完整性驗(yàn)證方法,確保下載文件無損。
與網(wǎng)絡(luò)庫整合
結(jié)合 Retrofit 或基于 OkHttp 的封裝,將斷點(diǎn)續(xù)傳功能作為下載模塊獨(dú)立出來,提高代碼復(fù)用性。
結(jié)論
本文詳細(xì)講解了如何在 Android 中實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能。從項(xiàng)目背景和需求分析入手,介紹了斷點(diǎn)續(xù)傳的基本原理和 HTTP Range 請求的使用,通過 RandomAccessFile 實(shí)現(xiàn)文件分段寫入和合并,并利用 SharedPreferences 保存下載進(jìn)度。整個(gè)方案從網(wǎng)絡(luò)請求、文件操作、狀態(tài)管理到異常處理均做了詳細(xì)設(shè)計(jì)和編碼示例說明。
項(xiàng)目測試結(jié)果表明,該方案能夠有效實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能,適用于文件下載、視頻、軟件更新等場景。同時(shí),本文還探討了多線程下載、進(jìn)度提示、擴(kuò)展到多任務(wù)下載等未來優(yōu)化方向,為開發(fā)者提供了豐富的實(shí)現(xiàn)思路和參考資料。
希望本文能為各位 Android 開發(fā)者提供充分的技術(shù)指導(dǎo)和實(shí)踐經(jīng)驗(yàn),助您在實(shí)際項(xiàng)目中實(shí)現(xiàn)既高效又穩(wěn)定的斷點(diǎn)續(xù)傳功能。
以上就是如何在Android中實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能的詳細(xì)內(nèi)容,更多關(guān)于Android斷點(diǎn)續(xù)傳的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Android Service與Activity之間通信的幾種方式
這篇文章主要介紹了詳解Android Service與Activity之間通信的幾種方式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04Android?Studio實(shí)現(xiàn)登錄界面功能
這篇文章主要為大家詳細(xì)介紹了Android?Studio實(shí)現(xiàn)登錄界面功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04android開發(fā)教程之間隔執(zhí)行程序(android計(jì)時(shí)器)
android開發(fā)中有些情況需要隔一段時(shí)間去執(zhí)行某個(gè)操作一次或者是每隔一段時(shí)間久執(zhí)行某個(gè)操作,下面是實(shí)現(xiàn)方法2014-02-02Android EditText限制輸入字符類型的方法總結(jié)
這篇文章主要介紹了Android EditText限制輸入字符類型的方法總結(jié)的相關(guān)資料,需要的朋友可以參考下2017-03-03Android自定義View實(shí)現(xiàn)QQ運(yùn)動(dòng)積分轉(zhuǎn)盤抽獎(jiǎng)功能
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)QQ運(yùn)動(dòng)積分轉(zhuǎn)盤抽獎(jiǎng)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Android手機(jī)開發(fā) 使用線性布局和相對布局實(shí)現(xiàn)Button垂直水平居中
本文主要結(jié)合自己的理解分別對使用LinearLayout和RelativeLayout兩種方式實(shí)現(xiàn)居中做了總結(jié),希望對大家有所幫助。2016-05-05Android如何監(jiān)測文件夾內(nèi)容變化詳解
最近在開發(fā)android應(yīng)用程序的時(shí)候遇到了一個(gè)監(jiān)測文件夾的功能,所以下面這篇文章主要給大家介紹了關(guān)于Android如何監(jiān)測文件夾內(nèi)容變化的相關(guān)資料,需要的朋友可以參考下2021-12-12Ubuntu中為Android系統(tǒng)實(shí)現(xiàn)內(nèi)置Java應(yīng)用程序測試Application Frameworks層的硬件服務(wù)
本文主要介紹Ubuntu中為Android系統(tǒng)內(nèi)置應(yīng)用訪問Application Frameworks層的硬件服務(wù),這里提供了詳細(xì)的流程和代碼實(shí)例,有興趣的朋友可以參考下2016-08-08