套接字客户端+线程+ Android +连接状态

时间:2012-03-16 19:21:27

标签: java android sockets client

我对java和Android开发都很陌生,我正在设计一个Android客户端来向服务器发送消息,并从服务器接收消息。它只执行一些功能,首先它将查询服务器的初始状态,然后它将使用该状态更新按钮,并使用充电符号来说明充电器是否正在充电。我已经完成了所有的通信代码,线程似乎发送和接收消息,但线程外的变量没有更新,如果我关闭服务器连接,客户端将保持连接打开,好像服务器还在那里。有人可以给我一些建议,解决我的问题吗?

package charger.app;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;


public class ChargeTabActivity extends Activity {

String serverIp = "192.168.6.120"; //server Ip address  
private static String preqon = "control:Charger:1\r\n"; //sets connection to turn charger on
private static String preqoff = "control:Charger:0\r\n";    //Turn charger off
public boolean connected = false; //connection 

//set up buttons
private ImageButton chargeOnOff;
private ImageButton connectButton;

//Set it so that Client Functions can be accessed from main program
ClientFunctions functions = new ClientFunctions();



@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //initialize UI
    setContentView(R.layout.main);

    //declare buttons for listeners, and display changes        
    connectButton = (ImageButton)findViewById(R.id.connectButton);       
        connectButton.setOnClickListener(connectButtonListener);    
    chargeOnOff = (ImageButton)findViewById(R.id.chargeOnOff);  
        chargeOnOff.setOnClickListener(chargeOnOffListener);
    Button chargeStatus = (Button)findViewById(R.id.chargeStatus);



    ////set up strict mode off/////
        StrictMode.ThreadPolicy policy = new StrictMode.
                ThreadPolicy.Builder().permitAll().build();
                StrictMode.setThreadPolicy(policy);


}



/*Listens to see if the connect button is pressed, if it is connected it will 
 * display connected, else it will try and connect*/
private OnClickListener connectButtonListener = new OnClickListener() 
{
    public void onClick(View v)
    {
        if (connected) 
        {
            toast("I am connected");
        }
        else 
        {
            toast("I am not connected");
        }
    }
};


/*Listens to see if the Charge on Off Button is pressed, if it is charging it will 
 * send a request to charge, else it will send a request to stop the charge*/
private OnClickListener chargeOnOffListener = new OnClickListener() 
{
    public void onClick(View v)
    { 
        //ask server
        try {
            functions.updateStatus();  //updates the charger status
        } catch (IOException e) {
            Log.e("Client","Trouble querying",e);
            e.printStackTrace();
        }

        //send message to turn server on or off
        if (functions.chargeStatNumber != 0) 
        {
            try {
                functions.sendMessage(preqoff);
                chargeOnOff.setImageResource(R.drawable.charge_on);
                toast("Turning Charger off");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


        }//end if


        else 
        {
            try {
                functions.sendMessage(preqon);
                chargeOnOff.setImageResource(R.drawable.charge_off);
                toast("Turning Charger on");

            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


        } //end else

        Log.d("ClientActivity", "Charge Button hit" );


        //ask server about its status
        try {
            functions.updateStatus();  //updates the charger status
        } catch (IOException e) {
            Log.e("Client","Trouble querying",e);
            e.printStackTrace();
        }

    }
};


/////When Application Starts
@Override
public void onStart() 
{
    super.onStart();

    Thread cThread = new Thread(new serverThread()); //Starts the thread that initiates communications
    cThread.start();
};

////////On Pause//////This is when a user makes another app, the center point of attention 
@Override
public void onPause() {
    super.onPause();
    functions.closeConnection();

};

//////On Resume/////This is used for when an app exits, and then the user brings it back
@Override
public void onResume() {
    super.onResume();


};

//////On Destroy//////////
@Override
public void onDestroy() {
    super.onDestroy();
    functions.closeConnection();

};



//toast messages
public void toast(String toastMessage) 
{
    Toast.makeText(DelphiChargeTabActivity.this, toastMessage,
            Toast.LENGTH_LONG).show();
};



//Thread to run and receive network connections

public class serverThread implements Runnable 
{
    public boolean connected = false; //connection
    public void run() //runs the thread
    {

        try 
        {
            functions.connectToServer(serverIp); //connects to server
            connected = true;

            while (connected) 
            {
                try 
                {
                    connectButton.setImageResource(R.drawable.blue_car);
                    functions.getStreams(); //establish stream connections
                    functions. updateStatus(); //updates the status of the server
                    //checkChangeChargeButton(); //sets initial state for charge button



                    try
                    {
                        Thread.sleep(2500);
                    }
                          catch ( InterruptedException interruptedException ) 
                          {
                             functions.displayMessage( "\nThread exception" );
                          } // end catch

                }
                    catch (IOException e) 
                    {
                        Log.e("Client","Trouble Getting Streams",e);

                    }



            }//end while
        }//end try
            catch (Exception e)
            {
                Log.e("Client", "Error Connecting", e);
                connected = false;
                connectButton.setImageResource(R.drawable.red_car);

            }
    }; //end run
}; //end serverThread

public void checkChangeChargeButton() 
{

    if (functions.chargeStatNumber != 0) 
    {
        chargeOnOff.setImageResource(R.drawable.charge_on);
    }
    else 
    {
        chargeOnOff.setImageResource(R.drawable.charge_off);
    }

};



} //This is the Activity close bracket

这是我的函数方法的代码

    package charger.app;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.Socket;

import android.util.Log;


public class ClientFunctions
{

private String message;
private String server;
public Socket sock;
private PrintWriter writer;
private DataInputStream inStream;
public Boolean connected;
private String encode = "UTF8";
public byte[] chargerstat;
public int  chargeStatNumber; //Used to set the array byte 15 to an int


//inquires server for status of charge
public void updateStatus() throws IOException 
{
    //Prompt user for server command
    System.out.println("Sending request for Charger status data.");
        String serverMessage = "meas:Charger?\r\n";

    // send the message
        sendMessage("meas:Charger?\r\n");
        System.out.println();
        displayMessage(serverMessage + "sent");

    // now receive the message
    receiveMessage();
        displayMessage("Receive complete");


};


public void connectToServer(String serverIp) throws IOException  //Server IP is sent in main    app as String "serverIp"
{
    //set server IP

    //display logcat trying to connect
    displayMessage("\nTrying to Connect");
    //Start Socket Connection
    sock = new Socket( InetAddress.getByName( serverIp ), 18088);
    //Display connected
    displayMessage( "\nConnected to: " + 
             sock.getInetAddress().getHostName() );



};

public void getStreams() throws IOException 
{
    //Set up PrintWriter
    writer = new PrintWriter(new BufferedWriter(new            OutputStreamWriter(sock.getOutputStream())),true);
    writer.flush();
    //Set Up I
    inStream = new DataInputStream(sock.getInputStream());
    //display Message Got I/O
    displayMessage("\nGot IO Streams");

};

public void sendMessage(final String serverMessage) throws UnsupportedEncodingException 
{


    //set variable for message
    message = serverMessage;
    //sends message
    writer.printf("%s", message);
    writer.flush();
    //display message sent
    displayMessage("\nsent" /*+ serverMessage*/);




};

public static int getInt(byte[] array, int offset) 
  {
    return
      ((array[offset+3]   & 0xff) << 24) |
      ((array[offset+2] & 0xff) << 16) |
      ((array[offset+1] & 0xff) << 8) |
       (array[offset] & 0xff);
  }


public void receiveMessage() throws IOException 
{
    {
        int c=0;
        int i;          
        int seqcountval;

        chargerstat = new byte[96];
        i=0;
        while(i < 96)
        {
            try
            {
                c = inStream.read();
                chargerstat[i] = (byte)c;
            }
            catch ( IOException ioException ) 
            {
                ioException.printStackTrace();
            } // end catch
// uncomment this to see each byte          
            //displayMessage(":" + i + " " + chargerstat[i]);
            i++;
        }

        seqcountval = getInt(chargerstat, 76);
        displayMessage("SeqCntr = " + seqcountval);
        chargeStatNumber = chargerstat[15];

    };
};

public  void closeConnection() 
{
    //closes connections
    displayMessage("\n\nClosing Connection");

    try 
    {
        writer.close();
        inStream.close();
        sock.close();


    }
    catch ( IOException ioException ) 
      {
         ioException.printStackTrace();
      } // end catch


};



public void displayMessage( final String messageToDisplay )
   {

         new Runnable()
         {
            public void run() // updates displayArea
            {
              //change to log.d for android
                System.out.println(messageToDisplay);
            } // end method run
         };  // end anonymous inner class

   } // end method displayMessage





};    

3 个答案:

答案 0 :(得分:1)

为什么不使用AsyncTask而不是Thread,分享信息会更容易,并且似乎适用于你想要做的事情。

  

使用AsyncTask

     

AsyncTask允许您对用户执行异步工作   接口。它在工作线程中执行阻塞操作   然后在UI线程上发布结果,无需您   自己处理线程和/或处理程序。

http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html

ChargerActivity中的“connected”变量与ServerThread中的变量不同,因此不会从线程更新ChargerActivity的连接。

答案 1 :(得分:1)

socket函数不能在android 4.0之后的ui线程中使用,比如你的connect funciton和sendMessage

答案 2 :(得分:0)

您无法从其他线程更新UI。您必须在主线程中更新UI。如果您想从不同的线程更新UI,您可以执行类似这样的操作

public void changeButtonImage(){
    runOnUiThread(new Runnable(){

        @Override
        public void run() {
            connectButton.setImageResource(R.drawable.blue_car);
        }});
}