diff --git a/myTracks/build.gradle b/myTracks/build.gradle index 35be59409..69a5cfcd3 100644 --- a/myTracks/build.gradle +++ b/myTracks/build.gradle @@ -5,7 +5,7 @@ android { defaultConfig { applicationId "com.google.android.maps.mytracks" - minSdkVersion 24 + minSdkVersion 21 targetSdkVersion 28 testApplicationId "com.google.android.maps.mytracks.test" diff --git a/myTracks/src/main/java/com/google/android/apps/mytracks/fragments/MarkerDetailFragment.java b/myTracks/src/main/java/com/google/android/apps/mytracks/fragments/MarkerDetailFragment.java index 56137d27c..d0e28b9f6 100644 --- a/myTracks/src/main/java/com/google/android/apps/mytracks/fragments/MarkerDetailFragment.java +++ b/myTracks/src/main/java/com/google/android/apps/mytracks/fragments/MarkerDetailFragment.java @@ -21,7 +21,6 @@ import android.location.Location; import android.os.Bundle; import android.os.Handler; import android.util.Log; -import android.view.Display; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -46,7 +45,6 @@ import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint.WaypointType; import com.google.android.apps.mytracks.util.IntentUtils; import com.google.android.apps.mytracks.util.ListItemUtils; -import com.google.android.apps.mytracks.util.PhotoUtils; import com.google.android.apps.mytracks.util.StatsUtils; import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.apps.mytracks.util.TrackIconUtils; @@ -245,9 +243,7 @@ public class MarkerDetailFragment extends Fragment { if (hasPhoto) { handler.removeCallbacks(hideText); - - Display defaultDisplay = getActivity().getWindowManager().getDefaultDisplay(); - PhotoUtils.setImageView(getActivity(), photo, waypoint.getPhotoURI(), defaultDisplay.getWidth(), defaultDisplay.getHeight(), true); + photo.setImageURI(waypoint.getPhotoURI()); handler.postDelayed(hideText, HIDE_TEXT_DELAY); } diff --git a/myTracks/src/main/java/com/google/android/apps/mytracks/services/tasks/BitmapLoader.java b/myTracks/src/main/java/com/google/android/apps/mytracks/services/tasks/BitmapLoader.java deleted file mode 100644 index bda82ae62..000000000 --- a/myTracks/src/main/java/com/google/android/apps/mytracks/services/tasks/BitmapLoader.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.android.apps.mytracks.services.tasks; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Matrix; -import android.media.ExifInterface; -import android.net.Uri; -import android.os.AsyncTask; -import android.util.Log; -import android.widget.ImageView; - -import com.google.android.apps.mytracks.util.PhotoUtils; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.lang.ref.WeakReference; - -/** - * A bitmap loader. - * - * @author Jimmy Shih - */ -public class BitmapLoader extends AsyncTask { - private static final String TAG = BitmapLoader.class.getSimpleName(); - - // Use a WeakReference to ensure the ImageView can be garbage collected - private final WeakReference imageViewReference; - private final Context context; - private final Uri uri; - private final int targetWidth; - private final int targetHeight; - private final boolean fitWithin; - - public BitmapLoader(Context context, ImageView imageView, Uri uri, int targetWidth, int targetHeight, boolean fitWithin) { - imageViewReference = new WeakReference<>(imageView); - - this.context = context; - this.targetWidth = targetWidth; - this.targetHeight = targetHeight; - this.fitWithin = fitWithin; - - this.uri = uri; - } - - public Uri getUri() { - return uri; - } - - @Override - protected Bitmap doInBackground(Void... params) { - // Get the image dimensions - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - - InputStream inputStream = null; - try { - inputStream = context.getContentResolver().openInputStream(uri); - } catch (FileNotFoundException e) { - Log.e(TAG, "Could not load bitmap from uri."); - return null; - } - BitmapFactory.decodeStream(inputStream); - - // Set imageWidth and imageHeight based on image rotation - try { - inputStream = context.getContentResolver().openInputStream(uri); - } catch (FileNotFoundException e) { - return null; - } - int rotation = getRotation(inputStream); - int imageWidth; - int imageHeight; - - if (rotation == 0 || rotation == 180) { - imageWidth = options.outWidth; - imageHeight = options.outHeight; - } else { - imageWidth = options.outHeight; - imageHeight = options.outWidth; - } - - // Get a scaled down version of the image - options.inJustDecodeBounds = false; - options.inSampleSize = getInSampleSize(imageWidth, imageHeight); - - try { - inputStream = context.getContentResolver().openInputStream(uri); - } catch (FileNotFoundException e) { - return null; - } - Bitmap scaledBitmap; - scaledBitmap = BitmapFactory.decodeStream(inputStream, null, options); - if (scaledBitmap == null) { - return null; - } - - // Get the final bitmap after rotating the scaled down image - Bitmap bitmap; - if (rotation == 0 && fitWithin) { - bitmap = scaledBitmap; - } else { - Matrix matrix = new Matrix(); - matrix.postRotate(rotation); - int xOffset = 0; - int yOffset = 0; - int width = scaledBitmap.getWidth(); - int height = scaledBitmap.getHeight(); - if (rotation == 0 || rotation == 180) { - if (!fitWithin && height > targetHeight) { - xOffset = (height - targetHeight) / 2; - height = targetHeight; - } - } else { - if (!fitWithin && width > targetHeight) { - yOffset = (width - targetHeight) / 2; - width = targetHeight; - } - } - bitmap = Bitmap.createBitmap(scaledBitmap, yOffset, xOffset, width, height, matrix, true); - scaledBitmap.recycle(); - } - return bitmap; - } - - @Override - protected void onPostExecute(Bitmap bitmap) { - if (isCancelled()) { - bitmap = null; - } - // If imageView is still around, set bitmap - if (imageViewReference != null && bitmap != null) { - ImageView imageView = imageViewReference.get(); - if (imageView != null) { - BitmapLoader bitmapLoader = PhotoUtils.getBitmapLoader(imageView); - if (this == bitmapLoader) { - imageView.setImageBitmap(bitmap); - } - } - } - } - - private int getRotation(InputStream inputStream) { - try { - ExifInterface exifInterface = new ExifInterface(inputStream); - switch (exifInterface.getAttributeInt( - ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)) { - case ExifInterface.ORIENTATION_ROTATE_90: - return 90; - case ExifInterface.ORIENTATION_ROTATE_180: - return 180; - case ExifInterface.ORIENTATION_ROTATE_270: - return 270; - default: - return 0; - } - } catch (IOException e) { - Log.e(TAG, "Unable to get photo orientation", e); - return 0; - } - } - - /** - * Gets the in sample size. - * - * @param imageWidth the image width - * @param imageHeight the image height - */ - private int getInSampleSize(int imageWidth, int imageHeight) { - float widthRatio = 1; - if (imageWidth > targetWidth) { - widthRatio = (float) imageWidth / (float) targetWidth; - } - - float heightRatio = 1; - if (imageHeight > targetHeight) { - heightRatio = (float) imageHeight / (float) targetHeight; - } - - double size; - if (fitWithin) { - /* - * To fit within the target area, return the larger sample ratio so the - * image will not be larger than the target dimensions. - */ - size = Math.max(widthRatio, heightRatio); - } else { - /* - * To fill the target area, return the smaller ratio so the image will - * cover both dimensions. - */ - size = Math.min(widthRatio, heightRatio); - } - // Use Math.floor to not under-sample. - return (int) Math.floor(size); - } -} diff --git a/myTracks/src/main/java/com/google/android/apps/mytracks/util/ListItemUtils.java b/myTracks/src/main/java/com/google/android/apps/mytracks/util/ListItemUtils.java index ff35abce4..af7bc0731 100644 --- a/myTracks/src/main/java/com/google/android/apps/mytracks/util/ListItemUtils.java +++ b/myTracks/src/main/java/com/google/android/apps/mytracks/util/ListItemUtils.java @@ -78,8 +78,7 @@ public class ListItemUtils { int photoHeight = getPhotoHeight(activity); photo.getLayoutParams().height = photoHeight; photo.setImageResource(android.R.color.transparent); - Display defaultDisplay = activity.getWindowManager().getDefaultDisplay(); - PhotoUtils.setImageView(activity, photo, Uri.parse(photoUrl), defaultDisplay.getWidth(), photoHeight, false); + photo.setImageURI(Uri.parse(photoUrl)); } // Set icon diff --git a/myTracks/src/main/java/com/google/android/apps/mytracks/util/PhotoUtils.java b/myTracks/src/main/java/com/google/android/apps/mytracks/util/PhotoUtils.java deleted file mode 100644 index 06cd6953f..000000000 --- a/myTracks/src/main/java/com/google/android/apps/mytracks/util/PhotoUtils.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.android.apps.mytracks.util; - -import android.content.Context; -import android.net.Uri; -import android.widget.ImageView; - -import com.google.android.apps.mytracks.services.tasks.BitmapLoader; - -import java.lang.ref.WeakReference; - -/** - * Utilities for photos. - * - * @author Jimmy Shih - */ -public class PhotoUtils { - - private PhotoUtils() {} - - /** - * Sets an image view. - * - * @param imageView the image view - * @param uri the image uri - * @param targetWidth the target width - * @param targetHeight the target height - * @param fitWithin true to fit within the target area in order to display the - * entire image (no cropping). False to fill the entire target area. - * (allow cropping). - */ - public static void setImageView(Context context, ImageView imageView, Uri uri, int targetWidth, int targetHeight, boolean fitWithin) { - if (cancelBitmapLoader(imageView, uri)) { - BitmapLoader bitmapLoader = new BitmapLoader(context, imageView, uri, targetWidth, targetHeight, fitWithin); - WeakReference bitmapLoaderReference = new WeakReference<>(bitmapLoader); - imageView.setTag(bitmapLoaderReference); - bitmapLoader.execute(); - } - } - - /** - * Gets the image view bitmap loader. - * - * @param imageView the image view - */ - public static BitmapLoader getBitmapLoader(ImageView imageView) { - if (imageView != null) { - Object object = imageView.getTag(); - if (object instanceof WeakReference) { - WeakReference bitmapLoaderReference = (WeakReference) object; - return bitmapLoaderReference.get(); - } - } - return null; - } - - /** - * Cancels the image view bitmap loader. - * - * @param imageView the image view - * @param uri the uri - * @return false if the bitmap loader shouldn't be canceled. True if there is - * no bitmap loader or the bitmap loader is cancelled. - */ - private static boolean cancelBitmapLoader(ImageView imageView, Uri uri) { - BitmapLoader bitmapLoaderAsyncTask = getBitmapLoader(imageView); - - if (bitmapLoaderAsyncTask != null) { - if (bitmapLoaderAsyncTask.getUri().equals(uri)) { - // same bitmap loader is already in progress, don't cancel - return false; - } else { - // cancel previous bitmap loader - bitmapLoaderAsyncTask.cancel(true); - } - } - // imageview has no bitmap loader, or an existing bitmap loader is cancelled - return true; - } -}