I have a Xamarin.Forms app where I developed a cross platform app for both iOS and Android. There, I rendered a website inside a webview. I will have a venmo button in that webview for payment. Once I click on venmo button, the venmo app that is already installed in my mobile will get launched and returns back to my app with an authorization. Everything is working fine in iOS. But in Android, when I click on venmo button in webview, venmo app is not getting launched. I have added intent filter as below in MainActivity.cs.
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable }, DataScheme = "com.venmo")]
Also added this in AndroidManifest.xml
<queries>
<package android:name="venmo" />
<intent>
<action android:name="android.intent.action.LAUNCH" />
<data android:scheme="com.venmo" />
</intent>
</queries>
For Android, you could use custom renderer to invoke C# from JavaScript.
To register the action like the code below.
webView.RegisterAction(data => DisplayAlert("Alert", "Hello " + data, "OK"));//you could use your own code to launch the app.
For more details, you could refer to the MS docs. https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/hybridwebview#create-the-custom-renderer-on-each-platform
You could download the code sample form GitHub for reference. https://learn.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/customrenderers-hybridwebview/
When you want to start another app in this app, you could StartActivity with the app package name.
public Task<bool> Launch(string stringUri)
{
Intent intent = Android.App.Application.Context.PackageManager.GetLaunchIntentForPackage(stringUri);
if (intent != null)
{
intent.AddFlags(ActivityFlags.NewTask);
Forms.Context.StartActivity(intent);
return Task.FromResult(true);
}
else
{
return Task.FromResult(true);
}
}
For the whole code about starting an app from another app, you could refer to the thread i done before. How to launch an app from another in Xamarin forms
Related
I am following Respond to system theme change to respond to OS theme in xamarin form app. The app supports both Dark and Light themes with AppThemeBinding. I am not using any custom themes. I am following OS themes only. So I have a Switch which the user would prefer to enable Dark Mode (same as OS). The link suggests the following code to enable specified Mode (e.g Dark Mode).
Application.Current.UserAppTheme = OSAppTheme.Dark;
The above code does nothing, but if I write the above code in App.cs after InitializeComponent() The app changes to Dark Mode.
I Then realized to restart the MainActivity in Android which I did with the help of Dependency.
[assembly: Dependency(typeof(AndroidThemeChanged))]
public class AndroidThemeChanged : ITheme
{
public void OnThemeChanged()
{
var activity = CrossCurrentActivity.Current.Activity;
var intent = GetLauncherActivity();
activity.Finish();
activity.StartActivity(intent);
}
public static Intent GetLauncherActivity()
{
var packageName = AndroidApp.Context.PackageName;
return AndroidApp.Context.PackageManager.GetLaunchIntentForPackage(packageName);
}
}
and Calling it
if (Device.RuntimePlatform == Device.Android)
DependencyService.Get<ITheme>().OnThemeChanged();
Is there any way to update application theme irrespective of OS theme (Dark/Light) without restarting the MainActivity?
My bad, I guess I was wrong. The code in my question works as expected. I don't need to have that Android Service to restart activity.
Calling below from any where changes the theme to Dark irrespective of OS theme.
Application.Current.UserAppTheme = OSAppTheme.Dark;
I guess you don't have to restart the MainActivity. As per the documentation here we can react to the theme changes using the Application.Current.RequestedThemeChanged event.
Please make sure to follow the AppThemeBinding markup extension as per the documentation here.
Try the below code.
Application.Current.RequestedThemeChanged += Current_RequestedThemeChanged;
private void Current_RequestedThemeChanged(object sender, AppThemeChangedEventArgs e)
{
if (e.RequestedTheme == OSAppTheme.Dark)
Application.Current.UserAppTheme = OSAppTheme.Dark;
else
Application.Current.UserAppTheme = OSAppTheme.Light;
}
I hope that helps.
I am using Xamarin.Essentials Phone Dialer in my xamarin forms app to make calls. In android when we click call it will directly open dialer. In ios when we click call it will firstly show a alert box that will ask Call or cancel. Is it possible to open the dialer in ios without showing the popup? If it is not possible can we get the alert box cancel or call click event?
Unfortunately, this is not possible in iOS.
From Apple's documentation:
openURL
When a third party application invokes openURL: on a tel://,
facetime://, or facetime-audio:// URL, iOS displays a prompt and
requires user confirmation before dialing.
For security reasons, iOS requires users to confirm they want to perform the call before dialing in.
Is it possible to open the dialer in ios without showing the popup?
No, it is by design.
can we get the alert box cancel or call click event
You have to detect the state of phone call by yourself in the iOS project, you can write below codes in the AppDelegate:
CXCallObserver callObserver = new CXCallObserver();
callObserver.SetDelegate(new myDelegate(), DispatchQueue.MainQueue);
And in the delegate, you can check the call state:
public class myDelegate : ICXCallObserverDelegate
{
public IntPtr Handle => throw new NotImplementedException();
public void CallChanged(CXCallObserver callObserver, CXCall call)
{
if (call.Outgoing==true && call.HasConnected ==false)
{
Console.WriteLine("Dialing");
//use Messaging Center to send the state to Xamarin.forms Project.
}
if (call.Outgoing ==false && call.HasConnected == false)
{
Console.WriteLine("disconnect");
//use Messaging Center to send the state to Xamarin.forms Project.
}
//you can use other state to check the state...
//call.OnHold; call.HasEnded;
}
public void Dispose()
{
}
}
I am building an Android application with Xamarin Forms 3 in Visual Studio 2017 and publishing to Google Play. Google Play offers automated testing (pre-launch report) but it cannot get past my sign-in screen.
Google Play has a place to enter the "username resource name", "password resource name", and "sign-in button resource name". I provided the Xamarin x:name for each control (txtEmail, txtPass, and btnSignIn), but apparently that is not correct, because the automated tester still can't get in and isn't even trying.
Here is my SignIn.xaml:
<Entry x:Name="txtEmail" Placeholder="email address" Keyboard="Email" />
<Entry x:Name="txtPass" IsPassword="True" />
<Button x:Name="btnSignIn" Text="Sign In" Clicked="OnSignInClicked" />
I've found these SO questions (here, here, and here) but they do not address my question from within a Xamarin Forms context. The first link seems particularly helpful but I do not know where to put that XML code.
It seems to me that Xamarin/C# is "compiled" into Android code and generates these XML files. How can I work with this process?
I understand an .APK file is just a ZIP file. Renaming the APK file I send to Google Play to .zip I'm able to browse the contents, but I do not see any XML code that makes sense.
For the moment, I added an extra "demo" button that, on click, puts a username and password into the fields and clicks the Sign In button. Google's automated tester likes this and can get in, but it's a terrible idea for human testing and I'd like to remove this workaround.
I've faced the same issue recently. I submitted an alpha build, enabled pre-launch report and got a policy violation error saying, that sign-in credentials are not provided. As it's stated in the question, I should have provided resource names along with the test credentials, but it wasn't obvious how to do it in Xamarin.Forms project. Nevertheless, I was able to workaround it using renderers. I know, it's a bit extreme to create a separate renderer and a control just to set id, but I really didn't want to change UI significantly, so, I created 3 empty controls:
public class UsernameEntry : Entry { }
public class PasswordEntry : Entry { }
public class LoginButton : Button { }
And used each of them in corresponding places on the login screen, instead of plain entries and the button.
Then I added ids.xml file into the Android project (Resource/values/ids.xml) and added 3 ids, one for every control:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="username_entry" type="id"/>
<item name="password_entry" type="id"/>
<item name="login_button" type="id"/>
</resources>
Finally, I created 3 renderers in the native Android project, one for each control. For example, this is how the UsernameEntryRenderer looks:
[assembly: ExportRenderer(typeof(UsernameEntry), typeof(UsernameEntryRenderer))]
namespace Android.Renderers
{
public class UsernameEntryRenderer : EntryRenderer
{
public UsernameEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
// here I can reference the id created previously in ids.xml file
// and set the native android id property
Control.Id = Resource.Id.username_entry;
}
}
}
}
This is not the perfect way, but it worked well in my case. I didn't need to change the UI drastically or to introduce some hidden UI elements. Hopefully, this will be helpful for anyone facing similar problem.
Inspired by Yehor's answer, I was able to come up with a solution that uses Xamarin Effects without using custom controls.
First add ids.xml file into the Android project (Resource/values/ids.xml) and add 3 ids, one for every control. Make sure the Build action is set to AndroidResource and the Custom Tool is set to MSBuild:UpdateGeneratedFiles so the C# files can be generated automatically for the styles:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="username_entry" type="id"/>
<item name="password_entry" type="id"/>
<item name="login_button" type="id"/>
</resources>
Then define an enum so the effects can be defined easily:
public enum CustomIdType
{
None,
Username,
Password,
LoginButton
}
For the Android custom renderer, implement the following assign the android ID based on the custom effects.
[assembly: ResolutionGroupName("CustomRendererHandler")]
[assembly: ExportEffect(typeof(AndroidCustomIdEffect), "CustomIdEffect")]
namespace YOUR_ANDROID_NAMESPACE
{
public class AndroidCustomIdEffect : PlatformEffect
{
protected override void OnAttached()
{
// get autofill effect
var effect = (CustomIdEffect)Element.Effects
.FirstOrDefault(e => e is CustomIdEffect);
// assign android ID if custom ID effect is not null
if (effect != null) {
switch (effect.Type) {
case CustomIdType.Username:
Control.Id = Resource.Id.username_entry;
break;
case CustomIdType.Password:
Control.Id = Resource.Id.password_entry;
break;
case CustomIdType.LoginButton:
Control.Id = Resource.Id.login_button;
break;
}
}
}
protected override void OnDetached()
{
}
}
}
Then define a Routing Effect in your shared code to consume the Android custom renderer:
public class CustomIdEffect : RoutingEffect
{
public CustomIdType Type { get; set; }
public CustomIdEffect() : base("CustomRendererHandler." + nameof(CustomIdEffect))
{
}
}
Finally, to consume the Effects in your login page, simply add the Effects to the controls in XAML:
<Entry PlaceHolder="Enter Username">
<Entry.Effects>
<local:CustomIdEffect Type="Username"/>
</Entry.Effects>
</Entry>
<Entry PlaceHolder="Enter Password">
<Entry.Effects>
<local:CustomIdEffect Type="Password"/>
</Entry.Effects>
</Entry>
<Button Text="Login">
<Button.Effects>
<local:CustomIdEffect Type="LoginButton"/>
</Button.Effects>
</Button>
After that Google Pre-launch Report should be able to get pass the login screen if you provide the right sign-in credentials.
My app receives toast from PHP using WNS server. Now I want to perform some actions when clicking on toast as listed below.
When the app is not active - the user should redirect to a page on the app "ShowPage".
When the app is active - the toast should show two buttons "Show" and "Cancel". When clicking on Show button app should redirect to "ShowPage"
My current toast from PHP is
$toastMessage= '<?xml version="1.0" encoding="utf-8"?>'.
'<toast launch="">'.
'<visual baseUri="">'.
'<binding template="ToastGeneric">'.
'<text>'.$subtitle.'</text>'.
'</binding>'.
'</visual>'.
'<actions />'.
'</toast>';
And I'm calling below function on App.xaml.cs
private async void RegisterEngagementNotification()
{
StoreServicesEngagementManager engagementManager = StoreServicesEngagementManager.GetDefault();
await engagementManager.RegisterNotificationChannelAsync();
}
Please see the documentation for sending a local toast and handling activation. Everything applies there (other than you're sending the toast from your server, but otherwise adding buttons and handling activation remains the same).
I saw that you're using StoreServicesEngagementManager APIs, then I know you're sending toast notification from windows developer dashboard. So, if you want to your toast contains two buttons, you would need to add actions like the following:
Then, in your "App.xaml.cs" file, you would need to add some code to handle this option in OnActivated.
protected override void OnActivated(IActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
}
base.OnActivated(args);
var toastActivationArgs = args as ToastNotificationActivatedEventArgs;
if (toastActivationArgs.Argument =="ShowPage")
{
rootFrame.Navigate(typeof(ShowPage));
}
}
I'm working on a Visual Studio extension which would benefit from being loaded when the IDE's start page is opened, but I cannot find an event that is fired when the start page is opened that my extension can subscribe to.
I know I can add the following attribute to my vsix package that will fire when the IDE is opened, but I am looking for something more specific to the start page itself.
[ProvideAutoLoad(UIContextGuids80.NoSolution)]
Is there an event that is fired when either the default start page or a custom the start page is opened ?
You can subscribe to DTE.Events.WindowEvents.WindowCreated event and check that the window title is Start Page.
I got this working in the end by subscribing to the WindowVisibilityEvents (courtesy of this old post from Carlos Quintero https://www.mztools.com/articles/2011/MZ2011010.aspx) and checking the window's type and title when it became visible.
The following is a cut-down version of the code in my vsix package class:
protected override void Initialize()
{
base.Initialize();
IServiceContainer serviceContainer = this as IServiceContainer;
EnvDTE.DTE dte = serviceContainer.GetService(typeof(SDTE)) as EnvDTE.DTE;
var events2 = (EnvDTE80.Events2)dte.Events;
EnvDTE80.WindowVisibilityEvents toolBoxWindowVisibilityEvents = events2.get_WindowVisibilityEvents();
toolBoxWindowVisibilityEvents.WindowShowing += WindowVisibilityEvents_WindowShowing;
}
private void WindowVisibilityEvents_WindowShowing(Window window)
{
if (window.Type == vsWindowType.vsWindowTypeToolWindow && window.Caption == "Start Page")
{
//Start page is opening...
}
}