diff --git a/build.gradle b/build.gradle index 2f11efd3..cd034d86 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.7.10' + ext.kotlin_version = '1.8.0' repositories { google() diff --git a/mapcache/build.gradle b/mapcache/build.gradle index 0323344c..12d8a8f3 100644 --- a/mapcache/build.gradle +++ b/mapcache/build.gradle @@ -4,7 +4,7 @@ def googleMapsApiReleaseKey = hasProperty('RELEASE_MAPS_MAPCACHE_API_KEY') ? REL def googleMapsApiKeyDebug = hasProperty('DEBUG_MAPS_API_KEY') ? DEBUG_MAPS_API_KEY : '' android { - compileSdkVersion 33 + compileSdkVersion 34 compileOptions { sourceCompatibility JavaVersion.VERSION_11 @@ -22,7 +22,7 @@ android { resValue "string", "applicationId", applicationId testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" minSdkVersion 28 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 60 versionName '2.1.11' multiDexEnabled true @@ -83,7 +83,8 @@ task androidAppVersion { dependencies { api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - api 'androidx.appcompat:appcompat:1.3.0' + api 'androidx.appcompat:appcompat:1.6.1' + api 'androidx.activity:activity:1.8.0' api 'com.google.android.material:material:1.6.0' api 'androidx.preference:preference:1.2.1' api 'androidx.lifecycle:lifecycle-extensions:2.2.0' diff --git a/mapcache/src/main/java/mil/nga/mapcache/preferences/PreferencesActivity.java b/mapcache/src/main/java/mil/nga/mapcache/preferences/PreferencesActivity.java index 1111ad62..640db183 100644 --- a/mapcache/src/main/java/mil/nga/mapcache/preferences/PreferencesActivity.java +++ b/mapcache/src/main/java/mil/nga/mapcache/preferences/PreferencesActivity.java @@ -45,8 +45,7 @@ protected void onCreate(Bundle savedInstanceState) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: -// NavUtils.navigateUpFromSameTask(this); - onBackPressed(); + super.getOnBackPressedDispatcher().onBackPressed(); return true; default: return super.onOptionsItemSelected(item); diff --git a/mapcache/src/main/java/mil/nga/mapcache/view/map/feature/FeatureViewActivity.java b/mapcache/src/main/java/mil/nga/mapcache/view/map/feature/FeatureViewActivity.java index bd22573d..4586e433 100644 --- a/mapcache/src/main/java/mil/nga/mapcache/view/map/feature/FeatureViewActivity.java +++ b/mapcache/src/main/java/mil/nga/mapcache/view/map/feature/FeatureViewActivity.java @@ -24,6 +24,7 @@ import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.PickVisualMediaRequest; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; @@ -71,10 +72,15 @@ public class FeatureViewActivity extends AppCompatActivity { /** - * Permission check + * Permission check for multiple */ public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 204; + /** + * Permission check for gallery usage + */ + public static final int REQUEST_ID_GALLERY_PERMISSIONS = 205; + /** * We'll generate a list of FCObjects to hold our data for the recycler */ @@ -156,16 +162,19 @@ public class FeatureViewActivity extends AppCompatActivity { private DeleteImageListener deleteImageListener; /** - * result listener for selecting images from the gallery + * Result listener for selecting images from the gallery. + * Registers a photo picker activity launcher in single-select mode. */ - private ActivityResultLauncher getImageFromGallery = registerForActivityResult(new ActivityResultContracts.GetContent(), - new ActivityResultCallback() { - @Override - public void onActivityResult(Uri uri) { + ActivityResultLauncher getImageFromGallery = + registerForActivityResult(new ActivityResultContracts.PickVisualMedia(), uri -> { + // Callback is invoked after the user selects a media item or closes the + // photo picker. + if (uri != null) { + Log.d("PhotoPicker", "Selected URI: " + uri); Bitmap image = getImageResult(uri); - if(image != null) { - addImageToGallery(image); - } + addImageToGallery(image); + } else { + Log.d("PhotoPicker", "No media selected"); } }); @@ -252,8 +261,8 @@ protected void onCreate(Bundle savedInstanceState) { */ private void createImageGallery(){ if(imageGalleryPager != null && featureViewObjects != null){ - for(Map.Entry map : featureViewObjects.getBitmaps().entrySet() ){ - sliderItems.add(new SliderItem((long)map.getKey(),(Bitmap)map.getValue())); + for(Map.Entry map : featureViewObjects.getBitmaps().entrySet() ){ + sliderItems.add(new SliderItem(map.getKey(),map.getValue())); } imageGalleryPager.setAdapter(sliderAdapter); imageGalleryPager.setClipToPadding(false); @@ -313,7 +322,7 @@ private void createButtonListeners(){ } if(galleryButton != null) { galleryButton.setOnClickListener(v -> { - if (checkAndRequestPermissions(FeatureViewActivity.this)) { + if (checkAndRequestGalleryPermissions(FeatureViewActivity.this)) { addFromGallery(); } }); @@ -419,8 +428,8 @@ private void updateImages(){ if(featureViewObjects != null){ sliderItems.clear(); featureViewObjects.getAddedBitmaps().clear(); - for(Map.Entry map : featureViewObjects.getBitmaps().entrySet() ){ - sliderItems.add(new SliderItem((long)map.getKey(),(Bitmap)map.getValue())); + for(Map.Entry map : featureViewObjects.getBitmaps().entrySet() ){ + sliderItems.add(new SliderItem(map.getKey(),map.getValue())); } } sliderAdapter.setData(sliderItems); @@ -455,7 +464,10 @@ private void takePicture(){ * Open the phone's image gallery to add an image */ private void addFromGallery(){ - getImageFromGallery.launch("image/*"); + ActivityResultContracts.PickVisualMedia.VisualMediaType mediaType = (ActivityResultContracts.PickVisualMedia.VisualMediaType) ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE; + getImageFromGallery.launch(new PickVisualMediaRequest.Builder() + .setMediaType(mediaType) + .build()); } @@ -550,6 +562,25 @@ public static boolean checkAndRequestPermissions(final Activity context) { return true; } + public static boolean checkAndRequestGalleryPermissions(final Activity context) { + int writeExternalPermission = ContextCompat.checkSelfPermission(context, + Manifest.permission.WRITE_EXTERNAL_STORAGE); + List listPermissionsNeeded = new ArrayList<>(); + if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q){ + if (writeExternalPermission != PackageManager.PERMISSION_GRANTED) { + listPermissionsNeeded + .add(Manifest.permission.WRITE_EXTERNAL_STORAGE); + } + } + if (!listPermissionsNeeded.isEmpty()) { + ActivityCompat.requestPermissions(context, listPermissionsNeeded + .toArray(new String[0]), + REQUEST_ID_GALLERY_PERMISSIONS); + return false; + } + return true; + } + /** @@ -566,19 +597,22 @@ public void onRequestPermissionsResult(int requestCode, @NotNull String[] permis "Camera permissions required", Toast.LENGTH_SHORT) .show(); flagged = true; + } else { + takePicture(); } + } + if (requestCode == REQUEST_ID_GALLERY_PERMISSIONS) { if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) { - if (ContextCompat.checkSelfPermission(FeatureViewActivity.this, + if (ContextCompat.checkSelfPermission(FeatureViewActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(getApplicationContext(), "Storage permissions required", Toast.LENGTH_SHORT).show(); - flagged = true; - - } + flagged = true; + } } - if(!flagged) { - takePicture(); + if(!flagged){ + addFromGallery(); } } }