2016-05-12 8 views
0

Ich habe eine minimale App mit Marmalade Core gemacht. Es erstellt eine Webansicht und sendet dann Daten, die mit s3eSecureStoragePut & s3eSecureStorageGet gespeichert und abgerufen werden sollen.Marmelade Core Storage (s3eSecureStoragePut & s3eSecureStorageGet) nicht persistent

Das funktioniert gut, bis ich die App schließe und wieder öffne. Nachdem es wieder geladen ist und ich versuche, die Daten zu laden, wird es leer angezeigt. Hat jemand irgendwelche Ideen, warum das passieren könnte? Es wird gebaut/Einsatz mit GCC ARM Debug für Android

Hier mein C++

#include "s3e.h" 
#include "s3eDevice.h" 
#include "IwDebug.h" 
#include "s3eWebView.h" 
#include "IwGx.h" 
#include "Iw2D.h" 
#include <string> 
#include <sstream> 

s3eWebView* webView; 
bool pageLoaded; 
const char* rom = "rom://index.html"; 

struct SStoreData { 
    std::string key; 
}; 

static int loadedCallback(s3eWebView* instance, void* sysData, void* userData) { 
    pageLoaded = true; 
    return 1; 
} 

static int javaScriptCallback(s3eWebView* instance, void* systemData, void* userData) { 
//cast the data to string for easier handling 
std::string data = (char*) systemData; 
char jsFunc[128]; 
//check if page has loaded to prevent errors 
if (pageLoaded) { 
    if (!std::strncmp(data.c_str(), "saveKey", std::strlen("saveKey"))) { 
     std::string key = data.substr(data.find("|") + 1, data.length()); 
     SStoreData *toSave = new SStoreData; 
     toSave->key = key; 
     s3eSecureStoragePut (toSave, sizeof (*toSave)); 
    } else if ("loadKey" == data) { 
     SStoreData *toLoad = new SStoreData; 
     s3eSecureStorageGet (toLoad,sizeof(*toLoad)); 
     sprintf(jsFunc, "dataLoaded(\"%s\", \"key\");", toLoad->key.c_str()); 
     s3eWebViewSendJavaScript(webView, jsFunc); 
    } else { 

     IwTrace(JS_CALLBACK, ("DID NOT RECEIVE ANYTHING")); 
    } 
} 
return 1; 
} 


void init() { 
//init vars 
webView = s3eWebViewCreate(false); 
pageLoaded = false; 

//register callbacks 
s3eWebViewRegister(S3E_WEBVIEW_FINISHED_LOADING, loadedCallback, NULL, webView); 
s3eWebViewRegister(S3E_WEBVIEW_FROM_JAVASCRIPT, javaScriptCallback, NULL, webView); 

//navigate to the webpage 
s3eWebViewNavigate(webView, rom); 
//display the webview 
s3eWebViewShow(webView, 0, 0, IwGxGetDisplayWidth(), IwGxGetDisplayHeight()); 
} 

void destroy() { 
if (webView) { 
    s3eWebViewDestroy(webView); 
    webView = NULL; 

    //unregister callbacks 
    s3eWebViewUnRegister(S3E_WEBVIEW_FINISHED_LOADING, loadedCallback, webView); 
    s3eWebViewUnRegister(S3E_WEBVIEW_FROM_JAVASCRIPT, javaScriptCallback, webView); 
} 
delete rom; 

//gives me warning so I'm leaving it out. 
//delete pipHandler; 
} 

// Main entry point for the application 
int main() 
{ 
    //Initialise graphics system(s) 
    //Initialise graphics system(s) 
    Iw2DInit(); 

    //Init 
    init(); 

    // Loop forever, until the user or the OS performs some action to quit the app 
    while (!s3eDeviceCheckQuitRequest()) { 
     //Update the input systems 
     s3eKeyboardUpdate(); 
     s3ePointerUpdate(); 


    // Your rendering/app code goes here. 


    // Sleep for 0ms to allow the OS to process events etc. 
     s3eDeviceYield(0); 
    } 

    destroy(); 

    //Terminate modules being used 

    // Return 
    return 0; 
} 

ist und hier ist die html/js für die Webansicht

<!DOCTYPE html> 
<html> 
<head> 
    <title>Storage Spike</title> 
</head> 
<body onload="main();"> 
    <div>Loaded value:<span id="loadedKey">(loaded value goes here)</span></div> 
    <input type="text" id="inputKey" value="123key" placeholder="enter key to save"/> 
    <button id="saveKey">Save</button> 
    <button id="loadKey">Load</button> 
    <br> 
    <script> 
    function main() 
    { 
     var saveKey = document.getElementById("saveKey"); 
     var loadKey = document.getElementById("loadKey"); 
     var inputKey = document.getElementById("inputKey"); 

     saveKey.addEventListener("click", function() { 
     var key = inputKey.value; 
     s3e.exec("saveKey|" + key); 
     }); 

     loadKey.addEventListener("click", function() { 
     s3e.exec("loadKey"); 
     }); 

    } 

    function dataLoaded(data, type) 
    { 
     console.log(data); 
     console.log(type); 
     var loadedKey = document.getElementById("loadedKey"); 
     if(type === "key") 
     loadedKey.innerHTML = data; 
     else 
     console.log("type error"); 
    } 

    </script> 
</body> 
</html> 

Jede Hilfe wäre sehr dankbar,

Mit freundlichen Grüßen

Antwort

0

Das Problem ist, dass Sie versuchen, direkt zu speichern eine Instanz von std :: string.

Eine std :: string-Instanz ist nichts anderes als drei Zeiger, die den Speicher beschreiben, den sie zum Speichern der eigentlichen Zeichenfolgedaten verwendet. Wenn die Anwendung geschlossen oder der Speicher zum Speichern der Daten freigegeben wird, verlieren diese Zeiger alle Bedeutung.

Sie müssen die tatsächlichen Zeichenkettendaten in s3eSecureStorage speichern, damit sie bestehen bleiben. Um dies zu tun, müssen Sie die std :: string-Instanz serialisieren. Eine einfache Möglichkeit zur Serialisierung besteht darin, zuerst die Länge der Zeichenfolge zu speichern und dann die tatsächlichen Zeichenfolgedaten zu speichern.

Um serialisiert werden und die Zeichenfolge zu s3eSecureStorage speichern, könnten Sie dies tun:

std::string input = "exampledata"; 
uint16 inputSize = static_cast<uint16>(input.size()); 
uint16 bufferSize = static_cast<uint16>(sizeof(uint16) + inputSize); 
buffer = new char[bufferSize]; 
std::memcpy(buffer, &inputSize, sizeof(uint16)); 
std::memcpy(buffer + sizeof(uint16), input.c_str(), inputSize); 
s3eSecureStoragePut(buffer, bufferSize); 
delete[] buffer; 

Und die Daten von s3eSecureStorage zu erhalten und die Zeichenfolge deserialisiert, können Sie dies tun:

std::string output; 
uint16 dataSize = 0; 
s3eSecureStorageGet(&dataSize, sizeof(uint16)); 
if (dataSize > 0) { 
    uint16 bufferSize = static_cast<uint16>(dataSize + sizeof(uint16)); 
    char* buffer = new char[bufferSize]; 
    s3eSecureStorageGet(buffer, bufferSize); 
    output.resize(dataSize); 
    std::memcpy(&output[0], buffer + sizeof(uint16), dataSize); 
    delete[] buffer; 
} 

Wenn Wenn Sie mehrere Werte speichern möchten, muss die Serialisierung etwas komplizierter sein, aber die Grundidee ist die gleiche.

Natürlich müssen Sie auch eine Art von Fehlerbehandlung verwenden, wenn in s3eSecureStorage nichts gespeichert ist.

Der Grund dafür, dass der von Ihnen gepostete Code in einer einzigen Ausführung Ihrer App funktioniert, ist, dass Sie die SStoreData-Instanz mit new zugewiesen und nie freigegeben haben. Wenn Sie die Zeiger von s3eSecureStorage zurückgeladen haben, verweisen sie immer noch auf den zugewiesenen Speicher, der die Zeichenfolgedaten enthielt.

Verwandte Themen