mirror of
https://github.com/CatimaLoyalty/Android.git
synced 2026-03-31 05:41:51 -04:00
Support importing content URIs and file URIs
When importing backed up settings other activities may provide data via a content URI. This is especially likely on Android 7+, where providing a file URI is flagged as a security issue. To support such activities, this commit enables supporting content URIs for importing settings.
This commit is contained in:
@@ -24,6 +24,10 @@ import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
|
||||
public class ImportExportActivity extends AppCompatActivity
|
||||
@@ -132,24 +136,34 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
startImport(exportFile);
|
||||
String fileUri = exportFile.toURI().toString();
|
||||
try
|
||||
{
|
||||
FileInputStream stream = new FileInputStream(exportFile);
|
||||
startImport(stream, fileUri);
|
||||
}
|
||||
catch(FileNotFoundException e)
|
||||
{
|
||||
Log.e(TAG, "Could not import file " + exportFile.getAbsolutePath(), e);
|
||||
onImportComplete(false, fileUri);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void startImport(File target)
|
||||
private void startImport(final InputStream target, final String targetUri)
|
||||
{
|
||||
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener()
|
||||
{
|
||||
@Override
|
||||
public void onTaskComplete(boolean success)
|
||||
{
|
||||
onImportComplete(success, exportFile);
|
||||
onImportComplete(success, targetUri);
|
||||
}
|
||||
};
|
||||
|
||||
importExporter = new ImportExportTask(ImportExportActivity.this,
|
||||
true, DataFormat.CSV, target, listener);
|
||||
DataFormat.CSV, target, listener);
|
||||
importExporter.execute();
|
||||
}
|
||||
|
||||
@@ -165,7 +179,7 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
};
|
||||
|
||||
importExporter = new ImportExportTask(ImportExportActivity.this,
|
||||
false, DataFormat.CSV, exportFile, listener);
|
||||
DataFormat.CSV, exportFile, listener);
|
||||
importExporter.execute();
|
||||
}
|
||||
|
||||
@@ -220,7 +234,7 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void onImportComplete(boolean success, File path)
|
||||
private void onImportComplete(boolean success, String path)
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
|
||||
@@ -236,7 +250,7 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
int messageId = success ? R.string.importedFrom : R.string.importFailed;
|
||||
|
||||
final String template = getResources().getString(messageId);
|
||||
final String message = String.format(template, path.getAbsolutePath());
|
||||
final String message = String.format(template, path);
|
||||
builder.setMessage(message);
|
||||
builder.setNeutralButton(R.string.ok, new DialogInterface.OnClickListener()
|
||||
{
|
||||
@@ -346,27 +360,24 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
|
||||
if (resultCode == RESULT_OK && requestCode == CHOOSE_EXPORT_FILE)
|
||||
{
|
||||
String path = null;
|
||||
|
||||
Uri uri = data.getData();
|
||||
if(uri != null && uri.toString().startsWith("/"))
|
||||
{
|
||||
uri = Uri.parse("file://" + uri.toString());
|
||||
}
|
||||
|
||||
if(uri != null)
|
||||
{
|
||||
path = uri.getPath();
|
||||
}
|
||||
|
||||
if(path != null)
|
||||
{
|
||||
Log.e(TAG, "Starting file import with: " + uri.toString());
|
||||
startImport(new File(path));
|
||||
try
|
||||
{
|
||||
InputStream reader = getContentResolver().openInputStream(uri);
|
||||
Log.e(TAG, "Starting file import with: " + uri.toString());
|
||||
startImport(reader, uri.toString());
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
Log.e(TAG, "Failed to import file: " + uri.toString(), e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.e(TAG, "Fail to make sense of URI returned from activity: " + (uri != null ? uri.toString() : "null"));
|
||||
Log.e(TAG, "Activity returned a NULL URI");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.Charset;
|
||||
@@ -24,29 +25,46 @@ class ImportExportTask extends AsyncTask<Void, Void, Boolean>
|
||||
private boolean doImport;
|
||||
private DataFormat format;
|
||||
private File target;
|
||||
private InputStream inputStream;
|
||||
private TaskCompleteListener listener;
|
||||
|
||||
private ProgressDialog progress;
|
||||
|
||||
public ImportExportTask(Activity activity, boolean doImport, DataFormat format, File target,
|
||||
/**
|
||||
* Constructor which will setup a task for exporting to the given file
|
||||
*/
|
||||
ImportExportTask(Activity activity, DataFormat format, File target,
|
||||
TaskCompleteListener listener)
|
||||
{
|
||||
super();
|
||||
this.activity = activity;
|
||||
this.doImport = doImport;
|
||||
this.doImport = false;
|
||||
this.format = format;
|
||||
this.target = target;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private boolean performImport(File importFile, DBHelper db)
|
||||
/**
|
||||
* Constructor which will setup a task for importing from the given InputStream.
|
||||
*/
|
||||
ImportExportTask(Activity activity, DataFormat format, InputStream input,
|
||||
TaskCompleteListener listener)
|
||||
{
|
||||
super();
|
||||
this.activity = activity;
|
||||
this.doImport = true;
|
||||
this.format = format;
|
||||
this.inputStream = input;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private boolean performImport(InputStream stream, DBHelper db)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
try
|
||||
{
|
||||
FileInputStream fileReader = new FileInputStream(importFile);
|
||||
InputStreamReader reader = new InputStreamReader(fileReader, Charset.forName("UTF-8"));
|
||||
InputStreamReader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
|
||||
result = MultiFormatImporter.importData(db, reader, format);
|
||||
reader.close();
|
||||
}
|
||||
@@ -55,7 +73,7 @@ class ImportExportTask extends AsyncTask<Void, Void, Boolean>
|
||||
Log.e(TAG, "Unable to import file", e);
|
||||
}
|
||||
|
||||
Log.i(TAG, "Import of '" + importFile.getAbsolutePath() + "' result: " + result);
|
||||
Log.i(TAG, "Import result: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -105,7 +123,7 @@ class ImportExportTask extends AsyncTask<Void, Void, Boolean>
|
||||
|
||||
if(doImport)
|
||||
{
|
||||
result = performImport(target, db);
|
||||
result = performImport(inputStream, db);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -17,6 +17,8 @@ import org.robolectric.annotation.Config;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
@@ -219,7 +221,7 @@ public class ImportExportTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useImportExportTask()
|
||||
public void useImportExportTask() throws FileNotFoundException
|
||||
{
|
||||
final int NUM_CARDS = 10;
|
||||
|
||||
@@ -233,7 +235,7 @@ public class ImportExportTest
|
||||
TestTaskCompleteListener listener = new TestTaskCompleteListener();
|
||||
|
||||
// Export to the file
|
||||
ImportExportTask task = new ImportExportTask(activity, false, format, exportFile, listener);
|
||||
ImportExportTask task = new ImportExportTask(activity, format, exportFile, listener);
|
||||
task.execute();
|
||||
|
||||
// Actually run the task to completion
|
||||
@@ -249,7 +251,9 @@ public class ImportExportTest
|
||||
|
||||
listener = new TestTaskCompleteListener();
|
||||
|
||||
task = new ImportExportTask(activity, true, format, exportFile, listener);
|
||||
FileInputStream fileStream = new FileInputStream(exportFile);
|
||||
|
||||
task = new ImportExportTask(activity, format, fileStream, listener);
|
||||
task.execute();
|
||||
|
||||
// Actually run the task to completion
|
||||
|
||||
Reference in New Issue
Block a user