我目前正在开发音乐播放器,并且由于每次在电话上更改方向并重新创建活动时,我希望音乐由服务播放。这样,用户就可以在没有音乐停止的情况下离开活动。 现在..我有这个奇怪的问题,我一直无法解决......每次我创建活动并给GUI充气时,服务就会启动。但是,在活动发送数据之后,服务总是受限...所以音乐永远不会开始...我知道这是因为如果我添加一个按钮来重新发送数据,音乐就会开始播放......这是我的代码对于活动:
public class Player extends Activity{
private Cursor audioCursor;
public static int position=0;
private int count;
private boolean pause = false,
play= false,
stop= false,
next= false,
back= false,
playerActive= true,
dataChanged= false,
finished= false,
playing= true;
private String action;
Messenger mService = null;
boolean mIsBound;
final Messenger mMessenger = new Messenger(new IncomingHandler());
private ServiceConnection mConnection=null;
static final int MSG_SET_BOOLEAN_VALUE = 5;
static final int MSG_SET_STRING_VALUE = 4;
static final int MSG_SET_INT_VALUE = 3;
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.player);
Bundle extras = getIntent().getExtras();
action=extras.getString("action");
if(!(Background.isRunning()))
startService(new Intent(Player.this, Background.class));
doBindService();
if(action.equals("play")){
position=extras.getInt("position");
String[] proj = {
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.IS_MUSIC,
MediaStore.Audio.Media.ALBUM_ID};
audioCursor = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj,
MediaStore.Audio.Media.IS_MUSIC, null,
MediaStore.Audio.Media.TITLE + " ASC");
startManagingCursor(audioCursor);
count = audioCursor.getCount();
inflatePlayer();
/////////////////////THIS IS THE CODE THAT ACTS BEFORE THE SERVICE CONNECTION
sendBoolToService(playerActive, "playerActive");
sendIntToService(position);
sendStringToService(action);
}
}
//THIS CODE MUST BE FASTER, BUT THE CONNECTION TAKES TOO LONG
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
Toast.makeText(getApplicationContext(), "ATTACHED!", Toast.LENGTH_LONG).show();
try {
Message msg = Message.obtain(null, Background.MSG_REGISTER_CLIENT);
msg.replyTo = mMessenger;
mService.send(msg);
} catch (RemoteException e) {
Toast.makeText(getApplicationContext(), "Connection failed!", Toast.LENGTH_LONG).show();
}
}
public void onServiceDisconnected(ComponentName className) {
mService = null;
Toast.makeText(getApplicationContext(), "UNATTACHED!", Toast.LENGTH_LONG).show();
}
};
private void inflatePlayer(){
//LOTS OF CODE FOR THE GUI, NOTHING TO DO WITH THE SERVICE... SO I OMITTED IT
}
@Override
protected void onStop(){
playerActive=false;
try {
doUnbindService();
} catch (Throwable t) {
}
if(!playing)
stopService(new Intent(Player.this, Background.class));
super.onStop();
}
@Override
protected void onDestroy(){
playerActive=false;
audioCursor.close();
try {
doUnbindService();
} catch (Throwable t) {
}
if(!playing)
stopService(new Intent(Player.this, Background.class));
super.onDestroy();
}
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SET_INT_VALUE:
String str = Integer.toString(msg.getData().getInt("int1"));
Toast.makeText(getApplicationContext(), "Int Message: " + str, Toast.LENGTH_LONG).show();
break;
case MSG_SET_STRING_VALUE:
String str1 = msg.getData().getString("str1");
break;
case MSG_SET_BOOLEAN_VALUE:
dataChanged=msg.getData().getBoolean("dataChanged");
finished=msg.getData().getBoolean("finished");
playing=msg.getData().getBoolean("playing");
if(!playing){
if(finished){
finished=false;
finish();
}
}
default:
super.handleMessage(msg);
}
}
}
private void sendIntToService(int intvaluetosend) {
if (mService != null) {
try {
Bundle b = new Bundle();
b.putInt("int1", intvaluetosend);
Message msg = Message.obtain(null, MSG_SET_INT_VALUE);
msg.setData(b);
mService.send(msg);
} catch (RemoteException e) {
}
}
}
private void sendStringToService(String stringtosend) {
if (mService != null) {
try {
Bundle b = new Bundle();
b.putString("str1", stringtosend);
Message msg = Message.obtain(null, MSG_SET_STRING_VALUE);
msg.setData(b);
mService.send(msg);
} catch (RemoteException e) {
}
}
}
private void sendBoolToService(boolean booltosend, String name) {
if (mService != null) {
try {
Bundle b = new Bundle();
b.putBoolean(name, booltosend);
Message msg = Message.obtain(null, MSG_SET_BOOLEAN_VALUE);
msg.setData(b);
mService.send(msg);
} catch (RemoteException e) {
}
}
}
void doBindService() {
bindService(new Intent(this, Background.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
Toast.makeText(getApplicationContext(), "BOUND!", Toast.LENGTH_LONG).show();
}
void doUnbindService() {
if (mIsBound) {
if (mService != null) {
try {
Message msg = Message.obtain(null, Background.MSG_UNREGISTER_CLIENT);
msg.replyTo = mMessenger;
mService.send(msg);
} catch (RemoteException e) {
}
}
unbindService(mConnection);
mIsBound = false;
Toast.makeText(getApplicationContext(), "UNBOUND!", Toast.LENGTH_LONG).show();
}
}
}
服务:
public class Background extends Service {
private NotificationManager nm;
private Cursor audioCursor;
MediaPlayer mp = new MediaPlayer();
private int count;
private boolean pause = false,
play= false,
stop= false,
next= false,
back= false,
playerActive= true,
dataChanged= false,
finished= false,
playing= false;
private int position;
private String action;
ArrayList<Messenger> mClients = new ArrayList<Messenger>();
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
static final int MSG_SET_INT_VALUE = 3;
static final int MSG_SET_STRING_VALUE = 4;
static final int MSG_SET_BOOLEAN_VALUE = 5;
final Messenger mMessenger = new Messenger(new IncomingHandler());
private static boolean isRunning = false;
private static final String TAG = "Background";
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
break;
case MSG_SET_INT_VALUE:
position=msg.getData().getInt("int1");
break;
case MSG_SET_STRING_VALUE:
action=msg.getData().getString("str1");
if(action.equals("play")){
String[] proj = { MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.IS_MUSIC,
MediaStore.Audio.Media.TITLE};
audioCursor = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj,
MediaStore.Audio.Media.IS_MUSIC, null,
MediaStore.Audio.Media.TITLE + " ASC");
count = audioCursor.getCount();
audioCursor.moveToPosition(position);
int column_index = audioCursor.getColumnIndex(MediaStore.Audio.Media.DATA);
String path = audioCursor.getString(column_index);
startAudioPlayer(path);
playing=true;
if(playerActive)
sendBool(playing, "playing");
}else{
startAudioPlayer(action);
playing=true;
if(playerActive)
sendBool(playing, "playing");
}
action=null;
break;
case MSG_SET_BOOLEAN_VALUE:
pause=msg.getData().getBoolean("pause");
play=msg.getData().getBoolean("play");
stop=msg.getData().getBoolean("stop");
next=msg.getData().getBoolean("next");
back=msg.getData().getBoolean("back");
playerActive=msg.getData().getBoolean("playerActive");
if(pause){
mp.pause();
play=false;
playing=false;
sendBool(playing, "playing");
pause=false;
}
if(play){
pause=false;
mp.start();
playing=true;
sendBool(playing, "playing");
play=false;
}
default:
super.handleMessage(msg);
}
}
}
private void sendInt(int intvaluetosend) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
Bundle b = new Bundle();
b.putInt("int1", intvaluetosend);
Message msg = Message.obtain(null, MSG_SET_INT_VALUE);
msg.setData(b);
mClients.get(i).send(msg);
} catch (RemoteException e) {
mClients.remove(i);
Log.d(TAG, "Int not send..."+e.getMessage());
}
}
}
private void sendString(String stringtosend) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
Bundle b = new Bundle();
b.putString("str1", stringtosend);
Message msg = Message.obtain(null, MSG_SET_STRING_VALUE);
msg.setData(b);
mClients.get(i).send(msg);
} catch (RemoteException e) {
mClients.remove(i);
Log.d(TAG, "String not send..." +e.getMessage());
}
}
}
private void sendBool(boolean booltosend, String name) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
Bundle b = new Bundle();
b.putBoolean(name, booltosend);
Message msg = Message.obtain(null, MSG_SET_BOOLEAN_VALUE);
msg.setData(b);
mClients.get(i).send(msg);
} catch (RemoteException e) {
mClients.remove(i);
Log.d(TAG, "Bool not send..." +e.getMessage());
}
}
}
@Override
public void onCreate() {
super.onCreate();
showNotification();
isRunning=true;
}
private void showNotification() {
nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
CharSequence text = getText(R.string.maintit);
Notification notification = new Notification(R.drawable.icon, text, System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Player.class), 0);
notification.setLatestEventInfo(this, getText(R.string.app_name), text, contentIntent);
nm.notify(R.string.app_name, notification);
}
@Override
public void onDestroy() {
//REMEMBER TO SAVE DATA!
if(mp.isPlaying())
mp.stop();
mp.release();
isRunning=false;
audioCursor.close();
nm.cancel(R.string.app_name);
super.onDestroy();
}
public static boolean isRunning()
{
return isRunning;
}
public void startAudioPlayer(String path){
try {
if(mp.isPlaying())
mp.reset();
mp.setDataSource(path);
} catch (IllegalArgumentException e) {
e.printStackTrace();
Log.d(TAG,e.getMessage());
} catch (IllegalStateException e) {
e.printStackTrace();
Log.d(TAG,e.getMessage());
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG,e.getMessage());
}
try {
mp.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
Log.d(TAG,e.getMessage());
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG,e.getMessage());
}
mp.start();
}
}
我希望有人可以提供帮助,我对此感到非常沮丧!此外,我非常确定媒体播放器没有问题,我之前没有服务测试过...游标也正常工作......事情是......我需要从GUI调用服务吗?播放音乐?我做错了什么?
编辑:网站不允许我回答我自己的问题,所以我在这里发布解决方案: 好的,终于找到了解决方案! 我读到只有onCreate方法完成后才能与服务进行交互...所以,我添加了一个Timer并用我需要运行的方法填充它:new Timer().schedule(new TimerTask(){
public void run(){
sendBoolToService(playerActive, "playerActive");
sendIntToService(position);
sendStringToService(action);
}
}, 1000);
AND VOILA!有用! :D希望它对某人有用!
答案 0 :(得分:0)
您需要做的是移动onCreate()中的代码,该代码取决于ServiceConnection实现中的onServiceConnected()方法可用的服务:
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
Toast.makeText(getApplicationContext(), "ATTACHED!", Toast.LENGTH_LONG).show();
try {
Message msg = Message.obtain(null, Background.MSG_REGISTER_CLIENT);
msg.replyTo = mMessenger;
mService.send(msg);
sendBoolToService(playerActive, "playerActive");
sendIntToService(position);
sendStringToService(action);
} catch (RemoteException e) {
Toast.makeText(getApplicationContext(), "Connection failed!", Toast.LENGTH_LONG).show();
}
}
public void onServiceDisconnected(ComponentName className) {
mService = null;
Toast.makeText(getApplicationContext(), "UNATTACHED!", Toast.LENGTH_LONG).show();
}
};
我还会查看您的服务实现,因为我无法理解为什么要调用mService = new Messenger(service)。您的IBinder实例应为您提供获取服务实例引用的机制。