Android中使用DownloadManager類來管理數(shù)據(jù)下載的教程
從Android 2.3(API level 9)開始Android用系統(tǒng)服務(wù)(Service)的方式提供了Download Manager來優(yōu)化處理長(zhǎng)時(shí)間的下載操作。Download Manager處理HTTP連接并監(jiān)控連接中的狀態(tài)變化以及系統(tǒng)重啟來確保每一個(gè)下載任務(wù)順利完成。
在大多數(shù)涉及到下載的情況中使用Download Manager都是不錯(cuò)的選擇,特別是當(dāng)用戶切換不同的應(yīng)用以后下載需要在后臺(tái)繼續(xù)進(jìn)行,以及當(dāng)下載任務(wù)順利完成非常重要的情況(DownloadManager對(duì)于斷點(diǎn)續(xù)傳功能支持很好)。
要想使用Download Manager,使用getSystemService方法請(qǐng)求系統(tǒng)的DOWNLOAD_SERVICE服務(wù),代碼片段如下:
String serviceString = Context.DOWNLOAD_SERVICE; DownloadManager downloadManager; downloadManager = (DownloadManager) getSystemService(serviceString);
下載文件
要請(qǐng)求一個(gè)下載操作,需要?jiǎng)?chuàng)建一個(gè)DownloadManager.Request對(duì)象,將要請(qǐng)求下載的文件的Uri傳遞給Download Manager的enqueue方法,代碼片段如下所示:
String serviceString = Context.DOWNLOAD_SERVICE; DownloadManager downloadManager; downloadManager = (DownloadManager)getSystemService(serviceString); Uri uri = Uri.parse("http://developer.android.com/shareables/icon_templates-v4.0.zip"); DownloadManager.Request request = new Request(uri); long reference = downloadManager.enqueue(request);
在這里返回的reference變量是系統(tǒng)為當(dāng)前的下載請(qǐng)求分配的一個(gè)唯一的ID,我們可以通過這個(gè)ID重新獲得這個(gè)下載任務(wù),進(jìn)行一些自己想要進(jìn)行的操作或者查詢
下載的狀態(tài)以及取消下載等等。
我們可以通過addRequestHeader方法為DownloadManager.Request對(duì)象request添加HTTP頭,也可以通過setMimeType方法重寫從服務(wù)器返回的mime type。
我們還可以指定在什么連接狀態(tài)下執(zhí)行下載操作。setAllowedNetworkTypes方法可以用來限定在WiFi還是手機(jī)網(wǎng)絡(luò)下進(jìn)行下載,setAllowedOverRoaming方法
可以用來阻止手機(jī)在漫游狀態(tài)下下載。
下面的代碼片段用于指定一個(gè)較大的文件只能在WiFi下進(jìn)行下載:
request.setAllowedNetworkTypes(Request.NETWORK_WIFI);
Android API level 11 介紹了getRecommendedMaxBytesOverMobile類方法(靜態(tài)方法),返回一個(gè)當(dāng)前手機(jī)網(wǎng)絡(luò)連接下的最大建議字節(jié)數(shù),可以來判斷下載
是否應(yīng)該限定在WiFi條件下。
調(diào)用enqueue方法之后,只要數(shù)據(jù)連接可用并且Download Manager可用,下載就會(huì)開始。
要在下載完成的時(shí)候獲得一個(gè)系統(tǒng)通知(notification),注冊(cè)一個(gè)廣播接受者來接收ACTION_DOWNLOAD_COMPLETE廣播,這個(gè)廣播會(huì)包含一個(gè)
EXTRA_DOWNLOAD_ID信息在intent中包含了已經(jīng)完成的這個(gè)下載的ID,代碼片段如下所示:
IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { long reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if (myDownloadReference == reference) { } } }; registerReceiver(receiver, filter);
使用Download Manager的openDownloadedFile方法可以打開一個(gè)已經(jīng)下載完成的文件,返回一個(gè)ParcelFileDescriptor對(duì)象。我們可以通過Download Manager來查詢下載文件的保存地址,如果在下載時(shí)制定了路徑和文件名,我們也可以直接操作文件。
我們可以為ACTION_NOTIFICATION_CLICKED action注冊(cè)一個(gè)廣播接受者,當(dāng)用戶從通知欄點(diǎn)擊了一個(gè)下載項(xiàng)目或者從Downloads app點(diǎn)擊可一個(gè)下載的項(xiàng)目的
時(shí)候,系統(tǒng)就會(huì)發(fā)出一個(gè)點(diǎn)擊下載項(xiàng)的廣播。
代碼片段如下:
IntentFilter filter = new IntentFilter(DownloadManager.ACTION_NOTIFICATION_CLICKED); BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String extraID = DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS; long[] references = intent.getLongArrayExtra(extraID); for (long reference : references) if (reference == myDownloadReference) { // Do something with downloading file. } } }; registerReceiver(receiver, filter);
定制Download Manager Notifications的樣式
默認(rèn)情況下,通知欄中會(huì)顯示被Download Manager管理的每一個(gè)download每一個(gè)Notification會(huì)顯示當(dāng)前的下載進(jìn)度和文件的名字。
通過Download Manager可以為每一個(gè)download request定制Notification的樣式,包括完全隱藏Notification。下面的代碼片段顯示了通過setTitle和setDescription
方法來定制顯示在文件下載Notification中顯示的文字。
request.setTitle(“Earthquakes”); request.setDescription(“Earthquake XML”);
setNotificationVisibility方法可以用來控制什么時(shí)候顯示Notification,甚至是隱藏該request的Notification。有以下幾個(gè)參數(shù):
- Request.VISIBILITY_VISIBLE:在下載進(jìn)行的過程中,通知欄中會(huì)一直顯示該下載的Notification,當(dāng)下載完成時(shí),該Notification會(huì)被移除,這是默認(rèn)的參數(shù)值。
- Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED:在下載過程中通知欄會(huì)一直顯示該下載的Notification,在下載完成后該Notification會(huì)繼續(xù)顯示,直到用戶點(diǎn)擊該
- Notification或者消除該Notification。
- Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION:只有在下載完成后該Notification才會(huì)被顯示。
- Request.VISIBILITY_HIDDEN:不顯示該下載請(qǐng)求的Notification。如果要使用這個(gè)參數(shù),需要在應(yīng)用的清單文件中加上DOWNLOAD_WITHOUT_NOTIFICATION權(quán)限。
指定下載保存地址
默認(rèn)情況下,所有通過Download Manager下載的文件都保存在一個(gè)共享下載緩存中,使用系統(tǒng)生成的文件名每一個(gè)Request對(duì)象都可以制定一個(gè)下載
保存的地址,通常情況下,所有的下載文件都應(yīng)該保存在外部存儲(chǔ)中,所以我們需要在應(yīng)用清單文件中加上WRITE_EXTERNAL_STORAGE權(quán)限:
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>
下面的代碼片段是在外部存儲(chǔ)中指定一個(gè)任意的保存位置的方法:
request.setDestinationUri(Uri.fromFile(f));
f是一個(gè)File對(duì)象。
如果下載的這個(gè)文件是你的應(yīng)用所專用的,你可能會(huì)希望把這個(gè)文件放在你的應(yīng)用在外部存儲(chǔ)中的一個(gè)專有文件夾中。注意這個(gè)文件夾不提供訪問控制,
所以其他的應(yīng)用也可以訪問這個(gè)文件夾。在這種情況下,如果你的應(yīng)用卸載了,那么在這個(gè)文件夾也會(huì)被刪除。
下面的代碼片段是指定存儲(chǔ)文件的路徑是應(yīng)用在外部存儲(chǔ)中的專用文件夾的方法:
request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, “Bugdroid.png”);
如果下載的文件希望被其他的應(yīng)用共享,特別是那些你下載下來希望被Media Scanner掃描到的文件(比如音樂文件),那么你可以指定你的下載路徑在
外部存儲(chǔ)的公共文件夾之下,下面的代碼片段是將文件存放到外部存儲(chǔ)中的公共音樂文件夾的方法:
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC, "Android_Rock.mp3");
在默認(rèn)的情況下,通過Download Manager下載的文件是不能被Media Scanner掃描到的,進(jìn)而這些下載的文件(音樂、視頻等)就不會(huì)在Gallery和Music Player這樣的應(yīng)用中看到。
為了讓下載的音樂文件可以被其他應(yīng)用掃描到,我們需要調(diào)用Request對(duì)象的allowScaningByMediaScanner方法。
如果我們希望下載的文件可以被系統(tǒng)的Downloads應(yīng)用掃描到并管理,我們需要調(diào)用Request對(duì)象的setVisibleInDownloadsUi方法,傳遞參數(shù)true。
取消和刪除下載
Download Manager的remove方法可以用來取消一個(gè)準(zhǔn)備進(jìn)行的下載,中止一個(gè)正在進(jìn)行的下載,或者刪除一個(gè)已經(jīng)完成的下載。
remove方法接受若干個(gè)download 的ID作為參數(shù),你可以設(shè)置一個(gè)或者幾個(gè)你想要取消的下載的ID,如下代碼段所示:
downloadManager.remove(REFERENCE_1, REFERENCE_2, REFERENCE_3);
該方法返回成功取消的下載的個(gè)數(shù),如果一個(gè)下載被取消了,所有相關(guān)聯(lián)的文件,部分下載的文件和完全下載的文件都會(huì)被刪除。
查詢Download Manager
你可以通過查詢Download Manager來獲得下載任務(wù)的狀態(tài),進(jìn)度,以及各種細(xì)節(jié),通過query方法返回一個(gè)包含了下載任務(wù)細(xì)節(jié)的Cursor。
query方法傳遞一個(gè)DownloadManager.Query對(duì)象作為參數(shù),通過DownloadManager.Query對(duì)象的setFilterById方法可以篩選我們希望查詢的下載任務(wù)的ID。也可以使用setFilterByStatus方法篩選我們希望查詢的某一種狀態(tài)的下載任務(wù),傳遞的參數(shù)是DownloadManager.STATUS_*常量,可以指定正在進(jìn)行、暫停、失敗、完成四種狀態(tài)。
Download Manager包含了一系列COLUMN_*靜態(tài)String常量,可以用來查詢Cursor中的結(jié)果列索引。我們可以查詢到下載任務(wù)的各種細(xì)節(jié),包括狀態(tài),文件大小,已經(jīng)下載的字節(jié)數(shù),標(biāo)題,描述,URI,本地文件名和URI,媒體類型以及Media Provider download URI。
下面的代碼段是通過注冊(cè)監(jiān)聽下載完成事件的廣播接受者來查詢下載完成文件的本地文件名和URI的實(shí)現(xiàn)方法:
@Override public void onReceive(Context context, Intent intent) { long reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if (myDownloadReference == reference) { Query myDownloadQuery = new Query(); myDownloadQuery.setFilterById(reference); Cursor myDownload = downloadManager.query(myDownloadQuery); if (myDownload.moveToFirst()) { int fileNameIdx = myDownload.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME); int fileUriIdx = myDownload.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI); String fileName = myDownload.getString(fileNameIdx); String fileUri = myDownload.getString(fileUriIdx); // TODO Do something with the file. Log.d(TAG, fileName + " : " + fileUri); } myDownload.close(); } }
對(duì)于暫停和失敗的下載,我們可以通過查詢COLUMN_REASON列查詢出原因的整數(shù)碼。
對(duì)于STATUS_PAUSED狀態(tài)的下載,可以通過DownloadManager.PAUSED_*靜態(tài)常量來翻譯出原因的整數(shù)碼,進(jìn)而判斷出下載是由于等待網(wǎng)絡(luò)連接還是等待WiFi連接還是準(zhǔn)備重新下載三種原因而暫停。
對(duì)于STATUS_FAILED狀態(tài)的下載,我們可以通過DownloadManager.ERROR_*來判斷失敗的原因,可能是錯(cuò)誤碼(失敗原因)包括沒有存儲(chǔ)設(shè)備,
存儲(chǔ)空間不足,重復(fù)的文件名,或者HTTP errors。
下面的代碼是如何查詢出當(dāng)前所有的暫停的下載任務(wù),提取出暫停的原因以及文件名稱,下載標(biāo)題以及當(dāng)前進(jìn)度的實(shí)現(xiàn)方法:
// Obtain the Download Manager Service. String serviceString = Context.DOWNLOAD_SERVICE; DownloadManager downloadManager; downloadManager = (DownloadManager)getSystemService(serviceString); // Create a query for paused downloads. Query pausedDownloadQuery = new Query(); pausedDownloadQuery.setFilterByStatus(DownloadManager.STATUS_PAUSED); // Query the Download Manager for paused downloads. Cursor pausedDownloads = downloadManager.query(pausedDownloadQuery); // Find the column indexes for the data we require. int reasonIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_REASON); int titleIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_TITLE); int fileSizeIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES); int bytesDLIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR); // Iterate over the result Cursor. while (pausedDownloads.moveToNext()) { // Extract the data we require from the Cursor. String title = pausedDownloads.getString(titleIdx); int fileSize = pausedDownloads.getInt(fileSizeIdx); int bytesDL = pausedDownloads.getInt(bytesDLIdx); // Translate the pause reason to friendly text. int reason = pausedDownloads.getInt(reasonIdx); String reasonString = "Unknown"; switch (reason) { case DownloadManager.PAUSED_QUEUED_FOR_WIFI : reasonString = "Waiting for WiFi"; break; case DownloadManager.PAUSED_WAITING_FOR_NETWORK : reasonString = "Waiting for connectivity"; break; case DownloadManager.PAUSED_WAITING_TO_RETRY : reasonString = "Waiting to retry"; break; default : break; } // Construct a status summary StringBuilder sb = new StringBuilder(); sb.append(title).append("\n"); sb.append(reasonString).append("\n"); sb.append("Downloaded ").append(bytesDL).append(" / " ).append(fileSize); // Display the status Log.d("DOWNLOAD", sb.toString()); } // Close the result Cursor. pausedDownloads.close();
附:DownloadManager的一些重要功能和參數(shù)整理
DownloadManager類提供了以下幾種方法來處理,
long enqueue(DownloadManager.Request request) //存入隊(duì)列一個(gè)新的下載項(xiàng)
ParcelFileDescriptor openDownloadedFile(long id) //打開一個(gè)下載后的文件用于讀取,參數(shù)中的long型id是一個(gè)provider中的一條記錄。
Cursor query(DownloadManager.Query query) //查詢一個(gè)下載,返回一個(gè)Cursor
int remove(long... ids) //取消下載同時(shí)移除這些條從下載管理中。
我們可以看到提供的方法都比較簡(jiǎn)單,給我們操作的最終封裝成為一個(gè)provider數(shù)據(jù)庫的方式進(jìn)行添加、查詢和移除,但是對(duì)于查詢和添加任務(wù)的細(xì)節(jié),我們要看看DownloadManager.Request類和DownloadManager.Query 類了。
一、DownloadManager.Request類的成員和定義
- DownloadManager.Request addRequestHeader(String header, String value) // 添加一個(gè)Http請(qǐng)求報(bào)頭,對(duì)于這兩個(gè)參數(shù),Android開發(fā)網(wǎng)給大家舉個(gè)小例子,比如說User-Agent值可以為Android123或 Windows XP等等了,主要是給服務(wù)器提供標(biāo)識(shí)。
- DownloadManager.Request setAllowedNetworkTypes(int flags) //設(shè)置允許使用的網(wǎng)絡(luò)類型,這一步Android 2.3做的很好,目前有兩種定義分別為NETWORK_MOBILE和NETWORK_WIFI我們可以選擇使用移動(dòng)網(wǎng)絡(luò)或Wifi方式來下載。
- DownloadManager.Request setAllowedOverRoaming(boolean allowed) //對(duì)于下載,考慮到流量費(fèi)用,這里是否允許使用漫游。
- DownloadManager.Request setDescription(CharSequence description) //設(shè)置一個(gè)描述信息,主要是最終顯示的notification提示,可以隨便寫個(gè)自己區(qū)別
- DownloadManager.Request setDestinationInExternalFilesDir(Context context, String dirType, String subPath) //設(shè)置目標(biāo)存儲(chǔ)在外部目錄,一般位置可以用 getExternalFilesDir()方法獲取。
- DownloadManager.Request setDestinationInExternalPublicDir(String dirType, String subPath) //設(shè)置外部存儲(chǔ)的公共目錄,一般通過getExternalStoragePublicDirectory()方法獲取。
- DownloadManager.Request setDestinationUri(Uri uri) //設(shè)置需要下載目標(biāo)的Uri,可以是http、ftp等等了。
- DownloadManager.Request setMimeType(String mimeType) //設(shè)置mime類型,這里看服務(wù)器配置,一般國家化的都為utf-8編碼。
- DownloadManager.Request setShowRunningNotification(boolean show) //是否顯示下載進(jìn)度的提示
- DownloadManager.Request setTitle(CharSequence title) //設(shè)置notification的標(biāo)題
- DownloadManager.Request setVisibleInDownloadsUi(boolean isVisible) //設(shè)置下載管理類在處理過程中的界面是否顯示
- 當(dāng)然了Google還提供了一個(gè)簡(jiǎn)單的方法來實(shí)例化本類,這個(gè)構(gòu)造方法為DownloadManager.Request(Uri uri) ,我們直接填寫一個(gè)Uri即可,上面的設(shè)置使用默認(rèn)情況。
二、DownloadManager.Query類
對(duì)于當(dāng)前下載內(nèi)容的狀態(tài),我們可以使用DownloadManager.Query類來獲取,本類比較簡(jiǎn)單,僅僅提供了兩個(gè)方法。
- DownloadManager.Query setFilterById(long... ids) //根據(jù)id來過濾查找。
- DownloadManager.Query setFilterByStatus(int flags) //根據(jù)任務(wù)的狀態(tài)來查找。
詳細(xì)的狀態(tài)在android.app.DownloadManager類中有定義,目前Android 2.3中的定義為:
- int STATUS_FAILED 失敗
- int STATUS_PAUSED 暫停
- int STATUS_PENDING 等待將開始
- int STATUS_RUNNING 正在處理中
- int STATUS_SUCCESSFUL 已經(jīng)下載成功
最后Android開發(fā)網(wǎng)提醒大家要說的是因?yàn)镈ownloadManager類提供的query方法返回一個(gè)Cursor對(duì)象,這些狀態(tài)保存在這個(gè)游標(biāo)的COLUMN_STATUS 字段中。
1. 下載的狀態(tài)完成均是以廣播的形式通知大家,目前API Level為9定義了下面三種Intent的action
(1)ACTION_DOWNLOAD_COMPLETE下載完成的動(dòng)作。
(2)ACTION_NOTIFICATION_CLICKED 當(dāng)用戶單擊notification中下載管理的某項(xiàng)時(shí)觸發(fā)。
(3)ACTION_VIEW_DOWNLOADS 查看下載項(xiàng)
2. 對(duì)于一個(gè)尚未完成的項(xiàng),在Cursor中我們查找COLUMN_REASON字段,可能有以下定義:
(1)int ERROR_CANNOT_RESUME 不能夠繼續(xù),由于一些其他原因。
(2)int ERROR_DEVICE_NOT_FOUND 外部存儲(chǔ)設(shè)備沒有找到,比如SD卡沒有插入。
(3)int ERROR_FILE_ALREADY_EXISTS 要下載的文件已經(jīng)存在了,Android123提示下載管理類是不會(huì)覆蓋已經(jīng)存在的文件,所以如果需要重新下載,請(qǐng)先刪除以前的文件。
(1)int ERROR_FILE_ERROR 可能由于SD卡原因?qū)е铝宋募e(cuò)誤。
(2)int ERROR_HTTP_DATA_ERROR 在Http傳輸過程中出現(xiàn)了問題。
(3)int ERROR_INSUFFICIENT_SPACE 由于SD卡空間不足造成的
(4)int ERROR_TOO_MANY_REDIRECTS 這個(gè)Http有太多的重定向,導(dǎo)致無法正常下載
(5)int ERROR_UNHANDLED_HTTP_CODE 無法獲取http出錯(cuò)的原因,比如說遠(yuǎn)程服務(wù)器沒有響應(yīng)。
(6)int ERROR_UNKNOWN 未知的錯(cuò)誤類型.
3. 有關(guān)暫停的一些狀態(tài),同樣COLUMN_REASON字段的值可能是以下定義
(1)int PAUSED_QUEUED_FOR_WIFI 由于移動(dòng)網(wǎng)絡(luò)數(shù)據(jù)問題,等待WiFi連接能用后再重新進(jìn)入下載隊(duì)列。
(2)int PAUSED_UNKNOWN 未知原因?qū)е铝巳蝿?wù)下載的暫停.
(3)int PAUSED_WAITING_FOR_NETWORK 可能由于沒有網(wǎng)絡(luò)連接而無法下載,等待有可用的網(wǎng)絡(luò)連接恢復(fù)。.
(4)int PAUSED_WAITING_TO_RETRY 由于重重原因?qū)е孪螺d暫停,等待重試。
- DownloadManager實(shí)現(xiàn)文件下載功能
- Android基于自帶的DownloadManager實(shí)現(xiàn)下載功能示例
- Android中DownloadManager實(shí)現(xiàn)文件下載實(shí)例詳解
- android中DownloadManager實(shí)現(xiàn)版本更新,監(jiān)聽下載進(jìn)度實(shí)例
- Android開發(fā)之自帶下載器DownloadManager的使用示例代碼
- 使用Android系統(tǒng)提供的DownloadManager來下載文件
- 基于DownloadManager的簡(jiǎn)單下載器編寫小結(jié)
相關(guān)文章
Android識(shí)別預(yù)裝的第三方App方法實(shí)例
這篇文章主要給大家介紹了關(guān)于Android如何識(shí)別預(yù)裝的第三方App的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01Android獲取設(shè)備隱私 忽略6.0權(quán)限管理
這篇文章主要介紹了Android獲取設(shè)備隱私,忽略6.0權(quán)限管理,感興趣的小伙伴們可以參考一下2016-01-015分鐘學(xué)會(huì)Android設(shè)計(jì)模式之策略模式Strategy Pattern教程
這篇文章主要為大家介紹了5分鐘學(xué)會(huì)Android設(shè)計(jì)模式之策略模式Strategy Pattern教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Android開發(fā)之針對(duì)聯(lián)系人的封裝
本文給大家分享的是如何在Android開發(fā)中封裝聯(lián)系人模塊以及封裝后的使用及總結(jié),最后奉上代碼,有需要的小伙伴可以參考下。2016-02-02Android實(shí)現(xiàn)自定義倒計(jì)時(shí)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)自定義倒計(jì)時(shí),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07Android仿一號(hào)店貨物詳情輪播圖動(dòng)畫效果
這篇文章主要為大家詳細(xì)介紹了Android-仿一號(hào)店貨物詳情輪播圖動(dòng)畫效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06android 仿微信demo——登錄功能實(shí)現(xiàn)(服務(wù)端)
這系列文章主要介紹了微信小程序-閱讀小程序?qū)嵗?,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望能給你們提供幫助2021-06-06android studio實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了android studio實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05