本文介紹如何使用Android SDK將媒體檔案從本地上傳至點播儲存。
前提條件
專案 | 要求 |
最低 Android 版本 | API 14(Android 4.0) |
編譯版本 | compileSdkVersion 30 |
阿里雲帳號 | |
鑒權服務 | 已準備好可簽發上傳憑證(UploadAuth)的後端服務 |
使用限制
目前Android SDK 只支援上傳音、視頻,不支援上傳輔助媒資。
整合SDK
整合方式
在工程根 build.gradle 中加入阿里雲 Maven 倉庫:
allprojects {
repositories {
maven { url "https://maven.aliyun.com/nexus/content/repositories/releases" }
}
}在模組 build.gradle 中加入 SDK 依賴:
dependencies {
implementation 'com.aliyun.video.android:upload:<sdk_version>'
}底層 OSS Android SDK 已由 VODUpload 通過 api 依賴傳遞,無需重複聲明。
專案配置
在 AndroidManifest.xml 中聲明許可權:
<uses-permission android:name="android.permission.INTERNET" />2<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />3<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />4<!-- Android 13+ 媒體細分許可權按需聲明 -->5<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />6<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />如開啟了代碼混淆,在 proguard-rules.pro 中追加:
-keep class com.alibaba.sdk.android.vod.upload.v2.** { *; }
-keep interface com.alibaba.sdk.android.vod.upload.v2.** { *; }底層 OSS Android SDK 內建 ProGuard 規則,無需重複聲明。
基礎設定
初始化上傳執行個體
通過 VODUploadConfig.Builder 構造配置並調用 VODUploadClient.create(...) 建立上傳執行個體:
import com.alibaba.sdk.android.vod.upload.v2.*;23VODUploadConfig config = new VODUploadConfig.Builder()4 .setGetAuth(getAuth) // 必填:鑒權回調,詳見"回調處理"5 .build();67VODUploadClient uploader = VODUploadClient.create(context, config);uploader 執行個體可複用,並發上傳多個檔案時複用同一執行個體即可。生命週期結束時調用 uploader.dispose() 釋放資源。
上傳控制
調用 upload(...) 啟動一次上傳,返回 VODUploadTask 控制代碼用於取消:
VODVideoMeta meta = new VODVideoMeta.Builder()
.setTitle("我的視訊")
.setTags("demo")
.setCateId(1000)
.build();
VODUploadOptions options = new VODUploadOptions.Builder()
.setVideoMeta(meta)
.setOnProgress((percent, uploaded, total) ->
Log.d("Upload", String.format("%.1f%%", percent * 100)))
.build();
VODUploadTask task = uploader.upload(filePath, options, new VODUploadResultCallback() {
@Override public void onSuccess(VODUploadResult r) {
Log.i("Upload",
"videoId=" + r.getVideoId()
+ " uploadTaskId=" + r.getUploadTaskId()
+ " etag=" + r.getEtag()
+ " requestId=" + r.getRequestId()
+ " durationMs=" + r.getDurationMs());
}
@Override public void onFailure(VODUploadError e) {
Log.e("Upload", e.getErrorCode() + " : " + e.getErrorMessage(), e.getCause());
}
});
// 中途取消(預設開啟斷點續傳,下次同檔案 upload 自動續傳)
task.cancel();
// task.getUploadTaskId() 可用於關聯日誌、對接埋點upload(...) 提供兩種重載,支援檔案路徑和 content:// Uri(適配 Android 10+ Scoped Storage):
uploader.upload(String filePath, VODUploadOptions options, VODUploadResultCallback callback);
uploader.upload(Uri fileUri, VODUploadOptions options, VODUploadResultCallback callback);圖片上傳:SDK 根據副檔名(jpg / jpeg / png / gif / bmp / webp / heic)或 options.imageMeta != null 自動走圖片鏈路,成功回調中 result.getImageId() 與 result.getImageUrl() 有值:
VODImageMeta imgMeta = new VODImageMeta.Builder()
.setImageType("cover")
.setTitle("封面")
.build();
uploader.upload("/sdcard/cover.jpg",
new VODUploadOptions.Builder().setImageMeta(imgMeta).build(),
callback);回調處理
v2 通過統一的 VODGetAuthCallback 非同步回調向業務方索取上傳憑證。SDK 在以下時機調用 getAuth,並通過 VODAuthContext.getKind() 告知所需憑證類型:
Kind | 觸發時機 | 業務方應調用的 OpenAPI |
| 首次上傳一個視頻檔案 | |
| 續傳 / 憑證重新整理 | |
| 上傳圖片 |
業務方只需把後端 OpenAPI 返回的原始 JSON 原樣回傳給 SDK。SDK 按 OpenAPI 原始欄位名(大小寫敏感)讀取以下鍵:
Kind | 必須包含的欄位 |
|
|
|
|
欄位名大小寫敏感,請直接轉寄 OpenAPI 響應;自行重新命名為 videoId / imageUrl / image_url 會導致 SDK 解析為 null。
VODGetAuthCallback getAuth = (ctx, completion) -> {
switch (ctx.getKind()) {
case CREATE_VIDEO:
yourBackend.createUploadVideo(ctx.getFileName(), ctx.getFileSize(),
json -> completion.onSuccess(json),
err -> completion.onFailure("BIZ.CREATE_VIDEO", err.getMessage()));
break;
case REFRESH_VIDEO:
yourBackend.refreshUploadVideo(ctx.getVideoId(),
json -> completion.onSuccess(json),
err -> completion.onFailure("BIZ.REFRESH_VIDEO", err.getMessage()));
break;
case CREATE_IMAGE:
yourBackend.createUploadImage(ctx.getFileName(),
json -> completion.onSuccess(json),
err -> completion.onFailure("BIZ.CREATE_IMAGE", err.getMessage()));
break;
}
};進階設定
上傳加速
將 VODVideoMeta.userData 設定為下面的 JSON,VOD 服務端在簽發 UploadAddress 時會自動返回 OSS 全球傳輸加速節點(oss-accelerate.aliyuncs.com),SDK 直傳到加速節點完成上傳:
VODVideoMeta meta = new VODVideoMeta.Builder()
.setTitle("我的視訊")
.setUserData("{\"Type\":\"oss\",\"Domain\":\"oss-accelerate.aliyuncs.com\"}")
.build();上傳加速能力依賴 OSS 全球傳輸加速,需在 OSS 控制台對 Bucket 開啟傳輸加速。詳情請參見通過傳輸加速訪問OSS。
上傳轉碼
通過 VODVideoMeta 指定轉碼模板組或工作流程:
VODVideoMeta meta = new VODVideoMeta.Builder()
.setTitle("我的視訊")
.setDescription("視頻描述")
.setCoverUrl("https://example.com/cover.jpg")
.setCateId(1000)
.setTags("tag1,tag2")
.setStorageLocation("<可選:自訂儲存地區>")
.setTemplateGroupId("<你的模板組 ID>") // 轉碼模板組
.setWorkflowId("<你的工作流程 ID>") // 工作流程(可選)
.setAppId("<可選:應用 ID>")
.build();VODVideoMeta 支援的欄位:title / description / coverUrl / cateId / tags / userData / storageLocation / templateGroupId / workflowId / appId。所有欄位均可選,最終透傳到 CreateUploadVideo。
上傳完成後 VOD 服務端根據模板組對源視頻轉碼。若不希望觸發轉碼,業務後端在 CreateUploadVideo 時傳入"無轉碼"模板組即可。
逾時重試
VODUploadConfig config = new VODUploadConfig.Builder()
.setGetAuth(getAuth)
.setTimeout(60 * 1000) // 單位:毫秒,預設 60s
.setMaxRetryCount(2) // 預設 2 次
.build();timeout 控制單次 OSS 請求的串連 / 讀寫逾時(單位毫秒);maxRetryCount 控制 OSS 請求在網路異常時的重試次數。
簽名版本
VODUploadConfig config = new VODUploadConfig.Builder()
.setGetAuth(getAuth)
.setSignature("v4") // 預設 "v4",可選 "v1"
.build();OSS V4 簽名是當前推薦版本,自 2025-09-01 起建立 Bucket 強制使用 V4 簽名,存量客戶也建議儘快遷移。僅當業務方依賴的 Bucket 仍只支援 V1 簽名時才需顯式設定 "v1"。
斷點續傳
預設開啟。SDK 使用 (lastModified, fileName, fileSize) 三元組作為續傳 key,自動持久化到 SharedPreferences:
情境 | SDK 行為 |
上傳途中調用 | 保留續傳記錄,下次同檔案 |
App 崩潰 / 進程被殺 | 保留續傳記錄,下次冷啟同檔案 |
檔案指紋任一變化 | 視為新檔案,全新上傳 |
OSS uploadId 到期 | SDK 自動清除舊記錄,重新走 |
如需關閉:
new VODUploadConfig.Builder().setGetAuth(getAuth).setCheckpoint(false).build();分區上傳
通過 partSize 控制分區大小、parallel 控制並發分區數:
// 全域配置
VODUploadConfig config = new VODUploadConfig.Builder()
.setGetAuth(getAuth)
.setPartSize(1024 * 1024) // 預設 1MB
.setParallel(4) // 預設 4
.build();
// 單次任務覆蓋
VODUploadOptions options = new VODUploadOptions.Builder()
.setVideoMeta(meta)
.setPartSize(2 * 1024 * 1024)
.setParallel(6)
.build();設定點播服務地區
new VODUploadConfig.Builder()
.setGetAuth(getAuth)
.setRegion("cn-shanghai") // 預設 cn-shanghai
.build();支援的 region 列表見點播地區標識。
資料上報
SDK 預設開啟上傳鏈路埋點用於產品品質監控,僅採集上傳過程的運行指標,不包含檔案內容。如需關閉:
VODUploadConfig config = new VODUploadConfig.Builder()
.setGetAuth(getAuth)
.setReportEnabled(false) // 預設 true
.build();錯誤處理
VODUploadError 繼承自 java.lang.Exception,錯誤碼採用 UPLOAD.{LAYER}.{TYPE} 三段式:
LAYER | 錯誤碼 | 含義 |
AUTH |
| getAuth 回調失敗 |
AUTH |
| UploadAuth 解碼失敗 |
AUTH |
| 憑證到期 |
OSS |
| OSS 拒絕訪問(許可權/簽名) |
OSS |
| Bucket 不存在 |
OSS |
| uploadId 到期(SDK 自動 fallback) |
OSS |
| OSS 上傳失敗 |
OSS |
| OSS 分區合并失敗 |
NETWORK |
| 網路逾時 |
NETWORK |
| 網路不可達 |
FILE |
| 檔案不存在 |
FILE |
| 檔案為空白 |
CANCEL |
| 使用者取消 |
INTERNAL |
| 執行個體已 dispose |
INTERNAL |
| 配置非法 |
公開方法:
String getErrorCode()— 錯誤碼。String getErrorMessage()— 錯誤資訊。String getUploadTaskId()— 上傳任務 ID。String getSuggestion()— SDK 內建的修複建議。Throwable getCause()— 底層 OSS 異常(繼承自 Exception)。
@Override public void onFailure(VODUploadError e) {
if (e.getErrorCode().startsWith("UPLOAD.AUTH.")) {
// 提醒使用者檢查後端鑒權
} else if (VODUploadError.OSS_UPLOAD_FAILED.equals(e.getErrorCode())) {
// 重試或提示使用者檢查網路
}
Log.e(TAG, e.getErrorCode() + ": " + e.getErrorMessage()
+ " (suggestion=" + e.getSuggestion() + ")", e.getCause());
}常見問題
能否同時發起多個upload
可以,每個 task 獨立。建議根據網路情況控制並發數,避免與 parallel 疊加放大上行頻寬壓力。
取消後再次upload沒有續傳
請按以下步驟排查:
確認是否同一檔案路徑;
確認檔案 lastModified / size 是否變化;
確認
config.checkpoint是否為true;確認uploadId 是否到期(響應
NoSuchUpload時 SDK 自動 fallback 全新上傳,屬預期行為)。
上傳content://Uri時fileName/fileSize拿到的是什麼
SDK 通過 ContentResolver.query(...) 讀取 OpenableColumns.DISPLAY_NAME 與 OpenableColumns.SIZE。讀不到 size 直接返回 UPLOAD.FILE.EMPTY。
getCause()返回什麼
繼承自 Exception,保留底層 OSS ServerException / ClientException / IOException 等,便於深度排查。