I have built an Camera application following a Tutorial from Youtube. It saves the Files on External Storage with following code
public void takePicture(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
file = Uri.fromFile(getOutputMediaFile());
intent.putExtra(MediaStore.EXTRA_OUTPUT, file);
startActivityForResult(intent, 100);
}
private static File getOutputMediaFile() {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "CameraDemo");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("CameraDemo", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
return new File(mediaStorageDir.getPath() + File.separator +
"IMG_" + timeStamp + ".jpg");
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100) {
if (resultCode == RESULT_OK) {
imageView.setImageURI(file);
}
}
}
But, I would like to show a Dialog box to user when app starts with directory chooser dialog where they want to save images which I followed the Tutorial from this link https://www.codeproject.com/Articles/547636/Android-Ready-to-use-simple-directory-chooser-dial
The code for Directory choose dialog is below
DirectoryChooserDialog directoryChooserDialog =
new DirectoryChooserDialog(MainActivity.this,
new DirectoryChooserDialog.ChosenDirectoryListener()
{
#Override
public void onChosenDir(String chosenDir)
{
m_chosenDir = chosenDir;
Toast.makeText(
MainActivity.this, "Chosen directory: " +
chosenDir, Toast.LENGTH_LONG).show();
}
});
// Toggle new folder button enabling
directoryChooserDialog.setNewFolderEnabled(m_newFolderEnabled);
// Load directory chooser dialog for initial 'm_chosenDir' directory.
// The registered callback will be called upon final directory selection.
directoryChooserDialog.chooseDirectory(m_chosenDir);
m_newFolderEnabled = ! m_newFolderEnabled;
And also indeed, I have a separate class of DirectoryChooserDialog.
Now how do I merge the first code with second one such that when Image taken from camera will save to the folder that users selected from second code not to external storage Directory as specified by first code.
Image file for DirectoryChooserDialog appears as
Related
I have been able to make users upload photos to server taken from their gallery, but when a user uses camera to capture live and upload, I get this error unsupported scheme: file::///storage/...
I am using android upload service library
implementation "net.gotev:uploadservice:3.5.2"
I searched and discovered that file:// scheme is not allowed to be attached with Intent.
1. Selecting image from camera on button click
capture_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,
FileProvider.getUriForFile(UploadActivity2.this, BuildConfig.APPLICATION_ID + ".provider",
createImageFile()));
startActivityForResult(intent, 0);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
2. Getting the image captured
if (resultCode == Activity.RESULT_OK)
switch (requestCode){
case 0:
try {
Uri cameraPath = FileProvider.getUriForFile(UploadActivity2.this,
BuildConfig.APPLICATION_ID + ".provider", createImageFile());
String stringUri = cameraPath.toString();
selectedImages.add(stringUri);
}catch (IOException ex) {
ex.printStackTrace();
Glide.with(this)
.load(cameraFilePath)
.into(display_image);
break;
}
}
As you see, I am using file provider to get Uri and storing the uri in a variable called selectedimages so I can pass it through an intent to another activity where the upload occurs
createImageFile method
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.UK).format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
//This is the directory in which the file will be created. This is the default location of Camera photos
File storageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM), "Camera");
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for using again
cameraFilePath = "file://" + image.getAbsolutePath();
return image;
}
3. Passing intent PATH, to uploadActivity
next_upload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(UploadActivity2.this, UploadActivity3.class);
intent.putStringArrayListExtra("PATH", selectedImages);
startActivity(intent);
}
});
5. UploadAcvity where the upload happens
public void upload() {
ArrayList<String> selectedImages = getIntent().getStringArrayListExtra("PATH");
try {
String uploadId = UUID.randomUUID().toString();
//Creating a multi part request
new MultipartUploadRequest(this, uploadId, EndPoints.UPLOAD_URL)
.addFileToUpload(selectedImages.get(0), "image") //Adding file
.addParameter("caption", captionx) //Adding text parameter to the request
.setNotificationConfig(new UploadNotificationConfig())
.setMaxRetries(0)
.startUpload(); //Starting the upload
} catch (Exception exc) {
Toast.makeText(this, exc.getMessage(), Toast.LENGTH_SHORT).show();
}
}
Using this.
a. The image is not displaying in point 2 using Glide.with(this)
.load(cameraFilePath)
.into(display_image);
b. The image uploads but it is an empty file of 0 bytes.
But when I change the value of the variable of selectedImages in point 2 from selectedImages.add(stringUri); to selectedImages.add(cameraFilePath);
b. After clicking upload, I get error unsupported scheme: file::///storage/
Found the answer.
1. In the createImageFile method. I had to get the coontent:// url from the captured file using -
File newFile = new File(storageDir, image.getName());
contentUrl = FileProvider.getUriForFile(UploadActivity2.this,
BuildConfig.APPLICATION_ID + ".provider", newFile);
stringContentUrl = contentUrl.toString();
2. Then I passed the stringContentUrl into selected images String while getting the image captured.
selectedImages.add(stringContentUrl);
3. Passed it through an intent Extra and called it in the uploadActivity as seen in point 3 and 4 in the question.
In my Android Studio project I want to implement a function, where 3 files should get exported. So I want the user to choose a directory and enter the name for a new directory, in which the files are going to be stored.
Right now, I already have an intent which lets the user choose, where to place the new folder and how to name the new folder:
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(DocumentsContract.Document.MIME_TYPE_DIR);
intent.putExtra(Intent.EXTRA_TITLE, getString(R.string.folder_backup));
startActivityForResult(intent, REQUEST_CODE_SAVE_BACKUP);
In the onActivityResult method, I tried to save the 3 files. Here is the code:
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_SAVE_BACKUP
&& resultCode == Activity.RESULT_OK) {
Uri uri = null;
if (data != null) {
uri = data.getData();
String dbFileName = ExampleDatabase.DB_NAME;
List<String> dbComponentsNames = new ArrayList<>();
dbComponentsNames.add(dbFileName);
dbComponentsNames.add(dbFileName + "-shm");
dbComponentsNames.add(dbFileName + "-wal");
try {
for (int i = 0; i < dbComponentsNames.size(); i++) {
uri = Uri.parse(uri.toString() + "%2F" + dbComponentsNames.get(i));
File dbComponent = getActivity().getDatabasePath(dbComponentsNames.get(i));
byte[] byteArray = new byte[(int) dbComponent.length()];
FileInputStream fileInputStream = new FileInputStream(dbComponent);
fileInputStream.read(byteArray);
ParcelFileDescriptor pfd = getActivity().getContentResolver().openFileDescriptor(uri, "w");
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
fileOutputStream.write(byteArray);
pfd.close();
}
} catch (Exception e) {
}
}
}
}
My idea was to get the URI from the created folder and just append the file names to that URI, so these files get stored in the newly created folder. I also found out, that a \ in the URI is replaced by %2F but this doesn't matter. Does anyone know, how to achieve saving multiple files without using MediaStore?
I want to implement the function of adding a photo in my application. The application must add a photo that the user took in the ImageView and show in the gallery of the phone.
I did the first part, but I can’t realize the second one. I see the file in the phone directory, but it is not added to the gallery. If it is easy for someone, tell me more how to create your own catalog in the phone gallery.
public File createFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "IMG_" + timeStamp + "_";
File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "Camera");
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
currentPhotoPath = "file://" + image.getAbsolutePath();
return image;
}
The function of adding photos to the gallery (took from Google's guide https://developer.android.com/training/camera/photobasics)
private void galleryAddPic() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(currentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
Log.d("camera", "galleryAddPic: image add");
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_IMAGE_CAPTURE){
Photo.setImageURI(Uri.parse(currentPhotoPath));
galleryAddPic();
Log.d("camera", "onActivityResult: photo added");
}
else if (requestCode == REQUEST_CATEGORY) {
presenter.detailCategory((String) data.getSerializableExtra("category"));
}
}
How to open inbuilt gallery app with a specific album opened on screen ?
I know this code can be used for launching gallery app , but how to filter a specific album ? or open it ?
Intent i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, RESULT_LOAD_IMAGE);
Assume your photos ares stored at youCam folder or it can be any folder
If you are compiling against API 23 or Greater then get runtime permision READ_EXTERNAL_STORAGE
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/youCam);
File[] listFile = file.listFiles();
new HomeScreen.SingleMediaScanner(HomeScreen.this, listFile[0]);
...
public class SingleMediaScanner implements MediaScannerConnection.MediaScannerConnectionClient {
private MediaScannerConnection mMs;
private File mFile;
public SingleMediaScanner(Context context, File f) {
mFile = f;
mMs = new MediaScannerConnection(context, this);
mMs.connect();
}
public void onMediaScannerConnected() {
mMs.scanFile(mFile.getAbsolutePath(), null);
}
public void onScanCompleted(String path, Uri uri) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
startActivity(intent);
mMs.disconnect();
}
}
This will open you all images in that folder in default gallery.
I have an app that right now opens up the camera at the click of a button. Then the user can take the picture with the standard camera app which leads to a Cancel/Save option. If cancel if chosen, the picture can be taken again. If the Save option is chosen the image is saved to the Gallery. I want to add some stuff to the image in this Cancel/Save mode before either are clicked.
I think the best way to do this would be to bring the photo into my app and do my modifications there and save with a button. I have no idea how to do this. I know I have to use the onActivityResult function, but thats about it.
Any advice is appreciated.
When you launch the IMAGE_CAPTURE intent to let the user take a photo, you should pass as parameter the path where you store the image.
First you should save the path of the taken picture, then, when the user come back to your activity, manage the bitmap and combine with other elements.
camera.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String storageState = Environment.getExternalStorageState();
if (storageState.equals(Environment.MEDIA_MOUNTED)) {
long time = System.currentTimeMillis();
File root = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
File dir = new File(root.getAbsolutePath() + "/Camera");
if (dir.exists() == false) {
dir.mkdirs();
}
String path = dir.getAbsolutePath() + File.separatorChar
+ time + ".jpg";
filesaved = new File(path);
try {
if (filesaved.exists() == false) {
filesaved.getParentFile().mkdirs();
filesaved.createNewFile();
}
} catch (IOException e) {
Toast.makeText(
context,
"Unable to create external file"
+ storageState, Toast.LENGTH_LONG).show();
return;
}
uritopass = Uri.fromFile(filesaved);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uritopass);
startActivityForResult(intent, TAKE_PICTURE);
} else {
Toast.makeText(
context,
"External Storeage (SD Card) is required.\n\nCurrent state: "
+ storageState, Toast.LENGTH_LONG).show();
}
}
});
...
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == TAKE_PICTURE) {
//user took a photo
File imageFile = new File(filesaved.toString());
Bitmap bm = decodeFile(imageFile);
if (bm != null) {
bm = combineImages(bm);
img.setImageBitmap(bm);
}
}
}
}
...
decodefile method to load the Bitmap from the original file Here.
combineImages method to combine 2 or more Bitmap Here .