From a6ca9e6bef7cea43f80c8b212b72d380c4740d8e Mon Sep 17 00:00:00 2001 From: pelya Date: Sun, 9 Nov 2014 23:24:45 +0200 Subject: [PATCH] Support for Google Play expansion files --- changeAppSettings.sh | 2 +- project/java/DataDownloader.java | 121 +++++++++++++++++++++++-------- 2 files changed, 90 insertions(+), 33 deletions(-) diff --git a/changeAppSettings.sh b/changeAppSettings.sh index 79df3eaf7..f4bee0b99 100755 --- a/changeAppSettings.sh +++ b/changeAppSettings.sh @@ -127,7 +127,7 @@ echo "# If you'll start Description with '!' symbol it will be enabled by defaul echo "# If the URL in in the form ':dir/file.dat:http://URL/' it will be downloaded as binary BLOB to the application dir and not unzipped" >> AndroidAppSettings.cfg echo "# If the URL does not contain 'http://' it is treated as file from 'project/jni/application/src/AndroidData' dir -" >> AndroidAppSettings.cfg echo "# these files are put inside .apk package by build system" >> AndroidAppSettings.cfg -echo "# Also please avoid 'https://' URLs, many Android devices do not have trust certificates and will fail to connect to SF.net over HTTPS" >> AndroidAppSettings.cfg +echo "# You can specify Google Play expansion files in the form 'obb:main.12345' or 'obb:patch.12345' where 12345 is the app version, first associated with the file" >> AndroidAppSettings.cfg echo AppDataDownloadUrl=\"$AppDataDownloadUrl\" >> AndroidAppSettings.cfg echo >> AndroidAppSettings.cfg echo "# Reset SDL config when updating application to the new version (y) / (n)" >> AndroidAppSettings.cfg diff --git a/project/java/DataDownloader.java b/project/java/DataDownloader.java index 1f1e35fea..e47fcffc9 100644 --- a/project/java/DataDownloader.java +++ b/project/java/DataDownloader.java @@ -284,22 +284,28 @@ class DataDownloader extends Thread catch( FileNotFoundException e ) {} catch( IOException e ) {}; - HttpResponse response = null, responseError = null; HttpGet request; + HttpResponse response = null, responseError = null; long totalLen = 0; + long partialDownloadLen = 0; CountingInputStream stream; - byte[] buf = new byte[16384]; boolean DoNotUnzip = false; boolean FileInAssets = false; + boolean FileInExpansion = false; String url = ""; - long partialDownloadLen = 0; int downloadUrlIndex = 1; while( downloadUrlIndex < downloadUrls.length ) { Log.i("SDL", "Processing download " + downloadUrls[downloadUrlIndex]); - url = new String(downloadUrls[downloadUrlIndex]); + DoNotUnzip = false; + FileInAssets = false; + FileInExpansion = false; + partialDownloadLen = 0; + totalLen = 0; + + url = new String(downloadUrls[downloadUrlIndex]); if(url.indexOf(":") == 0) { path = getOutFilePath(url.substring( 1, url.indexOf(":", 1) )); @@ -311,7 +317,24 @@ class DataDownloader extends Thread partialDownloadLen = partialDownload.length(); } Status.setText( downloadCount + "/" + downloadTotal + ": " + res.getString(R.string.connecting_to, url) ); - if( url.indexOf("http://") == -1 && url.indexOf("https://") == -1 ) // File inside assets + if( url.indexOf("obb:") == 0 ) // APK expansion file provided by Google Play + { + FileInExpansion = true; + url = url.substring("obb:".length()); + url = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/obb/" + + Parent.getPackageName() + "/" + url + "." + Parent.getPackageName() + ".obb"; + Log.i("SDL", "Fetching file from OBB: " + url); + InputStream stream1 = null; + try { + stream1 = new FileInputStream(url); + stream1.close(); + } catch( Exception e ) { + Log.i("SDL", "Failed to open file: " + url); + downloadUrlIndex++; + continue; + } + } + else if( url.indexOf("http://") == -1 && url.indexOf("https://") == -1 ) // File inside assets { InputStream stream1 = null; try { @@ -362,7 +385,22 @@ class DataDownloader extends Thread } } } - if( FileInAssets ) + + if( FileInExpansion ) + { + try { + stream = new CountingInputStream(new FileInputStream(url), 8192); + while( stream.skip(65536) > 0 ) { }; + totalLen = stream.getBytesRead(); + stream.close(); + stream = new CountingInputStream(new FileInputStream(url), 8192); + } catch( IOException e ) { + Log.i("SDL", "Unpacking from filesystem '" + url + "' - error: " + e.toString()); + Status.setText( res.getString(R.string.error_dl_from, url) ); + return false; + } + } + else if( FileInAssets ) { int multipartCounter = 0; InputStream multipart = null; @@ -393,7 +431,7 @@ class DataDownloader extends Thread try { stream = new CountingInputStream(Parent.getAssets().open(url), 8192); while( stream.skip(65536) > 0 ) { }; - totalLen += stream.getBytesRead(); + totalLen = stream.getBytesRead(); stream.close(); stream = new CountingInputStream(Parent.getAssets().open(url), 8192); } catch( IOException e ) { @@ -421,9 +459,49 @@ class DataDownloader extends Thread return false; } } - + + if( !copyUnpackFileStream(stream, path, url, DoNotUnzip, FileInAssets, FileInExpansion, totalLen, partialDownloadLen, response, downloadCount, downloadTotal) ) + return false; + + OutputStream out = null; + path = getOutFilePath(DownloadFlagFileName); + try { + out = new FileOutputStream( path ); + out.write(downloadUrls[downloadUrlIndex].getBytes("UTF-8")); + out.flush(); + out.close(); + } catch( FileNotFoundException e ) { + } catch( SecurityException e ) { + } catch( java.io.IOException e ) { + Status.setText( res.getString(R.string.error_write, path) + ": " + e.getMessage() ); + return false; + }; + Status.setText( downloadCount + "/" + downloadTotal + ": " + res.getString(R.string.dl_finished) ); + + try { + stream.close(); + if( FileInExpansion ) + { + Writer writer = new OutputStreamWriter(new FileOutputStream(url), "UTF-8"); + writer.write("Extracted and cleared\n"); + writer.close(); + } + } catch( java.io.IOException e ) { + }; + + return true; + }; + + // Moved part of code to a separate method, because Android imposes a stupid limit on Java method size + private boolean copyUnpackFileStream( CountingInputStream stream, String path, String url, + boolean DoNotUnzip, boolean FileInAssets, boolean FileInExpansion, + long totalLen, long partialDownloadLen, HttpResponse response, + int downloadCount, int downloadTotal) + { long updateStatusTime = 0; - + byte[] buf = new byte[16384]; + Resources res = Parent.getResources(); + if(DoNotUnzip) { Log.i("SDL", "Saving file '" + path + "'"); @@ -651,30 +729,9 @@ class DataDownloader extends Thread Log.i("SDL", "Saving file '" + path + "' done"); } }; - - OutputStream out = null; - path = getOutFilePath(DownloadFlagFileName); - try { - out = new FileOutputStream( path ); - out.write(downloadUrls[downloadUrlIndex].getBytes("UTF-8")); - out.flush(); - out.close(); - } catch( FileNotFoundException e ) { - } catch( SecurityException e ) { - } catch( java.io.IOException e ) { - Status.setText( res.getString(R.string.error_write, path) + ": " + e.getMessage() ); - return false; - }; - Status.setText( downloadCount + "/" + downloadTotal + ": " + res.getString(R.string.dl_finished) ); - - try { - stream.close(); - } catch( java.io.IOException e ) { - }; - return true; - }; - + } + private void initParent() { class Callback implements Runnable