Android ::在销毁活动后保持网络连接活跃

时间:2012-12-10 23:39:55

标签: java android

I am trying to create a service that manages my network communication on my app but everytime I destroy my activity my server crashes and I believe this is I am still waiting to receive on the server end. 
My understanding of the service is it runs until you stop it so I feel my channel should be open until I close. I know it'd take a lot of battery life but, I'm trying to understand the concept of the service very well before I optimize my battery life. Here is what I have



    public class SampleService extends Service {
        public final static String TAG = SampleService.class.getName();
        private HandlerThread nThread;
        private NetworkHandler nHandler;
        private Looper nLooper;
        private Socket socket;
        private ObjectInputStream is;
        private ObjectOutputStream os;
        .......
            .........
        @Override
        public void onCreate()
        {
            Log.i(TAG, "onCreate(); Sample Created");
            new Thread(new Runnable()
            {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        socket = new Socket("192.168.1.185", 6060);
                        os = new ObjectOutputStream(new DataOutputStream(socket.getOutputStream()));
                        is = new ObjectInputStream(new DataInputStream(socket.getInputStream()));
                    } catch (UnknownHostException e) {
                        // TODO Auto-generated catch block
                        Log.e(TAG, "onCreate(): UnknownHostException error", e);
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        Log.e(TAG, "onCreate(): IOException error", e);
                    }
                }

            }).start();
            nThread = new HandlerThread("Network Thread", Process.THREAD_PRIORITY_BACKGROUND);
            nThread.start();
            nLooper = nThread.getLooper();
            nHandler = new NetworkHandler(nLooper);
            Log.i(TAG, "onCreate(); Service setup");
        }

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Toast.makeText(this, "Service started "+ startId, Toast.LENGTH_SHORT).show();
            // We want this service to continue running until it is explicitly
            // stopped, so return sticky.
            return START_STICKY;
        }

        @Override
        public void onDestroy() {

            Toast.makeText(this,"Service Destroyed", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "onCreate(); Sample Destroyed");
        }

And Activity





      public class ServiceActivity extends Activity {
            Intent service;

            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_service);
                service = new Intent(this, SampleService.class);
                startService(service);
            }

            ........
    ........
            }

I don't really have much added there just this...





    public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.activity_service, menu);
            return true;
        }

        @Override
        public void onPause()
        {
            super.onPause();
    //      stopService(service);
        }



I decided to add my server to make things clear...



public class CloudServer{
    private ServerSocket serverSocket;
    private List<Socket>clientSockets;

    public static final String TAG = CloudServer.class.getName();

    public CloudServer(int port) throws IOException
    {
        serverSocket = new ServerSocket(port);
        clientSockets = new ArrayList<Socket>();

        System.out.println("Listening to clients on port "+ port);
        for(;;) // infinite loop
        {
            Socket s;
            String id = generateSessionId();
            clientSockets.add(s = serverSocket.accept());
            System.out.println("Connection was established");
            if(sessionId.size() > 0)
            {
                Set<String>ids = sessionId.keySet();
                for(String session: ids)
                {
                    while(id.equals(session))
                        id = generateSessionId();

                }
            }
            sessionId.put(id, s);
            new Thread(new Worker(s, id)).start();
        }
........
    }



    public static void main(String [] args) throws IOException, ClassNotFoundException, SQLException
    {

        new CloudServer(6060);
    }


.........
}

这是服务器的工作者

package com.dcloud.server.service;

import java.io.IOException;
import java.io.ObjectInputStream;

public class Worker implements Runnable{
    private Socket socket;
    private ObjectInputStream is;
    private ObjectOutputStream os;
    private boolean running;
    public static final String TAG = Worker.class.getName();
    private Message in;

    private String sessionId;
    public Worker(Socket s, String id) throws IOException
    {
        this.socket = s;
        os = new ObjectOutputStream(socket.getOutputStream());
        is = new ObjectInputStream(socket.getInputStream());
        sessionId = id;
        running = true;
    }

    public String getSessionId()
    {
        return sessionId;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(running)
        {
            try {

                while((in = (Message) is.readObject())!= null){
                    if(in.getRequest() == Event.Request.REGISTER)
                    {
                        //debugging purposes
                        CloudServer.writeToFile(TAG + ": got into the Register request");
                        new Thread(new Runnable()
                        {
                            @Override
                            public void run() {
                                // TODO Auto-generated method stub

                                try {
                                    String message = in.getMessage(); 
                                    registerUser(message);
                                } catch (ParserConfigurationException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                } catch (SAXException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                } catch (IOException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                } catch (SQLException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            }
                        }).start();
                    }

                    else if(in.getRequest() == Event.Request.LOGIN)
                    {
                        CloudServer.writeToFile(TAG + ": got into the login request");
                        new Thread(new Runnable()
                        {
                            @Override
                            public void run() {
                                // TODO Auto-generated method stub

                                try {
                                    String message = in.getMessage();
                                    handleLogin(message);
                                } catch (ParserConfigurationException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                } catch (SAXException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                } catch (IOException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                } catch (SQLException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            }
                        }).start();
                    }

                    else if(in.getRequest() == Event.Request.DISCONNECT)
                    {
                        running = false;
                        break;
                    }
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        try {
            is.close();
            os.close();
            socket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

........
.......
//  I don't think this affects anything...

}

我得到和IO异常及其因为while((in = is.readObject)!= null)行 这表明我的应用程序试图在销毁活动时突破连接。这就是我如何解释它,但根据Android网站上的服务文档,该服务应该是活着的,直到我自己明确地停止它...

java.io.EOFException
    at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at com.dcloud.server.service.Worker.run(Worker.java:56)
    at java.lang.Thread.run(Unknown Source)

1 个答案:

答案 0 :(得分:0)

如果手机进入睡眠状态(屏幕变暗),则无法建立网络连接。如果您想保持联系,您需要通过获取WakeLock来防止手机睡眠。这当然会带来使用电池的惩罚,因此您应该在完成网络操作后立即将其释放。

相关问题