File indexing completed on 2024-05-05 04:50:32
0001 /* 0002 SPDX-FileCopyrightText: 2018 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr> 0003 0004 SPDX-License-Identifier: LGPL-3.0-or-later 0005 */ 0006 0007 #include "androidfilelisting.h" 0008 0009 #include "android/androidcommon.h" 0010 0011 #include "elisa_settings.h" 0012 #include "elisautils.h" 0013 0014 #include "filescanner.h" 0015 0016 #include <KLocalizedString> 0017 0018 #include <QThread> 0019 #include <QFileInfo> 0020 #include <QAtomicInt> 0021 0022 // C++ code 0023 #include <jni.h> 0024 #include <QAndroidJniObject> 0025 #include <QtAndroid> 0026 0027 #include <algorithm> 0028 0029 class AndroidFileListingPrivate 0030 { 0031 public: 0032 QHash<QString, DataTypes::ListTrackDataType> mAllAlbums; 0033 0034 QHash<QUrl, QDateTime> mAllFiles; 0035 0036 DataTypes::ListTrackDataType mNewTracks; 0037 0038 QHash<QString, QUrl> mCovers; 0039 0040 QAtomicInt mStopRequest = 0; 0041 }; 0042 0043 AndroidFileListing::AndroidFileListing(QObject *parent) 0044 : AbstractFileListing(parent), d(std::make_unique<AndroidFileListingPrivate>()) 0045 { 0046 AndroidFileListing::mCurrentInstance = this; 0047 0048 registerNativeMethods(); 0049 } 0050 0051 AndroidFileListing::~AndroidFileListing() = default; 0052 0053 void AndroidFileListing::applicationAboutToQuit() 0054 { 0055 AbstractFileListing::applicationAboutToQuit(); 0056 d->mStopRequest = 1; 0057 } 0058 0059 AndroidFileListing *AndroidFileListing::mCurrentInstance = nullptr; 0060 0061 AndroidFileListing *AndroidFileListing::currentInstance() 0062 { 0063 return mCurrentInstance; 0064 } 0065 0066 void AndroidFileListing::registerNativeMethods() 0067 { 0068 } 0069 0070 void AndroidFileListing::executeInit(QHash<QUrl, QDateTime> allFiles) 0071 { 0072 qCInfo(orgKdeElisaAndroid()) << "AndroidFileListing::executeInit"; 0073 AbstractFileListing::executeInit(std::move(allFiles)); 0074 } 0075 0076 void AndroidFileListing::triggerRefreshOfContent() 0077 { 0078 qCInfo(orgKdeElisaAndroid()) << "AndroidFileListing::triggerRefreshOfContent"; 0079 Q_EMIT indexingStarted(); 0080 0081 if (QtAndroid::checkPermission(QStringLiteral("android.permission.READ_EXTERNAL_STORAGE")) == QtAndroid::PermissionResult::Denied) { 0082 QtAndroid::requestPermissionsSync({QStringLiteral("android.permission.READ_EXTERNAL_STORAGE")}); 0083 } 0084 0085 if (QtAndroid::checkPermission(QStringLiteral("android.permission.READ_EXTERNAL_STORAGE")) == QtAndroid::PermissionResult::Denied) { 0086 qCInfo(orgKdeElisaAndroid()) << "AndroidFileListing::triggerRefreshOfContent" << "not scanning files due to missing permission"; 0087 return; 0088 } 0089 0090 AbstractFileListing::triggerRefreshOfContent(); 0091 0092 QAndroidJniObject musicList = QAndroidJniObject::callStaticObjectMethod("org/kde/elisa/ElisaActivity", 0093 "listAudioFiles", 0094 "(Landroid/content/Context;)Ljava/util/ArrayList;", 0095 QtAndroid::androidContext().object()); 0096 0097 auto nbTracks = musicList.callMethod<jint>("size"); 0098 0099 for (int i = 0; i < nbTracks; ++i) { 0100 auto newTrack = DataTypes::TrackDataType{}; 0101 0102 auto track = musicList.callObjectMethod("get", "(I)Ljava/lang/Object;", i); 0103 0104 newTrack[DataTypes::TitleRole] = track.callObjectMethod("getTitle", "()Ljava/lang/String;").toString(); 0105 newTrack[DataTypes::ArtistRole] = track.callObjectMethod("getArtist", "()Ljava/lang/String;").toString(); 0106 newTrack[DataTypes::AlbumRole] = track.callObjectMethod("getAlbumName", "()Ljava/lang/String;").toString(); 0107 newTrack[DataTypes::AlbumArtistRole] = track.callObjectMethod("getAlbumArtist", "()Ljava/lang/String;").toString(); 0108 newTrack[DataTypes::TrackNumberRole] = track.callMethod<jint>("getTrackNumber"); 0109 newTrack[DataTypes::DiscNumberRole] = track.callMethod<jint>("getDiscNumber"); 0110 newTrack[DataTypes::DurationRole] = QTime::fromMSecsSinceStartOfDay(track.callMethod<jlong>("getDuration")); 0111 newTrack[DataTypes::ResourceRole] = QUrl::fromLocalFile(track.callObjectMethod("getResourceURI", "()Ljava/lang/String;").toString()); 0112 newTrack[DataTypes::ImageUrlRole] = QUrl::fromLocalFile(track.callObjectMethod("getAlbumCover", "()Ljava/lang/String;").toString()); 0113 newTrack[DataTypes::GenreRole] = track.callObjectMethod("getGenre", "()Ljava/lang/String;").toString(); 0114 newTrack[DataTypes::ComposerRole] = track.callObjectMethod("getComposer", "()Ljava/lang/String;").toString(); 0115 0116 QFileInfo scanFileInfo(newTrack.resourceURI().toLocalFile()); 0117 newTrack[DataTypes::FileModificationTime] = scanFileInfo.metadataChangeTime(); 0118 0119 newTrack[DataTypes::RatingRole] = 0; 0120 newTrack[DataTypes::ElementTypeRole] = ElisaUtils::Track; 0121 0122 qCInfo(orgKdeElisaAndroid()) << "AndroidFileListing::triggerRefreshOfContent" << newTrack; 0123 0124 d->mNewTracks.push_back(newTrack); 0125 } 0126 0127 Q_EMIT tracksList(d->mNewTracks, d->mCovers); 0128 0129 Q_EMIT indexingFinished(); 0130 } 0131 0132 DataTypes::TrackDataType AndroidFileListing::scanOneFile(const QUrl &scanFile, const QFileInfo &scanFileInfo, FileSystemWatchingModes watchForFileSystemChanges) 0133 { 0134 auto newTrack = DataTypes::TrackDataType{}; 0135 0136 return newTrack; 0137 } 0138 0139 #include "moc_androidfilelisting.cpp"