Gluonhq VideoService - javafxports

I m developing a media player app and I m using VideoService for this purpose, my issue is the app life cycle when its minmized in backgroud while playing first its pause the video and i handle this in pause handler, when i maximize the app i call videoservice.play() but it play for a second and the whole app stuck in black screen and crash at the end.
if i dont call videoservice.play it will just crash, here my sample code.
private void initVideoService(VideoService service) {
videoService = service;
videoService.setPosition(Pos.CENTER, 0, 40, 0, 40);
videoService.setControlsVisible(true);
videoService.fullScreenProperty().addListener((obs, ov, nv) -> MobileApplication.getInstance().getAppBar().setVisible(!nv)); MobileApplication.getInstance().getAppBar().getActionItems().addAll(playButton, stopButton, fullScreenButton);
videoService.statusProperty().addListener((obs, ov, nv) -> {
System.out.println(String.format("FullScreenCondition : %b", nv != MediaPlayer.Status.PLAYING && nv != MediaPlayer.Status.PAUSED));
fullScreenButton.setDisable(nv != MediaPlayer.Status.PLAYING && nv != MediaPlayer.Status.PAUSED);
if (videoService.statusProperty().get() == MediaPlayer.Status.PLAYING) {
System.out.println("Video is Playing");
playButton.setGraphic(MaterialDesignIcon.PAUSE.graphic());
videoService.setFullScreen(true);
} else if (videoService.statusProperty().get() == MediaPlayer.Status.PAUSED) {
System.out.println("Video is paused");
playButton.setGraphic(MaterialDesignIcon.PLAY_ARROW.graphic());
videoService.setFullScreen(false);
} else {
System.out.println("Video is Stopped");
playButton.setGraphic(MaterialDesignIcon.PLAY_ARROW.graphic());
videoService.setFullScreen(false);
}
});
Services.get(LifecycleService.class).ifPresent(s -> {
s.addListener(LifecycleEvent.PAUSE, () -> {
System.out.println("paused");
videoService.pause();
});
s.addListener(LifecycleEvent.RESUME, () -> {
System.out.println("Resumed");
videoService.play();
});
});
}
public void navToEpisode(Episode epi) {
Services.get(VideoService.class).ifPresent(service -> {
initVideoService(service);
});
RestClient.execute(new RestOperation() {
#Override
public void run() {
String videoDownloadLink = RestUtils.getVideoDownloadLink(epi.getLinkToEpisode());
try {
publish(() ->
{
if (Platform.isAndroid() || Platform.isIOS()) {
videoService.getPlaylist().add(videoDownloadLink);
videoService.play();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

Related

How to implement AdMob native ads in Xamarin Forms IOS?

I'm having a Xamarin Forms application where I could successfully add banner ads and native ads for the android with custom renderers using Google AdMob NuGet. What I'm trying to achieve here is to make them work on IOS, I managed to do that (I suppose as I'm receiving test ads) with banner but when it comes to native, I get unified native ad and it never renders...
I'm using it inside of a custom listview data template which I thought it might cause an issue, so I tried using it in the page itself but no luck, same issue.
Here is my IOS renderer so far:
[assembly: ExportRenderer(typeof(NativeAdMobUnit), typeof(NativeAdMobUnitRenderer))]
namespace Example.iOS.Components
{
public class NativeAdMobUnitRenderer : ViewRenderer<NativeAdMobUnit, NativeExpressAdView>
{
protected override void OnElementChanged(ElementChangedEventArgs<NativeAdMobUnit> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
if (e.OldElement == null)
{
CreateAdView(this, e.NewElement.AdUnitId);
}
}
private void CreateAdView(NativeAdMobUnitRenderer renderer,String AdUnitId)
{
if (Element == null) return;
var loader = new AdLoader(
AdUnitId,
GetVisibleViewController(),
new AdLoaderAdType[] { AdLoaderAdType.UnifiedNative },
new AdLoaderOptions[] {
new NativeAdViewAdOptions {PreferredAdChoicesPosition = AdChoicesPosition.TopRightCorner}
});
var request = Request.GetDefaultRequest();
request.TestDevices = new string[] { Request.SimulatorId };
try
{
loader.Delegate = new MyAdLoaderDelegate(renderer);
Device.BeginInvokeOnMainThread(() => {
loader.LoadRequest(Request.GetDefaultRequest());
});
}
catch(Exception ex)
{
}
}
private UIViewController GetVisibleViewController()
{
var windows = UIApplication.SharedApplication.Windows;
foreach (var window in windows)
{
if (window.RootViewController != null)
{
return window.RootViewController;
}
}
return null;
}
private class MyAdLoaderDelegate : NSObject, IUnifiedNativeAdLoaderDelegate
{
private readonly NativeAdMobUnitRenderer _renderer;
public MyAdLoaderDelegate(NativeAdMobUnitRenderer renderer)
{
_renderer = renderer;
}
public void DidReceiveUnifiedNativeAd(AdLoader adLoader, UnifiedNativeAd nativeAd)
{
Debug.WriteLine("DidReceiveUnifiedNativeAd");
}
public void DidFailToReceiveAd(AdLoader adLoader, RequestError error)
{
Debug.WriteLine("DidFailToReceiveAd");
}
public void DidFinishLoading(AdLoader adLoader)
{
Debug.WriteLine("DidFinishLoading");
}
}
}
}
And that's the same but for Android which is working as expected:
[assembly: ExportRenderer(typeof(NativeAdMobUnit), typeof(NativeAdMobUnitRenderer))]
namespace Example.Droid.Renderers
{
public class NativeAdMobUnitRenderer : ViewRenderer
{
public NativeAdMobUnitRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
{
base.OnElementChanged(e);
if (Control == null)
{
NativeAdMobUnit NativeAdUnit = (NativeAdMobUnit)Element;
var adLoader = new AdLoader.Builder(Context, NativeAdUnit.AdUnitId);
var listener = new UnifiedNativeAdLoadedListener();
listener.OnNativeAdLoaded += (s, ad) =>
{
try
{
var root = new UnifiedNativeAdView(Context);
var inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
var adView = (UnifiedNativeAdView)inflater.Inflate(Resource.Layout.ad_unified, root);
populateUnifiedNativeAdView(ad, adView);
SetNativeControl(adView);
}
catch
{
}
};
adLoader.ForUnifiedNativeAd(listener);
var requestBuilder = new AdRequest.Builder();
adLoader.Build().LoadAd(requestBuilder.Build());
}
}
private void populateUnifiedNativeAdView(UnifiedNativeAd nativeAd, UnifiedNativeAdView adView)
{
adView.MediaView = adView.FindViewById<MediaView>(Resource.Id.ad_media);
// Set other ad assets.
adView.HeadlineView = adView.FindViewById<TextView>(Resource.Id.ad_headline);
adView.BodyView = adView.FindViewById<TextView>(Resource.Id.ad_body);
adView.CallToActionView = adView.FindViewById<TextView>(Resource.Id.ad_call_to_action);
adView.IconView = adView.FindViewById<ImageView>(Resource.Id.ad_app_icon);
adView.PriceView = adView.FindViewById<TextView>(Resource.Id.ad_price);
adView.StarRatingView = adView.FindViewById<RatingBar>(Resource.Id.ad_stars);
adView.StoreView = adView.FindViewById<TextView>(Resource.Id.ad_store);
adView.AdvertiserView = adView.FindViewById<TextView>(Resource.Id.ad_advertiser);
// The headline and mediaContent are guaranteed to be in every UnifiedNativeAd.
((TextView)adView.HeadlineView).Text = nativeAd.Headline;
// These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to
// check before trying to display them.
if (nativeAd.Body == null)
{
adView.BodyView.Visibility = ViewStates.Invisible;
}
else
{
adView.BodyView.Visibility = ViewStates.Visible;
((TextView)adView.BodyView).Text = nativeAd.Body;
}
if (nativeAd.CallToAction == null)
{
adView.CallToActionView.Visibility = ViewStates.Invisible;
}
else
{
adView.CallToActionView.Visibility = ViewStates.Visible;
((Android.Widget.Button)adView.CallToActionView).Text = nativeAd.CallToAction;
}
if (nativeAd.Icon == null)
{
adView.IconView.Visibility = ViewStates.Gone;
}
else
{
((ImageView)adView.IconView).SetImageDrawable(nativeAd.Icon.Drawable);
adView.IconView.Visibility = ViewStates.Visible;
}
if (string.IsNullOrEmpty(nativeAd.Price))
{
adView.PriceView.Visibility = ViewStates.Gone;
}
else
{
adView.PriceView.Visibility = ViewStates.Visible;
((TextView)adView.PriceView).Text = nativeAd.Price;
}
if (nativeAd.Store == null)
{
adView.StoreView.Visibility = ViewStates.Invisible;
}
else
{
adView.StoreView.Visibility = ViewStates.Visible;
((TextView)adView.StoreView).Text = nativeAd.Store;
}
if (nativeAd.StarRating == null)
{
adView.StarRatingView.Visibility = ViewStates.Invisible;
}
else
{
((RatingBar)adView.StarRatingView).Rating = nativeAd.StarRating.FloatValue();
adView.StarRatingView.Visibility = ViewStates.Visible;
}
if (nativeAd.Advertiser == null)
{
adView.AdvertiserView.Visibility = ViewStates.Invisible;
}
else
{
((TextView)adView.AdvertiserView).Text = nativeAd.Advertiser;
adView.AdvertiserView.Visibility = ViewStates.Visible;
}
adView.SetNativeAd(nativeAd);
}
}
public class UnifiedNativeAdLoadedListener : AdListener, UnifiedNativeAd.IOnUnifiedNativeAdLoadedListener
{
public void OnUnifiedNativeAdLoaded(UnifiedNativeAd ad)
{
OnNativeAdLoaded?.Invoke(this, ad);
}
public EventHandler<UnifiedNativeAd> OnNativeAdLoaded { get; set; }
}
}

xamarin.ios DO NOT dismiss UIAlertController when click outside of it

I am working in xamarin.forms project and I am stuck at a problem.
I want the main screen to remain enabled whenever UIAlertController(in android terms Toast) is shown. Here for me both the things are important.
When showing the alert, buttons from the background view should be clickable. And because an important message needs to be shown, the alert should also appear in parallel for given time.
In android, Toast does not interfere with the user interaction on main screen. Can I have same working thing in iOS ?
Here is what I have tried in my dependency service.
void ShowAlert(string message, double seconds)
{
try
{
if (alert == null && alertDelay == null)
{
alertDelay = NSTimer.CreateScheduledTimer(seconds, (obj) =>
{
Device.BeginInvokeOnMainThread(() =>
{
DismissMessage();
});
});
Device.BeginInvokeOnMainThread(() =>
{
try
{
alert = UIAlertController.Create("", message, UIAlertControllerStyle.Alert);
alert.View.UserInteractionEnabled = true;
topViewControllerWithRootViewController(UIApplication.SharedApplication.KeyWindow.RootViewController).PresentViewController(alert, true, () =>
{
UITapGestureRecognizer tap = new UITapGestureRecognizer(() => { }); // I have tried this but nothing happens
alert.View.Superview.Subviews[0].AddGestureRecognizer(tap);
});
}
catch (Exception ex)
{
var Error = ex.Message;
}
});
}
}
catch (Exception ex)
{
var Error = ex.Message;
}
}
void DismissMessage()
{
if (alert != null)
{
alert.DismissViewController(true, null);
alert = null;
}
if (alertDelay != null)
{
alertDelay.Dispose();
alertDelay = null;
}
}
UIViewController topViewControllerWithRootViewController(UIViewController rootViewController)
{
try
{
if (rootViewController is UITabBarController)
{
UITabBarController tabBarController = (UITabBarController)rootViewController;
return topViewControllerWithRootViewController(tabBarController.SelectedViewController);
}
else if (rootViewController is UINavigationController)
{
UINavigationController navigationController = (UINavigationController)rootViewController;
return topViewControllerWithRootViewController(navigationController.VisibleViewController);
}
else if (rootViewController.PresentedViewController != null)
{
UIViewController presentedViewController = rootViewController.PresentedViewController;
return topViewControllerWithRootViewController(presentedViewController);
}
}
catch (Exception)
{
}
return rootViewController;
}
There is no iOS native equivalent of a toast. But, there are many way of doing this as mentioned here: Toast equivalent for Xamarin Forms
One of the many solutions mentioned there will work, and if you are looking for a native solution, you can display an alert that dismisses by itself after a specified time as shown:
public class MessageIOS
{
const double LONG_DELAY = 3.5;
const double SHORT_DELAY = 2.0;
NSTimer alertDelay;
UIAlertController alert;
public void LongAlert(string message)
{
ShowAlert(message, LONG_DELAY);
}
public void ShortAlert(string message)
{
ShowAlert(message, SHORT_DELAY);
}
void ShowAlert(string message, double seconds)
{
alertDelay = NSTimer.CreateScheduledTimer(seconds, (obj) =>
{
dismissMessage();
});
alert = UIAlertController.Create(null, message, UIAlertControllerStyle.Alert);
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(alert, true, null);
}
void dismissMessage()
{
if (alert != null)
{
alert.DismissViewController(true, null);
}
if (alertDelay != null)
{
alertDelay.Dispose();
}
}
}

Xamarin.forms app crashes on inserting data to SQLite database

I am trying to take information entered by the user in the AddPage.Xaml.cs and add it to a SQLite database. The code runs fine until I press the add button then it crashes, I can't really figure out what is going on and I don't really know what I'm doing.
here is the necessary code and their corresponding classes.
This is in the AddPage.xaml.cs:
private async Task AddButton_Clicked(object sender, EventArgs e)
{
App.characterDatabase.SaveCharacter(new Character()
{
Name = NameTxt.Text,
Species = SpeciesTxt.Text,
ImageUrl = ImageUrlTxt.Text
});
}
The CharacterDatabaseController.cs
public class CharacterDatabaseController
{
static object locker = new object();
SQLiteConnection database;
public CharacterDatabaseController()
{
database = DependencyService.Get<IDatabaseConnection>().DbConnection();
database.CreateTable<Character>();
}
public Character GetCharacter()
{
lock (locker)
{
if (database.Table<Character>().Count() == 0)
{
return null;
}
else
{
return database.Table<Character>().First();
}
}
}
public int SaveCharacter(Character character)
{
lock (locker)
{
if (character.Id != 0)
{
database.Update(character);
return character.Id;
}
else
{
return database.Insert(character);
}
}
}
public int DeleteCharacter(int id)
{
lock (locker)
{
return database.Delete<Character>(id);
}
}
}
and the App.cs:
public static CharacterDatabaseController characterDatabase
{
get
{
if (characterDatabase == null)
{
CharacterDatabase = new CharacterDatabaseController();
}
return CharacterDatabase;
}
}

How to initiate a Video call using lync sdk?

My Aim: I want to initiate a video call from the start.
My Problem: It is getting initiated into audio call and then it's turning into video after end user answers the call.
void ConversationManager_ConversationAdded_Video(object sender, ConversationManagerEventArgs e)
{
Console.WriteLine("Inside conversation added for Video");
if (e.Conversation.Modalities[ModalityTypes.AudioVideo].State != ModalityState.Notified)
{
if (e.Conversation.CanInvoke(ConversationAction.AddParticipant))
{
try
{
e.Conversation.ParticipantAdded += Conversation_ParticipantAdded_Video;
e.Conversation.AddParticipant(client.ContactManager.GetContactByUri(receipient));
}
catch (ItemAlreadyExistException ex)
{
}
}
}
}
void Conversation_ParticipantAdded_Video(object source, ParticipantCollectionChangedEventArgs data)
{
if (data.Participant.IsSelf != true)
{
if (((Conversation)source).Modalities[ModalityTypes.AudioVideo].CanInvoke(ModalityAction.Connect))
{
object[] asyncState = { ((Conversation)source).Modalities[ModalityTypes.AudioVideo], "CONNECT" };
try
{
((Conversation)source).Modalities[ModalityTypes.AudioVideo].ModalityStateChanged += _AVModality_ModalityStateChanged_Video;
Console.WriteLine("entered video Satheesh participant added");
// ((Conversation)source).Modalities[ModalityTypes.AudioVideo].BeginConnect(ModalityCallback, asyncState);
((Conversation)source).Modalities[ModalityTypes.AudioVideo].BeginConnect(ModalityCallback, asyncState);
//((Conversation)source).Modalities[ModalityTypes.AudioVideo].EndConnect(ModalityCallback, asyncState);
Thread.Sleep(6000);
Console.WriteLine(source);
Console.WriteLine("entered video participant added");
}
catch (LyncClientException lce)
{
throw new Exception("Lync Platform Exception on BeginConnect: " + lce.Message);
}
}
}
}
public void ModalityCallback(IAsyncResult ar)
{
Object[] asyncState = (Object[])ar.AsyncState;
try
{
if (ar.IsCompleted == true)
{
if (asyncState[1].ToString() == "RETRIEVE")
{
((AVModality)asyncState[0]).EndRetrieve(ar);
}
if (asyncState[1].ToString() == "HOLD")
{
((AVModality)asyncState[0]).EndHold(ar);
}
if (asyncState[1].ToString() == "CONNECT")
{
Console.WriteLine("inside connect method CONNECT");
((AVModality)asyncState[0]).EndConnect(ar);
}
if (asyncState[1].ToString() == "FORWARD")
{
((AVModality)asyncState[0]).EndForward(ar);
}
if (asyncState[1].ToString() == "ACCEPT")
{
((AVModality)asyncState[0]).Accept();
}
}
}
catch (LyncClientException)
{ }
}
public void _AVModality_ModalityStateChanged_Video(object sender, ModalityStateChangedEventArgs e)
{
Console.WriteLine(sender);
Console.WriteLine("entered video modality changed");
switch (e.NewState)
{
case ModalityState.Connected:
if (_VideoChannel == null)
{
_VideoChannel = ((AVModality)sender).VideoChannel;
_VideoChannel.StateChanged += new EventHandler<ChannelStateChangedEventArgs>(_VideoChannel_StateChanged);
}
if (_VideoChannel.CanInvoke(ChannelAction.Start))
{
Console.WriteLine("entered video modality changed123");
_VideoChannel.BeginStart(MediaChannelCallback, _VideoChannel);
}
break;
case ModalityState.OnHold:
break;
case ModalityState.Connecting:
case ModalityState.Forwarding:
break;
case ModalityState.Transferring:
break;
}
}
private void MediaChannelCallback(IAsyncResult ar)
{
((VideoChannel)ar.AsyncState).EndStart(ar);
}
I Think it is because you call _AVModality_ModalityStateChanged_Video in ParticipantAdded event.
that means that you start your video when the person you call (the new participant) joins the conversation. thats why it is getting initiated into audio call and then it's turning into video after end user answers the call.
The solution is to fire a new event : ConversationStateChangedEvent
this is where I did it and works fine :
/// <summary>
/// Handles event raised when New meetNow window change it's state
/// </summary>
private void _NewMeetNowConversation_StateChanged(object sender, ConversationStateChangedEventArgs e)
{
Conversation conference = (Conversation)sender;
switch(e.NewState)
{
case ConversationState.Active:
conference.Modalities[ModalityTypes.AudioVideo].ModalityStateChanged += AVConferenceModalityStateChanged;
conference.ParticipantAdded += ConfParticipantAdded;
break;
case ConversationState.Terminated: //conversation window completely closed
break;
case ConversationState.Inactive:
break;
case ConversationState.Parked:
break;
case ConversationState.Invalid:
break;
}
}

MVVMCross ZXing back button

I have got a problem with back button in MVVMCross when using zxing barcode scanner. Unfortunetly, when I press back button, there is an error: Java.Lang.NullPointerException: Attempt to invoke virtual method 'long android.graphics.Paint.getNativeInstance()' on a null object reference
When I comment metohs scan() weverything is ok.
Someone know what's going wrong?
This is my fragment scann view class:
public class ScannView : MvxFragmentActivity, IBarcodeFragmentOptions
{
protected ScannViewModel MainViewModel
{
get { return ViewModel as ScannViewModel; }
}
public static ZXingScannerFragment scanFragment;
protected override void OnResume()
{
base.OnResume();
try
{
if (scanFragment == null)
{
scanFragment = new ZXingScannerFragment();
SupportFragmentManager.BeginTransaction()
.Replace(Resource.Id.frameScanner, scanFragment)
.Commit();
}
scan();
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
protected override void OnPause()
{
try
{
scanFragment?.StopScanning();
base.OnPause();
}catch(Exception ex)
{
Console.WriteLine(ex);
}
}
protected override void OnRestart()
{
base.OnRestart();
}
public void ToogleFlashLight(bool on)
{
if (scanFragment != null)
scanFragment.SetTorch(on);
}
public void scan()
{
try
{
// var results = await CrossPermissions.Current.RequestPermissionsAsync(Plugin.Permissions.Abstractions.Permission.Camera);
// var status = results[Plugin.Permissions.Abstractions.Permission.Camera];
// if (status == Plugin.Permissions.Abstractions.PermissionStatus.Granted)
// {
var opts = new MobileBarcodeScanningOptions
{
PossibleFormats = new List<ZXing.BarcodeFormat> {
ZXing.BarcodeFormat.QR_CODE
},
CameraResolutionSelector = availableResolutions => {
foreach (var ar in availableResolutions)
{
Console.WriteLine("Resolution: " + ar.Width + "x" + ar.Height);
}
return null;
}
};
scanFragment?.StartScanning(opts,result =>
{
if (result == null || string.IsNullOrEmpty(result.Text))
{
RunOnUiThread(() => Toast.MakeText(this, "Anulowanie skanowanie", ToastLength.Long).Show());
return;
}
MainViewModel.ScannedCode = result.Text; //ChangePropertyToEmpty();
RunOnUiThread(() => Toast.MakeText(this, "Zeskanowano: " + result.Text, ToastLength.Short).Show());
});
// }
}catch(Exception ex)
{
Debug.WriteLine(ex);
}
}
protected override void OnViewModelSet()
{
MobileBarcodeScanner.Initialize(Application);
base.OnViewModelSet();
SetContentView(Resource.Layout.layout_scann);
}
}
And here in my viewmdoel I have simple method to close current viewmodel:
public void ButtonBackClick()
{
Close(this);
}

Resources