2

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.

Here is the MainActivity class which is having 3 tab fragments.

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<Integer> tab_icon = new ArrayList<Integer>();

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

This is the SongLibraryFragment in which I have added the songs from the user device. Now I want to play those songs.

public class SongLibraryFragment extends Fragment implements MediaPlayerControl {

private ArrayList<SongItem> 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<SongItem>();
    getSongList();
    SongAdapter songAdt = new SongAdapter(getActivity(), songList);
    songView.setAdapter(songAdt);

    Collections.sort(songList, new Comparator<SongItem>() {
        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 && 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 && musicBound && musicSrv.isPng())
        return musicSrv.getPosn();
    else return 0;

}

@Override
public int getDuration() {
    if(musicSrv!=null && musicBound && musicSrv.isPng())
        return musicSrv.getDur();
    else return 0;

}


@Override
public boolean isPlaying() {
    if(musicSrv!=null && 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();
}

SongAdapter class

public class SongAdapter extends BaseAdapter {

private ArrayList<SongItem> songs;
private LayoutInflater songInf;


public SongAdapter(Context c, ArrayList<SongItem> 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;
}

Song.xml file

<?xml version="1.0" encoding="utf-8"?>
<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">

    <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"/>
    <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"/>

</LinearLayout>

Error

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

So the main problem is with the songPicked method inside SongFragmentLibrary. I have added the onClick: songPicked in the song.xml file but it is searching for the songPicked method inside the MainActivity. I am not getting what is the problem.

Please can anyone help me with this?

Community
  • 1
  • 1
User0706
  • 1,067
  • 1
  • 18
  • 34
  • try to use this songpicked method in adapter OR instead of using songpicked method, make linear layout clickable and use the onclick listner for it as- view.findViewById(R.id.your_layout_id).setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View arg0) { //do what ever you want – sud Nov 16 '15 at 10:03
  • I have tried this. It didn't work. @sud – User0706 Nov 16 '15 at 10:37

1 Answers1

1

You are trying to set onclick listener from your fragment xml android:onClick="songPicked", you can't set onclick listener for a view which is part of fragment, in your getView() setOnClickListener:

LinearLayout songLay = (LinearLayout)songInf.inflate
            (R.layout.song, parent, false);
songLay.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
        //Handle click event
        }
}) 

OR You can simply set OnItemClickListener on your listview

list.setOnItemClickListener(this);// implement OnItemClickListener in your fragment class
Jaiprakash Soni
  • 4,100
  • 5
  • 36
  • 67
  • adding the onClickListener inside getView() didn't work. After adding that the song list disappears. – User0706 Nov 16 '15 at 10:36
  • song list layout is empty this the problem after adding onClick in getView() – User0706 Nov 16 '15 at 10:42
  • first use the solution which will make works onclick listener, and then if any other problems appear like empty songlist try to solve this you can easily find reason behind empty songlist by line by line debugging – sud Nov 16 '15 at 10:51
  • i want to play the song when onClick works. If no song list is visible then how can I make onClick work> @sud – User0706 Nov 16 '15 at 10:56
  • Thanks @JaiprakashSoni. Adding OnItemClickListener worked for me – User0706 Nov 16 '15 at 11:09