Skip to content

Commit

Permalink
(android) [Issue jellyfin-archive#73] Fix Push Notification stop cast…
Browse files Browse the repository at this point in the history
…ing button:

Add tests for stop casting and pause from push notification
  • Loading branch information
Lindsay-Needs-Sleep committed Oct 31, 2020
1 parent e39a848 commit 508ce1a
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 62 deletions.
45 changes: 26 additions & 19 deletions src/android/ChromecastConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@ public class ChromecastConnection {
private Activity activity;
/** settings object. */
private SharedPreferences settings;
/** Controls the media. */
private ChromecastSession media;
/** Controls the chromecastSession. */
private ChromecastSession chromecastSession;

/** Lifetime variable. */
private SessionListener newConnectionListener;
/** Indicates whether we left the session or stopped it. */
private boolean sessionEndBecauseOfLeave = false;
/** Any callback to call after sessionEnd. */
private CallbackContext sessionEndCallback = null;
/** The Listener callback. */
private Listener listener;

Expand All @@ -55,7 +59,7 @@ public class ChromecastConnection {
this.settings = activity.getSharedPreferences("CORDOVA-PLUGIN-CHROMECAST_ChromecastConnection", 0);
this.appId = settings.getString("appId", CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID);
this.listener = connectionListener;
this.media = new ChromecastSession(activity, listener);
this.chromecastSession = new ChromecastSession(activity, listener);

// Set the initial appId
CastOptionsProvider.setAppId(appId);
Expand All @@ -64,14 +68,27 @@ public class ChromecastConnection {
// CastContext and prep it for searching for a session to rejoin
// Also adds the receiver update callback
getContext().addCastStateListener(listener);
getSessionManager().addSessionManagerListener(new SessionListener() {
@Override
public void onSessionEnded(CastSession castSession, int errCode) {
chromecastSession.setSession(null);
if (sessionEndCallback != null) {
sessionEndCallback.success();
}
listener.onSessionEnd(ChromecastUtilities.createSessionObject(castSession, sessionEndBecauseOfLeave ? "disconnected" : "stopped"));
// Reset
sessionEndBecauseOfLeave = false;
sessionEndCallback = null;
}
}, CastSession.class);
}

/**
* Get the ChromecastSession object for controlling media and receiver functions.
* @return the ChromecastSession object
*/
ChromecastSession getChromecastSession() {
return this.media;
return chromecastSession;
}

/**
Expand Down Expand Up @@ -114,7 +131,7 @@ void onRouteUpdate(List<RouteInfo> routes) {
// If we do have a session
if (session != null) {
// Let the client know
media.setSession(session);
chromecastSession.setSession(session);
listener.onSessionRejoin(ChromecastUtilities.createSessionObject(session));
}
}
Expand Down Expand Up @@ -199,7 +216,7 @@ public void run() {
// getMediaRouter().getRoutes() which will result in "Ignoring attempt to select
// removed route: ", even if that route *should* be available. This state could
// happen because routes are periodically "removed" and "added", and if the last
// time media router was scanning ended when the route was temporarily removed the
// time chromecastSession router was scanning ended when the route was temporarily removed the
// getRoutes() fn will have no record of the route. We need the active scan to
// avoid this situation as well. PS. Just running the scan non-stop is a poor idea
// since it will drain battery power quickly.
Expand Down Expand Up @@ -372,7 +389,7 @@ private void listenForConnection(ConnectionCallback callback) {
@Override
public void onSessionStarted(CastSession castSession, String sessionId) {
getSessionManager().removeSessionManagerListener(this, CastSession.class);
media.setSession(castSession);
chromecastSession.setSession(castSession);
callback.onJoin(ChromecastUtilities.createSessionObject(castSession));
}
@Override
Expand Down Expand Up @@ -472,18 +489,8 @@ public void run() {
void endSession(boolean stopCasting, CallbackContext callback) {
activity.runOnUiThread(new Runnable() {
public void run() {
getSessionManager().addSessionManagerListener(new SessionListener() {
@Override
public void onSessionEnded(CastSession castSession, int error) {
getSessionManager().removeSessionManagerListener(this, CastSession.class);
media.setSession(null);
if (callback != null) {
callback.success();
}
listener.onSessionEnd(ChromecastUtilities.createSessionObject(castSession, stopCasting ? "stopped" : "disconnected"));
}
}, CastSession.class);

sessionEndCallback = callback;
sessionEndBecauseOfLeave = !stopCasting;
getSessionManager().endCurrentSession(stopCasting);
}
});
Expand Down
102 changes: 59 additions & 43 deletions tests/www/js/tests_manual.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
(function () {
'use strict';
/* eslint-env mocha */
/* global chrome */
/* global chrome cordova */

var assert = window.chai.assert;
var utils = window['cordova-plugin-chromecast-tests'].utils;
Expand Down Expand Up @@ -51,8 +51,20 @@
var cookieName = 'primary-p1_restart-reload';
var runningNum = parseInt(utils.getValue(cookieName) || '0');
var mediaInfo;
var photoItem;
var assertQueueProperties = function (media) {
utils.testMediaProperties(media);
assert.isObject(media.queueData);
utils.testQueueItems(media.items);
mediaUtils.assertMediaInfoItemEquals(media.media, mediaInfo);
var i = utils.getCurrentItemIndex(media);
assert.equal(i, 0);
mediaUtils.assertMediaInfoItemEquals(media.items[0].media, mediaInfo);
mediaUtils.assertMediaInfoItemEquals(media.items[1].media, photoItem);
};
before('Create MediaInfo', function () {
mediaInfo = mediaUtils.getMediaInfoItem('VIDEO', chrome.cast.media.MetadataType.GENERIC, new Date(2019, 10, 24));
photoItem = mediaUtils.getMediaInfoItem('IMAGE', chrome.cast.media.MetadataType.PHOTO, new Date(2020, 10, 31));
});
it('Create session', function (done) {
this.timeout(15000);
Expand Down Expand Up @@ -201,16 +213,13 @@
}
// Else, run the test

var photoItem = mediaUtils.getMediaInfoItem('IMAGE', chrome.cast.media.MetadataType.PHOTO, new Date(2020, 10, 31));
var request;

// Add items to the queue
var queue = [];
queue.push(new chrome.cast.media.QueueItem(mediaInfo));
queue.push(new chrome.cast.media.QueueItem(photoItem));

// Create request to repeat all and start at last item
request = new chrome.cast.media.QueueLoadRequest(queue);
var request = new chrome.cast.media.QueueLoadRequest(queue);
session.queueLoad(request, function (m) {
media = m;
console.log(media);
Expand All @@ -229,19 +238,8 @@
}, function (err) {
assert.fail('Unexpected Error: ' + err.code + ': ' + err.description);
});

function assertQueueProperties (media) {
utils.testMediaProperties(media);
assert.isObject(media.queueData);
utils.testQueueItems(media.items);
mediaUtils.assertMediaInfoItemEquals(media.media, mediaInfo);
var i = utils.getCurrentItemIndex(media);
assert.equal(i, 0);
mediaUtils.assertMediaInfoItemEquals(media.items[0].media, mediaInfo);
mediaUtils.assertMediaInfoItemEquals(media.items[1].media, photoItem);
}
});
it('media.pause should pause playback', function (done) {
it('Pause media from notifications', function (done) {
this.timeout(15000);
var testNum = 2;
assert.isAtLeast(runningNum, testNum, 'Should not be running this test yet');
Expand All @@ -250,30 +248,30 @@
return done();
}
// Else, run the test

var called = utils.waitForAllCalls([
{ id: success, repeats: false },
{ id: update, repeats: true }
], function () {
utils.storeValue(cookieName, ++runningNum);
done();
});
media.addUpdateListener(function listener (isAlive) {
assert.isTrue(isAlive);
assert.notEqual(media.playerState, chrome.cast.media.PlayerState.IDLE);
mediaUtils.assertMediaInfoItemEquals(media.media, mediaInfo);
assertQueueProperties(media);
if (media.playerState === chrome.cast.media.PlayerState.PAUSED) {
media.removeUpdateListener(listener);
called(update);
utils.storeValue(cookieName, ++runningNum);
done();
}
});
media.pause(null, function () {
assert.equal(media.playerState, chrome.cast.media.PlayerState.PAUSED);
mediaUtils.assertMediaInfoItemEquals(media.media, mediaInfo);
called(success);
}, function (err) {
assert.fail('Unexpected Error: ' + err.code + ': ' + err.description);
});
if (!utils.isDesktop() && cordova.platformId === 'android') {
utils.setAction('1. Drag down the Android notifications from the top status bar<br>2. Click the <b>pause button</b>',
'There is no chromecast notification drop-down', mediaPause);
} else {
mediaPause();
}
function mediaPause () {
media.pause(null, function () {
assert.equal(media.playerState, chrome.cast.media.PlayerState.PAUSED);
assertQueueProperties(media);
}, function (err) {
assert.fail('Unexpected Error: ' + err.code + ': ' + err.description);
});
}
});
it('Restart app with active session, should receive session on initialize', function (done) {
var instructionNum = 3;
Expand Down Expand Up @@ -313,11 +311,9 @@
function (sess) {
session = sess;
utils.testSessionProperties(sess);
// // Ensure the media is maintained
assert.isAbove(sess.media.length, 0);
// Ensure the media is maintained
media = sess.media[0];
assert.isUndefined(media.queueData);
mediaUtils.assertMediaInfoItemEquals(media.media, mediaInfo);
assertQueueProperties(media);
assert.equal(media.playerState, chrome.cast.media.PlayerState.PAUSED);
called(session_listener);
}, function receiverListener (availability) {
Expand Down Expand Up @@ -407,11 +403,9 @@
function (sess) {
session = sess;
utils.testSessionProperties(sess);
// // Ensure the media is maintained
assert.isAbove(sess.media.length, 0);
media = sess.media[0];
assert.isUndefined(media.queueData);
mediaUtils.assertMediaInfoItemEquals(media.media, mediaInfo);
// Ensure the media is maintained
media = session.media[0];
assertQueueProperties(media);
assert.equal(media.playerState, chrome.cast.media.PlayerState.PLAYING);
called(session_listener);
}, function receiverListener (availability) {
Expand All @@ -431,6 +425,28 @@
return done();
}
});
it('Stop session from notifications (android)', function (done) {
session.addUpdateListener(function listener (isAlive) {
if (session.status === chrome.cast.SessionStatus.STOPPED) {
assert.isFalse(isAlive);
session.removeUpdateListener(listener);
session = null;
done();
}
});
if (!utils.isDesktop() && cordova.platformId === 'android') {
utils.setAction('1. Drag down the Android notifications from the top status bar<br>2. Click the "<b>X</b>"',
'There is no chromecast notification drop-down', sessionStop);
} else {
sessionStop();
}
function sessionStop () {
session.stop(function () {
}, function (err) {
assert.fail('Unexpected Error: ' + err.code + ': ' + err.description);
});
}
});
after('Ensure session is stopped', function (done) {
// Reset tests
utils.storeValue(cookieName, 0);
Expand Down

0 comments on commit 508ce1a

Please sign in to comment.