Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从活动到服务的连接时间过长_Java_Android - Fatal编程技术网

Java 从活动到服务的连接时间过长

Java 从活动到服务的连接时间过长,java,android,Java,Android,我目前正在开发一款音乐播放器,因为每次手机上的方向发生变化,活动被重新创建时,我都希望通过服务播放音乐。这样,用户就可以在不停止音乐的情况下离开活动。。 现在。。我有一个奇怪的问题我无法解决。。。每次我创建活动并膨胀GUI时,服务都会启动。但服务总是在活动发送数据后被绑定。。。所以音乐永远不会开始。。。我知道会发生这种情况,因为如果我添加一个按钮来重新发送数据,音乐就会开始播放。。。以下是我的活动代码: public class Player extends Activity{ private

我目前正在开发一款音乐播放器,因为每次手机上的方向发生变化,活动被重新创建时,我都希望通过服务播放音乐。这样,用户就可以在不停止音乐的情况下离开活动。。 现在。。我有一个奇怪的问题我无法解决。。。每次我创建活动并膨胀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();
}
}

瞧!它起作用了!:我希望它对某人有用

您需要做的是移动onCreate()中的代码,这取决于ServiceConnection实现中OnServiceConnection()方法可用的服务:

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=newmessenger(service)。您的IBinder实例应该为您提供获取对您的服务实例的引用的机制

我不认为你的解决方案实际上是在解决问题。这是一种恰巧奏效的黑客行为。请参阅下面我的答案,了解如何通过在服务生命周期的正确点调用代码来正确地使其工作。但问题是,我需要根据要播放的音乐发送不同类型的数据,如果只发送一次数据就太完美了。。。此外,如果屏幕中的方向发生变化,则会重新建立连接。。这意味着服务将再次接收数据…关于我的实现,真相是。。。我没有太多的经验和他们,我创造了我的代码从许多其他人。。。有没有办法让它更有效率?也许你需要考虑一个比你的活动寿命更长的服务。从服务解除绑定并不一定会停止服务。当我不知道你的应用程序要实现什么样的功能时,很难更精确地给出如何最好地优化事情的想法。但是,您的“解决方案”可能会导致偶尔发生难以追踪的车祸。我强烈建议您熟悉服务生命周期,以便更好地了解如何有效地使用服务。嗯。。。也许你就是不明白我的密码。。。事实上,当活动被销毁或停止时,它只会从服务中解除绑定。。。只要有音乐播放,使用寿命就会延长。。。我一直在深思熟虑地测试它,没有遇到任何类型的崩溃。。。不管怎样,在这期间,它起作用了。。。我只需要完成其他功能的实现,一旦完成,我将寻求更好的解决方案。。。谢谢你的建议:D
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();
    }
};