Comments (19)
CrossOpenTok.Current.Permissions = OpenTokPermission.RecordAudio;
from opentok-xamarin.forms.
Hi, I think this can be enhanced.
Here is the requested permissions list: https://github.com/AndreiMisiukevich/OpenTok-Xamarin.Forms/blob/master/Lib/Xamarin.Forms.OpenTok.Android/Service/PlatformOpenTokService.cs#L23
But you can work around it now for your app if extend this class, override request permission method and put desired ones.
Then register your custom service instead default
// PlatformOpenTokService.Init(); REPLACE THIS LINE BY NEXT LINES
OpenTokPublisherViewRenderer.Preserve();
OpenTokSubscriberViewRenderer.Preserve();
CrossOpenTok.Init(() => new CustomPlatformOpenTokService()); // CustomPlatformOpenTokService your class
from opentok-xamarin.forms.
Hi, thank you for the help.
I've implemented a custom service like you said, but when I attempt to open a call page, I get Object reference not set to an instance of an object.
This is the relevant stack trace:
OpenTokViewRenderer.OnElementChanged() : OpenTokViewRenderer.cs:31
OpenTokViewRenderer.ResetControl() : OpenTokViewRenderer.cs:40
OpenTokSubscriberViewRenderer.GetNativeView() : OpenTokSubscriberViewRenderer.cs:37 <-- Here the exception
from opentok-xamarin.forms.
Did you register it CrossOpenTok.Init(() => new CustomPlatformOpenTokService())
?
from opentok-xamarin.forms.
Yes.
Did exactly like this:
// PlatformOpenTokService.Init(); REPLACE THIS LINE BY NEXT LINES
OpenTokPublisherViewRenderer.Preserve();
OpenTokSubscriberViewRenderer.Preserve();
CrossOpenTok.Init(() => new CustomPlatformOpenTokService()); // CustomPlatformOpenTokService your class
from opentok-xamarin.forms.
Please show me your CustomPlatformOpenTokService class
from opentok-xamarin.forms.
Sure. Basically copied PlatformOpenTokService and just changed the permissions.
[Preserve(AllMembers = true)]
public sealed class CustomPlatformOpenTokService : BaseOpenTokService
{
public event Action PublisherUpdated;
public event Action SubscriberUpdated;
private readonly string[] _requestPermissions = {
Manifest.Permission.RecordAudio,
Manifest.Permission.Internet,
Manifest.Permission.AccessNetworkState
};
private readonly object _sessionLocker = new object();
private readonly ObservableCollection<string> _subscriberStreamIds = new ObservableCollection<string>();
private readonly Collection<SubscriberKit> _subscribers = new Collection<SubscriberKit>();
public CustomPlatformOpenTokService()
{
_subscriberStreamIds.CollectionChanged += OnSubscriberStreamIdsCollectionChanged;
PropertyChanged += OnPropertyChanged;
StreamIdCollection = new ReadOnlyObservableCollection<string>(_subscriberStreamIds);
Subscribers = new ReadOnlyCollection<SubscriberKit>(_subscribers);
}
public static CustomPlatformOpenTokService Instance => CrossOpenTok.Current as CustomPlatformOpenTokService;
public override ReadOnlyObservableCollection<string> StreamIdCollection { get; }
public ReadOnlyCollection<SubscriberKit> Subscribers { get; }
public Session Session { get; private set; }
public PublisherKit PublisherKit { get; private set; }
public static void Init()
{
OpenTokPublisherViewRenderer.Preserve();
OpenTokSubscriberViewRenderer.Preserve();
CrossOpenTok.Init(() => new CustomPlatformOpenTokService());
}
public override bool TryStartSession()
{
lock (_sessionLocker)
{
if (!CheckPermissions() ||
string.IsNullOrWhiteSpace(ApiKey) ||
string.IsNullOrWhiteSpace(SessionId) ||
string.IsNullOrWhiteSpace(UserToken))
{
return false;
}
EndSession();
IsSessionStarted = true;
using (var builder = new Session.Builder(CrossCurrentActivity.Current.AppContext, ApiKey, SessionId)
.SessionOptions(new SessionOptions()))
{
Session = builder.Build();
Session.ConnectionDestroyed += OnConnectionDestroyed;
Session.Connected += OnConnected;
Session.StreamReceived += OnStreamReceived;
Session.StreamDropped += OnStreamDropped;
Session.Error += OnError;
Session.Signal += OnSignal;
Session.Connect(UserToken);
}
return true;
}
}
public override void EndSession()
{
lock (_sessionLocker)
{
try
{
if (Session == null)
{
return;
}
foreach (var subscriberKit in _subscribers)
{
ClearSubscriber(subscriberKit);
}
_subscribers.Clear();
_subscriberStreamIds.Clear();
if (PublisherKit != null)
{
using (PublisherKit)
{
PublisherKit.PublishAudio = false;
PublisherKit.PublishVideo = false;
PublisherKit.StreamCreated -= OnPublisherStreamCreated;
}
PublisherKit = null;
}
RaisePublisherUpdated().
RaiseSubscriberUpdated();
if (Session != null)
{
using (Session)
{
Session.ConnectionDestroyed -= OnConnectionDestroyed;
Session.Connected -= OnConnected;
Session.StreamReceived -= OnStreamReceived;
Session.StreamDropped -= OnStreamDropped;
Session.Error -= OnError;
Session.Signal -= OnSignal;
Session.Disconnect();
}
Session = null;
}
}
finally
{
IsSessionStarted = false;
IsPublishingStarted = false;
}
}
}
public override bool CheckPermissions()
{
var activity = CrossCurrentActivity.Current.Activity;
var shouldGrantPermissions = _requestPermissions.Any(permission => ContextCompat.CheckSelfPermission(activity, permission) != (int)Permission.Granted);
if (shouldGrantPermissions)
{
ActivityCompat.RequestPermissions(activity, _requestPermissions, 0);
}
return !shouldGrantPermissions;
}
public override Task<bool> SendMessageAsync(string message)
{
Session.SendSignal(string.Empty, message);
return Task.FromResult(true);
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(IsVideoPublishingEnabled):
UpdatePublisherProperty(p => p.PublishVideo = IsVideoPublishingEnabled);
return;
case nameof(IsAudioPublishingEnabled):
UpdatePublisherProperty(p => p.PublishAudio = IsAudioPublishingEnabled);
return;
case nameof(IsVideoSubscriptionEnabled):
UpdateSubscriberProperty(s => s.SubscribeToVideo = IsVideoSubscriptionEnabled);
return;
case nameof(IsAudioSubscriptionEnabled):
UpdateSubscriberProperty(s => s.SubscribeToAudio = IsAudioSubscriptionEnabled);
return;
}
}
private void UpdatePublisherProperty(Action<PublisherKit> updateAction)
{
if (PublisherKit == null)
{
return;
}
updateAction?.Invoke(PublisherKit);
}
private void UpdateSubscriberProperty(Action<SubscriberKit> updateAction)
{
foreach (var subscriberKit in _subscribers)
{
updateAction?.Invoke(subscriberKit);
}
}
public override void CycleCamera() => (PublisherKit as Publisher)?.CycleCamera();
private void OnConnectionDestroyed(object sender, Session.ConnectionDestroyedEventArgs e)
=> RaiseSubscriberUpdated();
private void OnConnected(object sender, Session.ConnectedEventArgs e)
{
if (Session == null || PublisherKit != null)
{
return;
}
using (var builder = new Publisher.Builder(CrossCurrentActivity.Current.AppContext)
.Resolution(Publisher.CameraCaptureResolution.High)
.Name("XamarinOpenTok"))
{
PublisherKit = builder.Build();
PublisherKit.PublishVideo = IsVideoPublishingEnabled;
PublisherKit.PublishAudio = IsAudioPublishingEnabled;
PublisherKit.SetStyle(BaseVideoRenderer.StyleVideoScale, BaseVideoRenderer.StyleVideoFill);
PublisherKit.StreamCreated += OnPublisherStreamCreated;
Session.Publish(PublisherKit);
RaisePublisherUpdated();
}
}
private void OnStreamReceived(object sender, Session.StreamReceivedEventArgs e)
{
if (Session == null)
{
return;
}
DropStream(e.P1?.StreamId);
using (var builder = new Subscriber.Builder(CrossCurrentActivity.Current.AppContext, e.P1))
{
var subscriberKit = builder.Build();
subscriberKit.SubscribeToAudio = IsAudioSubscriptionEnabled;
subscriberKit.SubscribeToVideo = IsVideoSubscriptionEnabled;
subscriberKit.SetStyle(BaseVideoRenderer.StyleVideoScale, BaseVideoRenderer.StyleVideoFill);
subscriberKit.Connected += OnSubscriberConnected;
subscriberKit.StreamDisconnected += OnStreamDisconnected;
subscriberKit.SubscriberDisconnected += OnSubscriberDisconnected;
subscriberKit.VideoDataReceived += OnSubscriberVideoDataReceived;
subscriberKit.VideoDisabled += OnSubscriberVideoDisabled;
subscriberKit.VideoEnabled += OnSubscriberVideoEnabled;
Session.Subscribe(subscriberKit);
var streamId = e.P1.StreamId;
_subscribers.Add(subscriberKit);
_subscriberStreamIds.Add(streamId);
}
}
private void OnStreamDropped(object sender, Session.StreamDroppedEventArgs e)
=> DropStream(e.P1?.StreamId);
private void OnError(object sender, Session.ErrorEventArgs e)
{
RaiseError(e.P1?.Message);
EndSession();
}
private void OnSubscriberVideoDisabled(object sender, SubscriberKit.VideoDisabledEventArgs e)
=> RaiseSubscriberUpdated();
private void OnSubscriberVideoDataReceived(object sender, SubscriberKit.VideoDataReceivedEventArgs e)
=> RaiseSubscriberUpdated();
private void OnSubscriberVideoEnabled(object sender, SubscriberKit.VideoEnabledEventArgs e)
=> RaiseSubscriberUpdated();
private void OnSubscriberConnected(object sender, SubscriberKit.ConnectedEventArgs e)
=> RaisePublisherUpdated().RaiseSubscriberUpdated();
private void OnSubscriberDisconnected(object sender, SubscriberKit.SubscriberListenerDisconnectedEventArgs e)
=> RaisePublisherUpdated().RaiseSubscriberUpdated();
private void OnStreamDisconnected(object sender, SubscriberKit.StreamListenerDisconnectedEventArgs e)
=> RaisePublisherUpdated().RaiseSubscriberUpdated();
private void DropStream(string streamId)
{
var subscriberKit = _subscribers.FirstOrDefault(x => x.Stream?.StreamId == streamId);
if (subscriberKit != null)
{
ClearSubscriber(subscriberKit);
_subscribers.Remove(subscriberKit);
}
_subscriberStreamIds.Remove(streamId);
RaiseSubscriberUpdated();
}
private CustomPlatformOpenTokService RaiseSubscriberUpdated()
{
SubscriberUpdated?.Invoke();
return this;
}
private CustomPlatformOpenTokService RaisePublisherUpdated()
{
PublisherUpdated?.Invoke();
return this;
}
private void OnPublisherStreamCreated(object sender, PublisherKit.StreamCreatedEventArgs e)
=> IsPublishingStarted = true;
private void OnSignal(object sender, Session.SignalEventArgs e)
=> RaiseMessageReceived(e.P2);
private void ClearSubscriber(SubscriberKit subscriberKit)
{
using (subscriberKit)
{
subscriberKit.SubscribeToAudio = false;
subscriberKit.SubscribeToVideo = false;
subscriberKit.Connected -= OnSubscriberConnected;
subscriberKit.StreamDisconnected -= OnStreamDisconnected;
subscriberKit.SubscriberDisconnected -= OnSubscriberDisconnected;
subscriberKit.VideoDataReceived -= OnSubscriberVideoDataReceived;
subscriberKit.VideoDisabled -= OnSubscriberVideoDisabled;
subscriberKit.VideoEnabled -= OnSubscriberVideoEnabled;
}
}
public sealed class SessionOptions : Session.SessionOptions
{
public static bool IsCameraTwoCapable { private get; set; } = true;
public override bool UseTextureViews() => true;
public override bool IsCamera2Capable => IsCameraTwoCapable;
}
}
from opentok-xamarin.forms.
CustomPlatformOpenTokService
Wow) I meant just
[Preserve(AllMembers = true)]
class CustomPlatformOpenTokService: PlatformOpenTokService {
private readonly string[] _requestPermissions = {
Manifest.Permission.RecordAudio,
Manifest.Permission.Internet,
Manifest.Permission.AccessNetworkState
};
public override bool CheckPermissions()
{
var activity = CrossCurrentActivity.Current.Activity;
var shouldGrantPermissions = _requestPermissions.Any(permission => ContextCompat.CheckSelfPermission(activity, permission) != (int)Permission.Granted);
if (shouldGrantPermissions)
{
ActivityCompat.RequestPermissions(activity, _requestPermissions, 0);
}
return !shouldGrantPermissions;
}
}
Well if it doesn't help I need to take a look
from opentok-xamarin.forms.
You can't inherit from sealed class
tho.
from opentok-xamarin.forms.
You can't inherit from
sealed class
tho.
Oh, you are right... Need to update it
from opentok-xamarin.forms.
I'd be happy to make those adjustments, but I need to make sure it works.
As a temporary hack I've "reimplemented" the entire class and just changed the permissions, but I get this error:
Hi, thank you for the help.
I've implemented a custom service like you said, but when I attempt to open a call page, I getObject reference not set to an instance of an object.
This is the relevant stack trace:OpenTokViewRenderer.OnElementChanged() : OpenTokViewRenderer.cs:31 OpenTokViewRenderer.ResetControl() : OpenTokViewRenderer.cs:40 OpenTokSubscriberViewRenderer.GetNativeView() : OpenTokSubscriberViewRenderer.cs:37 <-- Here the exception
Do you have an idea about this problem? Where can it be fixed?
from opentok-xamarin.forms.
Do you have an idea about this problem? Where can it be fixed?
Yes, sure. And I will fix it today
from opentok-xamarin.forms.
Hi Andrei,
Thank you for the changes.
Android
As soon as I open the call page, I get the following error:
validateClientPermissionsLocked:1120: Caller "com.example.app" (PID 10363, UID 24879) cannot open camera "1" without camera permission
iOS
It just asks me for Camera permissions.
This is the .xaml side
<tok:OpenTokSubscriberView
AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
AbsoluteLayout.LayoutFlags="All" />
<tok:OpenTokPublisherView
IsVideoViewRunning="False" />
App.xaml.cs
CrossOpenTok.Current.IsVideoPublishingEnabled = false;
CrossOpenTok.Current.Permissions = OpenTokPermission.RecordAudio;
from opentok-xamarin.forms.
Do you see this bug on iOS only? Or both iOS and Android
from opentok-xamarin.forms.
Only Android raise the said exception. But iOS still ask for camera permissions.
I may add that the subscriber view does show video, only the publisher is voice only.
from opentok-xamarin.forms.
Only Android raise the said exception. But iOS still ask for camera permissions.
I may add that the subscriber view does show video, only the publisher is voice only.
Would you like to debug the plugin?)
from opentok-xamarin.forms.
Sure!
Should I clone the repository into my project and uninstall the nuget package?
from opentok-xamarin.forms.
Sure!
Should I clone the repository into my project and uninstall the nuget package?
I guess yes
from opentok-xamarin.forms.
1.3.1
from opentok-xamarin.forms.
Related Issues (20)
- Remove_popup HOT 3
- Opentok Pre-Call test HOT 2
- Subscriber video paused- show message to publisher. HOT 1
- Remove binding to StreamIdCollection() from one Page and bind it again on another Page automatically on Android HOT 4
- Is there any way to get Audio Levels Information in Xamarin Forms ? HOT 2
- publishing to multiple sessions HOT 2
- Add event for new stream subscriptions HOT 4
- OpenTokSubscriberView not working HOT 6
- [Xamarin.iOS] Exception with CrossOpenTok.Current.EndSession() HOT 3
- Screen sharing - not being picked up HOT 5
- Screen share - is this possible in this package HOT 2
- I can't end session in android even if I call "CrossOpenTok.Current.EndSession()". The stream is still running. HOT 7
- Is it possible to use with UWP? HOT 1
- Can I force video call to use "Media volume button control" instead of "Call volume button" in Android? HOT 6
- Xamarin.Vonage.Android is not compiling for Andriod-10 and above HOT 2
- Attempt to read from field 'android.os.MessageQueue android.os.Looper.mQueue' on a null object reference HOT 1
- Session Ended Event HOT 1
- Error in Camera HOT 7
- Switch to Vonage nuget packages HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from opentok-xamarin.forms.