I've been following:
https://developer.xamarin.com/guides/android/platform_features/maps_and_location/maps/obtaining_a_google_maps_api_key/
and
https://developer.xamarin.com/guides/android/platform_features/maps_and_location/maps/obtaining_a_google_maps_api_key/
in order to use Google maps in an android app. And I cannot get the maps to show in my application at all. It always shows a blank page. I'm also not seeing any errors.
I have:
Added the necessary permissions to my android manifest
Enabled the API in the apis page online.
Added credentials based on using the local debug keystore
Added the map as a mapfragment on my main activity page.
Everything online is pointing at the debug key being incorrect but I must have tried everything I can with this one and it still doesn't work. Could it be picking a different one up somehow?
Also, I'm not sure of the significance, but the mapfragment is always null in on resume when I try to access it.
Keystore command:
keytool -list -v -keystore "C:\Users\<My User folder>\AppData\Local\Xamarin\Mono for Android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
Permissions in manifest (With AppName and key hidden):
<!-- Google Maps for Android v2 requires OpenGL ES v2 -->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<!-- We need to be able to download map tiles and access Google Play Services-->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Allow the application to access Google web-based services. -->
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<!-- Google Maps for Android v2 will cache map tiles on external storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Google Maps for Android v2 needs this permission so that it may check the connection state as it must download data -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Permission to receive remote notifications from Google Play Services -->
<!-- Notice here that we have the package name of our application as a prefix on the permissions. -->
<permission android:name="APPNAME.permission.MAPS_RECEIVE" android:protectionLevel="signature" />
<uses-permission android:name="APPNAME.permission.MAPS_RECEIVE" />
<!-- These are optional, but recommended. They will allow Maps to use the My Location provider. -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application android:label="<app name>">
<!-- Put your Google Maps V2 API Key here. -->
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="MYKEY" />
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
</application>
Main activity contents:
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment" />
in order to use Google maps in an android app. And I cannot get the maps to show in my application at all. It always shows a blank page. I'm also not seeing any errors.
This is probably caused by following reasons:
Check the reference here How can I create a keystore?
Once the app is signed then the map won't work.
When you use a different computer to build the app please get the SHA-1 from the new computer.
Do not use the keystore that is generated by Java. Please use the keystore that is generated by Visual Studio. It is in C:\Users\username\AppData\Local\Xamarin\Mono for Android/.
Use the emulator that contains Google API.
Do not forget to enable Google API in Google Console.
And this Xamarin Android Google Map demo should be helpful for you. I have tried this demo with my own keystore and API_KEY and it works.
I have solved this problem by configuring my project in Google Console to Enable
Places SDK for Android
And
Maps SDK for Android
wait for few minutes and BOOM !
Sometimes you might need to reinstall the app on your device.
If you enable Google Play App Signing then you need to use the keystore detail that will be provided by after you have uploaded your apk.
Release management -> App signing (tab)
App signing certificate is what you need. Copy the SHA-1 certificate fingerprint.
The current answer didn't quite work for me. I misunderstood what the docs -https://learn.microsoft.com/en-us/xamarin/android/platform/maps-and-location/maps/obtaining-a-google-maps-api-key?tabs=windows - meant when it says:
This API KEY must be the API KEY from the google developer console and not the SHA-1 that you used to generate your keystore. While this might have been obvious to most of you, hopefully this helps some other user in the future.
Just for collection..
I faced with the same problem but after load my bundle file application through the Google Play Console...
I signed my application by my release keystore key and ... nothing. maps doesn't appeared in application downloaded and installing from Google Play.
So solution is in this archive topic (in the last post):
https://social.msdn.microsoft.com/Forums/en-US/ef283f57-676a-498a-afa6-74ac237391f1/google-maps-blank-on-release-mode?forum=xamarinandroid
"In my case, it turned out that Google Play Console signed the released apk with its own Google certificate, setting a SHA1 different to the one used to authorize the Google Maps API."
It's exactly weird... but any way.. After i download my app from bundle explorer and check SHA1 I was "surprised"... Just added this "new" SHA1 in my Google Cloud Platform for my "Restrict usage to your Android apps" section.. And Maps appeared for all versions..
That's all.
I will be glad if it help someone
Related
I have a solution consisting of a Windows Application Packaging Project that groups two other projects:
A UWP project, named UwpUI, which is the entry point of the package. It can also be launched by protocol activation.
A .NET framework project, named FrameworkLogic, declared as Fulltrust.
An AppServiceConnection connects the two projects and allows a bi-directional communication between them.
It works using a well known pattern, described in this blog post by Stefan Wick:
Uwp with desktop extension-part 3
The package.appxmanifest (of my app) contains this.
<Extensions>
<desktop:Extension
Category="windows.fullTrustProcess"
Executable="FrameworkLogic\FrameworkLogic.exe">
</desktop:Extension>
<uap:Extension Category="windows.appService">
<uap:AppService Name="BidirectionalCom" />
</uap:Extension>
<uap:Extension Category="windows.protocol" Executable="UwpUI.exe"
EntryPoint="UwpUI.App">
<uap:Protocol Name="protoLaunch" />
</uap:Extension>
The uwp starts the fulltrust process like that:
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
In the entrypoint of the fulltrust .net framework, the connection is made with:
Connection = new AppServiceConnection();
Connection.AppServiceName = "BidirectionalCom";
var familyName = Package.Current.Id.FamilyName;
Connection.PackageFamilyName = familyName;
Connection.RequestReceived += Connection_RequestReceived;
Connection.ServiceClosed += Connection_ServiceClosed;
AppServiceConnectionStatus status = await Connection.OpenAsync();
opening the connection result in a call on the uwp side in the method
OnBackgroundActivated(BackgroundActivatedEventArgs args)
Where a reference to the connection is kept. Everything works.
The new requirement is this : set a console app (or a WPF app) as the package entry point.
If the package is launched without arguments, the new console app launches the uwp project by protocol activation. The bi-directional communication between the UWP and the .NET framework is instantiated and used.
If the app is launched with arguments (in my case, from the jumplist), then only the console app is used.
Adding the new project and setting it as the package entry point results in the following error:
DEP0700: Registration of the app failed. [0x80073CF6] AppxManifest.xml(44,10): error 0x80080204: Cannot register the package because the extension is missing an EntryPoint or StartPage attribute.
The solution on this SO post got me further.
Seems logical : the appservice must be defined under the project that uses it, which is not the package's entrypoint anymore.
My package manifest now include a second app (UwpUI) and looks like this:
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
<uap:VisualElements DisplayName="Home" Description="Package" BackgroundColor="white" Square44x44Logo="Images\Square44x44Logo.png">
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.protocol" Executable="UwpUI.exe" EntryPoint="UwpUI.App" ><uap:Protocol Name="protoLaunch" />
</uap:Extension>
<desktop:Extension Category="windows.fullTrustProcess" Executable="FrameworkLogic\FrameworkLogic.exe">
</desktop:Extension>
</Extensions>
</Application>
<Application Id="App2" Executable="UwpUI.exe" EntryPoint="UwpUI.App">
<uap:VisualElements AppListEntry="none" DisplayName="Home" Description="Package" BackgroundColor="white" Square44x44Logo="Images\Square44x44Logo.png" Square150x150Logo="Images\Square150x150Logo.png">
<uap:DefaultTile ShortName="-TestApp-" Square71x71Logo="Images\SmallTile.png" Wide310x150Logo="Images\Wide310x150Logo.png" Square310x310Logo="Images\LargeTile.png"/>
<uap:SplashScreen BackgroundColor="white" Image="Images\SplashScreen.png" a:Optional="true"/>
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.appService" >
<uap:AppService Name="BidirectionalCom" uap4:SupportsMultipleInstances="false"/>
</uap:Extension>
</Extensions>
</Application>
Doing that works as far as launching the fulltrust project, and establishing the connection, with a call to OnBackgroundActivated(BackgroundActivatedEventArgs args). There, I can succesfuly send a request and get an answer.
But I hit two major problems:
Any (static or instance) field or event instantiated in app.xaml.cs of the UwpUI project is null when it is called from another method, including the reference to the connection.
Prior to the modification, in debug mode at least, I could set breakpoints in both the UWP and the .NET framework project by doing 'detach all', then 'attach to process'. Now When attaching, the .NET framework project is greyed out.
Any idea what I'm missing? Problem 1 is the worse, since it breaks the app, but I need to solve the two.
Thank you.
EDIT : When looking at Task Manager, I see two processes with the same entry point (UwpUI.exe). Indeed, breakpoints show me that the call to the uwp constructor ( App.xaml.cs.App()), is called twice.
That certainly explains problem 1: fields are set in one instance and are of course null in the second instance.
Seems I need to structure my manifest differently, but I have yet to find how.
EDIT: Example project Here
System.Net.WebException:
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.'
This is an error that occurs in my VS2022 solution when working with a self signed certificate and Android.
The case is the following:
It is an android app that runs on an local network, with a local https backend service. A certificate has been issued for this service by the domain admin. However, the domain is not an official CA (Certificate Authority). You then have to manually install a CA, via settings.
Part of the solution
What I did to solve this is adding the CA certificates to the Android device (via Settings > Security -> Encryption & Credentials -> Install a Certificate).
The web browser, in the android app, can now successfully access the https site, without warnings.
I still need help with
However the CA store is not accessible via the app unless it is configured via network-security-config: https://developer.android.com/training/articles/security-config#TrustingAdditionalCas
This is something that can be done in the Xamarin days like:
https://devblogs.microsoft.com/xamarin/cleartext-http-android-network-security/
https://nicksnettravels.builttoroam.com/android-certificates/#:~:text=Accessing%20the%20Android%20Certificate%20Store
But in MAUI I'm a bit lost, I don't see the right resources, mipmap, etc.
I would like to solve this issue with a one-liner like this:
[assembly: Application(UsesCleartextTraffic = true)]
...which can also be configured via the via network-security-config.
Is there a one-liner or can someone help me out configuring my network-security-config to get the CA store available in a MAUI solution?
After this suggestion of Gerald, "So you can still add a xml folder under Resources (under the Android folder that is)", I finally got it!
Add a network_security_config.xml file, under the Android folder, with:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<!-- Trust preinstalled CAs -->
<certificates src="system" />
<!-- Additionaly trusted user added CAs -->
<certificates src="user"/>
</trust-anchors>
</base-config>
</network-security-config>
And in your AndroidManifest.xml add the: android:networkSecurityConfig="#xml/network_security_config" attribute to your Application node.
So, add it to the already existing node, don't add a new one (or else you'll get strange errors):
And the trust anchor exception is gone, but I'm still curious if there is another way - without the network-security-config. ;-)
PS Don't forget to add the CA certificates to the Android device, as stated in the original question.
OK so I see a couple of things here and not sure what you're after exactly so let me go over it one by one.
Let's start with: if you can, please avoid using clear text traffic! ;)
UseClearTextTraffic Attribute
Then, the easy one, you want the [assembly: Application(UsesCleartextTraffic = true)] oneliner. You can totally still do that and actually you can now that throughout the whole project I think. But it makes the most sense in Android.
Notice how the attribute says assembly so it works for the whole assembly anyway and it doesn't really matter where you put it. That is how it typically works. However, in .NET MAUI there is already a [Application] attribute above the MainApplication, so open that and modify it like below.
namespace MauiAndroidClearText;
[Application(UsesCleartextTraffic = true)]
public class MainApplication : MauiApplication
{
// Your code
}
Network Security Config
Basically your separate Android project is now under the Platforms\Android folder. Everything you put there, even if it's not there by default, will still behave as it was in a separate Android project.
So you can still add a xml folder under Resources (under the Android folder that is), then add the network_security_config.xml file with:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.0.2.2</domain> <!-- Debug port -->
<domain includeSubdomains="true">xamarin.com</domain>
</domain-config>
</network-security-config>
And in your AndroidManifest.xml add the android:networkSecurityConfig="#xml/network_security_config" attribute to your Application node.
See a full sample here: https://github.com/jfversluis/MauiAndroidClearText
How you asked how you could trust a self signed root certificate (self signed CA) without needed to install in the device, I will share the code.
I am using a MAUI project that use .NET 6.
In the MAUI project, in platform/android/resources/raw, you have to copy your ca.crt certificate. It can have .crt or .pem extension. In my case, I use .crt.
The raw folder is not created by default, so you have to create this folder.
In platform/android/resources, you have to create the folder xml, so you will have platform/android/resources/xml folder. In this folder, add a new xml file, with this name: network_security_config.xml.
This file set the certificates in which you want to trust.
The code of this file is:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<!--NOTA: el subdominio es necesario porque si no no se podrĂ¡ instalar-->
<domain includeSubdomains="true">192.168.1.200</domain>
<trust-anchors>
<certificates src="#raw/ca"/>
</trust-anchors>
</domain-config>
</network-security-config>
The certificate is ca, with no extension, if not, it will give an error when you try to compile.
You have to include a subdomain, in my case, the IP of the server, because I am not inside a domain. If you don't set this, when you try to debug it doesn't start, gives problems.
You have to edit the file AndroidManifest.xml, this exists. The code of my file is this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:icon="#mipmap/appicon" android:roundIcon="#mipmap/appicon_round" android:supportsRtl="true"
android:networkSecurityConfig="#xml/network_security_config"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
You only need to add android:networkSecurityConfig="#xml/network_security_config" in the application entry. This tells that you will config the network security.
That's all, you can build the project and then the application will include the CA in the trusted certificates, so you don't need to install the certificate in the device.
You can also see the following documentation for more information:
https://developer.android.com/training/articles/security-config
If you have some question, tell me and I will try tohelp.
Hello and thanks in advance. I'm writing this question because I've been serching the internet for weeks now and i still can't find the answer to my question. I need to include runtime permissions in my android aplication but I can't find a workig way to do this. My main problem is that I don't know where to put the requestPermissions() function.
First you need to specified the permission that your app needs in AndroidManifest.xml file
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
After that you need to ensure the Xamarin.Android.Support.Compat NuGet package is included in your project because this package will backport permission specific APIs to older versions of Android.
If you are using Android 6.0 o later, you can check the permission or request in your activity using the method ContextCompat.CheckSelfPermission
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) == (int)Permission.Granted)
{
// We have permission.
}
else
{
// Storage permission is not granted. If necessary display rationale & request.
}
I am trying to integrate different files and links to the Cortana voice commands using C#. Most of the applications are working fine when i copy those particular files in the Cortana voice command application folder but i am unable to launch an *.exe file (copied in the same folder). The usual error i am getting is access denied even after launching VS as admin. I am attaching the code line along with the error screenshot.
{"Abrir NAV", (Action)(async () => {
StorageFile file = await Package.Current.InstalledLocation.GetFileAsync(#"Microsoft.Dynamics.Nav.Client.exe");
await Launcher.LaunchFileAsync(file);
})
},
Cortana Error
You could not launch executable file from your UWP app directly.
MSDN document has mentioned this point:
This API also imposes several restrictions on what types of files it can launch. Many file types that contain executable code, for example .exe, .msi, and .js files, are blocked from launching. This restriction protects users from potentially malicious files that could modify the system. From launcher documentation.
According to your description, your ".exe" file was contained in your UWP project. So, you could use the FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync() method to activate the full-trust Win32 component of an application from a Universal Windows app component in the same application package.
Please note the "full-trust" concept. You would need to declare "full-trust" for your ".exe" file in "Package.appxmanifest". For example:
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap= "http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
IgnorableNamespaces="uap mp rescap desktop">
<Applications>
<Application>
...
<Extensions>
<desktop:Extension Category="windows.fullTrustProcess" Executable="MyFiles\ConsoleApp1.exe"/>
</Extensions>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust"/>
</Capabilities>
</Package>
Then, in code, you could call this method to launch that ".exe" file.
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
I've been having issues with using Ads on xamarin for android, was hoping someone with more expertise could offer some advice.
This is the first App I have build using Xamarin Android, or at least attempted to. Within the layout I have left a space for an advert.
I've followed multiple guides including;
How to integrate AdMob ads in the latest MonoGame Android (XNA)?
https://blog.tommyparnell.com/admob-with-xamarin-part-1-banner-ads/
Both guides I've followed to the letter and I'm getting the same error each time I try to run the application
The syntax in my main activity is as follows;
AdRequest adRequest = new AdRequest.Builder().Build();
layout.LoadAd(adRequest);
When this is included, I get a runtime error as follows;
Caused by: md52ce486a14f4bcd95899665e9d932190b.JavaProxyThrowable: System.NullReferenceException: Object reference not set to an instance of an object
06-05 09:39:21.062 E/AndroidRuntime( 7212): at MyApp.Android.MainActivity.OnCreate (Android.OS.Bundle) [0x00028] in c:\Users\User\Dropbox\Projects\MyApp_Xamarin\MyApp.Android\MainActivity.cs:44
I have tried deleting and recreating the google play services reference.
I've ensured my manifest has the relevant activity tags within it
<activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />
I'm at a total loss. The error I'm receiving looks like a java error, although as I'm in the c# environment I can't directly access and debug this that I can tell.
After 3 days of getting no further with this issue I've turned to StackOverflow, if anyone can point me in the right direction I'd be very grateful!
I am using visual studio 2013
Cheers.
I've added admob to a Xamarin Forms app but not an XNA game. Here is a link to my app on github
var adMobElement = Element as AdMobBuddyControl;
if ((adMobElement != null) && (e.OldElement == null))
{
AdView ad = new AdView(this.Context);
ad.AdSize = AdSize.Banner;
ad.AdUnitId = adMobElement.AdUnitId;
var requestbuilder = new AdRequest.Builder();
ad.LoadAd(requestbuilder.Build());
this.SetNativeControl(ad);
}
Make sure to have this in your application tag of manifest:
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />
And this permission:
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
I kind of fumbled my way through it. You may not need everything that I mentioned but hopefully it can give you a starting point.