xamarin forms android, Font asset not found sans-serif-medium when switching to AppShell - xamarin.forms

I am attempting to code an App in Xamarin Forms.
Upon startup, if the app is logged in the the user will be taken to the main shell with flyouts etc. If they are not logged in, then they will be taken to the signup/login page.
I have the following code in my App.xaml.cs
public App()
{
Instance = this;
InitializeComponent();
AssessStartupPage();
}
public void AssessStartupPage()
{
if (App.LoggedInUser == null)
{
SwitchToSignupPage_OTP();
return;
}
SwitchToShell();
}
public void SwitchToSignupPage_OTP() => SwitchMainView(new SignupPage_OTP());
public void SwitchToShell() => SwitchMainView(new AppShell());
When I attempt to switch to the shell from another Page (by calling App.Instance.SwitchToShell) the following exception is thrown:
Java.Lang.RuntimeException
Font asset not found sans-serif-medium
However if I change the AssessStartupPage() function which is called on startup to this:
public void AssessStartupPage()
{
SwitchToShell();
return;
}
The shell loads correctly at startup. However I need to be able to have the Signup page load at start if the user is not signed in and therefore need to be able to switch to the shell once signup is complete.
I have updated all the xamarin forms and xamarin essential libraries to the latest stable version but nothing seems to help.
The problem doesn't occur when I debug the app in UWP mode.

Related

How to navigate to page when on resume is called in app.xaml.cs for mvvm in xamarin forms app

I have an issue with navigation. When I click home screen button of device and get back to app I get app homescreen instead of pin page. Ideally it should show pin page and its working fine with back button of device.
OnStart() method has navigationasync but the same is not working with OnResume() method.
Do I have to go to each of the Platform project cs file and add the navigation there like for Android OnRestart()/OnResume() method?
If anyone knows the solution please let me know
Most commonly when writing your Xamarin Application with Prism you will have something like:
protected override void OnInitialized()
{
NavigationService.NavigateAsync("SomePage");
}
OnInitialized is called each time the App's ctor is invoked. This is an important consideration here because this means that any time that the native platform tombstones the app in the background or otherwise refreshes the app by calling OnCreate in your MainActivity or FinishedLaunching in your AppDelegate, then OnInitialized will be invoked resetting your App's Navigation stack to SomePage.
You can however override the OnStart/OnResume in PrismApplication and use whatever business logic you need to determine where to navigate and how you might want to restore your application.
public override void OnStart()
{
NavigationService.NavigateAsync("MainPage");
}
public override void OnResume()
{
if(someCondition)
{
NavigationService.NavigateAsync("SomePage");
}
else
{
NavigationService.NavigateAsync("AnotherPage");
}
}

xamarin.forms detect ios app entering foreground from background

I am creating app in Xamarin.Forms shared proeject. I want to detect app when it comes from background
currently, I have implemented OnActivated method in AppDelegate but this method is also called when we open control center in iphone. I want my app to reconnect with my server when app comes to foreground from background and show message accordingly but this message is also shown when I swipe up and open control center.
In native Xamarin.iOS app, there is a method WillEnterForegroundNotification but this method is not available here.
Is there any method that's called only if app comes from background ?
in App.xaml.cs
protected override void OnResume()
In native Xamarin.iOS app, there is a method
WillEnterForegroundNotification but this method is not available here.
You can access WillEnterForegroundNotification method in Xamarin.forms project, just override it in AppDelegate.cs:
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
public override void WillEnterForeground(UIApplication uiApplication)
{
//handle your event here
base.WillEnterForeground(uiApplication);
}
}

Xamarin iOS NFC Session is invalidated unexpectedly

Have a Xamarin forms project and trying to hook in NFC reading to the app. Currently plumbing in the iOS native side of things. I've setup all the provisioning and options on the apple portal side of things and i've added the following to the entitlements:
<dict>
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>NDEF</string>
</array>
</dict>
Also added to the info.plist:
<key>NFCReaderUsageDescription</key>
<string>NFC tag to read NDEF messages into the application</string>
The code i've got for my native dependency for iOS is as follows:
[assembly: Dependency(typeof(RFIDScannerHelper))]
namespace MyProject.Mobile.Platform.iOS
{
public class RFIDScannerHelper : IRFIDScannerHelper
{
public bool hasRFID()
{
return true;
}
NFCNdefReaderSession Session;
public void ScanRFID(Action<string> act, VisualElement el)
{
NFChecker nfchecker = new NFChecker();
Session = new NFCNdefReaderSession(nfchecker, null, false);
Session?.BeginSession();
}
}
public class NFChecker : NSObject, INFCNdefReaderSessionDelegate
{
public Action<string> nfcFoundAction;
public void DidDetect(NFCNdefReaderSession session, NFCNdefMessage[] messages)
{
foreach (NFCNdefMessage msg in messages)
{
if (msg.Records.Count() > 0)
{
nfcFoundAction.Invoke(new NSString(msg.Records[0].Payload, NSStringEncoding.UTF8));
}
}
}
public void DidInvalidate(NFCNdefReaderSession session, NSError error)
{
var readerError = (NFCReaderError)(long)error.Code;
if (readerError != NFCReaderError.ReaderSessionInvalidationErrorFirstNDEFTagRead &&
readerError != NFCReaderError.ReaderSessionInvalidationErrorUserCanceled)
{
}
}
}
}
When this runs it all seems to fire correctly but on start of session it goes straight to the DidInvalidate method in the ReaderDelegate and the error says "Session is invalidated unexpectedly".
Can anyone tell me what I could be missing out?
UPDATE
I've also tried the xamarin provided sample here. But I also receive the exact same error "Session is invalidated unexpectedly". I've mucked around with our provisioning but no combination changes this error. Has anyone even got the xamarin sample to work?
#matt, it's a Visual Studio 2019 error. You should select the Entitlements.plist in your project settings, but you are not able because the "entry" where you should insert the path is always disabled. I have reported the problem
https://developercommunity.visualstudio.com/content/problem/752711/xamarinios-i-cant-set-entitlements.html

How to setup PUB/SUB NetMQ in Xamarin Forms

I have a Windows Services running as a Publisher and I am trying to setup Xamarin Forms as the Subscriber. The code below works just fine in a Console App or LinqPad, but when copied and pasted into Xamarin Forms, the SubscriberSocket just does not respond to messages from the server.
Do you know how to wire this up?
I am using NetMQ v 4.0.0.1
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
Task.Run(() => StartPubSubSocketSubscriber());
}
private void StartPubSubSocketSubscriber()
{
string topic = "TopicA";
using (var subSocket = new SubscriberSocket())
{
subSocket.Options.ReceiveHighWatermark = 1000;
subSocket.Connect("tcp://192.168.30.120:5556");
subSocket.Subscribe(topic);
while (true)
{
string messageTopicReceived = subSocket.ReceiveFrameString();
string messageReceived = subSocket.ReceiveFrameString();
Device.BeginInvokeOnMainThread(() =>
{
label.Text = messageReceived;
});
}
}
}
}
I also tried starting the background thread with Task.Factory.StartNew(() => StartPubSubSocketSubscriber(), TaskCreationOptions.LongRunning); but it is just as unresponsive to messages from the publisher.
Thank you.
PS.: removed subSocket.Connect("tcp://localhost:5556");
The fix for this was a 2 step process:
The SubscriberSocket was incorrectly pointing to localhost. An understandable mistake since the emulator runs on the same machine as the server application. Make sure the Subscriber has the explicit IP address when running on a virtual environment or another device.
The issue with SubscriberSocket not responding was actually on a server. I had set it up with pubSocket.Bind("tcp://localhost:5556");, once I changed it to pubSocket.Bind("tcp://*:5556"); the SubscriberSocket started responding. This is an error in documentation.
The hint to the solution came from the NetMQ github issue tracking:
https://github.com/zeromq/netmq/issues/747

JavaFx Turn-based Multiplayer Application with Google Service

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.

Resources