Android: Be able to have assets in a zip file
This commit is contained in:
parent
f79a2e9bde
commit
cd7b0b42c3
|
@ -96,3 +96,4 @@ Thumbs.db
|
||||||
/Source/Project64-input/Version.h
|
/Source/Project64-input/Version.h
|
||||||
/Source/Project64-video/Version.h
|
/Source/Project64-video/Version.h
|
||||||
/Source/RSP/Version.h
|
/Source/RSP/Version.h
|
||||||
|
/Android/app/src/main/assets/assets.zip
|
||||||
|
|
|
@ -33,6 +33,10 @@ IF NOT EXIST "%base_dir%/Android/assets/project64_data/Config/Enhancements/" mkd
|
||||||
xcopy "%base_dir%/Config/Enhancements" "%base_dir%/Android/assets/project64_data/Config/Enhancements/" /D /I /F /Y /E
|
xcopy "%base_dir%/Config/Enhancements" "%base_dir%/Android/assets/project64_data/Config/Enhancements/" /D /I /F /Y /E
|
||||||
IF %ERRORLEVEL% NEQ 0 (exit /B 1)
|
IF %ERRORLEVEL% NEQ 0 (exit /B 1)
|
||||||
|
|
||||||
|
IF NOT EXIST "%base_dir%/Android/app/src/main/assets/" mkdir "%base_dir%/Android/app/src/main/assets/"
|
||||||
|
IF EXIST "%base_dir%/Android/app/src/main/assets/assets.zip" del "%base_dir%\Android\app\src\main\assets\assets.zip"
|
||||||
|
powershell Compress-Archive "%base_dir%/Android/assets/*" "%base_dir%/Android/app/src/main/assets/assets.zip"
|
||||||
|
|
||||||
goto :end
|
goto :end
|
||||||
|
|
||||||
:End
|
:End
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
package emu.project64;
|
package emu.project64;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import emu.project64.R;
|
import emu.project64.R;
|
||||||
import emu.project64.jni.NativeExports;
|
import emu.project64.jni.NativeExports;
|
||||||
import emu.project64.jni.SettingsID;
|
import emu.project64.jni.SettingsID;
|
||||||
import emu.project64.jni.UISettingID;
|
import emu.project64.jni.UISettingID;
|
||||||
import emu.project64.task.ExtractAssetsTask;
|
import emu.project64.task.ExtractAssetZipTask;
|
||||||
import emu.project64.task.ExtractAssetsTask.ExtractAssetsListener;
|
import emu.project64.task.ExtractAssetZipTask.ExtractAssetZipListener;
|
||||||
import emu.project64.task.ExtractAssetsTask.Failure;
|
import emu.project64.task.ExtractAssetsTask.Failure;
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.DialogInterface.OnClickListener;
|
import android.content.DialogInterface.OnClickListener;
|
||||||
|
@ -19,7 +17,6 @@ import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback;
|
import androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
@ -30,7 +27,7 @@ import android.util.Log;
|
||||||
import android.view.WindowManager.LayoutParams;
|
import android.view.WindowManager.LayoutParams;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
public class SplashActivity extends AppCompatActivity implements ExtractAssetsListener, OnRequestPermissionsResultCallback
|
public class SplashActivity extends AppCompatActivity implements ExtractAssetZipListener, OnRequestPermissionsResultCallback
|
||||||
{
|
{
|
||||||
static final int PERMISSION_REQUEST = 177;
|
static final int PERMISSION_REQUEST = 177;
|
||||||
static final int NUM_PERMISSIONS = 2;
|
static final int NUM_PERMISSIONS = 2;
|
||||||
|
@ -251,58 +248,29 @@ public class SplashActivity extends AppCompatActivity implements ExtractAssetsLi
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private boolean CountTotalAssetFiles(String path)
|
|
||||||
{
|
|
||||||
String [] list;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
list = getAssets().list(path);
|
|
||||||
if (list.length > 0)
|
|
||||||
{
|
|
||||||
for (String file : list)
|
|
||||||
{
|
|
||||||
if (!CountTotalAssetFiles(path + "/" + file))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TOTAL_ASSETS += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Runnable extractAssetsTaskLauncher = new Runnable()
|
private final Runnable extractAssetsTaskLauncher = new Runnable()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
Log.i( "Splash", "extractAssetsTaskLauncher - start");
|
Log.i( "Splash", "extractAssetsTaskLauncher - start");
|
||||||
TOTAL_ASSETS = 0;
|
new ExtractAssetZipTask( getAssets(), AndroidDevice.PACKAGE_DIRECTORY, SplashActivity.this ).execute();
|
||||||
CountTotalAssetFiles(SOURCE_DIR);
|
|
||||||
mAssetsExtracted = 0;
|
|
||||||
new ExtractAssetsTask( getAssets(), SOURCE_DIR, AndroidDevice.PACKAGE_DIRECTORY, SplashActivity.this ).execute();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onExtractAssetsProgress( String nextFileToExtract )
|
public void onExtractAssetsProgress( String text )
|
||||||
{
|
{
|
||||||
final float percent = ( 100f * mAssetsExtracted ) / (float) TOTAL_ASSETS;
|
runOnUiThread(new Runnable() {
|
||||||
final String text = getString( R.string.assetExtractor_progress, percent, nextFileToExtract );
|
@Override
|
||||||
mTextView.setText(text);
|
public void run() {
|
||||||
mAssetsExtracted++;
|
mTextView.setText(text);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onExtractAssetsFinished( List<Failure> failures )
|
public void onExtractAssetsFinished( List<ExtractAssetZipTask.Failure> failures )
|
||||||
{
|
{
|
||||||
if( failures.size() == 0 )
|
if( failures.size() == 0 )
|
||||||
{
|
{
|
||||||
|
@ -322,12 +290,12 @@ public class SplashActivity extends AppCompatActivity implements ExtractAssetsLi
|
||||||
String weblink = getResources().getString( R.string.assetExtractor_uriHelp );
|
String weblink = getResources().getString( R.string.assetExtractor_uriHelp );
|
||||||
String message = getString( R.string.assetExtractor_failed, weblink );
|
String message = getString( R.string.assetExtractor_failed, weblink );
|
||||||
String textHtml = message.replace( "\n", "<br/>" ) + "<p><small>";
|
String textHtml = message.replace( "\n", "<br/>" ) + "<p><small>";
|
||||||
for( Failure failure : failures )
|
for( ExtractAssetZipTask.Failure failure : failures )
|
||||||
{
|
{
|
||||||
textHtml += failure.toString() + "<br/>";
|
textHtml += failure.toString() + "<br/>";
|
||||||
}
|
}
|
||||||
textHtml += "</small>";
|
textHtml += "</small>";
|
||||||
mTextView.setText( Html.fromHtml( textHtml ) );
|
mTextView.setText( Html.fromHtml( textHtml ) );
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
package emu.project64.task;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
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.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class ExtractAssetZipTask extends AsyncTask<Void, String, List<ExtractAssetZipTask.Failure>>
|
||||||
|
{
|
||||||
|
public interface ExtractAssetZipListener
|
||||||
|
{
|
||||||
|
public void onExtractAssetsProgress( String nextFileToExtract );
|
||||||
|
public void onExtractAssetsFinished( List<Failure> failures );
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtractAssetZipTask( AssetManager assetManager, String dstPath, ExtractAssetZipListener listener)
|
||||||
|
{
|
||||||
|
if (assetManager == null )
|
||||||
|
throw new IllegalArgumentException( "Asset manager cannot be null" );
|
||||||
|
if( TextUtils.isEmpty( dstPath ) )
|
||||||
|
throw new IllegalArgumentException( "Destination path cannot be null or empty" );
|
||||||
|
|
||||||
|
mAssetManager = assetManager;
|
||||||
|
mDstPath = dstPath;
|
||||||
|
mListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final AssetManager mAssetManager;
|
||||||
|
private final String mDstPath;
|
||||||
|
private final ExtractAssetZipListener mListener;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Failure> doInBackground( Void... params )
|
||||||
|
{
|
||||||
|
return extractAssets( mDstPath );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onProgressUpdate( String... values )
|
||||||
|
{
|
||||||
|
mListener.onExtractAssetsProgress( values[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute( List<ExtractAssetZipTask.Failure> result )
|
||||||
|
{
|
||||||
|
mListener.onExtractAssetsFinished( result );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Failure
|
||||||
|
{
|
||||||
|
public enum Reason
|
||||||
|
{
|
||||||
|
FILE_UNWRITABLE,
|
||||||
|
FILE_UNCLOSABLE,
|
||||||
|
ASSET_UNCLOSABLE,
|
||||||
|
ASSET_IO_EXCEPTION,
|
||||||
|
FILE_IO_EXCEPTION,
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String srcPath;
|
||||||
|
public final String dstPath;
|
||||||
|
public final Reason reason;
|
||||||
|
public Failure( String srcPath, String dstPath, Reason reason )
|
||||||
|
{
|
||||||
|
this.srcPath = srcPath;
|
||||||
|
this.dstPath = dstPath;
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
switch( reason )
|
||||||
|
{
|
||||||
|
case FILE_UNWRITABLE:
|
||||||
|
return "Failed to open file " + dstPath;
|
||||||
|
case FILE_UNCLOSABLE:
|
||||||
|
return "Failed to close file " + dstPath;
|
||||||
|
case ASSET_UNCLOSABLE:
|
||||||
|
return "Failed to close asset " + srcPath;
|
||||||
|
case ASSET_IO_EXCEPTION:
|
||||||
|
return "Failed to extract asset " + srcPath + " to file " + dstPath;
|
||||||
|
case FILE_IO_EXCEPTION:
|
||||||
|
return "Failed to add file " + srcPath + " to file " + dstPath;
|
||||||
|
default:
|
||||||
|
return "Failed using source " + srcPath + " and destination " + dstPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Failure> extractAssets( String dstPath )
|
||||||
|
{
|
||||||
|
final List<Failure> failures = new ArrayList<Failure>();
|
||||||
|
|
||||||
|
// Ensure the parent directories exist
|
||||||
|
File root = new File(dstPath + "/");
|
||||||
|
if (!root.exists()) {
|
||||||
|
root.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
String dstFile = dstPath + "/assets.zip";
|
||||||
|
String srcFile = "assets.zip";
|
||||||
|
// Call the progress listener before extracting
|
||||||
|
publishProgress( dstPath );
|
||||||
|
|
||||||
|
// IO objects, initialize null to eliminate lint error
|
||||||
|
OutputStream out = null;
|
||||||
|
InputStream in = null;
|
||||||
|
|
||||||
|
Boolean ExtractZip = false;
|
||||||
|
// Extract the file
|
||||||
|
try
|
||||||
|
{
|
||||||
|
out = new FileOutputStream( dstFile );
|
||||||
|
in = mAssetManager.open( srcFile);
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int read;
|
||||||
|
|
||||||
|
mListener.onExtractAssetsProgress( "copying asset zip file" );
|
||||||
|
while( ( read = in.read( buffer ) ) != -1 )
|
||||||
|
{
|
||||||
|
out.write( buffer, 0, read );
|
||||||
|
}
|
||||||
|
mListener.onExtractAssetsProgress( "Finished copying assset zip" );
|
||||||
|
out.flush();
|
||||||
|
ExtractZip = true;
|
||||||
|
}
|
||||||
|
catch( FileNotFoundException e )
|
||||||
|
{
|
||||||
|
Failure failure = new Failure( srcFile, dstPath, Failure.Reason.FILE_UNWRITABLE );
|
||||||
|
Log.e( "ExtractAssetZipTask", failure.toString() );
|
||||||
|
failures.add( failure );
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
Failure failure = new Failure( srcFile, dstPath, Failure.Reason.ASSET_IO_EXCEPTION );
|
||||||
|
Log.e( "ExtractAssetZipTask", failure.toString() );
|
||||||
|
failures.add( failure );
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if( out != null )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
Failure failure = new Failure( srcFile, dstPath, Failure.Reason.FILE_UNCLOSABLE );
|
||||||
|
Log.e( "ExtractAssetZipTask", failure.toString() );
|
||||||
|
failures.add( failure );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( in != null )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
Failure failure = new Failure( srcFile, dstPath, Failure.Reason.ASSET_UNCLOSABLE );
|
||||||
|
Log.e( "ExtractAssetZipTask", failure.toString() );
|
||||||
|
failures.add( failure );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ExtractZip)
|
||||||
|
{
|
||||||
|
String zipFilePath = dstPath + "/assets.zip";
|
||||||
|
String destDir = dstPath + "/";
|
||||||
|
File dir = new File(destDir);
|
||||||
|
// create output directory if it doesn't exist
|
||||||
|
if(!dir.exists()) dir.mkdirs();
|
||||||
|
FileInputStream fis;
|
||||||
|
//buffer for read and write data to file
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
try {
|
||||||
|
fis = new FileInputStream(zipFilePath);
|
||||||
|
ZipInputStream zis = new ZipInputStream(fis);
|
||||||
|
ZipEntry ze = zis.getNextEntry();
|
||||||
|
while(ze != null){
|
||||||
|
String fileName = ze.getName();
|
||||||
|
File newFile = new File(destDir + File.separator + fileName.replace("\\", "/"));
|
||||||
|
mListener.onExtractAssetsProgress( "Unzipping "+fileName );
|
||||||
|
|
||||||
|
//create directories for sub directories in zip
|
||||||
|
new File(newFile.getParent()).mkdirs();
|
||||||
|
if (ze.getSize() != 0) {
|
||||||
|
FileOutputStream fos = new FileOutputStream(newFile);
|
||||||
|
int len;
|
||||||
|
while ((len = zis.read(buffer)) > 0) {
|
||||||
|
fos.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
//close this ZipEntry
|
||||||
|
zis.closeEntry();
|
||||||
|
ze = zis.getNextEntry();
|
||||||
|
}
|
||||||
|
//close last ZipEntry
|
||||||
|
zis.closeEntry();
|
||||||
|
zis.close();
|
||||||
|
fis.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Failure failure = new Failure( srcFile, dstPath, Failure.Reason.ASSET_IO_EXCEPTION );
|
||||||
|
Log.e( "ExtractAssetZipTask", failure.toString() );
|
||||||
|
failures.add( failure );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return failures;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,313 +0,0 @@
|
||||||
package emu.project64.task;
|
|
||||||
|
|
||||||
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.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import android.content.res.AssetManager;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class ExtractAssetsTask extends AsyncTask<Void, String, List<ExtractAssetsTask.Failure>>
|
|
||||||
{
|
|
||||||
public interface ExtractAssetsListener
|
|
||||||
{
|
|
||||||
public void onExtractAssetsProgress( String nextFileToExtract );
|
|
||||||
public void onExtractAssetsFinished( List<Failure> failures );
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExtractAssetsTask( AssetManager assetManager, String srcPath, String dstPath, ExtractAssetsListener listener )
|
|
||||||
{
|
|
||||||
if (assetManager == null )
|
|
||||||
throw new IllegalArgumentException( "Asset manager cannot be null" );
|
|
||||||
if( TextUtils.isEmpty( srcPath ) )
|
|
||||||
throw new IllegalArgumentException( "Source path cannot be null or empty" );
|
|
||||||
if( TextUtils.isEmpty( dstPath ) )
|
|
||||||
throw new IllegalArgumentException( "Destination path cannot be null or empty" );
|
|
||||||
if( listener == null )
|
|
||||||
throw new IllegalArgumentException( "Listener cannot be null" );
|
|
||||||
|
|
||||||
mAssetManager = assetManager;
|
|
||||||
mSrcPath = srcPath;
|
|
||||||
mDstPath = dstPath;
|
|
||||||
mListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final AssetManager mAssetManager;
|
|
||||||
private final String mSrcPath;
|
|
||||||
private final String mDstPath;
|
|
||||||
private final ExtractAssetsListener mListener;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<Failure> doInBackground( Void... params )
|
|
||||||
{
|
|
||||||
return extractAssets( mSrcPath, mDstPath );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onProgressUpdate( String... values )
|
|
||||||
{
|
|
||||||
mListener.onExtractAssetsProgress( values[0] );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute( List<ExtractAssetsTask.Failure> result )
|
|
||||||
{
|
|
||||||
mListener.onExtractAssetsFinished( result );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Failure
|
|
||||||
{
|
|
||||||
public enum Reason
|
|
||||||
{
|
|
||||||
FILE_UNWRITABLE,
|
|
||||||
FILE_UNCLOSABLE,
|
|
||||||
ASSET_UNCLOSABLE,
|
|
||||||
ASSET_IO_EXCEPTION,
|
|
||||||
FILE_IO_EXCEPTION,
|
|
||||||
}
|
|
||||||
|
|
||||||
public final String srcPath;
|
|
||||||
public final String dstPath;
|
|
||||||
public final Reason reason;
|
|
||||||
public Failure( String srcPath, String dstPath, Reason reason )
|
|
||||||
{
|
|
||||||
this.srcPath = srcPath;
|
|
||||||
this.dstPath = dstPath;
|
|
||||||
this.reason = reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
switch( reason )
|
|
||||||
{
|
|
||||||
case FILE_UNWRITABLE:
|
|
||||||
return "Failed to open file " + dstPath;
|
|
||||||
case FILE_UNCLOSABLE:
|
|
||||||
return "Failed to close file " + dstPath;
|
|
||||||
case ASSET_UNCLOSABLE:
|
|
||||||
return "Failed to close asset " + srcPath;
|
|
||||||
case ASSET_IO_EXCEPTION:
|
|
||||||
return "Failed to extract asset " + srcPath + " to file " + dstPath;
|
|
||||||
case FILE_IO_EXCEPTION:
|
|
||||||
return "Failed to add file " + srcPath + " to file " + dstPath;
|
|
||||||
default:
|
|
||||||
return "Failed using source " + srcPath + " and destination " + dstPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Failure> extractAssets( String srcPath, String dstPath )
|
|
||||||
{
|
|
||||||
final List<Failure> failures = new ArrayList<Failure>();
|
|
||||||
|
|
||||||
if( srcPath.startsWith( "/" ) )
|
|
||||||
srcPath = srcPath.substring( 1 );
|
|
||||||
|
|
||||||
String[] srcSubPaths = getAssetList( mAssetManager, srcPath );
|
|
||||||
|
|
||||||
if( srcSubPaths.length > 0 )
|
|
||||||
{
|
|
||||||
// srcPath is a directory
|
|
||||||
|
|
||||||
// Ensure the parent directories exist
|
|
||||||
new File( dstPath ).mkdirs();
|
|
||||||
|
|
||||||
// Some files are too big for Android 2.2 and below, so we break them into parts.
|
|
||||||
// We use a simple naming scheme where we just append .part0, .part1, etc.
|
|
||||||
Pattern pattern = Pattern.compile( "(.+)\\.part(\\d+)$" );
|
|
||||||
HashMap<String, Integer> fileParts = new HashMap<String, Integer>();
|
|
||||||
|
|
||||||
// Recurse into each subdirectory
|
|
||||||
for( String srcSubPath : srcSubPaths )
|
|
||||||
{
|
|
||||||
Matcher matcher = pattern.matcher( srcSubPath );
|
|
||||||
if( matcher.matches() )
|
|
||||||
{
|
|
||||||
String name = matcher.group(1);
|
|
||||||
if( fileParts.containsKey( name ) )
|
|
||||||
fileParts.put( name, fileParts.get( name ) + 1 );
|
|
||||||
else
|
|
||||||
fileParts.put( name, 1 );
|
|
||||||
}
|
|
||||||
String suffix = "/" + srcSubPath;
|
|
||||||
failures.addAll( extractAssets( srcPath + suffix, dstPath + suffix ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Combine the large broken files, if any
|
|
||||||
combineFileParts( fileParts, dstPath );
|
|
||||||
}
|
|
||||||
else // srcPath is a file.
|
|
||||||
{
|
|
||||||
// Call the progress listener before extracting
|
|
||||||
publishProgress( dstPath );
|
|
||||||
|
|
||||||
// IO objects, initialize null to eliminate lint error
|
|
||||||
OutputStream out = null;
|
|
||||||
InputStream in = null;
|
|
||||||
|
|
||||||
// Extract the file
|
|
||||||
try
|
|
||||||
{
|
|
||||||
out = new FileOutputStream( dstPath );
|
|
||||||
in = mAssetManager.open( srcPath );
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
int read;
|
|
||||||
|
|
||||||
while( ( read = in.read( buffer ) ) != -1 )
|
|
||||||
{
|
|
||||||
out.write( buffer, 0, read );
|
|
||||||
}
|
|
||||||
out.flush();
|
|
||||||
}
|
|
||||||
catch( FileNotFoundException e )
|
|
||||||
{
|
|
||||||
Failure failure = new Failure( srcPath, dstPath, Failure.Reason.FILE_UNWRITABLE );
|
|
||||||
Log.e( "ExtractAssetsTask", failure.toString() );
|
|
||||||
failures.add( failure );
|
|
||||||
}
|
|
||||||
catch( IOException e )
|
|
||||||
{
|
|
||||||
Failure failure = new Failure( srcPath, dstPath, Failure.Reason.ASSET_IO_EXCEPTION );
|
|
||||||
Log.e( "ExtractAssetsTask", failure.toString() );
|
|
||||||
failures.add( failure );
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if( out != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
catch( IOException e )
|
|
||||||
{
|
|
||||||
Failure failure = new Failure( srcPath, dstPath, Failure.Reason.FILE_UNCLOSABLE );
|
|
||||||
Log.e( "ExtractAssetsTask", failure.toString() );
|
|
||||||
failures.add( failure );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( in != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
in.close();
|
|
||||||
}
|
|
||||||
catch( IOException e )
|
|
||||||
{
|
|
||||||
Failure failure = new Failure( srcPath, dstPath, Failure.Reason.ASSET_UNCLOSABLE );
|
|
||||||
Log.e( "ExtractAssetsTask", failure.toString() );
|
|
||||||
failures.add( failure );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return failures;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String[] getAssetList( AssetManager assetManager, String srcPath )
|
|
||||||
{
|
|
||||||
String[] srcSubPaths = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
srcSubPaths = assetManager.list( srcPath );
|
|
||||||
}
|
|
||||||
catch( IOException e )
|
|
||||||
{
|
|
||||||
Log.w( "ExtractAssetsTask", "Failed to get asset file list." );
|
|
||||||
}
|
|
||||||
|
|
||||||
return srcSubPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Failure> combineFileParts( Map<String, Integer> filePieces, String dstPath )
|
|
||||||
{
|
|
||||||
List<Failure> failures = new ArrayList<Failure>();
|
|
||||||
for (String name : filePieces.keySet() )
|
|
||||||
{
|
|
||||||
String src = null;
|
|
||||||
String dst = dstPath + "/" + name;
|
|
||||||
OutputStream out = null;
|
|
||||||
InputStream in = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
out = new FileOutputStream( dst );
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
int read;
|
|
||||||
for( int i = 0; i < filePieces.get( name ); i++ )
|
|
||||||
{
|
|
||||||
src = dst + ".part" + i;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
in = new FileInputStream( src );
|
|
||||||
while( ( read = in.read( buffer ) ) != -1 )
|
|
||||||
{
|
|
||||||
out.write( buffer, 0, read );
|
|
||||||
}
|
|
||||||
out.flush();
|
|
||||||
}
|
|
||||||
catch( IOException e )
|
|
||||||
{
|
|
||||||
Failure failure = new Failure( src, dst, Failure.Reason.FILE_IO_EXCEPTION );
|
|
||||||
Log.e( "ExtractAssetsTask", failure.toString() );
|
|
||||||
failures.add( failure );
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if( in != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
in.close();
|
|
||||||
new File( src ).delete();
|
|
||||||
}
|
|
||||||
catch( IOException e )
|
|
||||||
{
|
|
||||||
Failure failure = new Failure( src, dst, Failure.Reason.FILE_UNCLOSABLE );
|
|
||||||
Log.e( "ExtractAssetsTask", failure.toString() );
|
|
||||||
failures.add( failure );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( FileNotFoundException e )
|
|
||||||
{
|
|
||||||
Failure failure = new Failure( src, dst, Failure.Reason.FILE_UNWRITABLE );
|
|
||||||
Log.e( "ExtractAssetsTask", failure.toString() );
|
|
||||||
failures.add( failure );
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if( out != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
catch( IOException e )
|
|
||||||
{
|
|
||||||
Failure failure = new Failure( src, dst, Failure.Reason.FILE_UNCLOSABLE );
|
|
||||||
Log.e( "ExtractAssetsTask", failure.toString() );
|
|
||||||
failures.add( failure );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return failures;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue