从活动到服务的连接花费的时间太长

时间:2011-06-07 05:32:06

标签: java android

我目前正在开发音乐播放器,并且由于每次在电话上更改方向并重新创建活动时,我希望音乐由服务播放。这样,用户就可以在没有音乐停止的情况下离开活动。 现在..我有这个奇怪的问题,我一直无法解决......每次我创建活动并给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希望它对某人有用!

1 个答案:

答案 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实例应为您提供获取服务实例引用的机制。