Import an existing SQLite database into an iOS Phonegap app - sqlite

I've an existing SQLite database called data_items.sqlite. This database includes about 10 tables and some initial data which I would like to import into XCode to open the database with the Phonegap Plugin in this way:
function onDeviceReady() {
var db = window.sqlitePlugin.openDatabase("data_items.sqlite", "1.0", "PhoneGap Demo", 200000);
...
}
How can I import the datafile? Where do I have to copy the file?

First create database as u used name data_items.sqlite and remove .sqlite extension. Then drag this db at Resources directory in xCode and follow next .
Choose option for adding file box will appear
check checkbox says 'Copy items into destination group's folder (if needed)' and finish.
You will see the Database file as sub list of Resources Directory
Sorry I don't have enough reputation to post images here
Now follow the link to copy this database file into location
How to copy sqlite database when application is launched in iOS?
I used the following code before the #end at last line in AppDelegate.m
- (void) copyDatabaseIfNeeded{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
_dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:_dbPath];
if(!success){
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"data_items"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:_dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}}
/********* Database Path *********/
- (NSString *) getDBPath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:#"data_items"];
}
And Copy the line
[self copyDatabaseIfNeeded];
after the code
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
CGRect screenBounds = [[UIScreen mainScreen] bounds];
That's it. Use your code
function onDeviceReady() {
var db = window.sqlitePlugin.openDatabase("data_items", "1.0", "data_items", 200000);
...
}
You can also edit database directly in from the copied location. Use following link
Where does the iPhone Simulator store its data?

It appears not to be possible to access the assets folder from PhoneGap, so you have to write a native plugin to copy the database file:
Prepopulate SQLite DataBase in PhoneGap Application

Related

How to upload an image file in a background session (iOS)?

I am unable to upload an image from my device's Photos in a background session. When I call [session uploadTaskWithRequest:req fromFile:nsurl] the system immediately complains by sending
Failed to issue sandbox extension for file file:///var/mobile/Media/DCIM/103APPLE/IMG_3984.JPG, errno = 1
to the console. (A similar Stack Overflow issue is here)
However, if I create my NSURLSessionConfiguration with [NSURLSessionConfiguration defaultSessionConfiguration] (instead of [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:id], which I need) and if I construct an NSData object out of the NSURL and upload that instead of uploading straight from a file (which is required by a background session) then the upload succeeds. Btw I'm uploading files into our Rackspace Cloud account, and am able to do this successfully with a simple Postman PUT.
The problem occurs in my uploadObject method, which looks like:
-(void) uploadObject:(NSURL*)urlToBeUploadedIn
{
NSDictionary *headers = #{ #"x-auth-token": state.tokenID,
#"content-type": #"image/jpeg",
#"cache-control": #"no-cache" };
// create destination url for Rackspace cloud upload
NSString *sURL = [NSString stringWithFormat:#"%#/testing_folder/%#.jpg", state.publicURL, [state generateImageName]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:sURL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
[request setHTTPMethod:#"PUT"];
[request setAllHTTPHeaderFields:headers];
self.sessionIdentifier = [NSString stringWithFormat:#"my-background-session"];
// NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; // when I use this instead of the line below the sandbox error goes away
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:self.sessionIdentifier];
self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromFile:urlToBeUploadedIn];
[uploadTask resume];
}
My call that invokes uploadObject: looks like:
PHFetchResult *fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:state.arrImagesToBeUploaded options:nil];
PHAsset *phAsset = [fetchResult objectAtIndex:0]; // yes the 0th item in array is guaranteed to exist, above.
[phAsset requestContentEditingInputWithOptions:nil
completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
NSURL *imageURL = contentEditingInput.fullSizeImageURL;
[self uploadObject:imageURL];
}];
Btw I first validate the NSURL I send to uploadObject: with a call to fileExistsAtPath: so I know my reference to the file is good. Finally, my delegate calls
(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)dataIn
(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error does get invoked, although the data
do get called by the server (although the response won't parse) so, I am getting something back from the server which never correctly receives the image.
A solution is to first copy the image to be uploaded into the app's sandbox. I used:
NSError *err;
BOOL bVal = [myNSDataOb writeToURL:myDestinationURL options:0 error:&err];
and copied into my app's 'Documents' directory, but one might also use:
NSError *err;
BOOL bVal = [[NSFileManager defaultManager] copyItemAtURL:myImageURL toURL:myDestinationURL error:&err];

Is there any way to remove encryption from an existing Realm database?

We are using the Objective-C version of Realm, version 2.0.2. The database is currently encrypted and is in the field.
Intermittent crashes on the startup of Realm have been occurring, with an error message of "Unable to open a Realm at path ... Realm file decryption failed". We are at the latest version available of Realm, and have not been able to find a solution.
We don't really need the database to be encrypted on the device, so we would like to consider removing the encryption. Is this an option, and if so, how would we migrate the existing encrypted databases?
You can use writeCopyToURL:encryptionKey:error: with a nil encryption key to write an unencrypted copy, and then move that over the original file:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
RLMRealmConfiguration *confg = [[RLMRealmConfiguration alloc] init];
config.encryptionKey = ...;
NSURL *tempUrl = [NSURL URLWithString:[NSTemporaryDirectory() stringByAppendingPathComponent:"temp.realm"]];
// Open the Realm within an autoreleasepool so that it's closed before we try
// to overwrite the original file
#autoreleasepool {
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
[realm writeCopyToURL:tempUrl encryptionKey:nil error:nil];
}
[[NSFileManager defaultManager] moveItemAtURL:tempUrl toURL:config.fileUrl error:nil];
// ... other didFinishLaunchingWithOptions things ...
return YES;
}

.icloud files on iCloud Drive with NSFileManager

I use theses function to read out the directory content of my app iCloud folder :
+(NSArray *)getiCloudFileList:(NSString *)icloudPath strMask:(NSString *)strMask {
NSError *error;
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSArray *directoryContent = [fileManager contentsOfDirectoryAtPath:icloudPath error:&error];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF like[cd] %#", strMask];
return [directoryContent filteredArrayUsingPredicate:predicate];
}
This function works fine if the app creates the files. If I copy a file with the Mac OS X Finder into the app folder, for example test1.txt in the directoryContent Array I get the result .test1.txt.icloud.
Gives there another way to get the directory content of an app iCloud folder without the .icloud extension or how can I copy files to an app iCloud folder without the .icloud extension ?

Downloading images from server and saving into Database

I have to download images and save it into my local database. So I am storing the images in NSData and than inserting it into local database. But there are atleast 50 images coming from the server so storing the images into NSData and then inserting into local database it taking more time. Is there any solution so that it will consume less time.
Please suggest me.
The more common way to handle image download from the internet is just cache it to the memory(NSURLCache) or disk(SDWebImageView). and only save the 'image url' to the database.
The Cache mechanism will find the image next image you use that URL.
Try to save the files on the disc, and put file paths into data base instead of inserting BLOBs into database
In another words:
Your database will contain images metadata and absolute paths to files
You can do even this:
Create file path
While downloading your image append bytes to the file at this
created file path ( several ways to do - manually by using
NSURLConnection, or use some libs like AFHTTPConnection with NSStream
attached)
Check if everything is OK, then put the file path string into your
database or clean the file and report about error
But it is better to:
Download file to the temporary directory
Check if everything is ok, then move to the permanent directory and store file path in data base
Clean your temporary directory if needed
Clean your temporary directory regulary (By the way, iOS will clean it sometimes)
just try with HCDownload it is a component that you use for downloading image from url. just download this class and use below code it is very easy. once your download is complete then delegate method finishedDownloadingURL is called for all images one by one then store its path (path of image where you stored) on database.
HCDownload
use this as describe below.
.h file
#import "HCDownloadViewController.h"
#interface HomeViewController_iPhone : UIViewController<HCDownloadViewControllerDelegate>
{
HCDownloadViewController *tblDownloadHairStyle;
}
#property (nonatomic,retain) HCDownloadViewController *tblDownloadHairStyle;
.m file
#synthesize tblDownloadHairStyle;
- (void)viewDidLoad
{
[super viewDidLoad];
tblDownloadHairStyle=[[HCDownloadViewController alloc] init];
tblDownloadHairStyle.delegate=self;
}
//Where you download the image
[self createDocumentDirectory:#"MyFolder"]; //create folder for save photo
NSString *pathHair=[self getDocumentDirectoryPath:#"MyFolder"];
tblDownloadHairStyle.downloadDirectory = pathHair;
// your other code just get the image path
NSString *strimage_path=[hairDictonary objectForKey:#"image_path"];
strimage_path=[NSString stringWithFormat:#"http://yoururr.com/%#",strimage_path];
[tblDownloadHairStyle downloadURL:[NSURL URLWithString:strimage_path] userInfo:hairDictonary];
#pragma mark-
#pragma mark-HCDownloadViewController Delegate Method
- (void)downloadController:(HCDownloadViewController *)vc startedDownloadingURL:(NSURL *)url userInfo:(NSDictionary *)userInfo {
NSLog(#"startedDownloadingURL=%#",url);
}
- (void)downloadController:(HCDownloadViewController *)vc finishedDownloadingURL:(NSURL *)url toFile:(NSString *)fileName userInfo:(NSDictionary *)userInfo {
NSLog(#"finishedDownloadingURL =%#",url);
}
- (void)downloadController:(HCDownloadViewController *)vc failedDownloadingURL:(NSURL *)url withError:(NSError *)error userInfo:(NSDictionary *)userInfo {
NSLog(#"failedDownloadingURL=%#",url);
}
#pragma mark - File Functions - Document Functions
-(void)createDocumentDirectory:(NSString*)pStrDirectoryName
{
NSString *dataPath = [self getDocumentDirectoryPath:pStrDirectoryName];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:NULL];
}
-(NSString*)getDocumentDirectoryPath:(NSString*)pStrPathName
{
NSString *strPath = #"";
if(pStrPathName)
strPath = [[kAppDirectoryPath objectAtIndex:0] stringByAppendingPathComponent:pStrPathName];
return strPath;
}
Edit
another simple way is
ImageDownload

Preload sqlite database creating by UIManagedDocument, running Ok in iphone simulator, refusing to work in iphone Device

I've been working on this problem for a week, and I googled and searched stack overflow, read about 40 posts, still can't fix my problem. here is what i did:
1.I wrote a testing app to create the sqlite database, and preload it with data.
2.I create myApp, and copied the preloaded DB to resource folder.
3.I wrote the following code to get the DB:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (!self.myDataBase) {
NSURL *url = [self localDocumentsDirectoryURL];
url = [url URLByAppendingPathComponent:#"myDB/"];
self.myDataBase = [[UIManagedDocument alloc] initWithFileURL:url];
}
return YES;
}
-(NSURL*)localDocumentsDirectoryURL {
static NSURL *localDocumentsDirectoryURL = nil;
if (localDocumentsDirectoryURL == nil) {
NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,NSUserDomainMask, YES ) objectAtIndex:0];
localDocumentsDirectoryURL = [NSURL fileURLWithPath:documentsDirectoryPath];
}
return localDocumentsDirectoryURL;
}
- (void)useDocument
{
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.ICCarDataBase.fileURL path]])
{
[self.ICCarDataBase saveToURL:self.ICCarDataBase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {}];
}
else
{
[self.ICCarDataBase openWithCompletionHandler:^(BOOL success) {}];
}
}
- (void) setICCarDataBase:(UIManagedDocument *)carDataBase
{
if (_ICCarDataBase != carDataBase) {
_ICCarDataBase = carDataBase;
[self useDocument];
}
}
Then when I run myApp in Simulator, myApp successfully get the DB data, and when I run it in my iPhone, the myApp can't get the DB data.
I don't know if the SDK version matters, coz, the simulator is iphone 5.1, and my iPhone is 5.0 (jailbreak). And I don't use any 5.1 specific function in my App.
Some says that you should copy the DataBase to document dir first for it to work, I've tried the solution, still works ok in simulator, but no data in iPhone. Plus, I looked into iphone folders using iTool, myDB folder is already in the document dir.The post suggest the solution is here:Pre-load core data database in iOS 5 with UIManagedDocument
Other says I should use persistentStoreCoordinator directly. But I think UIManagedDocument could work in my situation, since it create a implicit persistentStoreCoordinator itself.
Any suggestion about what's wrong with myApp?
And anyone can tell me why ios wrap the sqlite DB with two layers of folders, and name the actual sqlite db persisentStore?
I've solved this problem, thanks to this postiPhone: Can access files in documents directory in Simulator, but not device
In this post he referenced this blog :Xcode resource groups and folder references when building for iPhone
After solving my problem, I've come to realize the reason that preload sqlite database won't work in device is: when Xcode copy database to the device from the bundle, the folder layers(myDB/StoreContent/persistentStore) wrapping the persistentStore is removed. So there is only a persistentStore file mixed with all other files in the device in the myApp.app bundle. And when you use UIManagedDocument to access sqlite database, it can only work with sqlite in such directory structure: myDB/StoreContent/persistentStore. So, with only a naked persistentStore file, the UIManagedDocument will create a whole new directory structure for you, with an empty persistentStore in it.
If someone can suggest a way for UIManagedDocument to work with the persistentStore file without folder layers, I would be interested.
And I use this code to access the DB after I successfully replicate the directory structure in my device bundle:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (!self.myDataBase) {
NSURL *url = [[NSBundle mainBundle] resourceURL];
url = [url URLByAppendingPathComponent:#"myDB/"];
self.myDataBase = [[UIManagedDocument alloc] initWithFileURL:url];
}
return YES;
}

Resources