Xamarin Forms Webview stopped working - UWP App - xamarin.forms

I've a uwp app that requires login at start up through an url, for which I've been using Webview control. It has been doing ok until recently but suddenly stopped working without changing anything related to the login sequence. I've been using VS Community 2022 but the app was built in VS Community 2019, .NET Standard 2, Prism 7.2
Here's my xaml:
<ScrollView>
<WebView x:Name="webView"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
Source="{Binding LoginURL}"/>
</ScrollView>
Code in the view model (extracted relevant portions):
private string _loginURL;
public string LoginURL
{
get => _loginURL;
set => SetProperty(ref _loginURL, value);
}
private string _redirectURL;
public string RedirectURL
{
get => _redirectURL;
set => SetProperty(ref _redirectURL, value);
}
private void StartLogin(bool userInitialized)
{
try
{
if (userInitialized)
{
RedirectURL = _loginService.RedirectURL;
LoginURL = _loginService.LoginURL;
Debug.WriteLine("RedirectURL: " + RedirectURL);
Debug.WriteLine("LoginURL: " + LoginURL);
}
}
catch (Exception e)
{
_logService.LogError(e.Message);
}
}
The code behind the user control with webview:
public LoginView()
{
InitializeComponent();
webView.Navigating += CatchRedirectURL;
}
private async void CatchRedirectURL(object sender, WebNavigatingEventArgs e)
{
Debug.WriteLine("e.Url: " + e.Url);
Debug.WriteLine("webView.Source: " + (webView.Source as UrlWebViewSource).Url);
var vm = BindingContext as LoginViewModel;
if (e.Url.Contains(vm.RedirectURL))
{
var webViewSender = (WebView)sender;
e.Cancel = true; // prevent further browsing
var requestToken = ExtractRequestToken(e.Url);
var user = await vm.GenerateSessionAsync(requestToken);
var htmlSource = new HtmlWebViewSource();
if (user.AccessToken == null)
{
string msg = "Login Unsuccessful";
htmlSource.Html = #"<html><body>
<h1 style=""text-align:center;"">" + msg + #"</h1>
<p style=""text-align:center;"">oops...something went wrong.</p>
</body>
</html>";
}
else
{
string msg = "Hello, " + user.UserShortName + "!";
htmlSource.Html = #"<html><body>
<h1 style=""text-align:center;"">" + msg + #"</h1>
<p style=""text-align:center;"">Welcome</p>
</body>
</html>";
}
webViewSender.Source = htmlSource;
}
}
Immediately after loading the control, the StartLogin method is called from the view model. The debug output is here:
All the above urls are valid and if I copy and paste them in a browser, they work fine. But in the app the webview control is just plain blank despite the source property populated with correct url. I'm totally clueless as to what's going wrong here, especially when it was working so beautifully a few days ago.
Thanks in advance.

Related

HERE sdk Lite edition for android autosuggest return PARSING_ERROR

I'm a user HERE sdk Lite edition for android, mainly using the autosuggest search place feature. My application is already running and functioning properly. To this day problems arise so that they don't work. After I checked it turns out that in the SuggestCallback class section it return PARSING_ERROR. Please help
here is SuggestCallback class:
private final SuggestCallback autosuggestCallback = new SuggestCallback() {
#Override
public void onSuggestCompleted(#Nullable SearchError searchError, #Nullable List<Suggestion> list) {
if (searchError != null) {
//Log.d(LOG_TAG, "Autosuggest Error: " + searchError.name());
Toast.makeText(HereMapsActivity.this, "" + searchError.name(), Toast.LENGTH_SHORT).show();
return;
}
for (Suggestion autosuggestResult : list) {
String addressText = "Not a place.";
Place place = autosuggestResult.getPlace();
if (place != null) {
addressText = place.getAddress().addressText;
datatmp.add(new DataListLocation(
addressText,
place.getCoordinates().latitude,
place.getCoordinates().longitude
));
}else{
datatmp = new ArrayList<>();
}
adapterListLocation = new AdapterListLocation(HereMapsActivity.this, datatmp);
lstview.setAdapter(adapterListLocation);
}
progressDialog.dismiss();
}
};

receive message from android beam in xamarin forms

I'm develop cross-platform mobile application that use NFC. I already check the xamarin android beam sample here. Now i'm trying implement the same sample using xamarin forms so i'm using dependency service to call the function from android project.
I already create Ndef message and send function:
using System;
using System.Text;
using Android.App;
using MyApp.Droid;
using Android.Nfc;
using Xamarin.Forms;
[assembly: Dependency(typeof(PhoneBeam))]
namespace MyApp.Droid
{
public class PhoneBeam : Activity, NfcAdapter.ICreateNdefMessageCallback, NfcAdapter.IOnNdefPushCompleteCallback, iBeam
{
private NfcAdapter nfcAdapter;
public void Beam()
{
nfcAdapter = NfcAdapter.GetDefaultAdapter(MainActivity.Instance);
nfcAdapter.SetNdefPushMessageCallback(this, MainActivity.Instance);
nfcAdapter.SetOnNdefPushCompleteCallback(this, MainActivity.Instance);
}
public NdefMessage CreateNdefMessage(NfcEvent evt)
{
DateTime time = DateTime.Now;
var text = ("Beam me up!\n\n" + "Beam : " +
time.ToString("HH:mm:ss"));
NdefMessage msg = new NdefMessage(
new NdefRecord[]{ CreateMimeRecord (
"application/com.companyname.MyApp",
Encoding.UTF8.GetBytes (text)) });
return msg;
}
public NdefRecord CreateMimeRecord(String mimeType, byte[] payload)
{
byte[] mimeBytes = Encoding.UTF8.GetBytes(mimeType);
NdefRecord mimeRecord = new NdefRecord(
NdefRecord.TnfMimeMedia, mimeBytes, new byte[0], payload);
return mimeRecord;
}
public void OnNdefPushComplete(NfcEvent e){}
}
}
However, I really don't know how to receive a message. In android beam sample, they implement it in mainactivity. Here's sample:
protected override void OnResume ()
{
base.OnResume ();
if (NfcAdapter.ActionNdefDiscovered == Intent.Action) {
ProcessIntent (Intent);
}
}
void ProcessIntent (Intent intent)
{
IParcelable [] rawMsgs = intent.GetParcelableArrayExtra (
NfcAdapter.ExtraNdefMessages);
NdefMessage msg = (NdefMessage) rawMsgs [0];
mInfoText.Text = Encoding.UTF8.GetString (msg.GetRecords () [0].GetPayload ());
}
So i want to implement in class file so i can use dependencyService. Is there a way to implement this?
Edit: I did the send function:
public NdefMessage CreateNdefMessage (NfcEvent evt)
{
DateTime time = DateTime.Now;
var text = ("Beam me up!\n\n" +
"Beam Time: " + time.ToString ("HH:mm:ss"));
NdefMessage msg = new NdefMessage (
new NdefRecord[] { CreateMimeRecord (
"application/com.companyname.MyApp", Encoding.UTF8.GetBytes (text))
});
return msg;
}
But it return as "NEW TAG COLLECTED: application/com.companyname.MyApp". I want to resume MyApp and show the message. But it didn't.

xamarin forms ios camera crash issue

I have a xamarin forms cross platform application. In that application i am using a xamarin forms dependency service to take photo from iOS and android device on native platform. Android camera working fine but iOS camera giving error and app crash suddenly. I log and trace issues of iOS camera as following.
** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller .'
Following are my iOS native code used to take photo and it returns photo stream as result.I call this method or service from my shared xamarin form project using dependency service.
public Task<CameraResult> TakePictureAsync(bool cameraFlag) { var tcs = new TaskCompletionSource<CameraResult>();
Camera.TakePicture(UIApplication.SharedApplication.KeyWindow.RootViewController, (imagePickerResult) =>
{
if (imagePickerResult == null)
{
tcs.TrySetResult(null);
return;
}
var photo = imagePickerResult.ValueForKey(new NSString("UIImagePickerControllerOriginalImage")) as UIImage;
// You can get photo meta data with using the following
// var meta = obj.ValueForKey(new NSString("UIImagePickerControllerMediaMetadata")) as NSDictionary;
var documentsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string imageName = Settings.AppuserUserId + "_" + Guid.NewGuid();
string jpgFilename = Path.Combine(documentsDirectory, imageName + ".jpg");
NSData imgData = photo.AsJPEG();
NSError err = null;
if (imgData.Save(jpgFilename, false, out err))
{
CameraRes
ult result = new CameraResult();
result.Picture = ImageSource.FromStream(imgData.AsStream);
result.FilePath = jpgFilename;
tcs.TrySetResult(result);
}
else
{
tcs.TrySetException(new Exception(err.LocalizedDescription));
} });
return tcs.Task; }
void OnImagePickerFinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs args)
{
UIImage image = args.EditedImage ?? args.OriginalImage;
if (image != null)
{
// Convert UIImage to .NET Stream object
CameraResult result = new CameraResult();
NSData data = image.AsJPEG();
result.Picture = ImageSource.FromStream(data.AsStream);
taskCompletionSource.SetResult(result);
}
else
{
taskCompletionSource.SetResult(null);
}
imagePicker.DismissModalViewController(true);
}
void OnImagePickerCancelled(object sender, EventArgs args)
{
taskCompletionSource.SetResult(null);
imagePicker.DismissModalViewController(true);
}
}
Please share any solution for this issue and error.

Xamarin.Forms and Plugin.Media: after about 20 photos something crashes

I have a problem with Xamarin.Forms ver. 2.3.4.224 and Plugin.Media ver. 2.6.2. The problem occurs after taking about 20 photos (depends from the device): basically the app crashes without any apparently reason.
If you want to replicate the error, I created a test project for you on GitHub. With my iPad Air or iPad Pro after about 30 photos (video iPad Air - iPad Pro). All devices are iOS ver. 10.3.1 and they have enough space to storage photos.
The app is very simple: you have two buttons one for taking a picture and the other one to pick a photo. If you take photos one after another, after about 20 (32 in an iPad Air) the app crashes. I'm just take photos with the Plugin.Media nothing more.
Any ideas are welcome.
Update
In my project I had a reference to Refractored.MvvmHelpers and I noticed if I remove it, I can take more pictures. I created my BaseViewModel with INotifyPropertyChanged and I noticed I can take more photos.
I created then a new project (you can find it on GitHub under cameratesteasy) without MVVM and there is just the code to take a photo like:
public partial class cameratesteasyPage : ContentPage
{
int count = 0;
public cameratesteasyPage()
{
InitializeComponent();
CrossMedia.Current.Initialize();
}
void UpdateCount()
{
count++;
CountLabel.Text = $"{count} times";
}
async void StartCameraTapped(object sender, System.EventArgs args)
{
using (var file = await CrossMedia.Current.TakePhotoAsync(
new StoreCameraMediaOptions {}))
{
if (file == null)
return;
UpdateCount();
}
}
async void StartCameraTakeTapped(object sender, System.EventArgs args)
{
var file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
return;
UpdateCount();
}
}
In this case the app shut down after 52 photos. I saved the log for Xcode and you can see it here.
I used Xamarin Profile and the memory level is always low. After about 30 photos, an error occurs in Xamarin Profiler
Finally I could create a Xamarin Profiler file
Also I noticed this kind of error occurs on iPads. The same app in an iPhone is working fine (apparently) or I didn't find up to now the number of photos before crashing.
Update /2
I decided to implement a native function for taking photo.
Interface
public interface ICamera
{
void TakePicture();
}
Implementation
using System;
using cameratest.iOS;
using Foundation;
using UIKit;
using Xamarin.Forms;
[assembly: Xamarin.Forms.Dependency(typeof(Camera_iOS))]
namespace cameratest.iOS
{
public class Camera_iOS : ICamera
{
static UIImagePickerController picker;
static Action<NSDictionary> _callback;
static void Init()
{
if (picker != null)
return;
picker = new UIImagePickerController();
picker.Delegate = new CameraDelegate();
}
class CameraDelegate : UIImagePickerControllerDelegate
{
public override void FinishedPickingMedia(
UIImagePickerController picker, NSDictionary info)
{
var cb = _callback;
_callback = null;
picker.DismissModalViewController(true);
cb(info);
}
}
public static void TakePicture(UIViewController parent,
Action<NSDictionary> callback)
{
Init();
picker.SourceType = UIImagePickerControllerSourceType.Camera;
_callback = callback;
parent.PresentModalViewController(picker, true);
}
public static void SelectPicture(UIViewController parent,
Action<NSDictionary> callback)
{
Init();
picker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary;
_callback = callback;
parent.PresentModalViewController(picker, true);
}
public void TakePicture()
{
var rc = UIApplication.SharedApplication.KeyWindow.RootViewController;
TakePicture(rc, (obj) =>
{
var photo = obj.ValueForKey(
new NSString("UIImagePickerControllerOriginalImage")) as UIImage;
var documentsDirectory =
Environment.GetFolderPath(Environment.SpecialFolder.Personal);
// hardcoded filename, overwritten each time
string jpgFilename = System.IO.Path.Combine(documentsDirectory,
"Photo.jpg");
NSData imgData = photo.AsJPEG();
NSError err = null;
if (imgData.Save(jpgFilename, false, out err))
{
Console.WriteLine("saved as " + jpgFilename);
}
else
{
Console.WriteLine("NOT saved as " +
jpgFilename + " because" + err.LocalizedDescription);
}
});
}
}
}
With this code after about 30 photos, the app crashes. The only difference is with this code I can receive some alert from ReceiveMemoryWarning. If you have an interest, I updated the code on GitHub.

App Crash when comes back from Sleep

I am using xamarin for crossplatform app development . We have used asure mobile service to connect with database . Basically This application is for chatting purpose so we have used SignalR with .NET Framework.When app comes from sleep after some duration like 60 seconds it get crashed. Is there any way to connect back using SignalR.Issue seems with SignalR. Where exactly do I need to update code at client side or server side .
Client side code
public class SignalRClient
{
private static string CONNECTION_URL = "http://";
private static TimeSpan CONNECT_TIMEOUT = new TimeSpan(0, 0, 30);
private readonly HubConnection _hubConnection;
private readonly IHubProxy _chatHubProxy;
private static string AuthToken = "";
public string UserID;
public event SignalRConnectionStateChangedDelegate SignalRConnectionStateChangedEvent;
public SignalRClient(string authToken)
{
AuthToken = authToken;
_hubConnection = new HubConnection(CONNECTION_URL);
_hubConnection.Headers["xauth"] = AuthToken;
_hubConnection.TransportConnectTimeout = CONNECT_TIMEOUT;
_hubConnection.Error += ex =>
{
if (SignalRConnectionStateChangedEvent != null)
{
_hubConnection.Stop();
SignalRConnectionStateChangedEvent("Error :" + ex.Message);
}
};
_chatHubProxy = _hubConnection.CreateHubProxy("ChatServer");
}
public async Task Connect(string UserID)
{
if (_hubConnection.State != ConnectionState.Connected)
{
try
{
await _hubConnection.Start();
_hubConnection.StateChanged += (connectionState) =>
{
if (SignalRConnectionStateChangedEvent != null)
{
SignalRConnectionStateChangedEvent(connectionState.NewState.ToString().ToLower());
}
};
}
catch (Exception ex)
{
var message = ex.Message;
}

Resources