package org.kivy.android; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.util.Log; import org.kamranzafar.jtar.TarEntry; import org.kamranzafar.jtar.TarInputStream; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.zip.GZIPInputStream; public class AssetExtract { private static String TAG = AssetExtract.class.getSimpleName(); /** * @param parent File or directory to delete recursively */ public static void recursiveDelete(File parent) { if (parent.isDirectory()) { for (File child : parent.listFiles()) { recursiveDelete(child); } } parent.delete(); } public static void extractAsset(Context ctx, String assetName, File target) { // The version of data in memory and on disk. String packaged_version; String disk_version; try { PackageManager manager = ctx.getPackageManager(); PackageInfo info = manager.getPackageInfo(ctx.getPackageName(), 0); packaged_version = info.versionName; Log.v(TAG, "Data version is " + packaged_version); } catch (PackageManager.NameNotFoundException e) { packaged_version = null; } // If no packaged data version, no unpacking is necessary. if (packaged_version == null) { Log.w(TAG, "Data version not found"); return; } // Check the current disk version, if any. String filesDir = target.getAbsolutePath(); String disk_version_fn = filesDir + "/" + assetName + ".version"; try { byte buf[] = new byte[64]; FileInputStream is = new FileInputStream(disk_version_fn); int len = is.read(buf); disk_version = new String(buf, 0, len); is.close(); } catch (Exception e) { disk_version = ""; } if (packaged_version.equals(disk_version)) { Log.v(TAG, "Disk data version equals packaged data version."); return; } recursiveDelete(target); target.mkdirs(); if (!extractTar(ctx.getAssets(), assetName, target.getAbsolutePath())) { Log.e(TAG, "Could not extract " + assetName + " data."); } try { // Write .nomedia. new File(target, ".nomedia").createNewFile(); // Write version file. FileOutputStream os = new FileOutputStream(disk_version_fn); os.write(packaged_version.getBytes()); os.close(); } catch (Exception ex) { Log.w(TAG, ex); } } public static boolean extractTar(AssetManager assets, String assetName, String target) { byte buf[] = new byte[1024 * 1024]; InputStream assetStream = null; TarInputStream tis = null; try { assetStream = assets.open(assetName, AssetManager.ACCESS_STREAMING); tis = new TarInputStream(new BufferedInputStream( new GZIPInputStream(new BufferedInputStream(assetStream, 8192)), 8192)); } catch (IOException e) { Log.e(TAG, "opening up extract tar", e); return false; } while (true) { TarEntry entry = null; try { entry = tis.getNextEntry(); } catch (java.io.IOException e) { Log.e(TAG, "extracting tar", e); return false; } if (entry == null) { break; } if (entry.isDirectory()) { try { new File(target + "/" + entry.getName()).mkdirs(); } catch (SecurityException e) { Log.e(TAG, "extracting tar", e); } continue; } OutputStream out = null; String path = target + "/" + entry.getName(); try { out = new BufferedOutputStream(new FileOutputStream(path), 8192); } catch (FileNotFoundException e) { Log.e(TAG, "extracting tar", e); } catch (SecurityException e) { Log.e(TAG, "extracting tar", e); } if (out == null) { Log.e(TAG, "could not open " + path); return false; } try { while (true) { int len = tis.read(buf); if (len == -1) { break; } out.write(buf, 0, len); } out.flush(); out.close(); } catch (java.io.IOException e) { Log.e(TAG, "extracting zip", e); return false; } } try { tis.close(); assetStream.close(); } catch (IOException e) { // pass } return true; } }