From f4a754ad1cb513f708c7c7f1a17d174df182d3aa Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Fri, 6 Aug 2021 23:23:54 +0200 Subject: [PATCH] Notification! --- android/AndroidManifest.xml | 7 +- android/build.gradle | 1 + android/gradle.properties | 1 + android/res/drawable/ic_next_white.xml | 9 + android/res/drawable/ic_pause_white.xml | 9 + android/res/drawable/ic_play_white.xml | 9 + android/res/drawable/ic_previous_white.xml | 9 + android/src/org/kde/kasts/Activity.java | 27 --- android/src/org/kde/kasts/KastsActivity.java | 194 +++++++++++++++++++ src/audiomanager.cpp | 2 +- src/mediasessionclient.cpp | 31 ++- 11 files changed, 249 insertions(+), 50 deletions(-) create mode 100644 android/res/drawable/ic_next_white.xml create mode 100644 android/res/drawable/ic_pause_white.xml create mode 100644 android/res/drawable/ic_play_white.xml create mode 100644 android/res/drawable/ic_previous_white.xml delete mode 100644 android/src/org/kde/kasts/Activity.java create mode 100755 android/src/org/kde/kasts/KastsActivity.java diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 6b8960b4..9d2f317e 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -7,7 +7,7 @@ @@ -16,7 +16,7 @@ @@ -57,9 +57,6 @@ - - - diff --git a/android/build.gradle b/android/build.gradle index 538d0476..3032aa48 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -29,6 +29,7 @@ def timestamp = (int)(new Date().getTime()/1000) dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) implementation 'com.android.support:support-v4:28.0.0' + implementation 'androidx.core:core:1.3.1' } android { diff --git a/android/gradle.properties b/android/gradle.properties index 5bac8ac5..646c51b9 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1 +1,2 @@ android.useAndroidX=true +android.enableJetifier=true diff --git a/android/res/drawable/ic_next_white.xml b/android/res/drawable/ic_next_white.xml new file mode 100644 index 00000000..5d1017b1 --- /dev/null +++ b/android/res/drawable/ic_next_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/android/res/drawable/ic_pause_white.xml b/android/res/drawable/ic_pause_white.xml new file mode 100644 index 00000000..8356ff57 --- /dev/null +++ b/android/res/drawable/ic_pause_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/android/res/drawable/ic_play_white.xml b/android/res/drawable/ic_play_white.xml new file mode 100644 index 00000000..81a8f74f --- /dev/null +++ b/android/res/drawable/ic_play_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/android/res/drawable/ic_previous_white.xml b/android/res/drawable/ic_previous_white.xml new file mode 100644 index 00000000..75287857 --- /dev/null +++ b/android/res/drawable/ic_previous_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/android/src/org/kde/kasts/Activity.java b/android/src/org/kde/kasts/Activity.java deleted file mode 100644 index 1cb2e0e5..00000000 --- a/android/src/org/kde/kasts/Activity.java +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: 2018 Volker Krause -// SPDX-License-Identifier: LGPL-2.0-or-later - - -package org.kde.kasts; - -import org.qtproject.qt5.android.bindings.QtActivity; - -import android.content.Intent; -import android.database.Cursor; -import android.net.Uri; -import android.provider.CalendarContract; -import android.os.Bundle; -import android.util.Log; - -import java.io.*; -import java.util.*; - -public class Activity extends QtActivity -{ - private static final String TAG = "org.kde.kasts"; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } -} diff --git a/android/src/org/kde/kasts/KastsActivity.java b/android/src/org/kde/kasts/KastsActivity.java new file mode 100755 index 00000000..23a7451f --- /dev/null +++ b/android/src/org/kde/kasts/KastsActivity.java @@ -0,0 +1,194 @@ +// SPDX-FileCopyrightText: 2018 Volker Krause +// SPDX-License-Identifier: LGPL-2.0-or-later + + +package org.kde.kasts; + +import org.qtproject.qt5.android.bindings.QtActivity; + +import android.app.PendingIntent; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.provider.CalendarContract; +import android.os.Bundle; +import android.util.Log; + +import android.app.NotificationManager; +import android.app.NotificationChannel; +import android.app.Service; +import android.content.Context; +import android.support.v4.media.session.MediaSessionCompat; +import android.support.v4.media.session.PlaybackStateCompat; +import android.support.v4.media.MediaMetadataCompat; +import androidx.core.app.NotificationCompat; +import androidx.media.app.NotificationCompat.MediaStyle; + +import androidx.core.content.ContextCompat; + + +import java.io.*; +import java.util.*; + +public class KastsActivity extends QtActivity +{ + private static final String TAG = "org.kde.kasts.mediasession"; + + class MediaData { + public String title; + public long length; + public long position; + // add more variables here + } + + static MediaData mediaData; + + private static MediaSessionCompat mSession; + private static PlaybackStateCompat.Builder mPBuilder; + private static KastsActivity activity; + + void updateNotification() { + + // TODO: Change all of these variables to the values in mediaData + // add other required values + + MediaMetadataCompat.Builder metadata = new MediaMetadataCompat.Builder(); + + metadata.putString(MediaMetadataCompat.METADATA_KEY_TITLE, "The title"); + metadata.putString(MediaMetadataCompat.METADATA_KEY_AUTHOR, "Author"); + metadata.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, "Author"); + metadata.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, "The album"); + metadata.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, 1000000); + //TODO Image + mSession.setMetadata(metadata.build()); + + mPBuilder.setState(PlaybackStateCompat.STATE_PLAYING, 100000, 1.0f); + + Intent iPlay = new Intent(this, MediaSessionCallback.class); + iPlay.setAction("ACTION_PLAY"); + PendingIntent piPlay = PendingIntent.getBroadcast(this, 0, iPlay, PendingIntent.FLAG_UPDATE_CURRENT); + NotificationCompat.Action.Builder aPlay = new NotificationCompat.Action.Builder( + R.drawable.ic_play_white, "Play", piPlay); + + Intent iPause = new Intent(this, MediaSessionCallback.class); + iPause.setAction("ACTION_PAUSE"); + PendingIntent piPause = PendingIntent.getBroadcast(this, 0, iPause, PendingIntent.FLAG_UPDATE_CURRENT); + NotificationCompat.Action.Builder aPause = new NotificationCompat.Action.Builder( + R.drawable.ic_pause_white, "Pause", piPause); + + Intent iPrevious = new Intent(this, MediaSessionCallback.class); + iPrevious.setAction("ACTION_PREVIOUS"); + PendingIntent piPrevious = PendingIntent.getBroadcast(this, 0, iPrevious, PendingIntent.FLAG_UPDATE_CURRENT); + NotificationCompat.Action.Builder aPrevious = new NotificationCompat.Action.Builder( + R.drawable.ic_previous_white, "Previous", piPrevious); + + Intent iNext = new Intent(this, MediaSessionCallback.class); + iNext.setAction("ACTION_NEXT"); + PendingIntent piNext = PendingIntent.getBroadcast(this, 0, iNext, PendingIntent.FLAG_UPDATE_CURRENT); + NotificationCompat.Action.Builder aNext = new NotificationCompat.Action.Builder( + R.drawable.ic_next_white, "Next", piNext); + + Intent iOpenActivity = new Intent(this, KastsActivity.class); + iOpenActivity.putExtra("deviceId", "device"); + + NotificationCompat.Builder notification = new NotificationCompat.Builder(this, "media_control"); + notification + .setAutoCancel(false) + .setShowWhen(false) + .setVisibility(androidx.core.app.NotificationCompat.VISIBILITY_PUBLIC) + .setSubText("foobar") + .setContentTitle("Foo's title") + .setSmallIcon(this.getApplicationInfo().icon) + .setChannelId("org.kde.neochat.channel") + .setContentText("some random text"); + + notification.addAction(aPrevious.build()); + notification.addAction(aPause.build()); + notification.addAction(aNext.build()); + mSession.setPlaybackState(mPBuilder.build()); + MediaStyle mediaStyle = new MediaStyle(); + mediaStyle.setMediaSession(mSession.getSessionToken()); + mediaStyle.setShowActionsInCompactView(0, 1, 2); + notification.setStyle(mediaStyle); + notification.setGroup("MprisMediaSession"); + mSession.setActive(true); + NotificationManager nm = ContextCompat.getSystemService(this, NotificationManager.class); + NotificationChannel channel = new NotificationChannel("org.kde.neochat.channel", "KastsChannel", NotificationManager.IMPORTANCE_HIGH); + channel.setDescription("The notification channel"); + channel.enableLights(false); + channel.enableVibration(false); + nm.createNotificationChannel(channel); + nm.notify(0x487671, notification.build()); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mSession = new MediaSessionCompat(this, TAG); + mSession.setFlags( + MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | + MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS | + MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); + mSession.setCallback(new MediaSessionCallback(this)); + mPBuilder = new PlaybackStateCompat.Builder(); + activity = this; + mediaData = new MediaData(); + + updateNotification(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + mSession.release(); + } + + public static void setSessionState(int state) + { + //TODO: set state in mediadata + activity.updateNotification(); + + } + + private class MediaSessionCallback extends MediaSessionCompat.Callback { + private Context mContext; + + public MediaSessionCallback(Context context) { + super(); + + mContext = context; + } + + @Override + public void onPlay() { + super.onPlay(); + + mSession.setActive(true); + + //Update variables of mediaData; + activity.updateNotification(); + + //JNI to audiomanager play + //setPlaybackState for mSession + } + + @Override + public void onPause() { + super.onPause(); + + //JNI to audiomanager pause + //setPlaybackState for mSession + } + + @Override + public void onStop() { + super.onStop(); + + //JNI call to audiomanager stop + mSession.setActive(false); + } + } + +} diff --git a/src/audiomanager.cpp b/src/audiomanager.cpp index ebfcb367..1a0599c7 100644 --- a/src/audiomanager.cpp +++ b/src/audiomanager.cpp @@ -74,7 +74,7 @@ AudioManager::AudioManager(QObject *parent) connect(this, &AudioManager::logError, &ErrorLogModel::instance(), &ErrorLogModel::monitorErrorMessages); - MediaSessionClient mClient(this); + new MediaSessionClient(this); // Check if an entry was playing when the program was shut down and restore it if (DataManager::instance().lastPlayingEntry() != QStringLiteral("none")) { diff --git a/src/mediasessionclient.cpp b/src/mediasessionclient.cpp index 24eb3a22..a9e0ae20 100644 --- a/src/mediasessionclient.cpp +++ b/src/mediasessionclient.cpp @@ -21,29 +21,26 @@ void MediaSessionClient::setState() { qDebug() << m_audioPlayer->playbackState(); switch(m_audioPlayer->playbackState()) { - case QMediaPlayer::StoppedState : { - QAndroidJniObject::callStaticMethod - ("org/kde/kasts/MediaService" + case QMediaPlayer::StoppedState : + QAndroidJniObject::callStaticMethod + ("org/kde/kasts/KastsActivity" , "setSessionState" - , "(I)I" + , "(I)V" , 2); - break; - } - case QMediaPlayer::PausedState : { - QAndroidJniObject::callStaticMethod - ("org/kde/kasts/MediaService" + break; + case QMediaPlayer::PausedState : + QAndroidJniObject::callStaticMethod + ("org/kde/kasts/KastsActivity" , "setSessionState" - , "(I)I" + , "(I)V" , 1); - break; - } - case QMediaPlayer::PlayingState : { - QAndroidJniObject::callStaticMethod - ("org/kde/kasts/MediaService" + break; + case QMediaPlayer::PlayingState : + QAndroidJniObject::callStaticMethod + ("org/kde/kasts/KastsActivity" , "setSessionState" - , "(I)I" + , "(I)V" , 0); break; - } } }