jellyfin-archive / cordova-plugin-chromecast Goto Github PK
View Code? Open in Web Editor NEWChromecast Plugin for Cordova
License: Other
Chromecast Plugin for Cordova
License: Other
The largest changes of this refactor are:
iOS, Android, and Chrome Desktop all work the same now! (With a few caveats.)
All 3 will pass the same set of tests included in the plugin.
iOS and Android have scanForRoutes
, stopScan
, and selectRoute
to replace getRouteListElement
iOS and Android still do not implement the full chromecast API, but a few more have been added, and existing ones have been made to match chrome desktop behavior.
Bug Fixes:
sendJavascript
usageImprovements:
Auto-tests:
Manual Tests:
Hi there
Is there a way getting this to work in an iframe?
Regards
Flemming
Hi,
everytime i seek using the seek function, everything works as expected except from the push notification: it restarts from 00.00 everytime you seek.
Is that a known issue?
Thanks
Hi again! I'm almost done!
Here is the thing...I'm able to successfully listen to the event from the STOP CASTING button using:
this._session.addUpdateListener(function listenerSession() {
if (this._session.status === window.chrome.cast.SessionStatus.STOPPED) { /* here *\ }
But I'm not able when I touch the X in the cast notification. As far as I understand that stop the session too.
Thanks !!
If you have a bunch of Google Home devices on your network and have them in a Group in the Google Home app, you'll see those devices duplicated in the Choose a Chromecast dialog in the Jellyfin Android app.
As you can see from my screenshot below, I have three Google Home speakers
And two Chromecasts
Now, Salon
and Chambre
are members of a group called Maison
. So when you select Maison
, music is played in sync on both speakers. So that's the expected behaviour.
Now, as you may have noticed, both speakers appears two times. This is because they are part of a group. If I remove one from the Maison group, it will only show once.
I made some changes and will have a PR for this soon.
TODO
Add a link to the readme documentation links with:
chrome.cast.media.Media (Supports most "Properties" and "Methods")
Maybe link to the tests for example usage.
Or make another test file with more advanced usage. including play state detection, seek
The phonegap builder (for iOS) exits on the following error:
In file included from /project/xxx/Plugins/cordova-plugin-chromecast/MLPChromecast.m:5:
/project/xxx/Plugins/cordova-plugin-chromecast/MLPChromecast.h:6:9: fatal error: 'GoogleCast/GoogleCast.h' file not found
#import <GoogleCast/GoogleCast.h>
I import the plugin using:
<plugin source="git" spec="https://github.com/jellyfin/cordova-plugin-chromecast.git" />
in the config.xml
This method on iOS always returns an empty object.
This is the only way to style your own device picker, so we need to standardise this across iOS and android.
the following functions that comes in the example as
_media.pause ({}, function () {
});
,
_media.play({}, function () {
});
and
_media.stop({}, function () {
});
works properly, but could not get the
_media.seek(
This is isn't much of an issue, but it's a small bug I haven't been able to fix.
I'm building a feature to stream youtube video to a custom receiver. I've successfully managed to cast youtube videos to my custom receiver. However, whenever I start a cast session and start streaming the video to a chromecast and close my app to do something else in my phone, the cast session is still active (which is the desired behaviour), but whenever I re-open my app I can't determine if a session is active already before initializing the cast SDK.
I'm using Angular + Ionic. Here is my code, (Its not very elegant, but does the job haha)
// cast.service.ts
@Injectable({
providedIn: 'root',
})
export class CastService {
videoId: string;
startSeconds: number;
receiverId = 'my-receiver';
namespace = 'urn:x-cast:com.custom-namespace';
castEnabled = false;
isCasting = false;
castSession: any;
constructor() {}
setParams({ videoId, startSeconds }: { videoId: string; startSeconds: number }) {
this.videoId = videoId;
this.startSeconds = startSeconds;
}
getCast() {
return chrome.cast;
}
initCast() {
const apiConfig = new chrome.cast.ApiConfig(
new chrome.cast.SessionRequest(this.receiverId),
(session: any) => {
console.log(session);
this.castSession = session;
},
function (receiverAvailable: any) {
console.log(receiverAvailable);
}
);
chrome.cast.initialize(
apiConfig,
() => {
this.castEnabled = true;
alert(JSON.stringify(this.castSession, null, 2));
},
(err: any) => {
alert(JSON.stringify(err, null, 2));
}
);
}
requestSession(callback: Function) {
// TODO Refactor callback into a cast status observer to subscribe on player
chrome.cast.requestSession(
(session: any) => {
this.castSession = session;
this.loadYoutubeVideo();
callback();
// alert(JSON.stringify(this.castSession));
},
(err: any) => {
this.isCasting = false;
this.castSession = null;
callback();
// if (err.code === 'cancel') return;
// alert(JSON.stringify(err, null, 2));
}
);
}
stopSession() {
this.castSession.stop(
() => {
this.isCasting = false;
this.castSession = null;
},
(err: any) => {
alert(JSON.stringify(err, null, 2));
}
);
}
private loadYoutubeVideo() {
this.castSession.sendMessage(this.namespace, {
command: 'INIT_COMMUNICATION_CONSTANTS',
videoId: this.videoId,
startSeconds: 0,
});
this.isCasting = true;
}
}
// youtube-player.component.ts
@Component({
selector: 'app-youtube-player',
templateUrl: './youtube-player.component.html',
styleUrls: ['./youtube-player.component.scss'],
})
export class YoutubePlayerComponent implements OnInit {
@Input() src: string;
@ViewChild('player', { static: true }) player: ElementRef;
loading: boolean = true;
castButton: HTMLButtonElement;
cast: any;
constructor(public renderer: Renderer2, public castService: CastService) {}
ngOnInit() {
this.castService.setParams({ videoId: this.src, startSeconds: 0 });
document.addEventListener('deviceready', () => {
// Trying to determine if cast is already active
this.cast = this.castService.getCast();
alert(JSON.stringify(this.cast.SessionStatus, null, 2));
// Initialize cast sdk
this.castService.initCast();
});
this.renderer.setAttribute(this.player.nativeElement, 'data-plyr-provider', 'youtube');
this.renderer.setAttribute(this.player.nativeElement, 'data-plyr-embed-id', this.src);
const player = new Plyr(this.player.nativeElement, {
controls: () => playerControls,
});
player.on('ready', (event) => {
this.loading = false;
this.castButton = <HTMLButtonElement>document.getElementById('castButton');
this.castButton.addEventListener('click', (e) => {
this.castService.requestSession(() => {
this.castButton.blur(); // Loose focus to update DOM
if (this.castService.isCasting) {
this.castButton.innerHTML = castConnectedIcon;
} else {
this.castButton.innerHTML = castIcon;
}
});
});
if (!this.castService.castEnabled) {
this.castButton.classList.add('disabled');
} else {
this.castButton.classList.remove('disabled');
this.castButton.innerHTML = castIcon;
}
});
}
}
Also, is it possible to show a push notification whenever I start casting with this plugin?
Hello and thanks for this amazing plugin.
I have set it up and got the example with the video and pause/stop working in few minutes.
Unfortunately, that is not the use I would like to achieve: I would need to open a remote URL on the screen. I have found this project that uses Chromecast APIs and works like a charm on their web-example using Chrome browser:
Project: https://github.com/DeMille/url-cast-receiver
Example: https://demille.github.io/url-cast-receiver/
Basically, I would like to achieve that using this plugin.
I have tried to adapt their implementation inside my test cordova app, but I always get issues when calling the requestSession method: the error callback gets triggered, and the error I get is: "namespace 'urn:x-cast:com.url.cast' not founded unverified"
I have tried both using the recommended App ID and namespace from the project, and also tried using one generated by me, but always get that error. After that, it looks like I can no longer close the session, not even force closing the app, so the only way to be able to scan again my Chromecast TV is to uninstall the app and re-install again, but I believe this is only a side effect of the main issue.
Thanks for any hint!
This is an intermittent issue. Possibly happens for version 0.x as well.
I am mostly creating this issue so that all of these notes can be stored here rather than in the code.
(It took me ~12 hours to pinpoint all of this, so this information is going somewhere.)
(I believe I have basically fixed this issue.)
On occasion it will fail to join the route with this sequence of events:
SessionManagerListener.onSessionStarting
MediaRoute.Callback.onRouteUnselected
SessionManager().getCurrentCastSession()
will return a session
with session.isConnected() == false
(so it seems it "sort of" connected, but no feedback on chromecast TV)SessionManagerListener.onSessionEnding
SessionManagerListener.onSessionEnded
(errCode == 0 (success))It never hits:
SessionManagerListener.onSessionStarted
SessionManagerListener.onSessionStartFailed
Possibly related to #48
Appears to be a timing issue.
MediaRouter
logs one of the following out whenever this situation occurs:
--------- beginning of crash
2022-09-06 10:51:50.814 29922-29922/com.d.devott E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.d.devott, PID: 29922
java.lang.IllegalArgumentException: com.d.devott: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
at android.app.PendingIntent.checkFlags(PendingIntent.java:382)
at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:673)
at android.app.PendingIntent.getBroadcast(PendingIntent.java:660)
at com.google.android.gms.internal.cast.zzah.zza(Unknown Source:32)
at com.google.android.gms.cast.framework.CastSession$zzb.onResult(Unknown Source:12)
at com.google.android.gms.common.api.internal.BasePendingResult$CallbackHandler.handleMessage(com.google.android.gms:play-services-base@@18.0.0:6)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8663)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
It would be awesome if this plugin could cast even to Amazon Fire Tv Stick device. Do you plan to implement something like that?
Thanks!
Not able to get my CORDOVA app built after adding the plugin. I am not android guy so can't understand the problem.
BUILD FAILED in 23s
cmd: Command failed with exit code 1 Error output:
C:\Users\hp.gradle\caches\transforms-1\files-1.1\appcompat-1.0.0.aar\b5c9fb90315cdd0e79db194839b0d380\res\values-v28\values-v28.xml:9:5-12:13: AAPT: error: resource android:attr/dialogCornerRadius not found.
\platforms\android\app\build\intermediates\incremental\mergeDebugResources\merged.dir\values-v28\values-v28.xml:11: AAPT: error: resource android:attr/dialogCornerRadius not found.
C:\Users\hp.gradle\caches\transforms-1\files-1.1\appcompat-v7-24.1.1.aar\f6a78c37ce4f50869e1b2c73fc669a08\res\values\values.xml:201:5-69: AAPT: error: resource android:attr/fontVariationSettings not found.
C:\Users\hp.gradle\caches\transforms-1\files-1.1\appcompat-v7-24.1.1.aar\f6a78c37ce4f50869e1b2c73fc669a08\res\values\values.xml:201:5-69: AAPT: error: resource android:attr/ttcIndex not found.
\platforms\android\app\build\intermediates\incremental\mergeDebugResources\merged.dir\values-v28\values-v28.xml:7: error: resource android:attr/dialogCornerRadius not found.
\platforms\android\app\build\intermediates\incremental\mergeDebugResources\merged.dir\values-v28\values-v28.xml:11: error: resource android:attr/dialogCornerRadius not found.
\platforms\android\app\build\intermediates\incremental\mergeDebugResources\merged.dir\values\values.xml:271: error: resource android:attr/fontVariationSettings not found.
\platforms\android\app\build\intermediates\incremental\mergeDebugResources\merged.dir\values\values.xml:271: error: resource android:attr/ttcIndex not found.
error: failed linking references.
Failed to execute aapt
com.android.ide.common.process.ProcessException: Failed to execute aapt
at com.android.builder.core.AndroidBuilder.processResources(AndroidBuilder.java:796)
at com.android.build.gradle.tasks.ProcessAndroidResources.invokeAaptForSplit(ProcessAndroidResources.java:551)
at com.android.build.gradle.tasks.ProcessAndroidResources.doFullTaskAction(ProcessAndroidResources.java:285)
at com.android.build.gradle.internal.tasks.IncrementalTask.taskAction(IncrementalTask.java:109)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$IncrementalTaskAction.doExecute(DefaultTaskClassInfoStore.java:173)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:134)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:121)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:122)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:197)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:107)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:111)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:70)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:63)
at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:88)
at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:248)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:197)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:107)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:124)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:80)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:105)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:99)
at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:625)
at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:580)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:99)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:60)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:128)
at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:46)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
at org.gradle.initialization.DefaultGradleLauncher$ExecuteTasks.run(DefaultGradleLauncher.java:311)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:197)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:107)
at org.gradle.initialization.DefaultGradleLauncher.runTasks(DefaultGradleLauncher.java:202)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:132)
at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:107)
at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:78)
at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:75)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:152)
at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:100)
at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:75)
at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$1.run(RunAsBuildOperationBuildActionRunner.java:43)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:197)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:107)
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:40)
at org.gradle.tooling.internal.provider.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:51)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:45)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:29)
at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:39)
at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:25)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:71)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:45)
at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:51)
at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:32)
at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:36)
at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:25)
at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:64)
at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:29)
at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:55)
at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:42)
at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:58)
at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:33)
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
at org.gradle.util.Swapper.swap(Swapper.java:38)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:62)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:82)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details
at com.google.common.util.concurrent.AbstractFuture.getDoneValue(AbstractFuture.java:503)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:482)
at com.google.common.util.concurrent.AbstractFuture$TrustedFuture.get(AbstractFuture.java:79)
at com.android.builder.core.AndroidBuilder.processResources(AndroidBuilder.java:794)
... 115 more
Caused by: java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details
at com.google.common.util.concurrent.AbstractFuture.getDoneValue(AbstractFuture.java:503)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:462)
at com.google.common.util.concurrent.AbstractFuture$TrustedFuture.get(AbstractFuture.java:79)
at com.android.builder.internal.aapt.v2.QueueableAapt2.lambda$makeValidatedPackage$1(QueueableAapt2.java:179)
Caused by: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details
at com.android.builder.png.AaptProcess$NotifierProcessOutput.handleOutput(AaptProcess.java:463)
at com.android.builder.png.AaptProcess$NotifierProcessOutput.err(AaptProcess.java:415)
at com.android.builder.png.AaptProcess$ProcessOutputFacade.err(AaptProcess.java:332)
at com.android.utils.GrabProcessOutput$1.run(GrabProcessOutput.java:104)
Currently on the generic metadata type is supported in the native code, while we can set the other types (movie, musictrack etc) in javascript and it gets passed through the native code checked if the metadata type is generic and if not ignores it.
However, even when the metadata type is generic it is still not populated on the receiver.
Same implementation limit and issue present on iOS and Android (so at least they're consistent!).
Need to investigate why metadata isn't being sent to the receiver and fix for the generic type.
Need to implement the other supported metadata types once the first issue is resolved.
I've successfully cast the audio to cast device. Then I just let the app open for some minutes then the app has been crashed.
Logcat shows me this error.
2019-10-05 15:02:32.807 1022-1022/com.hintdesk.sachxua D/AndroidRuntime: Shutting down VM
2019-10-05 15:02:32.814 1022-1022/com.hintdesk.sachxua E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.hintdesk.sachxua, PID: 1022
java.lang.IllegalStateException: Not connected. Call connect() and wait for onConnected() to be called.
at com.google.android.gms.common.internal.BaseGmsClient.checkConnected(Unknown Source:198)
at com.google.android.gms.internal.cast.zzdd.getVolume(Unknown Source:136)
at com.google.android.gms.cast.Cast$CastApi$zza.getVolume(Unknown Source:23)
at acidhax.cordova.chromecast.ChromecastSession.createSessionObject(ChromecastSession.java:471)
at acidhax.cordova.chromecast.ChromecastSession.onConnectionSuspended(ChromecastSession.java:624)
at com.google.android.gms.common.internal.GmsClientEventManager.onUnintentionalDisconnection(Unknown Source:49)
at com.google.android.gms.common.api.internal.zaaw.zab(Unknown Source:319)
at com.google.android.gms.common.api.internal.zaah.onConnectionSuspended(Unknown Source:42)
at com.google.android.gms.common.api.internal.zabe.onConnectionSuspended(Unknown Source:106)
at com.google.android.gms.common.api.internal.zaq.onConnectionSuspended(Unknown Source:9)
at com.google.android.gms.common.internal.zaf.onConnectionSuspended(Unknown Source:4)
at com.google.android.gms.common.internal.BaseGmsClient$zzb.handleMessage(Unknown Source:39)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-10-05 15:02:32.823 1193-1204/? W/ActivityManager: Force finishing activity com.hintdesk.sachxua/.MainActivity
I noticed that the function documentation in chrome.cast.js is basically just a copy and paste from the official chromecast docs.
eg. chrome.cast.media.LoadRequest
https://developers.google.com/cast/docs/reference/chrome/chrome.cast.media.LoadRequest
At the bottom of the page it says:
"Creative Commons Attribution 4.0 License,Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License."
There site policies also give instructions on how to provide attribution:
https://developers.google.com/terms/site-policies#attribution
How this would apply in this case?
(I thought there was a thread about tracking license info for modules on here but I can't seem to find it... Maybe I was dreaming?)
The tv is showing a cromecast-icon when I run chrome.cast.requestSession (I use the example-script) but the function never finishes and there is no error.
Any thoughts on what it can be?
Jasmine is not really appropriate for our tests at all.
before
failed.I have started work on switching the test framework to Mocha. It appears that it will work much better.
Originally this was part of Issue #36, but that was getting monolithic and I would like to have a singular location that explains the reasoning for using a non-standard test framework.
When I try to deploy with this plugin added I get the following error:
Running command: Cordova\platforms\android\gradlew cdvBuildDebug -b Cordova\platforms\android\build.gradle
> Task :app:preBuild UP-TO-DATE
> Task :CordovaLib:preBuild UP-TO-DATE
> Task :CordovaLib:preDebugBuild UP-TO-DATE
> Task :CordovaLib:checkDebugManifest UP-TO-DATE
> Task :CordovaLib:processDebugManifest UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :CordovaLib:compileDebugAidl NO-SOURCE
> Task :app:compileDebugAidl UP-TO-DATE
> Task :CordovaLib:packageDebugRenderscript NO-SOURCE
> Task :app:compileDebugRenderscript UP-TO-DATE
> Task :app:checkDebugManifest UP-TO-DATE
> Task :app:generateDebugBuildConfig UP-TO-DATE
> Task :app:prepareLintJar UP-TO-DATE
> Task :app:generateDebugSources UP-TO-DATE
> Task :CordovaLib:compileDebugRenderscript UP-TO-DATE
> Task :CordovaLib:generateDebugBuildConfig UP-TO-DATE
> Task :CordovaLib:generateDebugResValues UP-TO-DATE
> Task :CordovaLib:generateDebugResources UP-TO-DATE
> Task :CordovaLib:packageDebugResources UP-TO-DATE
> Task :CordovaLib:generateDebugRFile UP-TO-DATE
> Task :CordovaLib:prepareLintJar UP-TO-DATE
> Task :CordovaLib:generateDebugSources UP-TO-DATE
> Task :CordovaLib:javaPreCompileDebug UP-TO-DATE
> Task :CordovaLib:compileDebugJavaWithJavac UP-TO-DATE
> Task :CordovaLib:processDebugJavaRes NO-SOURCE
> Task :CordovaLib:transformClassesAndResourcesWithPrepareIntermediateJarsForDebug UP-TO-DATE
> Task :app:javaPreCompileDebug UP-TO-DATE
> Task :app:mainApkListPersistenceDebug UP-TO-DATE
> Task :app:generateDebugResValues UP-TO-DATE
> Task :app:generateDebugResources UP-TO-DATE
> Task :app:mergeDebugResources UP-TO-DATE
> Task :app:createDebugCompatibleScreenManifests UP-TO-DATE
> Task :app:processDebugManifest UP-TO-DATE
> Task :app:processDebugResources UP-TO-DATE
> Task :app:compileDebugJavaWithJavac UP-TO-DATE
> Task :app:compileDebugNdk NO-SOURCE
> Task :app:compileDebugSources UP-TO-DATE
> Task :app:mergeDebugShaders UP-TO-DATE
> Task :app:compileDebugShaders UP-TO-DATE
> Task :app:generateDebugAssets UP-TO-DATE
> Task :CordovaLib:mergeDebugShaders UP-TO-DATE
> Task :CordovaLib:compileDebugShaders UP-TO-DATE
> Task :CordovaLib:generateDebugAssets UP-TO-DATE
> Task :CordovaLib:packageDebugAssets UP-TO-DATE
> Task :app:mergeDebugAssets UP-TO-DATE
> Task :app:validateSigningDebug UP-TO-DATE
> Task :app:signingConfigWriterDebug UP-TO-DATE
> Task :app:transformClassesWithDexBuilderForDebug UP-TO-DATE
D8: Program type already present: android.support.v4.media.MediaBrowserCompat$ConnectionCallback$ConnectionCallbackInternal
FAILURE: Build failed with an exception.
* What went wrong:
> Task :app:transformDexArchiveWithExternalLibsDexMergerForDebug FAILED
35 actionable tasks: 1 executed, 34 up-to-date
Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'.
> com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
Learn how to resolve the issue at https://developer.android.com/studio/build/dependencies#duplicate_classes. Program type already present: android.support.v4.media.MediaBrowserCompat$ConnectionCallback$ConnectionCallbackInternal
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 4s
Looking at the dependency tree, it looks like com.google.android.gms:play-services-cast:16.1.2
is the culprit for bringing in the older android.support.v4.media
library.
gradlew app:dependencies --configuration releaseRuntimeClasspath
:
> Task :app:dependencies
------------------------------------------------------------
Project :app
------------------------------------------------------------
releaseRuntimeClasspath - Resolved configuration for runtime for variant: release
+--- project :CordovaLib
+--- com.google.android.gms:play-services-cast:16.1.2
| +--- com.android.support:mediarouter-v7:26.1.0
| | +--- com.android.support:appcompat-v7:26.1.0
| | | +--- com.android.support:support-annotations:26.1.0
| | | +--- com.android.support:support-v4:26.1.0
| | | | +--- com.android.support:support-compat:26.1.0
| | | | | +--- com.android.support:support-annotations:26.1.0
| | | | | \--- android.arch.lifecycle:runtime:1.0.0
| | | | | +--- android.arch.lifecycle:common:1.0.0
| | | | | \--- android.arch.core:common:1.0.0
| | | | +--- com.android.support:support-media-compat:26.1.0
| | | | | +--- com.android.support:support-annotations:26.1.0
| | | | | \--- com.android.support:support-compat:26.1.0 (*)
| | | | +--- com.android.support:support-core-utils:26.1.0
| | | | | +--- com.android.support:support-annotations:26.1.0
| | | | | \--- com.android.support:support-compat:26.1.0 (*)
| | | | +--- com.android.support:support-core-ui:26.1.0
| | | | | +--- com.android.support:support-annotations:26.1.0
| | | | | \--- com.android.support:support-compat:26.1.0 (*)
| | | | \--- com.android.support:support-fragment:26.1.0
| | | | +--- com.android.support:support-compat:26.1.0 (*)
| | | | +--- com.android.support:support-core-ui:26.1.0 (*)
| | | | \--- com.android.support:support-core-utils:26.1.0 (*)
| | | +--- com.android.support:support-vector-drawable:26.1.0
| | | | +--- com.android.support:support-annotations:26.1.0
| | | | \--- com.android.support:support-compat:26.1.0 (*)
| | | \--- com.android.support:animated-vector-drawable:26.1.0
| | | +--- com.android.support:support-vector-drawable:26.1.0 (*)
| | | \--- com.android.support:support-core-ui:26.1.0 (*)
| | \--- com.android.support:palette-v7:26.1.0
| | +--- com.android.support:support-compat:26.1.0 (*)
| | \--- com.android.support:support-core-utils:26.1.0 (*)
| +--- com.google.android.gms:play-services-base:16.0.1
| | +--- com.google.android.gms:play-services-basement:16.0.1
| | | \--- com.android.support:support-v4:26.1.0 (*)
| | \--- com.google.android.gms:play-services-tasks:16.0.1
| | \--- com.google.android.gms:play-services-basement:16.0.1 (*)
| +--- com.google.android.gms:play-services-basement:16.0.1 (*)
| +--- com.google.android.gms:play-services-flags:16.0.1
| | +--- com.google.android.gms:play-services-base:16.0.1 (*)
| | \--- com.google.android.gms:play-services-basement:16.0.1 (*)
| \--- com.google.android.gms:play-services-tasks:16.0.1 (*)
+--- androidx.appcompat:appcompat:1.0.0
| +--- androidx.annotation:annotation:1.0.0
| +--- androidx.core:core:1.0.0
| | +--- androidx.annotation:annotation:1.0.0
| | +--- androidx.collection:collection:1.0.0
| | | \--- androidx.annotation:annotation:1.0.0
| | +--- androidx.lifecycle:lifecycle-runtime:2.0.0
| | | +--- androidx.lifecycle:lifecycle-common:2.0.0
| | | | \--- androidx.annotation:annotation:1.0.0
| | | +--- androidx.arch.core:core-common:2.0.0
| | | | \--- androidx.annotation:annotation:1.0.0
| | | \--- androidx.annotation:annotation:1.0.0
| | \--- androidx.versionedparcelable:versionedparcelable:1.0.0
| | +--- androidx.annotation:annotation:1.0.0
| | \--- androidx.collection:collection:1.0.0 (*)
| +--- androidx.collection:collection:1.0.0 (*)
| +--- androidx.cursoradapter:cursoradapter:1.0.0
| | \--- androidx.annotation:annotation:1.0.0
| +--- androidx.legacy:legacy-support-core-utils:1.0.0
| | +--- androidx.annotation:annotation:1.0.0
| | +--- androidx.core:core:1.0.0 (*)
| | +--- androidx.documentfile:documentfile:1.0.0
| | | \--- androidx.annotation:annotation:1.0.0
| | +--- androidx.loader:loader:1.0.0
| | | +--- androidx.annotation:annotation:1.0.0
| | | +--- androidx.core:core:1.0.0 (*)
| | | +--- androidx.lifecycle:lifecycle-livedata:2.0.0
| | | | +--- androidx.arch.core:core-runtime:2.0.0
| | | | | +--- androidx.annotation:annotation:1.0.0
| | | | | \--- androidx.arch.core:core-common:2.0.0 (*)
| | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.0.0
| | | | | +--- androidx.lifecycle:lifecycle-common:2.0.0 (*)
| | | | | +--- androidx.arch.core:core-common:2.0.0 (*)
| | | | | \--- androidx.arch.core:core-runtime:2.0.0 (*)
| | | | \--- androidx.arch.core:core-common:2.0.0 (*)
| | | \--- androidx.lifecycle:lifecycle-viewmodel:2.0.0
| | | \--- androidx.annotation:annotation:1.0.0
| | +--- androidx.localbroadcastmanager:localbroadcastmanager:1.0.0
| | | \--- androidx.annotation:annotation:1.0.0
| | \--- androidx.print:print:1.0.0
| | \--- androidx.annotation:annotation:1.0.0
| +--- androidx.fragment:fragment:1.0.0
| | +--- androidx.core:core:1.0.0 (*)
| | +--- androidx.legacy:legacy-support-core-ui:1.0.0
| | | +--- androidx.annotation:annotation:1.0.0
| | | +--- androidx.core:core:1.0.0 (*)
| | | +--- androidx.legacy:legacy-support-core-utils:1.0.0 (*)
| | | +--- androidx.customview:customview:1.0.0
| | | | +--- androidx.annotation:annotation:1.0.0
| | | | \--- androidx.core:core:1.0.0 (*)
| | | +--- androidx.viewpager:viewpager:1.0.0
| | | | +--- androidx.annotation:annotation:1.0.0
| | | | +--- androidx.core:core:1.0.0 (*)
| | | | \--- androidx.customview:customview:1.0.0 (*)
| | | +--- androidx.coordinatorlayout:coordinatorlayout:1.0.0
| | | | +--- androidx.annotation:annotation:1.0.0
| | | | +--- androidx.core:core:1.0.0 (*)
| | | | \--- androidx.customview:customview:1.0.0 (*)
| | | +--- androidx.drawerlayout:drawerlayout:1.0.0
| | | | +--- androidx.annotation:annotation:1.0.0
| | | | +--- androidx.core:core:1.0.0 (*)
| | | | \--- androidx.customview:customview:1.0.0 (*)
| | | +--- androidx.slidingpanelayout:slidingpanelayout:1.0.0
| | | | +--- androidx.annotation:annotation:1.0.0
| | | | +--- androidx.core:core:1.0.0 (*)
| | | | \--- androidx.customview:customview:1.0.0 (*)
| | | +--- androidx.interpolator:interpolator:1.0.0
| | | | \--- androidx.annotation:annotation:1.0.0
| | | +--- androidx.swiperefreshlayout:swiperefreshlayout:1.0.0
| | | | +--- androidx.annotation:annotation:1.0.0
| | | | +--- androidx.core:core:1.0.0 (*)
| | | | \--- androidx.interpolator:interpolator:1.0.0 (*)
| | | +--- androidx.asynclayoutinflater:asynclayoutinflater:1.0.0
| | | | +--- androidx.annotation:annotation:1.0.0
| | | | \--- androidx.core:core:1.0.0 (*)
| | | \--- androidx.cursoradapter:cursoradapter:1.0.0 (*)
| | +--- androidx.legacy:legacy-support-core-utils:1.0.0 (*)
| | +--- androidx.annotation:annotation:1.0.0
| | +--- androidx.loader:loader:1.0.0 (*)
| | \--- androidx.lifecycle:lifecycle-viewmodel:2.0.0 (*)
| +--- androidx.vectordrawable:vectordrawable:1.0.0
| | +--- androidx.annotation:annotation:1.0.0
| | \--- androidx.core:core:1.0.0 (*)
| \--- androidx.vectordrawable:vectordrawable-animated:1.0.0
| +--- androidx.vectordrawable:vectordrawable:1.0.0 (*)
| \--- androidx.legacy:legacy-support-core-ui:1.0.0 (*)
+--- androidx.mediarouter:mediarouter:1.0.0
| +--- androidx.media:media:1.0.0
| | +--- androidx.annotation:annotation:1.0.0
| | +--- androidx.core:core:1.0.0 (*)
| | \--- androidx.versionedparcelable:versionedparcelable:1.0.0 (*)
| +--- androidx.appcompat:appcompat:1.0.0 (*)
| +--- androidx.palette:palette:1.0.0
| | +--- androidx.core:core:1.0.0 (*)
| | \--- androidx.legacy:legacy-support-core-utils:1.0.0 (*)
| \--- androidx.recyclerview:recyclerview:1.0.0
| +--- androidx.annotation:annotation:1.0.0
| +--- androidx.core:core:1.0.0 (*)
| \--- androidx.legacy:legacy-support-core-ui:1.0.0 (*)
\--- androidx.legacy:legacy-support-v4:1.0.0
+--- androidx.core:core:1.0.0 (*)
+--- androidx.media:media:1.0.0 (*)
+--- androidx.legacy:legacy-support-core-utils:1.0.0 (*)
+--- androidx.legacy:legacy-support-core-ui:1.0.0 (*)
\--- androidx.fragment:fragment:1.0.0 (*)
(*) - dependencies omitted (listed previously)
I'm not quite sure how this is working for you guys?
In https://github.com/jellyfin/jellyfin-web/issues/440, it was discovered that playing a file with an apostrophe/single quote in its name would cause the Jellyfin Android app to lose control of the ChromeCast.
Through further review, it appears that this line presents an issue:
https://github.com/jellyfin/cordova-plugin-chromecast/blob/c1ba3e7b25ca1097efb21bef0baf19b0d6801971/src/android/Chromecast.java#L809
The Session ID is a GUID, and the namespace in this case is urn:x-cast:com.ConnectSDK
. The message is where the concern comes in.
Since the message will contain JSON, a single quote in a value (such as media title) is valid. However, the larger string in Java is wrapped in single quotes, so this causes the string to be terminated early.
We should identify the best way to handle unexpected single quotes in the message, or wrap this in a way where single quotes won’t interfere.
It would be nice if we could implement chrome Api's method of signalling that the api is available.
In Chrome desktop you do:
window['__onGCastApiAvailable'] = function(isAvailable, err) {
if (isAvailable) {
// start using the api
}
};
But in cordova-plugin-chromecast you do:
document.addEventListener("deviceready", function () {
// start using the api
});
Would be nice to conform a bit more because:
Hi,
This is not an issue but rather a discussion. I'd like to know if there is a way to display only the video receivers on the receiver list that pops up?
Thanks
Need to temporarily host local videos on a small server (nanohttpd maybe) and send the hosted url to the cast device to fix this probably.
Since this project is now being used in more than just an Android app, it is pretty important that we re-license it.
I don’t know about Cordova specifics with linking this plug-in, so I will start with an understanding that this is provided with any app that uses it.
Under the general terms of the GPLv2, distribution on the Apple App Store is not technically permitted. There are various reasons, and the FSF covers some here.
Technically, we have been given permission from @acidhax upstream to use the code as we see fit (see videostream/cordova-chromecast#62) and so @joshuaboniface added the GPLv2 (see 57ad1b7) as we believed that would be our only use at the time.
In order to make wider distribution more permissible, I propose that we re-license this library under a dual license. We will most likely follow the example set by VLC and choose a dual GPLv3/MPLv2 approach, but I am open to other suggestions.
In addition, to complete this process, we will need the permission of any contributors up to this point. I will tag them in a separate comment.
Hi ! I'm having trouble importing chrome just to use it
These are my steps:
INSTALL:
cordova plugin add https://github.com/jellyfin/cordova-plugin-chromecast.git
USE (This is probably the part Im doing wrong):
import * as Chrome from 'cordova-plugin-chromecast/www/chrome.cast';
Log:
ERROR in ./node_modules/cordova-plugin-chromecast/www/chrome.cast.js
Module not found: Error: Can't resolve 'cordova-plugin-chromecast.EventEmitter' in 'E:\Github Projects\moodreads-ionic-4\node_modules\cordova-plugin-chromecast\www'
resolve 'cordova-plugin-chromecast.EventEmitter' in 'E:\Github Projects\moodreads-ionic-4\node_modules\cordova-plugin-chromecast\www'
Parsed request is a module
using description file: E:\Github Projects\moodreads-ionic-4\node_modules\cordova-plugin-chromecast\package.json (relative path: ./www)
Field 'browser' doesn't contain a valid alias configuration
resolve as module
looking for modules in E:/Github Projects/moodreads-ionic-4
using description file: E:\Github Projects\moodreads-ionic-4\package.json (relative path: .)
Field 'browser' doesn't contain a valid alias configuration
using description file: E:\Github Projects\moodreads-ionic-4\package.json (relative path: ./cordova-plugin-chromecast.EventEmitter)
no extension
Field 'browser' doesn't contain a valid alias configuration
E:\Github Projects\moodreads-ionic-4\cordova-plugin-chromecast.EventEmitter doesn't exist
.ts
Field 'browser' doesn't contain a valid alias configuration
E:\Github Projects\moodreads-ionic-4\cordova-plugin-chromecast.EventEmitter.ts doesn't exist
.tsx
Field 'browser' doesn't contain a valid alias configuration
E:\Github Projects\moodreads-ionic-4\cordova-plugin-chromecast.EventEmitter.tsx doesn't exist
.mjs
Field 'browser' doesn't contain a valid alias configuration
E:\Github Projects\moodreads-ionic-4\cordova-plugin-chromecast.EventEmitter.mjs doesn't exist
.js
Field 'browser' doesn't contain a valid alias configuration
E:\Github Projects\moodreads-ionic-4\cordova-plugin-chromecast.EventEmitter.js doesn't exist
as directory
E:\Github Projects\moodreads-ionic-4\cordova-plugin-chromecast.EventEmitter doesn't exist
Thanks!
I got the following error:
cordova-plugin-chromecast/Chromecast.swift:1:8: error: no such module 'GoogleCast'
Maybe the dependencies are not installed correctly? But where can I download it and to which folder I have to copy it?
Thanks
Hi there! First of all, thank you for creating this plugin. I was trying to implement this plugin using @ionc/angular with cordova following th example code in the repo but whenever I select the device to cast the video it doesn't show anything on the smartTV screen but the casting icon and not the media. I'm using the default receiver appId as you do in the example, but would I have to make and register a custom receiver to be able to play the video on a smartTV or chromecast?
This is my implementation:
// cast.component.ts
@Component({
selector: 'app-cast',
templateUrl: 'cast.component.html',
styleUrls: ['cast.component.scss'],
})
export class Cast implements OnInit {
private cast: any;
private castSession: any;
private castMedia: any;
isCasting: boolean = false;
constructor() {}
ngOnInit() {
document.addEventListener('deviceready', () => this.initializeCast());
}
private initializeCast() {
this.cast = chrome.cast;
const castId = chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID;
const apiConfig = new this.cast.ApiConfig(
new this.cast.SessionRequest(castId),
(session: any) => {
console.log(session);
},
(receiverAvailable: any) => {
console.log(receiverAvailable);
}
);
this.cast.initialize(
apiConfig,
() => {
console.log('Cast initialized correctly!');
},
(err: string) => alert('Error initializing cast.')
);
}
requestSession() {
this.cast.requestSession(
(session: any) => {
this.castSession = session;
alert('Is suppossed to be casting!!!');
this.isCasting = true;
},
(err: string) => alert('Error requesting session.')
);
}
loadMedia() {
const videoUrl = 'https://ia801302.us.archive.org/1/items/TheWater_201510/TheWater.mp4';
const mediaInfo = new this.cast.media.MediaInfo(videoUrl, 'video/mp4');
this.castSession.loadMedia(
new this.cast.media.LoadRequest(mediaInfo),
(media: any) => {
console.log('Video should be playing now')
this.castMedia = media;
setTimeout(function () => this.pauseMedia(), 4000);
},
(err: string) => {
// Failed (check that the video works in your browser)
alert('Error loading media.');
}
);
}
pauseMedia() {
this.castMedia.pause(
{},
() => {
setTimeout(function () => this.stopSession(), 2000);
},
(err: any) => {
// Fail
alert(err);
}
);
}
stopCastSession() {
this.castSession.stop(
() => {
this.isCasting = false;
},
(err: string) => {
// Fail
alert(err);
}
);
}
}
And on the html
// cast.component.html
<ion-header [translucent]="true">
<ion-toolbar>
<ion-title> Testing App </ion-title>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Some title</ion-title>
</ion-toolbar>
</ion-header>
<div id="container">
<ion-button (click)="requestSession()">
{{isCasting ? 'Stop Casting' : 'Cast Video'}}
</ion-button>
</div>
</ion-content>
YOUTUBE - This really isn't an issue, but was looking through the repo and issues but didn't find any mention to casting Youtube videos and I was wondering if this was possible with this plugin.
When I send a content to Chromecast if I turn off the phone screen, when I go to de app again the sender can't send commands to de receiver, Ex: The play/pause action does not work and no notifications are received.
This occurs intermittently when trying to join a group route on 1.0.0. Possibly occurs in 0.x as well.
09-26 12:45:47.560 11533-11533/com.testy_pants.plugin_tests E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.miloproductionsinc.plugin_tests, PID: 11533
java.lang.NullPointerException
at androidx.mediarouter.media.MediaRouter$GlobalMediaRouter.setSelectedRouteInternal(MediaRouter.java:2633)
at androidx.mediarouter.media.MediaRouter$GlobalMediaRouter.selectRoute(MediaRouter.java:2120)
at androidx.mediarouter.media.MediaRouter$GlobalMediaRouter.selectRoute(MediaRouter.java:2108)
at androidx.mediarouter.media.MediaRouter.selectRoute(MediaRouter.java:406)
at acidhax.cordova.chromecast.ChromecastConnection$2$1.onRouteUpdate(ChromecastConnection.java:183)
at acidhax.cordova.chromecast.ChromecastConnection$ScanCallback.onFilteredRouteUpdate(ChromecastConnection.java:590)
at acidhax.cordova.chromecast.ChromecastConnection$ScanCallback.access$1200(ChromecastConnection.java:539)
at acidhax.cordova.chromecast.ChromecastConnection$5.run(ChromecastConnection.java:410)
at android.app.Activity.runOnUiThread(Activity.java:4713)
at acidhax.cordova.chromecast.ChromecastConnection.startRouteScan(ChromecastConnection.java:389)
at acidhax.cordova.chromecast.ChromecastConnection$2.run(ChromecastConnection.java:245)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Possibly slightly related to #49
Both problems seem to be caused by routes temporarily and quickly becoming unavailable before we are actually able to join.
From docs: https://developers.google.com/cast/docs/chrome_sender:
The Chrome Sender API consists of two parts: the Framework API (cast.framework) and the Base API (chrome.cast)
Is there any plan to implement first part - Framework API (cast.framework)?
I have two android devices and app crashes on method chrome.cast.requestSession call with below logs i found in logcat.
Device 1: OnePlus 7Pro, Android 9 - WORKS FINE
Device 2: OnePlus Two, Android 6.0.1 - CRASH
--------- beginning of crash
09-12 13:24:28.581 14046-14046/no.myapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: no.myapp, PID: 14046
java.lang.NoClassDefFoundError: acidhax.cordova.chromecast.-$$Lambda$r-7qqWexZCMew-ZX5x2dUMjX1R0
at acidhax.cordova.chromecast.Chromecast$2.run(Chromecast.java:209)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:152)
at android.app.ActivityThread.main(ActivityThread.java:5497)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
09-12 13:24:28.587 14046-14046/no.myapp D/AppTracker: App Event: crash
For Jellyfin testing, I only have one Android device that I can use. It is currently running 6.0.1, and I cannot update it to anything newer (there are no further updates provided by the manufacturer).
Starting with release 0.9.2, I can no longer cast. When I attempt to bring up the Chromecast dialog, there is this stack trace in the logs:
09-12 01:06:08.837 24419 24419 I chromium: [INFO:CONSOLE(214)] "chromecast launching app...", source: file:///android_asset/www/components/chromecast/chromecastplayer.js?v=12 (214)
09-12 01:06:08.847 24419 24474 I art : Rejecting re-init on previously-failed class java.lang.Class<acidhax.cordova.chromecast.-$$Lambda$r-7qqWexZCMew-ZX5x2dUMjX1R0>
09-12 01:06:08.847 24419 24474 I art : Rejecting re-init on previously-failed class java.lang.Class<acidhax.cordova.chromecast.-$$Lambda$r-7qqWexZCMew-ZX5x2dUMjX1R0>
09-12 01:06:08.850 24419 24419 I art : Rejecting re-init on previously-failed class java.lang.Class<acidhax.cordova.chromecast.-$$Lambda$r-7qqWexZCMew-ZX5x2dUMjX1R0>
09-12 01:06:08.850 24419 24419 D AndroidRuntime: Shutting down VM
09-12 01:06:08.852 24419 24419 E AndroidRuntime: FATAL EXCEPTION: main
09-12 01:06:08.852 24419 24419 E AndroidRuntime: Process: org.jellyfin.mobile, PID: 24419
09-12 01:06:08.852 24419 24419 E AndroidRuntime: java.lang.NoClassDefFoundError: acidhax.cordova.chromecast.-$$Lambda$r-7qqWexZCMew-ZX5x2dUMjX1R0
09-12 01:06:08.852 24419 24419 E AndroidRuntime: at acidhax.cordova.chromecast.Chromecast$2.run(Chromecast.java:210)
09-12 01:06:08.852 24419 24419 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:739)
09-12 01:06:08.852 24419 24419 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:95)
09-12 01:06:08.852 24419 24419 E AndroidRuntime: at android.os.Looper.loop(Looper.java:148)
09-12 01:06:08.852 24419 24419 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5417)
09-12 01:06:08.852 24419 24419 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
09-12 01:06:08.852 24419 24419 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
09-12 01:06:08.852 24419 24419 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
09-12 01:06:08.854 832 1420 W ActivityManager: Force finishing activity org.jellyfin.mobile/.MainActivity
The app then closes with a message: "Unfortunately, Jellyfin has stopped working."
If I revert back to our 0.9.1 release, everything is working. This would mean that some commit since July 5th 2019 has changed something that I means I can no longer test this.
sendJavascript is deprecated.
We are supposed to use the callbackContext instead.
Here is useful guide to get it started.
And here.
Hello,
Thanks for this fantastic plugin.
I have set it up in my Cordova app with targetSdkVersion: 30. But now, with targetSdkVersion: 33 it throws the following error when the app tries to connect the casing device.
I've updated all the plugins of my app but, couldn't find any way to solve it.
Thanks for any hint!
I'm getting this error after initiate cast from iOS:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid number value (infinite) in JSON write'
*** First throw call stack:
(0x213122190 0x2122f79f8 0x21302c3b0 0x213c28a84 0x213c26948 0x213c29950 0x21300d2e0 0x213c28f20 0x213c29950 0x21300d2e0 0x213c28f20 0x213ae55bc 0x213ae52e4 0x10030b940 0x1002f3bf4 0x1002f4a60 0x1002fe570 0x1002fe614 0x1003c35fc 0x10039872c 0x100398070 0x100396e50 0x10035232c 0x100365fa4 0x100365ae4 0x100352898 0x100371598 0x100db36f4 0x100db4c78 0x100dc26fc 0x2130b3b30 0x2130aea68 0x2130adfc4 0x2152af79c 0x23fa36c38 0x10029945c 0x212b6e8e0)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
The cast works on chromecast device but app crash.
Hi, I recently download the latest code (98edc9e) and the problem is that no tracks are received in javascript Media object. I started debug inside iOS code then i found that the code is commented at line 683 inside getMediaTracks's method, I think it's because of an error when creating the array of tracks. Then I try to fixed then I see the problem was [MLPCastUtilities getTextTrackSubtype:mediaTrack.textSubtype] when textSubtipe is 0 (Unknown) the method getTextTrackSubtype return nil because of default return inside switch. Thanks.
I want to know if anyone uses this, and whether or not it actually works?
@anthonylavado @dkanada Jellyfin uses a custom receiver I believe, which seems to be the main reason to use sendMessage.... So just wondering if you guys are using it? (even on the old version of cordova-plugin-chromecast)
I'm seeing some strange behavior that only happens on Android that i'm completely stuck on.
I do the following, I initialize a default media receiver, and I see that the receiver is available. I cast to the device successfully, and let the user stop the cast.
When the cast is stopped, if the user closes the app, removing it from the background apps by swiping to close, then the next time they open the app, the receiver will not become available. If they close it this way again, the receiver will be available this time. I can repeat this process in a pattern. Super frustrating, is there someway to reset the chrome.cast instance or something?
I am 100% sure I have no logic to cause this. Works completely fine every time on iOS and web.
Any help would be greatly appreciated.
Not an issue, but a question:
The only post I could find is this one https://stackoverflow.com/questions/19645972/chromecast-sdk-android-is-there-a-way-to-check-whether-the-media-playing-on but I wonder if any of you have used a different approach, it looks much for what it is.
The documentation has https://developers.google.com/cast/docs/reference/chrome/chrome.cast.media.Media#addUpdateListener but does not provide such a action.
Thanks!
Hi,
Right now I'm using chrome.cast
object and it works for android but not in IOS.
Can you please help me.
Thanks in advance!
desktop/cdv devs: devs who write a hosted app that runs on both cordova apps and on desktop browsers
This question arose when looking into PR #63.
The PR will add the function chrome.cast.media.setPlaybackRate
.
Unfortunately, media.setPlaybackRate
doesn't exist in the official Google Cast API for Chrome.
This is a problem for hosted cordova apps that run on both cordova apps and in desktop chrome.
Currently, you can use the exact same script to control a chromecast on cordova and on desktop chrome. Which is super convenient.
(Aside from functions under chrome.cast.cordova
, these functions supply operations that are impossible in the browser, and should be isolated to that).
Adding media.setPlaybackRate
would break this.
This functionality is possible in chrome desktop via:
session.sendMessage(
"urn:x-cast:com.google.cast.media",
{
mediaSessionId: session.media[0].mediaSessionId,
requestId: 12345,
type: 'SET_PLAYBACK_RATE',
playbackRate: 1
},
function () {
console.log('success');
}, function (err) {
console.log(err);
});
How do we handle this situation while inconveniencing the desktop/cdv devs minimally?
Here's what I can think of so far:
media.setPlaybackRate
and only use sendMessage
. Add a documentation note on how to set playback rate with sendMessage
.
media.setPlaybackRate
and add a note that this is a cordova exclusive function.
chrome.cast.cordova.setPlaybackRate
.
media.setPlaybackRate
which just calls the built sendMessage
function. Add a note for desktop-compatibly-hosted-web-app that they must include a copy of this file on their site to be able to use media.setPlaybackRate
.
media.setPlaybackRate*
, * points to note they need to add fileI like option 4 the best atm.
I would prefer to keep my chromecast controlling script as clean as possible. Currently, it doesn't even mention cordova once, I would like to keep it that way.
But I would like to hear any feedback about this issue/idea. Particularly from other desktop/cdv devs. But all welcome!
I had this same issue reported on my fork of the repo. I just tried running iOS myself as well (from jellyfin's master) and got the same error.
From the original issue post:
Build failed with this error.
'@objc' method name provides one argument name, but method has 0 parameters in Chromecast.swift
@objc(checkReceiverAvailable:)
@objc(checkReceiverAvailable:) func checkReceiverAvailable() { let sessionManager = GCKCastContext.sharedInstance().sessionManager if self.devicesAvailable.count > 0 || (sessionManager.currentSession != nil) { self.sendJavascript(jsCommand: "chrome.cast._.receiverAvailable()") } else { self.sendJavascript(jsCommand: "chrome.cast._.receiverUnavailable()") } }
I got this error while using cordova 9.0.0, ios platform 5.0.1, and xcode 10.2.2.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.