Fix update date template based on date source (#2483) (#2492)

* Fix update date template based on date source

* Add javadocs
This commit is contained in:
Vivek Maskara 2019-02-20 20:14:19 +05:30 committed by GitHub
parent 083a7a80f0
commit 546322ac35
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 151 additions and 19 deletions

View file

@ -27,7 +27,8 @@ dependencies {
implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.1.1'
implementation 'com.jakewharton.rxbinding2:rxbinding-design:2.1.1'
implementation 'com.facebook.fresco:fresco:1.10.0'
implementation 'com.drewnoakes:metadata-extractor:2.11.0'
// UI
implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar'
implementation 'com.github.chrisbanes:PhotoView:2.0.0'

View file

@ -3,25 +3,33 @@ package fr.free.nrw.commons.contributions;
import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.StringDef;
import java.lang.annotation.Retention;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.filepicker.UploadableFile;
import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.utils.ConfigUtils;
import fr.free.nrw.commons.utils.StringUtils;
import static java.lang.annotation.RetentionPolicy.SOURCE;
public class Contribution extends Media {
//{{According to EXIF data|2009-01-09}}
private static final String TEMPLATE_DATE_ACC_TO_EXIF = "|date={{According to EXIF data|%s}}";
//{{date|2009|1|9}} 9 January 2009
private static final String TEMPLATE_DATA_OTHER_SOURCE = "{{date|%d|%d|%d}}";
public static Creator<Contribution> CREATOR = new Creator<Contribution>() {
@Override
public Contribution createFromParcel(Parcel parcel) {
@ -57,6 +65,7 @@ public class Contribution extends Media {
private boolean isMultiple;
private String wikiDataEntityId;
private Uri contentProviderUri;
private String dateCreatedSource;
public Contribution(Uri contentUri, String filename, Uri localUri, String imageUrl, Date dateCreated,
int state, long dataLength, Date dateUploaded, long transferred,
@ -71,6 +80,7 @@ public class Contribution extends Media {
this.width = width;
this.height = height;
this.license = license;
this.dateCreatedSource = "";
}
public Contribution(Uri localUri, String imageUrl, String filename, String description, long dataLength,
@ -78,6 +88,7 @@ public class Contribution extends Media {
super(localUri, imageUrl, filename, description, dataLength, dateCreated, dateUploaded, creator);
this.decimalCoords = decimalCoords;
this.editSummary = editSummary;
this.dateCreatedSource = "";
}
public Contribution(Parcel in) {
@ -99,7 +110,13 @@ public class Contribution extends Media {
parcel.writeInt(isMultiple ? 1 : 0);
}
public String getDateCreatedSource() {
return dateCreatedSource;
}
public void setDateCreatedSource(String dateCreatedSource) {
this.dateCreatedSource = dateCreatedSource;
}
public boolean getMultiple() {
return isMultiple;
@ -143,20 +160,19 @@ public class Contribution extends Media {
public String getPageContents(Context applicationContext) {
StringBuilder buffer = new StringBuilder();
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
buffer
.append("== {{int:filedesc}} ==\n")
.append("{{Information\n")
.append("|description=").append(getDescription()).append("\n")
.append("|source=").append("{{own}}\n")
.append("|author=[[User:").append(creator).append("|").append(creator).append("]]\n");
if (dateCreated != null) {
buffer
.append("|date={{According to EXIF data|").append(isoFormat.format(dateCreated)).append("}}\n");
String templatizedCreatedDate = getTemplatizedCreatedDate();
if (!StringUtils.isNullOrWhiteSpace(templatizedCreatedDate)) {
buffer.append("|date=").append(templatizedCreatedDate);
}
buffer
.append("}}").append("\n");
buffer.append("}}").append("\n");
//Only add Location template (e.g. {{Location|37.51136|-77.602615}} ) if coords is not null
if (decimalCoords != null) {
@ -178,6 +194,28 @@ public class Contribution extends Media {
return buffer.toString();
}
/**
* Returns upload date in either TEMPLATE_DATE_ACC_TO_EXIF or TEMPLATE_DATA_OTHER_SOURCE
* @return
*/
private String getTemplatizedCreatedDate() {
if (dateCreated != null) {
if (UploadableFile.DateTimeWithSource.EXIF_SOURCE.equals(dateCreatedSource)) {
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
return String.format(Locale.ENGLISH, TEMPLATE_DATE_ACC_TO_EXIF, isoFormat.format(dateCreated)) + "\n";
} else {
Calendar calendar = Calendar.getInstance();
calendar.setTime(dateCreated);
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
return String.format(Locale.ENGLISH, TEMPLATE_DATA_OTHER_SOURCE,
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)) + "\n";
}
}
return "";
}
@Override
public void setFilename(String filename) {
this.filename = filename;

View file

@ -6,7 +6,16 @@ import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import javax.annotation.Nullable;
import fr.free.nrw.commons.upload.FileUtils;
@ -62,16 +71,32 @@ public class UploadableFile implements Parcelable {
return 0;
}
/**
* First try to get the file creation date from EXIF else fall back to CP
* @param context
* @return
*/
@Nullable
public DateTimeWithSource getFileCreatedDate(Context context) {
DateTimeWithSource dateTimeFromExif = getDateTimeFromExif();
if (dateTimeFromExif == null) {
return getFileCreatedDateFromCP(context);
} else {
return dateTimeFromExif;
}
}
/**
* Get filePath creation date from uri from all possible content providers
*
* @return
*/
public long getFileCreatedDate(Context context) {
private DateTimeWithSource getFileCreatedDateFromCP(Context context) {
try {
Cursor cursor = context.getContentResolver().query(contentUri, null, null, null, null);
if (cursor == null) {
return -1;//Could not fetch last_modified
return null;//Could not fetch last_modified
}
//Content provider contracts for opening gallery from the app and that by sharing from gallery from outside are different and we need to handle both the cases
int lastModifiedColumnIndex = cursor.getColumnIndex("last_modified");//If gallery is opened from in app
@ -80,18 +105,69 @@ public class UploadableFile implements Parcelable {
}
//If both the content providers do not give the data, lets leave it to Jesus
if (lastModifiedColumnIndex == -1) {
return -1l;
return null;
}
cursor.moveToFirst();
return cursor.getLong(lastModifiedColumnIndex);
return new DateTimeWithSource(cursor.getLong(lastModifiedColumnIndex), DateTimeWithSource.CP_SOURCE);
} catch (Exception e) {
return -1;////Could not fetch last_modified
return null;////Could not fetch last_modified
}
}
/**
* Get filePath creation date from uri from EXIF
*
* @return
*/
private DateTimeWithSource getDateTimeFromExif() {
Metadata metadata;
try {
metadata = ImageMetadataReader.readMetadata(file);
ExifSubIFDDirectory directory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
if (directory!=null && directory.containsTag(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL)) {
Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
return new DateTimeWithSource(date, DateTimeWithSource.EXIF_SOURCE);
}
} catch (ImageProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeParcelable(contentUri, 0);
parcel.writeSerializable(file);
}
/**
* This class contains the epochDate along with the source from which it was extracted
*/
public class DateTimeWithSource {
public static final String CP_SOURCE = "contentProvider";
public static final String EXIF_SOURCE = "exif";
private final long epochDate;
private final String source;
public DateTimeWithSource(long epochDate, String source) {
this.epochDate = epochDate;
this.source = source;
}
public DateTimeWithSource(Date date, String source) {
this.epochDate = date.getTime();
this.source = source;
}
public long getEpochDate() {
return epochDate;
}
public String getSource() {
return source;
}
}
}

View file

@ -43,7 +43,7 @@ public class UploadModel {
"",
GPSExtractor.DUMMY,
null,
-1L) {
-1L, "") {
};
private final BasicKvStore basicKvStore;
private final List<String> licenses;
@ -99,10 +99,16 @@ public class UploadModel {
String source,
SimilarImageInterface similarImageInterface) {
fileProcessor.initFileDetails(Objects.requireNonNull(uploadableFile.getFilePath()), context.getContentResolver());
long fileCreatedDate = uploadableFile.getFileCreatedDate(context);
UploadableFile.DateTimeWithSource dateTimeWithSource = uploadableFile.getFileCreatedDate(context);
long fileCreatedDate = -1;
String createdTimestampSource = "";
if (dateTimeWithSource != null) {
fileCreatedDate = dateTimeWithSource.getEpochDate();
createdTimestampSource = dateTimeWithSource.getSource();
}
Timber.d("File created date is %d", fileCreatedDate);
GPSExtractor gpsExtractor = fileProcessor.processFileCoordinates(similarImageInterface);
return new UploadItem(Uri.parse(uploadableFile.getFilePath()), uploadableFile.getMimeType(context), source, gpsExtractor, place, fileCreatedDate);
return new UploadItem(Uri.parse(uploadableFile.getFilePath()), uploadableFile.getMimeType(context), source, gpsExtractor, place, fileCreatedDate, createdTimestampSource);
}
void onItemsProcessed(Place place, List<UploadItem> uploadItems) {
@ -284,11 +290,13 @@ public class UploadModel {
contribution.setTag("mimeType", item.mimeType);
contribution.setSource(item.source);
contribution.setContentProviderUri(item.mediaUri);
Timber.d("Created timestamp while building contribution is %s, %s",
item.getCreatedTimestamp(),
new Date(item.getCreatedTimestamp()));
if (item.createdTimestamp != -1L) {
contribution.setDateCreated(new Date(item.getCreatedTimestamp()));
contribution.setDateCreatedSource(item.getCreatedTimestampSource());
//Set the date only if you have it, else the upload service is gonna try it the other way
}
return contribution;
@ -332,10 +340,15 @@ public class UploadModel {
private boolean visited;
private boolean error;
private long createdTimestamp;
private String createdTimestampSource;
private BehaviorSubject<Integer> imageQuality;
@SuppressLint("CheckResult")
UploadItem(Uri mediaUri, String mimeType, String source, GPSExtractor gpsCoords, @Nullable Place place, long createdTimestamp) {
UploadItem(Uri mediaUri, String mimeType, String source, GPSExtractor gpsCoords,
@Nullable Place place,
long createdTimestamp,
String createdTimestampSource) {
this.createdTimestampSource = createdTimestampSource;
title = new Title();
descriptions = new ArrayList<>();
descriptions.add(new Description());
@ -348,6 +361,10 @@ public class UploadModel {
imageQuality = BehaviorSubject.createDefault(ImageUtils.IMAGE_WAIT);
}
public String getCreatedTimestampSource() {
return createdTimestampSource;
}
public String getMimeType() {
return mimeType;
}