My app uses an SQLite database and updates it. With every start (or waking up from suspended mode) it connects to my web server and checks for a new database. To authenticate the database, it first only downloads a file containing the MD5 sum of the online database and calculates the MD5 sum of the database on the phone. Only if the sums differ, the new database will be downloaded. This has the nice side effect that it keeps the traffic low.
Sample code for calculatimg the MD5 sum:
#define CHUNK_SIZE 16384
#import <CommonCrypto/CommonDigest.h>
+ (NSString *)md5SumForFileAtPath:(NSString *)path {
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
CC_MD5_CTX md5;
CC_MD5_Init(&md5);
BOOL done = NO;
while(!done)
{
NSData* fileData = [handle readDataOfLength:CHUNK_SIZE];
CC_MD5_Update(&md5, [fileData bytes], [fileData length]);
if ([fileData length] == 0) done = YES;
}
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5_Final(result, &md5);
NSString *digest = [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
result[0], result[1], result[2], result[3],result[4],
result[5], result[6], result[7], result[8], result[9],
result[10], result[11], result[12], result[13],
result[14], result[15]
];
XLog("Checksum for file %@: %@", path, digest);
return digest;
}
However, downloading the entire database is only a good solution if the database is not to large. Additionally, I gzipped the database and extract it after the download.
#import <zlib.h>
+ (void)gunzipFileAtPath:(NSString *)zippedPath toPath:(NSString *)unzippedPath {
gzFile file = gzopen([zippedPath UTF8String], "rb");
FILE *dest = fopen([unzippedPath UTF8String], "w");
unsigned char buffer[CHUNK_SIZE];
int uncompressedLength;
while (uncompressedLength = gzread(file, buffer, CHUNK_SIZE) ) {
if(fwrite(buffer, 1, uncompressedLength, dest) != uncompressedLength || ferror(dest)) {
NSLog(@"error writing data");
}
}
fclose(dest);
gzclose(file);
}
It is perfectly fine to only show the network activity indicator in the status bar and not use a progress bar or other indicator. If the phone's database is up to date, I do not even notify the user, as it is unnecessary information and will only distract him. However, if there is an update, I fade in an overlay of the status bar and display the information for a few seconds. From the feedback of my users, I can tell that they pretty much appreciate this solution.
Do not forget that you add cryptography by calculating the MD5 sum. You have to indicate this to Apple when uploading your next Update. I only had to answer one more question and say that I use encryption only for authentication. The app was approved without any problems.