LoginSignup
0
1

【Androidアプリ開発】S3に格納した画像のPre-Signed URLを発行し、kotlinで表示する

Last updated at Posted at 2022-12-23

やりたいこと

S3においた画像イメージをLambda経由で取得しkotlinで表示する。

問題

元々はS3に格納した画像をLambdaで呼び出し、ByteArray形式に変換してクライアント端末に渡していたのですが、Lambdaにはレスポンス6MBの制限があり、大量の画像データを扱えなくなりました。

解決方法

S3のPre-Signed URLを使います。
Pre-Sined URLを使うと、S3オブジェクトへの限定的なアクセスを提供することが可能で、URLを渡すため、ByteArrayを渡すより格段に容量を減らせます。

実装例

S3

TESTバケットにsample.jpgを格納

Lambda

  • 環境:AWS Lambda Python 3.9

  • アタッチするポリシー:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::sample-s3-presignedurl/*"
        }
    ]
}
  • Lambda関数
# -- coding: utf-8 --
import json
import json
import boto3
import base64
from boto3.dynamodb.conditions import Key	#Keyオブジェクトを利用できるようにする


S3_BUCKET_NAME = 'TEST'
S3_OBJECT_KEY = 'sample.jpg'

s3 = boto3.client('s3')

def lambda_handler(event, context):
    # TODO implement
    url = s3.generate_presigned_url(
        'get_object',
        Params={
            'Bucket': S3_BUCKET_NAME,
            'Key': S3_OBJECT_KEY
        },
        ExpiresIn=3600
    )
    return {
        'statusCode': 200,
        'body': url
    }

kotlin

  • 本題ではないので、API Gatewayやcoroutine使ってhttps通信するとことろは省きます。
  • 頑張ってLambdaの戻り値を取得した前提です
  • GlideというURL画像を取得するライブラリを使います。

Glideの初期設定
「build.gradle」のdependenciesに下記のコードを追加します

implementation 'com.github.bumptech.glide:glide:4.10.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'

レイアウトの作成
ImageViewを作成

activity_glide.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".GlideActivity"
    android:gravity="center">
 
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:id="@+id/glideTest"
        android:layout_weight="1" />
 
</LinearLayout>

Glideで画像をロード

GlideUrl を継承したクラスを用意し、getCacheKeyメソッドをオーバーライドします

GlideActivity.kt
import com.bumptech.glide.load.model.GlideUrl

class GlideNoTokenUrl(private val url: String) : GlideUrl(url) {
  override fun getCacheKey(): String {
    // Domain(バケット名含む) + Path で判定する
    return url.substringBefore("?")
  }
}

Activity内でGlideで画像をロードしてImageViewに格納します

GlideActivity.kt
package com.example.hoge
 
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView
import com.bumptech.glide.Glide
 
class GlideActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_glide)

        val glideTest = findViewById<ImageView>(R.id.glideTest)  //イメージビュー

        // API Gateway+Lambdaで画像のPre-Signed URLを取得
        imageURL = getImageURL() // ここでHTTP通信などして画像URLを取得してください

        //GlideでImageViewに設定
        Glide.with(context)
             .load(GlideNoTokenUrl(url))  // ロードしたいイメージのURLを入力
             .placeholder(R.drawable.dreamhanks) //イメージをロード中に見せるイメージ設定
             .into(glideTest)  // セットしたいImageViewを入力
        }
    }
}

Glideの主要メソッド

  • 「with」:ContextやActivityについて設定
  • 「load」:実際にロードしたいイメージのURLを設定
  • 「placeholder」:イメージをロード中に見せるイメージを設定(なくてもいい)
  • 「into」:イメージを適用する「ImageView」を設定

以上

参考にさせていただいた素晴らしいサイト様

旅行アプリ、Tig Travelをリリースしました

おすすめの旅行プランを多数掲載。旅行プランをカスタマイズし、自分だけのプランを簡単に作成できます!

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1