title: Android Music Player inside a fragment
body: <p>I am implementing a music player app. I am able to fetch the songs from the sd card. But stuck in something from hours i.e. I am unable to make the songs play inside the fragment.</p>
  
  <p>Here is the <strong>MainActivity</strong> class which is having 3 tab fragments.</p>
  
  <pre><code>public class MainActivity extends AppCompatActivity {
  
  private final String[] TITLES = {"Now playing", "Library", "Groups"};
  private static boolean isInForeground = false;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
  
      //if (savedInstanceState == null) {}
  
      Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
      setSupportActionBar(toolbar);
  
      // Initialize the ViewPager and set an adapter
      ViewPager pager = (ViewPager) findViewById(R.id.pager);
      pager.setAdapter(new PagerAdapter(getSupportFragmentManager(), getBaseContext()));
  
      // Bind the tabs to the ViewPager
      PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
      tabs.setShouldExpand(true);
      tabs.setViewPager(pager);
  
      //Whenever the user changes tab, we want the title to change too
      tabs.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
  
          @Override
          public void onPageScrollStateChanged(int arg0) {
              // TODO Auto-generated method stub
  
          }
  
          @Override
          public void onPageScrolled(int arg0, float arg1, int arg2) {
              // TODO Auto-generated method stub
  
          }
  
          @Override
          public void onPageSelected(int position) {
              setTitle(TITLES[position]);
          }
  
      });
  
      //We want to have the library as default view
      pager.setCurrentItem(1);
      setTitle(TITLES[1]);
  
  }
  
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.menu_main, menu);
      return true;
  }
  
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
      // Handle action bar item clicks here. The action bar will
      // automatically handle clicks on the Home/Up button, so long
      // as you specify a parent activity in AndroidManifest.xml.
      int id = item.getItemId();
  
      //noinspection SimplifiableIfStatement
      if (id == R.id.action_settings) {
          return true;
      }
  
      return super.onOptionsItemSelected(item);
  }
  
  /**
   * A placeholder fragment containing a simple view.
   */
  public static class MainFragment extends Fragment {
  
      public MainFragment() {
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
                               Bundle savedInstanceState) {
          View view = inflater.inflate(R.layout.fragment_song_library, container, false);
  
          return view;
      }
  }
  
  public class PagerAdapter extends FragmentPagerAdapter
          implements PagerSlidingTabStrip.CustomTabProvider {
  
      private ArrayList&lt;Integer&gt; tab_icon = new ArrayList&lt;Integer&gt;();
  
      Context myContext;
  
      public PagerAdapter(FragmentManager fm, Context context) {
          super(fm);
  
          myContext = context;
          tab_icon.add(context.getResources().getIdentifier("ic_play_arrow_white_36dp", "drawable", context.getPackageName()));
          tab_icon.add(context.getResources().getIdentifier("ic_list_white_36dp", "drawable", context.getPackageName()));
          tab_icon.add(context.getResources().getIdentifier("ic_group_white_36dp", "drawable", context.getPackageName()));
      }
  
  
  
      @Override
      public CharSequence getPageTitle(int position) {
          return TITLES[position];
      }
  
      @Override
      public int getCount() {
          return TITLES.length;
      }
  
      @Override
      public Fragment getItem(int position) {
  
          if(position == 0){
              return SongNowPlayingFragment.newInstance();
          } else if (position == 1){
              return SongLibraryFragment.newInstance();
          } else if(position == 2){
              return GroupFragment.newInstance();
          }
  
          System.err.println("Invalid tab fragment!");
          return new Fragment();
      }
  
      @Override
      public View getCustomTabView(ViewGroup viewGroup, int position) {
  
          LinearLayout imageView = (LinearLayout) LayoutInflater.from(myContext)
                  .inflate(R.layout.tab_layout, null, false);
  
          ImageView tabImage = (ImageView) imageView.findViewById(R.id.tabImage);
          tabImage.setImageResource(tab_icon.get(position));
  
          return imageView;
      }
  }
  
  @Override
  protected void onResume()
  {
      super.onResume();
      isInForeground = true;
  }
  
  
  @Override
  protected void onPause()
  {
      super.onPause();
      isInForeground  = false;
  }
  
  static boolean isInForeground(){
      return isInForeground;
  }
  }
  </code></pre>
  
  <p>This is the <strong>SongLibraryFragment</strong> in which I have added the songs from the user device. Now I want to play those songs.</p>
  
  <pre><code>public class SongLibraryFragment extends Fragment implements MediaPlayerControl {
  
  private ArrayList&lt;SongItem&gt; songList;
  private ListView songView;
  
  private MusicService musicSrv;
  private Intent playIntent;
  private boolean musicBound=false;
  
  private MusicController controller;
  private boolean paused=false, playbackPaused=false;
  private MainActivity mainActivity = null;
  
  public static SongLibraryFragment newInstance() {
      SongLibraryFragment f = new SongLibraryFragment();
      Bundle b = new Bundle();
      f.setArguments(b);
      return f;
  }
  
  
  
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
      View rootView = inflater.inflate(R.layout.fragment_song_library, container, false);
  
      return rootView;
  }
  
  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
      super.onActivityCreated(savedInstanceState);
      mainActivity = (MainActivity) SongLibraryFragment.this.getActivity();
      songView = (ListView) getView().findViewById(R.id.library_song_list);
      songList = new ArrayList&lt;SongItem&gt;();
      getSongList();
      SongAdapter songAdt = new SongAdapter(getActivity(), songList);
      songView.setAdapter(songAdt);
  
      Collections.sort(songList, new Comparator&lt;SongItem&gt;() {
          public int compare(SongItem a, SongItem b) {
              return a.getTitle().compareTo(b.getTitle());
          }
      });
  
      setController();
  }
      //connect to the service
      private ServiceConnection musicConnection = new ServiceConnection(){
  
          @Override
          public void onServiceConnected(ComponentName name, IBinder service) {
              MusicBinder binder = (MusicBinder)service;
              //get service
              musicSrv = binder.getService();
              //pass list
              musicSrv.setList(songList);
              musicBound = true;
          }
  
          @Override
          public void onServiceDisconnected(ComponentName name) {
              musicBound = false;
          }
      };
  
  
  
  @Override
  public void onStart() {
      super.onStart();
      if(playIntent==null){
          playIntent = new Intent(getActivity(), MusicService.class);
          this.getActivity().bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
          this.getActivity().startService(playIntent);
      }
  }
  
  public void songPicked(View view){
      musicSrv.setSong(Integer.parseInt(view.getTag().toString()));
      musicSrv.playSong();
      if(playbackPaused){
          setController();
          playbackPaused=false;
      }
      controller.show(0);
  }
  
  public void getSongList() {
      //retrieve song info
      ContentResolver musicResolver = getActivity().getContentResolver();
      Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
      Cursor musicCursor = musicResolver.query(musicUri, null, null, null, null);
  
      if(musicCursor!=null &amp;&amp; musicCursor.moveToFirst()){
          //get columns
          int titleColumn = musicCursor.getColumnIndex
                  (android.provider.MediaStore.Audio.Media.TITLE);
          int idColumn = musicCursor.getColumnIndex
                  (android.provider.MediaStore.Audio.Media._ID);
          int artistColumn = musicCursor.getColumnIndex
                  (android.provider.MediaStore.Audio.Media.ARTIST);
          //add songs to list
          do {
              long thisId = musicCursor.getLong(idColumn);
              String thisTitle = musicCursor.getString(titleColumn);
              String thisArtist = musicCursor.getString(artistColumn);
              songList.add(new SongItem(thisId, thisTitle, thisArtist));
          }
          while (musicCursor.moveToNext());
      }
  
  }
  
  @Override
  public boolean canPause() {
      return true;
  }
  
  @Override
  public boolean canSeekBackward() {
      return true;
  }
  
  @Override
  public boolean canSeekForward() {
      return true;
  }
  
  @Override
  public int getAudioSessionId() {
      return 0;
  }
  
  @Override
  public int getBufferPercentage() {
      return 0;
  }
  
  @Override
  public int getCurrentPosition() {
      if(musicSrv!=null &amp;&amp; musicBound &amp;&amp; musicSrv.isPng())
          return musicSrv.getPosn();
      else return 0;
  
  }
  
  @Override
  public int getDuration() {
      if(musicSrv!=null &amp;&amp; musicBound &amp;&amp; musicSrv.isPng())
          return musicSrv.getDur();
      else return 0;
  
  }
  
  
  @Override
  public boolean isPlaying() {
      if(musicSrv!=null &amp;&amp; musicBound)
          return musicSrv.isPng();
      return false;
  
  }
  
  @Override
  public void pause() {
      playbackPaused=true;
      musicSrv.pausePlayer();
  }
  
  
  @Override
  public void seekTo(int pos) {
      musicSrv.seek(pos);
  }
  
  @Override
  public void start() {
      musicSrv.go();
  
  }
  
  private void setController(){
      //set the controller up
      controller = new MusicController(getActivity());
      controller.setPrevNextListeners(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              playNext();
          }
      }, new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              playPrev();
          }
      });
      controller.setMediaPlayer(this);
      controller.setAnchorView(getActivity().findViewById(R.id.library_song_list));
      controller.setEnabled(true);
  
  }
  //play next
  private void playNext(){
      musicSrv.playNext();
      if(playbackPaused){
          setController();
          playbackPaused=false;
      }
      controller.show(0);
  }
  
  //play previous
  private void playPrev(){
      musicSrv.playPrev();
      if(playbackPaused){
          setController();
          playbackPaused=false;
      }
      controller.show(0);
  }
  
  @Override
  public void onPause(){
      super.onPause();
      paused=true;
  }
  
  @Override
  public void onResume(){
      super.onResume();
      if(paused){
          setController();
          paused=false;
      }
  }
  
  @Override
  public void onStop() {
      controller.hide();
      super.onStop();
  }
  
  
  @Override
  public void onDestroy() {
      this.getActivity().stopService(playIntent);
      musicSrv=null;
      super.onDestroy();
  }
  </code></pre>
  
  <p><strong>SongAdapter</strong> class</p>
  
  <pre><code>public class SongAdapter extends BaseAdapter {
  
  private ArrayList&lt;SongItem&gt; songs;
  private LayoutInflater songInf;
  
  
  public SongAdapter(Context c, ArrayList&lt;SongItem&gt; theSongs){
      songs=theSongs;
      songInf=LayoutInflater.from(c);
  }
  
  @Override
  public int getCount() {
      // TODO Auto-generated method stub
      return songs.size();
  }
  
  @Override
  public Object getItem(int arg0) {
      // TODO Auto-generated method stub
      return null;
  }
  
  @Override
  public long getItemId(int arg0) {
      // TODO Auto-generated method stub
      return 0;
  }
  
  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
      //map to song layout
      LinearLayout songLay = (LinearLayout)songInf.inflate
              (R.layout.song, parent, false);
      //get title and artist views
      TextView songView = (TextView)songLay.findViewById(R.id.song_title);
      TextView artistView = (TextView)songLay.findViewById(R.id.song_artist);
      //ImageView imageView = (ImageView)songLay.findViewById(R.id.song_image);
      //get song using position
      SongItem currSong = songs.get(position);
      //get title and artist strings
      songView.setText(currSong.getTitle());
      artistView.setText(currSong.getArtist());
      //imageView.setImage(currSong.getImage());
      //set position as tag
      songLay.setTag(position);
      return songLay;
  }
  </code></pre>
  
  <p><strong>Song.xml file</strong> </p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:orientation="vertical"
      android:padding="5dp"
      android:onClick="songPicked"&gt;
  
      &lt;TextView
          android:id="@+id/song_title"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:layout_gravity="center_vertical"
          style="@style/Base.TextAppearance.AppCompat.Title"
          android:textColor="@color/primary_text_default_material_light"/&gt;
      &lt;TextView
          android:id="@+id/song_artist"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:layout_gravity="center_vertical"
          style="@style/Base.TextAppearance.AppCompat.Subhead"
          android:textColor="@color/secondary_text_default_material_light"/&gt;
  
  &lt;/LinearLayout&gt;
  </code></pre>
  
  <p><strong>Error</strong></p>
  
  <blockquote>
    <p>java.lang.IllegalStateException: Could not find a method
    songPicked(View) in the activity class
    co.adrianblan.noraoke.MainActivity for onClick handler on view class
    android.widget.LinearLayout</p>
  </blockquote>
  
  <p>So the main problem is with the <strong>songPicked</strong> method inside <strong>SongFragmentLibrary</strong>. I have added the onClick: songPicked in the song.xml file but it is searching for the songPicked method inside the <strong>MainActivity</strong>. I am not getting what is the problem.</p>
  
  <p>Please can anyone help me with this?</p>