Currently, I'm using Google Drive Android API, to store my Android app data, to Google Drive App Folder.
This is what I'm doing when saving my application data
Generate a checksum for the current local zip file.
Search in Google Drive App Folder, to see whether there is an existing App Folder zip file.
If there is, overwrite the content of existing App Folder zip file, with current local zip files. Also, we will rename existing App Folder zip filename, with the latest checksum.
If there isn't existing App Folder zip file, generate a new App Folder zip file, with local zip file's content. We will use the latest checksum as App Folder zip filename.
Here's the code which performs the above-mentioned operations.
Generate new App Folder zip file, or update existing App Folder zip file
public static boolean saveToGoogleDrive(GoogleApiClient googleApiClient, File file, HandleStatusable h, PublishProgressable p) {
// Should we new or replace?
GoogleCloudFile googleCloudFile = searchFromGoogleDrive(googleApiClient, h, p);
try {
p.publishProgress(JStockApplication.instance().getString(R.string.uploading));
final long checksum = org.yccheok.jstock.gui.Utils.getChecksum(file);
final long date = new Date().getTime();
final int version = org.yccheok.jstock.gui.Utils.getCloudFileVersionID();
final String title = getGoogleDriveTitle(checksum, date, version);
DriveContents driveContents;
DriveFile driveFile = null;
if (googleCloudFile == null) {
DriveApi.DriveContentsResult driveContentsResult = Drive.DriveApi.newDriveContents(googleApiClient).await();
if (driveContentsResult == null) {
return false;
}
Status status = driveContentsResult.getStatus();
if (!status.isSuccess()) {
h.handleStatus(status);
return false;
}
driveContents = driveContentsResult.getDriveContents();
} else {
driveFile = googleCloudFile.metadata.getDriveId().asDriveFile();
DriveApi.DriveContentsResult driveContentsResult = driveFile.open(googleApiClient, DriveFile.MODE_WRITE_ONLY, null).await();
if (driveContentsResult == null) {
return false;
}
Status status = driveContentsResult.getStatus();
if (!status.isSuccess()) {
h.handleStatus(status);
return false;
}
driveContents = driveContentsResult.getDriveContents();
}
OutputStream outputStream = driveContents.getOutputStream();
InputStream inputStream = null;
byte[] buf = new byte[8192];
try {
inputStream = new FileInputStream(file);
int c;
while ((c = inputStream.read(buf, 0, buf.length)) > 0) {
outputStream.write(buf, 0, c);
}
} catch (IOException e) {
Log.e(TAG, "", e);
return false;
} finally {
org.yccheok.jstock.file.Utils.close(outputStream);
org.yccheok.jstock.file.Utils.close(inputStream);
}
if (googleCloudFile == null) {
// Create the metadata for the new file including title and MIME
// type.
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
.setTitle(title)
.setMimeType("application/zip").build();
DriveFolder driveFolder = Drive.DriveApi.getAppFolder(googleApiClient);
DriveFolder.DriveFileResult driveFileResult = driveFolder.createFile(googleApiClient, metadataChangeSet, driveContents).await();
if (driveFileResult == null) {
return false;
}
Status status = driveFileResult.getStatus();
if (!status.isSuccess()) {
h.handleStatus(status);
return false;
}
} else {
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
.setTitle(title).build();
DriveResource.MetadataResult metadataResult = driveFile.updateMetadata(googleApiClient, metadataChangeSet).await();
Status status = metadataResult.getStatus();
if (!status.isSuccess()) {
h.handleStatus(status);
return false;
}
}
Status status;
try {
status = driveContents.commit(googleApiClient, null).await();
} catch (java.lang.IllegalStateException e) {
// java.lang.IllegalStateException: DriveContents already closed.
Log.e(TAG, "", e);
return false;
}
if (!status.isSuccess()) {
h.handleStatus(status);
return false;
}
status = Drive.DriveApi.requestSync(googleApiClient).await();
if (!status.isSuccess()) {
// Sync request rate limit exceeded.
//
//h.handleStatus(status);
//return false;
}
return true;
} finally {
if (googleCloudFile != null) {
googleCloudFile.metadataBuffer.release();
}
}
}
Search for existing App Folder zip file
private static String getGoogleDriveTitle(long checksum, long date, int version) {
return "jstock-" + org.yccheok.jstock.gui.Utils.getJStockUUID() + "-checksum=" + checksum + "-date=" + date + "-version=" + version + ".zip";
}
// https://stackoverflow.com/questions/1360113/is-java-regex-thread-safe
private static final Pattern googleDocTitlePattern = Pattern.compile("jstock-" + org.yccheok.jstock.gui.Utils.getJStockUUID() + "-checksum=([0-9]+)-date=([0-9]+)-version=([0-9]+)\\.zip", Pattern.CASE_INSENSITIVE);
private static GoogleCloudFile searchFromGoogleDrive(GoogleApiClient googleApiClient, HandleStatusable h, PublishProgressable p) {
DriveFolder driveFolder = Drive.DriveApi.getAppFolder(googleApiClient);
// https://stackoverflow.com/questions/34705929/filters-ownedbyme-doesnt-work-in-drive-api-for-android-but-works-correctly-i
final String titleName = ("jstock-" + org.yccheok.jstock.gui.Utils.getJStockUUID() + "-checksum=");
Query query = new Query.Builder()
.addFilter(Filters.and(
Filters.contains(SearchableField.TITLE, titleName),
Filters.eq(SearchableField.TRASHED, false)
))
.build();
DriveApi.MetadataBufferResult metadataBufferResult = driveFolder.queryChildren(googleApiClient, query).await();
if (metadataBufferResult == null) {
return null;
}
Status status = metadataBufferResult.getStatus();
if (!status.isSuccess()) {
h.handleStatus(status);
return null;
}
MetadataBuffer metadataBuffer = null;
boolean needToReleaseMetadataBuffer = true;
try {
metadataBuffer = metadataBufferResult.getMetadataBuffer();
if (metadataBuffer != null ) {
long checksum = 0;
long date = 0;
int version = 0;
Metadata metadata = null;
for (Metadata md : metadataBuffer) {
if (p.isCancelled()) {
return null;
}
if (md == null || !md.isDataValid()) {
continue;
}
final String title = md.getTitle();
// Retrieve checksum, date and version information from filename.
final Matcher matcher = googleDocTitlePattern.matcher(title);
String _checksum = null;
String _date = null;
String _version = null;
if (matcher.find()){
if (matcher.groupCount() == 3) {
_checksum = matcher.group(1);
_date = matcher.group(2);
_version = matcher.group(3);
}
}
if (_checksum == null || _date == null || _version == null) {
continue;
}
try {
checksum = Long.parseLong(_checksum);
date = Long.parseLong(_date);
version = Integer.parseInt(_version);
} catch (NumberFormatException ex) {
Log.e(TAG, "", ex);
continue;
}
metadata = md;
break;
} // for
if (metadata != null) {
// Caller will be responsible to release the resource. If release too early,
// metadata will not readable.
needToReleaseMetadataBuffer = false;
return GoogleCloudFile.newInstance(metadataBuffer, metadata, checksum, date, version);
}
} // if
} finally {
if (needToReleaseMetadataBuffer) {
if (metadataBuffer != null) {
metadataBuffer.release();
}
}
}
return null;
}
The problem occurs, during loading application data. Imagine the following operations
Upload zip data to Google Drive App Folder for the first time. The checksum is 12345. The filename being used is ...checksum=12345...zip
Search for zip data from Google Drive App Folder. Able to find the file with filename ...checksum=12345...zip. Download the content. Verify the checksum of content is 12345 too.
Overwrite new zip data to existing Google Drive App Folder file. New zip data checksum is 67890. The existing app folder zip file is renamed to ...checksum=67890...zip
Search for zip data from Google Drive App Folder. Able to find the file with filename ...checksum=67890...zip. However, after downloading the content, the checksum of the content is still old 12345!
Download App Folder zip file
public static CloudFile loadFromGoogleDrive(GoogleApiClient googleApiClient, HandleStatusable h, PublishProgressable p) {
final java.io.File directory = JStockApplication.instance().getExternalCacheDir();
if (directory == null) {
org.yccheok.jstock.gui.Utils.showLongToast(R.string.unable_to_access_external_storage);
return null;
}
Status status = Drive.DriveApi.requestSync(googleApiClient).await();
if (!status.isSuccess()) {
// Sync request rate limit exceeded.
//
//h.handleStatus(status);
//return null;
}
GoogleCloudFile googleCloudFile = searchFromGoogleDrive(googleApiClient, h, p);
if (googleCloudFile == null) {
return null;
}
try {
DriveFile driveFile = googleCloudFile.metadata.getDriveId().asDriveFile();
DriveApi.DriveContentsResult driveContentsResult = driveFile.open(googleApiClient, DriveFile.MODE_READ_ONLY, null).await();
if (driveContentsResult == null) {
return null;
}
status = driveContentsResult.getStatus();
if (!status.isSuccess()) {
h.handleStatus(status);
return null;
}
final long checksum = googleCloudFile.checksum;
final long date = googleCloudFile.date;
final int version = googleCloudFile.version;
p.publishProgress(JStockApplication.instance().getString(R.string.downloading));
final DriveContents driveContents = driveContentsResult.getDriveContents();
InputStream inputStream = null;
java.io.File outputFile = null;
OutputStream outputStream = null;
try {
inputStream = driveContents.getInputStream();
outputFile = java.io.File.createTempFile(org.yccheok.jstock.gui.Utils.getJStockUUID(), ".zip", directory);
outputFile.deleteOnExit();
outputStream = new FileOutputStream(outputFile);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
} catch (IOException ex) {
Log.e(TAG, "", ex);
} finally {
org.yccheok.jstock.file.Utils.close(outputStream);
org.yccheok.jstock.file.Utils.close(inputStream);
driveContents.discard(googleApiClient);
}
if (outputFile == null) {
return null;
}
return CloudFile.newInstance(outputFile, checksum, date, version);
} finally {
googleCloudFile.metadataBuffer.release();
}
}
First, I thought
Status status = Drive.DriveApi.requestSync(googleApiClient).await()
doesn't do the job well. It fails in most of the situation, with error message Sync request rate limit exceeded. In fact, the hard limit imposed in requestSync, make that API not particularly useful - Android Google Play / Drive Api
However, even when requestSync success, loadFromGoogleDrive still can only get the latest filename, but outdated checksum content.
I'm 100% sure loadFromGoogleDrive is returning me a cached data content, with the following observations.
I install a DownloadProgressListener in driveFile.open, bytesDownloaded is 0 and bytesExpected is -1.
If I use Google Drive Rest API, with the following desktop code, I can find the latest filename with correct checksum content.
If I uninstall my Android app and re-install again, loadFromGoogleDrive will able to get the latest filename with correct checksum content.
Is there any robust way, to avoid from always loading cached app data from Google Drive?
I manage to produce a demo. Here are the steps to reproduce this problem.
Step 1: Download source code
https://github.com/yccheok/google-drive-bug
Step 2 : Setup in API console
Step 3: Press button SAVE "123.TXT" WITH CONTENT "123"
A file with filename "123.TXT", content "123" will create in the app folder.
Step 4: Press button SAVE "456.TXT" WITH CONTENT "456"
The previous file will be renamed to "456.TXT", with content updated to "456"
Step 5: Press button LOAD LAST SAVED FILE
File with filename "456.TXT" was found, but the previous cached content "123" is read. I was expecting content "456".
Take note that, if we
Uninstall demo app.
Re-install demo app.
Press button LOAD LAST SAVED FILE, file with filename "456.TXT" and content "456" is found.
I had submitted issues report officially - https://code.google.com/a/google.com/p/apps-api-issues/issues/detail?id=4727
Other info
This is how it looks like under my device - http://youtu.be/kuIHoi4A1c0
I realise, not all users will hit with this problem. For instance, I had tested with another Nexus 6, Google Play Services 9.4.52 (440-127739847). The problem doesn't appear.
I had compiled an APK for testing purpose - https://github.com/yccheok/google-drive-bug/releases/download/1.0/demo.apk
Search on Google Drive is slow.
Why not use properties of the base folder to store id of the zip file?
https://developers.google.com/drive/v2/web/properties
File names on Google Drive are not unique, you can upload multiple files with same names. The File ID returned by Google, however, is unique.
Related
How to get media files and their details with Dropbox API v2 for Android(Java)? I have gone through the documentation for the FileMetadata , but I couldn't find the methods to get file details like file type(e.g. music, video, photo, text, ...) , file's URL and thumbnail.
this is my folders and files list Asyntask:
//login
DbxClientV2 client = DropboxClient.getClient(accessToken);
// Get files and folder metadata from root directory
String path = "";
TreeMap<String, Metadata> children = new TreeMap<>();
try {
try {
result = client.files().listFolder(path);
arrayList = new ArrayList<>();
//arrayList.add("/");
while (true) {
int i = 0;
for (Metadata md : result.getEntries()) {
if (md instanceof DeletedMetadata) {
children.remove(md.getPathLower());
} else {
String fileOrFolder = md.getPathLower();
children.put(fileOrFolder, md);
//if (!fileOrFolder.contains("."))//is a file
arrayList.add(fileOrFolder);
if (md instanceof FileMetadata) {
FileMetadata file = (FileMetadata) md;
//I need something like file.mineType, file.url, file.thumbnail
file.getParentSharedFolderId();
file.getName();
file.getPathLower();
file.getPathDisplay();
file.getClientModified();
file.getServerModified();
file.getSize();//in bytes
MediaInfo mInfo = file.getMediaInfo();//Additional information if the file is a photo or video, null if not present
MediaInfo.Tag tag;
if (mInfo != null) {
tag = mInfo.tag();}
}
}
i++;
}
if (!result.getHasMore()) break;
try {
result = client.files().listFolderContinue(result.getCursor());//what is this for ?
} catch (ListFolderContinueErrorException ex) {
ex.printStackTrace();
}
}
} catch (ListFolderErrorException ex) {
ex.printStackTrace();
}
} catch (DbxException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return result;
If you want media information, you should use listFolderBuilder to get a ListFolderBuilder object. You can use call .withIncludeMediaInfo(true) to set the parameter for media information, and then .start() to make the API call. The results will then have the media information set, where available.
Dropbox API v2 doesn't offer mime types, but you can keep your own file extension to mime type mapping as desired.
To get an existing link for a file, use listSharedLinks. To create a new one, use createSharedLinkWithSettings.
To get a thumbnail for a file, use getThumbnail.
How can i calculate the CheckSum of my APK file in android? I want to calculate the APK checksum and compare it everytime my app. executes to see if some one has modified the binary code? How can i calculate check sum and achieve this?
Updated in 2020 - Google Play can now optimise, repackage and re-sign uploaded .apks (and add security meta data to the .apk) so it's unlikely this tamper check is still valid. Better to use the SafetyNet attestation API to verify the device and in turn your app - just ensure you're verifying the signature offline on your server.
Here's some code to checksum your APK. I wrote and article on adding tamper detections to your apps (which ironically didn't include apk checksum).
private static long getApkFileChecksum(Context context) {
String apkPath = context.getPackageCodePath();
Long chksum = null;
try {
// Open the file and build a CRC32 checksum.
FileInputStream fis = new FileInputStream(new File(apkPath));
CRC32 chk = new CRC32();
CheckedInputStream cis = new CheckedInputStream(fis, chk);
byte[] buff = new byte[80];
while (cis.read(buff) >= 0) ;
chksum = chk.getValue();
} catch (Exception e) {
e.printStackTrace();
}
return chksum;
}
You could also use this to can the sha-256 of your apk...
public static String getApkFileDigest(Context context) {
String apkPath = context.getPackageCodePath();
try {
byte[] hashed= getDigest(new FileInputStream(apkPath), "SHA-256");
return Base64.encodeToString(hashed, Base64.DEFAULT);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
public static final int BUFFER_SIZE = 2048;
public static byte[] getDigest(InputStream in, String algorithm) throws Throwable {
MessageDigest md = MessageDigest.getInstance(algorithm);
try {
DigestInputStream dis = new DigestInputStream(in, md);
byte[] buffer = new byte[BUFFER_SIZE];
while (dis.read(buffer) != -1) {
}
dis.close();
} finally {
in.close();
}
return md.digest();
}
I'm trying to download a database from a server and then use it in my app. My initial situation is that I've got a database in my assets folder and I am trying to download the whole database from a server when the user is clicking a button.
I think I have to use the onUpgrade method but I don't know how I can download the database and then use it or and load it into the assetfolder.
You need to brake the problem into smaller issues.
Make sure that the server side is able to provide you with a web-service with which you'll do the actual download.
It would be ideal if your server would zip your sqlite database in order for you to minimize traffic.
After you have downloaded the db on your device, you'll have to unzip it, if you have taken this approach.
When you get to the point of having the db downloaded and unzipped it's just a matter of connecting to a sqlite db and Android provides api in this regards.
Of-course, all of the above needs to be done in a multithreaded environment, you could also take into account using an Android service.
This is an example of downloading a file from a server, it should help you get an idea, it's not too generic, it works in my environment.
private void handleSelectedItemDownload(final String downloadItem) {
try {
int bufferLength;
long downloadedSize = 0;
long downloadProgressBytes = 0;
final byte[] buffer = new byte[12 * 163840];
this.url = new URL(String.format(AppConstants.SERVICE_BASE_URL + AppConstants.MEDIA_IMAGE_REQUEST_URL_PATH + downloadItem));
InputStream inputStream = this.getStream(downloadedSize);
downloadedSize = this.chunkSize;
if (downloadedSize > 0) {
this.applicationFolder = downloadItem.equals("pictures") ? Utils.getThumbNailsFolder() : Utils.getApplicationFolder();
final File mediaFolder = new File(this.applicationFolder);
mediaFolder.mkdirs();
final File file = new File(mediaFolder, String.format(File.separator + downloadItem + ".zip"));
final FileOutputStream fileOutput = new FileOutputStream(file);
this.actionStatusProgressBar.setProgress(0);
final Message downloadStartMessage = new Message();
downloadStartMessage.what = ACTION_STARTED;
this.actionMessageHandler.sendMessage(downloadStartMessage);
int progressBarMax = (int) (this.totalDownloadSize / 1024);
this.actionStatusProgressBar.setMax(progressBarMax);
while (chunkSize != 0) {
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
downloadProgressBytes += bufferLength;
final Message currentProgressMessage = new Message();
currentProgressMessage.arg1 = (int) (downloadProgressBytes / 1024);
currentProgressMessage.what = ACTION_PROGRESS_VALUE;
this.actionMessageHandler.sendMessage(currentProgressMessage);
}
inputStream.close();
this.urlConnection.disconnect();
inputStream = this.getStream(downloadedSize);
downloadedSize += chunkSize;
}
fileOutput.close();
}
this.urlConnection.disconnect();
this.totalDownloadSize = 0;
} catch (MalformedURLException e) {
Log.e("DOWNLOAD_ERROR", e.getMessage() + e.toString());
this.errorEncountered = true;
this.actionType = IDataActionListener.ACTION_TYPE.ACTION_FAILED;
this.actionMessageHandler.sendEmptyMessage(ERROR_ENCOUNTERED);
} catch (IOException e) {
Log.e("DOWNLOAD_ERROR", e.getMessage() + e.toString());
this.errorEncountered = true;
this.actionType = IDataActionListener.ACTION_TYPE.ACTION_FAILED;
this.actionMessageHandler.sendEmptyMessage(ERROR_ENCOUNTERED);
} catch (Exception e) {
Log.e("DOWNLOAD_ERROR", e.getMessage() + e.toString());
this.errorEncountered = true;
this.actionType = IDataActionListener.ACTION_TYPE.ACTION_FAILED;
this.actionMessageHandler.sendEmptyMessage(ERROR_ENCOUNTERED);
}
}
private InputStream getStream(final long downloadedSize) throws IOException {
this.urlConnection = (HttpURLConnection) this.url.openConnection();
this.urlConnection.setRequestMethod("GET");
this.urlConnection.addRequestProperty("DOWNLOADED_SIZE", String.valueOf(downloadedSize));
final InputStream inputStream = this.urlConnection.getInputStream();
this.chunkSize = this.urlConnection.getContentLength();
if (!Utils.stringIsNullOrEmpty(this.urlConnection.getHeaderField("TOTAL_SIZE"))) {
if (this.totalDownloadSize == 0) {
this.totalDownloadSize = Long.parseLong(this.urlConnection.getHeaderField("TOTAL_SIZE"));
}
}
return inputStream;
}
Afterwards, when you have downloaded your db file, you can just create a SQLiteDatabase object:
final File dbFile = new File(filePath);
if (dbFile.exists()) {
this.localDatabase = SQLiteDatabase.openDatabase(filePath, null, SQLiteDatabase.OPEN_READWRITE);
this.localDatabase.setLocale(Locale.getDefault());
}
I still stick to the opinion that you should also give zipping a thought, you reduce a LOT the traffic and the time spent over network.
Is there any possible way to read the text from a file on Google Drive and store it in a String? This file may contain images as well. I was looking into the Google Drive SDK but they only allow us to download the entire file. How should I go about doing this?
From Files.get() documentation.
private static InputStream downloadFile(Drive service, File file) {
if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) {
try {
HttpResponse resp =
service.getRequestFactory().buildGetRequest(new GenericUrl(file.getDownloadUrl()))
.execute();
return resp.getContent();
} catch (IOException e) {
// An error occurred.
e.printStackTrace();
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
You can convert InputStream to String or File as you want.
I need unzip a .zip file of 2.5mb(1087 files - *.html, *.css and *.db) in android, i have used java.util.zip, it works fine, but i need improve the performance, the unzip process last 1.10 minutes, i need reduce this time.
I have followed some recomendations for improve the performance, for example :
Use BufferedInputStream, FileOutputStream and BufferedOutputStream.
Read the zip in blocks :
byte data[] = new byte[2048];
while ((counter = bisMediaFile.read(data, 0, 2048)) != -1)
{
bosMediaFile.write(data, 0, counter);
}
Is there any way to improve my code?. I was searching third party zip programs to use programatically, for example i tried the 7ZipJBinding, but it looks like android doesn't support this, because i referenced the sevenzipjbinding.jar and sevenzipjbinding-AllPlatforms.jar but i get an error : "Native Libraries Detected in sevenzipjbinding-AllPlatforms". At 7zip homepage there are versions for MAC, Windows, Linux, but i didn't see anything about android.
Could you please recommend any other library to unzip files in android?
This is my all code :
public static void processZipFile(String strBinaryPath,String strExtractPath, String strDestinationDBPath) throws Exception
{
ZipFile zipInFile = null;
try
{
if (strExtractPath != null)
{
zipInFile = new ZipFile(strBinaryPath);
for (Enumeration<? extends ZipEntry> entries = zipInFile.entries(); entries.hasMoreElements();)
{
ZipEntry zipMediaEntry = entries.nextElement();
if (zipMediaEntry.isDirectory())
{
File mediaDir = new File(String.format("%s\\%s", strExtractPath, zipMediaEntry.getName()));
mediaDir.mkdirs();
}
else
{
BufferedInputStream bisMediaFile = null;
FileOutputStream fosMediaFile = null;
BufferedOutputStream bosMediaFile = null;
try
{
String strFileName = String.format("%s\\%s", strExtractPath, zipMediaEntry.getName());
File uncompressDir = new File(strFileName).getParentFile();
uncompressDir.mkdirs();
//if is a database file, extract to other path : android.movinginteractive.com/databases
if(strFileName.contains(".db"))
strFileName = String.format("%s\\%s", strDestinationDBPath, ExtractDBName(zipMediaEntry.getName()));
bisMediaFile = new BufferedInputStream(zipInFile.getInputStream(zipMediaEntry));
fosMediaFile = new FileOutputStream(strFileName);
bosMediaFile = new BufferedOutputStream(fosMediaFile);
int counter;
byte data[] = new byte[2048];
while ((counter = bisMediaFile.read(data, 0, 2048)) != -1)
{
bosMediaFile.write(data, 0, counter);
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (bosMediaFile != null)
{
bosMediaFile.flush();
bosMediaFile.close();
}
if (bisMediaFile != null)
bisMediaFile.close();
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (zipInFile != null)
zipInFile.close();
File flZipToDelete = new File(strBinaryPath);
if(flZipToDelete.exists())
flZipToDelete.delete();
}
}
I'm sure you could find a C or C++ code snippet for unzipping files and run it through the Android NDK. That said, I'm not sure what performance gains you might get.