Как обновить пользовательский интерфейс фрагмента Android из сервиса? - PullRequest
0 голосов
/ 26 августа 2018

Я занимаюсь разработкой приложения для Android, которое будет воспроизводить потоковое радио в режиме реального времени.Для этой цели я реализовал Android MediaPlayer API, который постоянно получает аудиоданные из удаленного источника.

При нажатии кнопки воспроизведения я запускаю службу и оттуда управляю экземпляром MediaPlayer.Я успешно все это делаю, и мой рабочий код выглядит следующим образом:

ListenFragment.java

playbtn_flat.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v)
        {
            // TODO Auto-generated method stub
            if(isNetworkConnected())
            {
                serviceIntent.putExtra("sentAudioLink",strAudioLink);
                try
                {
                    getActivity().startService(new Intent(getContext(),PlayService.class));
                }
                catch (Exception e)
                {
                    Toast.makeText(getContext(),e.getClass().getName()+" "+e.getMessage(),Toast.LENGTH_SHORT).show();
                }

            }

        }
    });

PlayService.java:

public class PlayService extends Service implements MediaPlayer.OnCompletionListener,MediaPlayer.OnPreparedListener,
        MediaPlayer.OnErrorListener,MediaPlayer.OnSeekCompleteListener,MediaPlayer.OnInfoListener,
        MediaPlayer.OnBufferingUpdateListener {

    private MediaPlayer mediaPlayer = new MediaPlayer();
    private String sentAudioLink;

    @Override
    public void onCreate() {
        mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
        mediaPlayer.setOnCompletionListener(this);
        mediaPlayer.setOnPreparedListener(this);
        mediaPlayer.setOnErrorListener(this);
        mediaPlayer.setOnSeekCompleteListener(this);
        mediaPlayer.setOnInfoListener(this);
        mediaPlayer.setOnBufferingUpdateListener(this);
        mediaPlayer.reset();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        sentAudioLink = intent.getExtras().getString("sentAudioLink");
        mediaPlayer.reset();
        //setup the media player data source using the strAudioLink value
        if (!mediaPlayer.isPlaying()) {
            try {
                mediaPlayer.setDataSource(sentAudioLink);
                //prepare media player
                mediaPlayer.prepareAsync();
            } catch (IllegalStateException e) {
                Log.e("workingerror1", e.toString());
            } catch (IllegalArgumentException e) {
                Log.e("workingerror2", e.toString());
            } catch (IOException e) {
                Log.e("workingerror3", e.toString());
            }
        }
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
        }
        mediaPlayer.release();
    }

    @Override
    public void onBufferingUpdate(MediaPlayer mp, int percent) {

    }

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

    public void stopMedia() {
        if (mediaPlayer.isPlaying())
            mediaPlayer.stop();
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        Toast.makeText(this, "Error" + what, Toast.LENGTH_LONG).show();
        Log.e("workingmain_error", "error");
        Log.e("workingmain_error2", String.format("Error(%s%s)", what, extra));
        return false;
    }

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

    @Override
    public void onPrepared(MediaPlayer mp) {
        playMedia();
    }

    public void playMedia() {
        if (!mediaPlayer.isPlaying()) {
            Log.e("working4", "error");
            mediaPlayer.start();
        }
    }

    @Override
    public void onSeekComplete(MediaPlayer mp) {

    }

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

Единственная проблема, котораяя сталкиваюсь с тем, что я хочу изменить текст в TextView пользовательского интерфейса с " Listen Live " на " Загрузка ... ", а затем на " В эфире "как медиаплеер начинает.

мой пользовательский интерфейс ListenFragment: enter image description here

Ответы [ 2 ]

0 голосов
/ 26 августа 2018

Возможным решением будет использование привязанного сервиса https://developer.android.com/guide/components/bound-services иметь ссылку на экземпляр IBinder и позволить вам общаться с вашим сервисом. Связь (от службы к фрагменту) может быть осуществлена ​​путем предоставления объекта слушателя (например, IPlayServiceListener).

Вот так может выглядеть ваша служба:

public class PlayService extends Service implements MediaPlayer.OnCompletionListener,MediaPlayer.OnPreparedListener,
        MediaPlayer.OnErrorListener,MediaPlayer.OnSeekCompleteListener,MediaPlayer.OnInfoListener,
        MediaPlayer.OnBufferingUpdateListener {


    private final IBinder mBinder = new PlayServiceLocalBinder();
    private IPlayServiceListener listener = null;

    /** Binder allowing external components to interact with the service */
    public class PlayServiceLocalBinder extends Binder {
        public PlayService getService() {
            // Return this instance of LocalService so clients can call public methods
            return PlayService.this;
        }
    }

    public void setListener(IPlayServiceListener listener) {
        this.listener = listener;
    }

    ....

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

затем для запуска услуги:

Intent intent = new Intent(getContext(), PlayService.class);
bindService(intent, mPlayServiceConnection, Context.BIND_AUTO_CREATE));

private final ServiceConnection mPlayServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            PlayService.PlayServiceLocalBinder binder = (PlayService.PlayServiceLocalBinder) service;
            mPlayService = binder.getService();
            mPlayService.setListener(YourFragment.this);
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {

        }

    };
0 голосов
/ 26 августа 2018

Для этой цели вы можете использовать широковещательный приемник.В вашем сервисе отправьте трансляцию, и внутри своего фрагмента вы можете зарегистрироваться, чтобы прослушать это и изменить свой пользовательский интерфейс в соответствии с этим.

Например, используйте

 Intent intent = new Intent("intent_filter");
 intent.putString("messageToShow","On Air");
 LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
 localBroadcastManager.sendBroadcast(intent);

И для получения этогов вашем фрагменте используйте:

 LocalBroadcastManager.getInstance(this).registerReceiver(new YourReceiver(),new IntentFilter("intent_filter"));

Вы можете прочитать больше на https://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager

Вы также можете взглянуть на EventBus.

...