Reputation: 231
I wanted to created a playlist such that when the user clicks on the song, it plays and when he clicks on the next song, the song that is playing will stop and resume the next song. Additionally, i have placed a stop button which also stops the song which is being played. Now, here is the problem when i write the following block of code, my program crashes and my error log shows java.lang.NullPointerException-
public void playSong(int res)
{
if(mp.isPlaying()) {
mp.reset();
mp = MediaPlayer.create(getApplicationContext(), resid[res]);
mp.start();
}
else {
mp = MediaPlayer.create(getApplicationContext(), resid[res]);
mp.start();
}
}
But if i change the code to the following, it works fine. I see that mp.reset() is the issue. But I dont know how to fix it because without it the when i click on a song and there is already a song which is playing, both the songs play at the same time.-
public void playSong(int res)
{
mp = MediaPlayer.create(getApplicationContext(), resid[res]);
mp.start();
}
//Following is my full code. Please help me to fix the bug. Thanks--
package com.example.user.musicp;
import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
public class MainActivity extends Activity {
Button b;
private MediaPlayer mp;
private ListView v;
private int [] resid = {R.raw.k,R.raw.u};
private String [] name = {"k","u"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
v = (ListView) findViewById(R.id.listView);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, name);
v.setAdapter(adapter);
b = (Button) findViewById(R.id.StopButton);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// mp.stop();
// mp.release();
onDestroy();
}
});
v.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
playSong(i);
// mp = MediaPlayer.create(MainActivity.this, resid[i]);
// mp.start();
}
});
}
public void playSong(int res)
{
if(mp.isPlaying()) {
mp.reset(); //this is where the issue begins
mp = MediaPlayer.create(getApplicationContext(), resid[res]);
mp.start();
}
else {
mp = MediaPlayer.create(getApplicationContext(), resid[res]);
mp.start();
}
}
@Override
public void onDestroy() {
super.onDestroy();
mp.release();
}
@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);
}
}
References:- http://www.geeks.gallery/how-to-play-mp3-file-from-raw-folder-in-a-listview-android/
After some valuable suggestion by some users, i edited my code and was able to fix the bug. But here is the thing when i click on a song and there is a previous song which is already playing, i want the previous song to stop and the new song to be played but unfortunately both the songs keep playing. I tried every possible means to fix it but i may be doing mistake somewhere. Here is my edited code and when i implement the following, then my program crashes. PLease help me out -
public void playSong(int res)
{
boolean isplaying = mp.isPlaying();
if(isplaying)
{
mp.stop();
mp = MediaPlayer.create(getApplicationContext(), resid[res]);
mp.start();
}
else
{
mp = MediaPlayer.create(getApplicationContext(), resid[res]);
mp.start();
}
}
Here is the complete working code just in case someone gets stuck in the future. Thanks a lot to StackOverflow users for helping me out. Cheers!
package com.example.user.musicp;
import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import java.io.IOException;
public class MainActivity extends Activity {
Button b,c;
private MediaPlayer mp;
private ListView v;
private int [] resid = {R.raw.k,R.raw.u};
private String [] name = {"k","u"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mp = new MediaPlayer();
v = (ListView) findViewById(R.id.listView);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, name);
v.setAdapter(adapter);
b = (Button) findViewById(R.id.StopButton);
c = (Button) findViewById(R.id.next);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mp.stop();
}
});
c.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent in = new Intent("com.example.user.musicp.SPLASH");
startActivity(in);
}
});
v.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
playSong(i);
// mp = MediaPlayer.create(MainActivity.this, resid[i]);
// mp.start();
}
});
}
public void playSong(int res)
{
mp.reset();// stops any current playing song
mp = MediaPlayer.create(getApplicationContext(), resid[res]);// create's
mp.start(); // starting mediaplayer
}
@Override
public void onDestroy() {
super.onDestroy();
mp.release();
}
@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);
}
}
Upvotes: 1
Views: 542
Reputation: 2891
if(mp.isPlaying()) { // mp only declared (still null)
mp.reset();
mp = MediaPlayer.create(getApplicationContext(), resid[res]);
mp.start(); }
else {
mp = MediaPlayer.create(getApplicationContext(), resid[res]);
mp.start();
}
I suppose that at the moment of the if
statement mp
is only declared.
That's why you can not do mp.isPlaying()
because mp
is still null
.
That should explain why in this case it works fine
public void playSong(int res)
{
// here mp is still null
mp = MediaPlayer.create(getApplicationContext(), resid[res]); // From here on we can use mp
mp.start();
}
Here mp is not used before initialization, hence no null pointer exception.
EDIT : Creating the mediaplayer in the playSong
method is a bit weird. This means every time playSong
is called mp
gets reassigned. A better place could be in the class' constructor. Doing so you can be sure mp
will not be null
when playSong
gets invoked.
EDIT 2 : You're still reassigning mp
in playSong
.
I would suggest to do this :
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mp = MediaPlayer.create(getApplicationContext(), resid[res]);
// ...
}
And I would implement playSong
like this :
public void playSong(int songIndex)
{
if(mp.isPlaying()) {
mp.pause(); // Pause the current track
}
mp.selectTrack(songIndex); // Select the requested track
mp.start();
}
Upvotes: 2