diff --git a/myTracks/src/main/AndroidManifest.xml b/myTracks/src/main/AndroidManifest.xml index 8d50a6e4f..1329c6ed4 100644 --- a/myTracks/src/main/AndroidManifest.xml +++ b/myTracks/src/main/AndroidManifest.xml @@ -253,5 +253,15 @@ limitations under the License. android:authorities="com.google.android.maps.mytracks.search" android:exported="false" android:name="com.google.android.apps.mytracks.content.SearchEngineProvider" /> + + + + diff --git a/myTracks/src/main/java/com/google/android/apps/mytracks/AbstractSendToGoogleActivity.java b/myTracks/src/main/java/com/google/android/apps/mytracks/AbstractSendToGoogleActivity.java index cb301155c..7aa2a024f 100644 --- a/myTracks/src/main/java/com/google/android/apps/mytracks/AbstractSendToGoogleActivity.java +++ b/myTracks/src/main/java/com/google/android/apps/mytracks/AbstractSendToGoogleActivity.java @@ -53,7 +53,6 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv private static final int DELETE_REQUEST_CODE = 3; protected static final int GOOGLE_PLAY_SERVICES_REQUEST_CODE = 4; - protected static final int CAMERA_REQUEST_CODE = 5; protected static final int GPS_REQUEST_CODE = 6; @Override diff --git a/myTracks/src/main/java/com/google/android/apps/mytracks/TrackDetailActivity.java b/myTracks/src/main/java/com/google/android/apps/mytracks/TrackDetailActivity.java index c2f61c51a..dfe9ee07e 100644 --- a/myTracks/src/main/java/com/google/android/apps/mytracks/TrackDetailActivity.java +++ b/myTracks/src/main/java/com/google/android/apps/mytracks/TrackDetailActivity.java @@ -38,6 +38,7 @@ import com.google.android.apps.mytracks.util.TrackRecordingServiceConnectionUtil import com.google.android.apps.mytracks.util.TrackUtils; import com.google.android.maps.mytracks.R; +import android.Manifest; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -46,8 +47,14 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; + +import androidx.annotation.NonNull; +import androidx.core.app.ActivityCompat; import androidx.core.app.TaskStackBuilder; +import androidx.core.content.FileProvider; import androidx.viewpager.widget.ViewPager; + +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; @@ -70,6 +77,8 @@ import java.util.Date; public class TrackDetailActivity extends AbstractSendToGoogleActivity implements ChooseActivityTypeCaller, ConfirmDeleteDialogFragment.ConfirmDeleteCaller { + private static final String TAG = TrackDetailActivity.class.getSimpleName(); + public static final String EXTRA_TRACK_ID = "track_id"; public static final String EXTRA_MARKER_ID = "marker_id"; @@ -77,7 +86,10 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity private static final String PHOTO_URI_KEY = "photo_uri_key"; private static final String HAS_PHOTO_KEY = "has_photo_key"; private static final String JPEG_EXTENSION = "jpeg"; - + + private static final int CAMERA_REQUEST_CODE = 5; + private static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 6; + // The following are set in onCreate private boolean hasCamera; private Uri photoUri; @@ -289,11 +301,19 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity if (requestCode == CAMERA_REQUEST_CODE) { if (resultCode == RESULT_CANCELED) { Toast.makeText(this, R.string.marker_add_canceled, Toast.LENGTH_LONG).show(); + return; } hasPhoto = resultCode == RESULT_OK; - } else { - super.onActivityResult(requestCode, resultCode, data); + + if (hasPhoto) { + //Register photo in media scanner + Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + mediaScanIntent.setData(photoUri); + this.sendBroadcast(mediaScanIntent); + return; + } } + super.onActivityResult(requestCode, resultCode, data); } @Override @@ -331,6 +351,7 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker); insertPhotoMenuItem = menu.findItem(R.id.track_detail_insert_photo); + insertPhotoMenuItem.setVisible(new Intent(MediaStore.ACTION_IMAGE_CAPTURE).resolveActivity(getPackageManager()) != null); shareMenuItem = menu.findItem(R.id.track_detail_share); shareMenuItem.setEnabled(!isSharedWithMe); @@ -353,26 +374,18 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity Intent intent; switch (item.getItemId()) { case R.id.track_detail_insert_marker: - intent = IntentUtils.newIntent(this, MarkerEditActivity.class) - .putExtra(MarkerEditActivity.EXTRA_TRACK_ID, trackId); + intent = IntentUtils + .newIntent(this, MarkerEditActivity.class) + .putExtra(MarkerEditActivity.EXTRA_TRACK_ID, trackId); startActivity(intent); return true; case R.id.track_detail_insert_photo: - if (!FileUtils.isExternalStorageWriteable()) { - Toast.makeText(this, R.string.external_storage_not_writable, Toast.LENGTH_LONG).show(); + if (!FileUtils.isExternalStorageWriteable() || ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) { + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE); return false; } - File dir = FileUtils.getPhotoDir(trackId); - FileUtils.ensureDirectoryExists(dir); - - String fileName = SimpleDateFormat.getDateTimeInstance().format(new Date()); - File file = new File(dir, FileUtils.buildUniqueFileName(dir, fileName, JPEG_EXTENSION)); - - photoUri = Uri.fromFile(file); - intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE).putExtra( - MediaStore.EXTRA_OUTPUT, photoUri); - startActivityForResult(intent, CAMERA_REQUEST_CODE); + takePicture(); return true; case R.id.track_detail_markers: intent = IntentUtils.newIntent(this, MarkerListActivity.class) @@ -380,13 +393,11 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity startActivity(intent); return true; case R.id.track_detail_voice_frequency: - FrequencyDialogFragment.newInstance(R.string.voice_frequency_key, - PreferencesUtils.VOICE_FREQUENCY_DEFAULT, R.string.menu_voice_frequency) + FrequencyDialogFragment.newInstance(R.string.voice_frequency_key, PreferencesUtils.VOICE_FREQUENCY_DEFAULT, R.string.menu_voice_frequency) .show(getSupportFragmentManager(), FrequencyDialogFragment.FREQUENCY_DIALOG_TAG); return true; case R.id.track_detail_split_frequency: - FrequencyDialogFragment.newInstance(R.string.split_frequency_key, - PreferencesUtils.SPLIT_FREQUENCY_DEFAULT, R.string.menu_split_frequency) + FrequencyDialogFragment.newInstance(R.string.split_frequency_key, PreferencesUtils.SPLIT_FREQUENCY_DEFAULT, R.string.menu_split_frequency) .show(getSupportFragmentManager(), FrequencyDialogFragment.FREQUENCY_DIALOG_TAG); return true; case R.id.track_detail_edit: @@ -410,6 +421,36 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity } } + private void takePicture() { + Intent intent; + File dir = FileUtils.getPhotoDir(trackId); + FileUtils.ensureDirectoryExists(dir); + + String fileName = SimpleDateFormat.getDateTimeInstance().format(new Date()); + File file = new File(dir, FileUtils.buildUniqueFileName(dir, fileName, JPEG_EXTENSION)); + + if (file != null) { + photoUri = FileProvider.getUriForFile(this, "com.google.android.apps.mytracks.fileprovider", file); + Log.d(TAG, "Taking photo to URI: " + photoUri); + intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE) + .putExtra(MediaStore.EXTRA_OUTPUT, photoUri); + startActivityForResult(intent, CAMERA_REQUEST_CODE); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if (requestCode == EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE) { + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) { + Toast.makeText(this, R.string.external_storage_not_writable, Toast.LENGTH_LONG).show(); + } else { + this.takePicture(); + } + return; + } + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + @Override public boolean onTrackballEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { diff --git a/myTracks/src/main/res/xml/file_paths.xml b/myTracks/src/main/res/xml/file_paths.xml new file mode 100644 index 000000000..65aa363eb --- /dev/null +++ b/myTracks/src/main/res/xml/file_paths.xml @@ -0,0 +1,6 @@ + + + + diff --git a/myTracksLib/src/main/java/com/google/android/apps/mytracks/util/FileUtils.java b/myTracksLib/src/main/java/com/google/android/apps/mytracks/util/FileUtils.java index 023c88ce6..0f218c4b5 100644 --- a/myTracksLib/src/main/java/com/google/android/apps/mytracks/util/FileUtils.java +++ b/myTracksLib/src/main/java/com/google/android/apps/mytracks/util/FileUtils.java @@ -31,11 +31,6 @@ public class FileUtils { private FileUtils() {} - /** - * The backups directory under the My Tracks external storage directory. - */ - public static final String BACKUPS_DIR = "backups"; - /** * The My Tracks external storage directory. */ @@ -52,11 +47,6 @@ public class FileUtils { */ public static final String PLAY_TRACKS_DIR = "temp"; - /** - * The temp files directory under the My Tracks cache directory. - */ - public static final String TEMP_FILES_DIR = "temp_files"; - /** * The pictures directory under the My Tracks external storage directory. */