Monday, August 19, 2013

BB10 / Qt : How to serialize any user defined QObject class to QByteArray using QDataStream

Today I am going to write about how to serialize any QObject class and then write the object to a byte array and desalinize it back from the byte array. This is crucial if you want to send any object over the net or save it in a file or database.

First, we need a base class which make all of it's subclass serializable.

SerializableClass.h
#ifndef SerializableClass_H_
#define SerializableClass_H_
#include <qt4/QtCore/qobject.h>
#include <qt4/QtCore/qdatastream.h>
class SerializableClass : public QObject
{
    Q_OBJECT
public:
    explicit SerializableClass(QObject *parent = 0);

};
QDataStream &operator<<(QDataStream &ds, const SerializableClass &obj);
QDataStream &operator>>(QDataStream &ds, SerializableClass &obj) ;
#endif /* SerializableClass_H_ */
SerializableClass.cpp
#include "SerializableClass.h"
#include <qt4/Qt/qvariant.h>
#include <qt4/QtCore/qmetaobject.h>
SerializableClass::SerializableClass(QObject *parent) :
    QObject(parent)
{
}
QDataStream &operator<<(QDataStream &ds, const SerializableClass &obj) {
    for(int i=0; i<obj.metaObject()->propertyCount(); ++i)
    {
        if(obj.metaObject()->property(i).isStored(&obj))
        {
            ds << obj.metaObject()->property(i).read(&obj);
        }
    }
    return ds;
}
QDataStream &operator>>(QDataStream &ds, SerializableClass &obj) {
    QVariant var;
    for(int i=0; i<obj.metaObject()->propertyCount(); ++i)
    {
        if(obj.metaObject()->property(i).isStored(&obj))
        {
            ds >> var;
            obj.metaObject()->property(i).write(&obj, var);
        }
    }
    return ds;
}

Now, you need to extend this class to make your class serializable. Let's see as example.

Student.h
#ifndef STUDENT_H_
#define STUDENT_H_
#include "SerializableClass.h" 
class Student : public SerializableClass
{
    Q_OBJECT
    Q_PROPERTY(int id READ getId WRITE setId)
    Q_PROPERTY(QString Name READ getName WRITE setName)
public:
    Student();
    int getId() const { return id; }
    void setId(int newId) { id = newId; }
    QString getName() const { return Name; }
    void setName(const QString &newName) { Name = newName; }
private:
    int id;
    QString Name;
}; 
#endif /* STUDENT_H_ */

Student.cpp
#include "Student.h"
Student::Student()
{

Here Q_OBJECT, Q_PROPERTY macros are required to take care of generating proper metaObject for your class. Now we are going to put these classes in action at main() function.

main.cpp
Q_DECL_EXPORT int main(int argc, char **argv)
{
    Student G;
    Student G2;
   G.setId(30);
   G.setName("pervez");
   qDebug()<<G.getId()<<G.getName();
   QByteArray byteArray;
   QDataStream out(&byteArray, QIODevice::WriteOnly);
   out <<G;
   qDebug()<<G2.getId()<<G2.getName();
   QDataStream in(byteArray);
   in >> G2;
   qDebug()<<G2.getId()<<G2.getName();

   Application app(argc, argv);
   new ApplicationUI(&app);
   return Application::exec();
}

Here QDataStream out writes the G object in byteArray at "out <<G;" statement. that's why we use >> and << operator in SerializableClass.h header file


Wednesday, June 26, 2013

Android : Overview on WebRTC android Client with peer-to-peer support (libjingle)

WebRTC code, located in https://webrtc.googlecode.com/svn/trunk, contains only the video and audio codec, the RTP stack. On the other hand, the libjingle project has the stacks of XMPP, STUN and ICE implementation. It also uses the API of WebRTC. Libjingle project bundle has a android ndk project AppRTCDemo which can be used as application (.apk) on android device. Unlike WebRTCDemo (android project from WebRTC), this AppRTCDemo android project has libjingle's Peer-Connection module attached to it. So this android app can communicate with each other from different networks via p2p connection. To initiate p2p connection with other client, it communicate with http://apprtc.appspot.com server using Google App Engine Channel API. 
If you want to write your own server you may try node.js and replace the google's Channel 
api code with your own signaling code in AppRTCDemo. The AppRTCDemo can be built on ubuntu by following the instructions on this link. Make sure JAVA_HOME is properly configured in the class-path. It also provides the info on how to install the app on android device.

Sunday, April 21, 2013

Android : How to build latest WebRTC revision for Android (on Linux) and run on device

WebRTC is a free, open project that enables web browsers with Real-Time Communications (RTC) capabilities via simple Javascript APIs. It also has a android ndk project WebRTCDemo which can be used as application (.apk) on android device. But one thing I should mention that this demo client does not support peer-connection feature. So it can not connect with http://apprtc.appspot.com. If you need 
an android client that can connect http://apprtc.appspot.com then you need to check out 
libjingle project. I am going to post on this issue in near future.

The WebRTCDemo can be built on ubuntu if you go through the following steps (use terminal to execute command):

  • Download the latest Android SDK and NDK. edit ~/.bashrc to add the paths accordingly. 
export ANDROID_SDK="<path to your Android SDK directory>"
export ANDROID_NDK="<path to your Android NDK directory>"
export PATH="$PATH:$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools:$ANDROID_NDK"
  • Download depottools and edit ~/.bashrc to add path.
  • source ~/.bashrc
  • install (sudo apt-get install...):
      g++ (>= 4.2)
      python (>= 2.4)
      libasound2-dev
      libpulse-dev
      libjpeg62-dev
      libxv-dev
      libgtk2.0-dev
      libexpat1-dev

    For 32-bit builds on a 64-bit system:
      lib32asound2-dev
      ia32-libs
  • create a folder where you can download source code from trunk and go to the folder from terminal.
  • gclient config https://webrtc.googlecode.com/svn/trunk
  • vim .gclient 
  • add this line ";target_os = ["android", "unix"]" to .gclient file.
  • gclient sync
  • cd trunk
  • source ./build/android/envsetup.sh
  • gclient runhooks 
  • sudo ./build/install-build-deps-android.sh
  • vim ./webrtc/video_engine/test/android/build_demo.py
  • [replace return 'source %s && %s' % (_ANDROID_ENV_SCRIPT, cmd) with return '/bin/bash -c "source %s" && %s' % (_ANDROID_ENV_SCRIPT, cmd)]
  • ninja -C out/Debug
  • You will find your build file (.apk file) in ./webrtc/video_engine/test/android/bin folder.
Here are the steps to run the application on android device:
  • run apk on both android devices.
  • configure remote ip address in settings tab on both android devices.(Note: as it does not support peer-connection so these devices need to know each other directly without any server interaction. So devices need to be in same network)
  • press StartCall button in Main tab on both android devices.