void UUIDManager::Get(String &uuid) { result r = E_SUCCESS; String keyUUID("key_uuid"); AppRegistry* appRegistry = Application::GetInstance()->GetAppRegistry(); r = appRegistry->Get(keyUUID, uuid); if (r == E_KEY_NOT_FOUND) { String u; Tizen::Base::UuId* pUUID = Tizen::Base::UuId::GenerateN(); u.Append(pUUID->ToString().GetPointer()); appRegistry->Add(keyUUID, u); delete pUUID, pUUID = NULL; } r = appRegistry->Get(keyUUID, uuid); }
「Tizen」カテゴリーアーカイブ
Tizenでデータを永続化する
SQLiteを使うまでのデータでない場合に、SharedPreferencesやNSUserDefaultのようなものが欲しくなる。Tizenでは以下のようにする。
#include <FApp.h>
using namespace Tizen::App;
result r = E_SUCCESS; String hogeKey("tmp_hoge_key"); String hogeValue("tmp_hoge_value"); String value(""); AppRegistry* appRegistry = Application::GetInstance()->GetAppRegistry(); r = appRegistry->Get(hogeKey, value); if (r == E_KEY_NOT_FOUND) { AppLog("value:%ls", value.GetPointer()); appRegistry->Add(hogeKey, hogeValue); } r = appRegistry->Get(hogeKey, value); AppLog("value:%ls", value.GetPointer());
以下のようなログが表示される。
virtual result HogeHoge::OnInitializing()(45) > value: virtual result HogeHoge::OnInitializing()(50) > value:tmp_hoge_value
virtual result HogeHoge::OnInitializing()(50) > value:tmp_hoge_value
TizenアプリでSQLiteを使う
SDKに同梱されているコードがいまいちわかりにくかったので、オフィシャルサイトにあるdocumentationからサンプルコードを拝借する。
■DBManager.cpp
とりあえず上から読んでいってSQLもしくはそれに準ずるものを探す。
result DBManager::CreateTable()
CREATE TABLE文がそのまま見つかったので読んでみる。
String sql; result r = E_SUCCESS; sql.Append(L"CREATE TABLE IF NOT EXISTS member(seq INTEGER PRIMARY KEY,id varchar(20),name varchar(20),age INTEGER)"); r = Execute(sql); AppLog("create : %s",GetErrorMessage(r)); return r;
SQL文を作ってそのままprivateメソッドに投げてるようだ。
result DBManager::Execute(String sql)
投げられたSQLをそのまま処理しているようだ。
__pDatabase->BeginTransaction(); r = __pDatabase->ExecuteSql(sql, true); __pDatabase->CommitTransaction();
__pDatabaseを操作している。
result DBManager::Open(String dbName)
__pDatabaseをインスタンス化している。use `dbname`;的なところでDBをopenしているところのようだ。
AppLog("Open"); __dbName = dbName; result r = E_SUCCESS; __pDatabase = new Database; __pDatabase->Construct(__dbName,true); return r;
bool DBManager::IsMember(String id)
以下のとおり取り出したデータはAndroidのCursorのようになっているようだ。
bool isMember = false; String sql; sql.Format(100,L"SELECT id FROM member where id = '%ls'",id.GetPointer()); // select a query using the Database::QueryN() wrapper AP DbEnumerator* pEnum = __pDatabase->QueryN(sql); if (pEnum) { while (pEnum->MoveNext() == E_SUCCESS) { isMember = true; } delete pEnum; } return isMember;
result DBManager::GetAllMember(ArrayList& list)
もう少しちゃんと取り出しているところを見る。
AppLog("GetAllMember"); result r = E_SUCCESS; String sql; sql.Format(50,L"select seq, id, name,age from member"); MEMBERINFO* pInfo = null; // select a query using the Database::QueryN() wrapper AP DbEnumerator* pEnum = __pDatabase->QueryN(sql); if (pEnum) { while (pEnum->MoveNext() == E_SUCCESS) { pInfo = new MEMBERINFO(); r = pEnum->GetIntAt(0, pInfo->seq); r = pEnum->GetStringAt(1,pInfo->id); r = pEnum->GetStringAt(2,pInfo->name); r = pEnum->GetIntAt(3,pInfo->age); list.Add(*pInfo); } delete pEnum; } return r;
サンプルコードが簡略化されていて理解しやすい。
■DBManager.h
このクラスはSingletonパターンになっていて以下のメソッドでインスタンスを取得する。
static DBManager* GetDB() { if(__pInstance == null) { __pInstance = new DBManager(); } return __pInstance; }
使い終わった時のメソッドも用意されている。
static void ReleaseDB() { if(__pInstance) { delete __pInstance; __pInstance = null; } }
コンストラクタ
DBManager::DBManager() :__pDatabase(null) { // TODO Auto-generated constructor stub Init(); }
void DBManager::Init()
Open(App::GetInstance()->GetAppRootPath() + L"data/mdb.db"); CreateTable();
次の2つのメソッドを呼び出している。
result DBManager::Open(String dbName)
引き数で与えられたデータベースファイルを開く。
AppLog("Open"); __dbName = dbName; result r = E_SUCCESS; __pDatabase = new Database; __pDatabase->Construct(__dbName,true); return r;
result DBManager::CreateTable()
CREATE TABLE文を実行する。
String sql; result r = E_SUCCESS; sql.Append(L"CREATE TABLE IF NOT EXISTS member(seq INTEGER PRIMARY KEY,id varchar(20),name varchar(20),age INTEGER)"); r = Execute(sql); AppLog("create : %s",GetErrorMessage(r)); return r;
デストラクタ
DBManager::~DBManager() { Close(); // TODO Auto-generated destructor stub }
result DBManager::Close()
AppLog("Close"); result r = E_SUCCESS; if(__pDatabase) { delete __pDatabase; __pDatabase = null; } return r;
■Form1.cpp
DBManagerの使い方は以下のようになっている。
GetDB()->GetAllMember(list);
result Form1::OnTerminating(void) { result r = E_SUCCESS; if(__pInfoPopup) { delete __pInfoPopup; __pInfoPopup = null; } ReleaseDB(); // TODO: Add your termination code here return r; }
TizenアプリでJSONをパースする
サンプルアプリのJsonParserAppを見る。
■JsonForm.cpp
void JsonForm::ParseAndDisplay(void)
// なるべく簡略化したいのでエラー処理はコメントアウトしておく。 // fileを読み込み専用で開く。 File file; String filePath = App::GetInstance()->GetAppRootPath() + L"data/jsonSample.json"; result r = file.Construct(filePath, L"r"); #TryReturnVoid(r == E_SUCCESS, "file construction failure with [%s]", GetErrorMessage(r)); FileAttributes att; r = File::GetAttributes(filePath, att); #TryReturnVoid(r == E_SUCCESS, "file GetAttributes failure with [%s]", GetErrorMessage(r)); long long size = att.GetFileSize(); #TryReturnVoid(size > 0, "file does not contain valid data, size of file [%ld]", size); ByteBuffer buf; r = buf.Construct(size + 1);// fileサイズ+1で初期化 #TryReturnVoid(r == E_SUCCESS, "bytebuffer construct failure with [%s]", GetErrorMessage(r)); r = file.Read(buf);// fileを読み込む #TryReturnVoid(r == E_SUCCESS, "file read failure with [%s]", GetErrorMessage(r)); // 読み込んだデータをJSONにパース IJsonValue* pJson = JsonParser::ParseN(buf); TryCatch(pJson, , "ParseN failed with [%s]", GetErrorMessage(GetLastResult())); AppLog("Before traverse %d", _pList->GetItemCount()); _pJsonKeyList->RemoveAll(true); _pValueList->RemoveAll(true); TraverseFunction(pJson); AppLog("After traverse");
fileにclose的なものがないけどいいのかな。
void JsonForm::TraverseFunction(IJsonValue* pValue)
パースしたIJsonValueのオブジェクトを実際にどう扱うか見てみる。このメソッドは、pValue->GetType()で分岐してある。typeによっては自身を呼び出し再帰処理している。
FWebJsonIJsonValue.h
jsonの値の型は以下のように定義されている。
enum JsonType { JSON_TYPE_STRING, /**< The JSON string type*/ JSON_TYPE_NUMBER, /**< The JSON number type*/ JSON_TYPE_OBJECT, /**< The JSON object type*/ JSON_TYPE_ARRAY, /**< The JSON array type*/ JSON_TYPE_BOOL, /**< The JSON bool type*/ JSON_TYPE_NULL /**< The JSON null type*/ };
nullの時
TryReturnVoid(_pList, "_pList is null"); TryReturnVoid(pValue, "input jsonvalue pointer is null");
オブジェクトの時
Mapにしてkeyとvalueを取り出し、valueを引き数にして再帰呼び出ししている。
case JSON_TYPE_OBJECT: { JsonObject* pObject = static_cast< JsonObject* >(pValue); IMapEnumeratorT< const String*, IJsonValue* >* pMapEnum = pObject->GetMapEnumeratorN(); while (pMapEnum->MoveNext() == E_SUCCESS) { const String* key = null; IJsonValue* value = null; pMapEnum->GetKey(key); String* pListKey = new (std::nothrow) String(*key); _pJsonKeyList->Add(*pListKey); String* pStr = null; _isArray = 0; pMapEnum->GetValue(value); if (value->GetType() == JSON_TYPE_OBJECT) { pStr = new (std::nothrow) String("Value is an Object"); _pValueList->Add(*pStr); } else if (value->GetType() == JSON_TYPE_ARRAY) { pStr = new (std::nothrow) String("Value is an Array"); _pValueList->Add(*pStr); } TraverseFunction(value); } delete pMapEnum; } break;
文字列の場合
_pValueListに追加している。
case JSON_TYPE_STRING: { JsonString* pVal = static_cast< JsonString* >(pValue); if (_isArray == 0) { String* pStr = new (std::nothrow) String(*pVal); _pValueList->Add(*pStr); } } break;
配列の場合
keyとvalueを取り出し、valueを引き数にして再帰呼び出ししている。
case JSON_TYPE_ARRAY: { JsonArray* pJsonArray = static_cast< JsonArray* >(pValue); pJsonArray->GetCount(); IEnumeratorT< IJsonValue* >* pEnum = pJsonArray->GetEnumeratorN(); while (pEnum->MoveNext() == E_SUCCESS) { IJsonValue* pValue = null; pEnum->GetCurrent(pValue); if ((pValue->GetType() == JSON_TYPE_STRING) || (pValue->GetType() == JSON_TYPE_NUMBER) || (pValue->GetType() == JSON_TYPE_BOOL) || (pValue->GetType() == JSON_TYPE_NULL)) _isArray = 1; TraverseFunction(pValue); } delete pEnum; } break;
数値の場合
JsonNumberをtoStringして文字列にし、_pValueListにaddしている。
case JSON_TYPE_NUMBER: { JsonNumber* pVal = static_cast< JsonNumber* >(pValue); String* pStr = new (std::nothrow) String((pVal->ToString())); if (_isArray == 0) _pValueList->Add(*pStr); } break;
真偽値の場合
条件分岐して、文字列を_pValueListにaddするようにしている。
case JSON_TYPE_BOOL: { String* pStr = null; JsonBool* pVal = static_cast< JsonBool* >(pValue); if (*pVal == true) pStr = new (std::nothrow) String("true"); else pStr = new (std::nothrow) String("false"); if (_isArray == 0) _pValueList->Add(*pStr); } break;
nullの場合
nullという文字列を_pValueListにaddするようにしている。
case JSON_TYPE_NULL: { String* pStr = null; pStr = new (std::nothrow) String("null"); if (_isArray == 0) _pValueList->Add(*pStr); } break;
読むのが面倒だったがC++の基本が分かる良いコードだった。
TizenアプリでHTTP通信する
サンプルアプリのHttpClientを見る。
■MainForm.cpp
MainFormはTizen::Net::Http::IHttpTransactionEventListenerを継承している。
result MainForm::RequestHttpGet(void)
エラー処理を省くと以下の通りとなる。
HttpTransaction* pHttpTransaction = null; HttpRequest* pHttpRequest = null; pHttpTransaction = __pHttpSession->OpenTransactionN(); r = pHttpTransaction->AddHttpTransactionListener(*this); pHttpRequest = const_cast< HttpRequest* >(pHttpTransaction->GetRequest()); r = pHttpRequest->SetUri(HTTP_CLIENT_REQUEST_URI); r = pHttpRequest->SetMethod(NET_HTTP_METHOD_GET); r = pHttpTransaction->Submit();
AddHttpTransactionListenerの引き数はIHttpTransactionEventListenerを継承したクラスでサンプルアプリでは自身である。
void MainForm::OnTransactionReadyToRead(HttpSession& httpSession, HttpTransaction& httpTransaction, int availableBodyLen)
通信結果を受け取る。
HttpResponse* pHttpResponse = httpTransaction.GetResponse(); if (pHttpResponse->GetHttpStatusCode() == HTTP_STATUS_OK) { HttpHeader* pHttpHeader = pHttpResponse->GetHeader(); if (pHttpHeader != null) { String* tempHeaderString = pHttpHeader->GetRawHeaderN(); ByteBuffer* pBuffer = pHttpResponse->ReadBodyN(); String text(L"Read Body Length: "); text.Append(availableBodyLen); __pEditArea->SetText(text); Draw(); delete tempHeaderString; delete pBuffer; } }
IHttpTransactionEventListenerを継承した場合は以下のメソッドの実装が必要になるっぽい。
- void MainForm::OnTransactionReadyToRead(HttpSession& httpSession, HttpTransaction& httpTransaction, int availableBodyLen)
- void MainForm::OnTransactionAborted(HttpSession& httpSession, HttpTransaction& httpTransaction, result r)
- void MainForm::OnTransactionReadyToWrite(HttpSession& httpSession, HttpTransaction& httpTransaction, int recommendedChunkSize)
- void MainForm::OnTransactionHeaderCompleted(HttpSession& httpSession, HttpTransaction& httpTransaction, int headerLen, bool authRequired)
- void MainForm::OnTransactionCompleted(HttpSession& httpSession, HttpTransaction& httpTransaction)
- void MainForm::OnTransactionCertVerificationRequiredN(HttpSession& httpSession, HttpTransaction& httpTransaction, Tizen::Base::String* pCert)