Skip to content

Commit d29aa2e

Browse files
neslihanturanmisaochan
authored andcommitted
Fix urgent crashes A and E (commons-app#1749)
* Create utility class for contribution process * implement method to save five from given URİ * Add file utilities for directory checks * Add ContributionUtils for saving file during upload * Change method call acordingly with handleImagePicked() method * Call method to save file temproarily when a photo to upload is chosen from contributions list. * Call method to save file temproarily when a photo to upload is chosen from nearby list and map * Arrange method call * Write a method to save file temporarily during upload process. It will save the file to a internal path and it will be deleted by another method after upload process is done. * Add a method to save a file to a given path from a content provider Uri * On openAssetFileDescriptor method, use URi from temporarily saved file, instead of Contributions.getLocalUri which was Uri from content provider * Edit uploadContribution method so that it will use FileInputStream from temporarily saved file, insdeat of the Uri from content provider. * Make it work * Code cleanup * Add directory cleaner method * Call temp directory cleaner method at the end of uplpoad process * Use FileInputStream insted * Add directory cleaner method * Add file removal method * Use external directory instead * Make destination file name flexible * Make it work with share action coming from another activity * Make it work for Multiple hare Activity * Code cleanup * Solve camera issue * Fix camera crash * Cleanup * Revert change of commenting out posibly useles code, because I am not sure if it is useless or not. Requires discussion * Use timestamp in temoorary file names, so that we wont never create same file and access old file reference. It was a weird problem though * Code cleanup * Add nullable annotation to handleImagePicked method uri parameter * Add Nullable anotation to method * Code cleanup * Bugfix: use uri.getPath() instead uri.toString * Remove unecesarry file saving operation, which was added accidentally * Fix travis fail * Remove temp file if upload gets failed and file is still there * Code cleanup:Remove unused parameters from removeTempFile method * Empty temp directory on app create, in case some of files are still there * Add null check to array to prevent NPE on first run * Fix multiple uploads bug * Remove file if upload is succeed * Add external storage utility methods * Check external file permission before saving files temporarily * finish activity if permission is not granted * Add log lines * Remove files even if user decides to go back without sharing * Add easy null check * Change storage permission settings in singe upload fragment too * Finish app if permission is not granted * Code optimisation * Remove temp file if upload process never is finalised on activity stop * Bugfix maybe contribution is never created * Fix travis build
1 parent 22d2b17 commit d29aa2e

18 files changed

+441
-67
lines changed

app/src/main/java/fr/free/nrw/commons/CommonsApplication.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import fr.free.nrw.commons.di.ApplicationlessInjection;
2828
import fr.free.nrw.commons.modifications.ModifierSequenceDao;
2929
import fr.free.nrw.commons.upload.FileUtils;
30+
import fr.free.nrw.commons.utils.ContributionUtils;
3031
import io.reactivex.android.schedulers.AndroidSchedulers;
3132
import io.reactivex.schedulers.Schedulers;
3233
import timber.log.Timber;
@@ -68,7 +69,6 @@ public class CommonsApplication extends MultiDexApplication {
6869
@Override
6970
public void onCreate() {
7071
super.onCreate();
71-
7272
ApplicationlessInjection
7373
.getInstance(this)
7474
.getCommonsApplicationComponent()
@@ -81,6 +81,8 @@ public void onCreate() {
8181
if (setupLeakCanary() == RefWatcher.DISABLED) {
8282
return;
8383
}
84+
// Empty temp directory in case some temp files are created and never removed.
85+
ContributionUtils.emptyTemporaryDirectory();
8486

8587
Timber.plant(new Timber.DebugTree());
8688

app/src/main/java/fr/free/nrw/commons/MediaWikiImageView.java

+4-10
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,10 @@ public void setMedia(Media media) {
5151
return;
5252
}
5353

54-
if(media.getFilename() != null) {
55-
if (thumbnailUrlCache.get(media.getFilename()) != null) {
56-
setImageUrl(thumbnailUrlCache.get(media.getFilename()));
57-
} else {
58-
setImageUrl(null);
59-
currentThumbnailTask = new ThumbnailFetchTask(media, mwApi);
60-
currentThumbnailTask.execute(media.getFilename());
61-
}
62-
} else { // local image
63-
setImageUrl(media.getLocalUri().toString());
54+
if (media.getFilename() != null && thumbnailUrlCache.get(media.getFilename()) != null) {
55+
setImageUrl(thumbnailUrlCache.get(media.getFilename()));
56+
} else {
57+
setImageUrl(null);
6458
currentThumbnailTask = new ThumbnailFetchTask(media, mwApi);
6559
currentThumbnailTask.execute(media.getFilename());
6660
}

app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java

+9
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public Contribution[] newArray(int i) {
4646
private String decimalCoords;
4747
private boolean isMultiple;
4848
private String wikiDataEntityId;
49+
private Uri contentProviderUri;
4950

5051
public Contribution(Uri contentUri, String filename, Uri localUri, String imageUrl, Date timestamp,
5152
int state, long dataLength, Date dateUploaded, long transferred,
@@ -236,4 +237,12 @@ public String getWikiDataEntityId() {
236237
public void setWikiDataEntityId(String wikiDataEntityId) {
237238
this.wikiDataEntityId = wikiDataEntityId;
238239
}
240+
241+
public void setContentProviderUri(Uri contentProviderUri) {
242+
this.contentProviderUri = contentProviderUri;
243+
}
244+
245+
public Uri getContentProviderUri() {
246+
return contentProviderUri;
247+
}
239248
}

app/src/main/java/fr/free/nrw/commons/contributions/ContributionController.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
import android.net.Uri;
88
import android.os.Bundle;
99
import android.provider.MediaStore;
10+
import android.support.annotation.Nullable;
1011
import android.support.v4.app.Fragment;
1112
import android.support.v4.app.FragmentActivity;
1213
import android.support.v4.content.FileProvider;
14+
import android.util.Log;
1315

1416
import java.io.File;
1517
import java.util.Date;
@@ -28,8 +30,8 @@
2830

2931
public class ContributionController {
3032

31-
private static final int SELECT_FROM_GALLERY = 1;
32-
private static final int SELECT_FROM_CAMERA = 2;
33+
public static final int SELECT_FROM_GALLERY = 1;
34+
public static final int SELECT_FROM_CAMERA = 2;
3335

3436
private Fragment fragment;
3537

@@ -91,16 +93,15 @@ public void startGalleryPick() {
9193
fragment.startActivityForResult(pickImageIntent, SELECT_FROM_GALLERY);
9294
}
9395

94-
public void handleImagePicked(int requestCode, Intent data, boolean isDirectUpload, String wikiDataEntityId) {
95-
Timber.d("Is direct upload %s and the Wikidata entity ID is %s", isDirectUpload, wikiDataEntityId);
96+
public void handleImagePicked(int requestCode, @Nullable Uri uri, boolean isDirectUpload, String wikiDataEntityId) {
9697
FragmentActivity activity = fragment.getActivity();
9798
Timber.d("handleImagePicked() called with onActivityResult()");
9899
Intent shareIntent = new Intent(activity, ShareActivity.class);
99100
shareIntent.setAction(ACTION_SEND);
100101
switch (requestCode) {
101102
case SELECT_FROM_GALLERY:
102103
//Handles image picked from gallery
103-
Uri imageData = data.getData();
104+
Uri imageData = uri;
104105
shareIntent.setType(activity.getContentResolver().getType(imageData));
105106
shareIntent.putExtra(EXTRA_STREAM, imageData);
106107
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_GALLERY);

app/src/main/java/fr/free/nrw/commons/contributions/ContributionsActivity.java

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import fr.free.nrw.commons.quiz.QuizChecker;
3939
import fr.free.nrw.commons.settings.Prefs;
4040
import fr.free.nrw.commons.upload.UploadService;
41+
import fr.free.nrw.commons.utils.ContributionUtils;
4142
import fr.free.nrw.commons.utils.ViewUtil;
4243
import io.reactivex.android.schedulers.AndroidSchedulers;
4344
import io.reactivex.disposables.CompositeDisposable;
@@ -199,6 +200,9 @@ public void deleteUpload(int i) {
199200
Contribution c = contributionDao.fromCursor(allContributions);
200201
if (c.getState() == STATE_FAILED) {
201202
Timber.d("Deleting failed contrib %s", c.toString());
203+
// If upload fails and then user decides to cancel upload at all, which means contribution
204+
// object will be deleted. So we have to delete temp file for that contribution.
205+
ContributionUtils.removeTemporaryFile(c.getLocalUri());
202206
contributionDao.delete(c);
203207
} else {
204208
Timber.d("Skipping deletion for non-failed contrib %s", c.toString());

app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
import android.content.Intent;
44
import android.content.SharedPreferences;
55
import android.content.pm.PackageManager;
6+
import android.net.Uri;
67
import android.os.Build;
78
import android.os.Bundle;
89
import android.support.annotation.NonNull;
910
import android.support.v4.content.ContextCompat;
1011
import android.support.v7.app.AlertDialog;
12+
import android.util.Log;
1113
import android.view.LayoutInflater;
1214
import android.view.Menu;
1315
import android.view.MenuInflater;
@@ -31,6 +33,7 @@
3133
import fr.free.nrw.commons.R;
3234
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
3335
import fr.free.nrw.commons.nearby.NearbyActivity;
36+
import fr.free.nrw.commons.utils.ContributionUtils;
3437
import timber.log.Timber;
3538

3639
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
@@ -117,7 +120,13 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
117120
if (resultCode == RESULT_OK) {
118121
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
119122
requestCode, resultCode, data);
120-
controller.handleImagePicked(requestCode, data, false, null);
123+
if (requestCode == ContributionController.SELECT_FROM_CAMERA) {
124+
// If coming from camera, pass null as uri. Because camera photos get saved to a
125+
// fixed directory
126+
controller.handleImagePicked(requestCode, null, false, null);
127+
} else {
128+
controller.handleImagePicked(requestCode, data.getData(), false, null);
129+
}
121130
} else {
122131
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
123132
requestCode, resultCode, data);

app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.content.Context;
44
import android.content.SharedPreferences;
5+
import android.net.Uri;
56
import android.os.Build;
67
import android.support.annotation.NonNull;
78
import android.support.annotation.Nullable;
@@ -51,6 +52,7 @@
5152
import fr.free.nrw.commons.category.QueryContinue;
5253
import fr.free.nrw.commons.notification.Notification;
5354
import fr.free.nrw.commons.notification.NotificationUtils;
55+
import fr.free.nrw.commons.utils.ContributionUtils;
5456
import in.yuvi.http.fluent.Http;
5557
import io.reactivex.Observable;
5658
import io.reactivex.Single;
@@ -856,25 +858,30 @@ public UploadResult uploadFile(String filename,
856858
long dataLength,
857859
String pageContents,
858860
String editSummary,
859-
final ProgressListener progressListener) throws IOException {
861+
final ProgressListener progressListener,
862+
Uri fileUri,
863+
Uri contentProviderUri) throws IOException {
864+
860865
ApiResult result = api.upload(filename, file, dataLength, pageContents, editSummary, progressListener::onProgress);
861866

862867
Log.e("WTF", "Result: " + result.toString());
863868

864869
String resultStatus = result.getString("/api/upload/@result");
870+
865871
if (!resultStatus.equals("Success")) {
866872
String errorCode = result.getString("/api/error/@code");
867873
Timber.e(errorCode);
868874
return new UploadResult(resultStatus, errorCode);
869875
} else {
876+
// If success we have to remove file from temp directory
877+
ContributionUtils.removeTemporaryFile(fileUri);
870878
Date dateUploaded = parseMWDate(result.getString("/api/upload/imageinfo/@timestamp"));
871879
String canonicalFilename = "File:" + result.getString("/api/upload/@filename").replace("_", " "); // Title vs Filename
872880
String imageUrl = result.getString("/api/upload/imageinfo/@url");
873881
return new UploadResult(resultStatus, dateUploaded, canonicalFilename, imageUrl);
874882
}
875883
}
876884

877-
878885
@Override
879886
@NonNull
880887
public Single<Integer> getUploadCount(String userName) {

app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fr.free.nrw.commons.mwapi;
22

3+
import android.net.Uri;
34
import android.support.annotation.NonNull;
45
import android.support.annotation.Nullable;
56

@@ -54,7 +55,7 @@ public interface MediaWikiApi {
5455
List<String> searchCategory(String title, int offset);
5556

5657
@NonNull
57-
UploadResult uploadFile(String filename, InputStream file, long dataLength, String pageContents, String editSummary, ProgressListener progressListener) throws IOException;
58+
UploadResult uploadFile(String filename, InputStream file, long dataLength, String pageContents, String editSummary, ProgressListener progressListener, Uri fileUri, Uri contentProviderUri) throws IOException;
5859

5960
@Nullable
6061
String edit(String editToken, String processedPageContent, String filename, String summary) throws IOException;

app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import fr.free.nrw.commons.R;
3131
import fr.free.nrw.commons.contributions.ContributionController;
3232
import fr.free.nrw.commons.location.LatLng;
33+
import fr.free.nrw.commons.utils.ContributionUtils;
3334
import fr.free.nrw.commons.utils.UriDeserializer;
3435
import timber.log.Timber;
3536

@@ -147,7 +148,13 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
147148
if (resultCode == RESULT_OK) {
148149
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
149150
requestCode, resultCode, data);
150-
controller.handleImagePicked(requestCode, data, true, directPrefs.getString(WIKIDATA_ENTITY_ID_PREF, null));
151+
if (requestCode == ContributionController.SELECT_FROM_CAMERA) {
152+
// If coming from camera, pass null as uri. Because camera photos get saved to a
153+
// fixed directory
154+
controller.handleImagePicked(requestCode, null, true, null);
155+
} else {
156+
controller.handleImagePicked(requestCode, data.getData(), true, null);
157+
}
151158
} else {
152159
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
153160
requestCode, resultCode, data);

app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import fr.free.nrw.commons.R;
5757
import fr.free.nrw.commons.Utils;
5858
import fr.free.nrw.commons.contributions.ContributionController;
59+
import fr.free.nrw.commons.utils.ContributionUtils;
5960
import fr.free.nrw.commons.utils.UriDeserializer;
6061
import fr.free.nrw.commons.utils.ViewUtil;
6162
import timber.log.Timber;
@@ -765,10 +766,17 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
765766
public void onActivityResult(int requestCode, int resultCode, Intent data) {
766767
super.onActivityResult(requestCode, resultCode, data);
767768

769+
768770
if (resultCode == RESULT_OK) {
769771
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
770772
requestCode, resultCode, data);
771-
controller.handleImagePicked(requestCode, data, true, directPrefs.getString(WIKIDATA_ENTITY_ID_PREF, null));
773+
if (requestCode == ContributionController.SELECT_FROM_CAMERA) {
774+
// If coming from camera, pass null as uri. Because camera photos get saved to a
775+
// fixed directory
776+
controller.handleImagePicked(requestCode, null, true, null);
777+
} else {
778+
controller.handleImagePicked(requestCode, data.getData(), true, null);
779+
}
772780
} else {
773781
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
774782
requestCode, resultCode, data);

app/src/main/java/fr/free/nrw/commons/upload/FileUtils.java

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import android.provider.MediaStore;
1515
import android.support.annotation.NonNull;
1616
import android.support.annotation.Nullable;
17+
import android.util.Log;
1718

1819
import java.io.BufferedReader;
1920
import java.io.File;

0 commit comments

Comments
 (0)