1. AppPot SDKの初期化

アプリからAppPotを使うためには初期設定が必要です。
APService.setServiceInfoにサーバーなどの各種情報を引数で指定します。

// AppPotの初期化
APService service = APService.getInstance();
service.setServiceInfo(getApplicationContext(),
		"jp.co.ncdc.AppPotDemoApplication",    // アプリID
		"fb5dc1bb43ec4f5daa60a4df9cd3d1bd",    // アプリKey
		"1.0",                                 // アプリバージョン
		"49.212.158.239",                      // AppPotサーバー・ホスト名
		"apppot",                           // AppPotサーバー・コンテキストルート
		8080,                                  // AppPotサーバー・ポート番号
		false,                                 // Push通知要否
		false);                                // SSL要否

設定する情報は管理画面で指定したアプリのIDやバージョン、そしてAppPotサーバーの情報です。
AppPot SDKはここに設定された情報に基づいてAppPotサーバーとのやりとりを行います。
この設定情報が正しくない場合、AppPot SDKは正常に機能できません。

2. Value Objectの定義

AppPot SDKの初期化が終わったら次はアプリで使うデータを表現するValue Objectを定義します。
Value ObjectはAppPot SDKから提供するAPObjectを継承したクラスとして定義する必要があります。

Value Objectの宣言は以下の二つのパーツに区分して考える事ができます。

  • Value Objectの属性(データタイプ)の宣言
  • Value Objectの振る舞いの指定

以下にAPObjectを継承したCaseReportとFollowというクラスを使って定義の例を示します。

Value Objectの定義

各Value Objectは複数の属性で一つの固まりのデータを示します。データの属性はClassのpropertyとして定義します。
これは定義するクラスの親クラスをAPObjectに指定する他には普通のObjective-Cのクラスの定義と何も変わりがありません。
必要な属性をpropertyとして自由に定義できます。

import jp.co.ncdc.apppot.stew.dto.APObject;

public class CaseReport extends APObject {

	// 属性の定義
    public int age;
    public int gender;
    public int isFollow;
    public String memo;
    public String patientName;

		// データの持ち方、同期の間隔を設定
    public CaseReport() {
        setPersistentType(PersistentType.APLocalAndServer);
        this.setAutoRefresh(true);
        this.setRefreshInterval(1000);
    }
}

Value Objectの振る舞いの指定

Value Objectが継承するAPObjectでは複数の設定項目が用意されてあり、それに適切な値を設定することでValue Objectの振る舞いを制御できます。
各Value Objectの設定はコンストラクタの中で行います。ここで設定しない項目に対してはデフォルトの値が使われる事となります。

上記の例ではCaseReportと言うValue Objectに下記の設定を行っています。

  • データの保持の場所:setPersistentType(PersistentType.APLocalAndServer);。サーバーと端末内の両方に持つ
  • データ同期:this.setAutoRefresh(true);。自動更新する。PersistentType.APLocalAndServerの場合のみの設定。
  • 自動同期間隔:this.setRefreshInterval(1000);。1000秒おきに自動同期する。PersistentType.APLocalAndServerの場合のみの設定

Value Objectの振る舞いを指定する設定項目は下記の通りです。

データの保持場所の指定

persistentType : 何も指定しない場合はデフォルトでサーバー側にのみ保存することになっています。以下のいずれを選択できます。

  • APPersistentServerOnly, // サーバーだけに保持します。
  • APPersistentLocalOnly, // 端末内だけに保持します。
  • APPersistentLocalAndServer // 端末内とサーバーに保持します。

データの自動更新の指定

これはデータの保持場所が端末内及びサーバー側の両方(APPersistentLocalAndServer)が指定された場合のみ有効な指定です。
その他の保持場所が指定されている場合は以下の設定は無視されます。

  • isAutoRefresh : 該当データが自動更新対象であるかの指定。この設定はpersistentTypeがAPPersistentLocalAndServerの場合のみ有効です。この属性の値をYESにした場合、AppPot SDKは該当データを後述する条件で自動更新し、端末内のデータを最新のものに保ちます。
  • autoRefreshInterval : 自動更新の間隔を秒数で指定します。AppPot SDKはこの値を使って定期的にサーバーのデータを確認し、端末のデータを最新の状態に更新します。
  • scopeTypeForAutoRefresh : 自動更新するデータの権限の指定。1:ユーザー、2:グループ、3:全部から指定可能です。

3. Value Objectのの登録

Value Objectの定義が終わったらAppPot SDKに定義したValue Objectを登録します。登録するには先述したinitAppPotSDKメソッドに以下のコードを追加します。

// ValueObjectの登録
ArrayList tables = new ArrayList();
tables.add(new CaseReport());

boolean isCreateDatabase = true;

// App用DB作成。この時、端末と、サーバーの両方にデータベースが作成される
APEntityManager.getInstance().createAppDB(
    tables,             				// テーブル
    1,           							  // 会社コード
		isCreateDatabase,           // サーバーのデータベースを再生するかどうか、
    new APResponseHandler() {   // 応答は非同期で受け取ります

    @Override
    public void onFailure(APResponse arg0) {
        Log.e(TAG, "Can not create App Db:" + arg0.getDescription());

    }

    @Override
    public void onSuccess(APResponse arg0) {

        Log.i(TAG, "Created App Db successfully:" + arg0.getDescription());
    }
});

上記AppPot SDKに登録して自動的に管理するValue Objectの一覧を配列として作成し、AppPot SDKに登録しています。
アプリ起動の直後、AppPot SDKは登録されたValue Objectを解釈し、
必要に応じて端末内やAppPotのサーバーに各Value Objectの値を格納するためのデータ保存場所を作成します。
端末内でデータはValue Object単位でテーブルが作成され、SQLiteデータベースにデータが格納されます。

ただし、毎回上記の処理が行われるのはあまり効率的ではありません。初回のアプリ実行でデータベースが作成されたら、
上記のisCreateDatabaseの値をfalseに変えてデータベースの生成処理はスキップします。
アプリの開発中にValue Objectの定義を変えた場合にはまたisCreateDatabaseの値をtrueに変えて一回アプリを起動することで変更をデータベースに反映します。

これで全ての準備は終わりました。
これからは普通のアプリの作り方に基づいて、アプリの画面や画面遷移を自由に作成します。
アプリの各画面で必要なデータは各Value Objectを利用することで新規作成、照会、編集、削除等の操作ができます。

Value Objectの操作方法の詳細は次の章を参照して下さい。

4. AppPot SDKを利用したデータ(Value Object)の管理

新規データの作成

作成したValue ObjectのCaseReportを元に作成してみましょう。
CaseReportのオブジェクトを作って、属性に値をセットしていきます。
最後はAPEntityManger.saveDataメソッドで保存します。
Value Objectは開発者が定義した属性以外にも、制御用の情報をいくつか持っています。
scopeTypeもその1つで、これから作成するデータの共有範囲を設定できます。
下記の例では共有範囲をグループにしており、グループ外のユーザーからは参照することはできません。

CaseReport caseReport = new CaseReport();
caseReport.age = 25;
caseReport.gender = 0;
caseReport.isFollow = 1;
caseReport.memo = "新患。高血圧";
caseReport.patientName = "アップポット 太郎";

// 作成するデータの参照範囲を設定
// 1:本人のみ、2:データ生成ユーザーと同じグループ内で共有、3:全ユーザーに共有
caseReport.scopeType = 2;

APEntityManager.getInstance().saveData(caseReport);

saveObjectメソッドが呼ばれるまではデータはメモリー上に存在するだけです。saveDataを呼んだ時にデータの保存処理が行われます。
データの保存に成功するとnewReportのobjectIdと言う属性に値が設定されます。
objectIdはデータのユニークなキーであり、一件のデータの固有な識別子として使うことができます。

データが保存される場所は各クラスの設定によって異なります。
上記の例で使っているCaseReportクラスはpersistentTypeがAPPersistentLocalAndServerに設定されているため
データは端末内のデータベースとサーバー側に保存されます。
saveDataメソッドが呼ばれた時点で端末がオフラインの状態である場合はデータは端末内だけに保存され、
後でオンラインになった時点でサーバー側にもデータが送信され保存されます。
つまり、端末がオフラインの状態では端末内とサーバー側に異なるデータを持つ事になる場合があります。

データ一覧の取得

データの一覧の取得にはjp.co.ncdc.apppot.stew.APQueryクラスを使います。

データ取得条件の指定

単純にデータの一覧を取得するのではなく、条件を絞って取得するにはjp.co.ncdc.apppot.stew.APQueryに対して検索条件を指定します。
以下のメソッドの何れか、あるいは複数を組み合わせて検索条件を指定することができます。


/**
 *  @columnTable 検索対象のテーブル。APObjectを継承したクラスを指定する
 *  @column 検索対象のカラム名
 *  @value 検索する値
 *  @type APQuery.AND or APQuery.OR
 */
public void addWhereEqual(Class<?> columnTable, String column, Object value, String type)
public void addWhereEqualIgnoreCase(Class<?> columnTable, String column, Object value, String type)
public void addWhereNotEqual(Class<?> columnTable, String column, Object value, String type)
public void addWhereNotEqualIgnoreCase(Class<?> columnTable, String column, Object value, String type)
public void addWhereGreaterThan(Class<?> columnTable, String column, Object value)
public void addWhereLessThan(Class<?> columnTable, String column, Object value, String type)
public void addWhereLike(Class<?> columnTable, String column, Object value, String type)
public void addWhereLikeIgnoreCase(Class<?> columnTable, String column, Object value, String type)

以下にAPQueryに取得するデータの条件を指定するための処理の例を示します。

APQuery query = new APQuery(CaseReport.class);
// 名前をキーに検索
query.whereLike("patientName", "アップポット");
APEntityManager.getInstance().getData(query, new APResponseHandler() {

    @Override
    public void onFailure(APResponse arg0) {
        Log.e(TAG,"Can not get AppData:"+ arg0.getDescription());
    }

    @Override
    public void onSuccess(APResponse arg0) {
        Log.e(TAG, "get AppData:" + arg0.getDescription());
        List list = arg0.getResultForSearchObject(CaseReport.class).getSearchResuls();

        for (APObject object : list) {
             selectedCaseReport = (CaseReport) object;
             Log.e(TAG, "DATA:" + selectedCaseReport.patientName);

         }
    }

    });

データの更新

一件のデータを変更するにはValue Objectのpropertyを修正し、以下のメソッドを使います。

selectedCaseReport.memo = selectedCaseReport.memo + "\nメモを更新しました。";
APEntityManager.getInstance().saveData(selectedCaseReport);

新規に作成したデータも既存データも更新には上記のメソッドを使う事ができます。
AppPot SDKはobjectIdの有無を見て新規データか既存データかを判断します。
その判断結果に基づき、新規データである場合はデータの挿入、既存データの場合はデータの更新処理が行われます。
このメソッドの戻り値は変更等がデータベースに保存され、採番されたobjectIdが設定されたValue Objectとなります。

データの削除

データを削除するにはValue Objectの以下のメソッドの何れかを呼び出します。二つのメソッドの差は同期型で処理するか非同期型で処理するかです。

APEntityManager.getInstance().deleteData(selectedCaseReport)

5. AppPot SDKが提供する機能

ユーザー認証(ログインとログアウト)

AppPotはログイン、ログアウトのためにjp.co.ncdc.apppot.stew.APServiceクラスの以下の二つのメソッドを提供します。
ユーザー認証に使われるユーザーの情報はAppPotの管理画面から事前に登録されている必要があります。

ログイン
APService service = APService.getInstance();
service.authentication(
    1,          // 会社コード
    "sogo@stew.com",    // ユーザーID
    "a",            // ユーザーパスワード
    new APResponseHandler() {   // 結果は非同期で受け取ります

    @Override
    public void onFailure(APResponse arg0) {
        Log.e(TAG, "Can not Login:" + arg0.getDescription());
    }

    @Override
    public void onSuccess(APResponse arg0) {
        Log.i(TAG, "Login successfull:" + arg0.getDescription());
    }});

ログインの認証はAppPotのサーバー側で行われます。サーバー側では認証の方式を選択できますが、アプリ開発者はそれらを意識する必要はありません。

ログアウト
APService service = APService.getInstance();
service.logout(
    new APResponseHandler() {   // 結果は非同期で受け取ります

    @Override
    public void onFailure(APResponse arg0) {
        Log.e(TAG, "Can not Logout:" + arg0.getDescription());
    }

    @Override
    public void onSuccess(APResponse arg0) {
        Log.i(TAG, "Logout successfull:" + arg0.getDescription());
    }});

ログインとログアウト処理は非同期通信によって行われます。ログインとログアウト後の処理はコールバックメソッドの中に記述します。

ログインはサーバー側の認証を必須とするため必ず端末がオンラインの状態で行う必要があります。

アプリのログをサーバーに送信

jp.co.ncdc.apppot.stew.APLogはアプリの使用状況や問題発生の監視のために二つのログ出力用メソッドを提供します。
このメソッドを使ってどのような内容でもログとして残す事ができます。

APLog.monitor("エラーメッセージ");
APLog.monitor("利用ログ等のメッセージ");

これらのメソッドで記述された内容はアプリ側のログ出力されず、アプリ内のデータベースに保管され、適時にAppPotサーバーに送信されます。
サーバーへの送信のタイミングはAppPot SDKによって制御され、アプリ開発者が意識する必要はありません。

また送信するログの種類はAppPotサーバーの管理画面から指定できます。
つまり、モニタリング用のログとエラー発生時のログをアプリ実装用のコードの中に記述しておけば管理画面から適時ログ収集レベルを指定できます。
ログ収集レベルをモニタリングに設定すれば全てのログが収集されます。ログ収集レベルをエラーに設定すればエラー発生時のログだけが収集されます。

この仕組みによってアプリの運用状況に合わせたログ収集をサーバー側の管理で行う事ができます。
例えば、アプリ配布初期はユーザーの使用状況等を見るためにモニタリングをログ収集レベルとして設定しより細かい情報を収集できます。
またアプリがある程度使われ、使用者の使用傾向が把握できたらログ収集レベルをエラーに修正して収集するログの量を減らすこともできます。