简体   繁体   English

Android - 通过蓝牙传递 object

[英]Android - Pass object via bluetooth

The Bluetooth chat example for Android is very useful to learn how to pass strings between phones - is it possible to use the same code to pass objects between phones? Android 的蓝牙聊天示例对于学习如何在手机之间传递字符串非常有用 - 是否可以使用相同的代码在手机之间传递对象? I have the same classes defined in both phones, I just want to pass the instance of one class from one phone to another.我在两部手机中定义了相同的类,我只想将一个 class 的实例从一部手机传递到另一部手机。 Is there any sample code available?有没有可用的示例代码? I tried using serialization and replacing outputstream and inputstream in the chat example with objectoutputstream and objectinputstream but it didn't seem to work我尝试使用序列化并将聊天示例中的输出流和输入流替换为 objectoutputstream 和 objectinputstream 但它似乎不起作用

The best way I found to handle this was the following:我发现处理此问题的最佳方法如下:

  1. I set up my objects as implementing Serializable that I wanted to send.我将我的对象设置为实现我想要发送的 Serializable。
  2. I set up the following code to manage the messages:我设置了以下代码来管理消息:

     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. I changed the write statements to accept a Serializable, and then make the final write:我将写入语句更改为接受可序列化,然后进行最终写入:

     /** * 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); } }

The Bluetooth Chat example is a demonstration of using the Serial Port Profile (SPP) which is based upon RFCOMM.蓝牙聊天示例是使用基于 RFCOMM 的串行端口配置文件 (SPP) 的演示。 You can serially send across any data you like once the connection is established;建立连接后,您可以串行发送您喜欢的任何数据; you simply need to be able to represent your objects into a serial stream of bytes, ie serialize them.您只需要能够将您的对象表示为字节的串行 stream,即序列化它们。

Therefore the use of serialization would certainly be a way of getting your objects sent over the link.因此,使用序列化肯定是让您的对象通过链接发送的一种方式。 The Bluetooth API's send and receive functions deal with arrays of bytes, but you could easily adapt the Bluetooth Chat example to use streams, eg the send function would read bytes out of a stream and put them into an array buffer, then you send that buffer, etc. Then the application code would simply talk via input and output stream pipes - that's one way I've done it in the past.蓝牙 API 的发送和接收函数处理 arrays 字节,但您可以轻松地调整蓝牙聊天示例以使用流,例如发送 function 将从 ZF7B44CFAFD5C52223D5498196C8 中读取字节,然后您发送该缓冲区并将它们放入数组缓冲区中等。然后应用程序代码将简单地通过输入和 output stream 管道进行对话——这是我过去做过的一种方式。

So there's nothing wrong with your actual idea.所以你的实际想法没有错。 The bigger problem is that the way you've implemented it is not right, and more problematic still is that the way you've asked your question is quite poor, too.更大的问题是你实现它的方式不对,更成问题的是你提出问题的方式也很糟糕。 You need to be more descriptive about exactly what didn't work, explain what debugging you've already tried, and post code samples and Logcat outputs so we can help you properly.您需要更准确地描述哪些不起作用,解释您已经尝试过哪些调试,并发布代码示例和 Logcat 输出,以便我们可以为您提供适当的帮助。

Finally, I did find what I think is a bug in the Bluetooth Chat code example: The data receive function passes a reference of the receive byte array to the ArrayList that's used to show each line of text received.最后,我确实在蓝牙聊天代码示例中发现了我认为的错误:数据接收 function 将接收字节数组的引用传递给用于显示接收到的每一行文本的 ArrayList。 This is alright when small amounts of slow text are being transmitted across, but when you try to send large amounts of data, you start to see the data being corrupted, presumably because the ArrayList adapter is still reading bytes out of that same array when the array is being filled with even newer data.这在传输少量慢速文本时没问题,但是当您尝试发送大量数据时,您开始看到数据已损坏,大概是因为 ArrayList 适配器仍在从同一数组中读取字节时数组正在填充更新的数据。

Facing same problem... When i am sending a series of objects from one Android device, data sends properly... But in receiving end all objects does not construct from received byte[].面临同样的问题......当我从一个 Android 设备发送一系列对象时,数据发送正确......但在接收端,所有对象都不是从接收到的字节 [] 构造的。

Error occurs randomly for any received object but the same code works properly in Java... I think the some bytes misses when transferring data from one device to another...任何接收到的 object 都会随机发生错误,但相同的代码在 Java 中可以正常工作......我认为在将数据从一个设备传输到另一个设备时会丢失一些字节......

Serializable object to byte[] and byte[] to object conversion can be done with the following code可序列化 object 到 byte[] 和 byte[] 到 object 转换可以使用以下代码完成

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;
}

Trev16v, First of all, thanks for your initial feedback. Trev16v,首先,感谢您的初步反馈。

In order to serialise my object, I used the classes serializeObject and deserializeObject from http://www.jondev.net/articles/Android_Serialization_Example_(Java ) They seem to work well: if I serialise an object (created out of a class that implements Serializable) from a phone/activity and deserialize it from the same phone i manage to get an object out of the generated byte[]. In order to serialise my object, I used the classes serializeObject and deserializeObject from http://www.jondev.net/articles/Android_Serialization_Example_(Java ) They seem to work well: if I serialise an object (created out of a class that implements可序列化)从电话/活动并从同一部电话反序列化,我设法从生成的字节 [] 中获取 object。

I then tried to use the same code in the class BluetoothChatServices in the bluetooth chat example in oder to send the serialised object to the other phone (in that example there is然后,我尝试在蓝牙聊天示例中的 class BluetoothChatServices 中使用相同的代码,以便将序列化的 object 发送到另一部手机(在该示例中有

    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;
    }

and the bytes are passed using并且字节是使用传递的

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);
        }
    }

and read using并阅读使用

   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;
            }
        }
    }

The problem with using BluetoothChatServices as it is is that the array of bytes received on the other phone is different from the one sent when it comes to serialised objects.使用 BluetoothChatServices 的问题在于,在另一部手机上接收到的字节数组与在序列化对象时发送的字节数组不同。 For example, to give an idea element [0] of the seriealized object is =-84 when i send it, the one i receive from the other phone has element [0] to [4] =0, then [5]=4 and all the other elements are also not aligned.例如,给序列化 object 的一个想法元素 [0] 在我发送它时 =-84,我从另一部手机收到的元素 [0] 到 [4] =0,然后 [5]=4并且所有其他元素也未对齐。 I tried in the methods write and run above to change Inputstream and Outputstream with ObjectInputStream and ObjectOutputstream but without success (if this was supposed to be the way to implement it, I can post the code I tried to use)我尝试在上面的 write 和 run 方法中使用 ObjectInputStream 和 ObjectOutputstream 更改 Inputstream 和 Outputstream 但没有成功(如果这应该是实现它的方法,我可以发布我尝试使用的代码)

Again, thanks a lot for your help, I am new to all these concepts so if I am talking nonsense I will be also happy to be addressed to a tutorial再次感谢您的帮助,我对所有这些概念都很陌生,所以如果我在胡说八道,我也很乐意接受教程

thanks谢谢

The answer is yes.答案是肯定的。 A String is an Object.字符串是 Object。 Remember?记住? But how exactly to do it, I am still searching for a solution and that's what brought me here...但究竟该怎么做,我仍在寻找解决方案,这就是把我带到这里的原因......

I actually found the problem - when the bytes are loaded using我实际上发现了问题 - 当使用加载字节时

try {
   // Read from the InputStream
    bytes = mmInStream.read(buffer);

they are actually loaded in 2 steps.. While debugging and stepping into the code I found that if first loads 990 bytes and then the remaining bytes.. so when i am back to the UI handler i see only the bytes loaded in the second step..它们实际上是分两步加载的。在调试和单步执行代码时,我发现如果先加载 990 个字节,然后再加载剩余的字节。所以当我回到 UI 处理程序时,我只看到第二步中加载的字节..

i wonder if there is a way to force to load all bytes at once我想知道是否有办法强制一次加载所有字节

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM