Is there any plugin or way to show 'new version of app available' alert when user opens app - xamarin

I have Xamarin.Android app, I want to show alert to user (when user opens app) that please download latest version. Like other apps. How can I do that?
I have tried few ways but didn't get succeed. I have tried this. This is quite different from Android. I need it for Xamarin.
I already asked this question but existing functionality broke down due to having some changes in play store policies, consequently I am not getting specific string "itemprop=\"softwareVersion\">" from play store so I asked new question. Thank you

Working answer. I have used plugin for that Plugin.LatestVersion for Xam.Android to get latest version of app from Google play store. below line of code was returning latest app version.
var appStoreVersionString = await CrossLatestVersion.Current.GetLatestVersionNumber();
Then this is the further implementation
private void CompareVersion()
{
double currentVersion = 0d;
double appStoreversion = 0d;
bool IsUpdateRequired = false;
if (Context.PackageName != null)
{
PackageInfo info = Context.PackageManager.GetPackageInfo(Context.PackageName, PackageInfoFlags.Activities);
string currentVersionStrig = info.VersionName;
currentVersion = Convert.ToDouble(currentVersionStrig);
}
try
{
if (IsUpdateRequired == false)
{
string appStoreVersionString = string.Empty;
if (CheckNetConnection.IsNetConnected())
{
Task.Run(async () => { appStoreVersionString = await CrossLatestVersion.Current.GetLatestVersionNumber();}).Wait();
if (!string.IsNullOrEmpty(appStoreVersionString))
{
appStoreversion = Convert.ToDouble(appStoreVersionString);
if ((appStoreversion.ToString() != currentVersion.ToString() && (appStoreversion > currentVersion)))
{
IsUpdateRequired = true;
}
}
}
}
if (IsUpdateRequired)
{
Activity.RunOnUiThread(() =>
{
AlertDialog dialog = null;
var Alertdialog = new Android.App.AlertDialog.Builder(Context);
Alertdialog.SetTitle("Update Available");
Alertdialog.SetMessage($"A new version of [" + appStoreversion + "] is available. Please update to version [" + appStoreversion + "] now.");
Alertdialog.SetNegativeButton("Cancel", (sender, e) =>
{
if (dialog == null)
{
dialog = Alertdialog.Create();
}
dialog.Dismiss();
});
Alertdialog.SetPositiveButton("Update", (sender, e) =>
{
string appPackage = string.Empty;
try
{
appPackage = Application.Context.PackageName;
Utilities.Logout(Activity);
var ints = new Intent(Intent.ActionView, Android.Net.Uri.Parse("market://details?id=" + appPackage));
ints.SetFlags(ActivityFlags.ClearTop);
ints.SetFlags(ActivityFlags.NoAnimation);
ints.SetFlags(ActivityFlags.NewTask);
Application.Context.StartActivity(ints);
}
catch (ActivityNotFoundException)
{
var apppack = Application.Context.PackageName;
Utilities.Logout(Activity);
var ints = new Intent(Intent.ActionView, Android.Net.Uri.Parse("market://details?id=" + appPackage));
ints.SetFlags(ActivityFlags.ClearTop);
ints.SetFlags(ActivityFlags.NoAnimation);
ints.SetFlags(ActivityFlags.NewTask);
Application.Context.StartActivity(ints);
}
//this kills the app?
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
System.Environment.Exit(1);
});
if (dialog == null)
dialog = Alertdialog.Create();
dialog.Show();
});
}
}
catch (Exception ex)
{
var objLog = new LogService();
objLog.MobileLog(ex, SISConst.UserName);
}
}

Related

How to get version number of application from play store using xamarin forms

I need to check current version of Installed Application and Playstore application version. If it is not same app should navigate to Playstore .
im using xam.Plugin.LatestVersion(2.1.0) To get the latestversion number of application from play console. unfortunately not getting latest version number of application from play store. The below code im using.
private async void ChekAppVersion()
{
try
{
latestVersionNumber = await CrossLatestVersion.Current.GetLatestVersionNumber();
installedVersionNumber = CrossLatestVersion.Current.InstalledVersionNumber;
if (installedVersionNumber != latestVersionNumber)
{
await DisplayAlert("New Version", "There is a new version of this app available. Please update now?", "Ok");
await CrossLatestVersion.Current.OpenAppInStore();
ChekAppVersion();
}
else
{
}
}
catch (Exception ex)
{
}
}
Im getting the installedVersionNumber, but im unable to get the latestVersionNumber(Playstore).
Please help on this.
They have removed the version from div, now it's displayed with js, but data is still there inside a <script> tag. My current fixed code is:
private bool _lockCheckUpdates;
public async Task<bool> CheckNeedUpdate()
{
if (Connectivity.NetworkAccess != NetworkAccess.Internet || _lockCheckUpdates)
return false;
_lockCheckUpdates = true;
try
{
HttpClient myClient = CreateClient();
if (Device.RuntimePlatform == Device.Android)
{
var bundle = "com.todo.app"; //ANDROID BUNDLE NAME HERE
string url = $"https://play.google.com/store/apps/details?id={bundle}&hl=en";
string raw = await myClient.GetStringAsync(new Uri(url));
var doc = new HtmlDocument();
doc.LoadHtml(raw);
var scripts = doc.DocumentNode.Descendants()
.Where(n => n.Name == "script" && n.InnerText.Contains("AF_initDataCallback({key: 'ds:4'"))
.ToArray();
var script = scripts.First().InnerText;
var engine = new Jurassic.ScriptEngine();
var eval = "(function() { var AF_initDataCallback = function(p) { return p.data[1][2][140][0][0][0]; }; return " + script + " })()";
var result = engine.Evaluate(eval);
//var json = JSONObject.Stringify(engine, result); //for debug, check in browser console with JSON.parse(json)
var remote = $"{result}".ToDouble();
var local = App.Version.ToDouble();
return local < remote;
}
else if (Device.RuntimePlatform == Device.iOS)
{
var bundle = "com.todo.app";//iOS BUNDLE NAME HERE
string url = $"http://itunes.apple.com/lookup?bundleId={bundle}";
string raw = await myClient.GetStringAsync(new Uri(url));
var dto = JsonConvert.DeserializeObject<AppStoreRecord>(raw);
double local = App.Version.ToDouble();
if (dto.ResultCount > 0)
{
double remote = dto.Results[0].Version.ToDouble();
return remote > local;
}
}
}
catch (Exception e)
{
Logger.Error("CheckNeedUpdate", e);
}
finally
{
_lockCheckUpdates = false;
}
return false;
}
Using nugets
Jurassic to evaluate the script on page,
HtmlAgilityPack to parse html,
Xamarin.Essentials to check if we are online,
and AppoMobi.Specials for .ToDouble() etc
I hope this could also be useful to fix https://github.com/edsnider/latestversionplugin/issues/43 :)
The plugin you are using no longer works for Android https://github.com/edsnider/latestversionplugin/issues/43
You will need to find a new way to get the desired information.
PR has been made on this plugin... it works again ;-)

WebView File Chooser stops to respond after cancelled selection

we have implement file chooser for web view. it works successfully when attachment is selected, but fails when cancelled without file specification. The file chooser just stops to react on click
any help is appreciated. Thanks
we use chrome client. it works fine if in all cases, file selection is listed. but even from the first file selection is cancelled, no longer file chooser will work. It is Xamarin.Android app based fully on webview
Our code is:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
{
if (requestCode == FILECHOOSER_RESULTCODE)
{
if (null == _mUploadMessage)
return;
// Check that the response is a good one
if (resultCode == Result.Ok)
{
Android.Net.Uri[] results = null;
if (intent == null)
{
// If there is not data, then we may have taken a photo
if (mCameraPhotoPath != null)
{
results = new Android.Net.Uri[] { Android.Net.Uri.Parse(mCameraPhotoPath) };
}
}
else
{
if (intent.DataString != null)
{
results = new Android.Net.Uri[] { Android.Net.Uri.Parse(intent.DataString) };
}
}
_mUploadMessage.OnReceiveValue(results);
_mUploadMessage = null;
}
}
}
Chrome client:
var chrome = new FileChooserWebChromeClient((uploadMsg) =>
{
_mUploadMessage = uploadMsg;
mCameraPhotoPath = null;
Intent takePictureIntent = new Intent(Android.Provider.MediaStore.ActionImageCapture);
//Create the File where the photo should go
File photoFile = null;
try
{
string folder = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
photoFile = new File(folder, "image" + DateTime.Now.Millisecond + ".png");
takePictureIntent.PutExtra("PhotoPath", mCameraPhotoPath);
}
catch (IOException ex)
{
// Error occurred while creating the File
System.Console.WriteLine("" + ex.ToString());
}
// Continue only if the File was successfully created
if (photoFile != null)
{
mCameraPhotoPath = "file:" + photoFile.AbsolutePath;
takePictureIntent.PutExtra(Android.Provider.MediaStore.ExtraOutput,
Android.Net.Uri.FromFile(photoFile));
}
else
{
takePictureIntent = null;
}
Intent contentSelectionIntent = new Intent(Intent.ActionGetContent);
contentSelectionIntent.AddCategory(Intent.CategoryOpenable);
contentSelectionIntent.SetType("image/*");
Intent[] intentArray;
if (takePictureIntent != null)
{
intentArray = new Intent[] { takePictureIntent };
}
else
{
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ActionChooser);
chooserIntent.PutExtra(Intent.ExtraIntent, contentSelectionIntent);
chooserIntent.PutExtra(Intent.ExtraTitle, this.GetStringFromResource(Resource.String.chose_photo));
chooserIntent.PutExtra(Intent.ExtraInitialIntents, intentArray);
base.StartActivityForResult(chooserIntent, HarmonyAndroid.AndroidMainActivity.FILECHOOSER_RESULTCODE);
});
return chrome;
Part 2
class FileChooserWebChromeClient : WebChromeClient
{
Action<IValueCallback> callback;
public FileChooserWebChromeClient(Action<IValueCallback> callback)
{
this.callback = callback;
}
public override bool OnShowFileChooser(WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
{
callback(filePathCallback);
return true;
}
public override void OnCloseWindow(WebView window)
{
base.OnCloseWindow(window);
}
}
Part 3
webView.ImprovePerformance();
webView.SetWebViewClient(new HomeWebViewClient(customWebViewClientListener, clientId));
webView.SetWebChromeClient(chrome);
webView.Settings.JavaScriptEnabled = true;
webView.Settings.DomStorageEnabled = true;
webView.SetDownloadListener(new CustomDownloadListener(activity, customDownloadListener));
webView.AddJavascriptInterface(new JavaScriptToCSharpCommunication(activity, javaScriptToCSharpCommunicationListener), Constants.JS_CSHARP_COMMUNICATOR_NAME);
Try to give a null object to the uri callback, when the resultCode is not RESULT_OK.
add in your OnActivityResult method:
if (resultCode != Result.Ok)
{
_mUploadMessage.OnReceiveValue(null);
_mUploadMessage = null;
return;
}

Xamarin Forms button event not firing on Android

I have a Xamarin Forms app, in one of my pages I have two buttons, on Android when you tap the button it does not fire the event, it just highlights the button, if you tap a second time then it fires the event, on iOS it runs flawlessly. Below is some Code extracts, sorry if my code has bad practices, I am a noob, so please do correct me, best way to learn:
//Initialize Page
public GameDetailsNew(Game myEvent)
{
InitializeComponent();
MyEvent.Text = myEvent.EventName;
MyTimeHeader.Text = myEvent.TimeOfEvent;
myEventID = myEvent.EventID;
Task.Run(() => { GetAttendingEvent(myEvent.EventID); });
}
//GetAttendingEvent
private void GetAttendingEvent(int eventID)
{
var registerLable = "";
var attendinIsVisible = false;
var notAttendingIsVisible = false;
try
{
HelperFiles.APICaller ac = new HelperFiles.APICaller();
var x = (string)ac.CallCOFMOBILEBool("GetIsAttending?eventID=" + eventID);
if (x == "Attending")
{
registerLable = "You are currently Attending this Event";
attendinIsVisible = false;
notAttendingIsVisible = true;
}
else
{
registerLable = "You are currently NOT Attending this Event";
attendinIsVisible = true;
notAttendingIsVisible = false;
}
Device.BeginInvokeOnMainThread(() =>
{
RegisterLable.Text = registerLable;
AttendingButton.IsVisible = attendinIsVisible;
NotAttendingButton.IsVisible = notAttendingIsVisible;
});
}
catch (Exception ex)
{
MyAlerts("Error", ex.Message, "OK");
}
}
//My To Button Event Handlers
//Sets User as attending event
void AttendingClicked(object sender, System.EventArgs e)
{
try
{
HelperFiles.APICaller ac = new HelperFiles.APICaller();
var x = (string)ac.CallCOFMOBILEBool("GetCreateAttending?eventID=" + myEventID);
if (x == "1")
{
RegisterLable.Text = "You are currently Attending this Event";
AttendingButton.IsVisible = false;
NotAttendingButton.IsVisible = true;
}
else
{
RegisterLable.Text = "You are currently NOT Attending this Event";
AttendingButton.IsVisible = true;
NotAttendingButton.IsVisible = false;
}
GetDeployingEvent(myEventID);
}
catch (Exception ex)
{
MyAlerts("Error", ex.Message, "OK");
}
}
//Sets User as Not attending event
void NotAttendingClicked(object sender, System.EventArgs e)
{
try
{
HelperFiles.APICaller ac = new HelperFiles.APICaller();
var x = (string)ac.CallCOFMOBILEBool("GetCreateNotAttending?eventID=" + myEventID);
if (x != "1")
{
RegisterLable.Text = "You are currently Attending this Event";
AttendingButton.IsVisible = false;
NotAttendingButton.IsVisible = true;
}
else
{
RegisterLable.Text = "You are currently NOT Attending this Event";
AttendingButton.IsVisible = true;
NotAttendingButton.IsVisible = false;
}
GetDeployingEvent(myEventID);
}
catch (Exception ex)
{
MyAlerts("Error", ex.Message, "OK");
}
}
I just wanted to update on this, I managed to resolve the issue. about 8 months ago I started my project in Xamarin Studio, fast forward a few months, Xamarin Studios changed to Visual Studio. No matter what i done i could not get rid of this bug, I then started a brand new app and pasted all my code in to the new app. This has resolved the bug.

How to get current location coordinates in the Map feature in Xamarin Application?

I am working on location coordinates marking feature in the App.
I am using following dll's and google map.
Xamarin.Forms.Maps
Xam.Plugin.Geolocator
Xam.Plugin.ExternalMaps
In my iphone simulator, If the Location is NONE.It pulls default location some where in Rome, Italy
Following is the code written to pull the Map ..
public async Task<Xamarin.Forms.Maps.Position> GetPosition()
{
IsBusy = true;
Xamarin.Forms.Maps.Position p;
try
{
if (!locator.IsGeolocationAvailable)
{
p = new Xamarin.Forms.Maps.Position();
}
if (!locator.IsGeolocationEnabled)
{
p = new Xamarin.Forms.Maps.Position();
}
var position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);
p = new Xamarin.Forms.Maps.Position(position.Latitude,position.Longitude);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
p = new Xamarin.Forms.Maps.Position();
}
IsBusy = false;
return p;
}
public async Task<object> GetCityName(double latitude, double longitude) {
HttpClient client;
client = new HttpClient();
client.MaxResponseContentBufferSize = 256000;
try
{
var response = await client.GetAsync("https://maps.googleapis.com/maps/api/geocode/json?latlng=" + latitude + "," + longitude);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
var json = Newtonsoft.Json.Linq.JObject.Parse(result);
var reValue = "" + json["results"][0]["formatted_address"];
var strArr = reValue.Split(',');
if (strArr.Length > 2)
return strArr[strArr.Length - 2] + ", " +strArr[strArr.Length - 1];
else
return "";
}
else {
Debug.WriteLine(#"Failed.");
return "Failed";
}
}
catch (Exception ex)
{
Debug.WriteLine(#"ERROR {0}", ex.Message);
return ex.Message;
}
}
Image :
elaborate your problem please, and change your conditions as follows:
if (CrossGeolocator.Current.IsGeolocationAvailable)
{
if (CrossGeolocator.Current.IsGeolocationEnabled)
{
var position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);
p = new Xamarin.Forms.Maps.Position(position.Latitude,position.Longitude);
}
else
{
throw new Exception("Geolocation is turned off");
// Geolocation is turned off for the device.
}
}
else
{
throw new Exception("Geolocation is turned off");
// Geolocation not available for device
}
Here now Handle the catches from GetPosition() Method to make sure you don't get the default location.

Xamarin native login with Facebook and Twitter

I am developing a Xamarin Forms application which integrates Facebook and logs in using the Xamarin.Auth package. But each time a browser window will open to login with Facebook or Twitter.
Does Xamarin support native login with Facebook and Twitter? That is, can I log in using the Facebook or Twitter app on the user's device?
I need to get the Facebook and Twitter id of the user.
you can use ACAccountStore and if user doesn't have the social framework you can alternatively use xamarin auth
ACAccountStore accountStore = new ACAccountStore();
ACAccountType accountType = accountStore.FindAccountType(ACAccountType.Facebook);
AccountStoreOptions fbAccountStoreOptions = new AccountStoreOptions();
fbAccountStoreOptions.FacebookAppId = "333333";
fbAccountStoreOptions.SetPermissions(ACFacebookAudience.Everyone, new[] { "email", "user_birthday", "user_about_me","public_profile" });
Tuple<bool, NSError> requestResult = await accountStore.RequestAccessAsync(accountType, fbAccountStoreOptions);
if (requestResult.Item1)
{
ACAccount[] availableAccounts = accountStore.Accounts.Where(acco => acco.AccountType.Description == "Facebook").ToArray();
int fbAccountsCount = availableAccounts.Count();
if (fbAccountsCount < 1)
{
HandleFacebookAuthorizationUsingOAuthDialog();
}
else if (fbAccountsCount == 1)
{
HandleFacebookAuthorizationUsingACAccount(availableAccounts.First());
}}
private void HandleFacebookAuthorizationUsingOAuthDialog()
{
try
{
OAuth2Authenticator fbAuthenticator = new OAuth2Authenticator(SharedConstants.FacebookLiveClientId, "email,user_birthday,user_about_me", new Uri("https://m.facebook.com/dialog/oauth/"), new Uri("http://www.facebook.com/connect/login_success.html"));
fbAuthenticator.AllowCancel = true;
fbAuthenticator.Completed += FbAuthenticator_Completed;
fbAuthenticator.Error += FbAuthenticator_Error; ;
RootView.PresentViewController(fbAuthenticator.GetUI(), true, null);
}
catch (Exception ex)
{
}
}
private async void HandleFacebookAuthorizationUsingACAccount(ACAccount account)
{
try
{
NSMutableDictionary<NSString, NSString> params_ = new NSMutableDictionary<NSString, NSString>();
params_.SetValueForKey(new NSString("id,name,birthday,gender"), new NSString("fields"));
SLRequest request = SLRequest.Create(SLServiceKind.Facebook, SLRequestMethod.Get, new NSUrl($"https://graph.facebook.com/me"), params_);
request.Account = account ?? throw new ArgumentNullException(nameof(account));
SLRequestResult response = await request.PerformRequestAsync();
NSHttpUrlResponse responseData = response.Arg2;
if (responseData.StatusCode == 200)
{
string jsonResponse = response.Arg1.ToString();
FacebookAuthorizationResult authResult = ParseFacebookAuthorizationResultFromJsonResponse(jsonResponse);
_facebookAuthTCS?.TrySetResult(new SocailAutheticationResult<FacebookAuthorizationResult>(authResult));
}
else
{
_facebookAuthTCS?.TrySetResult(new SocailAutheticationResult<FacebookAuthorizationResult>(SocialAuthorizationState.CouldntConnectToService));
}
}
catch (Exception ex)
{
_
}
}

Resources