我是android平台的新手 . 目前正致力于流媒体广播应用 .
我想制作应用程序,启动音频播放和连续播放甚至应用程序转到后台 .
我使用 startService() 创建了一个服务,以便即使应用程序转到后台也可以继续播放 . 我还使用 bindService() 获取serviceConnection引用以使用service执行RPC调用 .
应用程序启动服务并正确启动回放,bindService能够获取引用并能够进行RPC调用,一切正常,直到应用程序转到后台 .
我在主要活动的 onResume() 和 onPause() 中调用了 bindService() 和 unBindService() .
当应用程序转到后台时,播放将继续,不会出现任何问题 . unBindservice()调用分离服务连接和在Service类中调用的onUnbind(Intent)方法 . 到目前为止没有问题 . 当应用程序到达前台时(当服务正在运行并且继续播放时),我没有获得服务连接引用(onServiceConnected()没有被调用),即使在activity onResume()方法中调用了bindService() . 我还验证了Service类onBind(Intent)方法也没有被调用 .
这几天我一直在努力解决这个问题 .
将 startService() 和 bindService() 与用户定义的Android服务一起使用的建议方法是什么?
任何帮助解决此问题,高度赞赏 .
活动onResume / onPause代码 .
@Override
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate => " + getIntent());
super.onCreate(savedInstanceState);
// set the default network preference, if it is not already set
setDefaultNetwork();
// initialize the navigation tab bars
initializeTabBar();
mPlayerController = AudioPlayerController.getInstance(this);
mActionBar.setDisplayShowHomeEnabled(true);
mActionBar.setDisplayShowTitleEnabled(true);
mRemoteControlReceiver = new RemoteControlReceiver();
IntentFilter filter = new IntentFilter(
"android.intent.action.MEDIA_BUTTON");
registerReceiver(mRemoteControlReceiver, filter);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG,"onResume");
mPlayerController.bindService();
restoreAppState();
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG,"onPause");
mPlayerController.unBindService();
storeAppState();
}
Controller类具有与服务相关的启动/停止/绑定/解除绑定方法
public void bindService() {
Intent intent = new Intent();
intent.setClassName("com.vikkrithik.radio.indradio",
"com.vikkrithik.radio.indradio.AudioPlayerService");
Log.d(TAG, "bindService Context " + mPlayerContext
+ " serviceConnection => " + audioServiceConnection);
mPlayerContext.bindService(intent, audioServiceConnection, 0);
}
public void unBindService() {
mPlayerContext.unbindService(audioServiceConnection);
Log.d(TAG, "unBindService done context => " + mPlayerContext
+ " serviceConnection => " + audioServiceConnection);
}
private ServiceConnection audioServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected " + name);
mAudioService = AudioPlayerServiceInterface.Stub
.asInterface(service);
}
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected " + name);
mAudioService = null;
}
};
/**
* Start the AudioService
*
*/
public void startAudioService(Station station) {
Intent intent = new Intent();
intent.setClassName("com.vikkrithik.radio.indradio",
"com.vikkrithik.radio.indradio.AudioPlayerService");
Bundle extras = new Bundle();
extras.putString("station_url", station.getUrl());
extras.putString("station_name", station.getStationName());
intent.putExtras(extras);
mCurrentStation = station;
mPlayerContext.startService(intent);
bindService();
Log.d(TAG, "startService called");
}
public void stopAudioService() {
//
// Check if AudioService is already created
//
if (null == mAudioService)
return;
Intent intent = new Intent();
intent.setClassName("com.vikkrithik.radio.indradio",
"com.vikkrithik.radio.indradio.AudioPlayerService");
mPlayerContext.stopService(intent);
Log.d(TAG, "stopAudioService done");
}
服务类方法
@Override
public IBinder onBind(Intent arg0) {
Log.d(TAG, "onBind invoked");
return audioServiceStub;
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG,"onUnbind invoked");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mNetworkStatusReceiver = new NetworkStatusReceiver();
IntentFilter filter = new IntentFilter(
ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(mNetworkStatusReceiver, filter);
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(
mNetworkStatusReceiver);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestory");
stopPlayback();
PreferenceManager.getDefaultSharedPreferences(this)
.unregisterOnSharedPreferenceChangeListener(
mNetworkStatusReceiver);
unregisterReceiver(mNetworkStatusReceiver);
cancelNotification();
audioServiceStub = null;
super.onDestroy();
}
Logcat output
当应用程序启动时
TabbarMainActivity(15432):onResume AudioPlayerController(15432):bindService Context com.vikkrithik.radio.indradio.TabbarMainActivity@4150fdb8 serviceConnection => com.vikkrithik.radio.indradio.AudioPlayerController$1@418a2d30
按下播放按钮时
AudioPlayerController(15432):bindService Context com.vikkrithik.radio.indradio.TabbarMainActivity@4150fdb8 serviceConnection => com.vikkrithik.radio.indradio.AudioPlayerController$1@418a2d30
AudioPlayerController(15432):调用startService
AudioPlayerService(15432):onCreate
AudioPlayerService(15432):onBind调用了 onBind() invoked
AudioPlayerService(15432):onStartCommand with IndetntIntent {cmp = xxxx(has extras)}
AudioPlayerController(15432):onServiceConnected ComponentInfo {com.vikkrithik.radio.indradio / com.vikkrithik.radio.indradio.AudioPlayerService} onServiceConnected invoked
当按下后退按钮时,应用程序转到后台
TabbarMainActivity(15432):完成调用
TabbarMainActivity(15432):onPause
AudioPlayerController(15432):unBindService done context => com.vikkrithik.radio.indradio.TabbarMainActivity@4150fdb8 serviceConnection => com.vikkrithik.radio.indradio.AudioPlayerController$1@418a2d30 onPause() calls unBindService()
AudioPlayerService(15432):onUnbind被调用 unBind Got invoked in Service
TabbarMainActivity(15432):onDestroy
App来到forground
TabbarMainActivity(15432):onCreate => Intent
TabbarMainActivity(15432):onResume bindService is called from onResume
AudioPlayerController(15432):bindService Context com.vikkrithik.radio.indradio.TabbarMainActivity@4150fdb8 serviceConnection => com.vikkrithik.radio.indradio.AudioPlayerController$1@418a2d30
播放停止后
AudioPlayerService(15432):停止
AudioPlayerService(15432):重置
AudioPlayerController(15432):stopAudioService完成
AudioPlayerFragment(15432):removeVisualizer
AudioPlayerService(15432):onDestory
3 回答
我无法“看到”这个问题,所以我创建了一个应用程序,它可以完成您需要的大部分工作,作为解决方案的基础 . 它不进行网络连接或使用真正的MediaPlayer,但该服务有一个后台线程,可以输出音频 . 您可以从两个按钮开始和停止音频 . 我能够点击后退按钮,并继续听到服务,然后从图标启动应用程序并停止并重新开始播放音频 . 我认为您可以按照我的步骤操作,如果它适用于您的设备,则开始将MediaPlayer和网络代码添加到功能服务中 .
我使用以下tutorial作为服务代码的基础,该服务代码使用消息而不是服务的Stub /接口 .
它基于Eclipse中的一个新的Android项目,然后我只添加了两个按钮并给它们新的文本和ID . 其余的在这里:
首先是我在MainActivity中添加的内容日食创造了:
接下来,Manifest文件的一个小插入:
最后是AudioPlayerService类的内容:
我看到一个应用程序的这些问题,该应用程序运行使用GPS记录车辆行程的服务 . 只需按一下按钮,服务就会启动并继续录制,如果需要,可以持续数小时 . 按下停止按钮后,服务终止 . 在录制期间,有一个界面可以传达UI上显示的某些实时数据,因此绑定/解除绑定可以处理由于轮换,后台/恢复应用程序等导致的中断/重新连接周期 .
只要服务运行就没有问题 . 但是,当我停止录制意味着我停止服务但继续维护与服务类的绑定/解除绑定解决方案时,会出现服务泄漏消息 . 我可能尝试做的是重新设计一些东西,以便我(1)只关心在服务运行时绑定unbind,或者(2)在应用程序生命周期内始终运行服务并添加方法告诉它开始或停止录制,让其在其他时间“空闲” . 也许(1)是要走的路,维护服务连接的方法也可能不是这种方式 .
为了能够重新绑定,请确保从
onUnbind
返回true,在这种情况下,当从Activity
调用bindService
时,将在Service
中调用onRebind
.Service.java