Search code examples
androidserviceandroid-service-binding

Null pointer exception on calling method of a service class from an activity class


I am trying to invoke method of a service class i.e getDur() from an activity class method i.e startPlay() but I am getting Null Pointer Exception. Below is the code of the project. I have also added some Log statements but nothing gets printed on the logs too

Herre I am trying to bind service class with activity class, if there is any other way by which I can call method of service class from activity class then please tell me.

songPlay.java

    Imports *

    public class songPlay extends AppCompatActivity {

    private static final int UPDATE_FREQUENCY = 500;
    private static final int STEP_VALUE = 4000;

    private TextView songName = null;
    private TextView songDurationCurrent = null;
    private TextView songDurationTotal = null;
    private TextView songArtistFile = null;
    private SeekBar seekbar = null;
    private ImageButton playButton = null;
    private ImageButton prevButton = null;
    private ImageButton nextButton = null;
    private Drawable clipArt = null;
    private ImageView albumCover = null;

    MusicService musicService;
    boolean mBound = false;

    private boolean isStarted = false;
    private boolean isMoveingSeekBar = false;

    String songId="", songTitle="", songArtist="", songPath="";

    private final Handler handler = new Handler();

    private final Runnable updatePositionRunnable = new Runnable() {
        public void run() {
            updatePosition();
        }
    };

    @Override
    protected void onStart() {
        super.onStart();
        Log.v("Check", "OnStart");
        Intent intent = new Intent(this, MusicService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_song_play);

        Intent intent = getIntent();

        if (intent != null && intent.hasExtra("SONG_ID")) {
            songId = intent.getStringExtra("SONG_ID");
            songTitle = intent.getStringExtra("SONG_TITLE");
            songArtist = intent.getStringExtra("SONG_ARTIST");
            songPath = intent.getStringExtra("SONG_PATH");

            songTitle = songTitle.replaceAll("\\s*\\([^\\)]*\\)\\s*", "");
            songTitle = songTitle.replaceAll("\\[.*?\\]", "");
            songArtist = songArtist.replaceAll("\\s*\\([^\\)]*\\)\\s*", "");

            songName = (TextView) findViewById(R.id.selectedfile);
            songName.setText(songTitle);
            songArtistFile = (TextView) findViewById(R.id.selectedfile_artistname);
            songArtistFile.setText(songArtist);
            songDurationCurrent = (TextView) findViewById(R.id.duration_current);
            songDurationTotal = (TextView) findViewById(R.id.duration_total);
            seekbar = (SeekBar) findViewById(R.id.seekbar);
            playButton = (ImageButton) findViewById(R.id.play);
            prevButton = (ImageButton) findViewById(R.id.prev);
            nextButton = (ImageButton) findViewById(R.id.next);
            albumCover = (ImageView) findViewById(R.id.cover);

            String selection = MediaStore.Audio.Media._ID + " = "+songId+"";

            Cursor cursor = getContentResolver().query(
                    MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[] {
                            MediaStore.Audio.Media._ID, MediaStore.Audio.Media.ALBUM_ID},
                    selection, null, null);

            if (cursor.moveToFirst()) {
                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);

                try {
                    albumCover.setImageURI(albumArtUri);
                }

                catch (Exception e) {
                    Log.e("Check", "Not Found");
                }
            }

            cursor.close();

            seekbar.setOnSeekBarChangeListener(seekBarChanged);

            playButton.setOnClickListener(onButtonClick);
            nextButton.setOnClickListener(onButtonClick);
            prevButton.setOnClickListener(onButtonClick);

            start();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacks(updatePositionRunnable);
        isStarted = false;
    }

    private void start() {
        startService(new Intent(getApplicationContext(), MusicService.class).putExtra("songPath", songPath));
        startPlay();
    }

    private void startPlay() {
        isStarted = true;
        seekbar.setProgress(0);
        seekbar.setMax(musicService.getDur());

        long millis = musicService.getDur();
        long second = (millis / 1000) % 60;
        long minute = (millis / (1000 * 60)) % 60;
        long hour = (millis / (1000 * 60 * 60)) % 24;
        String temp="",a="",b="",c="";
        if(hour==0)
            a = "00";
        else if(hour<=9 && hour>0)
            a = "0" + String.valueOf(hour);
        else
            a = String.valueOf(hour);
        if(minute==0)
            b = "00";
        else if(minute<=9 && minute>0)
            b = "0" + String.valueOf(minute);
        else
            b = String.valueOf(minute);
        if(second==0)
            c = "00";
        else if(second<=9 && second>0)
            c = "0" + String.valueOf(second);
        else
            c = String.valueOf(second);
        temp = a + ":" + b + ":" + c;
        songDurationTotal.setText(temp);
        playButton.setImageResource(android.R.drawable.ic_media_pause);
        isStarted = true;

        updatePosition();
    }

    private void stopPlay() {
        //musicService.stopPlay();
        Intent intent = new Intent("songAction");
        intent.putExtra("action", "stopPlay");
        sendBroadcast(intent);
        playButton.setImageResource(android.R.drawable.ic_media_play);
        handler.removeCallbacks(updatePositionRunnable);
        seekbar.setProgress(0);

        isStarted = false;
    }

    private void updatePosition() {
        handler.removeCallbacks(updatePositionRunnable);

        seekbar.setProgress(musicService.getCPos());
        long millis = musicService.getCPos();
        long second = (millis / 1000) % 60;
        long minute = (millis / (1000 * 60)) % 60;
        long hour = (millis / (1000 * 60 * 60)) % 24;
        String temp="",a="",b="",c="";
        if(hour==0)
            a = "00";
        else if(hour<=9 && hour>0)
            a = "0" + String.valueOf(hour);
        else
            a = String.valueOf(hour);
        if(minute==0)
            b = "00";
        else if(minute<=9 && minute>0)
            b = "0" + String.valueOf(minute);
        else
            b = String.valueOf(minute);
        if(second==0)
            c = "00";
        else if(second<=9 && second>0)
            c = "0" + String.valueOf(second);
        else
            c = String.valueOf(second);
        temp = a + ":" + b + ":" + c;
        songDurationCurrent.setText(temp);

        handler.postDelayed(updatePositionRunnable, UPDATE_FREQUENCY);
    }

    private View.OnClickListener onButtonClick = new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.play: {
                    if (musicService.isPlay()) {
                        handler.removeCallbacks(updatePositionRunnable);
                        //musicService.pausePlay();
                        Intent intent = new Intent("songAction");
                        intent.putExtra("action", "pausePlay");
                        sendBroadcast(intent);
                        playButton.setImageResource(android.R.drawable.ic_media_play);
                    } else {
                        if (isStarted) {
                            //musicService.startAgain();
                            Intent intent = new Intent("songAction");
                            intent.putExtra("action", "startAgain");
                            sendBroadcast(intent);
                            playButton.setImageResource(android.R.drawable.ic_media_pause);

                            updatePosition();
                        } else {
                            start();
                        }
                    }
                    break;
                }
                case R.id.next: {
                    int seekto = musicService.getCPos() + STEP_VALUE;

                    if (seekto > musicService.getDur())
                        seekto = musicService.getDur();

                    //musicService.pausePlay();
                    Intent intent = new Intent("songAction");
                    intent.putExtra("action", "seekTo");
                    intent.putExtra("value", String.valueOf(seekto));
                    sendBroadcast(intent);
                    //musicService.startAgain();

                    break;
                }
                case R.id.prev: {
                    int seekto = musicService.getCPos() - STEP_VALUE;

                    if (seekto < 0)
                        seekto = 0;

                    //musicService.pausePlay();
                     /*
                    Intent intent = new Intent("songAction");
                    intent.putExtra("action", "pausePlay");
                    sendBroadcast(intent);
                    player.seekTo(seekto);
                    intent.putExtra("action", "startAgain");
                    sendBroadcast(intent);


                    //musicService.startAgain();
                     */
                    Intent intent = new Intent("songAction");
                    intent.putExtra("action", "seekTo");
                    intent.putExtra("value", String.valueOf(seekto));
                    sendBroadcast(intent);

                    break;
                }
            }
        }
    };

    private SeekBar.OnSeekBarChangeListener seekBarChanged = new SeekBar.OnSeekBarChangeListener() {

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            isMoveingSeekBar = false;
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            isMoveingSeekBar = true;
        }

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            if (isMoveingSeekBar) {
               // player.seekTo(progress);
                Intent intent = new Intent("songAction");
                intent.putExtra("action", "seekTo");
                intent.putExtra("value", String.valueOf(progress));
                sendBroadcast(intent);
            }
        }
    };

    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            Log.v("Check", "Service Connected");
            MusicService.LocalBinder binder = (MusicService.LocalBinder) service;
            musicService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
    }

MusicService.java

    Imports*

    public class MusicService extends Service {

    String songPath = "", action = "";
    MediaPlayer player = null;
    private final IBinder mBinder = new LocalBinder();

    private BroadcastReceiver yourReceiver;

    @Override
    public IBinder onBind(Intent arg0) {
        return mBinder;
    }

    public class LocalBinder extends Binder {
        MusicService getService() {
            return MusicService.this;
        }
    }

    public void onCreate() {
        super.onCreate();
        player = new MediaPlayer();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, final int startId) {
        Log.v("Check", "Service Started");
        songPath = intent.getStringExtra("songPath");
        final IntentFilter theFilter = new IntentFilter();

        player.setOnCompletionListener(onCompletion);
        player.setOnErrorListener(onError);

        player.stop();
        player.reset();

        try {
            player.setDataSource(songPath);
            player.prepare();
            player.start();
        }

        catch (Exception e) {

        }

        this.yourReceiver = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if(action.equals("songAction")){
                    String state = intent.getExtras().getString("action");
                    if(state.equals("stopPlay")) {
                        stopPlay();
                    }
                    else if(state.equals("pausePlaye")) {
                        pausePlay();
                    }
                    else if(state.equals("startAgain")) {
                        startAgain();
                    }
                    else if(state.equals("seekTo")) {
                        int value = Integer.parseInt(intent.getExtras().getString("value"));
                        player.seekTo(value);
                    }
                }
            }
        };

        this.registerReceiver(this.yourReceiver, theFilter);

        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        player.stop();
        player.reset();
        player.release();
        player = null;
    }

    void stopPlay() {
        player.stop();
        player.reset();
    }

    void  pausePlay() {
        player.pause();
    }

    void startAgain() {
        player.start();
    }

    private MediaPlayer.OnCompletionListener onCompletion = new MediaPlayer.OnCompletionListener() {

        @Override
        public void onCompletion(MediaPlayer mp) {
            stopPlay();
        }
    };

    private MediaPlayer.OnErrorListener onError = new MediaPlayer.OnErrorListener() {

        @Override
        public boolean onError(MediaPlayer mp, int what, int extra) {
            return false;
        }
    };

    int getCPos() {
        return player.getCurrentPosition();
    }

    int getDur() {
        return player.getDuration();
    }

    boolean isPlay() {
        return player.isPlaying();
    }
    }

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.coderahul.player"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="24" />

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:name="com.android.tools.fd.runtime.BootstrapApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >

        <activity
            android:name="com.example.coderahul.player.MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.example.coderahul.beats.songPlay" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:enabled="true" android:process=":remote" android:name=".MusicService"/>
    </application>

</manifest>

Solution

  • You are calling start() method from onCreate which is before your service is connected. Call start() method after your service has been binded or started so that you have instance of the service class.
    
    @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            MusicService.LocalBinder binder = (MusicService.LocalBinder) service;
            musicService = binder.getService();      
            mBound = true;
            //here
            start();
        }