This topic provides answers to some commonly asked questions when you use Object Storage Service (OSS) SDK for Android.
Before you use the sample code, you must install HTTPDNS SDK for Android. For more information, see Install HTTPDNS SDK for Android.
Does OSS SDK for Android support DNS pre-resolution and cache policies?
Yes, OSS SDK for Android supports DNS pre-resolution and cache policies. The following sample code provides an example on how to use OSS SDK for Android with HTTPDNS SDK and OkHttp to implement DNS pre-resolution and cache policies.
Implement the API for a custom DNS resolution service.
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 { // Obtain the IP address by using the asynchronous parsing operation. String ip = httpdns.getIpByHostAsync(hostname); if(ip != null) { // If the returned IP address is not null, use the returned IP address to send requests. List<InetAddress> inetAddresses = Arrays.asList(InetAddress.getAllByName(ip)); Log.e("OkHttpDns", "inetAddresses:" + inetAddresses); return inetAddresses; } // If the returned IP address is null, use the system DNS service to resolve the domain name. return Dns.SYSTEM.lookup(hostname); } }
Create an okHttpClient instance and configure the instance for DNS pre-resolution and caching.
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; ClientConfiguration conf = new ClientConfiguration(); conf.setConnectionTimeout(15 * 1000); // The connection timeout period. Unit: seconds. Default value: 15. conf.setSocketTimeout(15 * 1000); // The socket timeout period. Unit: seconds. Default value: 15. conf.setMaxConcurrentRequest(5); // The maximum number of concurrent requests. Default value: 5. conf.setMaxErrorRetry(2); // The maximum number of retries. Default value: 2. OkHttpClient.Builder builder = new OkHttpClient.Builder() .dns(OkHttpDns.getInstance(getApplicationContext())); // If a custom value is specified for okHttpClient, some ClientConfiguration settings become invalid and must be manually specified in the 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()))); } } // Only OSS SDK for Android 2.9.12 or later supports the conf.setOkHttpClient(); method. conf.setOkHttpClient(builder.build()); OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider, conf);
Why does a progress callback return totalSize=-1 when I download objects?
Cause:
If you explicitly specify the Accept-Encoding:gzip header in your request to download an object whose Content-Type is text/cache-manifest, text/xml, text/plain, text/css, application/javascript, application/x-javascript, application/rss+xml, application/json, or text/json and whose size is greater than or equal to 1 KB, OSS returns data in the gzip format. Even if the Accept-Encoding header is not specified in the request when you download such an object, OkHttp automatically includes Accept-Encoding:gzip in the request and OSS returns data in gzip format. OSS cannot identify the size of an object in the gzip format and does not return the Content-Length response header. In this case, a progress callback returns totalSize=-1.
Solution:
To fix this issue, you can use Range to stop OkHttp from automatically including Accept-Encoding:gzip in requests. This way, OSS returns the Content-Length response header and a progress callback returns the progress as expected.
Map<String, String> header = new HashMap<>(); header.put("x-oss-range-behavior", "standard"); // Specify the name of the bucket and the full path of the object. In this example, the bucket name is examplebucket and the full path of the object is 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) { // The request is successful. InputStream inputStream = result.getObjectContent(); byte[] buffer = new byte[2048]; int len; try { while ((len = inputStream.read(buffer)) != -1) { // Process the downloaded data. } } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(GetObjectRequest request, ClientException clientExcepion, ServiceException serviceException) { // Handle request exceptions. if (clientExcepion != null) { // Handle client exceptions, such as network exceptions. clientExcepion.printStackTrace(); } if (serviceException != null) { // Handle service exceptions. Log.e("ErrorCode", serviceException.getErrorCode()); Log.e("RequestId", serviceException.getRequestId()); Log.e("HostId", serviceException.getHostId()); Log.e("RawMessage", serviceException.getRawMessage()); } } });