Skip to content

Commit

Permalink
handle external storage not available
Browse files Browse the repository at this point in the history
  • Loading branch information
mtotschnig committed Apr 4, 2015
1 parent 9f22d07 commit ba15b04
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.totschnig.myexpenses.dialog.ConfirmationDialogFragment.ConfirmationDialogListener;
import org.totschnig.myexpenses.dialog.DialogUtils;
import org.totschnig.myexpenses.dialog.MessageDialogFragment;
import org.totschnig.myexpenses.fragment.DbWriteFragment;
import org.totschnig.myexpenses.fragment.SplitPartList;
import org.totschnig.myexpenses.model.Account;
import org.totschnig.myexpenses.model.Account.Type;
Expand Down Expand Up @@ -1358,18 +1359,30 @@ public void onPostExecute(Object result) {
return;
}
Long sequenceCount = (Long) result;
if (sequenceCount == -1L) {
if (sequenceCount < 0L) {
if (mTransaction instanceof Template) {
//for the moment, the only case where saving will fail
//if the unique constraint for template titles is violated
//TODO: we should probably validate the title earlier
mTitleText.setError(getString(R.string.template_title_exists,((Template) mTransaction).title));
mCreateNew = false;
} else {
//possibly the selected category has been deleted
mCatId = null;
mCategoryButton.setText(R.string.select);
Toast.makeText(this, "Error while saving transaction. Try again", Toast.LENGTH_SHORT).show();
String errorMsg;
switch(sequenceCount.intValue()) {
case DbWriteFragment.ERROR_EXTERNAL_STORAGE_NOT_AVAILABLE:
errorMsg=getString(R.string.external_storage_unavailable);
break;
case DbWriteFragment.ERROR_UNKNOWN:
errorMsg="Error while saving picture";
break;
default:
//possibly the selected category has been deleted
mCatId = null;
mCategoryButton.setText(R.string.select);

errorMsg="Error while saving transaction";
}
Toast.makeText(this, errorMsg, Toast.LENGTH_LONG).show();
}
} else {
if (mRecordTemplateWidget) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@
* the later is only implemented for transactions
*/
public class DbWriteFragment extends Fragment {


public static final int ERROR_UNKNOWN = -1;
public static final int ERROR_EXTERNAL_STORAGE_NOT_AVAILABLE = -2;
public static final int ERROR_PICTURE_SAVE_UNKNOWN = -3;


/**
* Callback interface through which the fragment will report the
* task's progress and results back to the Activity.
Expand Down Expand Up @@ -130,18 +135,27 @@ protected void onPreExecute() {
*/
@Override
protected Object doInBackground(Model... object) {
long error = ERROR_UNKNOWN;
if (object[0] == null) {
Log.w(MyApplication.TAG, "DbWriteFragment called from an activity that did not provide an object");
return null;
}
Uri uri = null;

try {
uri = object[0].save();
} catch (Exception e) {
} catch (Transaction.ExternalStorageNotAvailableException e) {
error = ERROR_EXTERNAL_STORAGE_NOT_AVAILABLE;
}
catch (Transaction.UnknownPictureSaveException e) {
Utils.reportToAcra(e);
error = ERROR_PICTURE_SAVE_UNKNOWN;
}
catch (Exception e) {
Utils.reportToAcra(e);
}
if (returnSequenceCount && object[0] instanceof Transaction)
return uri == null ? -1 : Transaction.getSequenceCount();
return uri == null ? error : Transaction.getSequenceCount();
else
return uri;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,14 +399,28 @@ public Uri save() {
}
return uri;
}
private void throwExternalNotAvailable() {
throw new ExternalStorageNotAvailableException();
}

protected void savePicture(ContentValues initialValues) {
if (pictureUri!=null) {
if (pictureUri.toString().startsWith(Utils.getPictureUriBase(false))) {
String pictureUriBase = Utils.getPictureUriBase(false);
if (pictureUriBase==null) {
throwExternalNotAvailable();
}
if (pictureUri.toString().startsWith(pictureUriBase)) {
Log.d("DEBUG", "got Uri in our home space, nothing todo");
} else {
boolean isInTempFolder = pictureUri.toString().startsWith(Utils.getPictureUriBase(true));
pictureUriBase = Utils.getPictureUriBase(true);
if (pictureUriBase==null) {
throwExternalNotAvailable();
}
boolean isInTempFolder = pictureUri.toString().startsWith(pictureUriBase);
Uri homeUri = Utils.getOutputMediaUri(false);
if (homeUri==null) {
throwExternalNotAvailable();
}
if (isInTempFolder && homeUri.getScheme().equals("file")) {
if (new File(pictureUri.getPath()).renameTo(new File(homeUri.getPath()))) {
setPictureUri(homeUri);
Expand All @@ -416,13 +430,15 @@ protected void savePicture(ContentValues initialValues) {
}
} else {
try {
Utils.copy(pictureUri,homeUri);
if (!Utils.copy(pictureUri,homeUri)) {
throw new IOException("Copy to homeUri "+homeUri.getPath()+" failed");
}
if (isInTempFolder) {
new File(pictureUri.getPath()).delete();
}
setPictureUri(homeUri);
} catch (IOException e) {
Utils.reportToAcra(e);
throw new UnknownPictureSaveException(e);
}
}
}
Expand Down Expand Up @@ -594,4 +610,11 @@ public static Intent getViewIntent(Uri pictureUri) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
return intent;
}
public static class ExternalStorageNotAvailableException extends IllegalStateException {
}
public static class UnknownPictureSaveException extends IllegalStateException {
public UnknownPictureSaveException(IOException e) {
super(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

package org.totschnig.myexpenses.provider;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Locale;

Expand All @@ -38,6 +39,7 @@
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import static org.totschnig.myexpenses.provider.DatabaseConstants.*;

Expand Down Expand Up @@ -848,10 +850,24 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS feature_used");
}
if (oldVersion < 51) {
String prefix = Uri.fromFile(Utils.getPictureDir(false)).toString()+"/";
File pictureDir = Utils.getPictureDir(false);
//fallback if not mounted
if (pictureDir==null) {
pictureDir = new File(
Environment.getExternalStorageDirectory().getPath() +
"/Android/data/"+MyApplication.getInstance().getPackageName()+"/files",
Environment.DIRECTORY_PICTURES);
}
if (!pictureDir.exists()) {
Utils.reportToAcra(new Exception("Unable to calculate pictureDir during upgrade"));
}
//if pictureDir does not exist, we use its URI nonetheless, in order to have the data around
//for potential trouble handling
String prefix = Uri.fromFile(pictureDir).toString() + "/";
String postfix = ".jpg";
//if picture_id concat expression will also be null
db.execSQL("UPDATE transactions set picture_id = '"+prefix+"'||picture_id||'"+postfix+"'");
db.execSQL("UPDATE transactions set picture_id = '" + prefix + "'||picture_id||'" + postfix + "'");

db.execSQL("CREATE TABLE stale_uris ( picture_id text);");
db.execSQL("CREATE TRIGGER cache_stale_uri BEFORE DELETE ON transactions WHEN old.picture_id NOT NULL "
+ " BEGIN INSERT INTO stale_uris VALUES (old.picture_id); END");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,8 @@ protected Object doInBackground(T... ids) {
success = staleFile.renameTo(new File(staleFileDir, staleFile.getName()));
} else {
try {
Utils.copy(imageFileUri, Uri.fromFile(new File(staleFileDir, imageFileUri.getLastPathSegment())));
success = cr.delete(imageFileUri, null, null) > 0;
if (Utils.copy(imageFileUri, Uri.fromFile(new File(staleFileDir, imageFileUri.getLastPathSegment()))))
success = cr.delete(imageFileUri, null, null) > 0;
} catch (IOException e) {
e.printStackTrace();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,13 +282,14 @@ protected Result doInBackground(Void... ignored) {
Uri restored = null;
if (backupImage.exists()) {
File restoredImage = Utils.getOutputMediaFile(fileName.substring(0,fileName.lastIndexOf('.')),false);
if (!Utils.copy(backupImage,restoredImage)) {
if (restoredImage == null || !Utils.copy(backupImage,restoredImage)) {
Log.e(MyApplication.TAG,String.format("Could not restore file %s from backup",fromBackup.toString()));
} else {
restored = MyApplication.getInstance().isProtected() ?
FileProvider.getUriForFile(MyApplication.getInstance(),
"org.totschnig.myexpenses.fileprovider", restoredImage) :
Uri.fromFile(restoredImage);
}
restored = MyApplication.getInstance().isProtected() ?
FileProvider.getUriForFile(MyApplication.getInstance(),
"org.totschnig.myexpenses.fileprovider",restoredImage) :
Uri.fromFile(restoredImage);
} else {
Log.e(MyApplication.TAG,String.format("Could not restore file %s from backup",fromBackup.toString()));
}
Expand All @@ -312,6 +313,7 @@ protected Result doInBackground(Void... ignored) {

private void registerAsStale(boolean secure) {
File dir = Utils.getPictureDir(secure);
if (dir==null) return;
ContentValues values = new ContentValues();
for (File file: dir.listFiles()) {
Uri uri = secure ? FileProvider.getUriForFile(MyApplication.getInstance(),
Expand Down
72 changes: 44 additions & 28 deletions myExpenses/src/main/java/org/totschnig/myexpenses/util/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ public static File getOutputMediaFile(String fileName, boolean temp) {
// using Environment.getExternalStorageState() before doing this.

File mediaStorageDir = temp ? getCacheDir() : getPictureDir();
if (mediaStorageDir==null) return null;
int postfix = 0;
File result;
do {
Expand All @@ -443,18 +444,26 @@ public static File getOutputMediaFile(String fileName, boolean temp) {
public static Uri getOutputMediaUri(boolean temp) {
String fileName = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US)
.format(new Date());
if (MyApplication.getInstance().isProtected() && !temp) {
return FileProvider.getUriForFile(MyApplication.getInstance(),
"org.totschnig.myexpenses.fileprovider",
getOutputMediaFile(fileName,false));
} else {
return Uri.fromFile(getOutputMediaFile(fileName,temp));
}
}
public static String getPictureUriBase(boolean temp) {
String sampleUri = getOutputMediaUri(temp).toString();
return sampleUri.substring(0,sampleUri.lastIndexOf('/'));
File outputMediaFile;
if (MyApplication.getInstance().isProtected() && !temp) {
outputMediaFile = getOutputMediaFile(fileName, false);
if (outputMediaFile==null) return null;
return FileProvider.getUriForFile(MyApplication.getInstance(),
"org.totschnig.myexpenses.fileprovider",
outputMediaFile);
} else {
outputMediaFile = getOutputMediaFile(fileName,temp);
if (outputMediaFile==null) return null;
return Uri.fromFile(outputMediaFile);
}
}

public static String getPictureUriBase(boolean temp) {
Uri sampleUri = getOutputMediaUri(temp);
if (sampleUri==null) return null;
String uriString = sampleUri.toString();
return uriString.substring(0,uriString.lastIndexOf('/'));
}

private static String getOutputMediaFileName(String base,int postfix) {
if (postfix>0) {
Expand All @@ -466,13 +475,17 @@ public static File getPictureDir() {
return getPictureDir(MyApplication.getInstance().isProtected());
}
public static File getPictureDir(boolean secure) {
File result = secure ?
new File (MyApplication.getInstance().getFilesDir(),
"images") :
MyApplication.getInstance().getExternalFilesDir(
Environment.DIRECTORY_PICTURES);
result.mkdir();
return result;
File result;
if (secure) {
result = new File (MyApplication.getInstance().getFilesDir(),
"images");
} else {
result = MyApplication.getInstance().getExternalFilesDir(
Environment.DIRECTORY_PICTURES);
}
if (result==null) return null;
result.mkdir();
return result.exists() ? result : null;
}

/**
Expand All @@ -482,33 +495,36 @@ public static File getPictureDir(boolean secure) {
* @param dest
* @return
*/
public static void copy(Uri src, Uri dest) throws IOException {
public static boolean copy(Uri src, Uri dest) throws IOException {
InputStream input = null;
OutputStream output = null;
boolean success = false;

try {
input = MyApplication.getInstance().getContentResolver()
.openInputStream(src);
output = MyApplication.getInstance().getContentResolver()
.openOutputStream(dest);
final byte[] buffer = new byte[1024];
int read;
if (input!=null && output!=null) {
final byte[] buffer = new byte[1024];
int read;

while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
success = true;
}

output.flush();

} finally {
try {
input.close();
if (input!=null) input.close();
} catch (IOException e) {
}
try {
output.close();
if (output!=null) output.close();
} catch (IOException e) {
}
return success;
}
}

Expand Down

0 comments on commit ba15b04

Please sign in to comment.