从活动类调用服务类的方法时出现空指针异常

时间:2016-07-09 19:32:52

标签: android service android-service-binding

我试图从一个活动类方法调用服务类的方法,即getDur(),即startPlay(),但我得到Null Pointer Exception。以下是项目的代码。我还添加了一些日志语句,但日志上也没有打印

Herre我正在尝试将服务类绑定到活动类,如果有任何其他方法可以从活动类调用服务类的方法,那么请告诉我。

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>

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

bindService是异步的

将start()放在onServiceConnected:

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

日志

enter image description here

输出

enter image description here