快速入门
最近更新时间: 2024-10-17 17:10:00
开发准备
SDK 获取
对象存储服务的 XML Android SDK 资源下载地址:XML Android SDK。 演示示例 Demo 下载地址:XML Android SDK Demo。
开发准备
SDK 支持 Android 2.2 及以上版本的手机系统;
手机必须要有网络(GPRS、3G 或 WIFI 网络等);
手机可以没有存储空间,但会使部分功能无法正常工作;
从 COS v5 控制台 获取 APPID、SecretId、SecretKey。
说明:
关于文章中出现的 SecretId、SecretKey、Bucket 等名称的含义和获取方式请参考:COS 术语信息
SDK 配置
需要在工程项目中导入下列 jar 包,存放在 libs 文件夹下:
cos-android-sdk-V5.4.3.jar
qcloud-foundation.1.3.0.jar
okhttp-3.8.1.jar
okio-1.13.0.jar
或者使用gradle方式集成SDK到你的项目中,如下所示:
- compile 'com.tencent.qcloud:cosxml:5.4.3'
使用该 SDK 需要网络、存储等相关的一些访问权限,可在 AndroidManifest.xml 中增加如下权限声明(Android 5.0 以上还需要动态获取权限):
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
快速入门
初始化
进行任何操作之前,都需要实例化 CosXmlService 和 CosXmlServiceConfig。
CosXmlServiceConfig: 配置参数;
CosXmlService:SDK 提供的服务类,可操作各种 COS 服务;
String appid = "对象存储的服务 APPID";
String region = "存储桶所在的地域";
String domain = "DOMAIN.com"; // 替换成用户的 Domain
String endpoint = String.format("cos.%s.%s", region, domain);
String secretId = "云 API 密钥 SecretId";
String secretKey ="云 API 密钥 SecretKey";
long keyDuration = 600; //SecretKey 的有效时间,单位秒
//创建 CosXmlServiceConfig 对象,根据需要修改默认的配置参数
CosXmlServiceConfig serviceConfig = new CosXmlServiceConfig.Builder()
.setEndpointSuffix(endpoint)
.setDebuggable(true)
.builder();
//创建获取签名类(请参考下面的生成签名示例,或者参考 sdk中提供的ShortTimeCredentialProvider类)
LocalCredentialProvider localCredentialProvider = new LocalCredentialProvider(secretId, secretKey, keyDuration);
//创建 CosXmlService 对象,实现对象存储服务各项操作.
Context context = getApplicationContext(); //应用的上下文
CosXmlService cosXmlService = new CosXmlService(context,cosXmlServiceConfig, localCredentialProvider);
简单上传文件
String bucket = "存储桶名称"; // cos v5 的 bucket格式为:xxx-appid, 如 test-1253960454
String cosPath = "远端路径,即存储到 COS 上的绝对路径"; //格式如 cosPath = "/test.txt";
String srcPath = "本地文件的绝对路径"; // 如 srcPath = Environment.getExternalStorageDirectory().getPath() + "/test.txt";
long signDuration = 600; //签名的有效期,单位为秒
PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, cosPath, srcPath);
putObjectRequest.setSign(signDuration,null,null); //若不调用,则默认使用sdk中sign duration(60s)
/*设置进度显示
实现 CosXmlProgressListener.onProgress(long progress, long max)方法,
progress 已上传的大小, max 表示文件的总大小
*/
putObjectRequest.setProgressListener(new CosXmlProgressListener() {
@Override
public void onProgress(long progress, long max) {
float result = (float) (progress * 100.0/max);
Log.w("TEST","progress =" + (long)result + "%");
}
});
//使用同步方法上传
try {
PutObjectResult putObjectResult = cosXmlService.putObject(putObjectRequest);
Log.w("TEST","success: " + putObjectResult.accessUrl);
} catch (CosXmlClientException e) {
//抛出异常
Log.w("TEST","CosXmlClientException =" + e.toString());
} catch (CosXmlServiceException e) {
//抛出异常
Log.w("TEST","CosXmlServiceException =" + e.toString());
}
//使用异步回调上传:sdk 为对象存储各项服务提供异步回调操作方法
/**
cosXmlService.putObjectAsync(putObjectRequest, new CosXmlResultListener() {
@Override
public void onSuccess(CosXmlRequest request, CosXmlResult result) {
Log.w("TEST","success =" + result.accessUrl);
}
@Override
public void onFail(CosXmlRequest cosXmlRequest, CosXmlClientException clientException, CosXmlServiceException serviceException) {
String errorMsg = clientException != null ? clientException.toString() : serviceException.toString();
Log.w("TEST",errorMsg);
}
});
*/
分片上传文件
分片上传一般需要经历:初始化分片上传->分块上传->上传完成 3 个阶段。
String bucket = "存储桶名称"; // cos v5 的 bucket格式为:xxx-appid, 如 test-1253960454
String cosPath = "远端路径,即存储到 COS 上的绝对路径";
//第一步,初始化分片上传,获取 uploadId,用于后续的分片上传、完成上传等。
String uploadId = null;
InitMultipartUploadRequest initMultipartUploadRequest = new InitMultipartUploadRequest(bucket, cosPath);
initMultipartUploadRequest.setSign(600,null,null);
try {
InitMultipartUploadResult initMultipartUploadResult =
cosXmlService.initMultipartUpload(initMultipartUploadRequest);
//若初始化成功,则获取 uploadId;
Log.w("TEST","success");
uploadId = initMultipartUploadResult.initMultipartUpload.uploadId;
} catch (CosXmlClientException e) {
//抛出异常
Log.w("TEST","CosXmlClientException =" + e.toString());
} catch (CosXmlServiceException e) {
//抛出异常
Log.w("TEST","CosXmlServiceException =" + e.toString());
}
//第二步,分片上传,需要参数 uploadId 和分片号 partNumber; 并获取对应的 eTag # 此处只演示只有一个分片的文件例子 #.
//分片号:此分片在所有分片中的编号,从 1 开始
//etag: 是此分片上传成功后,返回的此分片的 MD5+ 分片号组成的。
String srcPath = "本地文件的绝对路径";
int partNumber = 1; //上传分片编码,从 1 开始; 此处演示上传第一个分片
String eTag = null;
UploadPartRequest uploadPartRequest = new UploadPartRequest(bucket, cosPath, partNumber,
srcPath, uploadId);
uploadPartRequest.setSign(600,null,null);
/*设置进度显示
实现 CosXmlProgressListener.onProgress(long progress, long max)方法,
progress已上传的大小, max 表示文件的总大小
*/
uploadPartRequest.setProgressListener(new CosXmlProgressListener() {
@Override
public void onProgress(long progress, long max) {
float result = (float) (progress * 100.0/max);
Log.w("TEST","progress =" + (long)result + "%");
}
});
try {
UploadPartResult uploadPartResult = cosXmlService.uploadPart(uploadPartRequest);
Log.w("TEST","success");
eTag = uploadPartResult.eTag; // 获取分片文件的 eTag
} catch (CosXmlClientException e) {
//抛出异常
Log.w("TEST","CosXmlClientException =" + e.toString());
} catch (CosXmlServiceException e) {
//抛出异常
Log.w("TEST","CosXmlServiceException =" + e.toString());
}
//第三步,当确定所有分片全部上传完成之后,调用 CompleteMultiUploadRequest 完成分片上传结束。
//需要参数 uploadId, partNumber 和对应每块分片文件的 eTag 值
CompleteMultiUploadRequest completeMultiUploadRequest = new CompleteMultiUploadRequest(bucket, cosPath, uploadId, null);
completeMultiUploadRequest.setPartNumberAndEtag(partNumber, eTag); //此处只演示一个分片的例子
completeMultiUploadRequest.setSign(600,null,null);
try {
CompleteMultiUploadResult completeMultiUploadResult =
cosXmlService.completeMultiUpload(completeMultiUploadRequest);
Log.w("TEST","success: " + completeMultiUploadResult.accessUrl );
} catch (CosXmlClientException e) {
//抛出异常
Log.w("TEST","CosXmlClientException =" + e.toString());
} catch (CosXmlServiceException e) {
//抛出异常
Log.w("TEST","CosXmlServiceException =" + e.toString());
}
UploadService,推荐使用该方法进行分片上传
//UploadService 封装了上述分片上传请求一系列过程的类
UploadService.ResumeData resumeData = new UploadService.ResumeData();
resumeData.bucket = "存储桶名称";
resumeData.cosPath = "远端路径,即存储到 COS 上的绝对路径"; //格式如 cosPath = "/test.txt";
resumeData.srcPath = "本地文件的绝对路径"; // 如 srcPath =Environment.getExternalStorageDirectory().getPath() + "/test.txt";
resumeData.sliceSize = 1024 * 1024; //每个分片的大小
resumeData.uploadId = null; //若是续传,则uploadId不为空
UploadService uploadService = new UploadService(cosXmlService, resumeData);
/*设置进度显示
实现 CosXmlProgressListener.onProgress(long progress, long max)方法,
progress 已上传的大小, max 表示文件的总大小
*/
uploadService.setProgressListener(new CosXmlProgressListener() {
@Override
public void onProgress(long progress, long max) {
float result = (float) (progress * 100.0/max);
Log.w("TEST","progress =" + (long)result + "%");
}
});
try {
CosXmlResult cosXmlResult = uploadService.upload();
Log.w("TEST","success: " + cosXmlResult.accessUrl );
} catch (CosXmlClientException e) {
//抛出异常
Log.w("TEST","CosXmlClientException =" + e.toString());
} catch (CosXmlServiceException e) {
//抛出异常
Log.w("TEST","CosXmlServiceException =" + e.toString());
}
下载文件
String bucket = "存储桶名称"; // cos v5 的 bucket格式为:xxx-appid, 如 test-1253960454
String cosPath = "远端路径,即存储到 COS 上的绝对路径";
String savePath = "下载到本地的路径";
GetObjectRequest getObjectRequest = GetObjectRequest(bucket, cosPath, savePath);
getObjectRequest.setSign(signDuration,null,null);
/*设置进度显示
实现 CosXmlProgressListener.onProgress(long progress, long max)方法,
progress 已上传的大小, max 表示文件的总大小
*/
getObjectRequest.setProgressListener(new CosXmlProgressListener() {
@Override
public void onProgress(long progress, long max) {
float result = (float) (progress * 100.0/max);
Log.w("TEST","progress =" + (long)result + "%");
}
});
//使用同步方法下载
try {
GetObjectResult getObjectResult =cosXmlService.getObject(getObjectRequest);
Log.w("TEST","success: " + getObjectResult.xCOSStorageClass);
} catch (CosXmlClientException e) {
Log.w("TEST","CosXmlClientException =" + e.toString());
} catch (CosXmlServiceException e) {
Log.w("TEST","CosXmlServiceException =" + e.toString());
}
//**使用异步回调请求**
/**
cosXmlService.getObjectAsync(getObjectRequest, new CosXmlResultListener() {
@Override
public void onSuccess(CosXmlRequest cosXmlRequest, CosXmlResult cosXmlResult) {
Log.w("TEST","success");
}
@Override
public void onFail(CosXmlRequest cosXmlRequest, CosXmlClientException clientException, CosXmlServiceException serviceException) {
String errorMsg = clientException != null ? clientException.toString() : serviceException.toString();
Log.w("TEST",errorMsg);
}
});
*/
生成签名
若需要了解签名具体的生成过程请参照 请求签名。 在使用 SDK 时,SDK 中已提供了签名获取类,只需要继承 BasicLifecycleCredentialProvider 类,并重写 fetchNewCredentials() 方法,从而获取 SecretId,SecretKey, SecretKey Duration;若是使用临时密钥发送请求,则需要获取tempSecretKey, tempSecrekId, sessionToken, expiredTime,关于如何通过CAM获取临时密钥,请参考快速搭建移动应用传输服务。
示例
/**
方法一:使用永久密钥进行签名
*/
public class LocalCredentialProvider extends BasicLifecycleCredentialProvider{
private String secretKey;
private long keyDuration;
private String secretId;
public LocalCredentialProvider(String secretId, String secretKey, long keyDuration) {
this.secretId = secretId;
this.secretKey = secretKey;
this.keyDuration = keyDuration;
}
/**
返回 BasicQCloudCredentials
*/
@Override
public QCloudLifecycleCredentials fetchNewCredentials() throws CosXmlClientException {
long current = System.currentTimeMillis() / 1000L;
long expired = current + duration;
String keyTime = current+";"+expired;
return new BasicQCloudCredentials(secretId, secretKeyToSignKey(secretKey, keyTime), keyTime);
}
private String secretKeyToSignKey(String secretKey, String keyTime) {
String signKey = null;
try {
if (secretKey == null) {
throw new IllegalArgumentException("secretKey is null");
}
if (keyTime == null) {
throw new IllegalArgumentException("qKeyTime is null");
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
try {
byte[] byteKey = secretKey.getBytes("utf-8");
SecretKey hmacKey = new SecretKeySpec(byteKey, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(hmacKey);
signKey = StringUtils.toHexString(mac.doFinal(keyTime.getBytes("utf-8")));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return signKey;
}
}
/**
方法二:使用临时密钥进行签名(推荐使用这种方法),此处假设已获取了临时密钥 tempSecretKey, tempSecrekId,
sessionToken, expiredTime.
*/
public class LocalSessionCredentialProvider extends BasicLifecycleCredentialProvider{
private String tempSecretId;
private String tempSecretKey;
private String sessionToken;
private long expiredTime;
public LocalCredentialProvider(String tempSecretId, String tempSecretKey, String sessionToken, long expiredTime) {
this.tempSecretId = tempSecretId;
this.tempSecretKey = tempSecretKey;
this.sessionToken = sessionToken;
this.expiredTime = keyDuration;
}
/**
返回 SessionQCloudCredential
*/
@Override
public QCloudLifecycleCredentials fetchNewCredentials() throws CosXmlClientException {
return new SessionQCloudCredentials(tmpSecretId, tmpSecretKey, sessionToken, expiredTime);
}
}