Search code examples
androidc++qtzxingbarcode-scanner

Start an external activity to scan barcode


I want to start the barcode scanner from my app and get the tag

Here is what I have so far :

scan.h

class DecodeBarCode : public QObject
{
    Q_OBJECT

    BarCodeReceiver *m_receiver;

public:
    explicit DecodeBarCode(QObject *parent = 0);
    ~DecodeBarCode();

    Q_INVOKABLE void useZXingApp();

signals:
    void tagFound(QString tag);
};

class BarCodeReceiver : public QAndroidActivityResultReceiver
{
    DecodeBarCode *m_decoder;
public:
    BarCodeReceiver(DecodeBarCode *decoder) : m_decoder(decoder) {}

    virtual void handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data) {
        emit m_decoder->tagFound("Receiver worked");
    }

};

scan.cpp

DecodeBarCode::DecodeBarCode(QObject *parent) : QObject(parent)
{
    m_receiver = new BarCodeReceiver(this);
}

DecodeBarCode::~DecodeBarCode()
{
    delete m_receiver;
}

void DecodeBarCode::useZXingApp()
{
    QAndroidJniObject intent = QAndroidJniObject::fromString("com/google/zxing/client/android/SCAN");
    if (intent.isValid()) {
        QtAndroid::startActivity(intent,0,m_receiver); // CRASH HERE
    } else {
        emit tagFound("Invalid"); // TEMP
    }
}

That is the first time I use JNI, never used it in java nor c++/Qt

There must be something very wrong, what is it ?


Solution

  • I finally got it to work, here is the full code :

    decodebarcode.h

    #ifndef DECODEBARCODE_H
    #define DECODEBARCODE_H
    
    #include <QObject>
    #ifdef Q_OS_ANDROID
    #include <QtAndroidExtras/QtAndroid>
    #include <QtAndroidExtras/QAndroidJniObject>
    #include <QtAndroidExtras/QAndroidJniEnvironment>
    #include <QtAndroidExtras/QAndroidActivityResultReceiver>
    #endif
    
    class BarCodeReceiver;
    
    class DecodeBarCode : public QObject
    {
        Q_OBJECT
    
        BarCodeReceiver *m_receiver;
    
    public:
        explicit DecodeBarCode(QObject *parent = 0);
        ~DecodeBarCode();
    
        Q_INVOKABLE void useZXingApp();
    
    signals:
        void tagFound(QString tag);
    };
    
    #ifdef Q_OS_ANDROID
    class BarCodeReceiver : public QAndroidActivityResultReceiver
    {
        DecodeBarCode *m_decoder;
    public:
        BarCodeReceiver(DecodeBarCode *decoder);
    
        virtual void handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data);
    
    };
    #else
    class BarCodeReceiver
    {
    public:
        BarCodeReceiver(DecodeBarCode *decoder) {Q_UNUSED(decoder)};
    };
    #endif
    
    #endif // DECODEBARCODE_H
    

    decodebarcode.cpp

    #include "decodebarcode.h"
    
    DecodeBarCode::DecodeBarCode(QObject *parent) : QObject(parent)
    {
        m_receiver = new BarCodeReceiver(this);
    }
    
    DecodeBarCode::~DecodeBarCode()
    {
        delete m_receiver;
    }
    
    void DecodeBarCode::useZXingApp()
    {
    #ifdef Q_OS_ANDROID
        QAndroidJniObject action = QAndroidJniObject::fromString("com.google.zxing.client.android.SCAN");
    
        // Intent intent = new Intent(action)
        QAndroidJniObject intent("android/content/Intent","(Ljava/lang/String;)V", action.object<jstring>());
    
        jint flagCategorieDefault = QAndroidJniObject::getStaticField<jint>("android/content/Intent", "CATEGORY_DEFAULT");
        jint flagActivityClearTop = QAndroidJniObject::getStaticField<jint>("android/content/Intent", "FLAG_ACTIVITY_CLEAR_TOP");
        jint flagActivityClearTaskReset = QAndroidJniObject::getStaticField<jint>("android/content/Intent", "FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET");
    
        // intentScan.addCategory(Intent.CATEGORY_DEFAULT);
        intent.callObjectMethod("addCategory", "(I)V", flagCategorieDefault);
    
        //intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.callObjectMethod("addFlags", "(I)V", flagActivityClearTop);
    
        //intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
        intent.callObjectMethod("addFlags", "(I)V", flagActivityClearTaskReset);
    
        QtAndroid::startActivity(intent, 0, m_receiver);
    #endif
    }
    
    
    #ifdef Q_OS_ANDROID
    BarCodeReceiver::BarCodeReceiver(DecodeBarCode *decoder)
        : m_decoder(decoder)
    {
    
    }
    
    void BarCodeReceiver::handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data)
    {
        QAndroidJniObject stringExtraScanResult = QAndroidJniObject::fromString("SCAN_RESULT");
        QAndroidJniObject scanResult = data.callObjectMethod("getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;", stringExtraScanResult.object<jstring>());
        emit m_decoder->tagFound(scanResult.toString());
    }
    #endif
    

    If you have the same problem, I hope that help