Support for Google Play expansion files
This commit is contained in:
@@ -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 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 "# 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 "# 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 AppDataDownloadUrl=\"$AppDataDownloadUrl\" >> AndroidAppSettings.cfg
|
||||||
echo >> AndroidAppSettings.cfg
|
echo >> AndroidAppSettings.cfg
|
||||||
echo "# Reset SDL config when updating application to the new version (y) / (n)" >> AndroidAppSettings.cfg
|
echo "# Reset SDL config when updating application to the new version (y) / (n)" >> AndroidAppSettings.cfg
|
||||||
|
|||||||
@@ -284,22 +284,28 @@ class DataDownloader extends Thread
|
|||||||
catch( FileNotFoundException e ) {}
|
catch( FileNotFoundException e ) {}
|
||||||
catch( IOException e ) {};
|
catch( IOException e ) {};
|
||||||
|
|
||||||
HttpResponse response = null, responseError = null;
|
|
||||||
HttpGet request;
|
HttpGet request;
|
||||||
|
HttpResponse response = null, responseError = null;
|
||||||
long totalLen = 0;
|
long totalLen = 0;
|
||||||
|
long partialDownloadLen = 0;
|
||||||
CountingInputStream stream;
|
CountingInputStream stream;
|
||||||
byte[] buf = new byte[16384];
|
|
||||||
boolean DoNotUnzip = false;
|
boolean DoNotUnzip = false;
|
||||||
boolean FileInAssets = false;
|
boolean FileInAssets = false;
|
||||||
|
boolean FileInExpansion = false;
|
||||||
String url = "";
|
String url = "";
|
||||||
long partialDownloadLen = 0;
|
|
||||||
|
|
||||||
int downloadUrlIndex = 1;
|
int downloadUrlIndex = 1;
|
||||||
while( downloadUrlIndex < downloadUrls.length )
|
while( downloadUrlIndex < downloadUrls.length )
|
||||||
{
|
{
|
||||||
Log.i("SDL", "Processing download " + downloadUrls[downloadUrlIndex]);
|
Log.i("SDL", "Processing download " + downloadUrls[downloadUrlIndex]);
|
||||||
url = new String(downloadUrls[downloadUrlIndex]);
|
|
||||||
DoNotUnzip = false;
|
DoNotUnzip = false;
|
||||||
|
FileInAssets = false;
|
||||||
|
FileInExpansion = false;
|
||||||
|
partialDownloadLen = 0;
|
||||||
|
totalLen = 0;
|
||||||
|
|
||||||
|
url = new String(downloadUrls[downloadUrlIndex]);
|
||||||
if(url.indexOf(":") == 0)
|
if(url.indexOf(":") == 0)
|
||||||
{
|
{
|
||||||
path = getOutFilePath(url.substring( 1, url.indexOf(":", 1) ));
|
path = getOutFilePath(url.substring( 1, url.indexOf(":", 1) ));
|
||||||
@@ -311,7 +317,24 @@ class DataDownloader extends Thread
|
|||||||
partialDownloadLen = partialDownload.length();
|
partialDownloadLen = partialDownload.length();
|
||||||
}
|
}
|
||||||
Status.setText( downloadCount + "/" + downloadTotal + ": " + res.getString(R.string.connecting_to, url) );
|
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;
|
InputStream stream1 = null;
|
||||||
try {
|
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;
|
int multipartCounter = 0;
|
||||||
InputStream multipart = null;
|
InputStream multipart = null;
|
||||||
@@ -393,7 +431,7 @@ class DataDownloader extends Thread
|
|||||||
try {
|
try {
|
||||||
stream = new CountingInputStream(Parent.getAssets().open(url), 8192);
|
stream = new CountingInputStream(Parent.getAssets().open(url), 8192);
|
||||||
while( stream.skip(65536) > 0 ) { };
|
while( stream.skip(65536) > 0 ) { };
|
||||||
totalLen += stream.getBytesRead();
|
totalLen = stream.getBytesRead();
|
||||||
stream.close();
|
stream.close();
|
||||||
stream = new CountingInputStream(Parent.getAssets().open(url), 8192);
|
stream = new CountingInputStream(Parent.getAssets().open(url), 8192);
|
||||||
} catch( IOException e ) {
|
} catch( IOException e ) {
|
||||||
@@ -421,9 +459,49 @@ class DataDownloader extends Thread
|
|||||||
return false;
|
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;
|
long updateStatusTime = 0;
|
||||||
|
byte[] buf = new byte[16384];
|
||||||
|
Resources res = Parent.getResources();
|
||||||
|
|
||||||
if(DoNotUnzip)
|
if(DoNotUnzip)
|
||||||
{
|
{
|
||||||
Log.i("SDL", "Saving file '" + path + "'");
|
Log.i("SDL", "Saving file '" + path + "'");
|
||||||
@@ -651,30 +729,9 @@ class DataDownloader extends Thread
|
|||||||
Log.i("SDL", "Saving file '" + path + "' done");
|
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;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
private void initParent()
|
private void initParent()
|
||||||
{
|
{
|
||||||
class Callback implements Runnable
|
class Callback implements Runnable
|
||||||
|
|||||||
Reference in New Issue
Block a user