BletchleyP BletchleyP - 1 month ago 10
Android Question

In an Android fragment no sound is played after an onClick event

I am new to all this so I started to write this app to learn.

The app starts with 6 clickable images that lead to a secondary activity composed of a series of "swipeable" screens each with an image that when clicked upon will generate a sound. Here is the code of the secondary and fragment code necessary to generated the screens :

SecondaryPage.java

import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

public class SecondaryPage extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Set the content of the activity to use the activity_main.xml layout file
setContentView(R.layout.secondary);

// Find the view pager that will allow the user to swipe between fragments
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);

// Create an adapter that knows which fragment should be shown on each page
SimpleFragmentPagerAdapter adapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager());

// Set the adapter onto the view pager
viewPager.setAdapter(adapter);
}
}


SimpleFragmentAdapter.java

AnimalsFragement.java (
Croc()
and
Camel()
are identical, except for the name)

import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;

import static com.example.testfrags.R.layout.animals;

public class AnimalsFragment extends Fragment {
private ImageView imageView;
private MediaPlayer mp;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = null;
//Inflating View to access it's resources

v = inflater.inflate(animals, container, false);
Log.i("AnimalsFragment", "mp before playing: " + mp);

//creating clickable image

imageView = (ImageView) v.findViewById(R.id.jungle_animals);

// Sound played once clicked
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Start playback.
mp = MediaPlayer.create(getActivity(), R.raw.lioncub2);
Log.i("AnimalsFragment", "mp: " + mp);
mp.start();
mp.stop();//Stops playback - added precaution

// release media resources
releaseMediaPlayer();
Log.i("AnimalsFragment", "mp after release: " + mp);
// Little msg confirm end of sound
Toast.makeText(v.getContext(), "Questo era il Leoncino", Toast.LENGTH_SHORT).show();

}
});

return v;
} // end of onCreatView

/**
* Clean up the media player by releasing its resources.
*/
private void releaseMediaPlayer() {
// If the media player is not null, then it may be currently playing a sound.
if (mp != null) {
// Regardless of the current state of the media player, release its resources
// because we no longer need it.
mp.reset();
mp.release();

// Set the media player back to null.

} // end of if
} // end of releaseMediaPlayer

@Override
public void onStop() {
super.onStop(); // Always call the superclass method first
releaseMediaPlayer();

}


}


These are the xml files :
secondary.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</LinearLayout>


animals.xml (croc.xml and camel.xml are the same)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">

<ImageView
android:id="@+id/jungle_animals"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/lion"/>

</LinearLayout>


The app compiles and runs but when I click on any image in any fragment no sound is played. I have tried both on my device and emulated but nothing.

What have I done wrong ?

I have tried changing
getActivity()
with
v.getContext()
in the line :

`mp = MediaPlayer.create(getActivity(), R.raw.lioncub2);`


but nothing changes.
All sound files are mp3. I have also written a version of secondaryPage.java without the fragments with the three images just to see if the mp3 files would work and they all played normally.
I also inserted the
Toast
message just to check if the
onClick()
method was working, which it does.
When I debug and step into the
mp = MediaPlayer.create(getActivity(), R.raw.lioncub2);
line and continue, the sound is played.

Here is the output of the Log.i statements :

10-15 10:50:36.962 2459-2459/com.example.testfrags I/Croc: mp before playing: null
10-15 10:50:37.682 2459-2459/com.example.testfrags I/Choreographer: Skipped 36 frames! The application may be doing too much work on its main thread.
10-15 10:50:39.472 2459-2459/com.example.testfrags I/AnimalsFragment: mp: android.media.MediaPlayer@b0fd1480
10-15 10:50:39.482 2459-2459/com.example.testfrags I/AnimalsFragment: mp after release: null


Thanks in advance for any help!

Answer

For what it's worth.... the fault in the code was in calling the releaseMediaPlayer method before the sound actually finished. So I should have have checked this by adding some form of control, which I did using MediaPlayer.OnCompletionListener.

I did this by defining a variable and invoking MediaPalyer.OnCompletionListner :

 private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        // Now that the sound file has finished playing, release the media player resources.
        releaseMediaPlayer();
    }

and then by calling the following just after the sound starts playing :

mp.setOnCompletionListener(mCompletionListener);

Thanks to all !