• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Android bluetooth app crashing

Teneppa

Lurker
Hey! I'm trying to code an application to communicate with the HC-06 (Serial bluetooth module). I'm trying to implement a joystick or more like a touchpad to control robotic arm. I would have used NRF24L01 chip with another microcontroller but I thought I could take a look how to code android; I've always wanted to code for phones but I've never got anything working out of it. Hope someone could help me to begin coding java for android.

Java:
package com.example.teemu.copied;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;

//package Android.Arduino.Bluetooth;

public class MainActivity extends Activity
{
    TextView myLabel;
    EditText myTextbox;
    BluetoothAdapter mBluetoothAdapter;
    BluetoothSocket mmSocket;
    BluetoothDevice mmDevice;
    OutputStream mmOutputStream;
    InputStream mmInputStream;
    Thread workerThread;
    byte[] readBuffer;
    int readBufferPosition;
    int counter;
    volatile boolean stopWorker;

    //NAME THE DEVICE
    String BT_NAME = "unnamed";

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

        Button openButton = (Button) findViewById(R.id.open);
        Button sendButton = (Button) findViewById(R.id.send);
        Button closeButton = (Button) findViewById(R.id.close);

        Button joystick = (Button) findViewById(R.id.b_joystic);

        myLabel = (TextView) findViewById(R.id.label);
        myTextbox = (EditText) findViewById(R.id.entry);

        joystick.setOnTouchListener(new View.OnTouchListener() {

            public boolean onTouch(View v, MotionEvent event) {
                int x = (int) event.getRawX();
                int y = (int) event.getRawY();

                TextView xt = (TextView) findViewById(R.id.x_txt);
                TextView yt = (TextView) findViewById(R.id.y_txt);

                xt.setText(x);
                yt.setText(y);

                return true;
            }
        });

        //Open Button
        openButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    findBT();
                    openBT();
                } catch (IOException ex) {
                }
            }
        });

        //Send Button
        sendButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    sendData();
                } catch (IOException ex) {
                }
            }
        });

        //Close button
        closeButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    closeBT();
                } catch (IOException ex) {
                }
            }
        });
    }

    void findBT()
    {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if(mBluetoothAdapter == null)
        {
            myLabel.setText("No bluetooth adapter available");
        }

        if(!mBluetoothAdapter.isEnabled())
        {
            Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBluetooth, 0);
        }

        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        if(pairedDevices.size() > 0)
        {
            for(BluetoothDevice device : pairedDevices)
            {
                if(device.getName().equals(BT_NAME))
                {
                    mmDevice = device;
                    break;
                }
            }
        }
        myLabel.setText("Bluetooth Device Found");
    }

    void openBT() throws IOException
    {
        UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //Standard SerialPortService ID
        mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
        mmSocket.connect();
        mmOutputStream = mmSocket.getOutputStream();
        mmInputStream = mmSocket.getInputStream();

        beginListenForData();

        myLabel.setText("Bluetooth Opened");
    }

    void beginListenForData()
    {
        final Handler handler = new Handler();
        final byte delimiter = 10; //This is the ASCII code for a newline character

        stopWorker = false;
        readBufferPosition = 0;
        readBuffer = new byte[1024];
        workerThread = new Thread(new Runnable()
        {
            public void run()
            {
                while(!Thread.currentThread().isInterrupted() && !stopWorker)
                {
                    try
                    {
                        int bytesAvailable = mmInputStream.available();
                        if(bytesAvailable > 0)
                        {
                            byte[] packetBytes = new byte[bytesAvailable];
                            mmInputStream.read(packetBytes);
                            for(int i=0;i<bytesAvailable;i++)
                            {
                                byte b = packetBytes[i];
                                if(b == delimiter)
                                {
                                    byte[] encodedBytes = new byte[readBufferPosition];
                                    System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
                                    final String data = new String(encodedBytes, "US-ASCII");
                                    readBufferPosition = 0;

                                    handler.post(new Runnable()
                                    {
                                        public void run()
                                        {
                                            myLabel.setText(data);
                                        }
                                    });
                                }
                                else
                                {
                                    readBuffer[readBufferPosition++] = b;
                                }
                            }
                        }
                    }
                    catch (IOException ex)
                    {
                        stopWorker = true;
                    }
                }
            }
        });

        workerThread.start();
    }

    void sendData() throws IOException
    {
        String msg = myTextbox.getText().toString();
        msg += "\n";
        mmOutputStream.write(msg.getBytes());
        myLabel.setText("Data Sent");
    }

    void closeBT() throws IOException
    {
        stopWorker = true;
        mmOutputStream.close();
        mmInputStream.close();
        mmSocket.close();
        myLabel.setText("Bluetooth Closed");
    }
}

Code:
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    tools:ignore="TextFields,HardcodedText" >

    <TextView
        android:id="@+id/label"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Type here:"
        android:layout_above="@+id/entry"
        android:layout_alignParentStart="true" />

    <EditText
        android:id="@+id/entry"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@android:drawable/editbox_background"
        android:layout_above="@+id/open"
        android:layout_alignParentStart="true"
        android:layout_marginBottom="22dp" />

    <Button
        android:id="@+id/open"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dip"
        android:text="Open"
        android:layout_alignBaseline="@+id/close"
        android:layout_alignBottom="@+id/close"
        android:layout_centerHorizontal="true" />

    <Button
        android:id="@+id/send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send"
        android:layout_marginEnd="26dp"
        android:layout_alignBaseline="@+id/open"
        android:layout_alignBottom="@+id/open"
        android:layout_alignParentEnd="true" />

    <Button
        android:id="@+id/close"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Close"
        android:layout_marginStart="23dp"
        android:layout_marginBottom="20dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true" />

    <Button
        android:id="@+id/b_joystic"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_alignEnd="@+id/send"
        android:layout_alignStart="@+id/close"
        android:layout_below="@+id/y_txt"
        android:layout_marginTop="14dp"
        android:backgroundTint="?android:attr/colorControlNormal"
        android:elevation="0dp"
        android:visibility="visible" />

    <TextView
        android:id="@+id/x_txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:text="TextView" />

    <TextView
        android:id="@+id/y_txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignEnd="@+id/x_txt"
        android:layout_below="@+id/x_txt"
        android:text="TextView" />

</RelativeLayout>
 
Do you mean this?

Code:
09-08 19:06:49.716 13587-13587/com.example.teemu.copied E/InputEventReceiver: Exception dispatching input event.
09-08 19:06:49.716 13587-13587/com.example.teemu.copied E/MessageQueue-JNI: Exception in MessageQueue callback: handleReceiveCallback
09-08 19:06:49.717 13587-13587/com.example.teemu.copied E/MessageQueue-JNI: android.content.res.Resources$NotFoundException: String resource ID #0x2ec
                                                                                at android.content.res.Resources.getText(Resources.java:312)
                                                                                at android.widget.TextView.setText(TextView.java:4422)
                                                                                at com.example.teemu.copied.MainActivity$1.onTouch(MainActivity.java:65)
                                                                                at android.view.View.dispatchTouchEvent(View.java:9296)
                                                                                at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
                                                                                at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
                                                                                at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
                                                                                at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
                                                                                at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
                                                                                at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
                                                                                at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
                                                                                at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
                                                                                at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403)
                                                                                at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737)
                                                                                at android.app.Activity.dispatchTouchEvent(Activity.java:2771)
                                                                                at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364)
                                                                                at android.view.View.dispatchPointerEvent(View.java:9520)
                                                                                at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230)
                                                                                at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096)
                                                                                at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
                                                                                at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
                                                                                at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
                                                                                at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787)
                                                                                at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
                                                                                at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844)
                                                                                at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
                                                                                at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
                                                                                at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
                                                                                at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
                                                                                at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
                                                                                at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5922)
                                                                                at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5896)
                                                                                at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5857)
                                                                                at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6025)
                                                                                at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
                                                                                at android.os.MessageQueue.nativePollOnce(Native Method)
                                                                                at android.os.MessageQueue.next(MessageQueue.java:323)
                                                                                at android.os.Looper.loop(Looper.java:135)
                                                                                at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                                at java.lang.reflect.Method.invoke(Native Method)
                                                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
09-08 19:06:49.717 13587-13587/com.example.teemu.copied D/AndroidRuntime: Shutting down VM
09-08 19:06:49.718 13587-13587/com.example.teemu.copied E/AndroidRuntime: FATAL EXCEPTION: main
                                                                          Process: com.example.teemu.copied, PID: 13587
                                                                          android.content.res.Resources$NotFoundException: String resource ID #0x2ec
                                                                              at android.content.res.Resources.getText(Resources.java:312)
                                                                              at android.widget.TextView.setText(TextView.java:4422)
                                                                              at com.example.teemu.copied.MainActivity$1.onTouch(MainActivity.java:65)
                                                                              at android.view.View.dispatchTouchEvent(View.java:9296)
                                                                              at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
                                                                              at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
                                                                              at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
                                                                              at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
                                                                              at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
                                                                              at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
                                                                              at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
                                                                              at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
                                                                              at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403)
                                                                              at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737)
                                                                              at android.app.Activity.dispatchTouchEvent(Activity.java:2771)
                                                                              at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364)
                                                                              at android.view.View.dispatchPointerEvent(View.java:9520)
                                                                              at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230)
                                                                              at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096)
                                                                              at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
                                                                              at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
                                                                              at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
                                                                              at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787)
                                                                              at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
                                                                              at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844)
                                                                              at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
                                                                              at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
                                                                              at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
                                                                              at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
                                                                              at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
                                                                              at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5922)
                                                                              at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5896)
                                                                              at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5857)
                                                                              at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6025)
                                                                              at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
                                                                              at android.os.MessageQueue.nativePollOnce(Native Method)
                                                                              at android.os.MessageQueue.next(MessageQueue.java:323)
                                                                              at android.os.Looper.loop(Looper.java:135)
                                                                              at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                              at java.lang.reflect.Method.invoke(Native Method)
                                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
 
If you read the stack trace error, this part of it tells you which line of your code caused the problem

Code:
at com.example.teemu.copied.MainActivity$1.onTouch(MainActivity.java:65)

This line is causing the problem

Code:
xt.setText(x);

So looking at the reference documentation for TextView, you can see that method setText() has two variants

https://developer.android.com/reference/android/widget/TextView.html#setText(int)

One of them takes an int parameter type, which should refer to a resource id.
The other one takes a CharSequence (String) parameter type. You should be using this one.
So to display your value (x), you need to convert this int value to a String.
I'll let you try and figure that out.
 
Seems like using
xt.setText(String.valueOf(x));
yt.setText(String.valueOf👍);
fixes that problem.

Theres only one more problem: the crashing if the bluetooth is off or if the device isn't paired.
Such a shame that the part is still on it's way so I can't develop this a whole lot further...

Seems like a null variable error. How I can avoid those? I have been coding only c++ so this is quite an experience for me ;)

Code:
9-08 17:48:47.274 4478-4528/com.example.teemu.copied E/eglCodecCommon: glUtilsParamSize: unknow param 0x000082da
09-08 17:48:47.274 4478-4528/com.example.teemu.copied E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008cdf
09-08 17:48:47.274 4478-4528/com.example.teemu.copied E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008824
09-08 17:48:47.293 4478-4528/com.example.teemu.copied D/EGL_emulation: eglMakeCurrent: 0x7fa8c215cf40: ver 3 1 (tinfo 0x7fa8c2147940)
09-08 17:48:49.141 4478-4478/com.example.teemu.copied E/BluetoothAdapter: Bluetooth binder is null
09-08 17:48:49.141 4478-4478/com.example.teemu.copied D/AndroidRuntime: Shutting down VM
09-08 17:48:49.141 4478-4478/com.example.teemu.copied E/AndroidRuntime: FATAL EXCEPTION: main
                                                                        Process: com.example.teemu.copied, PID: 4478
                                                                        java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.bluetooth.BluetoothAdapter.isEnabled()' on a null object reference
                                                                            at com.example.teemu.copied.MainActivity.findBT(MainActivity.java:112)
                                                                            at com.example.teemu.copied.MainActivity$2.onClick(MainActivity.java:76)
                                                                            at android.view.View.performClick(View.java:5198)
                                                                            at android.view.View$PerformClick.run(View.java:21147)
                                                                            at android.os.Handler.handleCallback(Handler.java:739)
                                                                            at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                            at android.os.Looper.loop(Looper.java:148)
                                                                            at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                            at java.lang.reflect.Method.invoke(Native Method)
                                                                            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

-edit-

Come on.. more bugs! This time Attempt to invoke virtual method 'void java.io.OutputStream.write(byte[])' on a null object reference
Absolutely no idea what that means :X

Code:
09-08 17:56:24.936 10336-10336/com.example.teemu.copied E/AndroidRuntime: FATAL EXCEPTION: main
                                                                          Process: com.example.teemu.copied, PID: 10336
                                                                          java.lang.NullPointerException: Attempt to invoke virtual method 'void java.io.OutputStream.write(byte[])' on a null object reference
                                                                              at com.example.teemu.copied.MainActivity.sendData(MainActivity.java:210)
                                                                              at com.example.teemu.copied.MainActivity$3.onClick(MainActivity.java:87)
                                                                              at android.view.View.performClick(View.java:5198)
                                                                              at android.view.View$PerformClick.run(View.java:21147)
                                                                              at android.os.Handler.handleCallback(Handler.java:739)
                                                                              at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                              at android.os.Looper.loop(Looper.java:148)
                                                                              at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                              at java.lang.reflect.Method.invoke(Native Method)
                                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
 
Last edited:
If you've coded C++ before, you must know that bad things happen if you try and de-reference a null pointer. Similarly in Java, if you declare an object variable, but don't allocate any memory before using it, then you get a NullPointerException. That's actually more help than C++ gives you, which in most cases your program will just bomb out without any clue what happened.
The stack trace you get from the Java stack trace is pretty clear what the problem is - mmOutputStream is null.
 
Back
Top Bottom