I have to following code to launch and the audio recorder on Android:
final Intent recordSoundIntent = new Intent
("android.provider.MediaStore.RECORD_SOUND");
String fileName = Environment.getExternalStorageDirectory() +
File.separator + UUID.randomUUID() + ".3gpp";
recordSoundIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new
File(fileName)));
startActivityForResult(Intent.createChooser(recordSoundIntent,
getString(R.string.record_sound_chooser)), INTENT_SOUND_RECORDING);
My problem is the following:
My filename (fileName) has no effect, the Uri returned from
data.getData() returns in my last test run: content://media/external/audio/media/41.
However, this file is created on my sdcard: recording34485.3gpp. If it
is not possible to set custom location upon creating sound it is the
location to this file I would like.
Was working on the same problem. Could not find a way to set location directly but found a work around solution of getting and renaming it.
Getting file name was dealt with here, file is then renamed using java.io.File.renameTo(). You'll need android.permission.WRITE_EXTERNAL_STORAGE in your manifest file for the rename to work.
Here is my test code example:
public static final int REQUEST_RECORD_SOUND = 7;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
startActivityForResult(intent, REQUEST_RECORD_SOUND);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == REQUEST_RECORD_SOUND){
String sourcePath = getRealPathFromURI(intent.getData());
File root = Environment.getExternalStorageDirectory();
String destPath = root.getPath() + File.separator + "newName.txt";
File sourceF = new File(sourcePath);
try {
sourceF.renameTo(new File(destPath));
} catch (Exception e) {
Toast.makeText(this, "Error:" + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
/**
* from:
* https://stackoverflow.com/questions/3401579/get-filename-and-path-from-uri-from-mediastore
*/
public String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
Related
I'm referencing this link for showing images from a specific path in internal storage. But its only working with ACTION_VIEW but when I use ACTION_PICK its not showing that same path instead its simply opening gallery. Is there any way to select a single image from that specific path after showing?
public class NewActivity extends AppCompatActivity{
private static final String file_path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/fun";
private File[] allFiles ;
private String imagepath ;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File folder = new File(file_path);
allFiles = folder.listFiles();
findViewById(R.id.start).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new SingleMediaScanner(NewActivity.this, allFiles[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_PICK);
intent.setData(uri);
startActivityForResult(intent, 100);
mMs.disconnect();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==100 && resultCode==RESULT_OK){
try{
Uri selectedImageUri = data.getData();
String[] projection = {MediaStore.Images.Media.DATA};
//Cursor cursor_gallery = activity.managedQuery(selectedImageUri, projection, null, null, null);
Cursor cursor_gallery = getContentResolver().query(selectedImageUri, projection, null, null, null);
int column_index = 0;
if (cursor_gallery != null) {
column_index = cursor_gallery.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor_gallery.moveToFirst();
imagepath = cursor_gallery.getString(column_index);
cursor_gallery.close();
}
System.out.println("sammy_imagepath "+imagepath);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
When you make an ACTION_PICK intent, you're asking another application to perform an action (let them pick a file). There is no way to ensure it works a certain way- the user could just as easily have added another app that implements ACTION_PICK and does something else. So no, there is no way to ensure it will pick from that path. If you absolutely need that, you need to implement your own picker instead of using ACTION_PICK.
I'm trying to read files from a USB storage device connected to my Google Pixel. I'm currently using this method to select the path of the drive so I can query it for its contents
private static final String TAG = "MainActivity";
private static final int REQUEST_CHOOSE_DRIVE = 1;
private TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.text);
Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(i, REQUEST_CHOOSE_DRIVE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CHOOSE_DRIVE) {
Uri uri = data.getData();
}
}
However, the Uri looks something like /tree/... which doesn't seem to be a real path in the Android file system (verified via adb shell). How can I use this uri to query the contents of a portable storage device? I tried using the answer given here but the linked function returns null.
You are getting tree Uri. So you need to Add below code to get files from Tree Uri.
DocumentFile documentFile = DocumentFile.fromTreeUri(this, uri);
for (DocumentFile file : documentFile.listFiles()) {
if(file.isDirectory()){ // if it is sub directory
// Do stuff with sub directory
}else{
// Do stuff with normal file
}
Log.d("Uri->",file.getUri() + "\n");
}
For the query the contents, you can use below code.
ContentResolver contentResolver = getActivity().getContentResolver();
Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri,
DocumentsContract.getTreeDocumentId(uri));
Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri,
DocumentsContract.getTreeDocumentId(uri));
Cursor docCursor = contentResolver.query(docUri, new String[]{
Document.COLUMN_DISPLAY_NAME, Document.COLUMN_MIME_TYPE}, null, null, null);
try {
while (docCursor.moveToNext()) {
Log.d(TAG, "found doc =" + docCursor.getString(0) + ", mime=" + docCursor
.getString(1));
}
} finally {
// close cursor
}
You can check Google sample code:
https://github.com/googlesamples/android-DirectorySelection/blob/master/Application/src/main/java/com/example/android/directoryselection/DirectorySelectionFragment.java#L150
I used Intent ACTION_GET_CONTENT to show recent files from phone memory. That includes images, pdf, google drive documents(pdf, xlsx) as shown in screenshot below. I want to get the name and full path so that I can upload the file to server. I/m getting the mime type correctly as of now.
public class MainActivity extends AppCompatActivity {
Button btn;
TextView txt;
private final static int EXTERNAL = 111;
private final static int ATTACH = 11;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.btn);
txt = (TextView)findViewById(R.id.txt);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
photoIntent();
} else {
if (shouldShowRequestPermissionRationale(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// showToast("Permission Required...");
}
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, EXTERNAL);
}
} else {
photoIntent();
}
}
});
}
private void photoIntent() {
Intent intent = new Intent();
Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath());
intent.setDataAndType(uri, "*/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Complete action using"), ATTACH);
}
#Override
public void onRequestPermissionsResult(int requestcode, String[] permission, int[] grantRes){
if (requestcode == EXTERNAL) {
if (grantRes[0] == PackageManager.PERMISSION_GRANTED) {
photoIntent();
} else {
Toast.makeText(this, "Unable to Access Image", Toast.LENGTH_SHORT).show();
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == ATTACH && resultCode == RESULT_OK){
Uri uri = data.getData();
System.out.println("sammy_sourceUri "+uri);
String mimeType = getContentResolver().getType(uri);
System.out.println("sammy_mimeType "+ mimeType);
}
}
}
I want to get the name and full path so that I can upload the file to server
There is no "full path", because there may not be a "file".
You are invoking ACTION_GET_CONTENT. This returns a Uri to some content. Where that content comes from is up to the developers of the ACTION_GET_CONTENT activity that the user chose. That could be:
An ordinary file on the filesystem that happens to be one that you could access
An ordinary file on the filesystem that resides somewhere that you cannot access, such as internal storage for the other app
A file that requires some sort of conversion for it to be useful, such as decryption
A BLOB column in a database
Content that is generated on the fly, the way this Web page is generated on the fly by the Stack Overflow servers
And so on
To use the content from the Uri, use a ContentResolver and openInputStream().
how to use this InputStream to upload to server API as file?
Either your chosen HTTP API supports an InputStream as the source of this content, or it does not. If it does, just use the InputStream directly. If not, use the InputStream to make a temporary copy of the content as a file that you can directly access (e.g., in getCacheDir()), upload that file, then delete the file when the upload is complete.
try this
public static ArrayList<String> getImagesFromCameraDir(Context context) {
Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ArrayList<String> filePaths = new ArrayList<>();
final String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_ADDED};
Cursor mCursor = context.getContentResolver().query(mImageUri, columns, MediaStore.Images.Media.DATA + " like ? ", new String[]{"%/DCIM/%"}, null);
if (mCursor != null) {
mCursor.moveToFirst();
try {
int uploadImage = 0;
uploadImage = mCursor.getCount();
for (int index = 0; index < uploadImage; index++) {
mCursor.moveToPosition(index);
int idx = mCursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
filePaths.add(mCursor.getString(idx));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
mCursor.close();
}
}
return filePaths;
}
get real path from URI
public String getRealPathFromURI(Uri contentUri)
{
String[] proj = { MediaStore.Audio.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
FILENAME :
String filename = path.substring(path.lastIndexOf("/")+1);
I am using the built-in voice recorder in my Android App. Is there a way I can change the default location of recorded files? They are stored in the "Sound" folder in SD Card. I want to store them in a different folder. How do I do it, if that's even possible?
Below is a simple code for calling the built-in Android voice recorder App.
Button startRecording = (Button) findViewById(R.id.startBtn);
startRecording.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent recordIntent = new Intent(
MediaStore.Audio.Media.RECORD_SOUND_ACTION);
startActivityForResult(recordIntent, REQUEST_CODE_RECORD);
}
});
well you will have to allow the file to be recorded using where ever the default location and file name that are used and then move the file.
you could do something like this in your onActivityResult:
#Override protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_RECORD:
if (resultCode == Activity.RESULT_OK) {
// Sound recorder does not support EXTRA_OUTPUT
Uri uri = data.getData();
try {
String filePath = getAudioPathFromUri(uri);
copyFile(filePath);
getContentResolver().delete(uri, null, null);
(new File(filePath)).delete();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
private String getAudioPathFromUri(Uri uri) {
Cursor cursor = getContentResolver()
.query(uri, null, null, null, null);
cursor.moveToFirst();
int index = cursor.getColumnIndex(MediaStore.Audio.AudioColumns.DATA);
return cursor.getString(index);
}
private void copyFile(String fileName) throws IOException {
Files.copy(new File(fileName),
new File(Environment.getExternalStorageDirectory(), fileName));
}
}
I'm currently developing an app which uses the built-in Camera.
I call this snippet by clicking a button :
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
path += "/myFolder/myPicture.jpg";
File file = new File( path );
//file.mkdirs();
Uri outputFileUri = Uri.fromFile( file );
//String absoluteOutputFileUri = file.getAbsolutePath();
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intent, 0);
After taking the picture with the camera, the jpg is well stored in sdcard/myFolder/myPicture.jpg, but it is also stored in /sdcard/DCIM/Camera/2011-06-14 10.36.10.jpg, which is the default path.
Is there a way to prevent the built-in Camera to store the picture in the default folder?
Edit : I think I will use the Camera class directly
Another way, tested on android 2.1, is take the ID or Absolute path of the gallery last image, then you can delete the duplicated image.
It can be done like that:
/**
* Gets the last image id from the media store
* #return
*/
private int getLastImageId(){
final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA };
final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, null, null, imageOrderBy);
if(imageCursor.moveToFirst()){
int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
String fullPath = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
Log.d(TAG, "getLastImageId::id " + id);
Log.d(TAG, "getLastImageId::path " + fullPath);
imageCursor.close();
return id;
}else{
return 0;
}
}
And to remove the file:
private void removeImage(int id) {
ContentResolver cr = getContentResolver();
cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media._ID + "=?", new String[]{ Long.toString(id) } );
}
This code was based on the post: Deleting a gallery image after camera intent photo taken
While the answer from "Ilango J" provides the basic idea.. I thought I'd actually write in how I actually did it.
The temporary file path that we were setting in intent.putExtra() should be avoided as it's a non standard way across different hardwares. On HTC Desire (Android 2.2) it did not work, And i've heard it works on other phones. It's best to have a neutral approach which works every where.
Please note that this solution (using the Intent) requires that the phone's SD Card is available and is not mounted onto the PC. Even the normal Camera app wouldn't work when the SD Card is connected to the PC.
1) Initiate the Camera Capture intent. Note, I disabled temporary file writes (non-standard across different hardware)
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(camera , 0);
2) Handle callback and retrieve the captured picture path from the Uri object and pass it to step#3
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case CAPTURE_PIC: {
if (resultCode == RESULT_OK && data != null) {
Uri capturedImageUri = data.getData();
String capturedPicFilePath = getRealPathFromURI(capturedImageUri);
writeImageData(capturedImageUri, capturedPicFilePath);
break;
}
}
}
}
public String getRealPathFromURI(Uri contentUri) {
String[] projx = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, projx, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
3) Clone and delete the file. See that I used the Uri's InputStream to read the content.
The same can be read from the File of the capturedPicFilePath too.
public void writeImageData(Uri capturedPictureUri, String capturedPicFilePath) {
// Here's where the new file will be written
String newCapturedFileAbsolutePath = "something" + JPG;
// Here's how to get FileInputStream Directly.
try {
InputStream fileInputStream = getContentResolver().openInputStream(capturedPictureUri);
cloneFile(fileInputStream, newCapturedFileAbsolutePath);
} catch (FileNotFoundException e) {
// suppress and log that the image write has failed.
}
// Delete original file from Android's Gallery
File capturedFile = new File(capturedPicFilePath);
boolean isCapturedCameraGalleryFileDeleted = capturedFile.delete();
}
public static void cloneFile(InputStream currentFileInputStream, String newPath) {
FileOutputStream newFileStream = null;
try {
newFileStream = new FileOutputStream(newPath);
byte[] bytesArray = new byte[1024];
int length;
while ((length = currentFileInputStream.read(bytesArray)) > 0) {
newFileStream.write(bytesArray, 0, length);
}
newFileStream.flush();
} catch (Exception e) {
Log.e("Prog", "Exception while copying file " + currentFileInputStream + " to "
+ newPath, e);
} finally {
try {
if (currentFileInputStream != null) {
currentFileInputStream.close();
}
if (newFileStream != null) {
newFileStream.close();
}
} catch (IOException e) {
// Suppress file stream close
Log.e("Prog", "Exception occured while closing filestream ", e);
}
}
}
try this code:
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
path += "/myFolder/myPicture.jpg";
File file = new File( path );
//file.mkdirs();
Uri outputFileUri = Uri.fromFile( file );
//String absoluteOutputFileUri = file.getAbsolutePath();
intent.putExtra("output", outputFileUri);
startActivityForResult(intent, 0);