I'm working on a Xamarin Forms app and am trying to open the the default mail client directly to the Inbox.
I'm able to open and pass data through to compose a message using XF Essentials
Email.ComposeAsync(message);
But I would like the app to open the default mail app's Inbox on a button press. Is this possible in Xamarin Forms?
I think Dependency Service is what you need.
Create an interface in your Forms project:
public interface IOpenManager
{
void openMail();
}
Then implement it on each platform, for iOS:
[assembly: Dependency(typeof(OpenImplementation))]
namespace Demo.iOS
{
public class OpenImplementation : IOpenManager
{
public void openMail()
{
NSUrl mailUrl = new NSUrl("message://");
if (UIApplication.SharedApplication.CanOpenUrl(mailUrl))
{
UIApplication.SharedApplication.OpenUrl(mailUrl);
}
}
}
}
For Android:
[assembly: Dependency(typeof(OpenImplementation))]
namespace Demo.Droid
{
public class OpenImplementation : IOpenManager
{
public void openMail()
{
Intent intent = new Intent(Intent.ActionMain);
intent.AddCategory(Intent.CategoryAppEmail);
Android.App.Application.Context.StartActivity(intent);
}
}
}
At last, call this dependcy via: DependencyService.Get<IOpenManager>().openMail();
Related
I have a page where I display all sorts of info and I would like to display either the android Sdk used or the iOS version used
How can I retrieve those in xamarin forms? Looked at xamarin essentials but cannot find it.
Result wanted
Android Sdk
29 (10)
ioS
14
Hope makes sense
thanks
You can get via Dependency Service. Create Interface in shared project and then implement this interface in platform specific projects.
Shared Project
public interface IDeviceInfo
{
string GetOSVersion();
}
iOS Project
[assembly: Dependency(typeof(DeviceInfo_iOS))]
namespace App1.iOS
{
public class DeviceInfo_iOS : IDeviceInfo
{
public string GetOSVersion()
{
return UIDevice.CurrentDevice.SystemVersion;
}
}
}
Android Project
[assembly: Dependency(typeof(DeviceInfo_Android))]
namespace App1.Droid
{
public class DeviceInfo_Android : IDeviceInfo
{
public string GetOSVersion()
{
return "Android Sdk " + (int)Build.VERSION.SdkInt +" (" + Build.VERSION.Release +")";
}
}
}
Call the DependencyService in Shared Project
var version = DependencyService.Get<IDeviceInfo>().GetOSVersion();
I save some preferences in Application.Current.Properties for my Xamarin.Forms app and have a BroadcastReceiver that needs those preferences. The problem is that Xamarin.Forms is not initialized in the BroadcastReceiver so I need a way to access those variables in native Xamain.Android. Is that possible?
I need a way to access those variables in native Xamain.Android
you could use DependencyService ,this functionality enables Xamarin.Forms apps to do anything that a native app can do.
here is a sample for using Android's Toast to show message in shared code:
1.create a interface in shared code:
public interface IToast
{
void LongAlert(string message);//the parameter could pass to the native platform
void ShortAlert(string message);
}
2.Android Implementation:
[assembly: Dependency(typeof(ToastAndroid))]
namespace Demo.Droid
{
class ToastAndroid : IToast
{
public void LongAlert(string message)
{
Toast.MakeText(Android.App.Application.Context, message, ToastLength.Long).Show();
}
public void ShortAlert(string message)
{
Toast.MakeText(Android.App.Application.Context, message, ToastLength.Short).Show();
}
}
}
3.call in shared code:
DependencyService.Get<IToast>().ShortAlert("short toast);
DependencyService.Get<IToast>().LongAlert("long toast);
DependencyService
I found the solution myself.
I used the Xamarin.Forms source (found here) to write a function that reads the values from the same file as they are written to in the forms app. Works like a charm.
Good day,
I need to build local notifications on my xamarin.forms, so i started from android:
1. In the core project i've created an interface:
public interface INotification
{
void CreateNotification();
}
2. In the Droid i've implemented notifications:
[assembly: Xamarin.Forms.Dependency(typeof(Notification))]
namespace Test.Droid
{
class Notification : Interfaces.INotification
{
public void CreateNotification()
{
string content = #"Here is the text";
int messageId = 999;
NotificationCompat.Builder builder = new NotificationCompat.Builder(Application.Context)
.SetAutoCancel(true)
.SetContentTitle("My Notifications")
.SetSmallIcon(Resource.Drawable.icon)
.SetContentText("Click here to next Activity")
.SetStyle(new NotificationCompat.BigTextStyle().BigText(content))
;
NotificationManager notificationManager = (NotificationManager)Application.Context.GetSystemService(Context.NotificationService);
notificationManager.Notify(messageId, builder.Build());
}
}
}
Finally, I put a dependency service on the main page of the core project
public MainPage()
{
InitializeComponent();
DependencyService.Get<INotification>().CreateNotification();
}
But i dont see a notification!
P.S. Its working fine on xamarin.android app.
The mistake was in a worng dependency :
[assembly: Xamarin.Forms.Dependency(typeof(Test.Droid.Notification))]
SOLVED
I have a MainPage in PCL which then navigates to a Platform Specific
Login Page on LoginButton Click Event
The LoginPage is inherited from
platform specific PageRenderer as it needs platform specific
Authentication to Social Providers (Facebook, Google, Twitter,
Microsoft, etc.)
I am using Xamarin.Auth to do the authentication.
Inside the OnElementChanged event of the LoginPage, it instantiates
the OAuth2Authenticator object.
Upon successful instantiation (based
on provider and app details), it needs to call the UI of the specific
provider.
To do that, I call the auth.GetUI where auth is
Xamarin.Auth.OAuth2Authenticator object.
I have two questions:
In UWP, how do I navigate to the provider login UI? More specifically, what is the equivalent in UWP of the following code snippets in iOS and Android? In iOS, the following code is used:
PresentViewController(auth.GetUI(), true, null);
where auth is Xamarin.Auth.OAuth2Authenticator object.
In Android the following is used:
activity.StartActivity(auth.GetUI(activity));
I am looking for the equivalent code in UWP. Please bear in mind that these calls are made from the LoginPage which is derived from Platform specific PageRenderer
How do I navigate back to my MainPage (which is in PCL) upon successful authentication?
The code is based off of a sample from the following source:
http://www.c-sharpcorner.com/article/oauth-login-authenticating-with-identity-provider-in-xamarin-forms/
Here is my code for the LoginPage:
using System;
using Valufy;
using Xamarin.Forms.Platform.UWP;
using System.ComponentModel;
using Valufy.UWP;
using Valufy.AuthConfiguration;
using Xamarin.Forms;
[assembly: ExportRenderer(typeof(ProviderLoginPage), typeof(LoginRenderer))]
namespace Valufy.UWP
{
class LoginRenderer: PageRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
//Get and Assign ProviderName from ProviderLoginPage
ProviderLoginPage loginPage = (ProviderLoginPage)Element;
string providername = loginPage.ProviderName;
//Create OauthProviderSetting class with Oauth Implementation .Refer Step 6
OAuthProviderSetting oauth = new OAuthProviderSetting();
Xamarin.Auth.OAuth2Authenticator auth = oauth.LoginWithProvider(providername);
// After facebook,google and all identity provider login completed
auth.Completed += Auth_Completed;
Type page_type = auth.GetUI();
//////THIS IS WHERE I AM STUCK...HOW DO I GO TO THE PROVIDER AUTH UI ////////////
//this.Frame.Navigate(page_type, auth);
//parentPage.Navigation.PushModalAsync(auth.GetUI());
}
}
private void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated)
{
OAuthConfig.User = new UserDetails();
// Get and Save User Details
OAuthConfig.User.Token = e.Account.Properties["oauth_token"];
OAuthConfig.User.TokenSecret = e.Account.Properties["oauth_token_secret"];
OAuthConfig.User.TwitterId = e.Account.Properties["user_id"];
OAuthConfig.User.ScreenName = e.Account.Properties["screen_name"];
/////NOW, HOW GO I GO BACK TO THE CALLING PAGE IN PCL ///////////////////
}
else
{
// The user cancelled
/////NOW, HOW GO I GO BACK TO THE CALLING PAGE IN PCL ///////////////////
}
}
}
}
Here is the code to navigate to the provider login for UWP:
WindowsPage windowsPage = new WindowsPage();
_frame = windowsPage.Frame;
if (_frame == null)
{
_frame = new Windows.UI.Xaml.Controls.Frame
{
Language = global::Windows.Globalization.ApplicationLanguages.Languages[0]
};
windowsPage.Content = _frame;
SetNativeControl(windowsPage);
}
Type pageType = auth.GetUI();
_frame.Navigate(pageType, auth);
To navigate back to my page upon successful authentication, here is the code:
private async void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated)
{
var request = new OAuth2Request("GET", new Uri("https://login.microsoftonline.com/common/oauth2/V2.0/token?oauth2_access_token=" + e.Account.Properties["access_token"]), null, e.Account);
try
{
string response = await MSGetUserInfo(e.Account);
}
catch (System.OperationCanceledException)
{
}
catch (Exception ex)
{
}
this.Element.Navigation.PushModalAsync(new MainPage());
}
else
{
// The user cancelled
}
}
1- In UWP, how do I navigate to the provider login UI
You need to create a UWP Page object, the same object you are will use to display in the renderer is the one you will use to do the navigation.
Type page_type = auth.GetUI();
page = new MyUWPLoginPage();
page.Frame.Navigate(page_type, auth);
2- How do I navigate back to my MainPage (which is in PCL) upon successful authentication?
There are many ways to do this, the easiest one is creating a public method in your ProviderLoginPage class and from the renderer classes call this method and pass-in the parameters.
public class ProviderLoginPage: ContentPage
{
......
public void AuthenticationCompleted(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
// Do your logic
}
}
In your Renderer using the Element:
private void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
var xamElement = Element as ProviderLogin;
xamElement?.AuthenticationCompleted(sender, e);
}
Move all the logic to the PCL class so you don't have to repeat it on each renderer.
This should help.
I'm currently building a Xamarin.Forms project using MVVMCross. In order to test my platform specific code I am using Nunit.Xamarin which features an app that run tests on device.
This test app is a forms app but doesn't use MVVMCross and I haven't had any luck setting it up to use MVVMCross due to the fact the Application class loads an App of type NUnit.Runner.App whereas MVVMCross requires MvxFormsApp.
I want to test this class the saves and loads user data from an SQLite Database:
public class DataStorageService : IDataStorageService
{
private readonly SQLiteConnection _connection;
public User UserData
{
get { return _connection.Table<User>().FirstOrDefault(); }
set { _connection.InsertOrReplace(value); }
}
public DataStorageService(IMvxSqliteConnectionFactory factory)
{
_connection = factory.GetConnection(DataStorageConstants.LocalDatabaseName);
_connection.CreateTable<User>();
}
}
I want to actually test that it saves and loads from a local SQLite database so I don't want to mock the IMvxSqliteConnectionFactory. I tried installing MVVMCross and the SQLite plugin into the project and then passing in the Android implementation of the connection factory but that repeatedly threw a typeloadexception.
Any ideas as to how I can set up this test with MVVMCross (or are there alternatives?) and dependency injection?
It is possible :) The important stuff happens in the MvxSplashScreenActivity. The MvxFormsApp is basically empty. So we don't have to care. Example Code: https://github.com/smstuebe/stackoverflow-answers/tree/master/mvx-android-test-app
Create a nunit Test app project
Install-Package MvvmCross.StarterPack -Version 4.1.4
Get rid of Views folder
Install the SQLite plugin
Reference your Core project
Install-Package MvvmCross.Forms.Presenter -Version 4.1.4
Remove MainLauncher = true from MainActivity
Adust Setup to return your core project's App
protected override IMvxApplication CreateApp()
{
return new MyApp.Core.App();
}
Change SplashScreen to (source)
[Activity(MainLauncher = true
, Theme = "#style/Theme.Splash"
, NoHistory = true
, ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashScreen
: MvxSplashScreenActivity
{
public SplashScreen()
: base(Resource.Layout.SplashScreen)
{
}
private bool _isInitializationComplete;
public override void InitializationComplete()
{
if (!_isInitializationComplete)
{
_isInitializationComplete = true;
StartActivity(typeof(MainActivity));
}
}
protected override void OnCreate(Android.OS.Bundle bundle)
{
Forms.Init(this, bundle);
Forms.ViewInitialized += (object sender, ViewInitializedEventArgs e) =>
{
if (!string.IsNullOrWhiteSpace(e.View.StyleId))
{
e.NativeView.ContentDescription = e.View.StyleId;
}
};
base.OnCreate(bundle);
}
}
Write a test like
[TestFixture]
public class TestClass
{
[Test]
public void TestMethod()
{
var service = Mvx.Resolve<IDataStorageService>();
Assert.IsNull(service.UserData);
}
}
Enjoy the awesomeness of MvvmCross