From ac6a031c7de26f2a1c89deff20eb2b8e7ca76321 Mon Sep 17 00:00:00 2001 From: pelya Date: Sat, 21 Aug 2010 16:40:52 +0300 Subject: [PATCH] Added opssibility to download optional content, and to save files without unzipping --- ChangeAppSettings.sh | 30 +- project/AndroidManifest.xml | 4 +- .../application/opentyrian/AppSettings.cfg | 9 +- project/src/DataDownloader.java | 349 ++++++++++-------- project/src/Globals.java | 3 +- project/src/Settings.java | 32 +- 6 files changed, 264 insertions(+), 163 deletions(-) diff --git a/ChangeAppSettings.sh b/ChangeAppSettings.sh index da4209f97..8b9820140 100755 --- a/ChangeAppSettings.sh +++ b/ChangeAppSettings.sh @@ -1,6 +1,6 @@ #!/bin/sh -CHANGE_APP_SETTINGS_VERSION=3 +CHANGE_APP_SETTINGS_VERSION=4 AUTO= if [ "X$1" = "X-a" ]; then @@ -46,10 +46,26 @@ if [ -n "$var" ] ; then ScreenOrientation="$var" fi -echo -n "\nSpecify URL to download application data in zip archive, you may specify backup URLs delimited by '|'\n($AppDataDownloadUrl):\n" -read var -if [ -n "$var" ] ; then - AppDataDownloadUrl="$var" +echo -n "\nSpecify path to download application data in zip archive in the form 'Description|URL|BackupURL|...'" +echo -n "\nYou may specify paths to optional game content delimited by newlines (empty line to finish)" +echo -n "\nIf the URL starts with '-' symbol it will be downloaded as-is to game dir and not unzipped\n\n" +echo -n "`echo $AppDataDownloadUrl | tr '^' '\\n'`" +echo +AppDataDownloadUrl1="" +while true; do + read var + if [ -n "$var" ] ; then + if [ -z "$AppDataDownloadUrl1" ]; then + AppDataDownloadUrl1="$var" + else + AppDataDownloadUrl1="$AppDataDownloadUrl1^$var" + fi + else + break + fi +done +if [ -n "$AppDataDownloadUrl1" ] ; then + AppDataDownloadUrl="$AppDataDownloadUrl1" fi echo -n "\nApplication window should be resized to fit into native device screen (480x320 or 800x480) (y) or (n) ($SdlVideoResize): " @@ -70,7 +86,7 @@ if [ -n "$var" ] ; then AppUsesMouse="$var" fi -echo -n "\nApplication needs arrow keys (y) or (n), if (y) the accelerometer or touchscreen keyboard\nwill be used as arrow keys if phone does not have dpad/trackball ($AppNeedsArrowKeys)\n: " +echo -n "\nApplication needs arrow keys (y) or (n), if (y) the accelerometer or touchscreen keyboard\nwill be used as arrow keys if phone does not have dpad/trackball ($AppNeedsArrowKeys): " read var if [ -n "$var" ] ; then AppNeedsArrowKeys="$var" @@ -277,7 +293,7 @@ done echo Patching project/src/Globals.java cat project/src/Globals.java | \ sed "s/public static String ApplicationName = .*;/public static String ApplicationName = \"$AppShortName\";/" | \ - sed "s^public static String DataDownloadUrl = \".*\";^public static String DataDownloadUrl = \"$AppDataDownloadUrl1\";^" | \ + sed "s@public static String DataDownloadUrl = .*@public static String DataDownloadUrl = \"$AppDataDownloadUrl1\";@" | \ sed "s/public static boolean NeedDepthBuffer = .*;/public static boolean NeedDepthBuffer = $NeedDepthBuffer;/" | \ sed "s/public static boolean HorizontalOrientation = .*;/public static boolean HorizontalOrientation = $HorizontalOrientation;/" | \ sed "s/public static boolean AppUsesMouse = .*;/public static boolean AppUsesMouse = $AppUsesMouse;/" | \ diff --git a/project/AndroidManifest.xml b/project/AndroidManifest.xml index 73a07c391..942be78f8 100644 --- a/project/AndroidManifest.xml +++ b/project/AndroidManifest.xml @@ -1,8 +1,8 @@ 0 && Globals.OptionalDataDownload.length > i && Globals.OptionalDataDownload[i] ) + DownloadDataFile(downloadFiles[i], "libsdl-DownloadFinished-" + String.valueOf(i) + ".flag"); + } + } + public void DownloadDataFile(final String DataDownloadUrl, final String DownloadFlagFileName) + { + String [] downloadUrls = DataDownloadUrl.split("[|]"); + if( downloadUrls.length < 2 ) + return; + String path = getOutFilePath(DownloadFlagFileName); InputStream checkFile = null; try { @@ -163,10 +175,13 @@ class DataDownloader extends Thread byte b[] = new byte[ Globals.DataDownloadUrl.getBytes("UTF-8").length + 1 ]; int readed = checkFile.read(b); String compare = new String( b, 0, b.length - 1, "UTF-8" ); - //Log.i("libSDL", "Saved URL '" + compare + "' requested URL '" + Globals.DataDownloadUrl + "'"); if( readed != b.length - 1 ) throw new IOException(); - if( compare.compareTo(Globals.DataDownloadUrl) != 0 ) + boolean matched = false; + for( int i = 1; i < downloadUrls.length; i++ ) + if( compare.compareTo(downloadUrls[i]) == 0 ) + matched = true; + if( ! matched ) throw new IOException(); Status.setText( "No need to download" ); DownloadComplete = true; @@ -176,6 +191,7 @@ class DataDownloader extends Thread } checkFile = null; + int downloadUrlIndex = 1; // Create output directory (not necessary for phone storage) if( Globals.DownloadToSdcard ) { @@ -184,182 +200,223 @@ class DataDownloader extends Thread } catch( SecurityException e ) { }; } - String [] downloadUrls = Globals.DataDownloadUrl.split("[|]"); - int downloadUrlIndex = 0; - downloading: while(true) { + HttpResponse response = null; + HttpGet request; + long totalLen; + CountingInputStream stream; + byte[] buf = new byte[16384]; + boolean DoNotUnzip = false; - HttpResponse response = null; - HttpGet request; - long totalLen; - CountingInputStream stream; - byte[] buf = new byte[16384]; - - while( downloadUrlIndex < downloadUrls.length && response == null ) - { - System.out.println("Connecting to " + downloadUrls[downloadUrlIndex]); - Status.setText( "Connecting to " + downloadUrls[downloadUrlIndex] ); - request = new HttpGet(downloadUrls[downloadUrlIndex]); - request.addHeader("Accept", "*/*"); - try { - DefaultHttpClient client = new DefaultHttpClient(); - client.getParams().setBooleanParameter("http.protocol.handle-redirects", true); - response = client.execute(request); - } catch (IOException e) { - System.out.println("Failed to connect to " + downloadUrls[downloadUrlIndex]); - downloadUrlIndex++; - }; - if( response != null ) + while( downloadUrlIndex < downloadUrls.length && response == null ) { - if( response.getStatusLine().getStatusCode() != 200 ) + System.out.println("Connecting to " + downloadUrls[downloadUrlIndex]); + Status.setText( "Connecting to " + downloadUrls[downloadUrlIndex] ); + String url = new String(downloadUrls[downloadUrlIndex]); + if(url.indexOf("-") == 0) { - response = null; + url = url.substring(1); + DoNotUnzip = true; + } + request = new HttpGet(url); + request.addHeader("Accept", "*/*"); + try { + DefaultHttpClient client = new DefaultHttpClient(); + client.getParams().setBooleanParameter("http.protocol.handle-redirects", true); + response = client.execute(request); + } catch (IOException e) { System.out.println("Failed to connect to " + downloadUrls[downloadUrlIndex]); downloadUrlIndex++; + }; + if( response != null ) + { + if( response.getStatusLine().getStatusCode() != 200 ) + { + response = null; + System.out.println("Failed to connect to " + downloadUrls[downloadUrlIndex]); + downloadUrlIndex++; + } } } - } - if( response == null ) - { - System.out.println("Error connecting to " + Globals.DataDownloadUrl); - Status.setText( "Error connecting to " + Globals.DataDownloadUrl ); - return; - } + if( response == null ) + { + System.out.println("Error connecting to " + Globals.DataDownloadUrl); + Status.setText( "Error connecting to " + Globals.DataDownloadUrl ); + return; + } - Status.setText( "Downloading data from " + Globals.DataDownloadUrl ); - totalLen = response.getEntity().getContentLength(); - try { - stream = new CountingInputStream(response.getEntity().getContent()); - } catch( java.io.IOException e ) { - Status.setText( "Error downloading data from " + Globals.DataDownloadUrl ); - return; - } - - ZipInputStream zip = new ZipInputStream(stream); - - while(true) - { - ZipEntry entry = null; + Status.setText( "Downloading data from " + Globals.DataDownloadUrl ); + totalLen = response.getEntity().getContentLength(); try { - entry = zip.getNextEntry(); + stream = new CountingInputStream(response.getEntity().getContent()); } catch( java.io.IOException e ) { Status.setText( "Error downloading data from " + Globals.DataDownloadUrl ); return; } - if( entry == null ) - break; - if( entry.isDirectory() ) + + if(DoNotUnzip) { + path = downloadUrls[downloadUrlIndex].substring(downloadUrls[downloadUrlIndex].lastIndexOf("/")+1, downloadUrls[downloadUrlIndex].indexOf("?")); + OutputStream out = null; try { - (new File( getOutFilePath(entry.getName()) )).mkdirs(); + out = new FileOutputStream( path ); + } catch( FileNotFoundException e ) { } catch( SecurityException e ) { }; - continue; + if( out == null ) + { + Status.setText( "Error writing to " + path ); + return; + } + + try { + int len = stream.read(buf); + while (len >= 0) + { + if(len > 0) + out.write(buf, 0, len); + len = stream.read(buf); + + String percent = ""; + if( totalLen > 0 ) + percent = String.valueOf(stream.getBytesRead() * 100 / totalLen) + "%: "; + Status.setText( percent + "writing file " + path ); + } + out.flush(); + out.close(); + out = null; + } catch( java.io.IOException e ) { + Status.setText( "Error writing file " + path ); + return; + } + } + else + { + ZipInputStream zip = new ZipInputStream(stream); + + while(true) + { + ZipEntry entry = null; + try { + entry = zip.getNextEntry(); + } catch( java.io.IOException e ) { + Status.setText( "Error downloading data from " + Globals.DataDownloadUrl ); + return; + } + if( entry == null ) + break; + if( entry.isDirectory() ) + { + try { + (new File( getOutFilePath(entry.getName()) )).mkdirs(); + } catch( SecurityException e ) { }; + continue; + } + + OutputStream out = null; + path = getOutFilePath(entry.getName()); + + try { + CheckedInputStream check = new CheckedInputStream( new FileInputStream(path), new CRC32() ); + while( check.read(buf, 0, buf.length) > 0 ) {}; + check.close(); + if( check.getChecksum().getValue() != entry.getCrc() ) + { + File ff = new File(path); + ff.delete(); + throw new Exception(); + } + continue; + } catch( Exception e ) + { + } + + try { + out = new FileOutputStream( path ); + } catch( FileNotFoundException e ) { + } catch( SecurityException e ) { }; + if( out == null ) + { + Status.setText( "Error writing to " + path ); + return; + } + + String percent = ""; + if( totalLen > 0 ) + percent = String.valueOf(stream.getBytesRead() * 100 / totalLen) + "%: "; + Status.setText( percent + "writing file " + path ); + + try { + int len = zip.read(buf); + while (len >= 0) + { + if(len > 0) + out.write(buf, 0, len); + len = zip.read(buf); + + percent = ""; + if( totalLen > 0 ) + percent = String.valueOf(stream.getBytesRead() * 100 / totalLen) + "%: "; + Status.setText( percent + "writing file " + path ); + } + out.flush(); + out.close(); + out = null; + } catch( java.io.IOException e ) { + Status.setText( "Error writing file " + path ); + return; + } + + try { + CheckedInputStream check = new CheckedInputStream( new FileInputStream(path), new CRC32() ); + while( check.read(buf, 0, buf.length) > 0 ) {}; + check.close(); + if( check.getChecksum().getValue() != entry.getCrc() ) + { + File ff = new File(path); + ff.delete(); + throw new Exception(); + } + } catch( Exception e ) + { + Status.setText( "CRC32 check failed for file " + path ); + continue downloading; // Start download over from the same URL + //return; + } + } } OutputStream out = null; - path = getOutFilePath(entry.getName()); - - try { - CheckedInputStream check = new CheckedInputStream( new FileInputStream(path), new CRC32() ); - while( check.read(buf, 0, buf.length) > 0 ) {}; - check.close(); - if( check.getChecksum().getValue() != entry.getCrc() ) - { - File ff = new File(path); - ff.delete(); - throw new Exception(); - } - continue; - } catch( Exception e ) - { - } - + 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( SecurityException e ) { + } catch( java.io.IOException e ) { + Status.setText( "Error writing file " + path ); + return; + }; + if( out == null ) { Status.setText( "Error writing to " + path ); return; } - - String percent = ""; - if( totalLen > 0 ) - percent = String.valueOf(stream.getBytesRead() * 100 / totalLen) + "%: "; - Status.setText( percent + "writing file " + path ); + + Status.setText( "Finished" ); + DownloadComplete = true; try { - int len = zip.read(buf); - while (len >= 0) - { - if(len > 0) - out.write(buf, 0, len); - len = zip.read(buf); - - percent = ""; - if( totalLen > 0 ) - percent = String.valueOf(stream.getBytesRead() * 100 / totalLen) + "%: "; - Status.setText( percent + "writing file " + path ); - } - out.flush(); - out.close(); - out = null; + stream.close(); } catch( java.io.IOException e ) { - Status.setText( "Error writing file " + path ); - return; - } + }; - try { - CheckedInputStream check = new CheckedInputStream( new FileInputStream(path), new CRC32() ); - while( check.read(buf, 0, buf.length) > 0 ) {}; - check.close(); - if( check.getChecksum().getValue() != entry.getCrc() ) - { - File ff = new File(path); - ff.delete(); - throw new Exception(); - } - } catch( Exception e ) - { - Status.setText( "CRC32 check failed for file " + path ); - continue downloading; // Start download over from the same URL - //return; - } - } - - OutputStream out = null; - path = getOutFilePath(DownloadFlagFileName); - try { - out = new FileOutputStream( path ); - out.write(Globals.DataDownloadUrl.getBytes("UTF-8")); - out.flush(); - out.close(); - } catch( FileNotFoundException e ) { - } catch( SecurityException e ) { - } catch( java.io.IOException e ) { - Status.setText( "Error writing file " + path ); - return; - }; - - if( out == null ) - { - Status.setText( "Error writing to " + path ); - return; - } - - Status.setText( "Finished" ); - DownloadComplete = true; - - try { - stream.close(); - } catch( java.io.IOException e ) { - }; - - initParent(); - break; + initParent(); + break; } }; diff --git a/project/src/Globals.java b/project/src/Globals.java index 0dcbf5dc6..aa1296ed0 100644 --- a/project/src/Globals.java +++ b/project/src/Globals.java @@ -8,7 +8,7 @@ class Globals { public static String ApplicationName = "OpenTyrian"; // Should be zip file - public static String DataDownloadUrl = "http://sites.google.com/site/xpelyax/Home/tyrian21-data.zip?attredirects=0%26d=1|http://sitesproxy.goapk.com/site/xpelyax/Home/tyrian21-data.zip"; // This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount + public static String DataDownloadUrl = "^Data files size is 10 Mb|http://sites.google.com/site/xpelyax/Home/tyrian21-data.zip?attredirects=0%26d=1|http://sitesproxy.goapk.com/site/xpelyax/Home/tyrian21-data.zip"; // Set this value to true if you're planning to render 3D using OpenGL - it eats some GFX resources, so disabled for 2D public static boolean NeedDepthBuffer = false; @@ -41,6 +41,7 @@ class Globals { public static int AccelerometerSensitivity = 0; public static int TrackballDampening = 0; public static int AudioBufferConfig = 0; + public static boolean OptionalDataDownload[] = null; } class LoadLibrary { diff --git a/project/src/Settings.java b/project/src/Settings.java index 66d2a8032..4ac2238c2 100644 --- a/project/src/Settings.java +++ b/project/src/Settings.java @@ -38,6 +38,9 @@ class Settings out.writeInt(Globals.AccelerometerSensitivity); out.writeInt(Globals.TrackballDampening); out.writeInt(Globals.AudioBufferConfig); + out.writeInt(Globals.OptionalDataDownload.length); + for(int i = 0; i < Globals.OptionalDataDownload.length; i++) + out.writeBoolean(Globals.OptionalDataDownload[i]); out.close(); } catch( FileNotFoundException e ) { } catch( SecurityException e ) { @@ -57,7 +60,9 @@ class Settings Globals.AccelerometerSensitivity = settingsFile.readInt(); Globals.TrackballDampening = settingsFile.readInt(); Globals.AudioBufferConfig = settingsFile.readInt(); - + Globals.OptionalDataDownload = new boolean[settingsFile.readInt()]; + for(int i = 0; i < Globals.OptionalDataDownload.length; i++) + Globals.OptionalDataDownload[i] = settingsFile.readBoolean(); AlertDialog.Builder builder = new AlertDialog.Builder(p); builder.setTitle("Phone configuration"); @@ -148,9 +153,30 @@ class Settings }catch(Exception e) {} final CharSequence[] items = {"Phone storage - " + String.valueOf(freePhone) + " Mb free", "SD card - " + String.valueOf(freeSdcard) + " Mb free"}; - AlertDialog.Builder builder = new AlertDialog.Builder(p); - builder.setTitle("Where to download application data"); + String [] downloadFiles = Globals.DataDownloadUrl.split("[^]"); + builder.setTitle(downloadFiles[0].split("[|]")[0]); + CharSequence[] items2 = null; + if(downloadFiles.length > 1) + { + Globals.OptionalDataDownload = new boolean[downloadFiles.length]; + items2 = new CharSequence[ downloadFiles.length - 1 ]; + for(int i = 1; i < downloadFiles.length; i++ ) + items2[i-1] = new String(downloadFiles[i].split("[|]")[0]); + if( items2 != null ) + builder.setMultiChoiceItems(items2, + Globals.OptionalDataDownload.length == items2.length ? Globals.OptionalDataDownload : null, + new DialogInterface.OnMultiChoiceClickListener() + { + public void onClick(DialogInterface dialog, int item, boolean isChecked) + { + Globals.OptionalDataDownload[item+1] = isChecked; + } + }); + } + if( Globals.OptionalDataDownload == null ) + Globals.OptionalDataDownload = new boolean[1]; + Globals.OptionalDataDownload[0] = true; builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item)