Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. SD card removed notification

SD card removed notification

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
3 Posts 2 Posters 894 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    vlada
    wrote on last edited by
    #1

    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.

    raven-worxR 1 Reply Last reply
    0
    • V vlada

      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.

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by raven-worx
      #2

      @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.

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      0
      • V Offline
        V Offline
        vlada
        wrote on last edited by vlada
        #3

        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.

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved