I'm relatively new to Android and can't get this working.
So far I have an app which has one large circular red button. When this is pressed by the user it executes an operation (at the moment it displays 'Hello World').
Instead, I would like it to delete all photos on the Android device. (Yes, it is a strange thing to do, I know)
My questions:
Is this possible? I've had trouble getting it to work and can't find apps which have done this before.
The only Android device I have is a Nexus 7 tablet. I would like it to work on both Android phones and tablets. Is this also possible, as I understand that their directory structures vary?
Yes you can delete Images but I do not suspect you can do them all at once.
I recommend you query the Mediastore to get the _ID of all Images and then loop through the list and delete them. Here is some sample code but i'm sure it can be better optimized. This code is filesystem agnostic so it should work anywhere.
Code to get list of all items on Mediastore.Images
List<Long> mediaStoreIds = new ArrayList<Long>();
Cursor c = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{BaseColumns._ID}, null, null, null);
if (c != null) {
final int id = c.getColumnIndexOrThrow(BaseColumns._ID);
c.moveToFirst();
while (!c.isAfterLast()) {
Long mediaStoreId = c.getLong(id);
mediaStoreIds.add(mediaStoreId);
c.moveToNext();
}
c.close();
}
Then to delete, well you could do that right in the original loop or loop through the arraylist, but here is how to delete:
context.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, BaseColumns._ID + "=?", new String[]{Long.toString(mediaStoreIds.get(i))});
Related
I am trying (without luck) to update entries for MediaStore for both audio tracks and images. I am using something like this:
ContentValues values = new ContentValues();
values.put(MediaStore.Audio.Media.TITLE, title);
values.put(MediaStore.Audio.Media.YEAR, year);
resolver.update(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values, MediaStore.Audio.Media._ID + "= ?", new String[] { String.valueOf(id) })
The above snippet works on API16->API28 without problems.
Though, on API29 it does not work. No errors are displayed on logs or messages. I am trying the above code on the API29 emulator. I am not sure if this issue is related to using an emulator or not.
I would really appreciate any information that points me in the right direction.
https://stackoverflow.com/a/60152702/786656 worked for me.
You need to call update once with the flag IS_PENDING set to 1. Then you call update again with the modified values you want and the flag IS_PENDING set to 0.
I'm trying to make a MediaBrowserService. In the past when I want to display all the music files actually on the device, I would use a ContentResolver and load a cursor from the MediaStore.
I can't figure out where I am supposed to do this in a MediaBrowserService.
There is the method: onLoadChildren
The examples I find look like this:
#Override
public void onLoadChildren(
#NonNull final String parentMediaId,
#NonNull final Result<List<MediaBrowserCompat.MediaItem>> result) {
result.sendResult(MusicLibrary.getMediaItems());
}
My question is, do I use my ContentResolver cursor within this method to return a list of MediaItems? Or is there some other internal method to use to go through the device and get all the music files?
Only examples I see online are streaming services which do an HTTP call to get a song list, or they just hard code fake songs to display for testing. I'm trying to allow the service to browse music files that are on the device itself.
I also tried to do the exactly same thing in my app, hitting the same wall as you. Finally I figured out how to do it using the Android's new Paging library. You do have to use a cursor with a ContentResolver at the service side in order to fetch the media items on the device, but in order to not iterate all the cursor's records just to return the children in the onLoadChildren() method, I use the paging library to return only the chunks the user is interested in this moment at the client/UI side. You can read about it in a post I wrote, where I also demonstrate the concept with code samples.
So guys, this is a big one
I'm currently working on an App which involves a big database creation.
Basicalls what it does is scanning the entire device for any kind of media file and adds it to the database (filtered by certain file extensions).
The way it currently does that is scanning through the device's folders with a recursive function, and every time it finds a file that is actually a file and not a directory AND matches the file extensions I picked it adds the file's path to a previously created ArrayList containing only strings.
This is implemented in an AsyncTask so it's done in the background.
As soon as that task finishes it passes the ArrayList on to another AsyncTask that is responsible for adding those files to the database. Out of simplicity resons I only took the file's path, its name and the title that is stored in its tags for every entry (simple sqlite stuff) and displayed the titles in a ListView in another activity over cursor adapters and so on (which isnt really an issue in my case).
Right now it workes pretty well, doesn't crash or return anything bad (I'm testing on a OnePlus One right now).
BUT I have a really big music library on my phone (around 5400 songs) which is nearly filling my entire storage. And out of some unknown reason to me, the scanning task i mentioned (with the ArrayList) stops at around 3000 files and passes the ArrayList on to the second task, which is obviously not what I'm aming at to have.
My guess is that there might be a big performance issue and using an ArrayList is not the best way to approach this. It might work with a number of files that is under 3000 but higher than that is also necessary...
So what would you guys suggest? Does my approach lack something or do I have to try something completely different?
You don't need scan your folders (and, probably, creating database of media files too), you can just use MediaStore class
The Media provider contains meta data for all available media on both internal and external storage devices.
For example, this piece of code will return all available audio playlists
private List<Playlist> getPlayListsList(){
ContentResolver resolver = getContentResolver();
Uri uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
String[] columns = { _ID, NAME };
Cursor playLists = resolver.query(uri, columns, null, null, null);
List<Playlist> result = new ArrayList<>();
if (playLists == null) {
return result;
}
Cursor cursor;
for (boolean hasItem = playLists.moveToFirst(); hasItem; hasItem = playLists.moveToNext()) {
long id = playLists.getLong(playLists.getColumnIndex(_ID));
String name = playLists.getString(playLists.getColumnIndex(NAME));
cursor = resolver.query(MediaStore.Audio.Playlists.Members.getContentUri("external", id),
new String[]{MediaStore.Audio.Playlists.Members.TITLE, MediaStore.Audio.Playlists.Members.ARTIST,
MediaStore.Audio.Media.DATA, MediaStore.Audio.Playlists.Members.PLAY_ORDER}, null, null, null
);
int songsCount = cursor.getCount();
result.add( new Playlist(
id,
name,
songsCount));
cursor.close();
}
playLists.close();
return result;
}
I am programming Android using LibGDX.
I have big file and want to sraightforward access specific line on the file without going through all the lines and iterating them until i reach desired line.
I was
suggested
to use SQLite for this.
So I followed example and did this:
DatabaseCursor cursor;
cursor = mydb1.rawQuery("SELECT * FROM comments");
while (cursor.next()) {
cursor.getString(1);
}
Well it works , but that is iteration (looping)! how to do it directly?
thanx
as advised did this and it worked:
cursor = mydb1.rawQuery("SELECT * FROM comments WHERE comment='test recorddd' ");
I'm working on a MP3 application in which I'd like to index the files on my SDCard. What is the best way to do it?
My Idea. Search for files when the application is started for the first time and register a broadcast receiver for the SDCard state change intents and search for the files whenever the intent is broadcasted.
But in this case the ANR would show up if my broadcast receiver doesn't return within 10 seconds.
Looking for better and failsafe ideas. Thanks.
Agree with Chris, MediaScanner finds music for you, populating the MediaStore database. Here's some code to look up a music entry:
final Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
final String[] cursor_cols = {
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.TITLE,
};
final String where = MediaStore.Audio.Media.IS_MUSIC + "=1";
final Cursor cursor = getContentResolver().query(uri, cursor_cols, where, null, null);
cursor.moveToNext();
final String artist = cursor.getString(_cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
final String album = cursor.getString(_cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
final String track = cursor.getString(_cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
doSomethingInteresting(artist, album, track);
The "data" field contains a handle you can use with MediaPlayer.
To avoid the ANR you need to do the search outside the UI thread. As SD cards can be big, you probably want to do it in a service rather than in your foreground activity so that the user can use their device for other things while the search is ongoing.
But android already finds and indexes supported media files, so you should see if you can leverage the built-in MediaScanner stuff.