SD card removed notification



  • Hi,

    I tried to implement a notification of SD card removal in my application on Android. There is a sample app and guide to do it. The sample works for me, but I stops working if I try to implement it in my application.

    I tried to change the sample app to meet my needs and at one point it stopped working too. Basically the Java part works OK and even the callback to C++ on Android UI thread works. Originally it is implemented like this:

    // native.cpp
    #include <jni.h>
     #include <QMetaObject>
     #include "mainwindow.h"
     
    /static void onReceiveNativeMounted(JNIEnv * /*env*/, jobject /*obj*/)
    {
        QMetaObject::invokeMethod(&MainWindow::instance(), "onReceiveMounted"
                                  , Qt::QueuedConnection);
    }
    

    Then there is the mainwindow class:

    // mainwindow.h
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
     
    #include <QMainWindow>
     
    namespace Ui {
    class MainWindow;
    }
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
     
    public:
        static MainWindow &instance(QWidget *parent = 0);
     
    public slots:
        void onReceiveMounted();
        void onReceiveUnmounted();
     
    private:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
     
    private:
        Ui::MainWindow *ui;
    };
    

    This construction works. Now all I did was to create my own class called AndroidLib and call it from the native.cpp. The modified part looks like this:

    #include "androidlib.h"
     
    static void onReceiveNativeMounted(JNIEnv * /*env*/, jobject /*obj*/)
    {
        QMetaObject::invokeMethod(&AndroidLib::instance(), "onReceiveMounted"
                                  , Qt::QueuedConnection);
    }
    

    The AndroidLib class looks almost identical to the former MainWindows class:

    #ifndef ANDROIDLIB_H
    #define ANDROIDLIB_H
    
    #include <QObject>
    #include <QDebug>
    
    class AndroidLib : public QObject
    {
        Q_OBJECT
    public:
        explicit AndroidLib(QObject *parent = nullptr);
        static AndroidLib &instance(QObject *parent = 0);
    
    /*private:
        explicit AndroidLib(QObject *parent = nullptr);*/
    
    public slots:
        void onReceiveMounted();
        void onReceiveUnmounted();
    
    signals:
        void sdMount(const bool mounted);
    };
    
    #endif // ANDROIDLIB_H
    
    

    The function in native.cpp is called. Even the function AndroidLib::instance() is called. But the function onReceiveMounted() in AndroidLib is not called.

    Is there something wrong in the command

    /QMetaObject::invokeMethod(&AndroidLib::instance(), "onReceiveMounted", Qt::QueuedConnection);
    

    which causes that the function is not executed?

    Thanks a lot for any advice regarding this issue.


  • Moderators

    @vlada
    How is AndroidLib::instance() exactly implemented?
    The fact that you need to use a reference (&AndroidLib::instance()) of the returned object seems a bit odd.
    If you return an object allocated on the stack the function call will never happen, since it is destroyed before.



  • The implementation can be found in the guide I mentioned in the beginning. It looks like this:

    MainWindow &MainWindow::instance(QWidget *parent)
    {
        static MainWindow mainWindow(parent);
        return mainWindow;
    }
    

    There is also explained, why it is a little bit more difficult then one would expect.

    The problem is that the function in native.cpp is executed in Android UI thread and I need to call the function in AndroidLib so that it is called in Qt main loop.

    After many trial and errors I finally made it to work although I'm not sure why. I found out that if I called the function in AndroidLib directly from main.cpp. Then it was executed. So I implemented a signal and connected it to the class when I needed the information. But that didn'T work.

    Now I've used this in my code:

    QObject::connect(&AndroidLib::instance(), SIGNAL(sdMount(bool)), qmltocpp, SLOT(sdMount(bool)));
    

    And it works!!!! The function in AndroidLib is called, the signal is emitted and received in my qmltocpp class. Because C++ doesn't have a garbage collector, I hope the AndroidLib instance will not be destroyed. And I can always get the reference to it by calling the static instance() function. The constructor is now a private function as in the example. Maybe that was the trick, I'm really confused.

    Now I need to move it to a service. That will be the next task. So the problem is solved but I still have no idea why it didn't work earlier and now it works.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.