마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

OnClickListener와 btn이 코드에서 이용되지 않다고 뜹니다

0 추천
package com.example.testteststest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.DisconnectedBufferOptions;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import org.w3c.dom.Text;

public class MainActivity extends AppCompatActivity {

    private MqttAndroidClient mqttAndroidClient;
    private Button btn1;
    private MqttConnectOptions getMqttConnectionOption(){
        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
        mqttConnectOptions.setCleanSession(false);
        mqttConnectOptions.setAutomaticReconnect(true);
        mqttConnectOptions.setWill("aaa", "I am going offline".getBytes(), 1, true);
        return mqttConnectOptions;
    }
    private DisconnectedBufferOptions getDisconnectedBufferOptions() {
        DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
        disconnectedBufferOptions.setBufferEnabled(true);
        disconnectedBufferOptions.setBufferSize(100);
        disconnectedBufferOptions.setPersistBuffer(true);
        disconnectedBufferOptions.setDeleteOldestMessages(false);
        return disconnectedBufferOptions;
    }

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

        final TextView txt1 = new TextView(this);
        txt1.setText("");
        setContentView(txt1);
        Button btn1 = (Button) findViewById(R.id.btn1);
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String ClientId = MqttClient.generateClientId();
                mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), "tcp://192.168.137.209:1883", ClientId);
                Toast.makeText(getApplicationContext(), "connect 시도중...", Toast.LENGTH_LONG).show();
            }
        });

        try {
            IMqttToken token = mqttAndroidClient.connect(getMqttConnectionOption());
            token.setActionCallback((new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    mqttAndroidClient.setBufferOpts(getDisconnectedBufferOptions());
                    Log.e("Connect Success", "Success");

                    try {
                        mqttAndroidClient.subscribe("test", 2, new IMqttMessageListener() {
                            @Override
                            public void messageArrived(String topic, MqttMessage message) throws Exception {
                                String msg = new String(message.getPayload());
                                txt1.setText(msg);
                            }
                        });
                    } catch (MqttException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    Log.e("connect fail", "Failure " + exception.toString());
                }
            }));
        } catch (MqttException e) {
            e.printStackTrace();
        }

        mqttAndroidClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable cause) {

            }

            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                if (topic.equals("test")) {
                    String msg = new String(message.getPayload());
                }
            }

            @Override
            public void
            deliveryComplete(IMqttDeliveryToken token) {

            }
        });
    }
}

버튼을 누르면 어플에서 MQTT 브로커에 연결해 센서값을 받아오는 기능을 구현하고싶습니다.
그러나 아직 android studio를 공부한지 2주정도밖에 되지않아 구현에 어려움을 겪고 있습니다. 고수님들의 도움을 얻고자 질문글 올립니다!
먼저 import android.view.View.OnClickListener; , private Button btn1; 부분이 사용되지않았다고 회색으로 뜨는 부분이 앱실행 실패가 된다고 생각하였는데 이를 해결하려면 어떻게 해야할지 조언을 얻고싶습니다.

KimYS (120 포인트) 님이 2022년 11월 27일 질문
로그캣부분이 잘 안보여서 댓글에 적겠습니다!FATAL EXCEPTION: main
Process: com.example.testteststest, PID: 1913
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.testteststest/com.example.testteststest.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3676)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3813)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2308)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7898)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.example.testteststest.MainActivity.onCreate(MainActivity.java:53)
at android.app.Activity.performCreate(Activity.java:8290)
at android.app.Activity.performCreate(Activity.java:8269)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1384)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3657)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3813) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2308) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loopOnce(Looper.java:201) 
at android.os.Looper.loop(Looper.java:288) 
at android.app.ActivityThread.main(ActivityThread.java:7898) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) 

2개의 답변

0 추천

에러 메세지를 잘 들여다 보시면 원인과 해결책이 나옵니다.

ava.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference

-> Button이 널인데, setOnClickListener를 호출한 걸로 보이네요. Butto이 왜 널이 되는지 확인하세요.

...
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)

-> LaunchActivityItem의 101번째 라인에서 에러가 발생했습니다.

올리신 코드에서 아마도 아래 코드가 에러가 나는 부분인 듯 싶습니다.

Button btn1 = (Button) findViewById(R.id.btn1); //btn이 널임
btn1.setOnClickListener(new View.OnClickListener() {...}

따라서 레이아웃에 btn1인 뷰가 존재하는지, 존재한다면 Button타입이 맞는지 확인하세요.

spark (224,800 포인트) 님이 2022년 11월 27일 답변
0 추천

@Override
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main); // 화면 레이아웃 지정

       final TextView txt1 = new TextView(this);
       txt1.setText("");
       setContentView(txt1); <--- 화면 레이아웃 재지정. 텍스트뷰로 화면 지정

       ...
}

작성하신 코드를 보면 setContentView 를 두번 호출하여 레이아웃을 교체하도록 되어있습니다. 
마지막으로 변경된 씬에는 텍스트뷰만 있어서 버튼 호출이 불가하겠습니다.

익명 님이 2022년 11월 28일 답변
답변 감사합니다!
말씀해주신 화면 레이아웃 지정하는 부분을 onclick함수 내에 넣고 진행하였더니 앱 실행이 되었습니다. 이후 mqtt 브로커와 연결하는 부분은 추후 실험 후에 다시 댓글 달겠습니다.
...