How to set system proxy in Android - c#

How to set system proxy setting for Android using C# in a MAUI application?
I have tried the following but no luck:
Java.Lang.JavaSystem.SetProperty("http.proxyHost", "127.0.0.1");
Java.Lang.JavaSystem.SetProperty("http.proxyPort", "8080");
I have set the following permission:
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

Related

Problems with AppServiceConnection when a third project is the package's entry point

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

How to set external storage writing runtime permission in android with xamarin.forms

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.
}

How to correctly enable UI access for a service?

I run a (C#) service that makes some keyboard output into other UI application, like a virtual keyboard would do.
Windows security (more precisely UIPI) restricts my service of doing this.
To bypass UIPI, I've created a manifest for my service with UIAccess flag set to "true" :
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="true" />
</requestedPrivileges>
</security>
</trustInfo>
Regarding the documentation, the service must respect two conditions to be elevated to UIAccess :
The service must be digitally signed
The service must be run from a secure location (only R/W access for administrators, like C:\Program Files)
My service respects those two conditions.
When I try to start my service, I get the following error :
Error 740: The requested operation requires elevation
I thought my service would get automatic elevation and be capable of running with UIAccess. What am I missing ?
Additional inflammations :
The service is running Local System account
The service is running with "asInvoker" execution level
I've tried to disable the following local policies : "Only elevate UIAccess applications that are installed in secure locations" and "Only elevate executable that are signed and validated"

Xamarin Google Maps Blank

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

"System.NullReferenceException: Object reference not set to an instance of an object" when trying to insert ads using google AdMob Xamarin Android

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.

Categories