Search code examples
androidandroid-mediaplayerandroid-recyclerview

RecyclerView + MediaPlayer + Toggle Button + String Uri


Background: I'm working on an Fitness app. Everything is working good till now but problem came when I was working with audio files MediaPlayer in android.

I have checked resources and found ListView but couldn't find anything on RecyclerView + MediaPlayer.

I want to know how to make it work while working with RecyclerView + Toggle Button + String Uri (Offline - Raw folder)

Problem: Right now it is playing the first .mp3 file on every click event (for Eng: R.raw.sample_one_eng is played and for Hindi: R.raw.sample_one_hindi is played). I think it is not taking int position into consideration.

Later, I would like to put it online (may be google cloud) since audio files (.mp3) are making my app quite heavy. Any ideas on that would be appreciated too (fast buffering, etc.).

ListExercises.java

public class ListExercises extends AppCompatActivity {

    List<ExerciseAudio> exerciseList = new ArrayList<>();
    RecyclerView.LayoutManager layoutManager;
    RecyclerView recyclerView;
    RecyclerViewAdapterAud adapter;
    PlayClickHandler clickHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_exercises);

        initData();

        recyclerView = (RecyclerView) findViewById(R.id.list_ex);
        adapter = new RecyclerViewAdapterAud(exerciseList, getBaseContext());
        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(adapter);
    }

    private void initData() {

        exerciseList.add(new ExerciseAudio(R.drawable.sample_one, "Sample Exercise One", "Sans One",
                R.raw.sample_one_eng,
                R.raw.sample_one_hindi));

        exerciseList.add(new ExerciseAudio(R.drawable.sample_two, "Sample Exercise Two", "Sans Two",
                R.raw.sample_two_eng,
                R.raw.sample_two_hindi));

        exerciseList.add(new ExerciseAudio(R.drawable.sample_three, "Sample Exercise Three", "Sans Three",
                R.raw.sample_three_eng,
                R.raw.sample_three_hindi));

        exerciseList.add(new ExerciseAudio(R.drawable.sample_four, "Sample Exercise Four", "Sans Four",
                R.raw.sample_four_eng,
                R.raw.sample_four_hindi));
    }
}

ViewExercise.java

public class ViewExercise extends AppCompatActivity {

    int image_id, eng_aud_url, hindi_aud_url;
    String name, sans_name;

    ArrayList<String> arrayList = new ArrayList<>();

    TextView timer, title, sansName;
    ImageView detail_image;
    ToggleButton tg_btn_speaker_eng, tg_btn_speaker_hindi;

    MediaPlayer mp;

    int position;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.view_exercise);

        Field[] field = R.raw.class.getFields();
        for (int i = 0; i < field.length; i++){
            arrayList.add(field[i].getName());
        }

        title = (TextView) findViewById(R.id.title);
        sansName = (TextView) findViewById(R.id.sans_name);
        detail_image = (ImageView) findViewById(R.id.detail_image);

        tg_btn_speaker_eng = (ToggleButton) findViewById(R.id.tg_btn_speaker_eng);
        tg_btn_speaker_hindi = (ToggleButton) findViewById(R.id.tg_btn_speaker_hindi);

        tg_btn_speaker_eng.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //toggleEnglish(tg_btn_speaker_eng.isChecked());
                int positionEng = 0;
                playSongEng(positionEng);
            }
        });

        tg_btn_speaker_hindi.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //toggleHindi(tg_btn_speaker_hindi.isChecked());
                int positionHindi = 0;
                playSongHindi(positionHindi);
            }
        });

        if (getIntent() != null) {
            image_id = getIntent().getIntExtra("image_id", -1);
            name = getIntent().getStringExtra("name");
            sans_name = getIntent().getStringExtra("sanskrit_name");

            detail_image.setImageResource(image_id);
            title.setText(name);
            sansName.setText(sans_name);
        }
    }


    public void playSongEng(int i) {
        //mp.reset();
        int resId = getResources().getIdentifier(arrayList.get(i), "raw", getPackageName());
        mp = MediaPlayer.create(getApplicationContext(), resId);
        mp.start();
    }

    public void playSongHindi(int i) {
        //mp.reset();
        int resId = getResources().getIdentifier(arrayList.get(i), "raw", getPackageName());
        mp = MediaPlayer.create(getApplicationContext(), resId);
        mp.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mp != null)
            mp.release();
    }
}

This is how it looks!

Edit (to avoid confusion): Just noticed, that image name would have been List Exercises instead of View Exercise which corresponds to ListExercises.java

List Exercise - RecyclerView

And this one corresponds to ViewExercise.java

View Exercise

Thanks!


Solution

  • You can also set the click listener inside onBindViewHolder without using any interface by setting the click listener on parent view of your item_exercise_aud layout like this:

    holder.parentView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, ViewExercise.class);
                intent.putExtra("image_id", exerciseList.get(position).getImage_id());
                intent.putExtra("name", exerciseList.get(position).getName());
                intent.putExtra("sanskrit_name", exerciseList.get(position).getSanskrit_name());
                intent.putExtra("eng_aud_url", exerciseList.get(position).getEng_aud_url());
                intent.putExtra("hindi_aud_url", exerciseList.get(position).getHindi_aud_url());
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(intent);
            }
        });
    

    Or you can refer here

    Edit - To play the audio according to the recyclerview list's position, we have to send the raw file name of that particular exercise to the media player.

    Add two new variables to ExerciseAudio model class:

    private String file_name_eng;
    private String file_name_hindi;
    

    Now modify the initData method as below:

    private void initData() {
    
        exerciseList.add(new ExerciseAudio(R.drawable.sample_one, "Sample Exercise One", "Sans One",
                R.raw.sample_one_eng, R.raw.sample_one_hindi,
                "sample_one_eng", "sample_one_hindi"));
    
        exerciseList.add(new ExerciseAudio(R.drawable.sample_two, "Sample Exercise Two", "Sans Two",
                R.raw.sample_two_eng, R.raw.sample_two_hindi,
                "sample_two_eng", "sample_one_hindi"));
    
        exerciseList.add(new ExerciseAudio(R.drawable.sample_three, "Sample Exercise Three", "Sans Three",
                R.raw.sample_three_eng, R.raw.sample_three_hindi,
                "sample_three_eng", "sample_three_hindi"));
    
        exerciseList.add(new ExerciseAudio(R.drawable.sample_four, "Sample Exercise Four", "Sans Four",
                R.raw.sample_four_eng, R.raw.sample_four_hindi,
                "sample_four_eng", "sample_four_hindi"));
    }
    

    Now Modify the ViewExercise intent as:

    intent.putExtra("file_name_eng", exerciseList.get(position).getFile_name_eng());
    intent.putExtra("file_name_hindi", exerciseList.get(position).getFile_name_hindi());
    

    Get the string extras in ViewExercise activity and send it to the mediaplayer:

    file_name_eng = getIntent().getStringExtra("file_name_eng");
    file_name_hindi = getIntent().getStringExtra("file_name_hindi");
    
    For english:
        int resId = getResources().getIdentifier(file_name_eng, "raw", getPackageName());
    
    For hindi:
        int resId = getResources().getIdentifier(file_name_hindi, "raw", getPackageName());