How can I replace an exising file into the assets folder with a refresh stuff? - c++

I'm develepping a BB10 mobile application using the momentics IDE.
I'm trying to save somes images coming from server into the "assets/images" folder using the Qt QFile object (you can see the code below) :
m_file = new QFile(argSavingFilePath);
if (m_file->exists()) {
m_file->remove();
}
m_file->open(QIODevice::WriteOnly);
m_file->write(argDataLoaded);
m_file->close();
m_file->~QFile();
It seems that is working but even if I exit out of the screen in question with the back button and then return it still doesn't show the latest image. It only works when I exit the app completely and launch a new instance.
According to this forum [link], they said :
"What's happening is that when you first load the image it gets read from the file system and then cached in memory. The app never goes back to re-read the image from the file. You would have to initiate that yourself."
How should I initiate the cashed memory myself ? is this the only solution ?

Whether the data is cached in memory or not is immaterial. The asset directory, in fact everything below and including the app directory is protected and immutable.
If you want to store data from a server the place to put it would be in data if you want it to persist, or tmp if not. Data in the tmp director is subject to removal by the OS when storage is needed for other things.
See: https://developer.blackberry.com/native/documentation/cascades/device_platform/data_access/file_system.html

Related

cfapi: CfDehydratePlaceholder seems to be stucked

My target is, that files can be hydrated or dehydrated on user request via the Explorer "free up space" or "Always keep on Device" ContextMenu entry. In case I create a new placeholder file that is dehydrated from the beginning, everything works and I can hydrate it via the callback mechanics. But the way around does not work for me. Inside of the Explorer the file will be marked as UnPinned and the file will be marked as syncing, but my application does not receive any callback from CF_CALLBACK_TYPE_NOTIFY_DEHYDRATE or CF_CALLBACK_TYPE_NOTIFY_DEHYDRATE_COMPLETION. Then I wanted to do it manually with CfDehydratePlaceholder, but exactly the same behaviour. Nothing happens and the file remains in the state, syncing. Even if I used CfSetInSyncState to set the state to CF_IN_SYNC_STATE_IN_SYNC it remains to be in the state syncing.
Now I wanted to implement a minimal example with the help of Cloud Mirror Example, but I realized it has the same behaviour. When I try to dehydrate a file again exactly the same happens there as well. From my perspective, it feels for me like cfapi expects an ack from the cloud service, which it never gets.
But in OneDrive everything works like expected. What I am missing? Did I have to set some specific settings?
I had a misunderstanding of the whole API and here is how I understand the API now, to help other people, who are struggling with it.
You have to register your sync root and connecting your app to it. In case of connecting it, you will receive a CF_CONNECTION_KEY, which is needed to communicate with the virtual filesystem. Then you can add extended attributes to all files inside of your sync root. The most important are custom attributes you can choose by yourself to identify the file object by your app if needed and then the PinState and SyncState. Mostly the SyncState don't have to be changed by the app, besides marking a file as synced after it was processed by the app. (you can do it at the moment you update your custom attributes) Because in case a file changed, the SyncState will automatically be changed. The PinState declares which final state a file should have. For example UNPINNED means, that the file should be dehydrated, and PINNED the opposite. It does not mean, that the file necessarily has already this state. My misunderstanding was, that I thought in case I unpinned a file, it will be automatically dehydrated. Or in case I pinned a placeholder I will receive a request via the callback function I mentioned in my question. But this is not the case. Your app needs to find out via a FileWatcher (i can recommend my own created FileWatcher project: https://github.com/neXenio/panoptes) that the file attribute of specific files was changed. Then your app has to process every step. Like already mentioned in case of dehydrating, the app needs to call CfDehydratePlaceholder. In case of hydrating, you need to open a transfer session via CfGetTransferKey and then hydrate (send the data to the empty file) via the method CfExecute, where you need the connection key and the transfer key. And that's are the basics. There is much more to tell about it, but I guess with this beginning, everybody can figure it out by himself.

Possible to make QML application "offline capable" using caches?

I'm trying to make one of my QML apps "offline capable" - that means I want users to be able to use the application when not connected to the internet.
The main problem I'm seeing is the fact that I'm pretty much pulling a QML file with the UI from one of my HTTP servers, allowing me to keep the bulk of the code within reach and easily updatable.
My "main QML file" obviously has external dependencies, such as fonts (using FontLoader), images (using Image) and other QML components (using Loader).
AFAIK all those resources are loaded through the Qt networking stack, so I'm wondering what I'll have to do to make all resources available when offline without having to download them all manually to the device.
Is it possible to do this by tweaking existing/implementing my own cache at Qt/C++ level or am I totally on the wrong track?
Thanks!
A simple solution is to invert the approach: include baseline files within your application's executable/bundle. Upon first startup, copy them to the application's data directory. Then, whenever you have access to your server, you can update the data directory.
All modifications of the data directory should be atomic - they must either completely succeed, or completely fail, without leaving the data directory in an unusable state.
Typically, you'd create a new, temporary data folder, and copy/hardlink the files there, and download what's needed, and only once everything checks out you'd swap the old data directory with the new one.
Letting your application access QML and similar resources directly online is pretty much impossible to get right, unless you insist on explicitly versioning all the resources and having the version numbers in the url.
Suppose your application was started, and has loaded some resources. There are no guarantees that the user has went to all the QML screens - thus only some resources will be loaded. QML also makes no guarantees as to how often and when will the resources be reloaded: it maintains its own caches, after all. Sometime then you update the contents on the server. The user proceeds to explore more of the application after you've done the changes, but now the application he experiences is a frankenstein of older and newer pieces, with no guarantees that these pieces are still meant to work together. It's a bad idea.

iOS iCloud not restoring after deleting App

I'm trying to get the key value store in iCloud to work and I'm running into an odd problem.
I store data using:
[[NSUbiquitousKeyValueStore defaultStore] setObject:#"SomeValue" forKey:#"SomeKey"];
[[NSUbiquitousKeyValueStore defaultStore] synchronize];
I read the data using:
someValue = [[NSUbiquitousKeyValueStore defaultStore] objectForKey:#"SomeKey"];
This all works great when I start and stop the App. Values are stored and I see the values being read. Everything is fine.
Then I delete the App from my device and load it again (via xcode). Now, I don't see any data come down from the cloud.
Isn't one of the main points of iCloud that you can delete an App and then recover data (in my case, game save state)?
Why does deleting my App and reinstall it (running it in xcode) cause all the iCloud data to vanish?
I am running this on the device, not the simulator. I've tried it on iOS 5 and iOS 6 with the same results.
NSUbiquitousKeyValueStore seems really simple to use, but I'm clearly doing something wrong.
First, try synchronizing before you read the data to make sure the latest updates have come in from iCloud.
Do you have another device on which you can test? If so, run the writing code on one device and then run the reading code on another device. It could be that even though you're using NSUbiquitiousKeyValueStore, it isn't actually syncing when you think it is. The reason that it would work on your device is that the key value store is available locally, but not in iCloud. So when you delete your app you're deleting the local (and also your only) copy of the data.
I found you need to register for the NSUbiquitousKeyValueStoreDidChangeExternallyNotification notification to make the sync work. It wouldn't persist data after a reinstall without it.
- (void)iCloudKeyStateChanged:(NSNotification*)n {
}
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
...
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(iCloudKeyStateChanged:) name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:nil];
}

How can I read the source URL of a file downloaded with FireFox from an external application?

I have an C++ app I built which is registered as the default handler for a file with a specific extension. So when I download one of these files with Firefox from a website, it downloads it to a temp directory and then shell executes my app while passing the full path to the downloaded file on the command line.
What is the best way to figure out from the external app what the original download url of the file was, given only it's path on disk? Can I use XPCOM API calls to inspect the FireFox download manager database?
I've figured out that this data get's stored in the "%APPData%\Mozilla\Firefox\($profile)\downloads.sqlite" file which is a SqlLite db file, but I really rather not try to open this file directly as FireFox has an open write handle to the file while running.
After perusing the Mozilla developer center for a while, I ran accross the nsIDownloadManager service, which seems to be just the thing. But I can't seem to get access to it from XPCOM in a separate process?
Here's the code I am using:
nsresult rv;
//init XPCOM
nsCOMPtr<nsIServiceManager> servMgr;
rv = NS_InitXPCOM2(getter_AddRefs(servMgr), nsnull, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
//Get a download manager instance
nsCOMPtr<nsIDownloadManager> downloadMgr;
rv = servMgr->GetServiceByContractID(NS_DOWNLOADMANAGER_CONTRACTID,
nsIDownloadManager::GetIID(), getter_AddRefs(downloadMgr));
NS_ENSURE_SUCCESS(rv, rv);
When I run this, the GetServiceByContractID() call returns 0x8007000e, which is defined in nsError.h as NS_ERROR_OUT_OF_MEMORY. (which I find very weird).
Any ideas here? Am I barking up the right tree?
No, you can't access Firefox's XPCOM objects from an external process, and you also shouldn't open the sqlite database while Firefox has it open. I don't know that there's any straightforward way to do what you want without writing a Firefox extension that has access to the Firefox internals.
I'm a little hazy on the details right now, but, assuming that your download is served with a custom MIME type, it's possible to register a handler for that type; your handler can then cancel the download and pass the URL to your application.

How do I open a new document in running application without opening a new instance of the application?

I have a situation that has been partially covered by other answers at SO, but I cannot find a complete answer. In short, we are trying to use URL's for our specific data types that when double clicked will open up our application and load those data sets into that app. We have this part working.
(for example, an URL might look like this: resource://shaders/basic_shader.hlsl)
What we would like to do is to prevent new instances of the application from opening when a new URL is double clicked. For example, let's say we have a URL that opens up a shader in our shader editor. When clicking this resource URL, it will open our shader editor. When a new shader URL is clicked, we'd like to be able to open up the shader in the currently running application and have it open up the new shader in a new tab in our editor.
We can easily detect if another instance of our application is running. The problem that we don't know how to easily solve is how to tell the currently running application to open up this new file for editing. This behavior is very much like the Apple Finder.
In unix, you could emulate this behavior by having your application open some named pipe and then new apps could check if this pipe is active and then send the document data down the pipe. Is there a more standard windows way of achieving this behavior?
We need a C/C++ solution. Thanks.
Named pipe is the best way.
First instance of your application opens the pipe and listens to it (use PIPE_ACCESS_INBOUND as dwOpenMode and the same code will also allow you to detect running instances).
All subsequent instances check that they are not alone, send command line argument to the pipe and shut down.
Create a named mutex when application launches as David Grant said, then before displaying the UI for the second URL, check for this mutex, if it is already created then just quit by passing the new URL to the first launched application (Have interface in the application to set the URL and tell to redirect programatically)
You can't avoid the program associated with the url to be executed.
The "windows" solutions would be to send a message (via DDE in the old days but maybe there is something more "modern" now) to the previously running application with the url then quit ...
You can acquire a named mutex upon startup and enforce it that way.
http://www.google.com/search?hl=en&q=named+mutex+single+instance
CreateMutex on MSDN
I got this working pretty well for my C++ MFC application by following Joseph Newcomer's tutorial here. He uses a named mutex that is checked on startup and a message sent to the already-running application with the new resource to be opened.