Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong cast if received Byte is bigger than 127 #10

Closed
Samyssmile opened this issue Aug 5, 2016 · 14 comments
Closed

Wrong cast if received Byte is bigger than 127 #10

Samyssmile opened this issue Aug 5, 2016 · 14 comments

Comments

@Samyssmile
Copy link

Samyssmile commented Aug 5, 2016

Hello Guys, great work you done.

We had for last Days some trouble with this API. Its exactly Issue#9. You wrote that you fixed it but it was not fixed.

Problem: If our App recieve byte 128 (hax 80), this lib read it as -128 and wrong hex.

We all know this happen because of signed Bytes in Java.

Workaround: SPPService.java
Replace this:
mHandler.obtainMessage(BluetoothSerial.MESSAGE_READ, bytes, -1, read.getBytes()).sendToTarget();

with this

mHandler.obtainMessage(BluetoothSerial.MESSAGE_READ, bytes, -1, read.getBytes(StandardCharsets.US_ASCII)).sendToTarget();

If you do this changes, issue like #9 never happen again. In most of usecases with SPP we think US_ASCII as default is much better....

Great work keep on.

@viethoa
Copy link

viethoa commented Aug 19, 2016

On the SPPSerive file, find ConnectedThread class and replace Run function by this:

public void run() {

        byte[] data = new byte[1024];
        int bytes;

        while (true) {
            try {
                bytes = mInputStream.read(data);
                String read = new String(data, 0, bytes, Charset.forName("ISO-8859-1"));
                mHandler.obtainMessage(BluetoothSerial.MESSAGE_READ, bytes, -1, read.getBytes(Charset.forName("ISO-8859-1"))).sendToTarget();
            } catch (IOException e) {
                reconnect(); // Connection lost
                SPPService.this.start();
                break;
            }
        }
    }

One more thing, You should check the UUID_SP, I am not sure I have edited it before, Btw now it look like this:
private static final UUID UUID_SPP = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

@bayudwirp
Copy link

Hello @Samyssmile
I've tried your suggestion to replace

mHandler.obtainMessage(BluetoothSerial.MESSAGE_READ, bytes, -1, read.getBytes()).sendToTarget();

With this :
mHandler.obtainMessage(BluetoothSerial.MESSAGE_READ, bytes, -1, read.getBytes(StandardCharsets.US_ASCII)).sendToTarget();

and it will always give 63 if we receive byte 128 to 255.

Any suggestion to solve the problem?

@MacroYau
Copy link
Owner

@bayudwirp Have your tried using BluetoothSerialRawListener?

@bayudwirp
Copy link

Hi @MacroYau ,
I've tried using BluetoothSerialRawListener and it give me same result. It will always give 63 if i receive byte from 128 to 255 but, if i receive byte from 0 until 127 it has no problem.

Have you any other suggestion to solve this problem?

@MacroYau
Copy link
Owner

@bayudwirp Would you mind showing your actual code implementation?

@bayudwirp
Copy link

bayudwirp commented Jan 23, 2017

Of course @MacroYau .
I'm trying to create an application that reads the input data from bluetooth (Based on the example of a chat application that you created), then the data are presented in into a decimal value.
The data that I send, will only have a range between 0 - 255 (00 - FF Hexadecimal).
And this is an example of the program that was I made:
(You can check part onBluetoothSerialRead)
(MainActivity.java)

package in.bayudwirp.testing;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

import com.macroyau.blue2serial.BluetoothDeviceListDialog;
import com.macroyau.blue2serial.BluetoothSerial;
import com.macroyau.blue2serial.BluetoothSerialListener;
import com.macroyau.blue2serial.BluetoothSerialRawListener;


public class MainActivity extends AppCompatActivity implements BluetoothSerialListener, BluetoothDeviceListDialog.OnDeviceSelectedListener, BluetoothSerialRawListener
{

    private static final int REQUEST_ENABLE_BLUETOOTH = 1;

    private BluetoothSerial bluetoothSerial;

    private MenuItem actionConnect, actionDisconnect;

    public  int bluetooth_status_flag = 0;
    public  String data_bluetooth_string = "";
    public  String data_bluetooth_string_konversi = "";
    public  int data_bluetooth_int = 0;
    public  byte[] data_bluetooth_byte;
    public  TextView textView1;

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

        textView1 = (TextView) findViewById(R.id.textView);

        // Bagian Bluetooth SPP
        // Create a new instance of BluetoothSerial
        bluetoothSerial = new BluetoothSerial(this, this);

    }

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

        // Check Bluetooth availability on the device and set up the Bluetooth adapter
        bluetoothSerial.setup();
    }

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

        // Open a Bluetooth serial port and get ready to establish a connection
        if (bluetoothSerial.checkBluetooth() && bluetoothSerial.isBluetoothEnabled()) {
            if (!bluetoothSerial.isConnected()) {
                bluetoothSerial.start();
            }
        }
    }

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

        // Disconnect from the remote device and close the serial port
        bluetoothSerial.stop();
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_terminal, menu);

        actionConnect = menu.findItem(R.id.action_connect);
        actionDisconnect = menu.findItem(R.id.action_disconnect);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_connect) {
            showDeviceListDialog();
            return true;
        } else if (id == R.id.action_disconnect) {
            bluetoothSerial.stop();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void invalidateOptionsMenu() {
        if (bluetoothSerial == null)
            return;

        // Show or hide the "Connect" and "Disconnect" buttons on the app bar
        if (bluetoothSerial.isConnected()) {
            if (actionConnect != null)
                actionConnect.setVisible(false);
            if (actionDisconnect != null)
                actionDisconnect.setVisible(true);
        } else {
            if (actionConnect != null)
                actionConnect.setVisible(true);
            if (actionDisconnect != null)
                actionDisconnect.setVisible(false);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode) {
            case REQUEST_ENABLE_BLUETOOTH:
                // Set up Bluetooth serial port when Bluetooth adapter is turned on
                if (resultCode == Activity.RESULT_OK) {
                    bluetoothSerial.setup();
                }
                break;
        }
    }

    private void updateBluetoothState() {
        // Get the current Bluetooth state
        final int state;
        if (bluetoothSerial != null)
            state = bluetoothSerial.getState();
        else
            state = BluetoothSerial.STATE_DISCONNECTED;

        // Display the current state on the app bar as the subtitle
        String subtitle;
        switch (state) {
            case BluetoothSerial.STATE_CONNECTING:
                subtitle = getString(R.string.status_connecting);
                break;
            case BluetoothSerial.STATE_CONNECTED:
                subtitle = getString(R.string.status_connected, bluetoothSerial.getConnectedDeviceName());
                break;
            default:
                subtitle = getString(R.string.status_disconnected);
                break;
        }

        if (getSupportActionBar() != null) {
            getSupportActionBar().setSubtitle(subtitle);
        }
    }

    private void showDeviceListDialog() {
        // Display dialog for selecting a remote Bluetooth device
        BluetoothDeviceListDialog dialog = new BluetoothDeviceListDialog(this);
        dialog.setOnDeviceSelectedListener(this);
        dialog.setTitle(R.string.paired_devices);
        dialog.setDevices(bluetoothSerial.getPairedDevices());
        dialog.showAddress(true);
        dialog.show();
    }

    /* Implementation of BluetoothSerialListener */
    @Override
    public void onBluetoothNotSupported() {
        new AlertDialog.Builder(this)
                .setMessage(R.string.no_bluetooth)
                .setPositiveButton(R.string.action_quit, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        finish();
                    }
                })
                .setCancelable(false)
                .show();
    }

    @Override
    public void onBluetoothDisabled() {
        Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBluetooth, REQUEST_ENABLE_BLUETOOTH);
    }

    @Override
    public void onBluetoothDeviceDisconnected() {
        invalidateOptionsMenu();
        updateBluetoothState();
        bluetooth_status_flag = 0;
    }

    @Override
    public void onConnectingBluetoothDevice() {
        updateBluetoothState();
    }

    @Override
    public void onBluetoothDeviceConnected(String name, String address) {
        invalidateOptionsMenu();
        updateBluetoothState();
        bluetooth_status_flag = 1;
    }

    @Override
    public void onBluetoothSerialRead(String message) {
        // Print the incoming message on the terminal screen
        data_bluetooth_string = message;
        data_bluetooth_string_konversi = asciiToHex(data_bluetooth_string);
        data_bluetooth_int = Integer.parseInt(data_bluetooth_string_konversi,16);
        textView1.setText("Data :"+data_bluetooth_int);                             // Data from bluetooth, will show in Integer Format
    }

    @Override
    public void onBluetoothSerialWrite(String message) {
        // Print the outgoing message on the terminal screen
        /*tvTerminal.append(getString(R.string.terminal_message_template,
                bluetoothSerial.getLocalAdapterName(),
                message));
        svTerminal.post(scrollTerminalToBottom);*/
    }

    @Override
    public void onBluetoothSerialReadRaw(byte[] bytes){
        //data_bluetooth_byte = bytes;
    }

    @Override
    public void onBluetoothSerialWriteRaw(byte[] bytes){}

    /* Implementation of BluetoothDeviceListDialog.OnDeviceSelectedListener */

    @Override
    public void onBluetoothDeviceSelected(BluetoothDevice device) {
        // Connect to the selected remote Bluetooth device
        bluetoothSerial.connect(device);
    }

    /* End of the implementation of listeners */
    private final Runnable scrollTerminalToBottom = new Runnable() {
        @Override
        public void run() {
            // Scroll the terminal screen to the bottom
            // svTerminal.fullScroll(ScrollView.FOCUS_DOWN);
        }
    };

    /* Convert ASCII String to Hexadecimal Value */
    private static String asciiToHex(String asciiValue)
    {
        char[] chars = asciiValue.toCharArray();
        StringBuffer hex = new StringBuffer();
        for (int i = 0; i < chars.length; i++)
        {
            hex.append(Integer.toHexString((int) chars[i]));
        }
        return hex.toString();
    }
}

And this script below is ActivityMain.xml
(ActivityMain.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <TextView
        android:text="TextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_marginRight="36dp"
        android:layout_marginEnd="36dp" />



</RelativeLayout>

Any suggestion from you, will be appreciated.
Thankyou.

@MacroYau
Copy link
Owner

@bayudwirp My suggestions:

  1. Remove the BluetoothSerialListener interface, and use BluetoothSerialRawListener only (and migrate the methods accordingly, of course).
  2. Use the following code in onBluetoothSerialReadRaw() to verify the output:
for (byte b : bytes)
    System.out.println("Read: " + (int) b & 0xFF);

@bayudwirp
Copy link

Thank you very much for your suggestion @MacroYau , very appreciate for you to helping me.
But, after I followed your suggestion to remove part BluetoothSerialListener interface, and then use only BluetoothSerialRawListener and use the code you suggest,

for (byte b : bytes)
    System.out.println("Read: " + (int) b & 0xFF);

the results remain as before, issued a byte value of 63 when it receives 128-255. I didn't know, how could this happen again.

@MacroYau
Copy link
Owner

@bayudwirp Your problem looks like #9 which should have already fixed... Can you try to log the incoming bit patterns as well?

@bayudwirp
Copy link

@MacroYau yes, i think so. But, i've tried to use your solution in #9 before i tried #10 solution. And, i've got value 65533, if i receive byte 128 - 255.

@MacroYau
Copy link
Owner

@bayudwirp How about the sending side? Is it really transmitting 128 to 255?

@bayudwirp
Copy link

@MacroYau I didn't try about sending side. But, if i try to sending character from your example apps (Blue2Serial), such as sending characters "name" (below byte 127, if we convert every characters to ASCII) there is no problem, but if i try to send specials character (above byte 127), it always receive not only the character that i was send, but also receive another random character.

@bayudwirp
Copy link

Hi @MacroYau

I've tried again about your suggestion to using BluetoothSerialRawListener and using this code

for (byte b : bytes)
    System.out.println("Read: " + (int) b & 0xFF);

and, i tried to restore a default SPPService.java (maybe i made mistake to change something on this file)
And i try to test again, and now its works fine.

Thankyou very much, for helping me. Have a good day for you :)

@MacroYau
Copy link
Owner

Great to hear that! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants