mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-10-30 22:34:02 +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) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Ritika Pahwa
						Ritika Pahwa