【Android】S3からzipをダウンロードして解凍・保存する

# やりたいこと
s3にあげているzipをダウンロードしてきて、アプリ内の任意の場所に保存する。
よくあるソシャゲの最初のアセットダウンロードみたいなことをしたい。

## 環境

クライアント
・Android Studio v3.*

サーバ
・AWS

ライブラリ（アリシャス！！）
・AWSClient & AWS Cognito
・ZipUtil（zip解凍）
https://github.com/zeroturnaround/zt-zip


## 実装

### アセット一覧を取得
アセットListは、DBに登録していて、それをphpで取得している。

### S3に接続にアクセスして、ファイルを取得する

##### クライアントを生成して、指定ファイルをダウンロードしてくるメソッド

S3クライアントを生成
↓
指定ファイルのインプットストリームを生成する

```
    // マルチパートアップロード最少サイズ
    private static final String ENDPOINT = "s3-ap-northeast-1.amazonaws.com";
    private static final String BUCKET_NAME = "hogehoge";

    /**
     * S3から対象のファイルを取得する
     *
     * @param bucketName 対象のバケット
     * @param objectKey  対象のファイル
     * @return object
     */
    public InputStream getObjectContent(String bucketName, String objectKey) {
        // AmazonS3Clientインスタンスを作成
        AmazonS3Client cli = makeS3Client();

        // エンドポイントを設定
        cli.setEndpoint(ENDPOINT);

        // rootDirectory(Bucket名), objectKey(オブジェクトまでの相対パス)からリクエストを作成
        GetObjectRequest request = new GetObjectRequest(bucketName, objectKey);

        S3Object object = cli.getObject(request);

        // Objectを開いたInputStreamを返す
        return object.getObjectContent();
    }
```

##### S3クライアント生成

S3クライアントインスタンスを生成する。
S3への接続には "Amazon Cognito"を使用してIDをもらう（直にkey、passを書くのは🙅）。

```
/**
     * S3接続クライアントを作成
     *
     * @return クライアント
     */
    private AmazonS3Client makeS3Client() {

        CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
                getApplicationContext(),
                "*******************", // ID プールの ID
                Regions.AP_NORTHEAST_1 // リージョン
        );

        // ConfigurationでTimeout時間を30秒に設定
        ClientConfiguration clientConfiguration = new ClientConfiguration();
        clientConfiguration.setConnectionTimeout(30000);

        // AmazonS3Clientをインスタンス化
        return new AmazonS3Client(credentialsProvider, clientConfiguration);
    }
```

### アセットをダウンロードし、解凍・ファイルを任意の場所に移動する

```
protected void assetDownload(String filename, String fileByte) {
        new AsyncTask<String, Integer, String>() {
            @Override
            protected void onPreExecute() {
                //ダイアログを表示させるなどのUIの準備
            }

            @Override
            protected String doInBackground(String... params) {
                String filename = params[0];
                String fileByte = params[1];
                InputStream is;
                FileOutputStream fos;

                try {
                    is = getObjectContent(BUCKET_NAME, filename);
                    String outPutFile = mContext.getFilesDir().getPath() + "/" + filename;
                    fos = new FileOutputStream(outPutFile);

                    byte[] buffer = new byte[1024 * 1024];
                    int readSize = -1;
                    int total_download = 0;
                    BigDecimal fileByteDecimal = new BigDecimal(fileByte);
                    while ((readSize = is.read(buffer, 0, buffer.length)) != -1) {
                        fos.write(buffer, 0, readSize);
                        total_download += readSize; // 合計ダウンロード完了byte
                        BigDecimal totalByteDecimal = new BigDecimal(total_download + "");
                        double wariai1 = totalByteDecimal.divide(fileByteDecimal, 3, BigDecimal.ROUND_HALF_UP).doubleValue();
                        BigDecimal a = new BigDecimal(wariai1);
                        BigDecimal b = new BigDecimal("100");
                        int wariai = a.multiply(b).intValue();
                        publishProgress(wariai);
                    }
                    fos.flush();
                    if (is != null) {
                        is.close();
                    }
                    if (fos != null) {
                        fos.close();
                    }

                    // Downloadしたzipを解凍する
                    File zipFile = new File(outPutFile); // unzipする対象のFile
                    File outputFile = new File(mContext.getFilesDir().getPath()); // 出力先のFile
                    ZipUtil.unpack(zipFile, outputFile);

                    // 中身のファイルをfilesに移動する
                    String DirName = filename.replace(".zip", "");
                    File outputDir = new File(mContext.getFilesDir().getPath() + "/" + DirName);
                    File[] files = outputDir.listFiles(); // ディレクトリの中身一覧
                    for (File file : files) {
                        if (file.isDirectory()) {
                            file.delete();
                        }
                        if (file.isFile()) {
                            // 移動
                            File moveFile = new File(mContext.getFilesDir().getPath() + "/" + file.getName()); // 出力先のFile
                            file.renameTo(moveFile);
                        }
                    }

                    // もとのZIP削除
                    zipFile.delete();
                } catch (IOException ex) {
                    Logger.log(ex.getMessage());
                } finally {
                }

                return "1";
            }

            @Override
            protected void onProgressUpdate(Integer... values) {
                super.onProgressUpdate(values);
                // ダウンロード進捗を表示。etc...
            }

            @Override
            protected void onPostExecute(String result) {
                // ファイルダウンロード完了
            }
        }.execute(filename, fileByte);
    }
```