Overview of In-App Purchase

A high-level look at IAP.  Could be wrong.  Oriented to a trial-use or freemium app.

Disambiguating

A user can acquire your app without using IAP.  That is, your app can be in the store without using IAP.

“Acquire” does not necessarily mean “pay for”.  If your app is free, a user can get it without payment, by browsing the App Store.  The free portion of your app is a product with a receipt, but it is not a product that you show in your app’s store facade, since the user already has it.

Trials

Apparently, Apple does not want “trial versions” of apps in the store.  But this just means: they don’t want duplicates (where one is crippled and the duplicate not) and  instead prefer one version with IAP.  The version in the store can still be a trial version in this sense: the app can require an IAP purchase to continue certain capabilities beyond a trial period.  Probably Apple also doesn’t want an app that won’t do anything after a trial period.  In other words, an app should continue to do something minimally useful after a trial period.

Probably they don’t even want you to advertise that an app is a trial-version: the user will see the IAP icon in the store, and know that the app may be limited (from the get-go, or after a trial period.)

Probably most users expect that certain apps will be trials or crippled.  Don’t worry about offending potential customers.

The Data Model

An app has one or more products.

A product has one or more receipts.  Each receipt is for a transaction.  (StoreKit lets you play back the transactions.)

A product has one or more content/capabilities.

Generally content/capabilities are one-to-one with receipts.

I am glossing here: it is probably only subscription type products that have many receipts for the same product.  That is, a subscription product entitles the purchaser to many contents, and each content has its own receipt.

The Facade Pattern

Your app presents a facade to the store.  In other words, your app has GUI for IAP.  Behind the scenes, your app collaborates with the store server using StoreKit.  Your app is a client of the store server.

You must submit a screen capture of your store facade during the app review process.

Validating a productID is the process for insuring that the products your facade presents to the user are indeed products in the store server (configured using iTunesConnect.)

Receipt Subclasses

Subclasses:

  • bona fide Apple receipts, stored in the app bundle and maintained by the OS/framework
  • ad hoc receipts, stored e.g. in NSUserDefaults and maintained by your app

The difference is in how much code you need, and strength of receipt against hacking.

Restoration

A purchase is restorable when a purchaser:

  • deletes your app from a device
  • buys a new device
  • enables Family Sharing for other devices

The store maintains records of purchases.   Your app must collaborate.

If you use ad-hoc receipts, when a user deletes your app, the settings for the app are deleted.  When a user re-downloads your app,  since you are not using Apple receipts, you won’t know that the user has downloaded it before (in another transaction.)  Thats a weakness of ad-hoc receipts.  Your app won’t have any record that it was downloaded previously.  Presumably, most users will purchase rather than repetitively download your free app (just to reset the trial period.)

Creating products

You need to create a product on both sides:

  • in the real store using iTunesConnect
  • in your store facade (hard coding productIDs or putting them in a .plist file)

Testing

There is a sandbox for testing IAP.  (If it works in the sandbox, it should work in the real world.  The only way to test in the real world is to actually purchase; be the first one if you are worried about it.)

Test Cases

You should test:

  1. Normal purchase: success on the main path.
    1. User declines: in your store facade, answers “No thanks.”
    2. User declines: Settings>Restrictions>IAP is On (Restrictions enabled, IAP restriction On)
    3. User declines : Cancels StoreKit’s log in dialog to the store.
    4. User declines : Cancels StoreKit’s confirmation dialog for purchase
  2. Product invalid: for some reason, what your app thinks is a product is not in the store.  (Your app configuration is wrong, or the store has removed your product.)
  3. Restoration: user installs your app on another device, or deletes and reinstalls your app.
  4. Store facade can be paused and resumed with the Home button
  5. Store facade handles user bottom double swipe up the Control Center

For a trial-use app:

  1. In the trial period: all capabilities
  2. After the trial period: capabilities are denied
  3. After the trial period: you dun the user when they try to use a capability (you present your store facade.)
Advertisements

iOS Multipeer Connectivity: invitation races and leader election

This is an informal discussion, and I could be mistaken.

Suppose your app begins advertising its service when the app starts.  Suppose your app has a button the user can click to begin browsing for connections.  What happens when two users begin browsing at the same time?  It might be a race to invite the other.

An invitation race

Race conditions are often discussed in computer science.

In this specific, MPC invitation race, two instances have the following event sequences, at the same time:

  • app advertises
  • user touches “Connect” button
  • app calls framework to display browser, showing the other instance (candidate peer)
  • user chooses a candidate peer
  • framework receives invitation and displays invitation dialog from the other
  • user chooses to accept the invitation

Now what happens?  In my experience, it fails to make a connection.  When I and another tester got into an invitation race, my app would connect then immediately disconnect.

You can imagine the same thing for a real birthday party.  Two people invite the other to a birthday party on the same date and then both as invitees via mail accept the other’s invitation.

How important is solving an MPC invitation race?

Probably not very important.  It is likely your MPC users are within shouting distance.  They can solve the race problem just by talking to each other: “OK, you invite me and I will accept your invitation.”  The users can figure it out themselves without any instruction.  So it’s “would be nice” to solve the invitation race.

Does the MPC framework solve the invitation race problem for you?

Apparently not.  I tried using the high-level MPC API (the one that provides the GUI’s for browsing and invitations.)    It was only when we negotiated by shouting that we could make a connection.  It could be that my code is wrong, that I’m just missing a simple step to fix the problem.  But it seems like the hooks are not in the API.  You can learn when the invitation dialog closes, but you can’t know that the framework received an invite and is about to display an invitation (so that your app could choose NOT to display the invitation since the app knows it has already extended a contending, simultaneous invite.)

Using the low-level MCP API (the one where you provide the GUI), it seems there exist methods in the API that let you implement a solution to an invitation race.  Sample code for leader election.  So the hooks are there, but you must implement it, and you must implement the GUI also.

 

Scalable user interfaces: phone, pad, and desktop

This is a brief note, at a high level about designing the GUI of an application for portability across platforms (of different screen sizes and pointer devices.)  Bottom line: use context menus.

This is mostly about small, focused, document centered apps, not large, complex, bloated apps.

Skins

Skins are look and feels, or views of your app (but more than just decorations.)  Use the MVC paradigm to separate the model from the view so that you can reskin your app.

Even if you don’t offer the user a choice of skin, you probably will reskin your app during its lifetime.

Skins can vary by platform.  Here I mostly discuss trying to design one skin that is cross-platform.

Actions are central to reskinning.  Actions are fundamental things the user can do.  They are in the view, but they are linked to a method in the model.  Actions in the view can be shared (without change) across many skins.  For example, an action can be associated with a toolbar icon, a context menu item text, or button in a dialog.

Context menu GUI’s are cross-platform

A context menu driven app is mostly cross-platform.

A context menu is also known as a pop-up, or action sheet.

A context menu actually varies across platforms:

  • phone: slides up (drawers) from the bottom (iOS), NOT at the pointer (touch)
  • pad and desktop: appears at the pointer, or with a keyboard key (Win) at the selection

The notion of context is tied to the notion of selection.  The context is of the object that the user designated but the object need not become a long-term selection.

An alternative to a context menu is a toolbar (toolbars are context sensitive, their contents change according to the user’s designated place in a hierarchy or place in the app.)  The UI problem with toolbars is that they are away from the focus, unlike context menus.  On a phone, context menus are also ‘away’ from the focus (not at the pointer), but since the screen is small, they are not far away.

Document centered apps are NOT cross platform

Many apps on desktops are document centered.  Conversely, few apps on mobile platforms are document centered.  This is mostly because mobile devices are used for communicating and browsing, and are hindered  by sandboxing between apps.

An exception is photos as documents: most mobile devices are also cameras.  Many mobile devices are photo centered: the OS supports save, open, and edit photos.

This is changing: iOS8 is beginning to support document centered with the notion of document providers.

Document centered and navigation

Mobile platforms support navigation using navigation bars (when an app has hierarchical data or nature, e.g. a music library.)

A file system having documents is also hierarchical and amenable to a navigation based UI.  The problem is that on mobile platforms, the file system is not usually navigable (there is no native file browser or Finder and app files are sandboxed i.e. segregated.)

A cross-platform document centered GUI

On mobile platforms, for  document centered apps, one possible navigation-based  GUI comprises three paged views, where the navigation bars for the views are :

  •                 Docs          Edit>
  • <Docs     document   Meta>     where ‘document’ is the title of the current document
  • <document   Meta

The first view lets the user browse the app’s private store of documents (or in upcoming iOS8 apps, the private data stores of all apps that provide the mimetype which the current app understands and consumes.)

The second view lets the user edit a document, in WYSIWYG (the user sees the document.)

The third view lets the user change meta data of the document (e.g. the style or non-visible attributes.)

So, to make a cross-platform, document centered app,  you use different skins:

  • mobile: a skin such as the above
  • on the desktop, a traditional skin having a menubar with a File menu and File Chooser dialog (instead of the first view above) and with a File>Properties or other menu item for the third view above.

Share: the OS as a clearing-house, broker for documents and apps that understand them

An OS understands what apps can publish and subscribe to document types (mimetypes.)

This is done at installation time, via resources in the app’s package:

  • iOS and OSX: document icons in the bundle
  • Android: ??? in the manifest
  • Linux: desktop ??? in the .deb package

Mobile platform OS’s also support the notion of ‘share’, with a native dialog that shows the user which apps can understand your mimetypes.  The desktops (and frameworks on top of them) don’t provide that dialog.

Sharing is broad, meaning either:

  • open with another application, right now (print, or view in another application)
  • send a copy to another place (a website, the cloud, or a file system)

You can see that in the iOS share dialog, separated top and bottom.  Loosely, the top is ‘send to another place’, the bottom is ‘open with another application’.

Sharing is similar to drag and drop, except it crosses devices and has different syntax (order of steps):  with drag and drop, both applications must be open or have an icon on the screen.  So you must decide what the target is, open the applications, then sharedrag.  With share, you don’t decide first; you might decide the target after you start the sharedrag.  The target application need not be ‘open’ (displaying, because the mobile platforms have only one active window.)

I suspect that the notion of share will be soon supported by desktops (OS or frameworks), precisely because it would simplify the development of cross-platform apps.

Embellishing a skin with menubar on the desktop

A menubar is absent from most mobile platforms.  But, an apps skin on the desktop might in addition have a menubar.

A menubar is a necessary wart on desktops: when you have many windows, the menubar tells you which window is active.

A menubar also helps a user because it might be redundant: it might include all the same actions that the context menu system does, but all in one place.  A user can navigate in the menu system without navigating in the other app views.

A menubar also has global actions such as undo and redo.  A notable wart of iOS is that there is an action for undo (shake) but no global action for redo (AFAIK that requires using the virtual keyboard.)  Android also lacks undo/redo.

 

Switching to QML from QWidget using Qt and PyQt

This is high-level, loose assemblage of discussion and links.

Context: you have a cross-platform app written using Qt and PyQt.  It is written using QWidgets.  You want to switch from QWidgets to QML.

The discussion is not exclusive to PyQt.  Much of the discussion also applies to apps writtent in C++, but mentions PyQt also.

This might also have some relevance for apps written purely in QML/Qt Quick.

Why switch to QML from QWidget?

These are possible reasons:

  • QML uses native platform style whereas QWidget fails to have native look and feel on some platforms (iOS)
  • QML more strongly follows the ModelViewController paradigm
  • QML is declarative (more compact and dense)
  • a QML GUI is easier to change (to provide multiple or improved GUI’s for the same business model)

To me, the first reason is the most compelling.  The last reason is least compelling: you probably won’t be changing the GUI often (but then here we are talking about changing at least the implementation of a GUI.)

(Qt apps are excluded from the Windows Store because Qt did not support Windows8/WinRt but Qt5.4 and QML may remedy that?)

Model View Controller paradigm

Qt documentation: Model – View Options in Qt

Wiki: Model–view–controller

It is quite likely that your existing QWidget apps does not strictly adhere to the MVC paradigm.  Thus you will be probably need to refactor your code: separate model code from view code.

A strategy for  developing (code changes) to switch to QML from QWidget

Assuming your app using QWidgets already runs and has tests, a good strategy is to keep the QWidget implementation of the View working, while you develop the QML implementation of the View.   In other words, use test driven development: make small changes, then test the QWidget implementation AND the QML implementation.  The QWidget implementation should always remain fully functional after each change.  The QML implementation will also always work, but in a stubbed-out, minimal fashion.

Changing the existing QWidget app will largely entail:

  • splitting classes along model/view lines
  • converting procedure calls to signals, connections, and properties

Swapping in the QML implementation of the view will be just a small change in the startup code: creating QML instead of QWidgets.  (Its a little more complicated than that, you might be making connections in the QML instead of in the main app.)

Embedding QML in a QWidget app

You can implement the main app window (and all other GUI) in QML.  But you can also embed QML GUI inside a QWidget app.

Briefly, it entails using QQuickView.  But a QQuickView not is-a QWidget.  But you can wrap a QQuickView in a QWidget:  Qt documentation: Introducing QWidget::createWindowContainer() discusses how to wrap a QQuickView in a QWidget.

Why retain a QWidget shell embedding QML?  I suspect there are few reasons to do so.  One reason might be just the strategy discussed above; get your feet wet by embedding QML and make the last step converting the main window from QWidget to QML.

My reason was different: my app uses elaborate UI  picking of objects from a QGraphicsScene.  The QML scene graph doesn’t expose the same API for picking that the QGraphicsScene does.

More on the interface between model and view using QML

Qt documentation:

Where ‘from C++’  more generally means ‘from model objects’ .  And the discussion applies to model objects written in PyQt.

The interaction is two-way, bidirectional:

  •  Control (in MVC) is from the view to the model
  • View is from the model to the view

Your interaction may be one direction or both:

  • a weather app is just a viewer of the weather
  • a styling app is just a controller of a document

Much of the logic in the QML is not business logic, just GUI logic.  For example, a button may switch pages and have no effect on the business model.  The button ‘controls’ the view, but not the business model.

Not all the interaction need be between the model and the view.  For example, if you are embedding QML in a QWidget app, the QWidget app may need to simply activate (show, make visible) a QML view component.  In other words, the interactions may be between the part of the view implemented in QWidgets and the part of the view implemented in QML.

PyQt and QML

PyQt fully supports QML.  You can use Python and PyQt for your model.

PyQt documentation:  Integrating Python and QML

I have shared a hacky Github project where I learn and test PyQt and QML.

For the same reason you use QML for the view, you should consider Python for the model (more expressive in fewer lines of code.)

The QML tradeoff: more portable but less native?

Typically, a cross-platform solution makes certain compromises.  Sometimes its discussed using terms such as “least common denominator” or “adaption.”

I can’t fully discuss this here.  (And probably the set of compromises that have been made are not fully documented in one place.)  But you should consider whether you will be able to live with any such compromises.

For example, I found that a QML Dialog on a desktop (Linux, I haven’t tested OSX) opens in a separate window, not on top of (transient to) the main window.  That probably doesn’t meet the HIG’s for desktops.  Possibly there is a solution that I haven’t yet found.  Or possibly I should look at that as a feature to embrace: I should make my dialogs non-modal and treat them as tear-offs that should not obscure the main window anyway.  But its an example of the compromises you might need to make.

There is much more to discuss here.  Briefly, Qt Quick Controls does use native widgets where possible, then falls back to QWidget implementations if possible, and then to a pure-QML implementation.

But again, its hard to know in advance without trying it.

Structuring your QML source code

In many examples, you see long QML files.  I  think that is an artifact of being an example: put everything in one file for ease of reading.  You can structure you QML source files into smaller files in more directories, using imports.

Qt documentation: Import Statements | QtQml 5.3

Packaging your app

I don’t foresee any show stoppers here.  Just more to learn.  If you are already packaging a PyQt app, you probably are already packaging resources using pyrcc.  The QML is just another resource to package.

But, I’m not sure how third-party QML plugins get packaged?

A strange architecture: PyQt and QML uses two interpreters

A PyQt app using QML uses two interpreters: the Python interpreter and QML’s Javascript interpreter.  (And on Android, there is a third Java interpreter.)  There is much discussion about the safety of, and constraints applied by app stores, re interpreters.   But this is just a curiousity, there are already shipping apps, using interpreters, in the stores .

A template for QML using models

Qt’s example Weather App is a starting place for reading code: Cross-Platform Applications in iOS and Android Stores with Qt

(I hope to reduce it to a simple template.)

Desktop to Mobile GUI difference: sharing

The main problem that I have found is that for certain apps (document editing or creation apps as opposed to reading or browings apps) the desktop:

  • exposes the file system to the user (in the File menu)
  • uses drag and drop

whereas mobile platforms use the notion of ‘sharing’ to the file system and other apps

Notably lacking in Qt Quick Control is a ‘share sheet’.  A github project QtSharingKit seeks to remedy that, with a QML plugin.

Pragmatically, that means more work for you:

More links about QML, Qt Quick, and Quick Controls.

You use these technology pieces:

  • QML a language.
  • Qt Quick: the standard library of types and functionality for QML
  • Qt Quick Controls: canned (pre-built) QUI controls built using QML
  • QML Applications

Porting Qt apps from desktop to mobile: look and feel: developer responsibilities

Porting a cross-platform app from desktop to mobile is non-trivial!  Especially porting cross mobile platforms (Android and iOS.)

About

A brief overview of look and feel differences when porting a Qt app from desktops to mobile platforms. Emphasizing the divide of responsibilities between developer and Qt .  In other words, a to-do list for app developers, with some how-to for Qt.

For each topic:

  • nature of the problem
  • what Qt solves
  • what a developer must solve
  • references to relevant Qt documentation

This is:

  • time sensitive: Qt and others may solve some problems.
  • preliminary draft: not definitive, as I am just starting to explore this topic

Topics /Contents

A different word/widget for everything

Mobile platform islanding

Small screen

Gestures and touch

Look (platform style)

Single window

Dynamic orientation

Quitless

File system / document-centered

Printing

Screen resolution

Virtual keyboards

Version lag

Sensor gestures and undo

Share / Drag and drop

Settings

Examples and references

An example app from Qt that crosses desktop and mobile: QuickForecast including source weather-app

A similar post about native look-and-feel with Qt.

A different word/widget for everything

Mobile platforms use different widgets (feel?) For example iOS uses ActionSheets (now deprecated in iOS8 in favor of AlertControllers.) Some of these widgets may have no corresponding widget in Qt.  (Although an iOS ActionSheet is just a pop-up QMenu?)

Qt Widgets doesn’t seem to have specialized their widget behaviour for mobile platforms. Qt QML seems to be more targeted for mobile platforms, including the widget classes that only the mobile platforms have, and using native widgets so that their style (look) is correct for the platform.

Developer might need to implement widgets unique to each platform (to achieve native feel.)  For example, here is a QtWidgets implementation of a mobile widget (Toolbar or ActionBar) that largely achieves the Android platform’s look and feel.  (I’m not sure it achieves iOS look and feel.)

Mobile platform islanding

The mobile platforms attempt to differentiate themselves.  Usually they claim user interface reasons (this is the best way to do UI) but possibly just for business marketing reasons.  See Pure Android. (Whenever you see the word ‘pure’ you know that marketing and politics are involved.  99.99% pure. )  For example, toolbars are on the bottom in iOS, and at the top in Android.

Qt solved some of this on the desktop, for example, adapting differences in the menubar among desktop platforms.  Has Qt solved if for mobile platforms?

This is related to gestures, there is not a universal set across mobile platforms.

Small screen

This is the major hurdle.  Unless your app was designed from the start for mobile platforms.  Related to feel.

Smart phones have less GUI real estate.

Qt doesn’t fully solve this? Some widgets may automagically adjust to a smaller size, for example by scrolling?

A developer may need to:

  • redesign many dialogs, menus, and toolbars to take less space.
  • use different interaction techniques and widgets

Gestures and touch

Mobile platforms use multi-touch instead of pointers (mice, etc.)

Qt supports gestures and touch.

Developer:

  • learn and implement gestures/touch.  There is a significant learning curve, since it involves elements of multi-processing/concurrent programming: gestures may happen concurrently and be canceled.
  • may need to implement gesture recognizers for gestures not built into Qt (e.g. TapTapSlide on WinRT)
  • may need platform specific code to adapt the semantics of gestures where the semantics are not the same across platform (for example, TapAndHold is similar to RMB on desktops, but WinRT says it ‘shows option’ while iOS seems to limit it to text items?)

Look (platform style)

Mobile platforms have their own style.

Qt provides stylesheets/themes for the platforms.

!!! Except not for QtWidgets on iOS !!! (Just using QML.  Since iOS does not expose enough to Qt.  See this long discussion on the Qt dev mailing list. )

Developer may need to use QML, or avoid iOS, or implement and style their own widgets.

Single window

Mobile platforms do not have a window manager.  Each of an app’s top-level windows (called a view on mobile platforms?)

Qt:  ???? I don’t know whether for example QToolBar is specialized for mobile platforms.

Developer: add a navigation toolbar so user can navigate between screens (‘navigate an information hierarchy or manage screen content’ .)  Called a ‘Navigation Bar’ on iOS

Dynamic orientation

A user expects to be able to rotate a mobile device from landscape to portrait orientation, and for the app to adjust in real time.  On a desktop, a user can rotate their screens, but they must restart the OS and apps.

Qt provides needed signals and methods.

Developer:

  • react to orientation changes, especially if an orientation change requires a change to the app’s feel (widgets).
  • mobile platforms support restriction of an app to certain orientations (say to landscape) but an app may still need to recognize physical ‘command’ button on right or left.

Quitless

On mobile platforms, a user hardly ever quits an app, instead just putting it in the background.  There is usually no File>Quit and no Close icon in a window title bar.  However, this is not unlike Sleep on desktops, which requires apps to be able to resume where they left off.

Qt supports state changes for applications.

Developer may need to save more context in settings?

File system / document-centered

Mobile platforms do not emphasize files and filesystems, or provide file browsers.  Mobile platforms sandbox (limit access) to the filesystem.  New is iOS8 is a feature called ‘Document Provider’, which seems to treat each application as a repository of document types (MimeTypes.)

QtWidgets QFileDialog seems to work on mobile platforms, but it is inappropriate for most users.  QML FileChooser???

Developer must provide their own dialogs for managing saved content.

Printing

Users don’t often print from mobile devices.  Note that simplified print support is new to iOS8.  Android?

Qt currently does not support the printing architectures of mobile platforms (the module QtPrintSupport is not compiled.)

A developer should wait for Qt to adapt QtPrintSupport to the mobile platforms?

Screen resolution

Mobile platforms often have higher resolution (pixels per inch) since a user holds the device closer.  (However, desktops are also trending to higher resolution just because it looks better.)  But I think this is orthogonal to screen size.  A mobile device may have a high resolution yet still have a small screen in terms of Point (Device Independent Pixels.)  Qt supporting high resolution does not magically solve the problem of a small screen.

Qt provides support for higher resolution using the concept of Device Independent Pixel (or Point.)

Developer may still have work to do?  See Qt’s Weather App, where the use a ratio?

See Retina Support in Qt

Virtual keyboards

A user on mobile platforms may not have a physical keyboard, but a virtual keyboard.  Also known as Software Input Panel or SIP (in Qt.)

Qt supports virtual keyboards transparently for TextEdit widgets.  However, they don’t expose the underlying classes, so it might be difficult to use if your app doesn’t use stock TextEdit widgets?

A developer must learn how to control a virtual keyboard via Qt’s methods on TextEdit.

QApplication.autoSipEnabled

WA_InputMethodEnabled

Version lag

The platforms roll out new versions more often than on the desktop.  Qt lags behind.  For example, iOS8 is out but Qt will not have bug free support until Qt 5.4?

Qt is committed to supporting new versions (and hopefully they will reduce the lag.)

Developer: suffer the delay, or contribute to Qt.

Sensor gestures and undo

Users on mobile platforms use sensors as input methods.  Desktops don’t (a desktop computer doesn’t move, i.e. change location.)  But mobile users expect to request undo using a shake.  Undo is common to both desktops and mobile.

Qt provides a plugin for gestures from sensor.  Qt does not seem to automatically convert a shake gesture to an undo event.

Developer must implement avail sensor gestures and call app undostack methods.  In other words, add mobile specific code to subscribe to sensor gestures, and connect the shake gesture to undo.

Share / Drag and drop

Since mobile platforms are single window, a user can’t drag and drop between windows.  Sending data between apps (typically social websites, but also including copy to clipboard, and printing) is known as ‘sharing.’  On mobile platforms, a user presses a ‘Share’ button and expects a view of targets that accept the current content.

Qt doesn’t yet seem to support this notion (UIActivityViewController on iOS, Intent.createChooser() on Android.)

Developer:

  • disable drag and drop.
  • implement this themselves, or contribute a solution to Qt?

Settings

On a desktop, an app usually provides a dialog for settings.  On a mobile platform, a user accesses the settiings for an app by choosing the system settings button, then finding your app in a list.

Qt doesn’t make this change automagically?

Developer: ??

Notes on pyqtdeploy

You should read the official documentation, but it is brief.  Here, I elaborate:

  • discuss general concepts that seem obvious to experienced developers
  • discuss specific commands

About pyqtdeploy

(See my other platform specific posts, I plan to consolidate sections here.)

Installing and upgrading pyqtdeploy

The pyqtdeploy download page is not really a place to download.  It says that you can:

  • install the latest stable release using pip3
  • install the latest development version using mercurial (hg)

Managing pyqtdeploy using pip3

Installing pip3

pip3 is needed to install stable pyqtdeploy

  • OSX: pip3 is installed with Python3.
  • Ubuntu: if pip3 is not already installed:
sudo apt-get install python3-pip
Installing latest stable pyqtdeploy
pip3 install pyqtdeploy

(If that fails on permissions: sudo pip3…. )

Upgrading stable pyqtdeploy

Pyqtdeploy is released frequently.  To upgrade to the latest stable release.

>pip3 install pyqtdeploy --upgrade

Soft linking to pyqtdeploy

It seems that the above does not put pyqtdeploy and pyqtdeploycli executables in the path.  You might need to make soft links:

>cd /usr/local/bin
>sudo ln -s /Library/Frameworks/Python.framework/Versions/3.4/bin/pyqtdeploycli pyqtdeploycli
>sudo ln -s /Library/Frameworks/Python.framework/Versions/3.4/bin/pyqtdeploy pyqtdeploy

Managing your development version of pyqtdeploy using Mercurial

Note that mercurial uses Python2.7 but pyqtdeploy uses Python3.

Installing pyqtdeploy using hg

>hg clone http://www.riverbankcomputing.com/hg/pyqtdeploy
>cd pyqtdeploy          # to the directory you just cloned
>make VERSION           # ? not sure why next two steps are not dependencies in the Makefile
>make pyqtdeploy/version.py
>sudo python3 setup.py install

Again note that we install in python3 site packages.

Updating your development version of pyqtdeploy
>cd ~/Downloads/pyqtdeploy*
>hg pull
>hg update
> ??? make VERSION
>sudo python3 setup.py install
Installing Mercurial

You need Mercurial to download development version of pyqtdeploy.  Mercurial is a version control system.  Also known as the ‘hg’ command.

The Mercurial downloads page.

Note that Mercurial uses Python 2.7 and doesn’t support Python3 but that’s usually OK since Python-2.7 is usually installed.

Pyqtdeploy is now two tools

Starting with version 0.6, there are separate tools:

  • pyqtdeploycli: a command line tool for building static libraries
  • pyqtdeploy: a GUI tool for building your app

(I suppose you could also use pyqtdeploycli to build your app, passing it a configuration file.  But using the GUI pyqtdeploy is much more intuitive and easy.)

Disambiguating deploy

The pyqtdeploy tools don’t actually deploy.  They just prepare for deploy.  They may create or touch:

  • source files (.c, .cpp and .py)
  • qmake projects (.pro)
  • make files (Makefile)

Subsequently you must continue to build using qmake, make, and other tools such as Qt Creator and Xcode.  Then you have a binary, executable app.

Qt Creator does not deploy to the App Store

You must read QT Platform Notes – iOS very carefully.  It says that Qt Creator will do everything for building a Qt iOS app except:  deploy to the App Store.

You don’t need to use Qt Creator, you can use only command line tools (and then possibly the Xcode GUI.)

But this is related to the difference between the iosSimulator and a real device: they use different ABI architectures.  You should think early about whether you will use Qt Creator, and whether you will use the iosSimulator or a real iOS device.  You must fork the process of building early, when you are building static libraries (for either iosSimulator/ i386 architecture, or a real device/ ARM architecture.)

(Will Qt Creator deploy to Google Play store?)

Choosing a toolchain

This is related to choosing a machine for deployment.

Ideally, you learn and use one toolchain that works for every platform (avoid the learning curve for some tools.)

  • use pyqtdeploy/qmake/Xcode/real iOS device for iOS
  • use pyqtdeploy/qmake/Xcode/real Android device for Android

But for Android I have also used, with mixed results:

  • pyqtdeploy/Qt Creator/real Android device
  • pyqtdeploy/qmake/command line scripts/real Android device

I’m not sure whether I need to learn and use the emulator/simulator tools to do sanity testing across device models (e.g. iPhone vs. iPad) and OS versions (e.g. iOSv7 vs iOSv8.)

Cross platform software development

These are not entirely general notes, but often specific to using:

  • Qt
  • PyQt
  • pyqtdeploy

GUI considerations for crossing mobile and desktop platforms

This doesn’t make sense unless your app’s GUI is carefully designed to be portable across mobile and desktop platforms.  I call  this a ‘universal user interface.’

A desktop has, and a mobile platform doesn’t have (?):

  • multiple overlapping windows
  • menubar
  • a file system and file browser

A mobile platform has, and a desktop may not have:

  • multitouch and gestures

I’m still experimenting here (but this a principal reason for my app.)  I don’t think that Qt provides a magic bullet.  That is, everything you can do in Qt may  not be portable and you still might need to have platform specific (mobile versus desktop) code in your app.

(And Qt encompasses many tools, such as Qt Quick, which I am ignoring here, but which may be more portable.)

Qt considerations for crossing mobile and desktop platforms

Printing: Qt does not currently seem to compile the QtPrintSupport module for the mobile platforms.

See QTBUG ????

Early versions of Android and iOS also did not support printing.  Now they do:

  • iOS: AirPrint
  • Android: ???

I suppose it just takes time for Qt to adapt to the mobile print frameworks.  How do they differ from desktop print frameworks?

How many dev machines do you need for cross platform development?

Suppose your software development process includes these steps:

  • development (creating new features and fixing bugs)
  • deployment (packaging)
  • testing

You might want a machine dedicated to each step (so you don’t need to worry about cross contamination.)

Probably you want a Mac for your deployment machine.  A real Mac can deploy to iOS, Android, and MacOS.  You can also create virtual machines (Ubuntu and Windows) on that Mac so that it can also deploy to those platforms.  In other words, a Mac can deploy to all platforms supported by Qt.

The reverse is not true.  No other platform will let you deploy to iOS since you are not legally permitted to create a MacOS virtual machine on anything other than a real Mac machine, and since Xcode runs only on a Mac, and since only Xcode lets you develop for iOS (with exceptions such as HTML5/Javascript?)

Note that Qt does not currently support WindowsRT (Metro).  That’s of little use anyway, since that platform is trailing in the market?

The latest pyqtdeploy user guide has a discussion about directory structures that enable sharing of data across target deployment processes.

Favoring Qt over Python modules for crossing platforms

In your code,  you should favor using Qt classes over using Python modules.  For example, use Qt’s support for file system operations over Python’s support.  More specifically, try not to use the os module (which drags in many other Python modules) of Python.

The reason is, as of this writing, the Python organization does not support mobile platforms.  You may have difficulty cross compiling Python modules to mobile platforms (which you must do when you use pyqtdeploy.)  Also, you will package Qt libraries with your app, and also packaging Python modules that do the same thing is superflous.

Emulators and Simulators for Mobile Devices

To test a mobile app without a real device you can use:

  • Android emulator (AVD)
  • iOS simulator

Note the difference.

An AVD is an emulator, presenting the ARM ABI (the interface of the target hardware).  It executes the same binary that will run on a real device.  Pragmatically, you only need to compile your app once, for the ARM ABI.

The iOS simulator is a simulator, presenting the iOS API (the interface of the target OS.)  It executes a binary that is compiled for the i386 ABI, which is not the same ABI as real devices (ARM.)  Pragmatically, this means you need to compile your app for both ABI’s  (if you want to test on the simulator.)