I am creating a music player app for android. I have a fragment in a ViewPager that displays a list of all songs on the device. I have implemented an onClick listener on the list item to start a service called PlayerService that will play the clicked music. However, I am getting a
NullPointerException
at the line
playerSrv.setList(songArray);
in the following code.
I can pass the songArray ArrayList to the listview adapter without any problem but when I try to pass it to the service, I get the error. Is there any reason why the songArray could be null? The service starts without any problem without the line that gives error.
The setList() method in the Service class is
public void setList(ArrayList<Song> theSongs) {
songs=theSongs; //where songs is a private variable of type ArrayList<Song>
}
public class AllSongsFragment extends Fragment {
private ArrayList<Song> songArray;
private ListView songListView;
private PlayerService playerSrv;
private Intent playIntent;
private boolean serviceBound=false;
//connect to the player service
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
ServiceBinder binder = (ServiceBinder)service;
//get service
playerSrv = binder.getService();
serviceBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
serviceBound = false;
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
} // onCreate()
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
songListView = (ListView)getView().findViewById(R.id.all_songs_list);
songArray = new ArrayList<Song>();
getSongList();
// Sort the songs
Collections.sort(songArray, new Comparator<Song>() {
public int compare(Song a, Song b) {
// For case-insensitive sorting
String a1 = a.getTitle().toString().toLowerCase();
String b1 = b.getTitle().toString().toLowerCase();
return a1.compareTo(b1);
}
});
AllSongsAdapter songAdt = new AllSongsAdapter(getActivity(), songArray);
songListView.setAdapter(songAdt);
songListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(playIntent==null) {
playIntent = new Intent(getActivity(), PlayerService.class);
getActivity().bindService(playIntent, serviceConnection, Context.BIND_AUTO_CREATE);
getActivity().startService(playIntent);
}
//pass list
playerSrv.setList(songArray); //ERROR AT THIS LINE
playerSrv.setSong(position);
playerSrv.playSong();
}
});
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.all_songs_fragment_layout, container, false);
return rootView;
} //onCreateView()
/*#Override
public void onPause() {
getActivity().stopService(playIntent);
//playerSrv=null;
super.onPause();
}*/
public void getSongList() {
//retrieve song info
ContentResolver musicResolver = getActivity().getContentResolver();
Uri musicUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = new String[] {MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST};
Cursor musicCursor = musicResolver.query(musicUri, projection, null, null, null);
// Iterate over the List
if(musicCursor!=null && musicCursor.moveToFirst()) {
//get columns
int idColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media._ID);
int titleColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
int artistColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
//add songs to list
do {
String thisId = musicCursor.getString(idColumn);
String thisTitle = musicCursor.getString(titleColumn);
String thisArtist = musicCursor.getString(artistColumn);
if(thisArtist == null || thisArtist.equals(MediaStore.UNKNOWN_STRING)) {
thisArtist = "Unknown Artist";
}
songArray.add(new Song(thisId, thisTitle, thisArtist));
} while (musicCursor.moveToNext());
} // if
} //getSongList()
} //AllSongsFragment
The service class is
public class PlayerService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {
private MediaPlayer player;
private ArrayList<Song> songs;
private int songPosition;
private final IBinder serviceBind = new ServiceBinder();
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return serviceBind;
}
#Override
public boolean onUnbind(Intent intent) {
player.stop();
player.release();
return false;
}
#Override
public void onCreate() {
super.onCreate();
//initialize position
songPosition=0;
//create player
player = new MediaPlayer();
initMusicPlayer();
}
public void initMusicPlayer() {
//set player properties
player.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnPreparedListener(this);
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
}
public void setList(ArrayList<Song> theSongs) {
// Used to pass music list from music browser to the Player Service
songs=theSongs;
}
public class ServiceBinder extends Binder {
PlayerService getService() {
return PlayerService.this;
}
}
public void playSong() {
//play a song
player.reset();
//get song
Song currentSong = songs.get(songPosition);
//get id
long songId = Long.parseLong(currentSong.getId());
//set uri
Uri trackUri = ContentUris.withAppendedId(android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, songId);
try {
player.setDataSource(getApplicationContext(), trackUri);
} catch(Exception e) {
Log.e("PLAYER SERVICE", "Error setting data source", e);
}
player.prepareAsync();
}
#Override
public void onPrepared(MediaPlayer mp) { //start playback
mp.start();
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.reset();
return false;
}
#Override
public void onCompletion(MediaPlayer mp) {
}
public void setSong(int songIndex) {
songPosition=songIndex;
}
}
Related
I'm making an app that play mp3 file from phone storage using service. I have an activity that has a small view to interact with the songs and a fragment that contains a full media function to interact with the songs will be added in if I tap on the small view told. The problem is I cannot get data from service to pass in the fragment to display data or interact between fragment and service.
Here's my main activity 1st photo
Here's my fragment after touch the field on 1st photo fragment
My code in MainActivity
public class MainActivity extends AppCompatActivity {
private List<AudioModel> mainList;
private ListView mainListView;
private MusicAdapter adapter;
private int REQUEST_CODE_PERMISSION = 2703;
private MusicPlayerService musicPlayerService;
public static Intent intentService;
private boolean boundService = false;
public static TextView txtMainTen, txtMainTacGia;
private ImageButton btnMainPlay, btnMainNext;
private int vitri = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainList = new ArrayList<>();
if(intentService == null){
intentService = new Intent(this, MusicPlayerService.class);
bindService(intentService, serviceConnection, Context.BIND_AUTO_CREATE);
startService(intentService);
}
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_PERMISSION);
mainListView = findViewById(R.id.listSong);
adapter = new MusicAdapter(MainActivity.this, R.layout.item_song, mainList);
mainListView.setAdapter(adapter);
mainListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
MainAudioCreate(position);
vitri = position;
}
});
txtMainTen = findViewById(R.id.txtPlaying);
txtMainTacGia = findViewById(R.id.txtAuthor);
btnMainPlay = findViewById(R.id.btnPlayBottom);
btnMainNext = findViewById(R.id.btnNextBottom);
btnMainPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (musicPlayerService.mediaPlayer.isPlaying()){
musicPlayerService.pause();
btnMainPlay.setImageResource(R.drawable.button_play);
}
else{
musicPlayerService.resume();
btnMainPlay.setImageResource(R.drawable.button_pause);
}
}
});
btnMainNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
vitri++;
if (vitri > mainList.size() - 1){
vitri = 0;
}
MainAudioCreate(vitri);
}
});
}
private void MainAudioCreate(int position){
musicPlayerService.setVitri(position);
musicPlayerService.play();
btnMainPlay.setImageResource(R.drawable.button_pause);
txtMainTen.setText(musicPlayerService.serviceList.get(position).getName());
txtMainTacGia.setText(musicPlayerService.serviceList.get(position).getArtist());
}
public void AddFragment(View view){
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment fragment = null;
int container = 0;
String tag = "";
switch (view.getId()) {
case R.id.layoutClose:
fragment = new FragmentClose();
container = R.id.frameContent;
tag = "fragClose";
break;
case R.id.layoutList:
fragment = new FragmentPlaylist();
container = R.id.frameContent;
tag = "fragList";
break;
case R.id.bottomPlayerTouchable:
fragment = new FragmentPlayer();
container = R.id.mainFrame;
tag = "fragPlayer";
break;
}
fragmentTransaction.add(container, fragment, tag);
fragmentTransaction.addToBackStack("fragment");
fragmentTransaction.commit();
}
public void GetSongFromStorage(Context context, List<AudioModel> list){
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
String[] projection = {MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.ALBUM, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.TITLE,};
Cursor c = context.getContentResolver().query(uri, projection, null, null, MediaStore.Audio.Media.TITLE + " ASC");
if (c != null){
while (c.moveToNext()) {
AudioModel audioModel = new AudioModel();
String path = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
mmr.setDataSource(path);
String album = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
String artist = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
String name = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
byte[] image = mmr.getEmbeddedPicture();
String displayName = path.substring(path.lastIndexOf("/") + 1);
audioModel.setName(name);
audioModel.setAlbum(album);
audioModel.setArtist(artist);
audioModel.setPath(path);
audioModel.setDisplayname(displayName);
if (image != null) audioModel.setImgPath(image);
list.add(audioModel);
}
adapter.notifyDataSetChanged();
c.close();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE_PERMISSION){
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
mainList.clear();
GetSongFromStorage(MainActivity.this, mainList);
}
else{
Toast.makeText(this, "Chưa cho phép", Toast.LENGTH_SHORT).show();
}
}
}
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicPlayerService.MusicBinder binder = (MusicPlayerService.MusicBinder) service;
musicPlayerService = binder.getService();
musicPlayerService.setList(mainList);
boundService = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
boundService = false;
}
};
}
My Service code
public class MusicPlayerService extends Service {
MediaPlayer mediaPlayer;
List<AudioModel> serviceList;
int vitri;
private final IBinder musicBind = new MusicBinder();
public class MusicBinder extends Binder {
MusicPlayerService getService(){
return MusicPlayerService.this;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return musicBind;
}
#Override
public boolean onUnbind(Intent intent) {
mediaPlayer.stop();
mediaPlayer.release();
return false;
}
public void initMusicPlayer(){
mediaPlayer.setWakeMode(getApplicationContext(),
PowerManager.PARTIAL_WAKE_LOCK);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
#Override
public void onCreate() {
super.onCreate();
vitri = 0;
mediaPlayer = new MediaPlayer();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
public void setList(List<AudioModel> mp3List){
serviceList = mp3List;
}
public void play(){
mediaPlayer.reset();
createSong();
}
public void pause(){
mediaPlayer.pause();
}
public void resume(){
mediaPlayer.start();
}
public void createSong(){
mediaPlayer = MediaPlayer.create(this, Uri.parse(serviceList.get(vitri).getPath()));
mediaPlayer.start();
}
public void setVitri(int pos){
vitri = pos;
}
}
My Fragment that will be added in code
public class FragmentPlayer extends Fragment {
ImageButton btnBackPlayer;
TextView txtTitlePlayer, txtTimeCurrent, txtTimeTotal;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_player, container, false);
btnBackPlayer = view.findViewById(R.id.btnBackPlayer);
txtTitlePlayer = view.findViewById(R.id.txtTitlePlayer);
txtTimeCurrent = view.findViewById(R.id.txt_timeCurrent);
txtTimeTotal = view.findViewById(R.id.txt_timeTotal);
view.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
btnBackPlayer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getFragmentManager().popBackStack();
}
});
return view;
}
}
You can use a broadcast in your service and set broadcast listener in your fragment.
My songadapter:
public class songAdapter extends RecyclerView.Adapter<songAdapter.ViewHolder> {
ArrayList<songInfo> songs;
Context context;
OnitemClickListener onitemClickListener;
public songAdapter(ArrayList<songInfo> songs, Context context) {
this.songs = songs;
this.context = context;
}
public interface OnitemClickListener{
void onItemclick(ViewHolder holder, View v, songInfo obj, int position);
}
public void setOnitemClickListener(OnitemClickListener onitemClickListener)
{
this.onitemClickListener=onitemClickListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mView= LayoutInflater.from(context).inflate(R.layout.raw_songs,parent,false);
return new ViewHolder(mView);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final songInfo song=songs.get(position);
holder.songName.setText(song.songName);
holder.artistName.setText(song.artistName);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(onitemClickListener!=null)
{
onitemClickListener.onItemclick(holder,view,song,position);
}
}
});
}
#Override
public int getItemCount() {
return songs.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView songName,artistName;
public ViewHolder(View itemView) {
super(itemView);
songName=(TextView)itemView.findViewById(R.id.songname);
artistName=(TextView)itemView.findViewById(R.id.artistName);
}
}
}
this is my mainactivity
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
private ArrayList<songInfo> songs=new ArrayList<songInfo>();
songAdapter songAdapter;
MediaPlayer mediaPlayer;
SeekBar seekBar;
Cursor cursor;
private Handler myHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView=(RecyclerView)findViewById(R.id.recyclerView);
seekBar = (SeekBar) findViewById(R.id.seekBar);
songAdapter=new songAdapter(songs, this);
recyclerView.setAdapter(songAdapter);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
linearLayoutManager.getOrientation());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.addItemDecoration(dividerItemDecoration);
songAdapter.setOnitemClickListener(new songAdapter.OnitemClickListener() {
#Override
public void onItemclick(songAdapter.ViewHolder holder, View v, songInfo obj, int position) {
mediaPlayer.start();
System.gc();
int songPath = cursor.getColumnIndex(MediaStore.Audio.Media.DATA);
cursor.moveToPosition(position);
final String filename = cursor.getString(songPath);
if(mediaPlayer.isPlaying()){
mediaPlayer.reset();
mediaPlayer.start();
}else {
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(filename);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
seekBar.setProgress(0);
seekBar.setMax(mediaPlayer.getDuration());
Log.d("Prog", "run: " + mediaPlayer.getDuration());
}
});
// b.setText("Stop");
}catch (Exception e){}
}
};
myHandler.postDelayed(runnable,100);
}
}
});
checkUserPermission();
Thread t = new runThread();
t.start();
}
public class runThread extends Thread {
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("Runwa", "run: " + 1);
if (mediaPlayer != null) {
seekBar.post(new Runnable() {
#Override
public void run() {
seekBar.setProgress(mediaPlayer.getCurrentPosition());
}
});
Log.d("Runwa", "run: " + mediaPlayer.getCurrentPosition());
}
}
}
}
private void checkUserPermission(){
if(Build.VERSION.SDK_INT>=23){
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED){
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},123);
return;
}
}
loadSongs();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode){
case 123:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
loadSongs();
}else{
Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show();
checkUserPermission();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private void loadSongs(){
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC+"!=0";
cursor = getContentResolver().query(uri,null,selection,null,null);
if(cursor != null){
if(cursor.moveToFirst()){
do{
String name = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
int songPath = cursor.getColumnIndex(MediaStore.Audio.Media.DATA);
songInfo s = new songInfo(name,artist,songPath);
songs.add(s);
}while (cursor.moveToNext());
}
// cursor.close();
songAdapter = new songAdapter(songs, MainActivity.this);
}
}
public void onDestroy() {
super.onDestroy();
cursor.close();
}
}
I fetched song from sd card and can see them on screen,but when i try to play those songs my app crashes with the following error.Attempt to invoke virtual method 'void android.media.MediaPlayer.start()' on a null object reference.
I dont know what to do please help.
This is my logcat
Process: com.example.murarilal.musicmania, PID: 26119
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.media.MediaPlayer.start()' on a null object reference at com.example.murarilal.musicmania.MainActivity$1.onItemclick(MainActivity.java:54)
at
com.example.murarilal.musicmania.songAdapter$1.onClick(songAdapter.java:54)**
The problem is that you are trying to access an null instance of MediaPlayer,
Attempt to invoke virtual method 'void
android.media.MediaPlayer.start()' on a null object reference.
so before execute mediaPlayer.start(); inside the method onClick() you need to initialize your MediaPlayer instance:
MediaPlayer mediaPlayer = new MediaPlayer();
for example:
private MediaPlayer mediaPlayer; //* Create variable type MediaPlayer .
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
...
mediaPlayer = new MediaPlayer(); //* Initialize MediaPlayer!
...
...
songAdapter.setOnitemClickListener(new songAdapter.OnitemClickListener() {
#Override
public void onItemclick(songAdapter.ViewHolder holder, View v, songInfo obj, int position) {
mediaPlayer.start(); //*Now you can use the MediaPlayer instance.
...
...
I have been searching the internet the whole day but couldn't find the solution. I have a music player service class that plays songs in the background as a service. The problem is I can't get the fragment to bind to this service. No error is being shown in logcat nor the app crashes. When I click on one of the songs nothing happens. This is my code below:
ServiceClass:
public class MediaPlayerService extends Service implements MediaPlayer.OnCompletionListener,
MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnSeekCompleteListener,
MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener,
AudioManager.OnAudioFocusChangeListener {
private final IBinder iBinder = new LocalBinder();
private static MediaPlayer mediaPlayer = new MediaPlayer();
private String mediaFile;
private int resumePosition;
private AudioManager audioManager;
//Handle incoming phone calls
private boolean ongoingCall = false;
private PhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
private ArrayList<SongInfoModel> songsServiceList = new ArrayList<>();
private int songPosn;
private int currentIndex ;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return iBinder;
}
private void initMediaPlayer() {
//Set up MediaPlayer event listeners
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnInfoListener(this);
//Reset so that the MediaPlayer is not pointing to another data source
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
#Override
public void onCreate() {
super.onCreate();
songPosn=0;
initMediaPlayer();
}
public void setList(ArrayList<SongInfoModel> theSongs){
songsServiceList=theSongs;
}
public void setSong(int songIndex){
songPosn=songIndex;
}
public void playSong(){
//play a song
mediaPlayer.reset();
//get song
SongInfoModel playSong = songsServiceList.get(songPosn);
//get id
long currSong = playSong.getSongID();
//set uri
Uri trackUri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
currSong);
try{
mediaPlayer.setDataSource(getApplicationContext(), trackUri);
}
catch(Exception e){
Log.e("MUSIC SERVICE", "Error setting data source", e);
}
mediaPlayer.prepareAsync();
MainActivity.handleSeekbar(mediaPlayer);
}
#Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.reset();
songPosn++;
if(songPosn>=songsServiceList.size()) songPosn=0;
playSong();
}
#Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
return false;
}
#Override
public boolean onInfo(MediaPlayer mediaPlayer, int i, int i1) {
return false;
}
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.reset();
} else {
mediaPlayer.start();
MainActivity.Handler(mediaPlayer);
}
}
public class LocalBinder extends Binder {
public MediaPlayerService getService() {
return MediaPlayerService.this;
}
}
FragmentClass:
public class Songs extends Fragment {
public static final String TAG = "Songs";
RecyclerView recyclerView;
private ArrayList<SongInfoModel> SongList = new ArrayList<SongInfoModel>();
SongAdapter songAdapter;
ScaleInAnimationAdapter alphaAdapter;
private MediaPlayerService player2;
boolean serviceBound2 = false;
private Intent playIntent2;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.songs_activity, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(linearLayoutManager);
songAdapter = new SongAdapter(getContext(), SongList, new SongAdapter.RecyclerItemClickListener() {
#Override
public void onClickListener(SongInfoModel song, int position) {
Toast.makeText(getContext(), song.getSongName(), Toast.LENGTH_SHORT).show();
MainActivity.setsongText(song);
MainActivity.ButtonPlay();
MainActivity.PauseImage();
if(serviceBound2 == true) {
player2.setSong(position);
player2.playSong();
}
}
#Override
public void onLongClickListener(SongInfoModel song, int position) {
Toast.makeText(getContext(), "You long clicked me, thank you!", Toast.LENGTH_SHORT).show();
}
});
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0";
Cursor cursor = getActivity().getContentResolver().query(uri, null, selection, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID));
String name = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
Long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
Long albumId = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
Uri albumArtUri = ContentUris.withAppendedId(sArtworkUri, albumId);
SongInfoModel s = new SongInfoModel(id, name, artist, null, null, null, duration, data,albumArtUri, albumId);
SongList.add(s);
} while (cursor.moveToNext());
}
cursor.close();
Collections.sort(SongList, new Comparator<SongInfoModel>() {
#Override
public int compare(SongInfoModel lhs, SongInfoModel rhs) {
return lhs.getSongName().compareTo(rhs.getSongName());
}
});
}
alphaAdapter = new ScaleInAnimationAdapter(songAdapter);
alphaAdapter.setDuration(1000);
alphaAdapter.setInterpolator(new OvershootInterpolator());
alphaAdapter.setFirstOnly(false);
recyclerView.setAdapter(alphaAdapter);
songAdapter.notifyDataSetChanged();
return view;
}
//Binding this Client to the AudioPlayer Service
private ServiceConnection serviceConnection2 = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
MediaPlayerService.LocalBinder binder = (MediaPlayerService.LocalBinder) service;
player2 = binder.getService();
player2.setList(SongList);
serviceBound2 = true;
Toast.makeText(getContext(), "Service Bound", Toast.LENGTH_SHORT).show();
}
#Override
public void onServiceDisconnected(ComponentName name) {
serviceBound2 = false;
}
};
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(playIntent2==null && serviceBound2==true){
playIntent2 = new Intent(getActivity(), MediaPlayerService.class);
getActivity().bindService(playIntent2, serviceConnection2, Context.BIND_AUTO_CREATE);
getActivity().startService(playIntent2);
}
}
Getting null object error on Service object. This method is not initializing
private ServiceConnection musicConnection = new ServiceConnection()
Its containg tab host then this Fragment.
public class PrimaryFragment extends Fragment {
RecyclerView rv;
LazyAdapter adapter;
ListView listView;
View rootView;
private MusicService serviceMusic;
ArrayList<AudioListModel> songsList;
private Intent playIntent;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.primary_layout, container, false);
songsList = SongsManager.GetSongs();
adapter = new LazyAdapter(getActivity(), songsList.toArray(new AudioListModel[songsList.size()]));
//rv = (RecyclerView) rootView.findViewById(R.id.songs_recycleview);
listView = (ListView) rootView.findViewById(R.id.SongList);
LazyAdapter ad = new LazyAdapter(getActivity(), songsList.toArray(new AudioListModel[songsList.size()]));
listView.setItemsCanFocus(false);
listView.setAdapter(ad);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Toast.makeText(getActivity(), position + "this is on click event", Toast.LENGTH_SHORT).show();
serviceMusic.setSelectedSong(position, MusicService.NOTIFICATION_ID); // getting error here......
Intent i = new Intent(getActivity(), PlaySongActivity.class);
startActivity(i);
}
});
return rootView;
}
// This method is not initializing.
private ServiceConnection musicConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.PlayerBinder binder = (MusicService.PlayerBinder) service;
//get servic1
serviceMusic = binder.getService();
serviceMusic.setSongList(songsList);
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
};
#Override
public void onStart() {
super.onStart();
//Start service
//Toast.makeText(getActivity(), "before onStart", Toast.LENGTH_SHORT).show();
if (playIntent == null) {
//Toast.makeText(getActivity(), "after onStart", Toast.LENGTH_SHORT).show();
playIntent = new Intent(getActivity(), MusicService.class);
getActivity().bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
getActivity().startService(playIntent);
}
}
}
here is music service class
public class MusicService extends Service implements
MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,
MediaPlayer.OnCompletionListener {
private MediaPlayer mPlayer;
private Uri mSongUri;
private ArrayList<ListModel> mListSongs;
private int SONG_POS = 0;
private final IBinder musicBind = new PlayerBinder();
private Notification.Builder notificationBuilder;
private Notification mNotification;
public class PlayerBinder extends Binder {//Service connection to play in background
public MusicService getService() {
Log.d("test", "getService()");
return MusicService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
Log.d("test", "onBind Called ");
return musicBind;
}
i had not registed MusicService in "AndroidManifest.xml". so i include this line and it started working.
"< service android:name=".MusicService" />"
we need to register services in manifest..
I'm devolping an music player application, when user click on an item (song) in the listview in PlayListFragment user redirects to the mediaPlayerFragment and the choosen melody starts to play. When user repeat the scenario i think that a new instance of mediaPlayer is created because there is two melodys playing at the same time.
How to avoid this problem?
(I have tried to place mediaPlayer.create(..) in onCreate() but there is probably something more that is need to be done to make it work correctly. I have also tried to create a singletonObject without success)
MediaPlayerFragment.java
public class MediaPlayerFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private MediaPlayer mediaPlayer;
private double endTime = 0;
private double startTime = 0;
private int forwardTime = 5000;
private int backwardTime = 5000;
public static int oneTimeOnly = 0;
private SeekBar seekBar;
private ImageButton btnPlay;
private ImageButton btnPause;
private ImageButton btnStop;
private ImageButton btnForward;
private ImageButton btnRewind;
public TextView songInfo;
public TextView txtEndTime;
public TextView txtStartTime;
private Handler mediaHandler = new Handler();
private boolean isPausePressed = false;
private boolean isPlayPressed = false;
private boolean isStopPressed = true;
private OnFragmentInteractionListener mListener;
private Song currentSong;
public static MediaPlayerFragment newInstance(String param1, String param2) {
MediaPlayerFragment fragment = new MediaPlayerFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public MediaPlayerFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_media_player, container, false);
getActivity().setTitle("Media Player");
songInfo = (TextView)view.findViewById(R.id.txt_currentsong);
txtEndTime = (TextView)view.findViewById(R.id.txt_time_left);
txtStartTime = (TextView)view.findViewById(R.id.txt_time_start);
seekBar = (SeekBar)view.findViewById(R.id.seek_bar_elapsed_time);
btnPlay = (ImageButton)view.findViewById(R.id.btn_play);
btnPause = (ImageButton)view.findViewById(R.id.btn_pause);
btnStop = (ImageButton)view.findViewById(R.id.btn_stop);
btnRewind = (ImageButton)view.findViewById(R.id.btn_previous);
btnForward = (ImageButton)view.findViewById(R.id.btn_next);
songInfo.setText(currentSong.getArtist() + " - " + currentSong.getTitle());
mediaPlayer = MediaPlayer.create(getActivity(), Uri.parse(currentSong.getUri()));
seekBar.setClickable(false);
btnPause.setEnabled(false);
btnStop.setEnabled(false);
btnForward.setEnabled(false);
btnRewind.setEnabled(false);
//Click events!
btnPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pause(view);
isPausePressed = true;
isPlayPressed = false;
isStopPressed = false;
}
});
btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
play(view);
isPausePressed = false;
isPlayPressed = true;
isStopPressed = false;
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stop(view);
isPausePressed = false;
isPlayPressed = false;
isStopPressed = true;
}
});
btnForward.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
forward(view);
isPausePressed = false;
isPlayPressed = false;
isStopPressed = false;
}
});
btnRewind.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
rewind(view);
isPausePressed = false;
isPlayPressed = false;
isStopPressed = false;
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStartTrackingTouch(SeekBar s) {
}
#Override
public void onStopTrackingTouch(SeekBar s) {
}
#Override
public void onProgressChanged(SeekBar s, int progress, boolean fromUser) {
if (mediaPlayer != null && fromUser) {
mediaPlayer.seekTo(progress);
// Check if pause, play or stop buttons is pressed
if(!isPausePressed && !isPlayPressed && !isStopPressed) {
play(view);
}
}
}
});
return view;
}
public void play(View view) {
//Check if a track has been choosen from playlist...
if(currentSong.getId() != null) {
mediaPlayer.start();
endTime = mediaPlayer.getDuration();
startTime = mediaPlayer.getCurrentPosition();
if (oneTimeOnly == 0) {
seekBar.setMax((int) endTime);
oneTimeOnly = 1;
}
txtEndTime.setText(String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes((long) endTime),
TimeUnit.MILLISECONDS.toSeconds((long) endTime) -
TimeUnit.MILLISECONDS.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) endTime)))
);
txtStartTime.setText(String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes((long) startTime),
TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) startTime)))
);
seekBar.setProgress((int) startTime);
mediaHandler.postDelayed(UpdateSongTime, 100);
btnPause.setEnabled(true);
btnStop.setEnabled(true);
btnRewind.setEnabled(true);
btnForward.setEnabled(true);
}
}
private Runnable UpdateSongTime = new Runnable() {
public void run() {
startTime = mediaPlayer.getCurrentPosition();
txtStartTime.setText(String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes((long) startTime),
TimeUnit.MILLISECONDS.toSeconds((long) startTime),
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) startTime)))
);
seekBar.setProgress((int) startTime);
mediaHandler.postDelayed(this, 100);
}
};
public void stop(View view) {
btnPause.setEnabled(false);
btnForward.setEnabled(false);
btnRewind.setEnabled(false);
btnStop.setEnabled(false);
mediaPlayer.pause();
mediaPlayer.seekTo(0);
}
public void pause(View view) {
mediaPlayer.pause();
btnPause.setEnabled(false);
btnPlay.setEnabled(true);
}
public void forward(View view) {
int temp = (int)startTime;
if ((temp + forwardTime)<= endTime) {
startTime = startTime + forwardTime;
mediaPlayer.seekTo((int) startTime);
}
}
public void rewind(View view) {
int temp = (int) startTime;
if ((temp-backwardTime)> 0) {
startTime = startTime - backwardTime;
mediaPlayer.seekTo((int)startTime);
}
}
public void setSong(Song song) {
this.currentSong = song;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
PlayListFragment.java
public class PlayListFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private PlayListAdapter playListAdapter;
private ListView lstPlayList;
public static ArrayList<Song> storeSongs = new ArrayList<>();
private OnFragmentInteractionListener mListener;
public static PlayListFragment newInstance(String param1, String param2) {
PlayListFragment fragment = new PlayListFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public PlayListFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_play_list, container, false);
getActivity().setTitle("Play List");
getSongList();
sort(storeSongs);
AddToListView(view);
lstPlayList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Song song = new Song();
//Get clicked song from listview.
song = (Song) parent.getAdapter().getItem(position);
changeToMediaPlayerFragment(song);
}
});
return view;
}
private void getSongList() {
ContentResolver musicResolver = getActivity().getContentResolver();
Uri musicUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor musicCursor = musicResolver.query(musicUri, null, null, null, null);
if (musicCursor != null && musicCursor.moveToFirst()) {
//get columns
int titleColumns = musicCursor.getColumnIndex( MediaStore.Audio.Media.TITLE);
int idColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media._ID);
int artistColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
int uriColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.DATA);
//Add songs to container (storeSongs).
do {
Long thisId = musicCursor.getLong(idColumn);
String thisTitle = musicCursor.getString(titleColumns);
String thisArtist = musicCursor.getString(artistColumn);
String thisUri = musicCursor.getString(uriColumn);
storeSongs.add(new Song(thisId, thisTitle, thisArtist, thisUri));
} while (musicCursor.moveToNext());
}
}
public void changeToMediaPlayerFragment(Song song) {
MediaPlayerFragment mediaPlayerFragment = MediaPlayerFragment.newInstance("", "");
mediaPlayerFragment.setSong(song);
FragmentManager fM = getFragmentManager();
FragmentTransaction fT = fM.beginTransaction();
fT.replace(R.id.container, mediaPlayerFragment, null);
fT.addToBackStack("go to mediaPlayer fragmement");
fT.commit();
}
private void AddToListView(View view) {
if (playListAdapter == null) {
playListAdapter = new PlayListAdapter(getActivity(), storeSongs);
}
this.lstPlayList = (ListView) view.findViewById(R.id.listView_play_list);
lstPlayList.setAdapter(playListAdapter);
playListAdapter.notifyDataSetChanged();
}
private void sort(ArrayList<Song> songs) {
Collections.sort(songs, new Comparator<Song>() {
#Override
public int compare(Song lhs, Song rhs) {
return lhs.getArtist().compareTo(rhs.getArtist());
}
});
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
As Dyrborg pointed out i have now made the activity responsible for holding one reference to PlayListFragment and one reference of the MediaPlayerFragment.
public void changeToPlayListFragment() {
if (playListFragment == null) {
playListFragment = PlayListFragment.newInstance("", "");
}
if (getCurrentFragment() == 2) {
return;
} else {
FragmentManager fME = getFragmentManager();
FragmentTransaction fTE = fME.beginTransaction();
fTE.replace(R.id.container, playListFragment, null);
fTE.addToBackStack("go to Playlist fragment");
fTE.commit();
}
}
private int getCurrentFragment() {
Fragment currentFragment = getFragmentManager().findFragmentById(R.id.container);
if (currentFragment instanceof MediaPlayerFragment) {
return 1;
} else if (currentFragment instanceof PlayListFragment) {
return 2;
} else {
return 0;
}
}
Link contains all java code for a simple light weight media player with knocking interaction "http://pastebin.com/BHVZYLGv"