Android Studio Online Radio app(java) from API [closed] - java

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have to do a project for univeristy in android studio a radio online who take elements from API(java language). For first i've done the adapterview(with a list) and take elements from api, My question is how can i implement media player in my code to play the stream from api(i have the code for media player but works only for one link and i dont know how to implement to this project.
I have put my code there:https://textuploader.com/tsu8j
https://i.stack.imgur.com/Cfwph.png

Please see onPlayClick which is called on the play button, right now I always change the URL to the radio station which is clicked on just to show you how can you change the URL for media to be played in mediaplayer.
YOu can yourself think of logic to show the `pause' button and updating them according to the song is played.
Right now this snippet is to show you how you can changes the ongoing radio to different when you clicked upon that.
getAdapterPosition(): I am taking leverage of this to know which row's Play button is clicked so that accordingly I can switch to that radio station.
mediaPlayer.prepareAsync(): so that I don't block the main thread.
setOnPreparedListener because we want to start our mediaPlayer when it is done prepared and as we have done it asynchronously we have to listen for the callback to know when to start our media player.
setOnErrorListener to know if there is some error while playing some media, this was helpful as in your case out of 10 stations only 5 or 6 are working and others are throwing error and this callback actually helped me to know why exactly media was not played.
stopPlaying There is mediaPlayer.stop(); and mediaPlayer.reset(); this are to make sure that before new media data is set using mediaPlayer.setDataSource already playing media is stopped and the data is reset.
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
// creating a variable for array list and context.
private ArrayList<RadioStation> radioStationArrayList;
private MediaPlayer mediaPlayer;
// creating a constructor for our variables.
public Adapter(ArrayList<RadioStation> radioStationArrayList, Context context) {
this.radioStationArrayList = radioStationArrayList;
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
#NonNull
#Override
public Adapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
// below line is to inflate our layout.
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.course_rv_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull Adapter.ViewHolder holder, int position) {
// setting data to our views of recycler view.
RadioStation modal = radioStationArrayList.get(position);
holder.name.setText(modal.getName());
Picasso.get().load(modal.getFavicon()).into(holder.favicon);
}
#Override
public int getItemCount() {
// returning the size of array list.
return radioStationArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
// creating variables for our views.
private TextView name;
private ImageView favicon;
private Button play;
public ViewHolder(#NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.idName);
favicon = itemView.findViewById(R.id.idImg);
play = itemView.findViewById(R.id.play);
play.setOnClickListener(view -> onPlayClick());
}
public void onPlayClick() {
stopPlaying();
startPlaying();
}
private void startPlaying() {
try {
mediaPlayer.setDataSource(radioStationArrayList.get(getAdapterPosition()).getUrl_resolved());
mediaPlayer.setOnPreparedListener(mp -> {
mediaPlayer.start();
Log.v("DINKAR", "Started");
});
mediaPlayer.setOnErrorListener((mp, what, extra) -> {
Log.e("DINKAR", "Error");
return false;
});
mediaPlayer.prepareAsync();
} catch (IOException e) {
Log.e("DINKAR", "failed");
}
}
private void stopPlaying() {
mediaPlayer.stop();
mediaPlayer.reset();
}
}
}
Note: many of the radio stations are having issues MediaPlayer were not able to play those.
I used https://textuploader.com/tsu8j to get your adapter class code and using your screenshot of the app created layout XML file on my own so that I can run the app to test it out before giving you any snippet

Related

Preload MediaPlayer in RecyclerView Adapter?

I have an RecylcerView with multiple imges in my app.
If the images are getting loaded in the onBindViewholder it should also prepare the MediaPlayer.
When the user clicks the button it should start the MediaPlayer.
Normaly I would just create the MediaPlayer when the user clicks the button but in my case I'm playing the sound from an URL so it takes some time for the sound to play when the user has bad internet.
So I try to create and prepare the MediaPlayer as soon as the RecyclerView Item gets created and start it when the user clicks the button.
Is this the right way to do it? Because now I have the problem that I have multiple MediaPlayers at once and I don't know how I can stop and clear all MediaPlayers when the user clicks a "stop" button.
Here is the onBindViewHolder method from my RecyclerView Adapter:
#Override
public void onBindViewHolder(#NonNull final SoundViewHolder holder, int position) {
SoundItems currentItem = mSoundItems.get(position);
final String imageUrl = currentItem.getImageResource();
final String mp3Path = currentItem.getMp3Path();
Glide.with(mContext)
.load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.DATA)
.into(holder.itemImageView);
final MediaPlayer mediaPlayer;
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(mp3Path);
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
holder.itemImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mediaPlayer.start();
}
});
What is the best way to preload the sounds so that the sound gets played instantly when the user clicks button and how to stop all MediaPlayers at once?
P.S
The sounds are between 3 and 30 seconds long.
You can use my code :
Instead of using Exoplayer you can use MediaPlayer if you want..
But with this code files will be prefetched too.
https://github.com/NehaKushwah993/InstagramVideoFeedClone
Let me know if it works.

mediaPlayer.release() crashes my app java

I have a project where I added a MediaPlayer in a custom Array Adapter and I make it take the Resource ID of the audio file from the Array List the problem is that I want to release the media player after the audio completes but every time I try to add release in OnCompletion and try to press a view while the media player plays a sound the app crashes .. I searched online and found a code but it gives me an error and I can't find the actual reason for such a crash.
that's the code for the on Click Listener and the Media player:
final MediaPlayer mediaPlayer = MediaPlayer.create(getContext(), currentWord.getVoiceResourceID());
// Wait for user's input by his click on the list's item to play the sound.
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// Storing the return value of getVoiceResourceID() into mVoice.
// I think this line can be ignored so we call the method inside the creation of the Media Player.
// Creating our media player and put our track on it.
mediaPlayer.selectTrack(currentWord.getVoiceResourceID());
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mediaPlayer.release();
}
});
}
};
I hope I could fix that problem.

Recyclerview : how to mix some post with image and no image? [duplicate]

This question already has answers here:
How to create RecyclerView with multiple view types
(23 answers)
Closed 3 years ago.
I want to display in same recycle-view which is some post have image and some post does not have images.
I can retrieve all the post with image and non-image,
but i want to change the size of the post when the user only post text(no image).
I expect the output like twitter feed..some post with image and without image have their own size.
Simple way to achieve this scenario is, All you have to do is create a view with both image and text, in recycler adapter check if image data is available make visibility of image visible else Image visibility gone.
Second Approach for this to make multiple view for RecyclerView.
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Log.d(TAG, "onBindViewHolder called");
ContentItem item = mContentItems.get(position);
if(item.getName()!=null){
holder.textName.setVisibility(View.Visible);
holder.textName.setText(item.getName());
}else{
holder.textName.setVisibility(View.GONE);
}
if(item.getPreviewImageDefault()!=null){
holder.imageIcon.setVisibility(View.Visible)
Picasso.with(mContext).load("file://" + item.getPreviewImageDefault()).into(holder.imageIcon);
}else{
holder.imageIcon.setVisibility(View.GONE)
}
}
Another possible solution is create 2 xml layouts and use ViewType in your RecyclerView.
look this How to create RecyclerView with multiple view type?
If you want to hide the image when it is ic_launcher you could do that (suppposing that data.getImage() returns the id of the drawable as integer):
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
if(mItems!=null){
AdapterData data = mItems.get(i);
viewHolder.text.setText(data.getText());
viewHolder.image.setImageResource(data.getImage());
if(TextUtils.isEmpty(data.getText())){
viewHolder.text.setVisibility(View.GONE);
}else{
viewHolder.text.setVisibility(View.VISIBLE);
}
if(data.getImage()==R.drawable.ic_launcher){
viewHolder.image.setVisibility(View.GONE);
}else{
viewHolder.image.setVisibility(View.VISIBLE);
}
}
}
One possible solution, like some people have already said, is to hide/show the ImageView.
You could do that in the ViewHolder that you use for your RecyclerView.
class OptionalImageViewHolder extends RecyclerView.ViewHolder {
private ImageView image;
private TextView text;
// any other views you have
public OptionalImageViewHolder(View itemView) {
super(itemView);
image = itemView.findViewById(R.id.yourImageViewIdHere);
text = itemView.findViewById(R.id.yourTextViewIdHere);
// same for any other views you have
}
public void bindView(Tweet tweet) {
// This is where the magic happens
// Note: I make the assumption that you have a class called "Tweet"
// that has a field for "text", a field for "image" (that can be
// null if there's no image), and any other necessary fields.
text.setText(tweet.getTweetText());
if (tweet.hasImage() /* function that returns whether or not there is an image */) {
image.setVisibility(View.VISIBLE);
image.setImageBitmap(tweet.getImage()); // or however you are setting the image
} else {
// else just make the image invisible
image.setVisibility(View.GONE);
}
}
}
Hopefully this gives you an idea.
RecyclerView supports different viewTypes (layouts) which is the proper way in such scenario. E.g.,
class MyAdapter : RecyclerView.Adapter<MyViewHolder>() {
override fun getViewTypes(position:Int) =
if (mydata[position].hasImage) return R.layout.mylayout_with_image
else R.layout.mylayout_no_image;
override fun onCreateViewHolder(viewType:Int, parent:ViewGroup) : MyViewHolder =
// here viewType = layout id
MyViewHolder(layoutInflater.inflate(viewType, parent))
override fun onBindViewHolder(viewHolder:MyViewHolder, position:Int) {
// guaranteed viewHolder.itemView is the view you want for that position
}
}

Data is not coming to my app from firebase

I'm trying to load image and name from Firebase database to my app in RecyclerView but when I run it it is not showing the image and name with no error, here is my code.
//Load menu
recycler_menu=(RecyclerView)findViewById(R.id.recycler_menu);
recycler_menu.setHasFixedSize(true);
layoutManager= new LinearLayoutManager(this);
recycler_menu.setLayoutManager(layoutManager);
loadMenu();
}
private void loadMenu(){
FirebaseRecyclerOptions<Category> options = new FirebaseRecyclerOptions.Builder<Category>().setQuery(category, Category.class).build();
FirebaseRecyclerAdapter<Category, MenuViewHolder> adapter= new FirebaseRecyclerAdapter<Category, MenuViewHolder>(options){
#Override
public MenuViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.menu_item, parent, false);
MenuViewHolder viewHolder = new MenuViewHolder(view);
return viewHolder;
}
#Override
protected void onBindViewHolder(MenuViewHolder holder, int position, Category model) {
holder.txtMenuName.setText(model.getName());
Picasso.with(getBaseContext()).load(model.getImage()).into(holder.imageView);
}
};
recycler_menu.setAdapter(adapter);
}
My code is running fine but image and name is not showing, blank activity is displaying. Please help.
Just add adapter.startListening() in your OnStart to start the data listener and adapter.stopListening() in your onStop to stop it by this way :
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
This is one of the main problems you usually face when you are using Firebase as your database. I could not see where you retrieve your data but the problem is, most probably, Firebase event listeners working asynchronous. In another way, your method returns before you retrieve the data. In my project, I solved this issue by retrieving data on onCreateView or onCreate and then use those values inside other methods. If it is not the case I just simply do the work inside the event listener, if I have to (It will make your code look extremely complicated and unreadable). It would be more helpful if you do more research about Firebase and its asynchronous working style.
If you somehow find a better way to solve this, please comment below so I can use it too. I am still seeking a better way.

ViewPager and AsyncTask for loading the Items

I've a ViewPager with an PageAdapter loading ImageViews.
The images displayed come from the internet and I use an AsyncTask for loading the Bitmap and then (if the Page hasn't been destroyed) assign it to the ImageView.
#Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView img = new ImageView(container.getContext());
new LoadImageTask(img,Data.getImageUrL(position)).execute();
container.addView(img );
return img;
}
So the ImageView has two states: loading or loaded. I need to track if the user waits for the image. So I implement this at the LoadImageTask onPostExecute:
if (loadListener != null) {
loadListener.onImageLoaded(position);
}
And in the listener:
public void onImageLoaded(int position) {
if (position == mViewPager.getCurrentItem()) {
// Save record ..
}
}
Since I only need to count the images displayed at the "Current Item of the ViewPager" this method is not enought because if the user moves to the item 5 for example, the ViewPager loads in cache the item 6. If the user waits enought time for this load (beeing the item 5 the current) the callback to onImageLoaded is lost (because the item 6 is not the currentItem at the moment, and then when the user moves to the item 6 I've no way of knowing if the image is loaded or not.
I was thinking in adding something like [[PSEUDOCODE]]:
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
if (mViewPager.isLoaded(posistion)){
// Save record ...
}
}
But I dont know how to retrieve if the corresponding view loaded the image or not at this moment. How can I do it?

Categories