即使在调用onDestroy()之后,Android服务是否仍然存在? [英] Is the Android service still alive even after the onDestroy() be called?

查看:93
本文介绍了即使在调用onDestroy()之后,Android服务是否仍然存在?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了研究Android服务,我编写了一个测试程序,该程序在屏幕上具有三个按钮"bind service","unbind service"和"send echo".单击时,他们使用bindService()unbindService()Messenger与服务进行通信.

For studying the Android service, I wrote a test program that have three button "bind service", "unbind service" and "send echo" on the screen. When clicked, they use bindService(), unbindService() and a Messenger to communicate with the service.

以下是服务代码:

public class MessengerService extends Service {

private final Messenger mMessenger = new Messenger(new TempHandler());
private class TempHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
        case MSG_SAY_HELLO:
            Toast.makeText(getApplicationContext(), "Hi, there.", Toast.LENGTH_SHORT).show();
            break;

        case MSG_SAY_GOODBYE:
            Toast.makeText(getApplicationContext(), "See you next time.", Toast.LENGTH_SHORT).show();
            break;

        case MSG_ECHO:
            Toast.makeText(getApplicationContext(), "Received " + msg.arg1 + " from client.", Toast.LENGTH_SHORT).show();

            Messenger replyMessenger = msg.replyTo;
            Message replyMsg = Message.obtain(null, MSG_ECHO, msg.arg1, 0);
            try {
                replyMessenger.send(replyMsg);
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        default:
            super.handleMessage(msg);
        }
    }

}

@Override
public IBinder onBind(Intent intent) {
    Toast.makeText(getApplicationContext(), "Service bound", Toast.LENGTH_SHORT).show();
    return mMessenger.getBinder();
}

@Override
public void onDestroy() {
    Log.d("", "Service.onDestroy()...");
    super.onDestroy();
}
}

这是活动代码:

public class MessengerActivity extends Activity {
private Messenger mMessengerService;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity2);

    Button bind = (Button) findViewById(R.id.button5);
    bind.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            doBindService();
        }           
    });

    Button unbind = (Button) findViewById(R.id.button6);
    unbind.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            doUnbindService();
        }
    });

    Button echo = (Button) findViewById(R.id.button7);
    echo.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            doSendEcho();
        }
    });
}

private void doBindService() {
    Intent intent = new Intent(getApplicationContext(), MessengerService.class);
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

private void doUnbindService() {
    Message msg = Message.obtain(null, MessengerService.MSG_SAY_GOODBYE);
    try {
        mMessengerService.send(msg);
    } catch (RemoteException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    unbindService(mConnection);     
}

private void doSendEcho() {
    if (mMessengerService != null) {
        Message msg = Message.obtain(null, MessengerService.MSG_ECHO, 12345, 0);
        msg.replyTo = mMessenger;
        try {
            mMessengerService.send(msg);
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

private final Messenger mMessenger = new Messenger(new TempHandler());
private ServiceConnection mConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Toast.makeText(getApplicationContext(), "Service is connected.", Toast.LENGTH_SHORT).show();

        mMessengerService = new Messenger(service);

        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO);
        try {
            mMessengerService.send(msg);
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        mMessengerService = null;
        Toast.makeText(getApplicationContext(), "Service is disconnected.", Toast.LENGTH_SHORT).show();
    }

};

private class TempHandler extends Handler {

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
        case MessengerService.MSG_ECHO:
            Toast.makeText(getApplicationContext(), "Get the echo message (" + msg.arg1 + ")", Toast.LENGTH_SHORT).show();
            break;

        default:
            super.handleMessage(msg);
        }
    }

}
}

当我单击绑定服务"和发送回显"按钮时.我可以看到服务已连接并且消息通信良好.然后单击取消绑定服务",我看到该服务onDestroy()被调用,因此我希望该服务已停止并且不应再次响应即将出现的消息.但实际上是,该服务似乎仍然有效,单击发送回显"按钮后,我可以再次得到回显消息.所以我想知道我做错了什么吗?还是我对这项服务不完全了解?

When I click "bind service" and "send echo" button. I can see the service is connected and the message communication is good. And then click "unbind service", I saw the service onDestroy() be called, so I expect the service is stopped and should not respond to the coming message again. But actually is, the service seems still alive and I could get the echo message again when click the "send echo" button. So I'm wondering is there anything I made incorrect? Or maybe I'm not fully understand about the service?

希望有人可以提供帮助,谢谢.

Hope someone can help, thanks.

推荐答案

当应用程序组件通过调用bindService()绑定到服务时,该服务被绑定".绑定的服务提供了一个客户端-服务器接口,该接口允许组件与该服务进行交互,发送请求,获取结果,甚至跨进程间通信(IPC)进行交互. 绑定服务仅在绑定了另一个应用程序组件的情况下运行.

A service is "bound" when an application component binds to it by calling bindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it.

http://developer.android.com/guide/components/services.html

所有bindService()调用均具有相应的unbindService()调用后,服务将关闭.如果没有绑定的客户端,则当且仅当有人在该服务上调用了startService()时,该服务也将需要stopService().

A service will shut down after all bindService() calls have had their corresponding unbindService() calls. If there are no bound clients, then the service will also need stopService() if and only if somebody called startService() on the service.

从下面的链接中绘制.

如何检查服务是否在Android上运行?

private void doSendEcho() {
    if(isMyServiceRunning()) // if service is running
    {
    if (mMessengerService != null) {
        Message msg = Message.obtain(null, MessengerService.MSG_ECHO, 12345, 0);
        msg.replyTo = mMessenger;
        try {
            mMessengerService.send(msg);
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    }
}
private boolean isMyServiceRunning() {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (MessengerService.class.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

@Override
protected void onStop() {
super.onStop();
// Unbind from the service
    unbindService(mConnection);
    Log.i("Stopped!",""+isMyServiceRunning()); 
    Log.i("stopped", "Service Stopped");    
 }

示例:

我在下面测试了一下,效果很好.

I tested the below it works fine.

public class MessengerService extends Service {

    public static final int MSG_SAY_HELLO =1;
    public static final int MSG_SAY_GOODBYE =2;

      ArrayList<Messenger> mClients = new ArrayList<Messenger>();

private final Messenger mMessenger = new Messenger(new TempHandler());
private class TempHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
        case MSG_SAY_HELLO:
            mClients.add(msg.replyTo);
            Toast.makeText(getApplicationContext(), "Hi, there.", Toast.LENGTH_SHORT).show();
            break;

        case MSG_SAY_GOODBYE:
            mClients.add(msg.replyTo);

            break;

        default:
            super.handleMessage(msg);
        }
    }

}

@Override
public IBinder onBind(Intent intent) {
    Toast.makeText(getApplicationContext(), "Service bound", Toast.LENGTH_SHORT).show();
    return mMessenger.getBinder();
}

@Override
public void onDestroy() {
    Log.i("MessengerService", "Service Destroyed...");
    super.onDestroy();
}
}

MainAactivity.java

MainAactivity.java

public class MainActivity extends Activity {

boolean mIsBound=false;
Messenger mService = null;
private boolean isMyServiceRunning() {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (MessengerService.class.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button bind = (Button) findViewById(R.id.button1);
    bind.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            doBindService();
        }           
    });

    Button unbind = (Button) findViewById(R.id.button2);
    unbind.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            doUnbindService();
        }
    });
}

class TempHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MessengerService.MSG_SAY_GOODBYE:
                Toast.makeText(MainActivity.this,"Received from service: " + msg.arg1,1000).show();
                break;
            default:
                super.handleMessage(msg);
        }
    }
}

/**
 * Target we publish for clients to send messages to IncomingHandler.
 */
final Messenger mMessenger = new Messenger(new TempHandler());

/**
 * Class for interacting with the main interface of the service.
 */
private ServiceConnection mConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className,
            IBinder service) {
        // This is called when the connection with the service has been
        // established, giving us the service object we can use to
        // interact with the service.  We are communicating with our
        // service through an IDL interface, so get a client-side
        // representation of that from the raw service object.
        mService = new Messenger(service);
      //  mCallbackText.setText("Attached.");

        // We want to monitor the service for as long as we are
        // connected to it.
        try {
            Message msg = Message.obtain(null,
                    MessengerService.MSG_SAY_HELLO);
            msg.replyTo = mMessenger;
            mService.send(msg);

            // Give it some value as an example.
//            msg = Message.obtain(null,
//                    MessengerService.MSG_E, this.hashCode(), 0);
//            mService.send(msg);
        } catch (RemoteException e) {
            // In this case the service has crashed before we could even
            // do anything with it; we can count on soon being
            // disconnected (and then reconnected if it can be restarted)
            // so there is no need to do anything here.
        }

        // As part of the sample, tell the user what happened.
        Toast.makeText(MainActivity.this, "remote_service_connected",
                Toast.LENGTH_SHORT).show();
    }

    public void onServiceDisconnected(ComponentName className) {
        // This is called when the connection with the service has been
        // unexpectedly disconnected -- that is, its process crashed.
        mService = null;
       // mCallbackText.setText("Disconnected.");

        // As part of the sample, tell the" user what happened.
        Toast.makeText(MainActivity.this, "remote_service_disconnected",
                Toast.LENGTH_SHORT).show();
    }
};



void doBindService() {
    // Establish a connection with the service.  We use an explicit
    // class name because there is no reason to be able to let other
    // applications replace our component.
    bindService(new Intent(MainActivity.this, 
            MessengerService.class), mConnection, Context.BIND_AUTO_CREATE);
    mIsBound=true;
    Toast.makeText(MainActivity.this, "Binding",1000).show();
}

void doUnbindService() {
    if (mIsBound) {
        // If we have received the service, and hence registered with
        // it, then now is the time to unregister.
        if (mService != null) {
            try {
                Message msg = Message.obtain(null,
                        MessengerService.MSG_SAY_GOODBYE);
                msg.replyTo = mMessenger;
                mService.send(msg);
            } catch (RemoteException e) {
                // There is nothing special we need to do if the service
                // has crashed.
            }
        }

        // Detach our existing connection.
        unbindService(mConnection);
        mIsBound = false;
       Toast.makeText(MainActivity.this, "UnBinding"+isMyServiceRunning(),1000).show();

    }
}
}

这篇关于即使在调用onDestroy()之后,Android服务是否仍然存在?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆