サイトアイコン PEOPLE Engineering Blog

BaaS@rakuza SDK for Androidを使ってみた

BaaS@rakuza

皆さん、こんにちは。入社二年目のにいだです。
業務で「BaaS@rakuza SDK」を使っていて、個人的にもっと使ってみたいと思いAndroid開発用の
「BaaS@rakuza SDK for Android」を使用して簡単なアプリを作ってみました。

作成したアプリ

作成したアプリは、ユーザー情報の登録/編集ができるアプリです。
初回アプリ起動時に自動でユーザ登録を行い、
ユーザ情報を入力して、更新ボタンタップでアカウント情報を更新できます。
実際に作成したアプリは次のものが完成しました。

管理画面でユーザを確認してみるとユーザNo APP00084としてユーザ情報が登録されていました。

必要な準備物(リソース)

BaaS@rakuzaを利用するためには利用申し込みが必要です。
公式サイトから利用申し込みします。(60日無料)
※「無料体験版申し込み・お問合せ」から
2~3日ほどでテナントキーなどのアカウント情報がメールに送信されます。

プロジェクトの作成

開発環境
IDE:AndroidStdio Arctic Fox 2020.3.1
OS:Windows 10

空のアクティビティーを選択します。

そのままだと私の環境ではビルドに失敗したため
implementation 'com.google.android.material:material
のバージョンを次のように1.6.1に下げました。参考

// build.gradle
dependencies {

    ・・・
    implementation 'com.google.android.material:material:1.6.1'
    ・・・
}

SDKのインストール

最新のSDKをGitHubから取得します。リリース一覧にアクセスして最新(ブログ執筆当時はv3.1.0)のバージョンをダウンロードしてください。
SDKを利用する手順はガイドを参考にして下さい。

登録するユーザー情報の項目

今回登録する項目はユーザ名、年代、性別としました。
ユーザ情報の項目は管理画面のユーザ項目設定から編集できます。

ユーザー情報の登録/編集

ユーザ編集画面を作成します。
初回アプリ起動時に自動で空のユーザを登録し(registUser()メソッド)、更新ボタンをタップ時にユーザ情報の編集(editUser()メソッド)を行います。
画面のファイル(main_activity.xml)には以下を記載しました。

<!-- main_activity.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">
        <TextView
            android:id="@+id/textView_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:textSize="30sp"
            android:text="プロフィール設定"
            android:gravity="center_horizontal"
            android:background="@color/teal_200"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_marginTop="0dp"
            />
        <TextView
            android:id="@+id/textView_message"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@color/teal_200"
            android:textSize="20sp"
            android:text="ユーザ情報を更新しました"
            android:gravity="center_horizontal"
            app:layout_constraintLeft_toLeftOf="@+id/textView_title"
            app:layout_constraintTop_toBottomOf="@+id/textView_title"
            android:layout_marginTop="30dp"
            android:layout_marginHorizontal="20dp"
            android:visibility="invisible"
            />

        <TextView
            android:id="@+id/textView_userName"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:textSize="20sp"
            android:text="ユーザ名"
            app:layout_constraintLeft_toLeftOf="@+id/textView_message"
            app:layout_constraintTop_toBottomOf="@id/textView_message"
            android:layout_marginTop="10dp"/>

        <EditText
            android:id="@+id/editText_userName"
            android:background="#D5DADA"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:layout_marginTop="10dp"
            app:layout_constraintStart_toStartOf="@+id/textView_userName"
            app:layout_constraintTop_toBottomOf="@+id/textView_userName"
            />
        <TextView
            android:id="@+id/textView_age"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:textSize="20sp"
            android:text="年齢"
            app:layout_constraintLeft_toLeftOf="@+id/editText_userName"
            app:layout_constraintTop_toBottomOf="@id/editText_userName"
            android:layout_marginTop="10dp"/>

        <Spinner
            android:id="@+id/spinner_age"
            android:background="#D5DADA"
            android:layout_width="200dp"
            android:layout_height="40dp"
            android:layout_marginTop="10dp"
            app:layout_constraintStart_toStartOf="@+id/textView_age"
            app:layout_constraintTop_toBottomOf="@+id/textView_age"
            />
        <TextView
            android:id="@+id/textView_sex"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:textSize="20sp"
            android:text="性別"
            app:layout_constraintLeft_toLeftOf="@+id/spinner_age"
            app:layout_constraintTop_toBottomOf="@+id/spinner_age"
            android:layout_marginTop="10dp"
            />
        <RadioGroup
            android:id="@+id/radioGroup_sex"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toLeftOf="@+id/textView_sex"
            app:layout_constraintTop_toBottomOf="@+id/textView_sex"
            android:layout_marginTop="0dp"
            />
        <Button
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:text="更新"
            android:onClick="clickRegistButton"
            app:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginHorizontal="20dp"
            android:layout_marginBottom="50dp"
            />
</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.ktに以下を追加

// MainActivity.kt
package com.example.samplerakuzaproject

import android.content.ContentValues.TAG
import android.content.Context
import android.content.SharedPreferences
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.ArrayAdapter
import android.widget.RadioButton
import com.example.samplerakuzaproject.databinding.ActivityMainBinding
import jp.co.pscsrv.android.baasatrakuza.client.RKZClient
import jp.co.pscsrv.android.baasatrakuza.model.User

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    private val ageItemsCode = arrayListOf<String?>(null)
    val sexItemsCode = arrayListOf<String?>(null)
    private val PROFILE_UPDATE_SUCCESS_MESSAGE = "登録情報を更新しました。"
    private val PROFILE_UPDATE_FILIED_MESSAGE = "登録情報の更新に失敗しました。"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        RKZClient.getInstance().initialize(
            this,"<配布したテナントキー>"
        ) { isSuccess, rkzResponseStatus ->
            // 初期化に成功した場合
            if (isSuccess) {
                // client変数を用いてSDKの機能を使用できます。
                Log.d(TAG, "RKZClientクラスの初期化に成功しました。")
                setAgeSpinner()
                setSexRadioButton()
                // "Data"という名前でインスタンスを生成
                val data: SharedPreferences = getSharedPreferences("Data", Context.MODE_PRIVATE)
                val userAccessToken = data.getString("USER_ACEESS_TOKEN", null)
                // アプリ初回起動時のみユーザ登録実行
                if (userAccessToken == null) {
                   registUser()// ユーザ登録
               }else {
                   getUser()// ユーザ取得
                }
            }
        }
    }
    fun registUser() {
        val user = User()
        RKZClient.getInstance().registUser(user) { newUser, rkzResponseStatus ->
            if (rkzResponseStatus.isSuccess) {
                // 成功時
                Log.d(TAG, "success-rakuza-registUser")
                Log.d(TAG, "userNo: ${newUser.userNo}") // ユーザーを一意に識別する顧客番号
                Log.d(TAG, "userAccessToken: ${newUser.userAccessToken}") // ユーザーアクセストークン
                // ユーザアクセストークンを保存
                val data: SharedPreferences = getSharedPreferences("Data", Context.MODE_PRIVATE)
                val editor = data.edit()
                editor.putString("USER_ACEESS_TOKEN", newUser.userAccessToken)
                editor.commit();
            } else {
                // 失敗
                Log.e(TAG, "statusCode: ${rkzResponseStatus.statusCode}")
                Log.e(TAG, "message: ${rkzResponseStatus.message}")
            }
        }
    }
    fun showUser(user:User) {
        // ユーザオブジェクトにユーザ名を設定
        binding.editTextUserName.setText(user.userName)
        // ユーザオブジェクトから性別を取得
        if(user.sexCd != null) user.sexCd.toIntOrNull()?.let { binding.radioGroupSex.check(it) }
        //binding.radioGroupSex.check()
        // ユーザオブジェクトに年齢を設定
        if(user.ageConfig != null) user.ageConfig.toIntOrNull()?.let { binding.spinnerAge.setSelection(it - 1) }
    }
    // ユーザ情報取得
    fun getUser() {
        val data: SharedPreferences = getSharedPreferences("Data", Context.MODE_PRIVATE)
        val userAccessToken = data.getString("USER_ACEESS_TOKEN", null)
        RKZClient.getInstance().getUser(userAccessToken) { user, rkzResponseStatus ->
            if (rkzResponseStatus.isSuccess) {
                // 成功時
                Log.d(TAG, "success-rakuza-getUser")
                Log.d(TAG, "userNo: ${user.userNo}") // ユーザーを一意に識別する顧客番号
                Log.d(TAG, "userAccessToken: ${user.userAccessToken}") // ユーザーアクセストークン
                showUser(user)
            } else {
                // 失敗
                Log.e(TAG, "statusCode: ${rkzResponseStatus.statusCode}")
                Log.e(TAG, "message: ${rkzResponseStatus.message}")
            }
        }
    }

    // ユーザ情報の更新処理更新
    fun editUser(user:User) {
        binding.textViewMessage.visibility = View.INVISIBLE//登録処理のレスポンスメッセージを非表示する
         RKZClient.getInstance().editUser(user) { newUser, rkzResponseStatus ->
            if (rkzResponseStatus.isSuccess) {
                // 成功時
                Log.d(TAG, "success-rakuza-editUser")
                Log.d(TAG, "userNo: ${newUser.userNo}") // ユーザーを一意に識別する顧客番号
                Log.d(TAG, "userAccessToken: ${newUser.userAccessToken}") // ユーザーアクセストークン

                // 登録処理のレスポンスメッセージを表示する
                binding.textViewMessage.text = PROFILE_UPDATE_SUCCESS_MESSAGE
                binding.textViewMessage.visibility = View.VISIBLE
            } else {
                // 失敗
                Log.e(TAG, "statusCode: ${rkzResponseStatus.statusCode}")
                Log.e(TAG, "message: ${rkzResponseStatus.message}")
                binding.textViewMessage.text = PROFILE_UPDATE_FILIED_MESSAGE
                binding.textViewMessage.visibility = View.VISIBLE
            }
        }
    }

    // 年齢のスピナーをセットする
    fun setAgeSpinner() {
        // 年齢オブジェクト取得
        val objectId = "age_constitution"
        val treeCount = 1 // 1階層分取得します(階層を指定しない場合、標準で3階層取得します)

        RKZClient.getInstance().getDataListWithRelationObjects(objectId, treeCount, null, null) { dataList, rkzResponseStatus ->
            if (rkzResponseStatus.isSuccess) {
                // 成功時
                Log.d(TAG, "success-rakuza-getDataListWithRelationObjects:age_constitution")
                val spinnerAgeItems = arrayListOf<String>("")
                dataList.forEach {
                    Log.d(TAG, "code: ${it.code}")
                    Log.d(TAG, "name: ${it.name}")
                    spinnerAgeItems.add(it.name) // 表示する選択肢のリスト
                    ageItemsCode.add(it.code) // 取得した年齢のコードを配列に保存
                }
                //年齢のSpinner設定
                val ageAdapter = ArrayAdapter(
                    applicationContext,
                    android.R.layout.simple_spinner_item, spinnerAgeItems
                )
                ageAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
                binding.spinnerAge.adapter = ageAdapter
            } else {
                // 失敗
                Log.e(TAG, "statusCode: ${rkzResponseStatus.statusCode}")
                Log.e(TAG, "message: ${rkzResponseStatus.message}")
            }
        }
    }

    // 性別のラジオボタンをセットする
    fun setSexRadioButton() {
    // 性別オブジェクト取得
        val objectId = "sex"
        val treeCount = 1 // 1階層分取得します(階層を指定しない場合、標準で3階層取得します)

        RKZClient.getInstance().getDataListWithRelationObjects(objectId, treeCount, null, null) { dataList, rkzResponseStatus ->
            if (rkzResponseStatus.isSuccess) {
                // 成功時
                Log.d(TAG, "success-rakuza-getDataListWithRelationObjects:sex")
                val radioGroup = binding.radioGroupSex // RadioGroupの取得
                dataList.forEach {
                    Log.d(TAG, "code: ${it.code}")
                    Log.d(TAG, "name: ${it.name}")
                    sexItemsCode.add(it.code)// 取得した性別のコードを配列に保存
                    val radioButton = RadioButton(this) // RadioButton生成
                    radioButton.text = it.name
                    radioGroup.addView(radioButton)// ラジオボタンを画面に追加
                }
            } else {
                // 失敗
                Log.e(TAG, "statusCode: ${rkzResponseStatus.statusCode}")
                Log.e(TAG, "message: ${rkzResponseStatus.message}")
            }
        }
    }

    // 更新ボタンクリック処理
    fun clickRegistButton(view: View){
        Log.d(TAG, "start-clickRegistButton")
        // 画面の入力情報からユーザオブジェクトを作成する
        val user = User()
        val data = getSharedPreferences("Data", Context.MODE_PRIVATE)
        user.userAccessToken = data.getString("USER_ACEESS_TOKEN", null) // ユーザオブジェクトにユーザアクセストークンを設定
        user.userName = binding.editTextUserName.text.toString() // ユーザオブジェクトにユーザ名を設定
        if(binding.radioGroupSex.checkedRadioButtonId != -1) {// 性別が選択されている場合
            user.sexCd = sexItemsCode[binding.radioGroupSex.checkedRadioButtonId] // ユーザオブジェクトに性別を設定
        }
        user.ageConfig = ageItemsCode[binding.spinnerAge.selectedItemPosition] // ユーザオブジェクトに年齢を設定

        editUser(user) // ユーザ情報更新
    }
}

工夫した点

アプリ初回起動時のみユーザ登録 以降の起動時は登録したユーザの情報を画面に初期表示する

アプリ初回起動時のユーザ登録成功時に取得できるユーザアクセストークンを、SharedPreferencesクラスを使用してアプリ内のデータとして永続保存し、
以降は起動時にユーザアクセストークンの有無でユーザ登録をするか、またはユーザ情報を取得して表示するかを切り分けました。

// MainActivity.kt
・・・
val data: SharedPreferences = getSharedPreferences("Data", Context.MODE_PRIVATE)
                val userAccessToken = data.getString("USER_ACEESS_TOKEN", null)
                // アプリ初回起動時のみユーザ登録実行
                if (userAccessToken == null) {
                   registUser()// ユーザ登録
               }else {
                   getUser()// ユーザ取得
                }
・・・

まとめ

BaaS@rakuzaを使用した業務経験は浅いですが、2,3時間くらいで簡単にアプリを作ることができました。
このようにBaaS@rakuzaを使うと速く簡単にアプリ作成ができるのででの開発に興味を持ってもらえると嬉しいです。
今後も何かしらの技術的なブログを書いてみようと思います!お楽しみに!

モバイルバージョンを終了