I made code that download APK from ftp, and I`m trying to install it after download. I wrote this for Honeycomb, so in every connection i have to use threads. How can I use startActivity in class within thread, or wait for thread to finish?
public class FTPapkDowload {
protected static final String TAG = "Tablet Development";
public FTPClient mFTPClient = null;
public FTPClient mFtp = null;
public void Start() {
Thread apkdowload = new Thread(new Runnable() {
#Override
public void run() {
ftpConnect("mysite", "username", "password",21);
Log.d(TAG, "Connected");
ftpDownload("/httpdocs/Shamir/app.apk", "sdcard/Download/app.apk");
ftpDisconnect();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/Download/" + "app.apk")), "application/vnd.android.package-archive");
startActivity(intent); //Here is the problem
}
//Connection
public boolean ftpConnect(String host, String username,
String password, int port) {
try {
mFTPClient = new FTPClient();
mFTPClient.connect(host, port);
if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {
boolean status = mFTPClient.login(username, password);
mFTPClient.setFileType(FTP.BINARY_FILE_TYPE);
mFTPClient.enterLocalPassiveMode();
return status;
}
} catch (Exception e) {
Log.d(TAG, "Error: could not connect to host " + host);
}
return false;
}
//Downloading
public boolean ftpDownload(String srcFilePath, String desFilePath) {
boolean status = false;
try {
FileOutputStream desFileStream = new FileOutputStream(
desFilePath);
status = mFTPClient
.retrieveFile(srcFilePath, desFileStream);
desFileStream.close();
return status;
} catch (Exception e) {
Log.d(TAG, "download failed");
}
return status;
}
public boolean ftpDisconnect() {
try {
mFTPClient.logout();
mFTPClient.disconnect();
Log.d(TAG, "Disconected from FTP on apk Download");
return true;
} catch (Exception e) {
Log.d(TAG,"Error occurred while disconnecting from ftp server on apk download.");
}
return false;
}
});
apkdowload.start();
}
}
You can use a handler:
private Handler handler = new Handler(){
public void handleMessage(Message msg)
{
}
};
When your thread is done running the code it needs to call: handler.sendEmptyMessage(0);
More info: http://developer.android.com/reference/android/os/Handler.html
The cleanest way to do this is for your FTP download code to notify your main thread that it has finished, and make the main (UI) thread call startActivity. You can do this using any number of methods for communication between threads, for example a Handler:
http://developer.android.com/reference/android/os/Handler.html
Or simply Activity.runOnUiThread:
http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
A good read is the "Painless Threading" blog post:
http://android-developers.blogspot.com/2009/05/painless-threading.html
I guess you need to pass context of your activity to the class in which you want to use activity's methods.
To execute UI methods you have run this on UI Thread:
Put this inside your normal Threads run() Method:
YourClass.this.runOnUiThread(new Runnable() {
#Override
public void run() {
startyourActivity();
}
});
Related
I am creating an android application in which i am creating socket connection in one activity and using Shared Preferences and in another activity I am fetching the socket variables to do furthur jobs but its not working as i am expected
My question is how can i use my exixting socket connection in different actvities i have searched about it Got some terms like singltone class,Aysnc task, But i am not getting it,if singltone is proper way to use socket connetion in different activities then How can i use singlton class in following code please suggest me changes...!!!
Otherwise is it proper way am i doing Shared PRef as following??also suggest some changes!!!
UPDATE: Tagged singlton for suggestions
So here is First Activity
public class ipInfo extends AppCompatActivity {
EditText ipaddress;
String IPADD;
Integer PORT=null;
EditText portnum;
Button connect_btn;
StrictMode.ThreadPolicy policy;
Socket cs = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ipinfo);
policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
ipaddress = (EditText)findViewById(R.id.editText);
portnum = (EditText)findViewById(R.id.editText2);
connect_btn =(Button)findViewById(R.id.button);
ip_check();
}
public void ip_check(){
connect_btn.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
IPADD=ipaddress.getText().toString();
PORT=Integer.parseInt(portnum.getText().toString());
try { cs = new Socket();
cs.connect(new InetSocketAddress(IPADD, PORT), 2000);
SharedPreferences sharedPreferences = getSharedPreferences("ipstore", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("ipadd",IPADD);
editor.putInt("port",PORT);
editor.commit();
if(cs.isConnected()) {
Toast.makeText(ipInfo.this, "Connected", Toast.LENGTH_SHORT).show();
Intent inst = new Intent(ipInfo.this,homeActivity.class);
startActivity(inst);
finish();
}
}catch (IOException e)
{Toast.makeText(ipInfo.this,"Server is disconnected\n",Toast.LENGTH_SHORT).show();
}catch (Exception e)
{Toast.makeText(ipInfo.this,e.getMessage(),Toast.LENGTH_SHORT).show();}
}
}
);
}
}
from this activity am fetching values in following activity
public class PowerActivity extends AppCompatActivity {
Button restart,shutdown,logof,sleep,abort;
StrictMode.ThreadPolicy policy;
Socket cs = null;
DataOutputStream out=null;
String SERVERIP;
int PORT;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_power);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
restart = (Button)findViewById(R.id.restart);
shutdown = (Button)findViewById(R.id.shutdown);
logof = (Button)findViewById(R.id.logof);
sleep = (Button)findViewById(R.id.sleep);
abort = (Button)findViewById(R.id.abort);
SharedPreferences sharedPreferences=getSharedPreferences("ipstore", Context.MODE_PRIVATE);
SERVERIP =sharedPreferences.getString("ipadd","");
PORT=sharedPreferences.getInt("port", 8002);
Toast.makeText(this,"Working"+SERVERIP+"\n"+PORT,Toast.LENGTH_LONG).show();//this line working fine
policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
remotecmnd();
}
public void remotecmnd(){
restart.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
//restart code
try{
cs = new Socket(SERVERIP,PORT);
try{
out = new DataOutputStream(cs.getOutputStream());
out.writeUTF("restart");
Toast.makeText(PowerActivity.this, "RESTART SUCCESS", Toast.LENGTH_LONG).show();
} catch (Exception ea) {
Toast.makeText(PowerActivity.this, ea.getMessage(), Toast.LENGTH_LONG).show();
}
}catch (IOException e) {
Toast.makeText(PowerActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
);
}
}
here is server part code
public class serverbackend extends Thread implements Runnable{
public static int SERVERPORT = 8002;
public boolean running = false;
public volatile boolean stop = false;
public Socket client = null;
ServerSocket sc = null;
String value;
public static void main(String[] args) {
mwcobj = new MainWindowController();
}
#Override
public void run() {
super.run();
running = true;
try {
System.out.println("Server Has Started........ \nWaiting for client........");
sc = new ServerSocket(SERVERPORT);
try {
while (!stop && running) {
client = sc.accept();
System.out.println("Connection Accepted......");
DataInputStream dis = new DataInputStream(client.getInputStream());
value = dis.readUTF();
switch (value) {
//Restart the system
case "restart":
System.out.println("Restarting");
Runtime.getRuntime().exec("shutdown -r -t 10");
break;
//some extra code
default:
break;
}
}
} catch (IOException e) {
System.out.println("Inner try catch "+e.getMessage());
}
} catch (IOException e) {
System.out.println("Final try catch error "+e.getMessage());
}
}
public void requestStop(){
try{
stop = true;
sc.close();
System.out.println("Server Has Stopped");
}catch(IOException e){System.out.println("Server Stopped "+e.getMessage());}
}
}
In my opinion, I created a bluetooth communication app,where I get the same problem,
The answer for the this is to use getter and setter methods. It is very easy to set socket and get socket from other java class rather than sending across activities , If I came across other methods I will definitely will tell you on that..
Using getter setter will work for you I beleive.
public class getset
{
static BluetoothSocket sock;
getset(BluetoothSocket sock)
{
this.sock=sock;
}
public static synchronized BluetoothSocket getSock() {
return sock;
}
public static synchronized void setSock(BluetoothSocket sock) {
getset.sock = sock;
}
}
In the place of using shared preference
setSock(socket); //socket is the Bluetoothsocket which you have to save
Bluetoothsocket socket=getSock(); // to get value from the socket
refer https://teamtreehouse.com/community/how-do-you-add-getters-and-setter-in-android-java
I have a button and when clicked calls a method which starts a thread. but there is stop for that thread, fine. I want that to complete the thread first then to execute the rest of the code.
I tried to use wait() but not working.
public void configure(Button arg0,TextView arg1) throws InterruptedException{
//calling OpenDeviceListener
readText=arg1;
button= arg0;
//handler
final Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Log.d("Handler","running");
if (actualNumBytes != 0x00) {
Log.d("handler","if");
readText.append(String.copyValueOf(readBuffer, 0,
actualNumBytes));
Log.d("handler","if 312");
actualNumBytes = 0;
Log.d("handler","if end");
}
Log.d("handler","closed");
}
};
Log.d("163","tab");
uartInterface = new CH34xAndroidDriver(
(UsbManager) getSystemService(Context.USB_SERVICE), this,
ACTION_USB_PERMISSION);
Log.d("167","tab");
act_string = getIntent().getAction();
if(-1 != act_string.indexOf("android.intent.action.MAIN"))
{
Log.d(TAG, "android.intent.action.MAIN 171");
}
else if(-1 != act_string.indexOf("android.hardware.usb.action.USB_DEVICE_ATTACHED"))
{
Log.d(TAG, "android.hardware.usb.action.USB_DEVICE_ATTACHED 175");
}
if(!uartInterface.UsbFeatureSupported())
{
Toast.makeText(this, "No Support USB host API", Toast.LENGTH_SHORT).show();
Log.d("182","tab");
readText.setText("No Support USB host API");
Log.d("184","tab");
uartInterface = null;
}
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
if(READ_ENABLE == false) {
READ_ENABLE = true;
Log.d("192","tab");
handlerThread = new readThread(handler);
handlerThread.start();
}
Log.d("192","End");
try{
this.wait(100);
}
catch(InterruptedException e){
e.printStackTrace();
Log.d("Exception",e.getMessage());
}
// TODO Auto-generated method stub
Log.d("205","OpenDeviceListener");
boolean flags;
if(false == isConfiged) {
Log.d("209","OpenDeviceListener");
Toast.makeText(global_context,""+((Boolean)uartInterface.isConnected()), Toast.LENGTH_LONG).show();
isConfiged = true;
// writeButton.setEnabled(true);
if(uartInterface.isConnected()) {
Toast.makeText(global_context,""+(Boolean)uartInterface.isConnected(), Toast.LENGTH_SHORT).show();
Log.d("213","OpenDeviceListener");
flags = uartInterface.UartInit();
if(!flags) {
Log.d(TAG, "Init Uart Error 2");
Toast.makeText(global_context, "Init Uart Error", Toast.LENGTH_SHORT).show();
} else {
if(uartInterface.SetConfig(baudRate, dataBit, stopBit, parity, flowControl)) {
Log.d(TAG, "Configed");
}
}
}
}
}
and plz clear one thing the stop() is not called for the thread, up to when the thread will run.
Thanks
final Runnable runnable = new Runnable() {
#Override
public void run() {
//this method will be called after 2 seconds
//do your task here
}
};
final Handler h = new Handler();
h.removeCallbacks(runnable); // cancel the running action (the
// hiding process)
h.postDelayed(runnable, 2000);
try this:
Object lock = new Object;
synchronized(lock){
lock.wait();
}
this will block current Thread running these code.
when it's time notify the blocked code
synchronized (lock) {
lock.notify();
}
if just want to sleep the thread for a specific time why not use
Thread.sleep(1000);
I am writing an IRC Client. The socket connection to the IRC Server is handled via a service. I have managed to stabilize all the UI elements of the Activities in question during the orientation change, but somehow the socket that is maintained by the service is being closed during the change.
Here is what I believe to be the relevant code. Please let me know if you need to see more.
//This is the Service in question
public class ConnectionService extends Service{
private BlockingQueue<String> MessageQueue;
public final IBinder myBind = new ConnectionBinder();
public class ConnectionBinder extends Binder {
ConnectionService getService() {
return ConnectionService.this;
}
}
private Socket socket;
private BufferedWriter writer;
private BufferedReader reader;
private IRCServer server;
private WifiManager.WifiLock wLock;
private Thread readThread = new Thread(new Runnable() {
#Override
public void run() {
try {
String line;
while ((line = reader.readLine( )) != null) {
if (line.toUpperCase().startsWith("PING ")) {
SendMessage("PONG " + line.substring(5));
}
else
queueMessage(line);
}
}
catch (Exception e) {}
}
});
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(MessageQueue == null)
MessageQueue = new LinkedBlockingQueue<String>();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return myBind;
}
#Override
public boolean stopService(Intent name) {
try {
socket.close();
wLock.release();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.stopService(name);
}
#Override
public void onDestroy()
{//I put this here so I had a breakpoint in place to make sure this wasn't firing instead of stopService
try {
socket.close();
wLock.release();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.onDestroy();
}
public void SendMessage(String message)
{
try {
writer.write(message + "\r\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public String readLine()
{
try {
if(!isConnected())
return null;
else
return MessageQueue.take();
} catch (InterruptedException e) {
return "";
}
}
public boolean ConnectToServer(IRCServer newServer)
{
try {
//create a new message queue (connecting to a new server)
MessageQueue = new LinkedBlockingQueue<String>();
//lock the wifi
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "LockTag");
wLock.acquire();
server = newServer;
//connect to server
socket = new Socket();
socket.setKeepAlive(true);
socket.setSoTimeout(60000);
socket.connect(new InetSocketAddress(server.NAME, Integer.parseInt(server.PORT)), 10000);
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//run basic login scripts.
if(server.PASS != "")
SendMessage("PASS " + server.PASS);
//write nickname
SendMessage("NICK " + server.NICK);
//write username login
SendMessage("USER " + server.NICK + " 0 * :Fluffy IRC");
String line;
while ((line = reader.readLine( )) != null) {
if (line.indexOf("004") >= 0) {
// We are now logged in.
break;
}
else if (line.indexOf("433") >= 0) {
//change to alt Nick
if(!server.NICK.equals(server.ALT_NICK) && !server.ALT_NICK.equals(""))
{
server.NICK = server.ALT_NICK;
SendMessage("NICK " + server.NICK);
}
else
{
queueMessage("Nickname already in use");
socket.close();
return false;
}
}
else if (line.toUpperCase().startsWith("PING ")) {
SendMessage("PONG " + line.substring(5));
}
else
{
queueMessage(line);
}
}
//start the reader thread AFTER the primary login!!!
CheckStartReader();
if(server.START_CHANNEL == null || server.START_CHANNEL == "")
{
server.WriteCommand("/join " + server.START_CHANNEL);
}
//we're done here, go home everyone
} catch (NumberFormatException e) {
return false;
} catch (IOException e) {
return false;
}
return true;
}
private void queueMessage(String line) {
try {
MessageQueue.put(line);
} catch (InterruptedException e) {
}
}
public boolean isConnected()
{
return socket.isConnected();
}
public void CheckStartReader()
{
if(this.isConnected() && !readThread.isAlive())
readThread.start();
}
}
//Here are the relevant portions of the hosting Activity that connects to the service
//NOTE: THE FOLLOWING CODE IS PART OF THE ACTIVITY, NOT THE SERVICE
private ConnectionService conn;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
conn = ((ConnectionService.ConnectionBinder)service).getService();
Toast.makeText(main_tab_page.this, "Connected", Toast.LENGTH_SHORT)
.show();
synchronized (_serviceConnWait) {
_serviceConnWait.notify();
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
conn = null;
}
};
#Override
protected void onSaveInstanceState(Bundle state){
super.onSaveInstanceState(state);
state.putParcelable("Server", server);
state.putString("Window", CurrentTabWindow.GetName());
unbindService(mConnection);
}
#Override
protected void onDestroy()
{
super.onDestroy();
if(this.isFinishing())
stopService(new Intent(this, ConnectionService.class));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_tab_page);
localTabHost = (TabHost)findViewById(R.id.tabHostMain);
localTabHost.setup();
localTabHost.setOnTabChangedListener(new tabChange());
_serviceConnWait = new Object();
if(savedInstanceState == null)
{//initial startup, coming from Intent to start
//get server definition
server = (IRCServer)this.getIntent().getParcelableExtra(IRC_WINDOW);
server.addObserver(this);
AddTabView(server);
startService(new Intent(this, ConnectionService.class));
}
else
{
server = (IRCServer)savedInstanceState.getParcelable("Server");
String windowName = savedInstanceState.getString("Window");
//Add Needed Tabs
//Server
if(!(windowName.equals(server.GetName())))
AddTabView(server);
//channels
for(IRCChannel c : server.GetAllChannels())
if(!(windowName.equals(c.GetName())))
AddTabView(c);
//reset each view's text (handled by tabChange)
if(windowName.equals(server.GetName()))
SetCurrentTab(server.NAME);
else
SetCurrentTab(windowName);
ResetMainView(CurrentTabWindow.GetWindowTextSpan());
//Rebind to service
BindToService(new Intent(this, ConnectionService.class));
}
}
#Override
protected void onStart()
{
super.onStart();
final Intent ServiceIntent = new Intent(this, ConnectionService.class);
//check start connection service
final Thread serverConnect = new Thread(new Runnable() {
#Override
public void run() {
if(!BindToService(ServiceIntent))
return;
server.conn = conn;
conn.ConnectToServer(server);
server.StartReader();
if(server.START_CHANNEL != null && !server.START_CHANNEL.equals(""))
{
IRCChannel chan = server.FindChannel(server.START_CHANNEL);
if(chan != null)
{
AddTabView(chan);
}
else
{
server.JoinChannel(server.START_CHANNEL);
chan = server.FindChannel(server.START_CHANNEL);
AddTabView(chan);
}
}
}
});
serverConnect.start();
}
private boolean BindToService(Intent ServiceIntent)
{
int tryCount = 0;
bindService(ServiceIntent, mConnection, Context.BIND_AUTO_CREATE);
while(conn == null && tryCount < 10)
{
tryCount++;
try {
synchronized (_serviceConnWait) {
_serviceConnWait.wait(1500);
}
}
catch (InterruptedException e) {
//do nothing
}
}
return conn != null;
}
Im not entirely certain what I am doing wrong there. Obviously there's something I'm missing, haven't found yet, or haven't even thought to check. What happens though is that after the orientation change my Send command gives me this message and nothing happens:
06-04 22:02:27.637: W/System.err(1024): java.net.SocketException: Socket closed
06-04 22:02:27.982: W/System.err(1024): at com.fluffyirc.ConnectionService.SendMessage(ConnectionService.java:90)
I have no idea when the socket is getting closed, or why.
Update
I have changed the code so that rather than binding to the service and using that to start it, instead I call startService and stopService at appropriate points as well as binding to it, on the thought that the service was being destroyed when the binding was lost. This is working exactly like it was before I changed it. The socket still closes on an orientation change, and I have no idea why.
Update :- Code and description
I added the code changes recently made for Start/Stop service and START_STICKY. I also recently read a very good article explaining how the orientation change process flow works and why its NOT a bad idea to add the android:configChanges="orientation|screenSize" line to your manifest. So this fixed the orientation issue, but its still doing the same thing if I put the activity into background mode, and then bring it back to the foreground. That still follows the same Save/Destroy/Create process that the orientation does without that manifest line...and it still closes my socket, and I still don't know why.
I do know that it doesn't close the socket until the re-create process...I know this because the message queue will display messages that were received while the app was in the background, but once I bring it back forward it closes the socket and nothing else can be sent or received.
'Socket closed' means that you closed the socket and then continued to use it. It isn't a 'disconnect'.
You need to put something into that catch block. Never just ignore an exception. You might get a surprise when you see what the exception actually was.
NB Socket.isConnected() doesn't tell you anything about the state of the connection: only whether you have ever connected the Socket. You have, so it returns true.
I have created a client-server application that the two parties communicate using a socket connection and input/output streams to send/receive data. It all works great but only if I have just one activity that uses the connection. Since I will be having more than just one activities in my application, and after some searching around, I've concluded that I have to create a Service which will handle the socket connection and sending/receiving from the socket streams. I've never worked with Services before and I thought I'd start one step at a time. At the moment I've just created a Service that creates an instance of my Client class(which extends Thread) and starts that thread, which establishes the connection to the server.
My Client class
T_Client:
public class T_Client extends Thread {
private static final String TAG = "T_Client";
private static String serverIP = "192.168.2.3";
private static int port = 4444;
private InetAddress serverAddr = null;
private Socket sock = null;
private boolean running = false;
private ObjectInputStream in;
private ObjectOutputStream out;
private Object objIn;
public void send(MessageCustom _msg) {
if (out != null) {
try {
out.writeObject(_msg);
out.flush();
Log.i("Send Method", "Outgoing : " + _msg.toString());
} catch (IOException ex) {
Log.e("Send Method", ex.toString());
}
}
}
public void stopClient() {
Log.v(TAG,"stopClient method run");
running = false;
}
#Override
public void run() {
running = true;
try {
serverAddr = InetAddress.getByName(serverIP);
Log.i("TCP Client", "C: Connecting...");
sock = new Socket(serverAddr, port);
try {
out = new ObjectOutputStream(sock.getOutputStream());
in = new ObjectInputStream(sock.getInputStream());
Log.i(TAG, "C: Connected.");
while (running) {
objIn = in.readObject();
Log.i("Object Read Class", objIn.getClass().toString());
Log.i("Object Read", objIn.toString());
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + objIn + "'");
} catch (Exception e) {
Log.e(TAG, "S: Error", e);
} finally {
out.close();
in.close();
sock.close();
Log.i(TAG, "Closing socket: " + sock);
}
} catch (Exception e) {
Log.e(TAG, "C: Error", e);
}
}
}
My Service Class
MyService:
public class MyService extends Service {
private static final String TAG = "MyService";
private T_Client client;
#Override
public void onDestroy() {
Log.v(TAG, "onDestroy");
if (client != null) {
try {
client.stopClient();
} catch (Exception e) {
Log.e(TAG, "Error on close: " + e);
}
}
super.onDestroy();
Toast.makeText(this, "Service stopped", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand");
client = new T_Client();
client.start();
Toast.makeText(this, "Service started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
All I do in my main activity at the moment is use a start and a stop button to start/stop the service
public void start(View v){
Log.i(TAG,"Start pressed");
Intent intent=new Intent(getBaseContext(),MyService.class);
startService(intent);
}
public void stop(View v){
Log.i(TAG,"Stop pressed");
Intent intent=new Intent(getBaseContext(),MyService.class);
stopService(intent);
}
So my questions are:
What do I have to do to send something using my Service?
How do I handle the objects that I read from the server so I can let the application know that something has been received, in real time?
Any input that could guide me towards resolving my issue is greatly appreciated.
Thank you in advance.
In case anyone else comes across this question, that has a similar problem, I managed to solve my problem by playing around with code from these two posts
Example: Communication between Activity and Service using
Messaging
How to keep the android client connected to the
server even on activity changes and send data to server?
I have implemented my own android service as follows
public class MyService extends Service {
private static final String TAG = "MyService";
private Server mServer;
private LocalServerSocket server;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Log.d(TAG, "onCreate");
mServer = new Server();
mServer.start();
}
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
if(server != null){
try {
server.close();
} catch (IOException e) {
Log.d(TAG, "exception in server close");
e.printStackTrace();
}
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStart");
return START_STICKY;
}
class Server extends Thread {
#Override
public void run() {
try {
server = new LocalServerSocket("my.socket");
while (true) {
LocalSocket receiver;
try{
receiver = server.accept();
}catch(SocketException e){
Log.d(TAG, "SocketException");
break;
}
catch(IOException e){
Log.d(TAG, "IOException");
break;
}
if (receiver != null) {
Log.d(TAG, "Got Data in receiver");
}
receiver.close();
}
} catch (IOException e) {
Log.d(TAG, "one more");
e.printStackTrace();
}
}
}
}
The problem I am facing is that, if my LocalServerSocket is blocking in accept(), then a call to server.close() in OnDestroy() will not throw a SocketException. Hence, next time I start the service, I get "address already in use exception". If instead of LocalServerSocket, I use java.net.Socket, then i get the required behavior. I would like to know why LocalServerSocket behaves differently from Java Sockets. In my case, how do I come out of the while loop.
I had the same problem and "solved" it this way. The thread run() method is checking for "!isInterrupted()". The method "stopSocketServer()" which I added to my Listener-Thread marks the thread for interrupt() and then made a connect request to itself to trigger the accept() method.
/**
* Executed if thread is started.
*/
public void run() {
try {
// leave while loop if thread is marked for interrupt.
while (!isInterrupted()) {
LocalSocket clientSocket = serverSocket.accept();
if (!isInterrupted()) {
threadPool.execute(new ClientProcessor(clientSocket));
}
}
} catch (IOException e) {
if (!isInterrupted()) {
Log.e(TAG, "socket listener terminated", e);
}
} finally {
try {
if (serverSocket != null) {
serverSocket.close();
}
if (threadPool != null) {
threadPool.shutdownNow();
}
Log.i(TAG, "socket listener stopped");
} catch (IOException e) {
}
}
}
public void stopSocketServer() {
if (serverSocket != null) {
try {
// mark thread as interrupted
interrupt();
// now send connect request to myself to trigger leaving accept()
LocalSocket ls = new LocalSocket();
ls.connect(serverSocket.getLocalSocketAddress());
ls.close();
} catch (IOException e) {
Log.e(TAG, "stopSocketServer failed", e);
}
}
}
From the code you've posted it looks like your LocalServerSocket server will remain null forever and onDestroy() won't close it. Also, closing the socket normally shouldn't throw IOException - but the accept() will do so if the socket is closed concurrently.