我开发了在线广播应用。我通过服务打电话给shoutcast无线电服务器。当我调用服务时,所有UI控件都被冻结,因此我使用了ProgressDialog但仍然冻结并且没有显示进度对话框。我使用过AsyncTask但没有工作。
HomeFragment.java
在按钮onClick事件中,执行CallingStreamServer AsyncTask。
public class CallingStreamServer extends AsyncTask<Void, Void, Void>{
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
progressDialog = new ProgressDialog(getActivity());
progressDialog.setTitle("Please Wait");
progressDialog.setMessage("Connecting Radio Station ...");
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(false);
progressDialog.show();
//progressDialog = ProgressDialog.show(getActivity(), "Please Wait", "Connecting Radio Station ...");
}
@Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
getActivity().startService(new Intent(getActivity(), StreamService.class));
return null;
}
@Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
progressDialog.dismiss();
super.onPostExecute(result);
}
}
StreamService.java
StreamService创建媒体播放器并连接shoutcast无线电服务器。
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.d(TAG, "onCreate");
try {
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
sharedPreEditor = prefs.edit();
notiManager = (NotificationManager)getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
Context context = getApplicationContext();
String notiTitle = context.getResources().getString(R.string.app_name);
String notiMsg = "Connecting ... ";
Intent mainActivity = new Intent(context, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, 0, mainActivity, 0);
noti = new Notification.Builder(context)
.setContentTitle(notiTitle)
.setContentText(notiMsg)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent)
.build();
notiManager.notify(notiID, noti);
String url = prefs.getString("streamURL", "");
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare();
} catch (Exception e) {
// TODO: handle exception
Log.e(TAG, "onCreate Method : " + e.getMessage());
}
}
@Override
@Deprecated
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Log.d(TAG, "onStart");
try {
mediaPlayer.start();
sharedPreEditor.putBoolean("isPlaying", true);
sharedPreEditor.commit();
Context context = getApplicationContext();
String notiTitle = context.getResources().getString(R.string.app_name);
String notiMsg = prefs.getString("displayStation", "") + " radio is now playing.";
Intent _intent = new Intent(context, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, 0, _intent, 0);
noti = new Notification.Builder(context)
.setContentTitle(notiTitle)
.setContentText(notiMsg)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent)
.build();
noti.flags = Notification.FLAG_NO_CLEAR;
notiManager.notify(notiID, noti);
} catch (Exception e) {
Log.e(TAG, "onStart Method : " + e.getMessage());
}
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.d(TAG, "onDestroy");
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
sharedPreEditor.putBoolean("isPlaying", false);
sharedPreEditor.commit();
notiManager.cancel(notiID);
stopSelf();
}
答案 0 :(得分:2)
我为我的问题做了一些伎俩。在服务onCreate事件中,mediaPlayer.prepare()被冻结用于从@Doug Stevenson识别出的点。因此我在服务中为mediaPlayer.prepare()和mediaPlayer.start()创建了1 线程。我使用 BroadcastReceiver 进行服务调用和结果。 :)
<强> HomeFragment.java 强>
注册BroadcastReceiver和按钮onClick事件发送到BroadcastReceiver进行服务调用
@Override
public void onClick(View v) {
if (v.getId() == butBoxOfMusic.getId()) {
Intent intent = new Intent();
intent.setAction(ACTION_STREAM_RECEIVER);
intent.putExtra("result", "start");
getActivity().sendBroadcast(intent);
}
}
public class StreamServiceReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (intent.getStringExtra("result").equals("start")) {
/// Calling service(call from onClick event)
progressDialog = ProgressDialog.show(getActivity(), "Please Wait", "Connecting Radio Station ...");
getActivity().startService(new Intent(getActivity(), StreamService.class));
}else{
/// Streaming playing(result from service)
progressDialog.dismiss();
}
}
}
StreamService.java
StreamService创建媒体播放器并连接shoutcast无线电服务器。
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.d(TAG, "onCreate");
try {
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
sharedPreEditor = prefs.edit();
notiManager = (NotificationManager)getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
Context context = getApplicationContext();
String notiTitle = context.getResources().getString(R.string.app_name);
String notiMsg = "Connecting ... ";
Intent mainActivity = new Intent(context, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, 0, mainActivity, 0);
noti = new Notification.Builder(context)
.setContentTitle(notiTitle)
.setContentText(notiMsg)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent)
.build();
notiManager.notify(notiID, noti);
String url = prefs.getString("streamURL", "");
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
// mediaPlayer.prepare();
} catch (Exception e) {
// TODO: handle exception
Log.e(TAG, "onCreate Method : " + e.getMessage());
}
}
@Override
@Deprecated
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Log.d(TAG, "onStart");
try {
Thread thread = new Thread("MediaPlayer" + String.valueOf(startId)){
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
mediaPlayer.prepare();
mediaPlayer.start();
sharedPreEditor.putBoolean("isPlaying", true);
sharedPreEditor.commit();
Context context = getApplicationContext();
String notiTitle = context.getResources().getString(R.string.app_name);
String notiMsg = prefs.getString("displayStation", "") + " radio is now playing.";
Intent _intent = new Intent(context, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, 0, _intent, 0);
noti = new Notification.Builder(context)
.setContentTitle(notiTitle)
.setContentText(notiMsg)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent)
.build();
noti.flags = Notification.FLAG_NO_CLEAR;
notiManager.notify(notiID, noti);
/// Send reslt to BroadcastReceiver ///
Intent intent = new Intent();
intent.setAction(HomeFragment.ACTION_STREAM_RECEIVER);
intent.putExtra("result", "Playing");
sendBroadcast(intent);
} catch (IllegalStateException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
thread.start();
} catch (Exception e) {
Log.e(TAG, "onStart Method : " + e.getMessage());
}
}
答案 1 :(得分:1)
Android服务onCreate总是在主线程上运行,因此它将阻止主线程上的其他内容,例如UI和动画。默认情况下,Service类不提供任何线程,因此如果您需要,您必须自己提供。
因此,您需要一种策略,将服务onCreate中的所有阻塞工作从主线程移到其他线程中。特别是,mediaPlayer.prepare()将阻塞一段未知的时间。
答案 2 :(得分:0)
MediaPlayer.prepare()
可能不会立即返回,因此会阻止您的UI线程。尝试使用MediaPlayer.prepareAsync()
并实现OnPreparedListerner
接口,以便在MediaPlayer
准备好后接收回调。
http://developer.android.com/reference/android/media/MediaPlayer.OnPreparedListener.html