mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
5196: Fix location stripped from EXIF metadata (#5227)
* MainActivity: add ACCESS_MEDIA_LOCATION permission check to retain location info in EXIF metadata * remove redundant permission check and optimise imports * FilePicker: switch to ACTION_OPEN_DOCUMENT intent for opening image files * add a comment explaining the change * implement GET_CONTENT photo picker toggle switch * add location loss warning pop up * SettingsFragment: modify the comment about GET_CONTENT takeover for more clarity
This commit is contained in:
parent
4d71c305f2
commit
9a0f35c681
6 changed files with 97 additions and 20 deletions
|
|
@ -3,12 +3,9 @@ package fr.free.nrw.commons.contributions;
|
|||
import static fr.free.nrw.commons.wikidata.WikidataConstants.PLACE_OBJECT;
|
||||
|
||||
import android.Manifest;
|
||||
import android.Manifest.permission;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import androidx.annotation.NonNull;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.filepicker.DefaultCallback;
|
||||
|
|
@ -70,15 +67,6 @@ public class ContributionController {
|
|||
PermissionUtils.checkPermissionsAndPerformAction(activity,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
() -> {
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.Q) {
|
||||
PermissionUtils.checkPermissionsAndPerformAction(
|
||||
activity,
|
||||
permission.ACCESS_MEDIA_LOCATION,
|
||||
() -> {},
|
||||
R.string.media_location_permission_denied,
|
||||
R.string.add_location_manually
|
||||
);
|
||||
}
|
||||
FilePicker.openCustomSelector(activity, 0);
|
||||
},
|
||||
R.string.storage_permission_title,
|
||||
|
|
@ -91,7 +79,8 @@ public class ContributionController {
|
|||
*/
|
||||
private void initiateGalleryUpload(final Activity activity, final boolean allowMultipleUploads) {
|
||||
setPickerConfiguration(activity, allowMultipleUploads);
|
||||
FilePicker.openGallery(activity, 0);
|
||||
boolean isGetContentPickerPreferred = defaultKvStore.getBoolean("getContentPhotoPickerPref");
|
||||
FilePicker.openGallery(activity, 0, isGetContentPickerPreferred);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import android.app.Activity;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.Bundle;
|
||||
|
|
@ -152,6 +151,20 @@ public class MainActivity extends BaseActivity
|
|||
}
|
||||
}
|
||||
setUpPager();
|
||||
/**
|
||||
* Ask the user for media location access just after login
|
||||
* so that location in the EXIF metadata of the images shared by the user
|
||||
* is retained on devices running Android 10 or above
|
||||
*/
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.Q) {
|
||||
PermissionUtils.checkPermissionsAndPerformAction(
|
||||
this,
|
||||
permission.ACCESS_MEDIA_LOCATION,
|
||||
() -> {},
|
||||
R.string.media_location_permission_denied,
|
||||
R.string.add_location_manually
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,10 +46,11 @@ public class FilePicker implements Constants {
|
|||
return uri;
|
||||
}
|
||||
|
||||
private static Intent createGalleryIntent(@NonNull Context context, int type) {
|
||||
private static Intent createGalleryIntent(@NonNull Context context, int type,
|
||||
boolean isGetContentPickerPreferred) {
|
||||
// storing picked image type to shared preferences
|
||||
storeType(context, type);
|
||||
return plainGalleryPickerIntent()
|
||||
return plainGalleryPickerIntent(isGetContentPickerPreferred)
|
||||
.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, configuration(context).allowsMultiplePickingInGallery());
|
||||
}
|
||||
|
||||
|
|
@ -105,8 +106,8 @@ public class FilePicker implements Constants {
|
|||
*
|
||||
* @param type Custom type of your choice, which will be returned with the images
|
||||
*/
|
||||
public static void openGallery(Activity activity, int type) {
|
||||
Intent intent = createGalleryIntent(activity, type);
|
||||
public static void openGallery(Activity activity, int type, boolean isGetContentPickerPreferred) {
|
||||
Intent intent = createGalleryIntent(activity, type, isGetContentPickerPreferred);
|
||||
activity.startActivityForResult(intent, RequestCodes.PICK_PICTURE_FROM_GALLERY);
|
||||
}
|
||||
|
||||
|
|
@ -200,8 +201,40 @@ public class FilePicker implements Constants {
|
|||
return data == null || (data.getData() == null && data.getClipData() == null);
|
||||
}
|
||||
|
||||
private static Intent plainGalleryPickerIntent() {
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
private static Intent plainGalleryPickerIntent(boolean isGetContentPickerPreferred) {
|
||||
/**
|
||||
* Asking for ACCESS_MEDIA_LOCATION at runtime solved the location-loss issue
|
||||
* in the custom selector in Contributions fragment.
|
||||
* Detailed discussion: https://github.com/commons-app/apps-android-commons/issues/5015
|
||||
*
|
||||
* This permission check, however, was insufficient to fix location-loss in
|
||||
* the regular selector in Contributions fragment and Nearby fragment,
|
||||
* especially on some devices running Android 13 that use the new Photo Picker by default.
|
||||
*
|
||||
* New Photo Picker: https://developer.android.com/training/data-storage/shared/photopicker
|
||||
*
|
||||
* The new Photo Picker introduced by Android redacts location tags from EXIF metadata.
|
||||
* Reported on the Google Issue Tracker: https://issuetracker.google.com/issues/243294058
|
||||
* Status: Won't fix (Intended behaviour)
|
||||
*
|
||||
* Switched intent from ACTION_GET_CONTENT to ACTION_OPEN_DOCUMENT
|
||||
* (based on user's preference) as:
|
||||
*
|
||||
* ACTION_GET_CONTENT opens the 'best application' for choosing that kind of data
|
||||
* The best application is the new Photo Picker that redacts the location tags
|
||||
*
|
||||
* ACTION_OPEN_DOCUMENT, however, displays the various DocumentsProvider instances
|
||||
* installed on the device, letting the user interactively navigate through them.
|
||||
*
|
||||
* So, this allows us to use the traditional file picker that does not redact location tags from EXIF.
|
||||
*
|
||||
*/
|
||||
Intent intent;
|
||||
if (isGetContentPickerPreferred) {
|
||||
intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
} else {
|
||||
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
}
|
||||
intent.setType("image/*");
|
||||
return intent;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import fr.free.nrw.commons.recentlanguages.Language;
|
|||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter;
|
||||
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
|
||||
import fr.free.nrw.commons.upload.LanguagesAdapter;
|
||||
import fr.free.nrw.commons.utils.DialogUtil;
|
||||
import fr.free.nrw.commons.utils.PermissionUtils;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -71,6 +72,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
private TextView recentLanguagesTextView;
|
||||
private View separator;
|
||||
private ListView languageHistoryListView;
|
||||
private static final String GET_CONTENT_PICKER_HELP_URL = "https://commons-app.github.io/docs.html#get-content";
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
|
|
@ -150,6 +152,17 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
checkPermissionsAndSendLogs();
|
||||
return true;
|
||||
});
|
||||
|
||||
Preference getContentPickerPreference = findPreference("getContentPhotoPickerPref");
|
||||
getContentPickerPreference.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
boolean isGetContentPickerTurnedOn = (boolean) newValue;
|
||||
if (isGetContentPickerTurnedOn) {
|
||||
showLocationLossWarning();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
// Disable some settings when not logged in.
|
||||
if (defaultKvStore.getBoolean("login_skipped", false)) {
|
||||
findPreference("useExternalStorage").setEnabled(false);
|
||||
|
|
@ -162,6 +175,26 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On some devices, the new Photo Picker with GET_CONTENT takeover
|
||||
* redacts location tags from EXIF metadata
|
||||
*
|
||||
* Show warning to the user when ACTION_GET_CONTENT intent is enabled
|
||||
*/
|
||||
private void showLocationLossWarning() {
|
||||
DialogUtil.showAlertDialog(
|
||||
getActivity(),
|
||||
null,
|
||||
getString(R.string.location_loss_warning),
|
||||
getString(R.string.ok),
|
||||
getString(R.string.read_help_link),
|
||||
() -> {},
|
||||
() -> Utils.handleWebUrl(requireContext(), Uri.parse(GET_CONTENT_PICKER_HELP_URL)),
|
||||
null,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Adapter onCreateAdapter(final PreferenceScreen preferenceScreen) {
|
||||
return new PreferenceGroupAdapter(preferenceScreen) {
|
||||
|
|
|
|||
|
|
@ -440,6 +440,9 @@ Upload your first media by tapping on the add button.</string>
|
|||
<string name="ends_on">Ends on:</string>
|
||||
<string name="display_campaigns">Display campaigns</string>
|
||||
<string name="display_campaigns_explanation">See the ongoing campaigns</string>
|
||||
<string name="get_content_photo_picker_title">Use GET_CONTENT photo picker</string>
|
||||
<string name="get_content_photo_picker_explanation">Disable if your pictures get uploaded without location</string>
|
||||
<string name="location_loss_warning">Please make sure that this new Android picker does not strip location from your pictures.</string>
|
||||
|
||||
<string name="nearby_campaign_dismiss_message">You won\'t see the campaigns anymore. However, you can re-enable this notification in Settings if you wish.</string>
|
||||
<string name="this_function_needs_network_connection">This function requires network connection, please check your connection settings.</string>
|
||||
|
|
|
|||
|
|
@ -70,6 +70,12 @@
|
|||
app:singleLineTitle="false"
|
||||
android:summary="@string/display_campaigns_explanation"
|
||||
android:title="@string/display_campaigns" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="getContentPhotoPickerPref"
|
||||
android:summary="@string/get_content_photo_picker_explanation"
|
||||
android:title="@string/get_content_photo_picker_title"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue