2021-10-12 17:40:20 -04:00
|
|
|
package com.virtualapplications.play;
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.OutputStream;
|
2021-11-08 16:41:24 -05:00
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.HashSet;
|
2021-10-12 17:40:20 -04:00
|
|
|
|
|
|
|
import androidx.documentfile.provider.DocumentFile;
|
|
|
|
|
|
|
|
class DataFilesMigrationProcess
|
|
|
|
{
|
|
|
|
//This class handles migration of data from the old "Play Data Files" folder to the data folder inside the app
|
|
|
|
//(ie.: Android 11 migration)
|
|
|
|
|
|
|
|
//Some notes/questions for the migration process:
|
|
|
|
//- Should we migrate the bootables.db file?
|
2021-10-13 09:36:58 -04:00
|
|
|
//- Should we overwrite files systematically?
|
|
|
|
// No, we can assume that files in the Data Files are always older
|
2021-10-12 17:40:20 -04:00
|
|
|
|
|
|
|
final Context _context;
|
2021-11-08 16:41:24 -05:00
|
|
|
final String _configXmlFileName = "config.xml";
|
|
|
|
final String _bootablesDbFileName = "bootables.db";
|
|
|
|
final HashSet<String> _excludedFileNames = new HashSet<>(Arrays.asList(_configXmlFileName, _bootablesDbFileName));
|
2021-10-12 17:40:20 -04:00
|
|
|
|
|
|
|
public DataFilesMigrationProcess(Context context)
|
|
|
|
{
|
|
|
|
_context = context;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Start(Uri srcFolderUri) throws Exception
|
|
|
|
{
|
|
|
|
CheckIsDataFilesFolder(srcFolderUri);
|
|
|
|
File dataFilesFolder = new File(_context.getFilesDir().getAbsolutePath() + "/Play Data Files");
|
|
|
|
if(!dataFilesFolder.exists())
|
|
|
|
{
|
|
|
|
throw new Exception("Play Data Files doesn't exist.");
|
|
|
|
}
|
|
|
|
DocumentFile dstFolderDoc = DocumentFile.fromFile(dataFilesFolder);
|
|
|
|
DocumentFile srcFolderDoc = DocumentFile.fromTreeUri(_context, srcFolderUri);
|
2021-10-13 09:36:58 -04:00
|
|
|
CopyTree(dstFolderDoc, srcFolderDoc);
|
2021-10-12 17:40:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void CheckIsDataFilesFolder(Uri srcFolderUri) throws Exception
|
|
|
|
{
|
|
|
|
DocumentFile folderDoc = DocumentFile.fromTreeUri(_context, srcFolderUri);
|
2021-11-08 16:41:24 -05:00
|
|
|
DocumentFile configFile = folderDoc.findFile(_configXmlFileName);
|
|
|
|
DocumentFile bootablesFile = folderDoc.findFile(_bootablesDbFileName);
|
|
|
|
if((configFile == null) && (bootablesFile == null))
|
2021-10-12 17:40:20 -04:00
|
|
|
{
|
|
|
|
throw new Exception("Selected folder doesn't seem to be a Data Files folder.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-13 09:36:58 -04:00
|
|
|
void CopyFile(DocumentFile dstFileDoc, DocumentFile srcFileDoc) throws IOException
|
2021-10-12 17:40:20 -04:00
|
|
|
{
|
2021-10-13 09:36:58 -04:00
|
|
|
InputStream srcStream = _context.getContentResolver().openInputStream(srcFileDoc.getUri());
|
|
|
|
OutputStream dstStream = _context.getContentResolver().openOutputStream(dstFileDoc.getUri());
|
|
|
|
try
|
2021-10-12 17:40:20 -04:00
|
|
|
{
|
2021-10-13 09:36:58 -04:00
|
|
|
int bufferSize = 0x10000;
|
|
|
|
byte[] buffer = new byte[bufferSize];
|
|
|
|
while(true)
|
|
|
|
{
|
|
|
|
int amountRead = srcStream.read(buffer);
|
|
|
|
if(amountRead == -1) break;
|
|
|
|
dstStream.write(buffer, 0, amountRead);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
srcStream.close();
|
|
|
|
dstStream.close();
|
2021-10-12 17:40:20 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-13 09:36:58 -04:00
|
|
|
void CopyTree(DocumentFile dstFolderDoc, DocumentFile srcFolderDoc)
|
2021-10-12 17:40:20 -04:00
|
|
|
{
|
|
|
|
for(DocumentFile srcFileDoc : srcFolderDoc.listFiles())
|
|
|
|
{
|
|
|
|
if(srcFileDoc.isDirectory())
|
|
|
|
{
|
|
|
|
Log.w(Constants.TAG, String.format("Creating directory '%s'...", srcFileDoc.getName()));
|
|
|
|
DocumentFile dstFileDoc = dstFolderDoc.createDirectory(srcFileDoc.getName());
|
2021-10-13 09:36:58 -04:00
|
|
|
CopyTree(dstFileDoc, srcFileDoc);
|
2021-10-12 17:40:20 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-13 09:36:58 -04:00
|
|
|
Log.w(Constants.TAG, String.format("Copying file '%s'...", srcFileDoc.getName()));
|
2021-10-12 17:40:20 -04:00
|
|
|
try
|
|
|
|
{
|
2021-10-13 09:36:58 -04:00
|
|
|
if(dstFolderDoc.findFile(srcFileDoc.getName()) != null)
|
2021-10-12 17:40:20 -04:00
|
|
|
{
|
2021-10-13 09:36:58 -04:00
|
|
|
Log.w(Constants.TAG, "Skipping because it already exists.");
|
|
|
|
continue;
|
2021-10-12 17:40:20 -04:00
|
|
|
}
|
2021-11-08 16:41:24 -05:00
|
|
|
if(_excludedFileNames.contains(srcFileDoc.getName()))
|
|
|
|
{
|
|
|
|
Log.w(Constants.TAG, "Skipping because it is excluded.");
|
|
|
|
continue;
|
|
|
|
}
|
2021-10-13 09:36:58 -04:00
|
|
|
DocumentFile dstFileDoc = dstFolderDoc.createFile("", srcFileDoc.getName());
|
|
|
|
CopyFile(dstFileDoc, srcFileDoc);
|
2021-10-12 17:40:20 -04:00
|
|
|
}
|
|
|
|
catch(Exception ex)
|
|
|
|
{
|
|
|
|
Log.e(Constants.TAG, "Failed to copy file.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|