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. [ Solved ] [ iOS ] How to open a custom file extension using "Open in MyApp" ?
Forum Updated to NodeBB v4.3 + New Features

[ Solved ] [ iOS ] How to open a custom file extension using "Open in MyApp" ?

Scheduled Pinned Locked Moved Mobile and Embedded
4 Posts 1 Posters 2.9k Views 1 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.
  • E Offline
    E Offline
    Eddie
    wrote on 1 Jun 2015, 22:27 last edited by Eddie 6 Feb 2015, 13:29
    #1

    I have a Qt 5.5 widget app.

    After adding UTExportedTypeDeclarations and CFBundleDocumentTypes sections to my Info.plist, I can now open a file attachment in Apple Mail and select "Open in MyApp" then MyApp launches.

    How can I receive the file and open it? Has anyone figured this out?

    I see openURL and didFinishLaunchingWithOptions being discussed.

    • (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
      {
      // handle the URL here
      }

    The LaunchMe Example uses OpenURL.
    https://developer.apple.com/library/ios/samplecode/LaunchMe/Introduction/Intro.html

    How to do same in Qt seems challenging.

    Thanks in advance for any tips,

    -Ed

    E 1 Reply Last reply 2 Jun 2015, 12:34
    0
    • E Eddie
      1 Jun 2015, 22:27

      I have a Qt 5.5 widget app.

      After adding UTExportedTypeDeclarations and CFBundleDocumentTypes sections to my Info.plist, I can now open a file attachment in Apple Mail and select "Open in MyApp" then MyApp launches.

      How can I receive the file and open it? Has anyone figured this out?

      I see openURL and didFinishLaunchingWithOptions being discussed.

      • (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
        {
        // handle the URL here
        }

      The LaunchMe Example uses OpenURL.
      https://developer.apple.com/library/ios/samplecode/LaunchMe/Introduction/Intro.html

      How to do same in Qt seems challenging.

      Thanks in advance for any tips,

      -Ed

      E Offline
      E Offline
      Eddie
      wrote on 2 Jun 2015, 12:34 last edited by Eddie 6 Feb 2015, 13:28
      #2

      Ben Lau on Qt Interest mailing list explained that Objective-C categories can be used to override classes even if you do not have the header file.

      I do not understand how. The following somehow works without having to initialize it to the instance of UIApplication.

      I put a breakpoint in openURL. When I open an email attachment, my app is launched, and the breakpoint is hit. Magic.

      File: myappdelegate.mm

      #include <UIKit/UIKit.h>

      #include "qiosapplicationdelegate.h"

      #include "mainwindow.h"

      @implementation QIOSApplicationDelegate (CmsApplicationDelegate)

      • (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
        sourceApplication:(NSString *)sourceApplication
        annotation:(id)annotation
        {
        Q_UNUSED(application);
        Q_UNUSED(annotation);

        NSLog(@"sourceApplication: %@",sourceApplication);
        NSLog(@"url: %@",url);

        // A bit of ugly code involving adding a static instance method and a static variable
        // But it works!
        //
        cms::MainWindow* mainWindow = cms::MainWindow::instance();
        if(0 != mainWindow)
        {
        QString filePath = QString::fromNSString(url.path);
        qDebug("filePath %s", filePath.toLatin1().data());
        mainWindow->openFile(filePath);
        }

        return YES;
        }
        @end

      I added an INCLUDEPATH to my project file.

      File: myapp.pro

      ios {
      QTBASE=$$clean_path($$QMAKE_QMAKE/../../..)/Src/qtbase
      INCLUDEPATH += $$QTBASE/src/plugins/platforms/ios
      }

      -Ed

      1 Reply Last reply
      0
      • E Offline
        E Offline
        Eddie
        wrote on 2 Jun 2015, 12:49 last edited by
        #3
        This post is deleted!
        1 Reply Last reply
        0
        • E Offline
          E Offline
          Eddie
          wrote on 2 Jun 2015, 16:24 last edited by Eddie 6 Feb 2015, 16:26
          #4

          I found a solution I like better that posts a QFileOpenEvent.

          I like it better because in order to handle file open on OS X I had to subclass QApplication and give it a pointer to my MainWindow to handle the QFileOpenEvent. Now my OS X and iOS implementation are similar and easier to maintain.

          File: cmsapplication.h

          <pre>
          #include <UIKit/UIKit.h>

          #include <QDebug>
          #include <QFileOpenEvent>

          #include "qiosapplicationdelegate.h"

          /// \category QIOSApplicationDelegate(CmsApplicationDelegate)
          /// \abstract A category on QIOSApplicationDelegate to override openURL

          /// Use the Objective-C category feature to override the openURL method
          @implementation QIOSApplicationDelegate (CmsApplicationDelegate)

          /// Posts a QFileOpenEvent to QCoreApplication when iOS calls openURL.
          ///
          /// This allows userto open a TSR file from Apple Mail,
          /// select "Open in TSR", to launch TSR and pass openURL the
          /// file to open.
          ///
          /// Must add UTExportedTypeDeclarations and CFBundleDocumentTypes to your
          /// Info.plist for this to work.
          ///
          /// Example: Info.plist
          /// \verbatim
          /// <key>UTExportedTypeDeclarations</key>
          /// <array>
          /// <dict>
          /// <key>UTTypeConformsTo</key>
          /// <array>
          /// <string>public.data</string>
          /// </array>
          /// <key>UTTypeDescription</key>
          /// <string>Tracking Status Report</string>
          /// <key>UTTypeIdentifier</key>
          /// <string>com.ditchwitch.tsr</string>
          /// <key>UTTypeTagSpecification</key>
          /// <dict>
          /// <key>public.filename-extension</key>
          /// <string>tsr</string>
          /// <key>public.mime-type</key>
          /// <string>public.data</string>
          /// </dict>
          /// </dict>
          /// </array>
          /// <key>CFBundleDocumentTypes</key>
          /// <array>
          /// <dict>
          /// <key>CFBundleTypeIconFiles</key>
          /// <array>
          /// <string>Icon.png</string>
          /// </array>
          /// <key>CFBundleTypeName</key>
          /// <string>Tracking Status Report</string>
          /// <key>CFBundleTypeRole</key>
          /// <string>Editor</string>
          /// <key>LSHandlerRank</key>
          /// <string>Owner</string>
          /// <key>LSItemContentTypes</key>
          /// <array>
          /// <string>com.ditchwitch.tsr</string>
          /// <string>public.data</string>
          /// </array>
          /// </dict>
          /// </array>
          /// \endverbatim
          ///
          /// See file: cmsapplication.cpp
          /// \see cmsapplication.cpp
          ///
          /// \see https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html
          ///

          • (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
            sourceApplication:(NSString *)sourceApplication
            annotation:(id)annotation
            {
            Q_UNUSED(application);
            Q_UNUSED(annotation);

            NSLog(@"sourceApplication: %@",sourceApplication);
            NSLog(@"url: %@",url);

            QString filePath = QString::fromNSString(url.path);
            qDebug("filePath %s", filePath.toLatin1().data());

            QFileOpenEvent *fileOpenEvent = new QFileOpenEvent(filePath);
            QCoreApplication::postEvent(QCoreApplication::instance(), fileOpenEvent);

            return YES;
            }

          @end
          </pre>

          File: cmsapplication.cpp

          // class CmsApplication : public QApplication

          <pre>
          #if defined(Q_OS_OSX) || defined(Q_OS_IOS)
          // Looks for QFileOpenEvent to implement TSR file open from
          /// other apps, for example, Finder on OS X, or Apple Mail on iOS and OS X.
          ///
          ///
          /// \remarks Could this work on Android too?
          ///
          /// See file: cmsapplicationdelegate.mm
          /// \see cmsapplicationdelegate.mm
          ///
          bool CmsApplication::event(QEvent* event)
          {
          qDebug() << event->type();
          // iOS receives ApplicationDeactivate, ApllicationStateChange, when Home is pressed
          // When iOS user opens Mail file attachment using "Open in TSR", ApplicationActivate event received but NOT QEvent::FileOpen
          switch (event->type())
          {
          case QEvent::ApplicationActivate:
          {
          //clean();
          if (false == m_mainWindow.isMinimized())
          {
          m_mainWindow.show();
          }
          return true;
          }
          case QEvent::FileOpen:
          {
          QString fileName = static_cast<QFileOpenEvent *>(event)->file();
          m_mainWindow.openFile(fileName);
          return true;
          }
          default:
          break;
          }
          return QApplication::event(event);
          }
          #endif
          </pre>

          1 Reply Last reply
          0

          4/4

          2 Jun 2015, 16:24

          • Login

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