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