'How to read-write character devices (like /dev/ttyS0) in Android

I have little knowledge of Java and Android. What I am trying to do is to open /dev/ttyS0 in an Android App which should talk to the serial line, but I am getting lost.

My device is rooted, and from a command line I can "echo ...>/dev/ttyS0" and also read from it, but I get lost trying to do that in Java. For start, I can not find a method to open a file in simple read-write mode, without coping with buffers and other intricacies (clearly, I want unbuffered I/O).

I searched the Internet, but all examples refer to USB which is not available for me. Then I've found the UartDevice class, but it is a class to derive a proper implementation from...

I tried to use the File class, and attach to it both a Reader and a Writer class, but the compiler complains and, frankly, I am not sure it is the way to go. I would need a skeleton code to start from; I miss a simple TextFile class with unbuffered read() and write() methods to be used at the same time on the same open file!

Can someone point me in the right direction thanks?



Solution 1:[1]

After many tries, and with the help of much information from the SO site, I finally succeded in the task. Here is the code:

public class MainActivity
        extends AppCompatActivity {

    File serport;
    private FileInputStream mSerR;
    private FileOutputStream mSerW;

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

        // let this program to access the serial port, and
        // turn off the local echo. sudo() is a routine found here on S.O.
        sudo("chmod a+rw /dev/ttyS0");
        sudo("stty -echo </dev/ttyS0");
        
        // open the file for read and write
        serport = new File("/dev/ttyS0");
        try {
            mSerR = new FileInputStream(serport);
            mSerW = new FileOutputStream(serport);
        } catch (FileNotFoundException e) {}

        // edLine is a textbox where to write a string and send to the port
        final EditText edLine = (EditText) findViewById(R.id.edLine);
        // edTerm is a multiline text box to show the dialog
        final TextView edTerm = findViewById(R.id.edTerm);
        // pressing Enter, the content of edLine is echoed and sent to the port
        edLine.setOnKeyListener(new View.OnKeyListener() {
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                // If the event is a key-down event on the "enter" button
                if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
                    // Perform action on key press
                    String cmd = edLine.getText()+"\n";
                    edTerm.append(cmd);
                    byte[] obuf = cmd.getBytes();
                    try {
                        mSerW.write(obuf);
                    } catch  (IOException e)  {}
                    edLine.setText("");

                    // read the reply; some time must be granted to the server
                    // for replying
                    cmd = "";
                    int b=-1, tries=8;
                    while (tries>0) {
                        try {
                            b = mSerR.read();
                        } catch  (IOException e)  {}
                        if (b==-1) {
                            try {
                                Thread.sleep(5);
                            } catch  (InterruptedException e)  {}
                            --tries;
                        } else {
                            tries=3;    // allow more timeout (more brief)
                            if (b==10) break;
                            cmd = cmd + (char) b;
                        }
                    }
                    // append the received reply to the multiline control
                    edTerm.append(cmd+"\n");
                    return true;
                }
                return false;
            }
        });

    }
}

Please note the presence of the sudo() command in the code: it is there to give r/w permissions to the ttyS0 file, and to disable its echo option. If those permissions+options are already right, or another mean to set them exists, then the sudo() command is not needed.

Note: I believe that the sudo() command implies that the device must be rooted.

Solution 2:[2]

All File access in Java is done via input and output streams. If you want to open a file, you simply create a FileOutputStream or FileInputStream for it. These are unbuffered streams. If you then want to write raw bytes you can wrap that in a ByteArrayOutputStream or ByteArrayInputStream.

To do character mode, you can use a Writer. An OutputStreamWriter with a charset of ascii can wrap the FileOutputStream. That should do the character conversion for you. Just don't use a FileWriter- while it seems like the right fit, it has no option to select a character set, and the default is not ascii. For reading in, use an InputStreamReader.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2