MediaBrowserService where to get the media files in onLoadChildren - java

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.

Related

getting error in saving data in Room Database like Images , emails and name of users

hope you all would be fine...
i am developing a simple app for testing and learning purposes that stores the name, email and image of the user into the ROOM DATABASE.
i am a newbie to Room database i watched many tutorials on youtube to learn that how to implement ROOM in android apps. the main problem is that in Tutorials all of them are using AsyncTask to store info into ROOM. but when i followed those tutorials then i came to know that the AsyncTask has been deprecated, which is the main cause that i am not getting MyDatabase.getInstance() method inside my MainActivity.
So tell me what to do right now.. what should i implement other than AsyncTask.
Also i want to learn that how to store Images into RoomDatabase
This is my Code where i am getting the error...
class InsertAsyncTask extends AsyncTask<User, Void, Void> {
#Override
protected Void doInBackground(User... users) {
//this is the line where i am getting the error. getInstance method becomes red.
//UserDatabase.getInstance(getApplicationContext()).dao().insertUser(users[0]);
return null;
}
}
You can use RxJAVA to perform database operation with Room.
Ex.
Observable.fromCallable(()->UserDatabase.getInstance(getApplicationContext()).dao().insertUser(users[0]))
.subscribeOn(Schedulers.io())
.subscribe(...);
For Storing image in database, you can check below link
How insert image in room persistence library?
From my point of view better solution is for storing image path rather than storing image in database.

Play Framework - How to build a web page with multiple MySQL queries

I've created my first Play Framework Website with Java using the official documentation. It has a single page where I display a list of items that can be filtered or modified.
I have a Controller class with a method:
public CompletionStage<Result> feedpostslist(String domain, String date, String state, int page, int resnum, String search) {
return feedRepository.getArticleList(domain, date, state, page, resnum, search).thenApplyAsync(articles -> {
FeedArticle[] list = new FeedArticle[articles.size()];
articles.toArray(list);
return ok(views.html.feedpostslist.render(list));
}, ec.current());
}
This method does a query to the DB (through feedRepository) and then display the result using the view feedpostslist.
Everything is fine but now I need to get other data from the DB to be used in the same web page (so multiple queries). How do I do this in Play Framework? I don't understand what is the best way to do that.
Should I do multiple DB request inside the method showed before (through feedRepository) and then pass all these informations to my view? I don't want to do a mess or even something too heavy to handle.
If the second query doesn't depend on the first one you can run them in parallel using combineAsync. This is a good example on how to do that:
https://github.com/playframework/play-samples/blob/2.8.x/play-java-ebean-example/app/controllers/HomeController.java#L85
If the second query depends on results on the first then there's nothing you can do but to wait for the first one to complete and run the second one.

JavaFX's Media Player not retrieving metadata

I'm creating a video player using JavaFX media player library. I need to retrieve the metadata and display in a window. I'm having problems retrieving the data though.
I've read 2 threads about this already and I understand that this is done asynchronously so I need a listener in order to get the metadata.
First Thread:Retrieving metadata from media files in JavaFX
Second Thread: https://stackoverflow.com/a/43144197/12787326
This code has been implemented like so below.
public void initialize(URL location, ResourceBundle resources) {
//Initialising path of the media file, replace this with your file path
String path = "Video.mp4";
//Instantiating Media class
Media media = new Media(new File(path).toURI().toString());
//Listener
media.getMetadata().addListener((MapChangeListener<String,Object>) change-> {
System.out.println(change);
});
//Instantiating MediaPlayer class
mediaPlayer = new MediaPlayer(media);
mv.setMediaPlayer(mediaPlayer);
mediaPlayer.setOnReady(() -> {
...
mediaPlayer.play();
});
}
I have tried a variety of different changes to the listener such as placing it in different areas of the code and trying to get the data from the mediaPlayer, which accesses the media itself. None of these seems to have fixed the problem.
I've tried print statements in the code trying to print off the contents of media.getMetadata but all I get is an empty list back.
I've tried creating a listener for media.getTracks() and that works as expected with updating each time the player switches its status. So that makes me wonder what is going wrong with media.getMetadata()
This is what the metadata of the video currently looks like so I assume I should be getting this infomarmation
I think the listener isn't seeing anything change, that's why print(change) is never reached. However, even if that is true, shouldn't me doing a system.out.print(media.getMetaData()) in the setOnAction code give me the data? Because when I try that all I get is an empty list.
Does anyone know how to fix this or tell me what I'm doing wrong?

Most efficient way to load a lot of images from URL Android

I'm making this netflix style app in which images are loaded into different categories. Let's say Dog videos (has 15 images), Cat videos (15 images), etc... All the images are loaded from a URL, it kind of takes a while for all to load. I was wondering if there was anything I could do to speed up the process? Or maybe show an empty container then fill it as the images load (that would be cool).
This is what I have done:
I have multiple async calls in one Activity, (1 async call per category)
JSONTask1 dogTask = new JSONTask1();
JSONTask2 catTask = new JSONTask2();
JSONTask3 pigTask = new JSONTask3();
JSONTask4 horseTask = new JSONTask4();
dogTask.execute("");
catTask.execute("");
pigTask.execute("");
horseTask.execute("");
I have all of those in a row in my actual code. Thanks.
I would use the "proxy pattern". Basically, you need to create a class that contains the minimal informations required for the display. In which, you have a preview image.
When ever you load everything you start by showing the preview content, ie : a loading gif for everypicture with the title of the movie or whatever. and basically the proxy would have a "loadImage" method that would make an ajax call or async call and the photos would load one by one. Plus, to make the loading easier, make sure the photos are not oversized.
You can see Picasso answers , in picasso i suggest you this way :
Picasso.with(getApplicationContext()).load("your url").placeholder(R.drawable.your_place_holder).error(R.drawable.showing_when_error_occured)
.into(imageView, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
}
});
Also another suggestion from me : convert your thumb images to base64 format in backend, then firstly retrieve your thumbs and show them. Then start an async task and change images when successfull.
Like whatsapp. In whatsapp you have thumb images they have so low resolution and super fast. When you click image if you have internet connection they load actual thumb images, and click again they load larger image.
Picasso website :http://square.github.io/picasso/
Load them asynchronously with Picasso, you can even show a placeholder image until the real one is loaded

Android massive database creation

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;
}

Categories