JavaFx Turn-based Multiplayer Application with Google Service - javafx

Now I am using Gluon plugin and it is very helpful to start working with JavaFXPorts. I have my application ready and I can use it on computers and phones. I tested on phone with system android. Application is working good but only with my server.
I take care of the different resolutions and I think that it is good for now.
I want to have Turn-based Multiplayer Application but I have still big problem with using Google Play Service. Tutorial which show how to use this services for turn-based multiplayer application is written in pure android and use Activity. My question is maybe very simple but If I have my application view from "fxml" how to use it as an tutorial Activity?
I want to do auto-matching for my application and next I want override method takeTurn() to suit it to my application.
For example, how can I change thing like that (code below) to application in JavaFX?
I must use google services from my JavaFX(src/main/java folder) class in addition AndroidPlatformProvider.java and all methods must be in src/android/java folder. I know that I must use PlatformService and PlatformProvider. I did it as in the examples: HelloPlatform and SMSTracker .
I use methods from my interface PlatformProvider but application still crashes. :(
I only use Provider from my code of JavaFX and I don't have android Activity. I don't know how to use these method without Activity or View:
- public void onActivityResult(int request, int response, Intent data)
- public void playTurn(View view)
Can I call from google service methods to methods from my controller for view (fxml).
I don't know how these methods should working with JavaFX.
public class TbmpGameActivity extends Activity {
...
#Override
public void onActivityResult(int request, int response, Intent data) {
super.onActivityResult(request, response, data);
...
if (request == RC_SELECT_PLAYERS) {
if (response != Activity.RESULT_OK) {
// user canceled
return;
}
// Get the invitee list.
final ArrayList<String> invitees =
data.getStringArrayListExtra(Games.EXTRA_PLAYER_IDS);
// Get auto-match criteria.
Bundle autoMatchCriteria = null;
int minAutoMatchPlayers = data.getIntExtra(
Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);
int maxAutoMatchPlayers = data.getIntExtra(
Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);
if (minAutoMatchPlayers > 0) {
autoMatchCriteria = RoomConfig.createAutoMatchCriteria(
minAutoMatchPlayers, maxAutoMatchPlayers, 0);
} else {
autoMatchCriteria = null;
}
TurnBasedMatchConfig tbmc = TurnBasedMatchConfig.builder()
.addInvitedPlayers(invitees)
.setAutoMatchCriteria(autoMatchCriteria)
.build();
// Create and start the match.
Games.TurnBasedMultiplayer
.createMatch(mGoogleApiClient, tbmc)
.setResultCallback(new MatchInitiatedCallback());
}
}
}
or something like that:
// Call this method when a player has completed his turn and wants to
// go onto the next player, which may be himself.
public void playTurn(View view) {
// Get the next participant in the game-defined way, possibly round-robin.
String nextParticipantId = getNextParticipantId();
// Get the updated state. In this example, we simply retrieve a
// text string from the view. In your game, there may be more
// complicated state.
mTurnData = mDataView.getText().toString();
// At this point, you might want to show a waiting dialog so that
// the current player does not try to submit turn actions twice.
showSpinner();
// Invoke the next turn. We are converting our data to a byte array.
Games.TurnBasedMultiplayer
.takeTurn(mGoogleApiClient, mMatch.getMatchId(),
mTurnData.getBytes(Charset.forName("UTF-16")),
nextParticipantId)
.setResultCallback(this);
}

Latest version of the jfxmobile plugin (1.0.3) includes recent changes in Dalvik SDK that contains the port of JavaFX 8 to android.
In FXActivity class, it has been added a very convenient method to listen to results of intents: setOnActivityResultHandler().
This means you shouldn't add new activities to your app, and only use FXActivity. You should add an Intent to it, and set a proper result handler to the FXActivity.
Have a look at this recent post at Gluon's site. It explains how to access native services, based on the case of taking a picture with the device's camera, and waiting to get the result of it to resume the app.
Basically, this is what it is required in this case:
public void takePicture() {
// create intent
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
...
// Add result handler
FXActivity.getInstance().setOnActivityResultHandler((requestCode, resultCode, data) -> {
if (requestCode == TAKE_PICTURE && resultCode == RESULT_OK) {
...
}
});
// launch activity
FXActivity.getInstance().startActivityForResult(intent, TAKE_PICTURE);
}
Try this approach with your app.

Related

Where do I place Firebase Check and Fix Dependencies code in Unity?

I wanted to use Firebase in my Unity game so one of the steps was to add the following code, but the place into which the code should be added wasn't specified. Any help?
Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
var dependencyStatus = task.Result;
if (dependencyStatus == Firebase.DependencyStatus.Available) {
// Create and hold a reference to your FirebaseApp,
// where app is a Firebase.FirebaseApp property of your application class.
app = Firebase.FirebaseApp.DefaultInstance;
// Set a flag here to indicate whether Firebase is ready to use by your app.
} else {
UnityEngine.Debug.LogError(System.String.Format(
"Could not resolve all Firebase dependencies: {0}", dependencyStatus));
// Firebase Unity SDK is not safe to use here.
}
});
(This is the link to the instructions on Firebase)
https://firebase.google.com/docs/unity/setup?authuser=0#confirm-google-play-version
The best answer I can give is "before you do anything else" in Unity.
In a normal application, you'd have something like a main api entry point (application:didFinishLaunchingWithOptions in iOS, Activity.onCreate in Android, or literally void main(int,char**) in a typical C/C++ desktop application). But in Unity, you don't have any sort of "run this before everything else" logic. Whichever scene is first is up to you and subject to change, and scripts execute roughly in parallel (in an order that's best considered random but technically can be ordered).
Here are the patterns I've either used or have thought about using and a few associated pros and cons:
[Recommended for beginners and small projects] In my videos, I typically recommend having a "loading" or "setup" scene. In that scene I place a FirebaseInit script that will initialize Firebase and raise an event when it's done. I can then either collect a bunch of initialization functionality (say downloading asset bundles or doing some initial setup processing) or just jump immediately into my main scene. Most of the time this will resolve to a no-op (on Android play services is up to date), so you can even shove it in the main menu if you're careful:
using System;
using Firebase;
using Firebase.Extensions;
using UnityEngine;
using UnityEngine.Events;
public class FirebaseInit : MonoBehaviour
{
public UnityEvent OnInitialized = new UnityEvent();
public InitializationFailedEvent OnInitializationFailed = new InitializationFailedEvent();
void Start()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
{
if (task.Exception != null)
{
OnInitializationFailed.Invoke(task.Exception);
}
else
{
OnInitialized.Invoke();
}
});
}
[Serializable]
public class InitializationFailedEvent : UnityEvent<Exception>
{
}
}
I'm not a big proponent of dependency injection (as in I typically don't use DI frameworks, but I do tend to use [SerializedField]s as a pseudo-DI system), so I don't have a good example to share. You can use ZenJect to create and inject the Firebase singletons to anything that needs them. The biggest issue you run into is that you have to await the dependencies to be initialized, which is possible but I just haven't gone through the steps of doing it in a sample project. The benefit is that you only need to express "I depend on Firebase", and ZenJect will take care of the rest (just avoid the DefaultInstance functions in this case).
In more complex projects, I'll tend to wrap Firebase in a Coroutine (or an async task, but I prefer coroutines in Unity). So I'll have a Coroutine that will wait for check and fix dependencies to complete and return an instance of Realtime Database when it finishes (and intelligent logic to skip the waiting if not necessary). Again you have to avoid DefaultInstance outside of your management script, and every use of Firebase becomes a coroutine, but you can be sure that you always await on construction. Here is one example focusing on Realtime Database (I'm stripping unnecessary code to make it fit in a SO answer), and I'll reiterate that this is a lot of overhead for a small project:
public class FirebaseBehaviour : MonoBehaviour
{
private IEnumerator _setupFirebase;
private DatabaseReference _databaseReference;
void Awake()
{
// everything depends on firebase being setup. Do this first.
_setupFirebase = SetupFirebase();
StartCoroutine(_setupFirebase);
}
private IEnumerator SetupFirebase()
{
// we need to fix dependencies on Android
if (Application.platform == RuntimePlatform.Android && !Application.isEditor)
{
Debug.Log("Checking dependencies on Android");
var checkDependencies = new TaskYieldInstruction<DependencyStatus>(FirebaseApp.CheckDependenciesAsync());
yield return checkDependencies;
Debug.Log($"Check Dependencies: {checkDependencies.Result}");
}
_databaseReference = FirebaseDatabase.DefaultInstance.RootReference;
}
/// <summary>
/// Safely gets a database reference at the given path
/// </summary>
/// <param name="path">The path at which to get a reference</param>
/// <returns>A yield instruction that can be yielded in a coroutine</returns>
public GetDatabaseReferenceYieldInstruction GetDatabaseReference(string path)
{
return new GetDatabaseReferenceYieldInstruction(path, _setupFirebase);
}
/// <summary>
/// Asynchronously gets a database reference at the given path after a predicate executes
/// </summary>
public class GetDatabaseReferenceYieldInstruction : IEnumerator
{
private IEnumerator _predicate;
private readonly string _path;
public DatabaseReference Root { get; private set; }
public GetDatabaseReferenceYieldInstruction(string path, IEnumerator predicate)
{
_path = path;
_predicate = predicate;
}
public bool MoveNext()
{
if (_predicate != null)
{
if (_predicate.MoveNext())
{
return true;
}
_predicate = null;
// TODO: this is a cross cutting concern to inject
Root = FirebaseDatabase.DefaultInstance.RootReference.Child(_path);
}
return false;
}
public void Reset()
{
}
public object Current => Root;
}
}
Which you can use like this:
[SerializeField] private FirebaseSingleton _firebaseSingleton;
public void Awake()
{
_firebase = _firebaseSingleton.Instance;
_getDatabase = _firebase.GetDatabaseReference(DatabaseName);
}
private IEnumerator RegisterForEvents()
{
yield return _getDatabase;
_getPigDatabase.Root.ValueChanged += HandlePigValuesChanged;
}
With Unity's new DOTS system, I've been flirting with the idea of moving Unity's initialization into the OnCreate function for a system. Because you have a clean entrypoint, you'd be able to block Firebase functionality until it comes online, and you could control Firebase by injecting specific entities into the world with custom Firebase-specific components on it. I don't have a good example yet, although it's on my project backlog.

How to open the app privacy settings from xamarin forms

Trying to open my app settings , so the user can see the permissions my app is required.
cant find anything with a similar example.
*
if (item.Name == "Privacy preferences")
{
switch (Device.RuntimePlatform)
{
case Device.iOS:
Device.OpenUri(
new Uri(FORGOT WHAT TO PUT IN HERE .. APP/SETTINGS?);
break;
case Device.Android:
Device.OpenUri(
new Uri();
break;
}
*
Fairly simple, you will have to create platform specific implementations.
The Interface
public interface ISettingsHelper
{
void OpenAppSettings();
}
iOS
public void OpenAppSettings()
{
var url = new NSUrl($"app-settings:{app_bundle_id}");
UIApplication.SharedApplication.OpenUrl(url);
}
Android
public void OpenAppSettings()
{
var intent = new Intent(Android.Provider.Settings.ActionApplicationDetailsSettings);
intent.AddFlags(ActivityFlags.NewTask);
var uri = Android.Net.Uri.FromParts("package", package_name, null);
intent.SetData(uri);
Application.Context.StartActivity(intent);
}
From Xamarin.Forms project you could simple call OpenAppSettings();.
P.S.: Please keep in mind that this solution requires tweaking if you would like it to work on older devices.
Try Device.OpenUri(new Uri("app-settings:"));
If this doesn't work (I think it has a while ago), you probably have to do this in your platform specific parts and use e.g. the dependency service. For IOS then use UIApplication.SharedApplication.OpenUrl(new NSUrl("app-settings:"));
Edit: #EvZ's answer is the one with platform specific code and the abstraction, if you also need UWP you can call
await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-location"));

Re-instantiate a singleton with Prism in Xamarin Forms

How can I dispose and re-instantiate a singleton with Prism/DryIoC in Xamarin Forms?
I'm working with Azure Mobile Apps for offline data. Occasionally, I need to delete the local sqlite database and re-initialize it. Unfortunately the MobileServiceClient occasionally holds the db connection open and there's no method exposed to close it. The suggested solution (https://github.com/Azure/azure-mobile-apps-net-client/issues/379) is to dispose of MobileServiceClient. Only problem is that is registered with DryIoC as a singleton.
I'm not overly familiar with DryIoC, or Prism and Forms for that matter... But for the life of me, I can't see a way to do this.
I did cook up a pretty elaborate scheme that almost worked.
In my ViewModel method, when I needed the db freed up, I fired off an event -
_eventAggregator.GetEvent<RegisterDatabaseEvent>().Publish(false);
Then in App.xaml.cs, I wired up a listener and a handler like so -
_eventAggregator.GetEvent<RegisterDatabaseEvent>().Subscribe(OnRegisterDatabaseEventPublished);
private void OnRegisterDatabaseEventPublished()
{
Container.GetContainer().Unregister<IAppMobileClient>();
Container.GetContainer().Unregister<IMobileServiceClient>();
Container.GetContainer().Register<IMobileServiceClient, AppMobileClient>(new SingletonReuse());
Container.GetContainer().Register<IAppMobileClient, AppMobileClient>(new SingletonReuse());
_eventAggregator.GetEvent<RegisterDatabaseCompletedEvent>().Publish(register);
}
Lastly, back in the ViewModel constructor, I had a final listener that handled the event coming back from App.xaml and finished processing.
_eventAggregator.GetEvent<RegisterDatabaseCompletedEvent>().Subscribe(OnRegisterDatabaseCompletedEventPublished);
So the amazing thing is that this worked. The database was able to be deleted and all was good. But then I navigated to a different page and BOOM. DryIoC said it couldn't wire up the ViewModel for that page. I assume the unregister/register jacked up DryIoC for all injection... So how can I accomplish what needs to be done?
FINAL SOLUTION
Thanks so much to dadhi for taking the time to help. You are certainly a class act and I'm now considering using DryIoC elsewhere.
For anyone who stumbles on this, I'm posting the final solution below. I'll be as verbose as I can to avoid any confusion.
First, in my App.xaml.cs, I added a method for registering my database.
public void RegisterDatabase(IContainer container)
{
container.RegisterMany<AppMobileClient>(Reuse.Singleton,
setup: Setup.With(asResolutionCall: true),
ifAlreadyRegistered: IfAlreadyRegistered.Replace,
serviceTypeCondition: type =>
type == typeof(IMobileServiceClient) || type == typeof(IAppMobileClient));
}
I simply add a call to that method in RegisterTypes in place of registering the types in there directly.
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.GetContainer().Rules.WithoutEagerCachingSingletonForFasterAccess();
...
RegisterDatabase(containerRegistry.GetContainer());
...
}
Note also the added rule for eager caching, per dadhi.
Later on when I need to release the database in the ViewModel... I kick things off by resetting my local db variable and sending an event to App.xaml.cs
_client = null;
_eventAggregator.GetEvent<RegisterDatabaseEvent>().Publish(true);
In App.xaml.cs, I have subscribed to that event and tied it to the following method.
private void OnRegisterDatabaseEventPublished()
{
RegisterDatabase(Container.GetContainer());
_eventAggregator.GetEvent<RegisterDatabaseCompletedEvent>().Publish(register);
}
Here I just call RegisterMany again, exactly the same as I do when the app starts up. No need to unregister anything. With the setup and ifAlreadyRegistered arguments (thanks, dadhi!), DryIoC allows the object to be replaced. Then I raise an event back to the VM letting it know the database has been released.
Finally, back in the ViewModel, I'm listening for the completed event. The handler for that event updates the local copy of the object like so.
_client = ((PrismApplication)App.Current).Container.Resolve<IAppMobileClient>();
And then I can work with the new object, as needed. This is key. Without setting _client to null above and resolving it again here, I actually ended up with 2 copies of the object and calls to methods were being hit 2x.
Hope that helps someone else looking to release their Azure Mobile Apps database!
I am not sure how exactly XF handles these things.
But in DryIoc in order for service to be fully deleted or replaced it need to be registered with setup: Setup.With(asResolutionCall: true). Read here for more details: https://bitbucket.org/dadhi/dryioc/wiki/UnregisterAndResolutionCache#markdown-header-unregister-and-resolution-cache
Update
Here are two options and considerations that work in pure DryIoc and may not work XF. But it probably may help with solution.
public class Foo
{
public IBar Bar { get; private set; }
public Foo(IBar bar) { Bar = bar; }
}
public interface IBar {}
public class Bar : IBar {}
public class Bar2 : IBar { }
[Test]
public void Replace_singleton_dependency_with_asResolutionCall()
{
var c = new Container(rules => rules.WithoutEagerCachingSingletonForFasterAccess());
c.Register<Foo>();
//c.Register<Foo>(Reuse.Singleton); // !!! If the consumer of replaced dependency is singleton, it won't work
// cause the consumer singleton should be replaced too
c.Register<IBar, Bar>(Reuse.Singleton,
setup: Setup.With(asResolutionCall: true)); // required
var foo = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar>(foo.Bar);
c.Register<IBar, Bar2>(Reuse.Singleton,
setup: Setup.With(asResolutionCall: true), // required
ifAlreadyRegistered: IfAlreadyRegistered.Replace); // required
var foo2 = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar2>(foo2.Bar);
}
[Test]
public void Replace_singleton_dependency_with_UseInstance()
{
var c = new Container();
c.Register<Foo>();
//c.Register<Foo>(Reuse.Singleton); // !!! If the consumer of replaced dependency is singleton, it won't work
// cause the consumer singleton should be replaced too
c.UseInstance<IBar>(new Bar());
var foo = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar>(foo.Bar);
c.UseInstance<IBar>(new Bar2());
var foo2 = c.Resolve<Foo>();
Assert.IsInstanceOf<Bar2>(foo2.Bar);
}

Filtering SignalR requests from ApplicationInsight

I've configured Application Insights on my web application however the telemetry is full of 'failed' requests from SingalR which makes spotting genuine issues difficult (see screenshot below). I want to filter out all SignalR requests and not send them to AI.
I've created a Telemetry Processor (see code below based on this example from MS) and registered it in the ApplicationInsights.config file, this works as expected when debugging locally and prevents any SignalR events from being sent however it doesn't seem to have any effect once the web application published and running in IIS.
public class SignalRFilter : ITelemetryProcessor
{
private ITelemetryProcessor Next { get; set; }
public SignalRFilter(ITelemetryProcessor next)
{
this.Next = next;
}
public void Process(ITelemetry item)
{
if (!OKtoSend(item))
return;
else
this.Next.Process(item);
}
private bool OKtoSend(ITelemetry item)
{
if (item is RequestTelemetry && ((RequestTelemetry)item).Url.AbsolutePath.Contains("signalr"))
return false;
else
return true;
}
}
Any suggestions?
You're looking at these requests in Live Metrics Stream. For this particular view you can filter them out on demand. Feature is available in latest 2.4-beta (the stable version should be released soon). In this case you can click on Filter button and add proper filters to every stream. Similar behavior exists for charts:
Have you checked whether you see /signair/start in you Application Insights Analytics? It might be the case that you did filter them out successfully and they only show up in Live view.

ASP.net how to long polling with PokeIn?

I want to make a service that notify the user in case there are some new messages sent to him. Thus I want to use some Comet framework that provide the server push ability. So I have looked into PokeIn.
Just wondering a thing. I have checked on the samples that they have on the website. None of them look into the database to retrieve new entries if there are some. But it is just a matter of modification to it I guess.
One of the sample implement this long polling by using a sleep on the server side. So if I use the same approach I can check the database, if there are any new entries, every 5 seconds. However this approach doesn't seem to be much different from when using polling on the client side with javascript.
This part is from a sample. As can be seen they put a sleep there for to update current time for everybody.
static void UpdateClients()
{
while (true)
{
//.. code to check database
if (CometWorker.ActiveClientCount > 0)
{
CometWorker.SendToAll(JSON.Method("UpdateTime", DateTime.Now));
}
Thread.Sleep(500);
}
}
So I wonder is this how I should implement the message notifier? It seems that the above approach is still going to push a huge load demand on the server side. The message notifier is intend to work same way as the one found Facebook.
You shouldn't implement this way, that sample is only implemented like that because the keep PokeIn related part is clear. You should implement SQL part as mentioned http://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events
in order to track changes on database.
So, when you have something to send, call one of the PokeIn methods for the client side delivery. I don't know, how much your application is time critical because in addition to reverse ajax, PokeIn's internal websocket feature is very easy to activate and delivers messages to client quite fast.
You can do this with database as #Zuuum said, but I implemented it in a different way.
I'm using ASP.NET MVC with PokeIn and EF in a Windows Azure environment:
I have domain events similar to this approach: Strengthening your domain: Domain Events
When someone invokes an action, that's a Unit of Work
If that UOW succeeds then I raise a domain event (e.g. ChatMessageSent)
I have subscribers for these domain events so they can receive the event and forward the message to the PokeIn listeners
I use this pattern for all my real-time needs on my game site (making moves, actions etc in a game), I don't want to advertise it here, you can find it through me if you want.
I always use this pattern as a duplex communication solution so everybody gets their update via PokeIn, even the user who invoked the action so every client will behave the same. So when someone calls an action it won't return anything except the success signal.
The next examples are won't work because they are only snippets to demonstrate the flow
Here is an action snippet from my code:
[HttpPost]
[UnitOfWork]
[RestrictToAjax]
[ValidateAntiForgeryToken]
public JsonResult Post(SendMessageViewModel msg)
{
if (ModelState.IsValid)
{
var chatMessage = new ChatMessage
{
ContainerType = msg.ContainerType,
ContainerID = msg.ContainerID,
Message = _xssEncoder.Encode(msg.Message),
User = _profileService.CurrentUser
};
_chatRepository.AddMessage(chatMessage);
OnSuccessfulUoW = () => EventBroker.Current.Send(this, new ChatMessageSentPayload(chatMessage));
}
return Json(Constants.AjaxOk);
}
And the (simplified) EventBroker implementation:
public class UnityEventBroker : EventBroker
{
private readonly IUnityContainer _container;
public UnityEventBroker(IUnityContainer container)
{
_container = container;
}
public override void Send<TPayload>(object sender, TPayload payload)
{
var subscribers = _container.ResolveAll<IEventSubscriber<TPayload>>();
if (subscribers == null) return;
foreach (var subscriber in subscribers)
{
subscriber.Receive(sender, payload);
}
}
}
And the even more simplified subscriber:
public class ChatMessageSentSubscriber : IEventSubscriber<ChatMessageSentPayload>
{
public void Receive(object sender, ChatMessageSentPayload payload)
{
var message = payload.Message;
var content = SiteContent.Global;
var clients = Client.GetClients(c => c.ContentID == message.ContainerID && c.Content == content)
.Select(c => c.ClientID)
.ToArray();
var dto = ObjectMapper.Current.Map<ChatMessage, ChatMessageSentDto>(message);
var json = PokeIn.JSON.Method("pokein", dto);
CometWorker.SendToClients(clients, json);
}
}

Resources