I am knew to Android Studio. I want to create folder in external storage through android app. I tried using getExternalStorageDir() but it is not implemented for API level above 23. Please guide me to create folder and file in android app. Ignore any grammatical mistake if present. And I also want this process to be done in background without going anywhere from mainactivity.
The user can choose to make a new folder while using the SAF picker, but you can't programmatically create a folder in external storage without any user interaction.
For instance, add a Button to your layout and give it an OnClickListener. Then have it run this code when clicked:
int OPEN_REQUEST_CODE = 41;
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_TITLE, "Notes");
startActivityForResult(intent, OPEN_REQUEST_CODE);
This will prompt the user to create a document titled "Notes", but the user can choose where the document is stored and can even rename it if they so choose. Within the picker, there's an option named "New folder" that the user can select.
Part of the idea by Scoped Storage is that they don't want us devs to just be polluting the external storage with all sorts of files and folders. So this puts the user more in control.
You can make a subfolder once the user chooses a folder, but this still requires prompting the user to grant one-time access to a chosen folder:
https://stackoverflow.com/a/36547137/7434090
Also, this tutorial was very helpful to me while learning SAF:
https://en.proft.me/2018/05/24/using-android-storage-access-framework/
Put this in public void
Intent intent = new
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, NEW_FOLDER_REQUEST_CODE);
This on Activity Result
if (_resultCode == Activity.RESULT_OK) { if (_requestCode ==
NEW_FOLDER_REQUEST_CODE)
{ if (_data != null) { Uri currentUri = _data.getData();
DocumentFile pickedDir =
DocumentFile.fromTreeUri(this, currentUri);
DocumentFile newDir =
pickedDir.createDirectory("MyFolder"); } } }
This is another public void on oncreate
}
private static final int NEW_FOLDER_REQUEST_CODE = 43;
}
Related
I am working on an android app, please tell me, How to show only videos folder?
this code shows all folder in my device, But I want to show only videos folder. How to do that?
here is my code
public class MainActivity extends ListActivity {
private List<String> listfile = new ArrayList<String>();
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
File fileroot = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
File[] files = fileroot.listFiles();
FileFilter fileFilter = new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
};
files = fileroot.listFiles(fileFilter);
System.out.println(files.length);
if (files.length == 0) {
//
} else {
for (int i = 0; i < files.length; i++) {
listfile.add(files[i].getName());
}
ArrayAdapter <String> dis = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listfile);
setListAdapter(dis);
}
}
}
There's no simple way to do this in Android. It's a mistake to assume that there will be only one directory videos/ on a particular device. Even if there is, you can't assume that video files will be stored there, and nowhere else.
If you really only want to scan one directory, then a simple approach is to prompt the user for the location when your app first starts, and store the selected location for future use. Many android apps that handle media do, in fact, take this approach -- although they might allow the user to select multiple locations.
If you want to list video files, rather than the contents of a specific directory, then the way to do this is to query the Android media store. This store is (or should be) updated whenever files are transferred to the device. Each file is tagged with various attributes according to various inspection methods built into Android. Modern Android versions are pretty good at recognizing video files, although that wasn't always the case.
To use the media store, you'd do a query on the ContentResolver for a specific Context, testing for a flag that indicates that the content is video. Then you'd iterate the results, extracting the various pieces of information you need.
To be honest, I've not used the Android media store for video, although I have for audio. I think the basic principles will be the same. I have some sample code for audio queries here, if that's any help:
https://github.com/kevinboone/androidmusicserver/blob/master/src/net/kevinboone/androidmusicplayer/AudioDatabase.java
I am using Android Studio for a simple communication app and this definitly might be a stupid question but I couldn't find the answer to it yet.
I am simply starting a new intent on a button click. However, the very first time the user does this, he is asked what kind of app he wants to use. Therefore, there are at least two applications with the same intent filter, namely "ACTION_VIEW"
My Problem:
After the initial click the button always "reuses" his initial choice so the user does not have a decision anymore which app he wants to use for this intent.
Unfortunately, this is excactly what I want. The user should get the chance to select the app of his favor each time he clicks on the button.
The relevant part of code is as simple as follows:
String uri = String.format(Locale.ENGLISH, "geo:%f,%f", latitude, longitude);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(intent);
Intent.FLAG_UPDATE_CURRENT could probably help you.
https://developer.android.com/reference/android/app/PendingIntent.html
You can use an App Chooser to show the dialog for the user to choose which app to use each time:
[I]f the action to be performed could be handled by multiple apps and the user might prefer a different app each time—such as a "share" action, for which users might have several apps through which they might share an item—you should explicitly show a chooser dialog.... The chooser dialog forces the user to select which app to use for the action every time (the user cannot select a default app for the action).
Intent intent = new Intent(Intent.ACTION_SEND);
...
// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, title);
// Verify the intent will resolve to at least one activity
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
I've written an Android app that is a simpler version of the stock camera. It only records video.
Despite this being a custom app, I'd like to have the videos recorded by this be easily visible from the Photos and Gallery apps.
I was under the impression that this is what the "MediaScannerConnection" class is for. I've found common advice that shows how to use this in either a "sendBroadcast" mode, or a more manual "scanFile" approach. I've implemented both of these options and found that they appear to have no effect. When I stop the recorder, a valid video is stored (I can play it from a file browser afterwards), but neither Photos or Gallery is made aware of the new video.
I've been storing the videos in files like "/storage/emulated/0/DCIM/Camera/20151223_150115.mp4". That directory also contains videos taken by the stock camera app. The base path was obtained from "Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)". I originally tried replacing "Camera" with a directory name based on the name of my app, but as that wasn't working (Photos/Gallery not seeing it, despite it being stored properly), I decided to try storing them where the stock videos are stored. That isn't working either.
My test device is a Galaxy Note 3, running Android 5.0.
My first attempt at using MediaScannerConnection was with this:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + outputFilePath)));
One of the values of "outputFilePath" is exactly the path shown above.
As this didn't appear to do anything, I then later tried this:
new SingleMediaScanner(getApplicationContext(), new File(outputFilePath));
Where "SingleMediaScanner" is this:
public static 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();
}
#Override
public void onMediaScannerConnected() {
mMs.scanFile(mFile.getAbsolutePath(), "image/*");
}
#Override
public void onScanCompleted(String path, Uri uri) {
mMs.disconnect();
}
}
I tried running the last implementation in the debugger, and I saw it get to "onScanCompleted", but neither of the aforementioned apps see the new video.
Update:
With the current implementation, the "onScanCompleted" callback method gets called with "path" and "uri" parameters, which have the following values:
path: /storage/emulated/0/DCIM/Camera/20151223_194434.mp4
uri.toString(): content://media/external/file/106639
Uri.fromFile(new File(Path)): file:///storage/emulated/0/DCIM/Camera/20151223_194434.mp4
Ok, so this code works great to call the stock android camera app:
public void clickEvent(View e) {
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
startActivity(intent);
}
However, I need to capture that picture file after it's taken, rename it and maybe place it somewhere else.
Is there a way to do that?
You can set the EXTRA_OUTPUT extra on the intent to tell whatever app responds to the intent where to put the file.
I am working on a small File manager to get the hang of things on Android and I have cut/copy/paste operation. It seems to work fine, but I run into issues with pasting things. On my app it is displayed fine, but for it to be recognized by other apps, it requires that I reboot the phone. For example, if I cut/paste an image from the download folder to the DCIM folder, the gallery app does not display that image unless I reboot the whole phone. I am using an algorithm that takes data byte by byte. Its extremely inefficient, but I am not totally sure how to implement a faster algorithm.
Thanks.
No actually you wont need to reboot our phone. When you copy an image and paste it to other location your newly copied media file is not added to the android's ContentResolver. So you should scan your data using the class MediaScannerConnection
Eg:
When you paste a file you have the file right ?
Modify as your wish, this works fine
private void scanImage(File targetLocation) {
// Scans the media to load images
String mimetype = Utility.getMimeType(targetLocation.getAbsolutePath());
if(mimetype.contains("image"))
{
MediaScannerConnection.scanFile(context, new String[] { targetLocation.getPath() }, new String[] { "image/jpeg" }, this);
}
}
UPDATE
Callback should be like
either you can implement OnScanCompletedListener in your class and add unimplemented method, So you can pass this as callback OR you can use
OnScanCompletedListener listener = new OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
// you will get the callback here
}
};
and pass listener as callback