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 Exception and Its 因为 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)