[Alibaba Cloud] Android端末からOSSへアクセスする

#目的
Android端末からAlibaba CloudのOSS(S3)へファイルのアップロード、ダウンロードをする。

#開発環境
Android 7.0
Windows 10
Alibaba Cloud

#Alibaba構成
[Alibabaのドキュメント](https://jp.alibabacloud.com/help/doc-detail/31922.htm?spm=a21mg.p38356.b99.77.f3c47903M1yFuU)通りに構成していきます。
今回はApp Server(アプリケーションサーバー)に関してはECSを使用せず、
・ApiGateway
・Function Compute
を用いて 図の

>1.Request STS credentials
>2.Request AsuumeRole
>3.Return STS Credentials
>4.Return STS Credentials

を実装していきます。
![1424_en-US.png](https://qiita-image-store.s3.amazonaws.com/0/143249/c70873a3-24f0-a5a5-2d82-5c14a6387db2.png)

#設定
##OSSの設定
Alibabaドキュメント 
[OSSデモの紹介]
(https://jp.alibabacloud.com/help/doc-detail/31941.htm?spm=a21mg.p38356.b99.100.33ed6d34ruoWh3)
を参照して

1.OSSにてバケットの作成
2.STSの有効化 
     *AccessKeyID
     *AccessKeySecret
     *RoleArm
の保存することを忘れないこと

##Fuction Computeの設定
1.関数を作成

```python:test.py
#!/usr/bin/env python
#coding=utf-8
from aliyunsdkcore import client
from aliyunsdksts.request.v20150401 import AssumeRoleRequest
import json

def getSts(event, context):
  AccessKeyID = "Your AccessKey"
  AccessKeySecret = "Your SecretAccessKey"
  roleArn = "Your RoleArn"
  clt = client.AcsClient(AccessKeyID,AccessKeySecret,'ap-northeast-1')
  request = AssumeRoleRequest.AssumeRoleRequest()
  request.set_RoleArn(roleArn)
  request.set_RoleSessionName('external-username')
  try:
    response = clt.do_action_with_exception(request)
    text = json.loads(response)
    stsDict = {}
    stsDict["StatusCode"] = "200"
    stsDict["body"] = {}
    stsDict["body"] = text["Credentials"]
    stsDict["body"]["StatusCode"] = stsDict["StatusCode"]
  except Exception as e:
    errorDict = dict().fromkeys(['StatusCode','ErrorCode','ErrorMessage'])
    errorDict["StatusCode"] = "500"
    errorDict["ErrorMessage"] = e.message
    errorDict["ErrorCode"] = e.error_code
    stsText = json.dumps(errorDict)
  return stsDict
  pass
```

ここでなぜか、出力するJSONはbodyの中に記述しなければ
AndroidのSDKでは値を取得できなかったので注意が必要。
（なぜ、jsonでbody宣言が必要なのかがいまいち理解できてないです）

##ApiGatewayの設定
###基本リクエスト
Path: 任意
プロトコル: HTTP
HTTP Method : GET
リクエストモード :　リクエストパラメータをマッピング

###バックエンドサービス情報
バックエンドサービスタイプ: FunctionCompute
リージョン: FunctionComputeが設定されているリージョン
サービス名：FunctionComputeで設定したサービス名
関数名：FunctionComputeで設定した関数名
Role Arn: STSを有効化した時に保存したRoleArn

###返されるレスポンス
返されるタイプ：JSON (application/json; charset=utf-8)

#Android側設定
Alibabaドキュメント 
[OSSデモの紹介]
(https://jp.alibabacloud.com/help/doc-detail/31941.htm?spm=a21mg.p38356.b99.100.33ed6d34ruoWh3)
のAndroidソースコードを参考にさせてもらいました。

buttonをLayoutに一つだけ追加してします。

```Kotlin:MainActiviy.kt
class MainActivity : AppCompatActivity() {

    val endPoint = "OSS のエンドポイント"
    val stsServer = "API のエンドポイント"

    fun getOSSCredentialProvider() : OSSCredentialProvider {
        return OSSAuthCredentialsProvider(stsServer)
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button.setOnClickListener {
            val oss = getOSSClient(getOSSCredentialProvider())

            val get = GetObjectRequest("OSSのバケット名", "取得したいファイル名")
            oss.asyncGetObject(get, object : OSSCompletedCallback<GetObjectRequest, GetObjectResult>{
                override fun onSuccess(request: GetObjectRequest?, result: GetObjectResult?) {
                    Log.d("MainActivity", "success")
                }

                override fun onFailure(
                    request: GetObjectRequest?,
                    clientException: ClientException?,
                    serviceException: ServiceException?
                ) {
                    Log.d("MainActivity", "end")
                }
            })
        }
    }
}
```

※API Gatewayのエンドポイントはサブドメインにパスを追加
![API GATEWAY ENDPOINT.png](https://qiita-image-store.s3.amazonaws.com/0/143249/39be17a7-52b7-4010-c8be-ec4f8ed35a7c.png)

※S3のエンドポイント
![S3 ENDPOINT.png](https://qiita-image-store.s3.amazonaws.com/0/143249/26ad41db-4d63-6b9b-a5a8-7fb47399a0de.png)

Logcatで
>2018-12-14 18:08:25.755 2652-3947/net.zaisan.alibabaosssamle D/MainActivity: success

きちんと取得できてることを確認できた☆
PUTしたりDeleteしたりすることができる環境のベースができたので、
これを応用していきたい。

#まとめ
API GatewayとComputeFunctionを使うことでSTS認証にてOSSをコントロールすることができた。
ECSを使わないことで、サーバーレスにて簡単に構築できるのはよいと思う。