[英]How to update android fragment UI from service?
I am developing an android application which will play live radio audio stream. 我正在开发一个可播放实时广播音频流的android应用程序。 I have implemeted android MediaPlayer API for this purpose which constantly receives the audio data from a remote source.
我已经为此实现了android MediaPlayer API,该API不断从远程源接收音频数据。
On the click of play button, I have started a Service and controling the MediaPlayer instance from there. 在单击“播放”按钮上,我启动了一个服务并从那里控制MediaPlayer实例。 I am successful in doing all so and my working code is as follows:
我成功完成了所有工作,我的工作代码如下:
ListenFragment.java 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: 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;
}
}
The only problem that i face is that I want to change the text in UI TextView from " Listen Live " to " Loading... " and then to " On Air " as the media player gets started. 我面对的唯一问题是,我想在UI的TextView文本从“ 听现场 ”改变“ 载入中...”,再到“ 直播 ”为媒体播放器启动。
You can use broadcast receiver for that purpose. 您可以为此使用广播接收器。 In your service send a broadcast, and inside your fragment you can register to listen for that and the change your UI according to that.
在您的服务中发送广播,并且可以在片段中注册以收听该广播,并根据该广播更改UI。
For eg, use 例如,使用
Intent intent = new Intent("intent_filter");
intent.putString("messageToShow","On Air");
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.sendBroadcast(intent);
And for receiving that in your fragment use: 并在您的片段中使用:
LocalBroadcastManager.getInstance(this).registerReceiver(new YourReceiver(),new IntentFilter("intent_filter"));
You can read more on https://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager 您可以在https://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager上阅读更多内容
You can also take a look at EventBus. 您还可以查看EventBus。
A possible solution will be to use a bound service https://developer.android.com/guide/components/bound-services to have a reference to an IBinder instance and let you communicate to your service. 一种可能的解决方案是使用绑定服务https://developer.android.com/guide/components/bound-services引用IBinder实例,并让您与服务进行通信。 The communication (from service to fragment) can be done by providing a listener object (
IPlayServiceListener
for instance). 通信(从服务到片段)可以通过提供侦听器对象(例如
IPlayServiceListener
)来完成。
This is how your service might look like: 这是您的服务的样子:
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;
}
}
then in order to start the service: 然后为了启动服务:
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) {
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.