Handle null URI while uploading picture (#2262)

* Handle null URI while uploading picture

* Modify cache method to never return null path

* Fix tests
This commit is contained in:
Vivek Maskara 2019-01-04 13:51:55 +05:30 committed by Josephine Lim
parent e69c03cf83
commit e773a82206
6 changed files with 71 additions and 36 deletions

View file

@ -98,14 +98,27 @@ public class FileUtils {
}
}
static String createCopyPathAndCopy(boolean useExternalStorage,
Uri uri,
ContentResolver contentResolver,
Context context) throws IOException {
return useExternalStorage ? createExternalCopyPathAndCopy(uri, contentResolver) :
createCopyPathAndCopy(uri, context);
}
/**
* In older devices getPath() may fail depending on the source URI. Creating and using a copy of the file seems to work instead.
*
* @return path of copy
*/
@NonNull
static String createExternalCopyPathAndCopy(Uri uri, ContentResolver contentResolver) throws IOException {
FileDescriptor fileDescriptor = contentResolver.openFileDescriptor(uri, "r").getFileDescriptor();
@Nullable
private static String createExternalCopyPathAndCopy(Uri uri, ContentResolver contentResolver) throws IOException {
ParcelFileDescriptor parcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r");
if (parcelFileDescriptor == null) {
return null;
}
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
String copyPath = Environment.getExternalStorageDirectory().toString() + "/CommonsApp/" + new Date().getTime() + "." + getFileExt(uri, contentResolver);
File newFile = new File(Environment.getExternalStorageDirectory().toString() + "/CommonsApp");
newFile.mkdir();
@ -119,8 +132,8 @@ public class FileUtils {
*
* @return path of copy
*/
@NonNull
static String createCopyPathAndCopy(Uri uri, Context context) throws IOException {
@Nullable
private static String createCopyPathAndCopy(Uri uri, Context context) throws IOException {
FileDescriptor fileDescriptor = context.getContentResolver().openFileDescriptor(uri, "r").getFileDescriptor();
String copyPath = context.getCacheDir().getAbsolutePath() + "/" + new Date().getTime() + "." + getFileExt(uri, context.getContentResolver());
FileUtils.copy(fileDescriptor, copyPath);

View file

@ -20,12 +20,14 @@ public class FileUtilsWrapper {
}
public String createExternalCopyPathAndCopy(Uri uri, ContentResolver contentResolver) throws IOException {
return FileUtils.createExternalCopyPathAndCopy(uri, contentResolver);
}
public String createCopyPathAndCopy(Uri uri, Context context) throws IOException {
return FileUtils.createCopyPathAndCopy(uri, context);
public String createCopyPathAndCopy(boolean useExtStorage,
Uri uri,
ContentResolver contentResolver,
Context context) throws IOException {
return FileUtils.createCopyPathAndCopy(useExtStorage,
uri,
contentResolver,
context);
}
public String getFileExt(String fileName) {

View file

@ -71,7 +71,6 @@ import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ENTITY_ID_
import static fr.free.nrw.commons.wikidata.WikidataConstants.WIKIDATA_ITEM_LOCATION;
public class UploadActivity extends AuthenticatedActivity implements UploadView, SimilarImageInterface {
@Inject InputMethodManager inputMethodManager;
@Inject MediaWikiApi mwApi;
@Inject @Named("direct_nearby_upload_prefs") SharedPreferences directPrefs;
@Inject UploadPresenter presenter;
@ -613,6 +612,10 @@ public class UploadActivity extends AuthenticatedActivity implements UploadView,
if (Intent.ACTION_SEND.equals(intent.getAction())) {
Uri mediaUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if(mediaUri == null) {
handleNullMedia();
return;
}
if (intent.getBooleanExtra("isDirectUpload", false)) {
String imageTitle = directPrefs.getString("Title", "");
String imageDesc = directPrefs.getString("Desc", "");
@ -627,10 +630,24 @@ public class UploadActivity extends AuthenticatedActivity implements UploadView,
} else if (Intent.ACTION_SEND_MULTIPLE.equals(intent.getAction())) {
ArrayList<Uri> urisList = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
Timber.i("Received multiple upload %s", urisList.size());
if(urisList.isEmpty()) {
handleNullMedia();
return;
}
presenter.receive(urisList, mimeType, source);
}
}
/**
* Handle null URI from the received intent.
* Current implementation will simply show a toast and finish the upload activity.
*/
private void handleNullMedia() {
ViewUtil.showLongToast(this, R.string.error_processing_image);
finish();
}
private void updateCardState(boolean state, ImageView button, View... content) {
button.animate().rotation(button.getRotation() + (state ? 180 : -180)).start();
if (content != null) {

View file

@ -27,6 +27,7 @@ import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.utils.BitmapRegionDecoderWrapper;
import fr.free.nrw.commons.utils.ImageUtils;
import fr.free.nrw.commons.utils.ImageUtilsWrapper;
import fr.free.nrw.commons.utils.StringUtils;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.disposables.Disposable;
@ -171,6 +172,7 @@ public class UploadModel {
/**
* Get file creation date from uri from all possible content providers
*
* @param media
* @return
*/
@ -354,23 +356,25 @@ public class UploadModel {
/**
* Copy files into local storage and return file path
*
* If somehow copy fails, it returns the original path
* @param media Uri of the file
* @return path of the enw file
*/
private String cacheFileUpload(Uri media) {
String finalFilePath;
try {
String copyPath;
if (useExtStorage)
copyPath = fileUtilsWrapper.createExternalCopyPathAndCopy(media, contentResolver);
else
copyPath = fileUtilsWrapper.createCopyPathAndCopy(media, context);
Timber.i("File path is " + copyPath);
return copyPath;
} catch (IOException e) {
Timber.w(e, "Error in copying URI " + media.getPath());
return null;
String copyFilePath = fileUtilsWrapper.createCopyPathAndCopy(useExtStorage, media, contentResolver, context);
Timber.i("Copied file path is %s", copyFilePath);
finalFilePath = copyFilePath;
} catch (Exception e) {
Timber.w(e, "Error in copying URI %s. Using original file path instead", media.getPath());
finalFilePath = media.getPath();
}
if (StringUtils.isNullOrWhiteSpace(finalFilePath)) {
finalFilePath = media.getPath();
}
return finalFilePath;
}
void keepPicture() {

View file

@ -450,6 +450,7 @@ Upload your first media by touching the camera or gallery icon above.</string>
<string name="this_function_needs_network_connection">This function requires network connection, please check your connection settings.</string>
<string name="bad_token_error_proposed_solution">Upload failed due to issues with edit token. Please try logging out and in again. </string>
<string name="error_processing_image">Error occurred while processing the image. Please try again!</string>
<plurals name="receiving_shared_content">
<item quantity="one">Receiving shared content. Processing the image might take some time depending on the size of the image and your device</item>

View file

@ -64,10 +64,8 @@ class UploadModelTest {
`when`(context!!.applicationContext)
.thenReturn(mock(Application::class.java))
`when`(fileUtilsWrapper!!.createCopyPathAndCopy(any(Uri::class.java), any(Context::class.java)))
`when`(fileUtilsWrapper!!.createCopyPathAndCopy(anyBoolean(), any(Uri::class.java), nullable(ContentResolver::class.java), any(Context::class.java)))
.thenReturn("file.jpg")
`when`(fileUtilsWrapper!!.createExternalCopyPathAndCopy(any(Uri::class.java), any(ContentResolver::class.java)))
.thenReturn("extFile.jpg")
`when`(fileUtilsWrapper!!.getFileExt(anyString()))
.thenReturn("jpg")
`when`(fileUtilsWrapper!!.getSHA1(any(InputStream::class.java)))