summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Shaw <andy.shaw@qt.io>2018-11-02 10:36:20 +0100
committerAndy Shaw <andy.shaw@qt.io>2018-12-21 13:25:54 +0000
commit4aac07d0237cd4895f670ae2df6a8844ab91b699 (patch)
treed9c79f91f844e42a5e779fe52edb7b5751d31f1a
parent28b2232e7818f560bcd6c57f09ef42f2363e5338 (diff)
Android: Add support for setting/getting html and uris from clipboard
This also updates the used API to use ClipData and not the deprecated ClipboardManager API. [ChangeLog][Platform Specific Changes][Android] QClipboard now supports HTML and URI data. Fixes: QTBUG-47835 Fixes: QTBUG-71503 Change-Id: I43f82bfc63b3d159087c0fb6c840c186a370e20c Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java131
-rw-r--r--src/plugins/platforms/android/androidjniclipboard.cpp68
-rw-r--r--src/plugins/platforms/android/androidjniclipboard.h5
-rw-r--r--src/plugins/platforms/android/qandroidplatformclipboard.cpp11
-rw-r--r--src/plugins/platforms/android/qandroidplatformclipboard.h5
5 files changed, 180 insertions, 40 deletions
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index adc67e93fb..5562c010aa 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -47,6 +47,7 @@ import java.util.concurrent.Semaphore;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
+import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ActivityInfo;
@@ -57,6 +58,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.content.ClipboardManager;
import android.content.ClipboardManager.OnPrimaryClipChangedListener;
+import android.content.ClipData;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
@@ -98,7 +100,9 @@ public class QtNative
private static ClipboardManager m_clipboardManager = null;
private static Method m_checkSelfPermissionMethod = null;
private static Boolean m_tabletEventSupported = null;
+ private static boolean m_usePrimaryClip = false;
public static QtThread m_qtThread = new QtThread();
+ private static Method m_addItemMethod = null;
private static final Runnable runPendingCppRunnablesRunnable = new Runnable() {
@Override
public void run() {
@@ -697,26 +701,133 @@ public class QtNative
}
}
+ private static void clearClipData()
+ {
+ m_usePrimaryClip = false;
+ }
private static void setClipboardText(String text)
{
- if (m_clipboardManager != null)
- m_clipboardManager.setText(text);
+ if (m_clipboardManager != null) {
+ ClipData clipData = ClipData.newPlainText("text/plain", text);
+ updatePrimaryClip(clipData);
+ }
}
public static boolean hasClipboardText()
{
- if (m_clipboardManager != null)
- return m_clipboardManager.hasText();
- else
- return false;
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getText() != null)
+ return true;
+ }
+ return false;
}
private static String getClipboardText()
{
- if (m_clipboardManager != null)
- return m_clipboardManager.getText().toString();
- else
- return "";
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getText() != null)
+ return primaryClip.getItemAt(i).getText().toString();
+ }
+ return "";
+ }
+
+ private static void updatePrimaryClip(ClipData clipData)
+ {
+ if (m_usePrimaryClip) {
+ ClipData clip = m_clipboardManager.getPrimaryClip();
+ if (Build.VERSION.SDK_INT >= 26) {
+ if (m_addItemMethod == null) {
+ Class[] cArg = new Class[2];
+ cArg[0] = ContentResolver.class;
+ cArg[1] = ClipData.Item.class;
+ try {
+ m_addItemMethod = m_clipboardManager.getClass().getMethod("addItem", cArg);
+ } catch (Exception e) {
+ }
+ }
+ }
+ if (m_addItemMethod != null) {
+ try {
+ m_addItemMethod.invoke(m_activity.getContentResolver(), clipData.getItemAt(0));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else {
+ clip.addItem(clipData.getItemAt(0));
+ }
+ m_clipboardManager.setPrimaryClip(clip);
+ } else {
+ m_clipboardManager.setPrimaryClip(clipData);
+ m_usePrimaryClip = true;
+ }
+ }
+
+ private static void setClipboardHtml(String text, String html)
+ {
+ if (m_clipboardManager != null) {
+ ClipData clipData = ClipData.newHtmlText("text/html", text, html);
+ updatePrimaryClip(clipData);
+ }
+ }
+
+ public static boolean hasClipboardHtml()
+ {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getHtmlText() != null)
+ return true;
+ }
+ return false;
+ }
+
+ private static String getClipboardHtml()
+ {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getHtmlText() != null)
+ return primaryClip.getItemAt(i).getHtmlText().toString();
+ }
+ return "";
+ }
+
+ private static void setClipboardUri(String uriString)
+ {
+ if (m_clipboardManager != null) {
+ ClipData clipData = ClipData.newUri(m_activity.getContentResolver(), "text/uri-list",
+ Uri.parse(uriString));
+ updatePrimaryClip(clipData);
+ }
+ }
+
+ public static boolean hasClipboardUri()
+ {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getUri() != null)
+ return true;
+ }
+ return false;
+ }
+
+ private static String[] getClipboardUris()
+ {
+ ArrayList<String> uris = new ArrayList<String>();
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getUri() != null)
+ uris.add(primaryClip.getItemAt(i).getUri().toString());
+ }
+ String[] strings = new String[uris.size()];
+ strings = uris.toArray(strings);
+ return strings;
}
private static void openContextMenu(final int x, final int y, final int w, final int h)
diff --git a/src/plugins/platforms/android/androidjniclipboard.cpp b/src/plugins/platforms/android/androidjniclipboard.cpp
index d169035339..671d0b56d0 100644
--- a/src/plugins/platforms/android/androidjniclipboard.cpp
+++ b/src/plugins/platforms/android/androidjniclipboard.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "androidjniclipboard.h"
+#include <QtCore/QUrl>
#include <QtCore/private/qjni_p.h>
QT_BEGIN_NAMESPACE
@@ -62,27 +63,60 @@ namespace QtAndroidClipboard
return;
}
}
-
- void setClipboardText(const QString &text)
+ void setClipboardMimeData(QMimeData *data)
{
- QJNIObjectPrivate::callStaticMethod<void>(applicationClass(),
- "setClipboardText",
- "(Ljava/lang/String;)V",
- QJNIObjectPrivate::fromString(text).object());
- }
-
- bool hasClipboardText()
- {
- return QJNIObjectPrivate::callStaticMethod<jboolean>(applicationClass(),
- "hasClipboardText");
+ QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "clearClipData");
+ if (data->hasText()) {
+ QJNIObjectPrivate::callStaticMethod<void>(applicationClass(),
+ "setClipboardText", "(Ljava/lang/String;)V",
+ QJNIObjectPrivate::fromString(data->text()).object());
+ }
+ if (data->hasHtml()) {
+ QJNIObjectPrivate::callStaticMethod<void>(applicationClass(),
+ "setClipboardHtml",
+ "(Ljava/lang/String;Ljava/lang/String;)V",
+ QJNIObjectPrivate::fromString(data->text()).object(),
+ QJNIObjectPrivate::fromString(data->html()).object());
+ }
+ if (data->hasUrls()) {
+ QList<QUrl> urls = data->urls();
+ for (const auto &u : qAsConst(urls)) {
+ QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "setClipboardUri",
+ "(Ljava/lang/String;)V",
+ QJNIObjectPrivate::fromString(u.toEncoded()).object());
+ }
+ }
}
- QString clipboardText()
+ QMimeData *getClipboardMimeData()
{
- QJNIObjectPrivate text = QJNIObjectPrivate::callStaticObjectMethod(applicationClass(),
- "getClipboardText",
- "()Ljava/lang/String;");
- return text.toString();
+ QMimeData *data = new QMimeData;
+ if (QJNIObjectPrivate::callStaticMethod<jboolean>(applicationClass(), "hasClipboardText")) {
+ data->setText(QJNIObjectPrivate::callStaticObjectMethod(applicationClass(),
+ "getClipboardText",
+ "()Ljava/lang/String;").toString());
+ }
+ if (QJNIObjectPrivate::callStaticMethod<jboolean>(applicationClass(), "hasClipboardHtml")) {
+ data->setHtml(QJNIObjectPrivate::callStaticObjectMethod(applicationClass(),
+ "getClipboardHtml",
+ "()Ljava/lang/String;").toString());
+ }
+ if (QJNIObjectPrivate::callStaticMethod<jboolean>(applicationClass(), "hasClipboardUri")) {
+ QJNIObjectPrivate uris = QJNIObjectPrivate::callStaticObjectMethod(applicationClass(),
+ "getClipboardUris",
+ "()[Ljava/lang/String;");
+ if (uris.isValid()) {
+ QList<QUrl> urls;
+ QJNIEnvironmentPrivate env;
+ jobjectArray juris = static_cast<jobjectArray>(uris.object());
+ const jint nUris = env->GetArrayLength(juris);
+ urls.reserve(static_cast<int>(nUris));
+ for (int i = 0; i < nUris; ++i)
+ urls << QUrl(QJNIObjectPrivate(env->GetObjectArrayElement(juris, i)).toString());
+ data->setUrls(urls);
+ }
+ }
+ return data;
}
void onClipboardDataChanged(JNIEnv */*env*/, jobject /*thiz*/)
diff --git a/src/plugins/platforms/android/androidjniclipboard.h b/src/plugins/platforms/android/androidjniclipboard.h
index 2ec566e729..e83e6b555c 100644
--- a/src/plugins/platforms/android/androidjniclipboard.h
+++ b/src/plugins/platforms/android/androidjniclipboard.h
@@ -51,9 +51,8 @@ namespace QtAndroidClipboard
{
// Clipboard support
void setClipboardManager(QAndroidPlatformClipboard *manager);
- void setClipboardText(const QString &text);
- bool hasClipboardText();
- QString clipboardText();
+ void setClipboardMimeData(QMimeData *data);
+ QMimeData *getClipboardMimeData();
void onClipboardDataChanged(JNIEnv */*env*/, jobject /*thiz*/);
// Clipboard support
}
diff --git a/src/plugins/platforms/android/qandroidplatformclipboard.cpp b/src/plugins/platforms/android/qandroidplatformclipboard.cpp
index dc5147b259..17dfe27d12 100644
--- a/src/plugins/platforms/android/qandroidplatformclipboard.cpp
+++ b/src/plugins/platforms/android/qandroidplatformclipboard.cpp
@@ -52,16 +52,15 @@ QMimeData *QAndroidPlatformClipboard::mimeData(QClipboard::Mode mode)
{
Q_UNUSED(mode);
Q_ASSERT(supportsMode(mode));
- m_mimeData.setText(QtAndroidClipboard::hasClipboardText()
- ? QtAndroidClipboard::clipboardText()
- : QString());
- return &m_mimeData;
+ QMimeData *data = QtAndroidClipboard::getClipboardMimeData();
+ data->setParent(this);
+ return data;
}
void QAndroidPlatformClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
{
- if (supportsMode(mode))
- QtAndroidClipboard::setClipboardText(data != 0 && data->hasText() ? data->text() : QString());
+ if (data && supportsMode(mode))
+ QtAndroidClipboard::setClipboardMimeData(data);
if (data != 0)
data->deleteLater();
}
diff --git a/src/plugins/platforms/android/qandroidplatformclipboard.h b/src/plugins/platforms/android/qandroidplatformclipboard.h
index dfc3629c10..3ed9d323f8 100644
--- a/src/plugins/platforms/android/qandroidplatformclipboard.h
+++ b/src/plugins/platforms/android/qandroidplatformclipboard.h
@@ -46,7 +46,7 @@
#ifndef QT_NO_CLIPBOARD
QT_BEGIN_NAMESPACE
-class QAndroidPlatformClipboard: public QPlatformClipboard
+class QAndroidPlatformClipboard : public QObject, public QPlatformClipboard
{
public:
QAndroidPlatformClipboard();
@@ -54,9 +54,6 @@ public:
QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;
void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) override;
bool supportsMode(QClipboard::Mode mode) const override;
-
-private:
- QMimeData m_mimeData;
};
QT_END_NAMESPACE