我是android平台的新手。当前正在开发流广播应用程序。
我要制作应用程序,开始音频播放并连续播放,即使应用程序进入后台。
我已经使用startService()创建了Service,因此即使应用程序进入后台,回放仍将继续。我还使用bindService()获取serviceConnection引用,以对服务执行RPC调用。
应用程序启动服务并正确开始播放,bindService能够获取引用并能够进行RPC调用,直到应用程序进入后台,一切正常。
我在主要活动的onResume()和onPause()中调用bindService()和unBindService()调用。
当应用程序进入后台运行时,继续播放不会出现任何问题。 unBindservice()调用分离了服务连接,并且在Service类中调用了onUnbind(Intent)方法。到目前为止没有问题。
当应用程序出现在前台(服务正在运行且播放继续)时,
即使没有在活动onResume()方法中调用bindService(),我也没有获得服务连接参考(onServiceConnected()未被调用)。我还验证了Service类的onBind(Intent)方法也没有被调用。
在过去的几天里,我一直在努力解决这个问题。
推荐的方法是将startService()和bindService()与用户定义的Android Service一起使用。
对解决此问题的任何帮助,深表感谢。
活动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();
}
控制器类具有与服务相关的启动/停止/绑定/取消绑定方法
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输出
应用启动时
TabbarMainActivity(15432):onResume
AudioPlayerController(15432):bindService上下文com.vikkrithik.radio.indradio.TabbarMainActivity@4150fdb8 serviceConnection => com.vikkrithik.radio.indradio.AudioPlayerController$1@418a2d30
当按下播放按钮时
AudioPlayerController(15432):bindService上下文com.vikkrithik.radio.indradio.TabbarMainActivity@4150fdb8 serviceConnection => com.vikkrithik.radio.indradio.AudioPlayerController$1@418a2d30
AudioPlayerController(15432):调用了startService
AudioPlayerService(15432):onCreate
AudioPlayerService(15432):调用onBind调用onBind()
AudioPlayerService(15432):带有IndetntIntent {cmp = xxxx(有其他功能)的onStartCommand}
AudioPlayerController(15432):onServiceConnected ComponentInfo {com.vikkrithik.radio.indradio / com.vikkrithik.radio.indradio.AudioPlayerService} onServiceConnected调用
当按下后退按钮时,应用程序进入后台
TabbarMainActivity(15432):完成调用
TabbarMainActivity(15432):onPause
AudioPlayerController(15432):unBindService完成上下文=> com.vikkrithik.radio.indradio.TabbarMainActivity@4150fdb8 serviceConnection => com.vikkrithik.radio.indradio.AudioPlayerController$1@418a2d30 onPause()调用unBindService()
AudioPlayerService(15432):在服务中调用了onUnbind和unBind
TabbarMainActivity(15432):onDestroy
应用程序登场
TabbarMainActivity(15432):onCreate => Intent {cmp = xxxx}
TabbarMainActivity(15432):从onResume调用onResume bindService
AudioPlayerController(15432):bindService上下文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
最佳答案
我不能仅仅“看到”问题,所以我创建了一个应用程序,该应用程序可以解决您需要做的大部分事情。它不进行网络连接或使用真正的MediaPlayer,但是该服务具有一个后台线程,可以输出音频。您可以通过两个按钮启动和停止音频。我能够按下后退按钮,继续收听服务,然后从图标启动应用程序,然后停止并重新开始播放音频。我认为您可以按照我的步骤进行操作,如果它可以与您的设备一起使用,则可以开始将MediaPlayer和网络代码添加到功能服务中。
我使用以下tutorial作为服务代码的基础,该服务代码使用消息而不是服务的Stub /接口。
它基于Eclipse中的一个新Android项目,然后我只添加了两个按钮,并给了他们新的文本和ID。其余的在这里:
首先,我输入eclipse创建的MainActivity的内容:
private final static String TAG = "MainActivity";
// Service stuff
Messenger myService = null;
boolean isBound;
private Button startBut;
private Button stopBut;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startBut = (Button) findViewById(R.id.startAudio);
startBut.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
try
{
if (myService != null && isBound)
{
Log.d(TAG, "Service Connected! sending start request");
Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("MyString", "start");
msg.setData(bundle);
myService.send(msg);
}
}
catch (Throwable th)
{
Log.d(TAG, "error sending start", th);
}
}
});
stopBut = (Button) findViewById(R.id.stopAudio);
stopBut.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
try
{
Log.d(TAG, "Service Connected! sending stop request");
Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("MyString", "stop");
msg.setData(bundle);
myService.send(msg);
}
catch (Throwable th)
{
Log.d(TAG, "error sending start", th);
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
protected void onPause()
{
super.onPause();
unBindService();
}
@Override
protected void onResume()
{
super.onResume();
Log.d(TAG, "Resuming: binding to service");
Intent intent = new Intent("com.example.audioservice.AudioPlayerService");
// Start the service ourselves because we don't want it to stop when the activity/application does.
startService(intent);
bindService(intent, myConnection, 0);
}
private ServiceConnection myConnection = new ServiceConnection()
{
public void onServiceConnected(ComponentName className, IBinder service) {
myService = new Messenger(service);
isBound = true;
Log.d(TAG, "Service Connected!");
}
public void onServiceDisconnected(ComponentName className) {
myService = null;
isBound = false;
}
};
public void unBindService()
{
this.unbindService(myConnection);
Log.d(TAG, "unBindService done context => "
+ " serviceConnection => " + myConnection);
}
接下来,在清单文件中插入一个小片段:
<service android:enabled="true" android:name="com.example.audioservice.AudioPlayerService"
android:process=":my_process" >
<intent-filter>
<action android:name="com.example.audioservice.AudioPlayerService" >
</action>
</intent-filter>
</service>
最后是AudioPlayerService类的内容:
public class AudioPlayerService extends Service
{
private static final String TAG = "AudioPlayerService";
AudioManager audioManager;
private boolean playing = false;
private Player player;
class IncomingHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
Bundle data = msg.getData();
String dataString = data.getString("MyString");
if ("start".equalsIgnoreCase(dataString))
{
Log.d(TAG, "Got a start request");
// Start playing
playing = true;
}
else if ("stop".equalsIgnoreCase(dataString))
{
Log.d(TAG, "Got a stop request");
// Stop playing
playing = false;
}
}
}
@SuppressLint("HandlerLeak")
final Messenger myMessenger = new Messenger(new IncomingHandler());
@Override
public IBinder onBind(Intent arg0)
{
Log.d(TAG, "onBind invoked");
return myMessenger.getBinder();
}
@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);
audioManager.loadSoundEffects();
player = new Player();
player.start();
}
@Override
public void onDestroy()
{
Log.d(TAG, "onDestory");
stopPlayback();
super.onDestroy();
}
private void stopPlayback()
{
playing = false;
}
// Pointless Thread to let us know the service is still doing its thing
class Player extends Thread
{
public void run()
{
int x = 7;
while (1 < x)
{
try
{
if (playing)
{
Thread.sleep(10000);
Log.d(TAG, ".");
audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
}
}
catch (Throwable th)
{
Log.d(TAG, "error in Player", th);
}
}
}
}
}
关于android - Android服务-与startService一起使用时BindService出现问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15106805/