What if you want to add a share feature to your cross platform QML app? Share on Facebook, Twitter, Email etc...
QML side
We will use a custom component that will let us share a text and a URL.
import QtQuick 2.3
import QtQuick.Controls 1.2
// Our import
import com.lasconic 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Share Utils")
//Custom component
ShareUtils {
id: shareUtils
}
Button {
id: share
text: "Share lasconic's blog"
anchors.centerIn: parent
onClicked: {
//simple call
shareUtils.share("Interesting blog", "http://blog.lasconic.com")
}
}
}
The component needs to be registered in the main.cpp of the app.
qmlRegisterType<ShareUtils> ("com.lasconic", 1, 0, "ShareUtils");
Now, of course, we need to implement the component on iOS and Android.
C++ side
The main C++ class is a just a delegate for the OS specific implementation.
ShareUtils::ShareUtils(QQuickItem *parent)
: QQuickItem(parent)
{
#if defined(Q_OS_IOS)
_pShareUtils = new IosShareUtils(this);
#elif defined(Q_OS_ANDROID)
_pShareUtils = new AndroidShareUtils(this);
#else
_pShareUtils = new PlatformShareUtils(this);
#endif
}
void ShareUtils::share(const QString &text, const QUrl &url)
{
_pShareUtils->share(text, url);
}
On Android
C++
We will just use JNI on the C++ side to call the Java side and the Android API. The Qt AndroidExtras package is handy.
void AndroidShareUtils::share(const QString &text, const QUrl &url)
{
QAndroidJniObject jsText = QAndroidJniObject::fromString(text);
QAndroidJniObject jsUrl = QAndroidJniObject::fromString(url.toString());
QAndroidJniObject::callStaticMethod<void>("com/musescore/QShareUtils",
"share",
"(Ljava/lang/String;Ljava/lang/String;)V",
jsText.object<jstring>(), jsUrl.object<jstring>());
}
In the pro file, we need to add QT += androidextras to be able to use QAndroidJniObject.
Java
We use QtNative to get the current activity and then it's pure Android API code. It will display all the apps that can deal with the text/plain mime type. We could choose which one we want to be listed, add a subject field etc... but it's beyond the scope of this article. A good intro here.
import org.qtproject.qt5.android.QtNative;
public static void share(String text, String url) {
if (QtNative.activity() == null)
return;
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, text + " " + url);
sendIntent.setType("text/plain");
QtNative.activity().startActivity(sendIntent);
}
On iOS
#import <UIKit/UIKit.h>
#import <QtGui/qpa/qplatformnativeinterface.h>
#import <QGuiApplication>
#import <QQuickWindow>
void IosShareUtils::share(const QString &text, const QUrl &url) {
NSMutableArray *sharingItems = [NSMutableArray new];
if (!text.isEmpty()) {
[sharingItems addObject:text.toNSString()];
}
if (url.isValid()) {
[sharingItems addObject:url.toNSURL()];
}
// Get the UIViewController
UIViewController *qtController = [[UIApplication sharedApplication].keyWindow rootViewController];
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
[qtController presentViewController:activityController animated:YES completion:nil];
}
Conclusion
Et voilà, the QML app will be able to pass a text and a URL to the underlying operating system and the user can enjoy a native UI to share to the social media of his choice.
Full code: https://github.com/lasconic/ShareUtils-QML