1

I'm working on a small code that uses socket communications on Java and I'm trying to do the following:

  1. Receive a JSON object and parse it [Done]
  2. If the command received was login then start a login [Done]
  3. Print out to the socket the result of the login procedure It's the last portion I'm having trouble with, my code is as follows:

    public class LoginActivity extends Activity {
    
    private Button btnLogin;
    private Button btnDemo;
    private EditText edtLogin;
    private EditText edtSenha;
    
    private ProgressDialog pd;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
    
        btnLogin = (Button)findViewById(R.id.btnLogin);
        btnDemo = (Button)findViewById(R.id.btnDemo);
        edtLogin = (EditText)findViewById(R.id.edtLogin);
        edtSenha = (EditText)findViewById(R.id.edtSenha);
        pd = new ProgressDialog(this);
    
        new Thread(new Runnable(){
            public void run(){
                try {
                    String inMsg;
                    JSONObject fromClient;
                    String cmd;
                    JSONArray args;
                    ServerSocket server;
                    Socket client;
                    BufferedReader in;
                    PrintWriter out;
                    //TODO: Getting reconnects on a proper method
                    System.out.println("Waiting for client on port 8888");
                    server = new ServerSocket(8888);
                    client = server.accept();
                    System.out.println("Just connected to " + client.getRemoteSocketAddress());
                    in = new BufferedReader(new InputStreamReader(client.getInputStream()));
                    out = new PrintWriter(client.getOutputStream(), true);
                    while(true)
                    {
                        inMsg = in.readLine();       
                        if (inMsg == null)
                        {
                            System.out.println("Waiting for client on port 8888");
                            client = server.accept();
                            System.out.println("Just connected to " + client.getRemoteSocketAddress());
                            in = new BufferedReader(new InputStreamReader(client.getInputStream()));
                            out = new PrintWriter(client.getOutputStream(), true);
                            continue;
                        }
                        fromClient = new JSONObject(inMsg);
                        System.out.println("In: " + fromClient);
                        cmd = fromClient.getString("command");
                        args = new JSONArray(fromClient.getString("args"));
                        if(cmd.equals("login")){
                            final String login = args.getString(0);
                            final String pwd = args.getString(1);
                            AndroidUtil.mostrarProgressoAguarde(LoginActivity.this, pd);
    
                            new Thread(new Runnable() {
                                public void run() {
                                    PagPop.getInstance().logar(LoginActivity.this, login, pwd, new ServidorListener<Cliente>() {
                                        @Override
                                        public void recebeuResposta(String mensagem, RespostaServidor<Cliente> resposta) {
                                            handleResposta(mensagem, resposta);
                                        }
                                    });
                                }
                            }).start();
                            //out.println(mensagem);
                        }
    
                        else 
                        {
                            out.println("Received");
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        btnLogin.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                final String login = edtLogin.getText().toString();
                final String senha = edtSenha.getText().toString();
                System.out.print("Tentando Logar");
    
                AndroidUtil.mostrarProgressoAguarde(LoginActivity.this, pd);
    
                new Thread(new Runnable() {
                    public void run() {
                        PagPop.getInstance().logar(LoginActivity.this, login, senha, new ServidorListener<Cliente>() {
                            @Override
                            public void recebeuResposta(String mensagem, RespostaServidor<Cliente> resposta) {
                                handleResposta(mensagem, resposta);
                            }
                        });
                    }
                }).start();
            }
        });
    

Near the middle of the code there is my failed attempt to print out the desired variable at //out.println(mensagem); If I try to compile my code with that the following happens:

[javac] /android/demo/LoginActivity.java:107: error: local variable out is accessed from within inner class; needs to be declared final

[javac] out.println(mensagem);

How can I either transport that variable mensagem out of there so I can out.println it from the if level or access out from that method without making out final?

Bernardo Meurer
  • 2,295
  • 5
  • 31
  • 52
  • Can you try making your `out` variable final? you should be able to move this `out.println(mensagem);` inside `recebeuResposta`. – Gennadii Saprykin Mar 08 '16 at 18:40
  • You can make `out` a class variable. – a_m Mar 08 '16 at 18:41
  • If I make it final would I still be able to do a `out = new PrintWriter(client.getOutputStream(), true);` in case the communication went down(receiving a null)? – Bernardo Meurer Mar 08 '16 at 18:41
  • Possible duplicate of [access to variable within inner class in java](http://stackoverflow.com/questions/3901597/access-to-variable-within-inner-class-in-java) – Solomon Slow Mar 08 '16 at 18:45
  • @jameslarge Not a duplicated; setting it as `final` doesn't serve in this case because out needs to be redefined in case of a connection fail. The question may be similar, but the solution will be different. – Bernardo Meurer Mar 08 '16 at 18:48
  • 1
    The problem here is nothing to do with android or multithreading or sockets. It's strictly a Java language thing: An inner class may not refer to a local variable from an enclosing scope unless the variable is (effectively) `final`. In older Java versions, the variable had to actually be _declared_ `final`. In Java8 it is sufficient that the variable is not modified anywhere in scope after its initial assignment. – Solomon Slow Mar 08 '16 at 18:49
  • @jameslarge The solution you give doesn't solve the problem and that doesn't matter? Let's all just give random answers then huh? As Xoce proved there is indeed another answer that does work, different from your alleged duplicate. – Bernardo Meurer Mar 08 '16 at 18:54

1 Answers1

1

Declare PrintWriter out as a global variable in the activity / fragment

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97