1.集成android 开发环境
implementation 'com.amazonaws:aws-android-sdk-s3:2.17.1'
目前这个版本是最新的
2.s3 服务端的相关数据,注册时都会给到.有两种方式使用S3,一种是直接使用是直接使用s3的服务,一种就是像我们这样,直接部署的.
private String accessKeyId; 注册后就会有
private String secretAccessKey; 注册后就会有
private String sessionToken; //token 这个可有可无,但是无门是不许要的,否则会权限拒绝错误
private String bucket; //桶 这个就是具体的数据存放地,是一个虚拟的地址
private String endpoint; //服务器地址
private String uploadPath;
private String expiration;
这是我们服务端给到的数据.
3.代码集成 这个比较坑,找了很久,没有找到相关具体的api 文档,从网上也没有找到好的文章,只找到了几个关键类,所以我基本上把相关的源码都看了一遍,折腾了好久才搞好,本质代码不多.
1.创建s3 客户端
private AWSCredentials getS3Credentials() {
AWSCredentials sessionCredentials = new BasicSessionCredentials (
relayUploadBean.getAccessKeyId (),
relayUploadBean.getSecretAccessKey (),
relayUploadBean.getSessionToken ());
return sessionCredentials;
}
这里也可以是两个函数创建的AWSCredentials ,根据也许来,有token 的原因是建立失效机制,
public AmazonS3 getS3Cline() {
if (amazonS3Cline == null) {
amazonS3Cline = new AmazonS3Client (new MYAWSCredentialsProvider (), new ClientConfiguration ());
amazonS3Cline.setEndpoint ("https://" + relayUploadBean.getEndpoint ());
}
Log.d (TAG, "getS3Cline: " + relayUploadBean.toString ());
return amazonS3Cline;
}
创建 TransferUtility 类,这个类是关键,他自动帮我们实现了上传的分片机制,建议看下源码,
public TransferUtility getTransferUtility() {
TransferUtility sTransferUtility = null;
try {
sTransferUtility = TransferUtility.builder ()
.s3Client (getS3Cline ())
.context (BaseApplication.mContext)
.build ();
} catch (Exception e) {
e.printStackTrace ();
}
return sTransferUtility;
}
然后就是开始上传了,我用的是这个方法
public TransferObserver upload(String bucket, String key, File file) {
return upload(bucket, key, file, new ObjectMetadata());
}
三个参数因该比较好理解,bucket 是桶名,但是我们自建的是比较怪的,用的是路径,但是无所谓,只要最后s3 帮我们拼的全路径是我们服务器的地址就好,key :一般用文件名 ,然后传入一个file 就可以了.
TransferObserver 是返回的一个类,通过他我们可以监听文件的上传进度
transferObserver.setTransferListener (transferListener);
public interface TransferListener {
/**
* Called when the state of the transfer is changed.
*
* @param id The id of the transfer record.
* @param state The new state of the transfer.
*/
public void onStateChanged(int id, TransferState state);
/**
* Called when more bytes are transferred.
*
* @param id The id of the transfer record.
* @param bytesCurrent Bytes transferred currently.
* @param bytesTotal The total bytes to be transferred.
*/
public void onProgressChanged(int id, long bytesCurrent, long bytesTotal);
/**
* Called when an exception happens.
*
* @param id The id of the transfer record.
* @param ex An exception object.
*/
public void onError(int id, Exception ex);
}
这里返回的id 是整个资源的唯一标示,建议存到数据库中,后边会用到.
TransferState 返回了当前资源的状态,是一个枚举类.
long bytesCurrent, long bytesTotal 分别代表上传大小和源文件大小
int progress = (int) (((double) bytesCurrent / (double) bytesTotal) * 100);
这样就拿到了当前就进度, 直接。 progress % 就可以了.
关于暂停.开始与状态检查
TransferObserver transferObserver = sTransferUtility.getTransferById (resId);
这里的resId 就是我上边说的id,s3 本身实现了一套数据库他保存了对应id 的信息,包括上传进度,状态等等.
当app 暴力推出或者暂停时都可以使用它来判断.
if (transferObserver != null) {
TransferState transferState = transferObserver.getState ();
Log.d (TAG, "upload: 获取历史记录" + transferState.name ());
if (transferState.equals (TransferState.FAILED)) {
Log.d (TAG, "upload: 失败了,重新开始");
transferObserver = sTransferUtility.upload (finalPath, file.getName (), file);
} else if (transferState.equals (TransferState.IN_PROGRESS)) {
if (sTransferUtility.pause (resId)) {
Log.d (TAG, "upload: 进行中 暂停后重新开始");
transferObserver = sTransferUtility.resume (resId);
}
} else if (transferState.equals (TransferState.COMPLETED)) {
Log.d (TAG, "upload: 已经完成了" + resId);
transferListener.onStateChanged (resId,transferState);
} else {
transferObserver = sTransferUtility.resume (resId);
Log.d (TAG, String.format ("upload: 正在上传中无需重复 恢复: total: %d, current: %d",
transferObserver.getBytesTransferred (), transferObserver.getBytesTotal ()));
}
就这么多.
主要就三个方法
resume(int id) 恢复开始
pause (int id) 暂停
upload(String bucket, String key, File file)。 开始上传