Loading app/src/main/java/net/fabiszewski/ulogger/ImageHelper.java +3 −3 Original line number Diff line number Diff line Loading @@ -171,7 +171,7 @@ class ImageHelper { int sizePx = getThumbnailSize(context); Bitmap bitmap; ContentResolver cr = context.getContentResolver(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (uri.getScheme().equals("content") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { bitmap = cr.loadThumbnail(uri, new Size(sizePx, sizePx), null); } else { try (InputStream is = cr.openInputStream(uri)) { Loading @@ -185,9 +185,9 @@ class ImageHelper { } /** * Extract thumbnail from URI * Extract thumbnail from bitmap * @param context Context * @param uri URI * @param bitmap Bitmap * @return Thumbnail */ static Bitmap getThumbnail(@NonNull Context context, @NonNull Bitmap bitmap) { Loading app/src/main/java/net/fabiszewski/ulogger/ImageTask.java +20 −8 Original line number Diff line number Diff line Loading @@ -47,12 +47,18 @@ class ImageTask implements Runnable { private boolean isRunning = false; private boolean isCancelled = false; private final boolean onlyThumbnail; private final Handler uiHandler = new Handler(Looper.getMainLooper()); ImageTask(Uri uri, ImageTaskCallback callback) { this(uri, callback, false); } ImageTask(Uri uri, ImageTaskCallback callback, boolean onlyThumbnail) { this.uri = uri; weakCallback = new WeakReference<>(callback); this.onlyThumbnail = onlyThumbnail; } @Override Loading Loading @@ -83,11 +89,16 @@ class ImageTask implements Runnable { if (activity == null) { return null; } ImageTaskResult result = null; try { Uri savedUri; Bitmap thumbnail; if (onlyThumbnail) { savedUri = uri; thumbnail = getThumbnail(activity, uri); } else { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); int dstWidth = Integer.parseInt(prefs.getString(SettingsActivity.KEY_IMAGE_SIZE, activity.getString(R.string.pref_imagesize_default))); if (dstWidth == 0) { Loading @@ -100,6 +111,7 @@ class ImageTask implements Runnable { thumbnail = getThumbnail(activity, bitmap); bitmap.recycle(); } } if (savedUri != null && thumbnail != null) { result = new ImageTaskResult(savedUri, thumbnail); } Loading app/src/main/java/net/fabiszewski/ulogger/WaypointFragment.java +98 −68 Original line number Diff line number Diff line Loading @@ -53,8 +53,8 @@ import java.util.concurrent.ExecutorService; public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskCallback, ImageTask.ImageTaskCallback { private static final String KEY_URI = "keyPhotoUri"; private static final String KEY_THUMB = "keyPhotoThumb"; private static final String KEY_LOCATION = "keyLocation"; private static final String KEY_WAITING = "keyWaiting"; private static final String TAG = WaypointFragment.class.getSimpleName(); Loading @@ -72,9 +72,74 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC private Location location = null; private Uri photoUri = null; private Bitmap photoThumb = null; private boolean isWaitingForCamera = false; private final ExecutorService executor = newCachedThreadPool(); /** * Request location permission(s), on granted run logger task */ final ActivityResultLauncher<String[]> requestLocationPermission = registerForActivityResult(new RequestMultiplePermissions(), results -> { if (Logger.DEBUG) { Log.d(TAG, "[requestLocationPermission: " + results.entrySet() + "]"); } boolean isGranted = false; for (Map.Entry<String, Boolean> result : results.entrySet()) { if (result.getValue()) { isGranted = true; } } if (isGranted) { if (Logger.DEBUG) { Log.d(TAG, "[LocationPermission: granted]"); } runLoggerTask(); } else { if (Logger.DEBUG) { Log.d(TAG, "[LocationPermission: refused]"); } finish(); } }); /** * Request write permission, on granted take picture */ final ActivityResultLauncher<String> requestWritePermission = registerForActivityResult(new RequestPermission(), isGranted -> { if (Logger.DEBUG) { Log.d(TAG, "[requestWritePermission: " + isGranted + "]"); } if (isGranted) { requestImageCapture(); } }); /** * Take picture, then run image task */ final ActivityResultLauncher<Uri> takePicture = registerForActivityResult(new TakePicture() { @NonNull @Override public Intent createIntent(@NonNull Context context, @NonNull Uri input) { isWaitingForCamera = true; int flags = FLAG_GRANT_WRITE_URI_PERMISSION|FLAG_GRANT_READ_URI_PERMISSION|FLAG_GRANT_PERSISTABLE_URI_PERMISSION; return super.createIntent(context, input).addFlags(flags); } }, isSaved -> { if (Logger.DEBUG) { Log.d(TAG, "[TakePicture result]"); } if (isSaved) { if (photoUri != null) { ImageHelper.galleryAdd(requireContext(), photoUri); runImageTask(photoUri); } } else { clearImage(); } isWaitingForCamera = false; }); /** * Open image file, then run image task */ final ActivityResultLauncher<String[]> openPicture = registerForActivityResult(new OpenLocalDocument(), uri -> { if (uri != null) { photoUri = uri; runImageTask(photoUri); } }); public WaypointFragment() { } static WaypointFragment newInstance() { Loading @@ -84,13 +149,13 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); //noinspection deprecation setRetainInstance(true); if (Logger.DEBUG) { Log.d(TAG, "[onCreate]"); } } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { if (Logger.DEBUG) { Log.d(TAG, "[onCreateView]"); } View layout = inflater.inflate(R.layout.fragment_waypoint, container, false); locationNotFoundTextView = layout.findViewById(R.id.waypointLocationNotFound); Loading @@ -111,13 +176,12 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC } private void restoreState(Bundle savedInstanceState) { if (Logger.DEBUG) { Log.d(TAG, "[restoreState]"); } if (savedInstanceState.containsKey(KEY_WAITING)) { isWaitingForCamera = true; } if (savedInstanceState.containsKey(KEY_URI)) { photoUri = savedInstanceState.getParcelable(KEY_URI); setThumbnail(photoThumb); } if (savedInstanceState.containsKey(KEY_THUMB)) { photoThumb = savedInstanceState.getParcelable(KEY_THUMB); setThumbnail(photoThumb); } if (savedInstanceState.containsKey(KEY_LOCATION)) { location = savedInstanceState.getParcelable(KEY_LOCATION); Loading @@ -134,23 +198,28 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); if (Logger.DEBUG) { Log.d(TAG, "[onSaveInstanceState]"); } if (photoUri != null) { outState.putParcelable(KEY_URI, photoUri); } if (photoThumb != null) { outState.putParcelable(KEY_THUMB, photoThumb); } if (location != null) { outState.putParcelable(KEY_LOCATION, location); } if (isWaitingForCamera) { outState.putBoolean(KEY_WAITING, true); } } @Override public void onResume() { super.onResume(); if (Logger.DEBUG) { Log.d(TAG, "[onResume]"); } if (!hasLocation()) { runLoggerTask(); } if (photoUri != null && photoThumb == null && !isWaitingForCamera) { runThumbnailTask(photoUri); } } /** Loading Loading @@ -196,9 +265,12 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC /** * Start image task * Transforms image if needed and generates thumbnail for URI * @param uri URI */ private void runImageTask(@NonNull Uri uri) { if (imageTask == null || !imageTask.isRunning()) { if (Logger.DEBUG) { Log.d(TAG, "[runImageTask]"); } clearImage(); saveButton.setEnabled(false); imageTask = new ImageTask(uri, this); Loading @@ -207,6 +279,20 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC } } /** * Start thumbnail task * Generates thumbnail for URI * @param uri URI */ private void runThumbnailTask(@NonNull Uri uri) { if (imageTask == null || !imageTask.isRunning()) { if (Logger.DEBUG) { Log.d(TAG, "[runThumbnailTask]"); } imageTask = new ImageTask(uri, this, true); executor.execute(imageTask); setRefreshing(true); } } private void setRefreshing(boolean refreshing) { swipe.setRefreshing(refreshing); } Loading @@ -214,6 +300,7 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC @Override public void onDetach() { super.onDetach(); if (Logger.DEBUG) { Log.d(TAG, "[onDetach]"); } cancelLoggerTask(); cancelImageTask(); } Loading Loading @@ -362,63 +449,6 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC } } /** * Request location permission(s), on granted run logger task */ final ActivityResultLauncher<String[]> requestLocationPermission = registerForActivityResult(new RequestMultiplePermissions(), results -> { if (Logger.DEBUG) { Log.d(TAG, "[requestLocationPermission: " + results.entrySet() + "]"); } boolean isGranted = false; for (Map.Entry<String, Boolean> result : results.entrySet()) { if (result.getValue()) { isGranted = true; } } if (isGranted) { if (Logger.DEBUG) { Log.d(TAG, "[LocationPermission: granted]"); } runLoggerTask(); } else { if (Logger.DEBUG) { Log.d(TAG, "[LocationPermission: refused]"); } finish(); } }); /** * Request write permission, on granted take picture */ final ActivityResultLauncher<String> requestWritePermission = registerForActivityResult(new RequestPermission(), isGranted -> { if (Logger.DEBUG) { Log.d(TAG, "[requestWritePermission: " + isGranted + "]"); } if (isGranted) { requestImageCapture(); } }); /** * Take picture, then run image task */ final ActivityResultLauncher<Uri> takePicture = registerForActivityResult(new TakePicture() { @NonNull @Override public Intent createIntent(@NonNull Context context, @NonNull Uri input) { int flags = FLAG_GRANT_WRITE_URI_PERMISSION|FLAG_GRANT_READ_URI_PERMISSION|FLAG_GRANT_PERSISTABLE_URI_PERMISSION; return super.createIntent(context, input).addFlags(flags); } }, isSaved -> { if (isSaved && photoUri != null) { ImageHelper.galleryAdd(requireContext(), photoUri); runImageTask(photoUri); } }); /** * Open image file, then run image task */ final ActivityResultLauncher<String[]> openPicture = registerForActivityResult(new OpenLocalDocument(), uri -> { if (uri != null) { photoUri = uri; runImageTask(photoUri); } }); /** * Update state on location received * @param location Current location Loading Loading
app/src/main/java/net/fabiszewski/ulogger/ImageHelper.java +3 −3 Original line number Diff line number Diff line Loading @@ -171,7 +171,7 @@ class ImageHelper { int sizePx = getThumbnailSize(context); Bitmap bitmap; ContentResolver cr = context.getContentResolver(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (uri.getScheme().equals("content") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { bitmap = cr.loadThumbnail(uri, new Size(sizePx, sizePx), null); } else { try (InputStream is = cr.openInputStream(uri)) { Loading @@ -185,9 +185,9 @@ class ImageHelper { } /** * Extract thumbnail from URI * Extract thumbnail from bitmap * @param context Context * @param uri URI * @param bitmap Bitmap * @return Thumbnail */ static Bitmap getThumbnail(@NonNull Context context, @NonNull Bitmap bitmap) { Loading
app/src/main/java/net/fabiszewski/ulogger/ImageTask.java +20 −8 Original line number Diff line number Diff line Loading @@ -47,12 +47,18 @@ class ImageTask implements Runnable { private boolean isRunning = false; private boolean isCancelled = false; private final boolean onlyThumbnail; private final Handler uiHandler = new Handler(Looper.getMainLooper()); ImageTask(Uri uri, ImageTaskCallback callback) { this(uri, callback, false); } ImageTask(Uri uri, ImageTaskCallback callback, boolean onlyThumbnail) { this.uri = uri; weakCallback = new WeakReference<>(callback); this.onlyThumbnail = onlyThumbnail; } @Override Loading Loading @@ -83,11 +89,16 @@ class ImageTask implements Runnable { if (activity == null) { return null; } ImageTaskResult result = null; try { Uri savedUri; Bitmap thumbnail; if (onlyThumbnail) { savedUri = uri; thumbnail = getThumbnail(activity, uri); } else { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); int dstWidth = Integer.parseInt(prefs.getString(SettingsActivity.KEY_IMAGE_SIZE, activity.getString(R.string.pref_imagesize_default))); if (dstWidth == 0) { Loading @@ -100,6 +111,7 @@ class ImageTask implements Runnable { thumbnail = getThumbnail(activity, bitmap); bitmap.recycle(); } } if (savedUri != null && thumbnail != null) { result = new ImageTaskResult(savedUri, thumbnail); } Loading
app/src/main/java/net/fabiszewski/ulogger/WaypointFragment.java +98 −68 Original line number Diff line number Diff line Loading @@ -53,8 +53,8 @@ import java.util.concurrent.ExecutorService; public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskCallback, ImageTask.ImageTaskCallback { private static final String KEY_URI = "keyPhotoUri"; private static final String KEY_THUMB = "keyPhotoThumb"; private static final String KEY_LOCATION = "keyLocation"; private static final String KEY_WAITING = "keyWaiting"; private static final String TAG = WaypointFragment.class.getSimpleName(); Loading @@ -72,9 +72,74 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC private Location location = null; private Uri photoUri = null; private Bitmap photoThumb = null; private boolean isWaitingForCamera = false; private final ExecutorService executor = newCachedThreadPool(); /** * Request location permission(s), on granted run logger task */ final ActivityResultLauncher<String[]> requestLocationPermission = registerForActivityResult(new RequestMultiplePermissions(), results -> { if (Logger.DEBUG) { Log.d(TAG, "[requestLocationPermission: " + results.entrySet() + "]"); } boolean isGranted = false; for (Map.Entry<String, Boolean> result : results.entrySet()) { if (result.getValue()) { isGranted = true; } } if (isGranted) { if (Logger.DEBUG) { Log.d(TAG, "[LocationPermission: granted]"); } runLoggerTask(); } else { if (Logger.DEBUG) { Log.d(TAG, "[LocationPermission: refused]"); } finish(); } }); /** * Request write permission, on granted take picture */ final ActivityResultLauncher<String> requestWritePermission = registerForActivityResult(new RequestPermission(), isGranted -> { if (Logger.DEBUG) { Log.d(TAG, "[requestWritePermission: " + isGranted + "]"); } if (isGranted) { requestImageCapture(); } }); /** * Take picture, then run image task */ final ActivityResultLauncher<Uri> takePicture = registerForActivityResult(new TakePicture() { @NonNull @Override public Intent createIntent(@NonNull Context context, @NonNull Uri input) { isWaitingForCamera = true; int flags = FLAG_GRANT_WRITE_URI_PERMISSION|FLAG_GRANT_READ_URI_PERMISSION|FLAG_GRANT_PERSISTABLE_URI_PERMISSION; return super.createIntent(context, input).addFlags(flags); } }, isSaved -> { if (Logger.DEBUG) { Log.d(TAG, "[TakePicture result]"); } if (isSaved) { if (photoUri != null) { ImageHelper.galleryAdd(requireContext(), photoUri); runImageTask(photoUri); } } else { clearImage(); } isWaitingForCamera = false; }); /** * Open image file, then run image task */ final ActivityResultLauncher<String[]> openPicture = registerForActivityResult(new OpenLocalDocument(), uri -> { if (uri != null) { photoUri = uri; runImageTask(photoUri); } }); public WaypointFragment() { } static WaypointFragment newInstance() { Loading @@ -84,13 +149,13 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); //noinspection deprecation setRetainInstance(true); if (Logger.DEBUG) { Log.d(TAG, "[onCreate]"); } } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { if (Logger.DEBUG) { Log.d(TAG, "[onCreateView]"); } View layout = inflater.inflate(R.layout.fragment_waypoint, container, false); locationNotFoundTextView = layout.findViewById(R.id.waypointLocationNotFound); Loading @@ -111,13 +176,12 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC } private void restoreState(Bundle savedInstanceState) { if (Logger.DEBUG) { Log.d(TAG, "[restoreState]"); } if (savedInstanceState.containsKey(KEY_WAITING)) { isWaitingForCamera = true; } if (savedInstanceState.containsKey(KEY_URI)) { photoUri = savedInstanceState.getParcelable(KEY_URI); setThumbnail(photoThumb); } if (savedInstanceState.containsKey(KEY_THUMB)) { photoThumb = savedInstanceState.getParcelable(KEY_THUMB); setThumbnail(photoThumb); } if (savedInstanceState.containsKey(KEY_LOCATION)) { location = savedInstanceState.getParcelable(KEY_LOCATION); Loading @@ -134,23 +198,28 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); if (Logger.DEBUG) { Log.d(TAG, "[onSaveInstanceState]"); } if (photoUri != null) { outState.putParcelable(KEY_URI, photoUri); } if (photoThumb != null) { outState.putParcelable(KEY_THUMB, photoThumb); } if (location != null) { outState.putParcelable(KEY_LOCATION, location); } if (isWaitingForCamera) { outState.putBoolean(KEY_WAITING, true); } } @Override public void onResume() { super.onResume(); if (Logger.DEBUG) { Log.d(TAG, "[onResume]"); } if (!hasLocation()) { runLoggerTask(); } if (photoUri != null && photoThumb == null && !isWaitingForCamera) { runThumbnailTask(photoUri); } } /** Loading Loading @@ -196,9 +265,12 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC /** * Start image task * Transforms image if needed and generates thumbnail for URI * @param uri URI */ private void runImageTask(@NonNull Uri uri) { if (imageTask == null || !imageTask.isRunning()) { if (Logger.DEBUG) { Log.d(TAG, "[runImageTask]"); } clearImage(); saveButton.setEnabled(false); imageTask = new ImageTask(uri, this); Loading @@ -207,6 +279,20 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC } } /** * Start thumbnail task * Generates thumbnail for URI * @param uri URI */ private void runThumbnailTask(@NonNull Uri uri) { if (imageTask == null || !imageTask.isRunning()) { if (Logger.DEBUG) { Log.d(TAG, "[runThumbnailTask]"); } imageTask = new ImageTask(uri, this, true); executor.execute(imageTask); setRefreshing(true); } } private void setRefreshing(boolean refreshing) { swipe.setRefreshing(refreshing); } Loading @@ -214,6 +300,7 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC @Override public void onDetach() { super.onDetach(); if (Logger.DEBUG) { Log.d(TAG, "[onDetach]"); } cancelLoggerTask(); cancelImageTask(); } Loading Loading @@ -362,63 +449,6 @@ public class WaypointFragment extends Fragment implements LoggerTask.LoggerTaskC } } /** * Request location permission(s), on granted run logger task */ final ActivityResultLauncher<String[]> requestLocationPermission = registerForActivityResult(new RequestMultiplePermissions(), results -> { if (Logger.DEBUG) { Log.d(TAG, "[requestLocationPermission: " + results.entrySet() + "]"); } boolean isGranted = false; for (Map.Entry<String, Boolean> result : results.entrySet()) { if (result.getValue()) { isGranted = true; } } if (isGranted) { if (Logger.DEBUG) { Log.d(TAG, "[LocationPermission: granted]"); } runLoggerTask(); } else { if (Logger.DEBUG) { Log.d(TAG, "[LocationPermission: refused]"); } finish(); } }); /** * Request write permission, on granted take picture */ final ActivityResultLauncher<String> requestWritePermission = registerForActivityResult(new RequestPermission(), isGranted -> { if (Logger.DEBUG) { Log.d(TAG, "[requestWritePermission: " + isGranted + "]"); } if (isGranted) { requestImageCapture(); } }); /** * Take picture, then run image task */ final ActivityResultLauncher<Uri> takePicture = registerForActivityResult(new TakePicture() { @NonNull @Override public Intent createIntent(@NonNull Context context, @NonNull Uri input) { int flags = FLAG_GRANT_WRITE_URI_PERMISSION|FLAG_GRANT_READ_URI_PERMISSION|FLAG_GRANT_PERSISTABLE_URI_PERMISSION; return super.createIntent(context, input).addFlags(flags); } }, isSaved -> { if (isSaved && photoUri != null) { ImageHelper.galleryAdd(requireContext(), photoUri); runImageTask(photoUri); } }); /** * Open image file, then run image task */ final ActivityResultLauncher<String[]> openPicture = registerForActivityResult(new OpenLocalDocument(), uri -> { if (uri != null) { photoUri = uri; runImageTask(photoUri); } }); /** * Update state on location received * @param location Current location Loading