diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
index 6817d65b06be661b19fa1fba48a5a8d429e08c65..90efcc5030d91e34733b2d07bd6a2284e182e11e 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
@@ -325,8 +325,10 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent,
     mMediaPlayer->setDataSource(mediaPath);
     mMediaPlayer->prepareAsync();
 
-    if (!reloading)
+    if (!reloading) {
         Q_EMIT mediaChanged(mMediaContent);
+        Q_EMIT actualMediaLocationChanged(mediaPath);
+    }
 
     resetBufferingProgress();
 }
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
index 5744c11b8a5deb6d5ce921216feded5debd62c21..1f61809cd84bff4d0c143660ab480d3cb32c3236 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
@@ -80,6 +80,7 @@ public:
 
 Q_SIGNALS:
     void metaDataUpdated();
+    void actualMediaLocationChanged(const QString &url);
 
 public Q_SLOTS:
     void setPosition(qint64 position) Q_DECL_OVERRIDE;
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp
index 175958676bb7685007d7ddcb6b1bd7d56c7d0e23..c6a7d3c391b871da83077fe7e6e7cce8bff708b9 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp
@@ -53,8 +53,8 @@ QAndroidMediaService::QAndroidMediaService(QObject *parent)
 {
     mMediaControl = new QAndroidMediaPlayerControl;
     mMetadataControl = new QAndroidMetaDataReaderControl;
-    connect(mMediaControl, SIGNAL(mediaChanged(QMediaContent)),
-            mMetadataControl, SLOT(onMediaChanged(QMediaContent)));
+    connect(mMediaControl, SIGNAL(actualMediaLocationChanged(QString)),
+            mMetadataControl, SLOT(onMediaChanged(QString)));
     connect(mMediaControl, SIGNAL(metaDataUpdated()),
             mMetadataControl, SLOT(onUpdateMetaData()));
 }
diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp
index 82bd7499785ab653dbe9ed676a951131d8de048a..7f68bc13cac45b4ff9de70726caa24f64d427302 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp
+++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp
@@ -101,18 +101,18 @@ QStringList QAndroidMetaDataReaderControl::availableMetaData() const
     return m_metadata.keys();
 }
 
-void QAndroidMetaDataReaderControl::onMediaChanged(const QMediaContent &media)
+void QAndroidMetaDataReaderControl::onMediaChanged(const QString &url)
 {
     if (!m_retriever)
         return;
 
-    m_mediaContent = media;
+    m_mediaLocation = url;
     updateData();
 }
 
 void QAndroidMetaDataReaderControl::onUpdateMetaData()
 {
-    if (!m_retriever || m_mediaContent.isNull())
+    if (!m_retriever || m_mediaLocation.isEmpty())
         return;
 
     updateData();
@@ -122,8 +122,8 @@ void QAndroidMetaDataReaderControl::updateData()
 {
     m_metadata.clear();
 
-    if (!m_mediaContent.isNull()) {
-        if (m_retriever->setDataSource(m_mediaContent.canonicalUrl())) {
+    if (!m_mediaLocation.isEmpty()) {
+        if (m_retriever->setDataSource(m_mediaLocation)) {
             QString mimeType = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::MimeType);
             if (!mimeType.isNull())
                 m_metadata.insert(QMediaMetaData::MediaType, mimeType);
diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h
index 67b92f1eb62e670ba34fe41213683f4c7a49f836..a8f1d92f2133d5dd5276cef313c562f79a0cf6d9 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h
+++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h
@@ -62,13 +62,13 @@ public:
     QStringList availableMetaData() const Q_DECL_OVERRIDE;
 
 public Q_SLOTS:
-    void onMediaChanged(const QMediaContent &media);
+    void onMediaChanged(const QString &url);
     void onUpdateMetaData();
 
 private:
     void updateData();
 
-    QMediaContent m_mediaContent;
+    QString m_mediaLocation;
     bool m_available;
     QVariantMap m_metadata;
 
diff --git a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp
index 7dfc6a6e329ddf8f7344567713c69e12b04994bd..83f12cb8c0b381b602c2350d7ab6991097d5dd83 100644
--- a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp
+++ b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp
@@ -43,9 +43,24 @@
 
 #include <QtCore/private/qjnihelpers_p.h>
 #include <QtCore/private/qjni_p.h>
+#include <QtCore/QUrl>
+#include <qdebug.h>
 
 QT_BEGIN_NAMESPACE
 
+static bool exceptionCheckAndClear(JNIEnv *env)
+{
+    if (Q_UNLIKELY(env->ExceptionCheck())) {
+#ifdef QT_DEBUG
+        env->ExceptionDescribe();
+#endif // QT_DEBUG
+        env->ExceptionClear();
+        return true;
+    }
+
+    return false;
+}
+
 AndroidMediaMetadataRetriever::AndroidMediaMetadataRetriever()
 {
     m_metadataRetriever = QJNIObjectPrivate("android/media/MediaMetadataRetriever");
@@ -76,55 +91,105 @@ void AndroidMediaMetadataRetriever::release()
     m_metadataRetriever.callMethod<void>("release");
 }
 
-bool AndroidMediaMetadataRetriever::setDataSource(const QUrl &url)
+bool AndroidMediaMetadataRetriever::setDataSource(const QString &urlString)
 {
     if (!m_metadataRetriever.isValid())
         return false;
 
     QJNIEnvironmentPrivate env;
+    QUrl url(urlString);
 
-    bool loaded = false;
+    if (url.isLocalFile()) { // also includes qrc files (copied to a temp file)
+        QJNIObjectPrivate string = QJNIObjectPrivate::fromString(url.path());
+        QJNIObjectPrivate fileInputStream("java/io/FileInputStream",
+                                          "(Ljava/lang/String;)V",
+                                          string.object());
 
-    QJNIObjectPrivate string = QJNIObjectPrivate::fromString(url.toString());
+        if (exceptionCheckAndClear(env))
+            return false;
+
+        QJNIObjectPrivate fd = fileInputStream.callObjectMethod("getFD",
+                                                                "()Ljava/io/FileDescriptor;");
+        if (exceptionCheckAndClear(env)) {
+            fileInputStream.callMethod<void>("close");
+            exceptionCheckAndClear(env);
+            return false;
+        }
 
-    QJNIObjectPrivate uri = m_metadataRetriever.callStaticObjectMethod("android/net/Uri",
-                                                                       "parse",
-                                                                       "(Ljava/lang/String;)Landroid/net/Uri;",
-                                                                       string.object());
-    if (env->ExceptionCheck()) {
-        env->ExceptionClear();
-    } else {
         m_metadataRetriever.callMethod<void>("setDataSource",
-                                             "(Landroid/content/Context;Landroid/net/Uri;)V",
-                                             QtAndroidPrivate::activity(),
-                                             uri.object());
-        if (env->ExceptionCheck())
-            env->ExceptionClear();
-        else
-            loaded = true;
-    }
+                                             "(Ljava/io/FileDescriptor;)V",
+                                             fd.object());
+
+        bool ok = !exceptionCheckAndClear(env);
+
+        fileInputStream.callMethod<void>("close");
+        exceptionCheckAndClear(env);
+
+        if (!ok)
+            return false;
+    } else if (url.scheme() == QLatin1String("assets")) {
+        QJNIObjectPrivate string = QJNIObjectPrivate::fromString(url.path().mid(1)); // remove first '/'
+        QJNIObjectPrivate activity(QtAndroidPrivate::activity());
+        QJNIObjectPrivate assetManager = activity.callObjectMethod("getAssets",
+                                                                   "()Landroid/content/res/AssetManager;");
+        QJNIObjectPrivate assetFd = assetManager.callObjectMethod("openFd",
+                                                                  "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;",
+                                                                  string.object());
+        if (exceptionCheckAndClear(env))
+            return false;
+
+        QJNIObjectPrivate fd = assetFd.callObjectMethod("getFileDescriptor",
+                                                        "()Ljava/io/FileDescriptor;");
+        if (exceptionCheckAndClear(env)) {
+            assetFd.callMethod<void>("close");
+            exceptionCheckAndClear(env);
+            return false;
+        }
 
-    return loaded;
-}
+        m_metadataRetriever.callMethod<void>("setDataSource",
+                                             "(Ljava/io/FileDescriptor;JJ)V",
+                                             fd.object(),
+                                             assetFd.callMethod<jlong>("getStartOffset"),
+                                             assetFd.callMethod<jlong>("getLength"));
 
-bool AndroidMediaMetadataRetriever::setDataSource(const QString &path)
-{
-    if (!m_metadataRetriever.isValid())
-        return false;
+        bool ok = !exceptionCheckAndClear(env);
 
-    QJNIEnvironmentPrivate env;
+        assetFd.callMethod<void>("close");
+        exceptionCheckAndClear(env);
 
-    bool loaded = false;
+        if (!ok)
+            return false;
+    } else if (QtAndroidPrivate::androidSdkVersion() >= 14) {
+        // On API levels >= 14, only setDataSource(String, Map<String, String>) accepts remote media
+        QJNIObjectPrivate string = QJNIObjectPrivate::fromString(urlString);
+        QJNIObjectPrivate hash("java/util/HashMap");
 
-    m_metadataRetriever.callMethod<void>("setDataSource",
-                                         "(Ljava/lang/String;)V",
-                                         QJNIObjectPrivate::fromString(path).object());
-    if (env->ExceptionCheck())
-        env->ExceptionClear();
-    else
-        loaded = true;
+        m_metadataRetriever.callMethod<void>("setDataSource",
+                                             "(Ljava/lang/String;Ljava/util/Map;)V",
+                                             string.object(),
+                                             hash.object());
+        if (exceptionCheckAndClear(env))
+            return false;
+    } else {
+        // While on API levels < 14, only setDataSource(Context, Uri) is available and works for
+        // remote media...
+        QJNIObjectPrivate string = QJNIObjectPrivate::fromString(urlString);
+        QJNIObjectPrivate uri = m_metadataRetriever.callStaticObjectMethod("android/net/Uri",
+                                                                           "parse",
+                                                                           "(Ljava/lang/String;)Landroid/net/Uri;",
+                                                                           string.object());
+        if (exceptionCheckAndClear(env))
+            return false;
+
+        m_metadataRetriever.callMethod<void>("setDataSource",
+                                             "(Landroid/content/Context;Landroid/net/Uri;)V",
+                                             QtAndroidPrivate::activity(),
+                                             uri.object());
+        if (exceptionCheckAndClear(env))
+            return false;
+    }
 
-    return loaded;
+    return true;
 }
 
 QT_END_NAMESPACE
diff --git a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h
index f18cec11d73efc9fb75bf69497a65186a6319dda..1a4a876ee8666e6f3063672a17a9cb2043805f20 100644
--- a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h
+++ b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h
@@ -43,7 +43,6 @@
 #define ANDROIDMEDIAMETADATARETRIEVER_H
 
 #include <QtCore/private/qjni_p.h>
-#include <qurl.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -81,8 +80,7 @@ public:
 
     QString extractMetadata(MetadataKey key);
     void release();
-    bool setDataSource(const QUrl &url);
-    bool setDataSource(const QString &path);
+    bool setDataSource(const QString &url);
 
 private:
     QJNIObjectPrivate m_metadataRetriever;