AndroidとDynamoDB実装方法 (4/4) - コーディング -
AWSのNoSQLデータベースDynamoDBをDBとしてデータ操作を行うための基本的な設定のご紹介です。
AndroidとDynamoDB実装方法 (3/4) - DynamoDB初期設定 -に続き、プログラミングになります。
MainActivity.javaと、DynamoDBのテーブルクラスを定義したBooks.javaの2ファイルからの構成となるプログラミングを行います。
[目次]
コード
Books.java
package com.example.sample.dynamodb_sample; import com.amazonaws.auth.CognitoCachingCredentialsProvider; import com.amazonaws.regions.Regions; import com.amazonaws.services.dynamodbv2.*; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.*; /* Dynammoテーブル名*/ @DynamoDBTable(tableName = "Books") public class Books { private String author; private String title; private int price; private String releasedate; /* パーティションキーで指定した属性名 */ @DynamoDBHashKey(attributeName = "Author") public String getAuthor() {return author; } public void setAuthor(String author) { this.author = author; } /* ソートキーで指定した属性名 */ @DynamoDBRangeKey(attributeName = "Title") public String getTitle() {return title; } public void setTitle(String title) { this.title = title; } /* 任意の属性名 AWSコンソールで事前定義不要*/ @DynamoDBAttribute(attributeName = "Price") public int getPrice() {return price; } public void setPrice(Integer price) { this.price = price; } /* 任意の属性名 AWSコンソールで事前定義不要*/ @DynamoDBAttribute(attributeName = "Releasedate") public String getReleasedate() {return releasedate; } public void setReleasedate(String releasedate) { this.releasedate = releasedate; } }
プログラム内で記載している以下はAWSコンソールで事前定義をしたDynamoDBのマッピング定義で必ず定義が必要なアノテーションです。
@DynamoDBTable(tableName = "Books")
@DynamoDBHashKey(attributeName = "Author")
@DynamoDBRangeKey(attributeName = "Title")
以下は、AWSコンソールで事前定義をしたものではなく、本アプリで使用し得る属性名として定義しているアノテーションです。
@DynamoDBAttribute(attributeName = "Price")
@DynamoDBAttribute(attributeName = "Releasedate")
他にも色々とアノテーションを定義するルールが以下に記載されています。
docs.aws.amazon.com
MainActivity.java
package com.example.sample.dynamodb_sample; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.amazonaws.auth.CognitoCachingCredentialsProvider; import com.amazonaws.regions.Regions; import com.amazonaws.regions.Region; import com.amazonaws.services.dynamodbv2.*; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.*; import java.util.Date; public class MainActivity extends AppCompatActivity { private Books book; private Runnable runnable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // (1) Cognitoで出力した認証定義です CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider( getApplicationContext(), "ap-northeast-1:xxxxxxxxxxxxxxxxxxxxxxxxxxx ", // Identity Pool ID Regions.AP_NORTHEAST_1 // Region ); // (2) DynamoDBのクライアントセッションを作成します AmazonDynamoDBClient ddbClient = new AmazonDynamoDBClient(credentialsProvider); // (3) デフォルトではUS-EASTがリージョンで指定されてしまうため意図的にAP_NORTHEASTにしています Region apNortheast1 = Region.getRegion(Regions.AP_NORTHEAST_1); ddbClient.setRegion(apNortheast1); // (4) マッパーのインスタンス作成 final DynamoDBMapper mapper = new DynamoDBMapper(ddbClient); // (5) インターネットのアクセスを行うためにスレッドを作成し、その中でインサート処理を定義します runnable = new Runnable() { public void run() { Books book = new Books(); book.setAuthor("Charles Dickens"); book.setTitle("Great Expectations"); book.setPrice(20000); Date date = new Date(); book.setReleasedate(date.toString()); mapper.save(book); }; }; Thread mythread = new Thread(runnable); mythread.start(); } }
コード解説
(1) AWSの認証
AndroidとDynamoDB実装方法 (2) - Cognito初期設定 - - AWS Mobile Application Developmentで取得した「Get AWS Credentials」を定義して認証処理を行います。
(2) DynamoDBのクライアントセッション作成
(1)でDynamoDB用のクライアントセッションを作成します。
(3) リージョンの指定
デフォルトではUS-EASTがリージョンで指定されてしまうため、これを設定しないと以下のエラーが発生します。その為、意図的にAP_NORTHEASTにしています。
E/AndroidRuntime: FATAL EXCEPTION: Thread-9 Process: com.example.sample.dynamodb_sample, PID: 2269 com.amazonaws.AmazonServiceException: User: arn:aws:sts::xxxxxxxxxxxxx:assumed-role/Cognito_DynamoTestUnauth_Role/CognitoIdentityCredentials is not authorized to perform: dynamodb:UpdateItem on resource: arn:aws:dynamodb:us-east-1:xxxxxxxxxxxxxx:table/Books (Service: AmazonDynamoDB; Status Code: 400; Error Code: AccessDeniedException; Request ID: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
(5) 別スレッドでDB処理を行う
Androidではインターネット処理をメインスレッド(UIスレッド)で行ってはいけません。ワーカスレッドを作成しそれ上で処理を行う必要があります。これを行わなかった場合以下のエラーが発生します。
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.sample.dynamodb_sample, PID: 3056 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sample.dynamodb_sample/com.example.sample.dynamodb_sample.MainActivity}: android.os.NetworkOnMainThreadException
Mainスレッドとは別でインターネットの処理し結果をメインスレッドへコールバックをすることがAndroidの基本です。実現方法法として、「Runnable」と「AsyncTask」がありますので「Runnable」は上記に書いていますので「AsyncTask」実装例を以下に記載します。
package com.example.sample.dynamodb_sample; import android.os.AsyncTask; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; import com.amazonaws.auth.CognitoCachingCredentialsProvider; import com.amazonaws.regions.Regions; import com.amazonaws.regions.Region; import com.amazonaws.services.dynamodbv2.*; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.*; import java.util.Date; public class MainActivity extends AppCompatActivity { private CognitoCachingCredentialsProvider credentialsProvider; private static final String TAG = MainActivity.class.getSimpleName(); private Books book; private DynamoDBMapper mapper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // (1) Cognitoで出力した認証定義です CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider( getApplicationContext(), "ap-northeast-1:xxxxxxxxxxxxxxxxxxxxxxx", // Identity Pool ID Regions.AP_NORTHEAST_1 // Region ); // (2) DynamoDBのクライアントセッションを作成します AmazonDynamoDBClient ddbClient = new AmazonDynamoDBClient(credentialsProvider); // (3) デフォルトではUS-EASTがリージョンで指定されてしまうため意図的にAP_NORTHEASTにしています Region apNortheast1 = Region.getRegion(Regions.AP_NORTHEAST_1); ddbClient.setRegion(apNortheast1); // (4) マッパーのインスタンス作成 mapper = new DynamoDBMapper(ddbClient); new db().execute(""); } //AsyncTask<Params, Progress, Result> private class db extends AsyncTask<String, Integer, String> { /** doInBackgroundメソッドの実行前にメインスレッドで実行されます。 非同期処理前に何か処理を行いたい場合に使用。 */ @Override protected void onPreExecute() { Log.i(TAG,"onPreExecuted ...."); } /** メインスレッドとは別のスレッドで実行されます。 非同期で処理したい内容を記述します。記載必須。 */ @Override protected String doInBackground(String... params) { Log.i(TAG,"doInBackground ...."); Books book = new Books(); int i = 0; for(i = 0; i < 20; i++){ try { Thread.sleep(1500); book.setAuthor("村上春樹"); book.setTitle("1Q24" + "第" + i + "版"); book.setPrice(20000); Date date = new Date(); book.setReleasedate(date.toString()); mapper.save(book); publishProgress(i); }catch(InterruptedException e){ Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_SHORT).show(); } } /* onPostExecute(String s) の s に "Executed" が入ります */ return "Executed"; } /**メインスレッドで実行されます。 非同期処理の進行状況をプログレスバーで 表示したい時などに使うことができます。 */ @Override protected void onProgressUpdate(Integer... values) { Log.i(TAG,"onProgressUpdate .... " + values[0]); } /**doInBackgroundメソッドの実行後にメインスレッドで実行されます。 doInBackgroundメソッドの戻り値をこのメソッドの引数として受け取り、 その結果を画面に反映させることができます。 */ @Override protected void onPostExecute(String s) { Log.i(TAG,"onPostExecute ....return value is " + s); } } }
[参考]
関連記事
AndroidとDynamoDB実装方法 (1/4) - AWS SDKの準備 -
AndroidとDynamoDB実装方法 (2/4) - Cognito初期設定 -
AndroidとDynamoDB実装方法 (3/4) - DynamoDB初期設定 -
AndroidとDynamoDB実装方法 (4/4) - プログラミング -
参考
- AWS DynamoDBへサンプルデータを投入しクエリーを出す(Java) | infoScoop開発者ブログ
- AWS DynamoDBの項目の取得(Java) | infoScoop開発者ブログ
- amazon web services - "the provided key element does not match the schema" in the sample from AWS Android SDK - Stack Overflow
- 【AWS】今更ながらDynamoDB入門 - Qiita
- Store and Query App Data in DynamoDB — Android Developer Guide
- DynamoDB 用の Java 注釈 - Amazon DynamoDB
- Store and Retrieve App Data in Amazon DynamoDB — Android Developer Guide
- Step 1: Create Example Tables - Amazon DynamoDB
- AsyncTaskを使った非同期処理のきほん | Developers.IO