Xamarin Portable config file using PCLAppConfig - xamarin

I am trying to put a config file in the PCL portion of my IOS/Android app.
The documentation at: https://github.com/mrbrl/PCLAppConfig
suggests:
Assembly assembly = typeof(App).GetTypeInfo().Assembly;
ConfigurationManager.AppSettings = new ConfigurationManager(assembly.GetManifestResourceStream("DemoApp.App.config")).GetAppSettings;
I expect DemoApp is the assembly name of their sample app so I have:
using PCLAppConfig;
namespace LYG
{
public class App : Application
{
public App ()
{
Assembly assembly = typeof(App).GetTypeInfo().Assembly;
ConfigurationManager.AppSettings = new ConfigurationManager(assembly.GetManifestResourceStream("LYG.App.config")).AppSettings;
}
...
}
}
I get the following compile error:
/Users/greg/Projects/LYG/LYG/LYG.cs(122,122): Error CS1061: Type PCLAppConfig.ConfigurationManager' does not contain a definition forGetAppSettings' and no extension method GetAppSettings' of typePCLAppConfig.ConfigurationManager' could be found. Are you missing an assembly reference? (CS1061) (LYG)
This is my packages.config file:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="PCLAppConfig" version="0.3.1" targetFramework="portable45-net45+win8+wp8" />
<package id="PCLStorage" version="1.0.2" targetFramework="portable45-net45+win8+wp8" />
<package id="Xamarin.Forms" version="2.3.2.127" targetFramework="portable45-net45+win8+wp8" />
</packages>
I also tried with parentheses:
ConfigurationManager.AppSettings = new ConfigurationManager(assembly.GetManifestResourceStream("LYG.App.config")).AppSettings();
Why can't the GetAppSettings be found?

You need to add the PCLAppConfig nuget package to your PCL and platforms projects.
Then I take you are trying to use the resource based app.config;
I just updated the documentation to reflect the last version update.
then use:
Assembly assembly = typeof(App).GetTypeInfo().Assembly;
ConfigurationManager.Initialise(assembly.GetManifestResourceStream("DemoApp.App.config"));
in doubt, check the demo project on github : https://github.com/mrbrl/PCLAppConfig/tree/master/src/DemoApp

Related

Xamarin ... migration to .NET Standard 2.0 failed

I'm trying to migrate my PCL project to the new "net standard" but for now I failed.
Currently I got the following exception :
System.MissingMethodException: 'Method not found: 'Void Xamarin.Forms.Xaml.Internals.SimpleValueTargetProvider..ctor(System.Object[], System.Object, Xamarin.Forms.Internals.INameScope)'.'
It happend directly from the 'InitializeComponent' of a page where I have the following xaml tag:
<Image Source="{ns_uc:ImageResource i_home_on.png}"/>
where the 'ImageResource' is an extension marker, this one works like a charm in my PCL project. Here is a part of the definition :
public class ImageResourceExtension : IMarkupExtension
But this class is not called from my new .NET Standard project !
In the .csproj I have the following references, it should be enough ?
<PackageReference Include="System.ComponentModel" Version="4.3.0" />
<PackageReference Include="Xamarin.Forms" Version="3.4.0.1008975" />
So, if someone have an idea because I have already spend 2 days in this migration, without success :-(
BTW, it seems I'm not alone : https://forums.xamarin.com/discussion/101999/cant-use-imarkupextension-in-a-net-standard-library
Thanks for your help
1.System.ComponentModel is a NuGet package in some NetStandard versions.Try to install it if it doesn't exist.
2.You can use <Image Source="myImage.png"/> directly instead of using IMarkupExtension in .net standard project.
3.The implement of ImageResourceExtension maybe different in PCL project and .net standard 2.0 project. Here is an implement in official demo you can refer:
[ContentProperty("Source")]
class ImageResourceExtension : IMarkupExtension<ImageSource>
{
public string Source { set; get; }
public ImageSource ProvideValue(IServiceProvider serviceProvider)
{
if (String.IsNullOrEmpty(Source))
{
IXmlLineInfoProvider lineInfoProvider = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider;
IXmlLineInfo lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
throw new XamlParseException("ImageResourceExtension requires Source property to be set", lineInfo);
}
string assemblyName = GetType().GetTypeInfo().Assembly.GetName().Name;
return ImageSource.FromResource(assemblyName + "." + Source, typeof(ImageResourceExtension).GetTypeInfo().Assembly);
}
object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
{
return (this as IMarkupExtension<ImageSource>).ProvideValue(serviceProvider);
}
}
You can refer the demo below to fix your project.
Refer:Demo of ImageResourceExtension
Documents of Markup Extensions
I would follow James Montemagno's steps:
https://montemagno.com/how-to-convert-a-pcl-library-to-net-standard-and-keep-git-history/
I followed this video from the Xamarin show:
https://channel9.msdn.com/Shows/XamarinShow/Snack-Pack-15-Upgrading-to-XamarinForms-to-NET-Standard
I tried it on my own the first go around and failed miserably. The second go around I followed the instructions from the video exactly and everything worked.

Difficulties with using Flashlight/Torch in Xamarin.Forms (Xamarin.Android) Project

Problem
Errors and Exceptions when trying to Turn on flashlight/Torch on an Android device using Xamarin.Forms (Xamarin.Android project) app.
Please see the below code' comments for the errors and exceptions mentioned:
// Get CameraService - This works fine and gets the CameraService
CameraManager CamMgr = (CameraManager) Application.Context.GetSystemService(Context.CameraService);
// Get Cameras - This Returns 0 strings, eg. NULL, it should return id 0 and 1 for respectively back and front camera
string[] CamIdList = CamMgr.GetCameraIdList();
// Turn ON Camera Torch(Flashlight) on camera id 0 - This results in the exception: Unhandled Exception: Java.Lang.NoSuchMethodError: no method with name='setTorchMode' signature='(Ljava/lang/String;Z)V' in class Landroid/hardware/camera2/CameraManager;
CamMgr.SetTorchMode("0", true);
// Turn ON Camera Torch(Flashlight) on camera id 1 - This results in the exception: Unhandled Exception: Java.Lang.NoSuchMethodError: no method with name='setTorchMode' signature='(Ljava/lang/String;Z)V' in class Landroid/hardware/camera2/CameraManager;
CamMgr.SetTorchMode("1", true);
Android Manifest permissions:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto">
<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.camera.flash" />
<application android:label="Lommelygte.Android"></application>
</manifest>
Platform and Developing environment
I am using Visual Studio Community 2017 15.0.0-RTW+26228.4 version as IDE.
I am using Android namespace (Xamarin assembly): Android.Hardware.Camera2 to use Flashlight functionality.
My Xamarin.Forms Project is using PCL (Portable Class Library) for sharing code.
I am not using Xamarin.Forms Pre release nuget packages or libraries.
I am using Xamarin.Forms (Xamarin.Android project)
I am using Device Samsung Galaxy Note 2 LTE (GT7105) - Android 4.4.2 (Kitkat) - API Level 19 (has Camera flash functionality) to debug application on.
What I have tried to resolve the problem:
Installed Android API 19 SDK
Cleaned Project, Then cleaned Solution, then Rebuild Solution
Checked for new Xamarin.Forms stable release
Tried using decrecated API 21 namespace + class instead for flash: Android.Hardware.Camera.Open();
Researched Xamarin Documentation
Researhed Stackoverflow posts
Researched various blogs and other places
Changed Target Framework to the exact API 19 that my phone supports: 4.4.2 (kitkat)
Researched implementations in Java, to get an overview of how it natively is done.
Looked at the definition of the Android.Hardware.Camera2 namespace and verified that the SetTorchMode method exists there, as displayed here (I am sorry for the majority of the code not being presented correctly in a codeblock, having some trouble with that):
Assembly Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065
using System;
using Android.OS;
using Android.Runtime;
using Java.Interop;
using Java.Lang;
namespace Android.Hardware.Camera2
{
[Register("android/hardware/camera2/CameraManager", DoNotGenerateAcw = true, ApiSince = 21)]
public sealed class CameraManager : Java.Lang.Object
{
public override JniPeerMembers JniPeerMembers { get; }
protected override IntPtr ThresholdClass { get; }
protected override Type ThresholdType { get; }
[Register("getCameraCharacteristics", "(Ljava/lang/String;)Landroid/hardware/camera2/CameraCharacteristics;", "")]
public CameraCharacteristics GetCameraCharacteristics(string cameraId);
[Register("getCameraIdList", "()[Ljava/lang/String;", "")]
public string[] GetCameraIdList();
[Register("registerAvailabilityCallback", "(Landroid/hardware/camera2/CameraManager$AvailabilityCallback;Landroid/os/Handler;)V", "")]
public void RegisterAvailabilityCallback(AvailabilityCallback callback, Handler handler);
[Register("setTorchMode", "(Ljava/lang/String;Z)V", "", ApiSince = 23)]
public void SetTorchMode(string cameraId, bool enabled);
What I have not done yet
....
Hypothesis
I am suspecting that the Xamarin assembly that handles the Android.Hardware.Camera2 does not interface correctly with all the methods of the java implementation of the namespace, in particular the Class: Camera, Method: setTorchMode.
However I cant find a new stable Xamarin version that might solve the problem.
I also suspect that because the definition says API since 23 that the code won't work at runtime on my device, because it does not support API 23 and the definition seems to require it, so how do I get around this?
This is the exact register for the definition of said method:
[Register("setTorchMode", "(Ljava/lang/String;Z)V", "", ApiSince = 23)]
How can I solve this?
Do you need more information to help me figure out the issue?
Your phone is API 19, CameraManager was added in API 21 and CameraManager.setTorchMode was added in API 23. Thus, those methods can not be called when running on that phone.
You can perform runtime checks to determine which API levels to use:
if (Build.VERSION.SdkInt <= BuildVersionCodes.KitkatWatch)
{
if (PackageManager.HasSystemFeature("FEATURE_CAMERA_FLASH"))
{
camera = Camera.Open(); // `Camera camera` variable is held as the class level
var camParameters = camera.GetParameters();
camParameters.FlashMode = "FLASH_MODE_TORCH";
camera.SetParameters(camParameters);
camera.StartPreview(); // Turn on
//When done with flashlight:
//camera.StopPreview(); // Turn off
//camera.Dispose();
}
else
Log.Debug("SO", "Phone does not contain a flash....");
}
else
{
// Use API 21+ methods...
}
Note: Many phones that have a "torch" mode but are older than API 21, require a SurfaceView to be used so the camera will function properly and thus allow the flash to function. Add a SurfaceView to your UI, get a SurfaceHolder from it and attach the camera to it (camera.SetPreviewDisplay)

Get a Xamarin assembly build date on iOS, Android and OS X

In my code I need a Xamarin assembly build date. On Windows I can use linker time stamp. However on iOS this does not work. I guess it would not work on OS X too as Portable Executable header is specific to Windows.
There is also an option to embed a resource with a date, however I would like to avoid using resources in this particular project.
Are there any way to find a Xamarin assembly build date that works on iOS, Android and OS X?
One approach would be to use an MSBuild task to substitute the build time into a string that is returned by a property on the app. We are using this approach successfully in an app that has Xamarin.Forms, Xamarin.Android, and Xamarin.iOS projects.
If using msbuild, this can be an MSBuild inline task, while on Mac using xbuild, it will need to be an MSBuild custom task compiled for Mono.
EDIT:
Simplified by moving all of the logic into the build task, and using Regex instead of simple string replace so that the file can be modified by each build without a "reset".
The MSBuild inline task definition (saved in a SetBuildDate.targets file local to the Xamarin.Forms project for this example):
<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="12.0">
<UsingTask TaskName="SetBuildDate" TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
<ParameterGroup>
<FilePath ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs"><![CDATA[
DateTime now = DateTime.UtcNow;
string buildDate = now.ToString("F");
string replacement = string.Format("BuildDate => \"{0}\"", buildDate);
string pattern = #"BuildDate => ""([^""]*)""";
string content = File.ReadAllText(FilePath);
System.Text.RegularExpressions.Regex rgx = new System.Text.RegularExpressions.Regex(pattern);
content = rgx.Replace(content, replacement);
File.WriteAllText(FilePath, content);
File.SetLastWriteTimeUtc(FilePath, now);
]]></Code>
</Task>
</UsingTask>
</Project>
EDIT:
Added an MSBuild Exec step to remove readonly attribute. Gotta love TFS.
Invoking the MSBuild task (inline or compiled, inline approach is commented for xbuild) in the Xamarin.Forms csproj file in target BeforeBuild:
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. -->
<!--<Import Project="SetBuildDate.targets" />-->
<UsingTask AssemblyFile="$(MSBuildProjectDirectory)\BI.Framework.BuildExtensions.dll" TaskName="Some.Framework.BuildExtensions.BuildDateTask" />
<Target Name="BeforeBuild">
<Exec Command="attrib $(MSBuildProjectDirectory)\BuildMetadata.cs -r" />
<!--<SetBuildDate FilePath="$(MSBuildProjectDirectory)\BuildMetadata.cs" />-->
<BuildDateTask FilePath="$(MSBuildProjectDirectory)\BuildMetadata.cs" />
</Target>
The FilePath property is set to a BuildMetadata.cs file in the Xamarin.Forms project that contains a simple class with a string property BuildDate, into which the build time will be substituted:
public class BuildMetadata
{
public static string BuildDate => "This can be any arbitrary string";
}
Add this file BuildMetadata.cs to project. It will be modified by every build, but in a manner that allows repeated builds (repeated replacements), so you may include or omit it in source control as desired.
ADDED:
Here is a custom MSBuild task to replace the MSBuild inline task for when building with xbuild on Mac:
using System;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Some.Framework.BuildExtensions
{
public class BuildDateTask : Task
{
#region Methods
/// <summary>
/// Called automatically when the task is run.
/// </summary>
/// <returns><c>true</c>for task success, <c>false</c> otherwise.</returns>
public override bool Execute()
{
const string pattern = #"BuildDate => ""([^""]*)""";
var now = DateTime.UtcNow;
var buildDate = now.ToString("F");
var replacement = $"BuildDate => \"{buildDate}\"";
var content = File.ReadAllText(FilePath);
var rgx = new Regex(pattern);
content = rgx.Replace(content, replacement);
File.WriteAllText(FilePath, content);
File.SetLastWriteTimeUtc(FilePath, now);
return true;
}
#endregion Methods
#region Properties
[Required]
public string FilePath { get; set; }
#endregion Properties
}
}
Build this custom task for Release via xbuild, then copy the output custom task dll to the project directory of the project for which you want to set the build date.

xjc binding compiler configuration to add xmlns element to the package-info class?

I am using Gradle to generate jaxb classes in my project. Every thing is working fine but while marshalling the jaxb object we are seeing different namespaces prefixes like ns1, ns2 .. randomly in the output xml. But we dont want this and want to specify specific namespace prefixes for each namespace. I checked here and found the link 15772478 saying we have to have package-info class with xmlns element, How can i say to xjc binding compiler to add xmlns element with prifixes and namespaceURI? below is the gradle configuration i have to generate Jaxb classes from schemas.
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath:configurations.jaxb.asPath)
ant.jaxbTargetDir = jaxbTargetDir
ant.xjc(destdir: '${jaxbTargetDir}', binding: 'xjc-bindings/bindings.jaxb', extension: true) {
//arg(value: '-npa')
arg(value: '-readOnly')
arg(value: file('src/main/webapp/schemas/primary1.xsd'))
arg(value: file('src/main/webapp/schemas/primary2.xsd'))
arg(value: file('xjc-bindings/xjc-a.xsd'))
arg(value: file('xjc-bindings/xjc-b.xsd'))
}
sample package-info.java generated by xjc binding.
#XmlSchema(namespace = "urn:neustar:names:decedm:1.0")
package biz.neustar.dece.xml.jaxb.decedm;
import javax.xml.bind.annotation.XmlSchema;
I am expecting the package-info class like below.
#XmlSchema(namespace = "<someuri>",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns={
#XmlNs(prefix="someprefix" , namespaceURI = "<some uri>")
})
package biz.neustar.dece.xml.jaxb.core;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlSchema;
Can somebody please suggest me what is the configuration need to achieve this?
I don't want to use NamespacePrefixMapper to specify the prefixes.
You need to update you binding file like following. It will use eCH-0007 as prefix.
<?xml version="1.0"?>
<jxb:bindings version="1.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:namespace="http://jaxb2-commons.dev.java.net/namespace-prefix"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd
http://jaxb2-commons.dev.java.net/namespace-prefix http://java.net/projects/jaxb2-commons/sources/svn/content/namespace-prefix/trunk/src/main/resources/prefix-namespace-schema.xsd">
<jxb:bindings schemaLocation="eCH-0007-3-0.xsd">
<jxb:schemaBindings>
<jxb:package name="ch.ech.ech0007.v3" />
</jxb:schemaBindings>
<jxb:bindings>
<namespace:prefix name="eCH-0007" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
You can check complete example on this link Namespace-prefix.

compiler error "could not load embedded UI class EmbeddedUI.EmbeddedUI from assembly"

I'm trying to create an application using WIX 3.7 UI. If I assembly where my code is using. When compiling for .NET 4.0 I get the following error message:
SFXCA: Binding to CLR version v2.0.50727
Error: could not load embedded UI class EmbeddedUI.EmbeddedUI from assembly: CustomActions
I have tried different things in CustomAction.config. The current version is:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" />
</startup>
</configuration>
The class is implemented as follows:
public class HelloWorld : IEmbeddedUI
{
#region IEmbeddedUI Members
public bool Initialize(Session session, string resourcePath, ref InstallUIOptions internalUILevel)
{
System.Windows.Forms.MessageBox.Show("test256");
return true;
}
public MessageResult ProcessMessage(InstallMessage messageType, Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton)
{
return MessageResult.OK;
}
public void Shutdown()
{
}
#endregion
}
In the file Product.wxs:
<UI Id="Embedded">
<EmbeddedUI Id="MyTest" Name="CustomAction45CA.dll" SourceFile="..\CustomAction45\bin\Debug\CustomAction45CA.dll">
</EmbeddedUI>
</UI>
I'm using Visual Studio 2012.
When I switch from Framework in AssemblyProperties from 4.0 to 3.5 then everything works.
And the test with bootstrapper application works with framework 4.0.
I suspect that the MakeSfxCA.exe makes my dll broken. But I do not know what I can do. I have already experimented with MakeSfxCA.exe.config and x86 and x64.
I would be very grateful for any help
Error will be thrown only with EmbedddedUI. CustomAction from the same dll runs with message in installer log SFXCA: Binding to CLR version v4.0.30319

Resources