如何通过片段从MainActivity调用服务绑定器?

时间:2015-09-24 22:22:47

标签: java android android-fragments android-service onclicklistener

我在我的ViewHolder上将一个OnClickListener设置为cardviews:

 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item, parent, false);
        view.setBackgroundResource(mBackground);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        holder.mBoundString = mValues.get(position);
        holder.mTextView.setText(mValues.get(position));

        holder.mView.setOnClickListener(new View.OnClickListener() {
            @Override

            public void onClick(View v) {


                MainActivity mActivity= new MainActivity();
                mActivity.onClickPlayButton(v);
            }
        });

        Glide.with(holder.mImageView.getContext())
                .load(Stations.getRandomCheeseDrawable())
                .fitCenter()
                .into(holder.mImageView);
    }

这是我在MainActivity上的onClickPlayButton:

public void onClickPlayButton(View view) {
        radioServiceBinder.play();
    }

这是服务代码:

public class RadioService extends Service implements OnErrorListener, OnCompletionListener, OnPreparedListener, OnInfoListener {

private MediaPlayer mediaPlayer;
private List<String> radioStreamURL = new ArrayList<>();
private int radioStreamingIndex = 0;

public static final String MODE_CREATED = "CREATED";
public static final String MODE_DESTROYED = "DESTROYED";
public static final String MODE_PREPARED = "PREPARED";
public static final String MODE_STARTED = "STARTED";
public static final String MODE_PLAYING = "PLAYING";
public static final String MODE_PAUSED = "PAUSED";
public static final String MODE_STOPPED = "STOPPED";
public static final String MODE_COMPLETED = "COMPLETED";
public static final String MODE_ERROR = "ERROR";
public static final String MODE_BUFFERING_START = "BUFFERING_START";
public static final String MODE_BUFFERING_END = "BUFFERING_END";

private boolean isPrepared = false;

private final IBinder binder = new RadioBinder();

    @Override
    public void onCreate() {
        // add stations to the list

        radioStreamURL.add("http://momori.animenfo.com:8000/");
        radioStreamURL.add("http://momori.animenfo.com:8000/");
        radioStreamURL.add("http://momori.animenfo.com:8000/");

        /* Create MediaPlayer when it starts for first time */
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setOnCompletionListener(this);
        mediaPlayer.setOnErrorListener(this);
        mediaPlayer.setOnPreparedListener(this);
        mediaPlayer.setOnInfoListener(this);

        sendBroadcast(new Intent(MODE_CREATED));
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mediaPlayer.stop();
        mediaPlayer.reset();
        isPrepared = false;
        sendBroadcast(new Intent(MODE_DESTROYED));
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        sendBroadcast(new Intent(MODE_STARTED));

        /* Starts playback at first time or resumes if it is restarted */
        if(mediaPlayer.isPlaying())
            sendBroadcast(new Intent(MODE_PLAYING));
        else if(isPrepared) {
            sendBroadcast(new Intent(MODE_PAUSED));
        }

        return Service.START_STICKY;
    }


    @Override
    public void onPrepared(MediaPlayer _mediaPlayer) {
        /* If radio is prepared then start playback */
        sendBroadcast(new Intent(MODE_PREPARED));
        isPrepared = true;
        play();
    }

    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        /* When no stream found then complete the playback */
        mediaPlayer.stop();
        mediaPlayer.reset();
        isPrepared = false;
        sendBroadcast(new Intent(MODE_COMPLETED));
    }

    public void prepare() {
        /* Prepare Async Task - starts buffering */
        try {
            mediaPlayer.setDataSource(radioStreamURL.get(radioStreamingIndex));
            mediaPlayer.prepareAsync();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void nextStation(){
        changeStation(radioStreamingIndex+1);
    }

    public void prevStation(){
        changeStation(radioStreamingIndex-1);
    }

    public void changeStation(int stationIndex){
        if(stationIndex > 0 && stationIndex < radioStreamURL.size()){
            radioStreamingIndex = stationIndex;
            stop();
            play();
        }
    }

    public void play() {
        if(isPrepared) {
            mediaPlayer.start();
            System.out.println("RadioService: play");
            //sendBroadcast(new Intent(MODE_PLAYING));
        }
        else
        {
            //sendBroadcast(new Intent(MODE_STARTED));
            prepare();
        }
    }

    public void pause() {
        mediaPlayer.pause();
        System.out.println("RadioService: pause");
        sendBroadcast(new Intent(MODE_PAUSED));
    }

    public void stop() {
        mediaPlayer.stop();
        mediaPlayer.reset();
        isPrepared = false;
        System.out.println("RadioService: stop");
        sendBroadcast(new Intent(MODE_STOPPED));
    }

    @Override
    public boolean onInfo(MediaPlayer mp, int what, int extra) {
        /* Check when buffering is started or ended */
        if(what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
            sendBroadcast(new Intent(MODE_BUFFERING_START));
        }
        else if(what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
            sendBroadcast(new Intent(MODE_BUFFERING_END));
        }

        return false;
    }


    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        sendBroadcast(new Intent(MODE_ERROR));
        switch (what) {
            case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
                Log.v("ERROR","MEDIA ERROR NOT VALID FOR PROGRESSIVE PLAYBACK " + extra);
                break;
            case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
                Log.v("ERROR","MEDIA ERROR SERVER DIED " + extra);
                break;
            case MediaPlayer.MEDIA_ERROR_UNKNOWN:
                Log.v("ERROR","MEDIA ERROR UNKNOWN " + extra);
                break;
        }
        return false;
    }


    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    /* Allowing activity to access all methods of RadioService */
    public class RadioBinder extends Binder {
        RadioService getService() {
            // Return this instance of RadioService so clients can call public methods
            return RadioService.this;
        }
    }

}

当我点击它时,我在logcat上遇到了这个错误:java.lang.NullPointerException:尝试调用虚方法.... RadioService.play()&#39;在null对象引用上。

我认为play()方法没有任何问题。

我希望OnClickListener或onClickPlayButton从绑定到MainActivity的Service类调用play()方法。我怎样才能做到这一点? 我坚持这个问题。

1 个答案:

答案 0 :(得分:0)

你的错误

MainActivity mActivity= new MainActivity();
mActivity.onClickPlayButton(v);

您尝试调用Activitys类的新实例的方法。但是你应该调用当前的方法,运行你的活动实例。因此,您必须将对您的活动的引用发送到适配器并在其上调用您的方法。

据我了解,您初始化变量并在OnCreate或您的活动的onResume上绑定您的服务。但是这个方法没有被调用,所以你创建了一个MainActivity类的新实例;

<强> UPD_0:

所以你的适配器类应该是这样的:

public class YOURS_ADAPTERS_CLASS_NAME extends RecyclerView.Adapter<YOURS_ADAPTERS_CLASS_NAME.ViewHolder>
{
    Context ctx;

public YOURS_ADAPTERS_CLASS_NAME(Context ctx)
{
    this.ctx=ctx;
}

///other lines of yours code

所以现在你有你的实例在你的适配器类中运行活动。您现在应该将它转换为您的活动类并以这种方式调用您的方法:

 MainActivity mActivity= (MainActivity) ctx;
 mActivity.onClickPlayButton(v);

此外,您不需要(我可以看到)方法onClickPlayButton()

中的参数