Gunakan ApsaraVideo VOD Android Upload SDK untuk mengunggah file media dari perangkat lokal ke penyimpanan ApsaraVideo VOD. Topik ini menjelaskan cara mengintegrasikan SDK, mengonfigurasi unggahan, dan menangani error.
Prasyarat
| Item | Persyaratan |
| Versi Android minimum | API 14 (Android 4.0) |
| Versi kompilasi | compileSdkVersion 30 |
| Akun Alibaba Cloud | Telah diperolehAktifkan ApsaraVideo VOD |
| Layanan otorisasi | Layanan backend yang dapat menerbitkan kredensial unggah (UploadAuth) |
Batasan penggunaan
Android SDK mendukung pengunggahan audio, video, dan gambar. Pengunggahan aset media pendukung tidak didukung.
Integrasikan SDK
Tambahkan dependensi SDK
Tambahkan repositori Maven Alibaba Cloud ke build.gradle tingkat proyek:
allprojects {
repositories {
maven { url "https://maven.aliyun.com/nexus/content/repositories/releases" }
}
}Tambahkan dependensi SDK ke build.gradle tingkat modul:
dependencies {
implementation 'com.aliyun.video.android:upload:2.0.1'
}OSS Android SDK yang mendasari disertakan secara transitif melalui dependensi api dari VODUpload. Anda tidak perlu mendeklarasikannya lagi.
Konfigurasi proyek
Deklarasikan izin yang diperlukan di AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- Izin media granular Android 13+, deklarasikan sesuai kebutuhan -->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />Jika Anda mengaktifkan obfuscation kode, tambahkan aturan berikut ke proguard-rules.pro:
-keep class com.alibaba.sdk.android.vod.upload.v2.** { *; }
-keep interface com.alibaba.sdk.android.vod.upload.v2.** { *; }OSS Android SDK yang mendasari telah menyertakan aturan ProGuard bawaan. Anda tidak perlu mendeklarasikannya lagi.
Penggunaan dasar
Penanganan callback
Upload SDK (v2) menggunakan callback asinkron terpadu VODGetAuthCallback untuk meminta kredensial unggah dari lapisan bisnis. SDK memanggil getAuth dalam skenario berikut dan menggunakan VODAuthContext.getKind() untuk menunjukkan jenis kredensial yang diperlukan:
| Jenis | Pemicu | Operasi OpenAPI yang dipanggil |
CREATE_VIDEO | Unggahan pertama file video | CreateUploadVideo |
REFRESH_VIDEO | Unggah yang dapat dilanjutkan / refresh kredensial | RefreshUploadVideo |
CREATE_IMAGE | Unggah gambar | CreateUploadImage |
Lapisan bisnis hanya perlu meneruskan respons JSON mentah dari backend OpenAPI kembali ke SDK apa adanya. SDK membaca kunci berikut menggunakan nama bidang OpenAPI yang tepat (sensitif terhadap huruf besar/kecil):
| Jenis | Bidang yang diperlukan |
CREATE_VIDEO / REFRESH_VIDEO | UploadAuth, UploadAddress, VideoId |
CREATE_IMAGE | UploadAuth, UploadAddress, ImageId, ImageURL (diteruskan ke result.getImageUrl()) |
Jangan mengganti nama bidang tersebut. Mengganti nama bidang menjadi videoId, imageUrl, atau image_url menyebabkan SDK menguraikannya sebagai null.
Contoh berikut menunjukkan implementasi getAuth yang menangani setiap jenis:
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;
}
};Inisialisasi instans unggah
Gunakan VODUploadConfig.Builder untuk membuat konfigurasi dan panggil VODUploadClient.create(...) untuk membuat instans unggah:
import com.alibaba.sdk.android.vod.upload.v2.*;
VODUploadConfig config = new VODUploadConfig.Builder()
.setGetAuth(getAuth) // Wajib: callback autentikasi. Untuk informasi selengkapnya, lihat "Penanganan callback".
.build();
VODUploadClient uploader = VODUploadClient.create(context, config);Instans uploader dapat digunakan kembali. Anda dapat menggunakan instans yang sama untuk mengunggah beberapa file secara konkuren. Panggil uploader.dispose() untuk melepaskan sumber daya saat siklus hidup berakhir.
Kontrol unggah
Panggil upload(...) untuk memulai unggahan. Metode ini mengembalikan handle VODUploadTask yang dapat Anda gunakan untuk membatalkan unggahan:
VODVideoMeta meta = new VODVideoMeta.Builder()
.setTitle("My Video")
.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());
}
});
// Batalkan unggahan di tengah jalan. Unggah yang dapat dilanjutkan diaktifkan secara default. Pemanggilan upload(...) berikutnya untuk file yang sama akan secara otomatis melanjutkan unggahan.
task.cancel();
// task.getUploadTaskId() dapat digunakan untuk mengkorelasikan log atau mengintegrasikan dengan analitik.upload(...) menyediakan dua overload yang mendukung path file dan URI content:// (kompatibel dengan Scoped Storage Android 10+):
uploader.upload(String filePath, VODUploadOptions options, VODUploadResultCallback callback);
uploader.upload(Uri fileUri, VODUploadOptions options, VODUploadResultCallback callback);Unggah gambar: SDK secara otomatis menggunakan jalur unggah gambar berdasarkan ekstensi nama file (jpg / jpeg / png / gif / bmp / webp / heic) atau ketika options.imageMeta != null. Di callback sukses, result.getImageId() dan result.getImageUrl() berisi nilai yang valid:
VODImageMeta imgMeta = new VODImageMeta.Builder()
.setImageType("cover")
.setTitle("Cover")
.build();
uploader.upload("/sdcard/cover.jpg",
new VODUploadOptions.Builder().setImageMeta(imgMeta).build(),
callback);Pengaturan lanjutan
Akselerasi unggah
Atur VODVideoMeta.userData ke JSON berikut. Server VOD secara otomatis mengembalikan titik akhir akselerasi transfer global OSS (oss-accelerate.aliyuncs.com) saat menerbitkan UploadAddress. SDK mengunggah langsung ke titik akhir percepatan:
VODVideoMeta meta = new VODVideoMeta.Builder()
.setTitle("My Video")
.setUserData("{\"Type\":\"oss\",\"Domain\":\"oss-accelerate.aliyuncs.com\"}")
.build();Akselerasi unggah bergantung pada akselerasi transfer global OSS. Anda harus mengaktifkan akselerasi transfer untuk bucket di Konsol OSS. Untuk informasi selengkapnya, lihat Akses OSS menggunakan akselerasi transfer.
Unggah dan transkoding
Tentukan kelompok template transkoding atau alur kerja melalui VODVideoMeta:
VODVideoMeta meta = new VODVideoMeta.Builder()
.setTitle("My Video")
.setDescription("Video description")
.setCoverUrl("https://example.com/cover.jpg")
.setCateId(1000)
.setTags("tag1,tag2")
.setStorageLocation("<Opsional: wilayah penyimpanan kustom>")
.setTemplateGroupId("<ID kelompok template Anda>") // kelompok template transkoding
.setWorkflowId("<ID alur kerja Anda>") // Alur kerja (opsional)
.setAppId("<Opsional: ID aplikasi>")
.build();VODVideoMeta mendukung bidang berikut: title / description / coverUrl / cateId / tags / userData / storageLocation / templateGroupId / workflowId / appId. Semua bidang bersifat opsional dan diteruskan ke CreateUploadVideo.
Setelah unggahan selesai, server VOD melakukan transkoding video sumber berdasarkan kelompok template transkoding. Jika Anda tidak ingin memicu transkoding, teruskan kelompok template "tanpa transkoding" dalam pemanggilan CreateUploadVideo dari backend Anda.
Timeout dan retry
Konfigurasikan timeout dan jumlah retry untuk permintaan OSS:
VODUploadConfig config = new VODUploadConfig.Builder()
.setGetAuth(getAuth)
.setTimeout(60 * 1000) // Satuan: milidetik. Default: 60 detik
.setMaxRetryCount(2) // Default: 2
.build();timeout mengontrol timeout koneksi dan baca/tulis untuk satu permintaan OSS (dalam milidetik). maxRetryCount mengontrol jumlah retry untuk permintaan OSS saat terjadi exception jaringan.
Versi signature
Tentukan versi signature OSS:
VODUploadConfig config = new VODUploadConfig.Builder()
.setGetAuth(getAuth)
.setSignature("v4") // Default: "v4". Opsi: "v1"
.build();Signature OSS V4 adalah versi yang direkomendasikan. Mulai 1 September 2025, bucket yang baru dibuat harus menggunakan signature V4. Pelanggan yang sudah ada juga disarankan untuk segera migrasi. Atur "v1" secara eksplisit hanya jika bucket Anda masih hanya mendukung signature V1.
Unggah yang dapat dilanjutkan
Secara default, unggah yang dapat dilanjutkan diaktifkan. SDK menggunakan triplet (lastModified, fileName, fileSize) sebagai kunci unggah yang dapat dilanjutkan dan secara otomatis menyimpannya ke SharedPreferences.
| Skenario | Perilaku SDK |
task.cancel() dipanggil selama unggahan | Catatan unggah yang dapat dilanjutkan dipertahankan. Pemanggilan upload(...) berikutnya untuk file yang sama secara otomatis melanjutkan unggahan. |
| Crash aplikasi / terminasi proses | Catatan unggah yang dapat dilanjutkan dipertahankan. Pemanggilan upload(...) cold start berikutnya untuk file yang sama secara otomatis melanjutkan unggahan. |
| Adanya perubahan pada sidik jari file | File dianggap sebagai file baru dan diunggah dari awal. |
| Kedaluwarsa uploadId OSS | SDK secara otomatis menghapus catatan lama dan memulai unggahan baru melalui CREATE_VIDEO. |
Untuk menonaktifkan unggah yang dapat dilanjutkan:
new VODUploadConfig.Builder().setGetAuth(getAuth).setCheckpoint(false).build();Unggah multipart
Gunakan partSize untuk mengontrol ukuran part dan parallel untuk mengontrol jumlah part konkuren:
// Konfigurasi global
VODUploadConfig config = new VODUploadConfig.Builder()
.setGetAuth(getAuth)
.setPartSize(1024 * 1024) // Default: 1 MB
.setParallel(4) // Default: 4
.build();
// Timpa untuk satu task
VODUploadOptions options = new VODUploadOptions.Builder()
.setVideoMeta(meta)
.setPartSize(2 * 1024 * 1024)
.setParallel(6)
.build();Tentukan wilayah layanan VOD
Tentukan wilayah layanan ApsaraVideo VOD:
new VODUploadConfig.Builder()
.setGetAuth(getAuth)
.setRegion("cn-shanghai") // Default: cn-shanghai
.build();Untuk daftar wilayah yang didukung, lihat ID wilayah ApsaraVideo VOD.
Pelaporan data
Secara default, SDK mengaktifkan instrumentasi jalur unggah untuk pemantauan kualitas produk. Hanya metrik waktu proses dari proses unggah yang dikumpulkan. Konten file tidak dikumpulkan. Untuk menonaktifkan pelaporan data:
VODUploadConfig config = new VODUploadConfig.Builder()
.setGetAuth(getAuth)
.setReportEnabled(false) // Default: true
.build();Penanganan error
VODUploadError merupakan turunan dari java.lang.Exception. Kode error mengikuti format tiga segmen UPLOAD.{LAYER}.{TIPE}:
| LAYER | Kode error | Deskripsi |
| AUTH | UPLOAD.AUTH.GET_AUTH_FAILED | Callback getAuth gagal. |
| AUTH | UPLOAD.AUTH.DECODE_FAILED | Gagal mengurai UploadAuth. |
| AUTH | UPLOAD.AUTH.EXPIRED | Kredensial telah kedaluwarsa. |
| OSS | UPLOAD.OSS.ACCESS_DENIED | Akses OSS ditolak (masalah izin/signature). |
| OSS | UPLOAD.OSS.NO_SUCH_BUCKET | Bucket tidak ada. |
| OSS | UPLOAD.OSS.NO_SUCH_UPLOAD | uploadId telah kedaluwarsa. SDK secara otomatis kembali ke unggahan baru. |
| OSS | UPLOAD.OSS.UPLOAD_FAILED | Unggahan OSS gagal. |
| OSS | UPLOAD.OSS.MERGE_FAILED | Penggabungan multipart OSS gagal. |
| NETWORK | UPLOAD.NETWORK.TIMEOUT | Timeout jaringan. |
| NETWORK | UPLOAD.NETWORK.UNREACHABLE | Jaringan tidak dapat dijangkau. |
| FILE | UPLOAD.FILE.NOT_FOUND | File tidak ada. |
| FILE | UPLOAD.FILE.EMPTY | File kosong. |
| CANCEL | UPLOAD.CANCEL.USER_CANCELLED | Unggahan dibatalkan oleh pengguna. |
| INTERNAL | UPLOAD.INTERNAL.DISPOSED | Instans telah di-dispose. |
| INTERNAL | UPLOAD.INTERNAL.INVALID_CONFIG | Konfigurasi tidak valid. |
Metode publik dari VODUploadError:
String getErrorCode()— Mengembalikan kode error.String getErrorMessage()— Mengembalikan pesan error.String getUploadTaskId()— Mengembalikan ID task unggah.String getSuggestion()— Mengembalikan saran perbaikan bawaan dari SDK.Throwable getCause()— Mengembalikan exception OSS mendasar (diwariskan dariException).
Contoh berikut menangani error berdasarkan kode error:
@Override public void onFailure(VODUploadError e) {
if (e.getErrorCode().startsWith("UPLOAD.AUTH.")) {
// Prompt pengguna untuk memeriksa autentikasi backend
} else if (VODUploadError.OSS_UPLOAD_FAILED.equals(e.getErrorCode())) {
// Coba ulang atau prompt pengguna untuk memeriksa jaringan
}
Log.e(TAG, e.getErrorCode() + ": " + e.getErrorMessage()
+ " (suggestion=" + e.getSuggestion() + ")", e.getCause());
}FAQ
Apakah saya dapat memulai beberapa unggahan secara simultan?
Ya. Setiap task bersifat independen. Sebagai praktik terbaik, kendalikan jumlah unggahan konkuren berdasarkan kondisi jaringan untuk menghindari peningkatan tekanan bandwidth upstream saat dikombinasikan dengan parallel.
Unggah yang dapat dilanjutkan tidak berfungsi setelah pembatalan dan unggah ulang
Periksa hal berikut:
Verifikasi bahwa path file sama.
Verifikasi bahwa nilai
lastModifieddansizefile tidak berubah.Verifikasi bahwa
config.checkpointdiatur ketrue.Verifikasi apakah uploadId telah kedaluwarsa. Saat respons adalah
NoSuchUpload, SDK secara otomatis kembali ke unggahan baru. Ini adalah perilaku yang diharapkan.
Apa nilai fileName dan fileSize saat mengunggah URI content://?
SDK membaca OpenableColumns.DISPLAY_NAME dan OpenableColumns.SIZE melalui ContentResolver.query(...). Jika ukuran tidak dapat dibaca, UPLOAD.FILE.EMPTY dikembalikan.
Apa yang dikembalikan oleh getCause()?
Nilai kembali diwariskan dari Exception dan mempertahankan ServerException, ClientException, atau IOException OSS mendasar, yang membantu Anda melakukan troubleshooting secara mendalam.