无法在未调用Looper.prepare()

时间:2015-05-03 23:26:01

标签: android sockets android-asynctask ui-thread ports

编辑:我的解决方案是使用此代码获得一个常量类:

static EditText Port = (EditText) MainActivity.mDialog.findViewById(R.id.txtPort); static int mPort = Integer.parseInt(Port.getText().toString()); public static final int PORT = mPort;

我试图看到其他问题而且我明白我必须对UIThread做些什么?老实说,我什么都不懂。我是新的Android。

应用程序(聊天应用程序)工作正常,直到我想拥有多个端口选项,具体取决于我是托管(port 5050)还是加入(port 80)聊天室。从一开始我只有一个恒定的端口值(public static final int PORT)但现在我不能拥有那个ofc。如果你们有关于如何获得两个PORT值的任何其他建议,请分享你的提示。

无论如何,在尝试了一切之后我决定在我的主类中放一个方法,然后在其他类中声明它。这是端口值的方法:

public int getPORT() {
        txtPORT = (EditText) findViewById(R.id.txtPort);
        //String txtPORTa = txtPORT.getText().toString();

        int dennaPORT = 0;

        if (mJoin.isChecked()) {
            dennaPORT = Integer.parseInt(txtPORT.getText().toString());
            return dennaPORT;
        }
        else if (mHost.isChecked()) {
            dennaPORT = 5050;
            return dennaPORT;
        }
        return dennaPORT;
    }

这是我的MainActivity

package chat.chris.android.se.chatup;

import android.app.Activity;
import android.app.Dialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;

import java.util.ArrayList;

import chat.chris.android.se.chatup.Listeners.ChatListener;
import chat.chris.android.se.chatup.Listeners.ConnectionListener;
import chat.chris.android.se.chatup.Networking.Client;
import chat.chris.android.se.chatup.Networking.Server;
import chat.chris.android.se.chatup.Utilities.ServerUtils;

import static chat.chris.android.se.chatup.R.id.rdioHost;
import static chat.chris.android.se.chatup.R.id.rdioJoin;

public class MainActivity extends Activity {

    private Adapter chatAdapter;
    private Button btnSendMessage;
    private EditText txtMessage;
    private ListView lstMessages;
    private static Dialog mDialog;
    private Client mClient;
    private Server mServer;
    private EditText txtPORT;
    private RadioButton mJoin;
    private RadioButton mHost;

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

        showChatSelection();

        chatAdapter = new Adapter(this, new ArrayList<ChatItem>());

        lstMessages = (ListView) findViewById(R.id.lstChat);
        lstMessages.setAdapter(chatAdapter);

        txtMessage = (EditText) findViewById(R.id.txtSay);
        txtMessage.setOnEditorActionListener(txtMessageEditorActionListener);

        btnSendMessage = (Button) findViewById(R.id.btnSend);
        btnSendMessage.setOnClickListener(btnSendMessageClickListener);

        Client.setOnChatListener(chatListener);
        Client.setOnConnectionListener(connectionListener);

    }



    public void showChatSelection() {

        mDialog = new Dialog(this);
        mDialog.setContentView(R.layout.layout_chat_choose);
        mDialog.setTitle("Chat Room");
        mDialog.setCancelable(false);

        final EditText txtServer = (EditText) mDialog.findViewById(R.id.txtAddress);
        final TextView lblServer = (TextView) mDialog.findViewById(R.id.lblAddress);
        final TextView txtPort = (EditText) mDialog.findViewById(R.id.txtPort);
        final RadioButton mHost = (RadioButton) mDialog.findViewById(rdioHost);
        final RadioButton mJoin = (RadioButton) mDialog.findViewById(rdioJoin);

        try {
            lblServer.setText(ServerUtils.getLocalIp(this));
        } catch (NullPointerException e) {
            mHost.setEnabled(false);
            mHost.setChecked(false);
            lblServer.setText("Wifi must be enabled to host");
            mJoin.setChecked(true);
            txtServer.setVisibility(View.VISIBLE);
            txtPort.setVisibility(View.VISIBLE);
        }

        mDialog.findViewById(R.id.btnChoose).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                mDialog.findViewById(R.id.progLoading).setVisibility(View.VISIBLE);

                new SetupChat().execute(mHost.isChecked(), mJoin.isChecked() ? txtServer.getText().toString() : "");
            }
        });

        mHost.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    mJoin.setChecked(false);
                    txtServer.setVisibility(View.INVISIBLE);
                    txtPort.setVisibility(View.INVISIBLE);
                    lblServer.setVisibility(View.VISIBLE);
                }

            }
        });

        mJoin.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    mHost.setChecked(false);
                    txtServer.setVisibility(View.VISIBLE);
                    txtPort.setVisibility(View.VISIBLE);
                    lblServer.setVisibility(View.INVISIBLE);
                }

            }
        });

        mDialog.show();

    }

    private final OnClickListener btnSendMessageClickListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            sendMessage();
        }
    };

    private final OnEditorActionListener txtMessageEditorActionListener = new OnEditorActionListener() {

        @Override
        public boolean onEditorAction(TextView v, int id, KeyEvent event) {
            if (id == EditorInfo.IME_ACTION_NEXT || id == EditorInfo.IME_ACTION_DONE)
                sendMessage();
            return true;
        }
    };

    private final ChatListener chatListener = new ChatListener() {

        @Override
        public void onChat(String message) {
            chatAdapter.addItem(new ChatItem("<html>" + message + "</html>", "Friend"));
        }
    };

    private final ConnectionListener connectionListener = new ConnectionListener() {

        @Override
        public void onDisconnect(Client client) {
            chatAdapter.addItem(new ChatItem(client.getName() + " left the chat room", ""));
        }

        @Override
        public void onJoin(Client client) {
            chatAdapter.addItem(new ChatItem(client.getName() + " joined the chat room", ""));
        }
    };

    public void sendMessage() {

        String message = txtMessage.getText().toString();

        if(message == null || message.isEmpty())
            return;

        message = message.replace(">", "&gt;");
        message = message.replace("<", "&lt;");


        try {
            if (mServer != null) {
                mServer.sendMessage(message);
                chatAdapter.addItem(new ChatItem(message, "You"));
            } else if (mClient != null) {
                mClient.sendMessage(message);
                chatAdapter.addItem(new ChatItem(message, "You"));
            } else {
                return;
            }
        } catch (Exception e) {
            chatAdapter.addItem(new ChatItem(e.getMessage(), "<font color='red'>Error</font>"));
            return;
        }

        txtMessage.setText("");
    }

    public int getPORT() {
        txtPORT = (EditText) findViewById(R.id.txtPort);
        //String txtPORTa = txtPORT.getText().toString();

        int dennaPORT = 0;

        if (mJoin.isChecked()) {
            dennaPORT = Integer.parseInt(txtPORT.getText().toString());
            return dennaPORT;
        }
        else if (mHost.isChecked()) {
            dennaPORT = 5050;
            return dennaPORT;
        }
        return dennaPORT;
    }

    private class SetupChat extends AsyncTask<Object,Void, Boolean> {

        @Override
        protected Boolean doInBackground(Object... args) {

            try {

                if ((Boolean)args[0]) {
                    mServer = new Server();
                    new Thread(mServer).start();
                } else {
                    String address = args[1].toString();
                    mClient = Client.connect(address);
                    if (mClient == null)
                        return true;
                    new Thread(mClient).start();
                }

            } catch (Exception e) {
                e.printStackTrace();
                return true;
            }
            return false;
        }

        @Override
        protected void onPostExecute(Boolean errors) {

            if (errors)
                Toast.makeText(getApplicationContext(), "Någonting gick fel\nSkrev du in allting rätt?", Toast.LENGTH_LONG).show();
            else
                mDialog.dismiss();

        }
    }

}

这是客户端类

package chat.chris.android.se.chatup.Networking;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;

import chat.chris.android.se.chatup.Listeners.ChatListener;
import chat.chris.android.se.chatup.Listeners.ConnectionListener;
import chat.chris.android.se.chatup.MainActivity;
import chat.chris.android.se.chatup.Utilities.Crypto;

public class Client implements Runnable {

    private BufferedReader reader;
    private DataOutputStream writer;
    private boolean disconnecting;
    private byte[] cryptoKey;
    private String name;
    private static ChatListener chatListener;
    private static ConnectionListener connectionListener;

    //Instansierar ny klient
    public Client(Socket s) throws IOException {

        cryptoKey = new byte[16];

        try {
            reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
            writer = new DataOutputStream(s.getOutputStream());
        } catch (IOException e) {
            disconnect();
            return;
        }

    }

    //Ger klienten ett namn
    public String getName() {
        return name;
    }

    //Sätter namnet
    public void setName(String name) {
        this.name = name;
    }

    public static void setOnChatListener(ChatListener listener) {
        chatListener = listener;
    }

    public static void setOnConnectionListener(ConnectionListener listener) {
        connectionListener = listener;
    }

    public BufferedReader getReader() {
        return reader;
    }

    public byte[] getKey(){
        return cryptoKey;
    }

    public void setKey(byte[] key) {
        cryptoKey = key;
    }


    @Override
    public void run() {
        if (connectionListener != null) {
            connectionListener.onJoin(this);
        }

        try {

            while (!disconnecting) {

                String read;
                if ((read = reader.readLine()) != null) {
                    if (chatListener != null) {
                        chatListener.onChat(Crypto.decrypt(read, cryptoKey));
                    }
                }
                else{
                    return;
                }
                Thread.sleep(5);
            }

        } catch (IOException e) {
            disconnect();
        } catch (Exception e) {
            e.printStackTrace();
            disconnect();
        }
    }

    //Connectar till adressen och returnerar klienten
    public static Client connect(String address) throws IOException {

        MainActivity porten = new MainActivity();
        int PORT;
        PORT = porten.getPORT();

        InetAddress localAddress = InetAddress.getByName(address);
        InetSocketAddress localSocketAddress = new InetSocketAddress(localAddress, PORT);

        Socket socket = new Socket();
        socket.connect(localSocketAddress, 5000);
        Client client = new Client(socket);
        socket.getInputStream().read(client.cryptoKey, 0, 16);

        System.out.println("Client -> " + new String(client.cryptoKey));

        return client;
    }

    public void sendMessage(String message) throws Exception {
        if(message == null || message.isEmpty())
            return;

        writer.writeUTF(Crypto.encrypt(message, cryptoKey));
    }

    public void disconnect() {

        if (connectionListener != null) {
            connectionListener.onDisconnect(this);
        }

        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        reader = null;
        writer = null;

    }
}

这是服务器类

package chat.chris.android.se.chatup.Networking;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Random;

import chat.chris.android.se.chatup.MainActivity;

import static chat.chris.android.se.chatup.Utilities.Constants.MAX_USERS;
//import static chat.chris.android.se.chatup.Utilities.Constants.PORT;

public class Server implements Runnable {

    private ArrayList<Client> clientList;
    private ServerSocket mSocket;
    private byte[] cryptoKey;
    private boolean shuttingDown;
    MainActivity porten = new MainActivity();

    //Instansierar en ny server chatt
    public Server() throws IOException {
        int PORT = porten.getPORT();

        mSocket = new ServerSocket(PORT);
        clientList = new ArrayList<>();

        Random mRand = new SecureRandom();
        cryptoKey = new byte[16];
        mRand.nextBytes(cryptoKey);

        System.out.println("Server ->" + new String(cryptoKey));
    }

    public boolean isShuttingDown() {
        return shuttingDown;
    }

    public void setShuttingDown(boolean shuttingDown) {
        this.shuttingDown = shuttingDown;
    }

    @Override
    public void run() {

        while (!shuttingDown) {
            Socket socket = null;
            Client client;
            try {
                socket = this.mSocket.accept();

                if (clientList.size() >= MAX_USERS) {
                    socket.close();
                    return;
                }

                socket.getOutputStream().write(cryptoKey);
                client = new Client(socket);
                client.setKey(cryptoKey);
                new Thread(client).start();
                clientList.add(client);
            } catch (IOException e) {
                e.printStackTrace();
                try {

                    if (socket != null)
                        socket.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    public void sendMessage(String message) throws Exception {
        for (Client client : clientList) {

            if (shuttingDown)
                return;

            client.sendMessage(message);
        }

    }

    public void shutdown() {
        shuttingDown = true;

        try {
            mSocket.close();
        } catch (IOException e) {
        } finally {
            mSocket = null;
        }

    }
}

使用此设置即可获得以下错误:

05-04 00:41:58.969  12319-12370/chat.chris.android.se.chatup W/System.err﹕ java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-04 00:41:58.970  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at android.os.Handler.<init>(Handler.java:200)
05-04 00:41:58.975  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at android.os.Handler.<init>(Handler.java:114)
05-04 00:41:58.975  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at android.app.Activity.<init>(Activity.java:793)
05-04 00:41:58.975  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at chat.chris.android.se.chatup.MainActivity.<init>(MainActivity.java:32)
05-04 00:41:58.976  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at chat.chris.android.se.chatup.Networking.Server.<init>(Server.java:21)
05-04 00:41:58.976  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at chat.chris.android.se.chatup.MainActivity$SetupChat.doInBackground(MainActivity.java:229)
05-04 00:41:58.976  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at chat.chris.android.se.chatup.MainActivity$SetupChat.doInBackground(MainActivity.java:221)
05-04 00:41:58.976  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at android.os.AsyncTask$2.call(AsyncTask.java:288)
05-04 00:41:58.976  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:237)
05-04 00:41:58.976  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
05-04 00:41:58.976  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
05-04 00:41:58.976  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
05-04 00:41:58.976  12319-12370/chat.chris.android.se.chatup W/System.err﹕ at java.lang.Thread.run(Thread.java:818)

1 个答案:

答案 0 :(得分:2)

从不自己创建ActivityServiceContentProvider的实例。这些是由框架始终创建的。删除:

MainActivity porten = new MainActivity();

通过其他方式将端口传递到奇怪命名的Server类,例如构造函数参数或setter方法。