Topik ini menjelaskan isu umum dan solusinya terkait penggunaan Object Storage Service (OSS) SDK untuk Android.
Sebelum menggunakan kode contoh, integrasikan HTTPDNS SDK untuk Android. Untuk informasi selengkapnya, lihat Proses integrasi Android SDK.
Apakah Android SDK mendukung pre-resolution DNS dan kebijakan cache?
Contoh berikut menunjukkan cara mengimplementasikan pre-resolution DNS dan kebijakan cache pada Android menggunakan HTTPDNS SDK dan OkHttp.
Kustomisasi antarmuka DNS.
public class OkHttpDns implements Dns { private static final Dns SYSTEM = Dns.SYSTEM; HttpDnsService httpdns; private static OkHttpDns instance = null; private OkHttpDns(Context context) { this.httpdns = HttpDns.getService(context, "account id"); } public static OkHttpDns getInstance(Context context) { if(instance == null) { instance = new OkHttpDns(context); } return instance; } @Override public List<InetAddress> lookup(String hostname) throws UnknownHostException { // Dapatkan alamat IP dari antarmuka parsing asinkron. String ip = httpdns.getIpByHostAsync(hostname); if(ip != null) { // Jika alamat IP yang tidak null dikembalikan, gunakan untuk permintaan jaringan. List<InetAddress> inetAddresses = Arrays.asList(InetAddress.getAllByName(ip)); Log.e("OkHttpDns", "inetAddresses:" + inetAddresses); return inetAddresses; } // Jika alamat IP null dikembalikan, selesaikan nama domain menggunakan layanan DNS sistem. return Dns.SYSTEM.lookup(hostname); } }Buat instans okHttpClient dan konfigurasikan untuk OSS.
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; ClientConfiguration conf = new ClientConfiguration(); conf.setConnectionTimeout(15 * 1000); // Connection timeout. Default: 15 detik. conf.setSocketTimeout(15 * 1000); // Socket timeout. Default: 15 detik. conf.setMaxConcurrentRequest(5); // Jumlah maksimum permintaan konkuren. Default: 5. conf.setMaxErrorRetry(2); // Jumlah maksimum percobaan ulang setelah kegagalan. Default: 2. OkHttpClient.Builder builder = new OkHttpClient.Builder() .dns(OkHttpDns.getInstance(getApplicationContext())); // Jika Anda menetapkan okHttpClient kustom, beberapa pengaturan ClientConfiguration akan diabaikan. Anda harus menetapkannya secara manual pada builder. if (conf != null) { Dispatcher dispatcher = new Dispatcher(); dispatcher.setMaxRequests(conf.getMaxConcurrentRequest()); builder.connectTimeout(conf.getConnectionTimeout(), TimeUnit.MILLISECONDS) .readTimeout(conf.getSocketTimeout(), TimeUnit.MILLISECONDS) .writeTimeout(conf.getSocketTimeout(), TimeUnit.MILLISECONDS) .followRedirects(conf.isFollowRedirectsEnable()) .followSslRedirects(conf.isFollowRedirectsEnable()) .dispatcher(dispatcher); if (conf.getProxyHost() != null && conf.getProxyPort() != 0) { builder.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(conf.getProxyHost(), conf.getProxyPort()))); } } // Metode conf.setOkHttpClient() hanya didukung pada Android SDK 2.9.12 dan versi lebih baru. conf.setOkHttpClient(builder.build()); OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider, conf);
Callback progress menampilkan totalSize=-1 saat beberapa file diunduh
Penyebab
OSS mengembalikan data terkompresi Gzip untuk file berukuran 1 KB atau lebih besar dengan Content-Type text/cache-manifest, text/xml, text/plain, text/css, application/javascript, application/x-javascript, application/rss+xml, application/json, atau text/json. Kompresi ini terjadi jika header Accept-Encoding: gzip secara eksplisit ditetapkan dalam permintaan. Bahkan jika Anda tidak menetapkan header tersebut, OkHttp secara otomatis menambahkannya saat mengunduh file. Karena ukuran file terkompresi Gzip tidak dapat ditentukan, OSS tidak mengembalikan header Content-Length. Akibatnya, callback progress mengembalikan totalSize = -1.
Solusi
Tetapkan rentang (range) untuk mencegah OkHttp secara otomatis menambahkan header Accept-Encoding: gzip. Hal ini memastikan bahwa header Content-Length dikembalikan dan progress ditampilkan dengan benar.
Map<String, String> header = new HashMap<>(); header.put("x-oss-range-behavior", "standard"); // Tentukan nama bucket, misalnya examplebucket, dan path lengkap objek, misalnya exampledir/exampleobject.txt. GetObjectRequest get = new GetObjectRequest("examplebucket", "exampledir/exampleobject.txt"); get.setRange(new Range(0, -1)); get.setRequestHeaders(header); OSSAsyncTask task = oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() { @Override public void onSuccess(GetObjectRequest request, GetObjectResult result) { // Permintaan berhasil. InputStream inputStream = result.getObjectContent(); byte[] buffer = new byte[2048]; int len; try { while ((len = inputStream.read(buffer)) != -1) { // Proses data yang diunduh. } } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(GetObjectRequest request, ClientException clientExcepion, ServiceException serviceException) { // Permintaan gagal. if (clientExcepion != null) { // Terjadi exception pada client, seperti error jaringan. clientExcepion.printStackTrace(); } if (serviceException != null) { // Terjadi exception pada layanan. Log.e("ErrorCode", serviceException.getErrorCode()); Log.e("RequestId", serviceException.getRequestId()); Log.e("HostId", serviceException.getHostId()); Log.e("RawMessage", serviceException.getRawMessage()); } } });
Callback onFailure tidak dipicu saat Anda menggunakan Kotlin dengan OSS Android SDK
Penyebab
Secara default, OSS Android SDK menggunakan sintaksis Java, seperti yang ditunjukkan pada gambar berikut:

Saat menggunakan Kotlin, sintaksis onFailure pada gambar sebelumnya dapat menyebabkan masalah nullability. Untuk memperbaiki masalah ini, ubah kode sebagai berikut:
onFailure(request: ResumableUploadRequest, clientExcepion:ClientException?, serviceException: ServiceException?)