Xamarin forms: Selected picture is not showing in UI from gallery and camera for IOS - xamarin.forms

Complete Scenario
I have an add icon on one page, it will show camera and gallery options when tap. If choose the camera, I will open another content page and open camera there. But the captured picture is not showing in the UI. Same for the gallery, selected image from the gallery is not showing in UI. This feature is working fine in android and not working in IOS.
Codes
When click add icon
string action = await DisplayActionSheet(null, "Cancel", null, "Camera", "Gallery");
if (action == "Camera")
{
await Navigation.PushModalAsync(new NewTweetPage("Camera"));
}
else if (action == "Gallery")
{
await Navigation.PushModalAsync(new NewTweetPage("Gallery"));
}
When entering next page
public NewTweetPage(String medium)
{
InitializeComponent();
if (medium == "Camera" )
{
OpenMyCamera();
}
else if(medium == "Gallery")
{
OpenMygallery();
}
}
public async void OpenMyCamera()
{
try
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("Camera", "No camera available.", "OK");
return;
}
_mediaFile = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "Sample",
Name = "test.jpg",
AllowCropping = true
});
if (_mediaFile == null)
return;
tweetPicture.Source = ImageSource.FromStream(() =>
{
isPicture = true;
return _mediaFile.GetStream();
});
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Exception:>" + ex);
}
}
public async void OpenMygallery()
{
try
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert("Gallery", ":( No photos available.", "OK");
return;
}
_mediaFile = await CrossMedia.Current.PickPhotoAsync();
if (_mediaFile == null)
return;
tweetPicture.Source = ImageSource.FromStream(() =>
{
isPicture = true;
return _mediaFile.GetStream();
});
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Exception:>" + ex);
}
}
The same code is working fine in profile page part, but in that case, there is no page navigation, everything is happening on the same page.
Don't know what is the problem with the current code, please help me to solve this issue.

Putting navigation commands in the constructor can cause issues. I would recommend putting them in the OnAppearing override. Also, instead of having a try...catch around a large section of code, you should handle null-checks or similar in code.

Related

Blazor navigate to navigating to correct page and immediately back to current page

I have a button on an edit page that I want to execute an entity query and then navigate back to the main page.
<button class="btn" #onclick="(() => UpdateEmpById(Emp))">Save Emp</button>
The method this button is calling can be seen below...
`private async Task UpdateEmpById(Emp emp)
{
if (emp is null || IsBusy)
{
return;
}
IsBusy = true;
try
{
using var context = ContextFactory.CreateDbContext();
List<Emp > Temp = await context.Emps
.Where(x => x.Id == emp.id)
.ToListAsync();
}
catch (DbUpdateConcurrencyException)
{
ErrorMessage = "The employee was modified. Please reload the page";
}
catch (Exception ex)
{
ErrorMessage = $"Error while saving employee: {ex.Message}";
}
finally
{
IsBusy = false;
}
NavigationManager.NavigateTo($"/");
}`
The page navigates back to "/" and immediately back to the current page and I am unsure why.
I am somewhat new to Blazor and do not know what to try currently.

Xamarin Forms Android Subscription purchase

We have an XF Forms app that we are adding subscription support for. We implemented Plugin.InAppBilling. Works as expected on iOS. We followed JM's docs for configuring on Android - but getting "This app not configured for subscriptions" error.
This is the purchase method we are using:
public async Task<InAppBillingPurchase> MakePurchase()
{
if (!CrossInAppBilling.IsSupported)
return null;
var currentPage = GetCurrentPage();
if(currentPage != null)
{
var confirm = await currentPage.DisplayAlert("Q5id subscription", "Become a subscriber to create an alert to find your loved one.","Confirm", "Cancel");
if (!confirm) return null;
}
var billing = CrossInAppBilling.Current;
try
{
var connected = await CrossInAppBilling.Current.ConnectAsync();
if (!connected)
{
//Couldn't connect to billing, could be offline, alert user
return null;
}
//try to purchase item
var purchase = await CrossInAppBilling.Current.PurchaseAsync(SUBSCRIPTION_PRODUCT_ID, ItemType.Subscription);
deviceService.DeviceLog("PurchaseAsync purchase: ", purchase);
var isFinish = await CrossInAppBilling.Current.FinishTransaction(purchase);
deviceService.DeviceLog("PurchaseAsync isFinish: ", isFinish);
return purchase;
}
catch (Exception ex)
{
Debug.WriteLine("Error MakePurchase: " + ex.Message);
deviceService.DeviceLog("Error MakePurchase: ", ex);
return null;
}
finally
{
await billing.DisconnectAsync();
}
}
We have verified bundleid, Play Console looks right. Any ideas?

Save and load data to firebase not working unity

maybe my code will mess here beacuse I'm new into firebase stuff and there is lack doc for newbie like me, so I want to make save and load data from firebase, there is 2 scene the first for main menu and second one the main game,so when firstime login or auto login, user will load current user data from realtime database (I'm using firebase) also applies to user when back to main menu.
in the second scene itself, user load current user highscore data at first start then when game over if the score > lasthighscore that will save/update latest highscore to realtime database.
here the preview this is when I auto-login then playgame until game over:
it's supposed to be updated but not when back to main menu, I already try with player prefs since i erase all data when sign out so the highscore always be 0 and if login with other account that highscore is not belong to other account.
here my firebase script on main menu:
private void Start()
{
Time.timeScale = 1;
mainPanel.SetActive(true);
InitializeFirebase();
}
void InitializeFirebase()
{
auth = FirebaseAuth.DefaultInstance;
DBreference = FirebaseDatabase.DefaultInstance.RootReference;
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
void AuthStateChanged(object sender, System.EventArgs eventArgs)
{
//This checks if the user (your local user) is the same as the one from the auth
if (auth.CurrentUser != User)
{
//this seems the same, but user could have been null before
bool signedIn = User != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && User != null)
{
Debug.Log("Signed out " + User.UserId);
loginPanel.SetActive(true);
}
//this is important step, this user is the one you should be working with
User = auth.CurrentUser;
if (signedIn)
{
Debug.Log("Signed in " + User.UserId);
userNameShowText.text = User.DisplayName;
StartCoroutine(LoadUserData());
loginPanel.SetActive(false);
// //highScoreMainMenu.text = PlayerPrefs.GetInt("highscore").ToString("0000000");
}
else
{
loginPanel.SetActive(true);
}
}
}
public IEnumerator Login(string _email, string _password)
{
//Call the Firebase auth signin function passing the email and password
var LoginTask = auth.SignInWithEmailAndPasswordAsync(_email, _password);
//Wait until the task completes
yield return new WaitUntil(predicate: () => LoginTask.IsCompleted);
if (LoginTask.Exception != null)
{
//If there are errors handle them
Debug.LogWarning(message: $"Failed to register task with {LoginTask.Exception}");
FirebaseException firebaseEx = LoginTask.Exception.GetBaseException() as FirebaseException;
AuthError errorCode = (AuthError)firebaseEx.ErrorCode;
string message = "Login Failed!";
switch (errorCode)
{
case AuthError.MissingEmail:
message = "Missing Email";
break;
case AuthError.MissingPassword:
message = "Missing Password";
break;
case AuthError.WrongPassword:
message = "Wrong Password";
break;
case AuthError.InvalidEmail:
message = "Invalid Email";
break;
case AuthError.UserNotFound:
message = "Account does not exist";
break;
}
warningLoginText.text = message;
}
else
{
//User is now logged in
//Now get the result
User = LoginTask.Result;
Debug.LogFormat("User signed in successfully: {0} ({1})", User.DisplayName, User.Email);
warningLoginText.text = "";
confirmLoginText.text = "Logged In";
StartCoroutine(LoadUserData());
yield return new WaitForSeconds(2);
userNameShowText.text = User.DisplayName;
UserDataScreen(); // Change to user data UI
confirmLoginText.text = "";
ClearLoginFeilds();
ClearRegisterFeilds();
}
}
public IEnumerator UpdateHighScore(int _highScore)
{
var DBTask = DBreference.Child("users").Child(auth.CurrentUser.UserId).Child("highscore").SetValueAsync(_highScore);
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)
{
Debug.LogWarning(message: $"Failed to register task with {DBTask.Exception}");
}
else
{
//giscrore now updated
}
}
and this is for the game scene also same function for update higscore like on main menu.
void Start()
{
InitializeFirebase();
YetGameOver();
//GetScore
score = 0;
scoreText.text = score.ToString("00000");
//highScoreText.text = "HI :" + PlayerPrefs.GetInt("highscore", 0).ToString("00000");
maxTime = .1f;
}
void InitializeFirebase()
{
auth = FirebaseAuth.DefaultInstance;
DBreference = FirebaseDatabase.DefaultInstance.RootReference;
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
void AuthStateChanged(object sender, System.EventArgs eventArgs)
{
//This checks if the user (your local user) is the same as the one from the auth
if (auth.CurrentUser != User)
{
//this seems the same, but user could have been null before
bool signedIn = User != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && User != null)
{
Debug.Log("Signed out " + User.UserId);
}
//this is important step, this user is the one you should be working with
User = auth.CurrentUser;
if (signedIn)
{
Debug.Log("Signed in " + User.UserId);
StartCoroutine(LoadUserData());
//highScoreMainMenu.text = PlayerPrefs.GetInt("highscore").ToString("0000000");
}
}
}
public void GameOver()
{
SaveData();
StartCoroutine(WaitToDeath());
}
public void SaveData()
{
Debug.Log("Saved");
StartCoroutine(UpdateHighScore(PlayerPrefs.GetInt("highscore", 0)));
}
public IEnumerator WaitToDeath()
{
_CamShake.instance.shouldShake = true;
DeathSound();
gameOverPanel.SetActive(true);
endHighScoreText.text = "HI :" + PlayerPrefs.GetInt("highscore").ToString("0000000");
scoreText.gameObject.SetActive(false);
highScoreText.gameObject.SetActive(false);
yield return new WaitForSeconds(.1f);
//_AdmobAds.instance.ShowInterstitialAd();
isStarted = false;
isGameOver = true;
Time.timeScale = 0;
}
//same function like main menu
public IEnumerator UpdateHighScore(int _highScore)
{
var DBTask = DBreference.Child("users").Child(auth.CurrentUser.UserId).Child("highscore").SetValueAsync(_highScore);
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)
{
Debug.LogWarning(message: $"Failed to register task with {DBTask.Exception}");
}
else
{
//highscore are now updated
}
}
public IEnumerator LoadUserData()
{
//Get the currently logged in user data
var DBTask = DBreference.Child("users").Child(User.UserId).GetValueAsync();
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)
{
Debug.LogWarning(message: $"Failed to register task with {DBTask.Exception}");
}
else if (DBTask.Result.Value == null)
{
//No data exists yet
highScoreText.text = "0";
endHighScoreText.text = "0";
}
else
{
//Data has been retrieved
DataSnapshot snapshot = DBTask.Result;
highScoreText.text = endHighScoreText.text = snapshot.Child("highscore").Value.ToString();
}
}
You don't capture child in this method. You can only capture all the data from the root. So, simply remove the child. It will work.
my solution to firebase realtime database not working was that my google-services.json wasnt updated after adding the google-services.json from firebase auth. firebase, project overview cogwheel, project settings, json on that page somewhere.
and my problem with firebase auth before that was that i didnt set the Client ID in unity, window, google play games, setup, android setup.. get the id from google play console, play games services, setup & management, configuration, and figure out how to add game server credentials

cannot connect to itunes store xamarin forms

enter image description hereHi Thanks in advance i have facing a problem in my xamarin forms ios. Problem is that when i want to purchase product it thrown an exception that cannot to connect to itune store my same code in working fine on xamarin forms android.My code for restore purchases is working fine.
Here is my code for make purchases
private async Task<bool> MakePurchase(string ProductId, string Payload)
{
if (!CrossInAppBilling.IsSupported)
{
return false;
}
var billing = CrossInAppBilling.Current;
try
{
var connected = await billing.ConnectAsync();
if (!connected)//Couldn't connect to billing, could be offline,
alert user
{
DependencyService.Get<IToast>().Show("Something went
wrong or you may not connected with the internet!");
return false;
}
//try to purchase item
var purchase = await billing.PurchaseAsync(ProductId,
ItemType.InAppPurchase, Payload);
if (purchase == null)
{
return false;
}
else
{
//Purchased, save this information
var responseId = purchase.Id;
var responseToken = purchase.PurchaseToken;
var state = purchase.State;
return true;
}
}
catch (InAppBillingPurchaseException ex)
{
if (ex.PurchaseError == PurchaseError.DeveloperError)
{
DependencyService.Get<IToast>().Show("DeveloperError");
ex.Message.ToString();
}
else if (ex.PurchaseError == PurchaseError.AlreadyOwned)
{
DependencyService.Get<IToast>().Show("AlreadyOwned");
return true;
}
else if(ex.PurchaseError == PurchaseError.BillingUnavailable)
{
DependencyService.Get<IToast>
().Show("BillingUnavailable");
return false;
}
else if(ex.PurchaseError == PurchaseError.InvalidProduct)
{
DependencyService.Get<IToast>().Show("InvalidProduct");
return false;
}
else if(ex.PurchaseError == PurchaseError.ItemUnavailable)
{
DependencyService.Get<IToast>().Show("ItemUnavailable");
return false;
}
else if(ex.PurchaseError == PurchaseError.GeneralError)
{
DependencyService.Get<IToast>().Show("General Error");
return false;
}
//Something bad has occurred, alert user
}
finally
{
//Disconnect, it is okay if we never connected
await billing.DisconnectAsync();
}
return false;
}

can not show alertcontroller when page is displayed using PushModalAsync

I am trying to show toast message in android and iOS from xamarin.forms project using Dependency Service. In iOS project message is shown on MainPage or NavigationPage. but when I navigate a second page on button click using PushModalAsync, message is not displayed.
How I navigate the page
public LoginPage()
{
Device.BeginInvokeOnMainThread(() =>
{
CustomToast.LongMessage("Hiiiiii"); // Message shown
});
Navigation.PushModalAsync(new RegisterPage()); //Doesn't show
//var reg = new RegisterPage();
//Application.Current.MainPage = reg; // toast shown here
}
Code for alertController in iOS :
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)
{
try
{
if (alert == null && alertDelay == null)
{
alertDelay = NSTimer.CreateScheduledTimer(seconds, (obj) =>
{
Device.BeginInvokeOnMainThread(() =>
{
DismissMessage();
});
});
Device.BeginInvokeOnMainThread(() =>
{
try
{
alert = UIAlertController.Create("", message, UIAlertControllerStyle.ActionSheet);
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(alert, true, null);
}
catch (Exception ex)
{
var Error = ex.Message;
}
});
}
}
catch (Exception ex)
{
TraceLog("Message iOS ShowAlert : " + ex.Message);
}
}
void DismissMessage()
{
if (alert != null)
{
alert.DismissViewController(true, null);
alert = null;
}
if (alertDelay != null)
{
alertDelay.Dispose();
alertDelay = null;
}
}
And I call this from my register page constructor
Device.BeginInvokeOnMainThread(() =>
{
CustomToast.LongMessage("Hiiiiii");
});
It doesn't go in catch anywhere but its not displayed also. can anyone please suggest some advice ?
This is because RegisterPage is a presented page on your LoginPage, UIApplication.SharedApplication.KeyWindow.RootViewController this code can't retrieve a correct view controller for RegisterPage. It just presented an action sheet on the previous page, but your app has reached a new page then this Toast can be shown on the screen.
Firstly, you have to find out the top page on the window:
UIViewController topViewControllerWithRootViewController(UIViewController rootViewController)
{
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);
}
return rootViewController;
}
Secondly, adjust your presenting code like:
Device.BeginInvokeOnMainThread(() =>
{
try
{
alert = UIAlertController.Create("", messages, UIAlertControllerStyle.ActionSheet);
topViewControllerWithRootViewController(UIApplication.SharedApplication.KeyWindow.RootViewController).PresentViewController(alert, true, null);
}
catch (Exception ex)
{
var Error = ex.Message;
}
});
At last, you could show your toast using Navigation.PushModalAsync(new RegisterPage());

Resources