0

これは私のアプリケーションでは複雑な問題かもしれませんが、できる限り正確に説明できるよう最善を尽くします。

私は Android クライアントを作成しており、他の誰かが職場で私に渡したいくつかのヘルパー クラスを利用しています。ヘルパー Android クラスは、TcpClient.java および PVDCAndroidClient.java と呼ばれます。PVDCAndroidClient.java は、tcpCLient オブジェクトを使用して serverIP とポート経由で接続し、TcpCLient を利用します。

PVDCAndroidClient.java は次のとおりです。

    public class PVDCAndroidClient {

    // constants
    public static final String DEFAULT_LOGIN_URI = "http://me.net:8000/";


    private TcpClient tcpClient = null;
    private UdpClient udpClient = null;
    private boolean connected = false;
    private boolean loggedin = false;
    private static SimpleDateFormat sdf;
    private String loginURI = DEFAULT_LOGIN_URI;
    private int getUserNumber;
    TcpMessageListener listener = null;

    /**
     * Connects to proxy server, blocks until complete or timeout
     * @param serverIP
     * @param port
     */
    public void connect(String serverIP, int port)
    {
        try
          {
            if(serverIP.length() != 0 && port != 0)
            {
              tcpClient = new TcpClient();

              tcpClient.addTcpListener(listener);
              tcpClient.connect(serverIP, port);

            }
          }
        catch(Exception e)
        {
            e.printStackTrace();
            Log.d("Could not connect to server, possbile timeout...", "error");
        }



    }

    ///// Make login function a blocking call

    // Default login, use last location as login location
    public boolean login(String fName, String lName, String password)
    {
        return this.login(fName, lName, password, "last location");
    }

    public boolean login(String fName, String lName, String password, String region)
    {
        return this.login(fName, lName, password, "last location", 128, 128, 20);
    }

    public boolean login(String fName, String lName, String password, String region, int loginX, int loginY, int loginZ)
    {            sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
                 sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

        // Check passed values
            // x, y and z should be between [0, 256]
            // strings should not be null or empty(except lName which can be empty)
        if((loginX >= 0 && loginX <= 256) && (loginY >=0 && loginY <= 256) && (loginZ >= 0 && loginZ <= 256))
        {
            if(fName.length() != 0 && fName != null)
            {


                // Construct packet xml structure

                // Send request and wait until reply or timeout

                // return false if timeout (or throw exception?)
                // if not timeout, read result packet and determine return value

                // getUserNumber = tcpClient.getUserNum();

                StringWriter stringWriter = new StringWriter();


                XmlSerializer serializer = Xml.newSerializer();

                try {

                    serializer.setOutput(stringWriter);

                    // Indentation is not required, but helps with reading
                    serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);

                    // TODO: Remove hardcoding of strings, make either constants or place in strings.xml
                    // TODO: Move the header construction to other method as it is fairly constant other than request num and no need to repeat that much code
                    serializer.startTag("", "pvdc_pkt");

                        serializer.startTag("", "pvdc_header");




                            // TODO: replace this with a string unique to the system
                            serializer.startTag("", "ID");
                                serializer.text("838393djdjdjd");
                            serializer.endTag("", "ID");

                            // TODO: replace this with actual user number from server
                            serializer.startTag("", "user_num");
                                serializer.text("22");//get userNum from above
                            serializer.endTag("", "user_num");

                            // TODO: add a request number counter to increment this on each request
                            serializer.startTag("", "request_num");
                                serializer.text("1");
                            serializer.endTag("", "request_num");

                            serializer.startTag("", "DateTime");
                                serializer.text(sdf.toString()); //utc time variable.
                            serializer.endTag("", "DateTime");

                        serializer.endTag("", "pvdc_header");

                        serializer.startTag("", "pvdc_content");
                            serializer.attribute("", "type", "requestlogin");

                            serializer.startTag("", "name");
                                serializer.attribute("", "fname", fName);
                                serializer.attribute("", "lname", lName);
                            serializer.endTag("", "name");

                            serializer.startTag("", "password");
                                serializer.text(password);
                            serializer.endTag("", "password");

                            serializer.startTag("", "server");
                                serializer.text(this.loginURI);
                            serializer.endTag("", "server");

                            serializer.startTag("", "location");
                                serializer.attribute("", "region", region);
                                serializer.text(loginX + ";" + loginY +";" + loginZ);
                            serializer.endTag("", "location");

                        serializer.endTag("", "pvdc_content");

                    serializer.endTag("", "pvdc_pkt");

                    // Finish writing
                    serializer.endDocument();
                    // write xml data out
                    serializer.flush();

                    // 
                    sendLogin(stringWriter);

                } catch (Exception e) {
                    Log.e("Exception", "error occurred while creating xml file");
                    return false;
                }
                // Print out xml for debugging
                Log.d("PVDCAndroidClient Login", stringWriter.toString().trim());

            }
            else
            {
                Log.d("Error in name checking", "fName either blank or null");
            }

         }
        else
        {
            Log.d("login coordinates X,Y, or Z not between 0-256", "Coordinates Error");
        }

        return true;
       }


    // moveString should contain the properly formatted movement command(s)[see above move request description]
    public void sendLogin(StringWriter stringWriter)
    {
        tcpClient.sendMessage(stringWriter.toString());
    }
}

実際の TcpClient.java は次のとおりです。

    public class TcpClient {

    public interface TcpMessageListener{

        public void onMessage(TcpClient client, String message);
    }

    private Socket socket = null;
    private PrintWriter out = null;
    private BufferedReader in = null;
    private Thread listenThread = null;
    private boolean listening = false;
    private int userNum = -1;
    private List<TcpMessageListener> listeners = new ArrayList<TcpMessageListener>();


    public int getUserNum()
    {
        return this.userNum;
    }

    public TcpClient() {

    }

    public void addTcpListener(TcpMessageListener listener)
    {
        synchronized(this.listeners)
        {
            this.listeners.add(listener);
        }
    }

    public void removeTcpListener(TcpMessageListener listener)
    {
        synchronized(this.listeners)
        {
            this.listeners.remove(listener);
        }
    }

    public boolean connect(String serverIpOrHost, int port) {
        try {
            socket = new Socket(serverIpOrHost, port);
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            this.listenThread = new Thread(new Runnable(){

                public void run() {
                    int charsRead = 0;
                    char[] buff = new char[4096];
                    while(listening && charsRead >= 0)
                    {
                        try {
                            charsRead = in.read(buff);
                            if(charsRead > 0)
                            {
                                Log.d("TCPClient",new String(buff).trim());
                                String input = new String(buff).trim();
                                synchronized(listeners)
                                {
                                    for(TcpMessageListener l : listeners){
                                        l.onMessage(TcpClient.this, input);
                                    }
                                }

                                if (input.toLowerCase().contains("<user_num>")){
                                    int index = input.toLowerCase().indexOf("<user_num>");
                                    index += "<user_num>".length();
                                    int index2 = input.toLowerCase().indexOf("</user_num>");
                                    userNum = Integer.parseInt(input.substring(index,  index2));

                                }
                            }
                        } catch (IOException e) {
                            Log.e("TCPClient", "IOException while reading input stream");
                            listening = false;
                        }
                    }
                }

            });

            this.listening = true;
            this.listenThread.setDaemon(true);
            this.listenThread.start();

        } catch (UnknownHostException e) {
            System.err.println("Don't know about host");
            return false;
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection");
            return false;
        } catch (Exception e) {
            System.err.println(e.getMessage().toString());
            return false;
        }
        return true;
    }

    public void sendMessage(String msg) {
        if(out != null)
        {
            out.println(msg);
            out.flush();
        }
    }

    public void disconnect() {
        try {
            if(out != null){
                out.close();
                out = null;
            }
            if(in != null){
                in.close();
                in = null;
            }
            if (socket != null) {
                socket.close();
                socket = null;
            }
            if(this.listenThread != null){
                this.listening = false;
                this.listenThread.interrupt();
            }
            this.userNum = -1;
        } catch (IOException ioe) {
            System.err.println("I/O error in closing connection.");
        }
    }
}

最後に、これが私が今日コーディングしているもので、これを機能させることができないようです。露骨な例外は発生しません。Logcat に「接続の I/O を取得できませんでした」という警告が表示されるだけです。

    public class AndroidClientCompnt extends Activity {

    private TcpClient myTcpClient = null;
    private UdpClient udpClient;
    private static final String IP_ADDRESS_SHARED_PREFS = "ipAddressPref";
    private static final String PORT_SHARED_PREFS = "portNumberPref";
    private String encryptPassLoginActivity;
    private String getIpAddressSharedPrefs;
    private String getPassword, getName, getRegionSelect, getGridSelect;
    private String fName, lName;
    private SharedPreferences settings;
    private boolean resultCheck = false;
    private int portNum;
    PVDCAndroidClient client;
    private String name;
    private CharSequence[] getView;

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

        Intent intent = getIntent();
        // getting object's properties from LoginActivity class.

        getName = intent.getStringExtra("name");
        getPassword = intent.getStringExtra("password");
        getRegionSelect = intent.getStringExtra("regionSelect");
        getGridSelect = intent.getStringExtra("gridSelect");

        Log.d("VARIABLES", "getName = " + getName + "getPassword" + getPassword
                + "getRegionSelect = " + getRegionSelect + ".");
        setResult(Activity.RESULT_CANCELED);

        client = new PVDCAndroidClient();
    }

    @Override
    protected void onStart() {
        super.onStart();

        // Take care of getting user's login information:

        // grid selected as well? sometime?

        settings = PreferenceManager.getDefaultSharedPreferences(this);

        getIpAddressSharedPrefs = settings.getString(IP_ADDRESS_SHARED_PREFS,
                "");
        portNum = Integer.parseInt(settings.getString(PORT_SHARED_PREFS, ""));
        Log.d("SHARED" + getIpAddressSharedPrefs + "port " + portNum, "");

        if (getIpAddressSharedPrefs.length() != 0 && portNum != 0) {

            try {
                // first connect attempt.

                client.connect(getIpAddressSharedPrefs, portNum);
                resultCheck = client.isConnected();

                // here is where I want to call Async to do login
                // or do whatever else.

                UploadTask task = new UploadTask();
                task.execute();

            } catch (Exception e) {
                Toast.makeText(getApplicationContext(), "Could not connect.",
                        Toast.LENGTH_LONG).show();
                e.printStackTrace();
            }

        } else {
            Toast.makeText(getApplicationContext(),
                    "Ip preference and port blank", Toast.LENGTH_LONG).show();
        }

        finish();
    }

    private class UploadTask extends AsyncTask<String, Integer, Void> {
        @Override
        protected void onPreExecute() {
            Toast.makeText(getApplicationContext(), "Loading...",
                    Toast.LENGTH_LONG).show();
        }

        @Override
        protected Void doInBackground(String... names) {

            // encrypting user's password with Md5Hash class.
            try {
                encryptPassLoginActivity = MdHashing
                        .MD5(getPassword.toString());
            } catch (NoSuchAlgorithmException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            if (resultCheck == true) {

                String[] firstAndLast;

                String spcDelmt = " ";

                firstAndLast = name.toString().split(spcDelmt);

                fName = firstAndLast[0];
                lName = firstAndLast[1];

                // set up the tcp client to sent the information to the
                // server.
                client.login(fName, lName, encryptPassLoginActivity,
                        getRegionSelect, 128, 128, 20);

            }

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {

            Intent goToInWorld = new Intent(
                    AndroidClientCompnt.this.getApplicationContext(),
                    PocketVDCActivity.class);
            startActivity(goToInWorld);
            Toast.makeText(getApplicationContext(), "Connected",
                    Toast.LENGTH_LONG).show();

        }

    }

}

これが非常に長い投稿であることは承知しており、多くの質問をしていますが、誰かがこれを見てくれれば、とても感謝しています. 私は一日中、私が手に入れたこれらのヘルパークラスを利用しようとしましたが、それを機能させることができません. また、このクライアント/サーバー関連の経験があまりないことも役に立ちません。正しい方向への微調整や受け入れられた解決策は、私にとって本当に意味があります。

よろしくお願いします。

こんばんは。

4

2 に答える 2

1

マニフェストを投稿できますか?

以下を追加する必要がある場合があります。

 <uses-permission android:name="android.permission.INTERNET"/>

さらに、この接続のサーバー側では何も起こらないと思いますか?

于 2012-07-11T01:49:00.680 に答える
0

1) Android-Manifest ファイルに次の権限があることを確認してください。

 <uses-permission android:name="android.permission.INTERNET/> 

これがないと、tcp/ip 接続を確立することはできません。

2) コードをデバッグ モードで実行し、接続情報が設定されている場所にブレークポイントを配置し、いくつかのポイントで結果を確認します。言い換えれば、より深く掘り下げる必要があります。

コーディングに多少慣れていない場合は、デバッガーを実行してコードを 1 行ずつ実行することほど時間の無駄はありません。コードは、変数の値と結果を確認できるデバッガー内でのみ有効になります。したがって、いくつかのブレークポイントを設定し、ステップスルーすると、さらに表示されます。ただし、スレッドがある場所をデバッグするのはより困難です。

于 2012-07-11T01:49:22.410 に答える