Android - 通过蓝牙传递对象

时间:2011-06-08 07:18:52

标签: java android bluetooth

Android的蓝牙聊天示例对于学习如何在手机之间传递字符串非常有用 - 是否可以使用相同的代码在手机之间传递对象?我在两部手机中定义了相同的类,我只想将一个类的实例从一个手机传递到另一个手机。有可用的示例代码吗?我尝试使用序列化并使用objectoutputstream和objectinputstream替换聊天示例中的outputstream和inputstream,但它似乎无法正常工作

6 个答案:

答案 0 :(得分:7)

我发现处理此问题的最佳方法如下:

  1. 我将我的对象设置为实现我想发送的Serializable。
  2. 我设置了以下代码来管理消息:

    public byte[] serialize() throws IOException {
        ByteArrayOutputStream b = new ByteArrayOutputStream();
        ObjectOutputStream o = new ObjectOutputStream(b);
        o.writeObject(this);
        return b.toByteArray();
    }
    //AbstractMessage was actually the message type I used, but feel free to choose your own type
    public static AbstractMessage deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream b = new ByteArrayInputStream(bytes);
        ObjectInputStream o = new ObjectInputStream(b);
        return (AbstractMessage) o.readObject();
    
  3. 我更改了write语句以接受Serializable,然后进行最后的写:

    /**
     * Write to the connected OutStream.
     * @param buffer  The bytes to write
     */
    public void write(AbstractMessage buffer) {
        try {
            Log.v(TAG,"Writing \""+(buffer.serialize())+"\"");
            mmOutStream.write(buffer.serialize());
    
            // Share the sent message back to the UI Activity
            mHandler.obtainMessage(AbstractMessageManager.MESSAGE_WRITE, -1, -1, buffer)
                    .sendToTarget();
        } catch (IOException e) {
            Log.e(TAG, "Exception during write", e);
        }
    }
    

答案 1 :(得分:2)

蓝牙聊天示例演示了如何使用基于RFCOMM的串行端口配置文件(SPP)。建立连接后,您可以串行发送任何您喜欢的数据;您只需要能够将对象表示为串行字节流,即序列化它们。

因此,使用序列化肯定是通过链接发送对象的一种方式。蓝牙API的发送和接收功能处理字节数组,但您可以轻松地调整蓝牙聊天示例以使用流,例如send函数将从流中读取字节并将它们放入数组缓冲区,然后发送该缓冲区等。然后应用程序代码将简单地通过输入和输出流管道进行通信 - 这是我在过去。

所以你的实际想法没有错。更大的问题是你实施它的方式不对,更有问题的是,你提出问题的方式也很差。您需要更准确地描述 无效的内容,解释您已经尝试过的调试,并发布代码示例和Logcat输出,以便我们可以正确地帮助您。

最后,我确实发现了我认为蓝牙聊天代码示例中的错误:数据接收功能将接收字节数组的引用传递给用于显示接收到的每行文本的ArrayList。当传输少量慢速文本时,这是正常的,但是当您尝试发送大量数据时,您开始看到数据被破坏,可能是因为ArrayList适配器仍然在读取相同数组的字节时数组正在填充更新的数据。

答案 2 :(得分:0)

Trev16v, 首先,感谢您的初步反馈。

为了序列化我的对象,我使用了类serializeObject和deserializeObject http://www.jondev.net/articles/Android_Serialization_Example_(Java) 它们似乎运行良好:如果我从一个电话/活动序列化一个对象(由一个实现Serializable的类创建)并从同一个手机反序列化,我设法从生成的byte []中获取一个对象。

然后,我尝试在奥德蓝牙聊天示例中的蓝牙聊天服务类中使用相同的代码,将序列化对象发送到另一部手机(在该示例中有

    public ConnectedThread(BluetoothSocket socket) {
        Log.d(TAG, "create ConnectedThread");
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;

        // Get the BluetoothSocket input and output streams
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) {
            Log.e(TAG, "temp sockets not created", e);
        }

        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }

并使用

传递字节
public void write(byte[] buffer) {
        try {
            mmOutStream.write(buffer);

            // Share the sent message back to the UI Activity
            mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
                    .sendToTarget();
        } catch (IOException e) {
            Log.e(TAG, "Exception during write", e);
        }
    }

并使用

阅读
   public void run() {
        Log.i(TAG, "BEGIN mConnectedThread");
        byte[] buffer = new byte[10240];
        int bytes;
        // Keep listening to the InputStream while connected
        while (true) {
            try {
                // Read from the InputStream
                bytes = mmInStream.read(buffer);

                    // Send the obtained bytes to the UI Activity
                mHandler.obtainMessage(BluetoothManageActivity.MESSAGE_READ, bytes, -1, buffer)
                        .sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "disconnected", e);
                connectionLost();
                break;
            }
        }
    }

使用BluetoothChatServices的问题在于,另一部手机上接收的字节数组与序列化对象时发送的字节数不同。例如,当我发送它时,给出seriealized对象的一个​​想法元素[0]是= -84,我从另一个手机接收的那个元素[0]到[4] = 0,然后[5] = 4而且所有其他元素也没有对齐。我尝试使用上面的方法编写并运行以使用ObjectInputStream和ObjectOutputstream更改Inputstream和Outputstream但是没有成功(如果这应该是实现它的方式,我可以发布我尝试使用的代码)

再次,非常感谢你的帮助,我是所有这些概念的新手,所以如果我说废话,我也很乐意接受教程

感谢

答案 3 :(得分:0)

答案是肯定的。 String是一个Object。记得?但究竟如何做到这一点,我仍在寻找解决方案,这就是我带来的原因......

答案 4 :(得分:0)

遇到同样的问题......当我从一个Android设备发送一系列对象时,数据正常发送......但是在接收端,所有对象都不是从接收到的byte []构造的。

任何收到的对象都会随机出现错误但是相同的代码在Java中正常工作......我认为在将数据从一个设备传输到另一个设备时,有些字节错过了......

可以使用以下代码

完成Serializable对象到byte []和byte []到对象的转换
public static byte[] toByteArray(Object obj)
{
    byte[] bytes = null;
    ObjectOutputStream oos = null;

    try 
    {
        oos = new ObjectOutputStream(new ByteArrayOutputStream());
        oos.writeObject(obj);
        oos.flush();

        return bos.toByteArray();
    }
    catch(Exception e)
    {
        Log.e("Bluetooth", "Cast exception at sending end ...");
    }

    return bytes;
}

public static Object toObject(byte[] bytes) 
{
    Object obj = null;
    ObjectInputStream ois = null;

    try 
    {
        ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
        return ois.readObject();
    } 
    catch(Exception ex)
    {
        Log.e("Bluetooth", "Cast exception at receiving end ...");
    }

    return obj;
}

答案 5 :(得分:-1)

我实际上发现了问题 - 当使用

加载字节时
try {
   // Read from the InputStream
    bytes = mmInStream.read(buffer);
实际上它们是按步骤加载的..在调试和单步执行代码时,我发现如果首先加载990个字节,然后是剩余的字节..所以当我回到UI处理程序时,我只看到加载的字节第二步..

我想知道是否有办法强制一次加载所有字节