I'm working on a Xamarin Forms app which has two projects, an Android App and an iOS app. All the other code is stored in shared projects.
Solution looks like this:
MyApp.Android (Android project), references MyApp.Base
MyApp.iOS (iOS project), references MyApp.Base
MyApp.Base (Shared project)
I am using the following code to read an SVG image from the shared project:
using (var stream = GetType().Assembly.GetManifestResourceStream("MyApp.Base.image.svg"))
{
// do work here...
}
This works perfectly when the image is in the Android or iOS project, but I want the image to be shared so I put it in the shared project.
GetType().Assembly return MyApp.Android, thus it cannot find the image. I suppose I'm overlooking something but I haven't been able to find a solution.
Can anyone point me in the right direction? Thanks!
You are using the Shared Project NOT the PCL or .Net Standard library. So, all of your Shared Project contents will get merged into the Platform specific project when you Compile them. That means - even if you Embed your resource in your MyApp.Base that will get merged into .iOS/.Droid project.
I suggest you to learn more about Shared Project vs PCL or .Net Standard library.
Below code; I did't tested but this is the direction that you should follow:
#if __IOS__
var resourcePrefix = "MyApp.iOS.";
#endif
#if __ANDROID__
var resourcePrefix = "MyApp.Android.";
#endif
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(SharedPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream
(resourcePrefix + "image.svg");
For more information please look into this page : https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/files?tabs=macos#embedding-in-shared-projects
Related
Trying to make a cross-platform application library that will be able to work on UWP, Winforms, Wpf, Android and iOS.
Using NetStandard2.0
I've been using Xamarin Forms to test the library because of the cross-platform option but something I want to do is to get hardware information and emulate the devices such as Audio output.
I can't find a way that works across all platforms/devices only ones that target specific. And I can't find a way to run specific code or use a specific library based on the platform that is running.
Targeting multiple frameworks don't work because they cause errors in all the other files.
Tried creating separate libraries that are specifically targeting a platform like UWP, Android and iOS separately but when referencing them, I get a not supported errors:
Project ****.UWP is not compatible with netstandard2.0 (.NETStandard,Version=v2.0).
Project ****.UWP supports: uap10.0.17763 (UAP,Version=v10.0.17763)
stuff like that and for each project (UWP, Android and iOS)
What can I do?
Targeting multiple frameworks don't work because they cause errors in all the other files. Tried creating separate libraries that are specifically targeting a platform like UWP,
The platform specific code can't be used into share library directly. for calling native api for each platforms. the better way is using DependencyService to approach. And here is official document that you could refer to.
And the other way is using Conditional Compilation
For example
public static string DatabaseFilePath
{
get
{
var filename = "TodoDatabase.db3";
#if SILVERLIGHT
// Windows Phone 8
var path = filename;
#else
#if __ANDROID__
string libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
#else
#if __IOS__
// we need to put in /Library/ on iOS5.1 to meet Apple's iCloud terms
// (they don't want non-user-generated data in Documents)
string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); // Documents folder
string libraryPath = Path.Combine (documentsPath, "..", "Library");
#else
// UWP
string libraryPath = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
#endif
#endif
var path = Path.Combine(libraryPath, filename);
#endif
return path;
}
}
I am making a mobile app. In my Solution I have a shared project. Some of the files I do not want to be used in my iOS or Android builds.
My code looks something like this:
#if __MOBILE__
#else
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Queues;
using Azure.Storage.Queues.Models;
using System;
namespace Blah.Utils
{
public static class AzureBlobService
{
public static async Task<string> CreateCloudQueue(string connectionString, string queueName)
{
// blah
}
}
}
#endif
This doesn't seem to be removing this file for my mobile apps. It still wants me to get those
nuget Azure.Storage packages. How can I get that #if to work the way I want it to?
Well after struggling with this for a long time and thinking it must be some obscure setting somewhere...it was because my shared library was being referenced by a project in between my mobile app project.
So in other words the projects were referencing each other like this:
Sharedproject <--- CoreLib proj <--- Mobile app proj
And I wasn't putting MOBILE in the 'Conditional Compilation Symbol' in the CoreLib proj properties.
ugh
My question is similar to this one, although it doesn't really address my issue.
I am working on some new AWS Lambda functions, and I would like to keep their implementation in separate class libraries for reuse. I'm testing this concept using two solutions:
A solution with a single .NET Standard class library project. This class library has a reference to HTML Agility Pack.
A solution with a single .NET Core 2.0 console application project.
Class library:
using System;
using HtmlAgilityPack;
namespace ClassLibrary1
{
public class Class1
{
public static bool FoundDotNet(string html)
{
bool foundDotNet = false;
HtmlDocument document = new HtmlDocument();
document.LoadHtml(html);
var titleNode = document.DocumentNode.SelectSingleNode("//title");
if (titleNode != null)
{
string titleText = titleNode.InnerText;
if (titleText.ToLower().Contains(".net"))
{
foundDotNet = true;
}
}
return foundDotNet;
}
}
}
Console application:
using System;
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
var foundDotNet = ClassLibrary1.Class1.FoundDotNet("<html><head><title>.NET WTF Buddy</title></head><body>You're doin' me a confuse.</body></html>");
Console.WriteLine(foundDotNet);
}
}
}
Both projects build without issue. However, the HTML Agility Pack assembly isn't copied into the Debug directory for either of the projects, and when I try to run the console application, I get Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'HtmlAgilityPack'
I have the package management format set to "PackageReference" for both projects, which I thought would handle the transitive dependency correctly. HTML Agility Pack is listed in the json.deps file, so I'm not sure what the problem is.
"HtmlAgilityPack/1.7.1": {
"dependencies": {
"System.Net.Http": "4.3.2",
"System.Xml.XPath": "4.3.0",
"System.Xml.XPath.XmlDocument": "4.3.0",
"System.Xml.XmlDocument": "4.3.0"
}
If I move the the class library project into the same solution as the console application, it works fine. What's preventing me from separating my code into separate solutions?
I'm using a large, complicated library in several solutions and the library has many transitive dependencies.
First, set up your library. Right click on the library's project name and choose Properties. About halfway down you'll see a tab labeled Packages. You can use that to auto-generate the NuGet package every time you rebuild the project. Just increment the version number. I use four position version numbering -- the first three are semver-style (major release, minor release, patch release), and the fourth one I increment manually for each new build.
I recommend creating a folder on your drive or network specifically for your local NuGet packages. You can create folders under that for each project. Then you point your debug and release build output to that project folder, and the NuGet package will be generated there, too.
Finally, back in Visual Studio, go to Tools -> Options -> NuGet Package Manager -> Package Sources and add that top-level folder as a package source.
From there it's simple -- open your NuGet dependencies in your consuming app. There's a drop-down at the top right where you can choose the package source. It will automatically search all the child folders and find whatever packages you've created. Now when you tweak your library, it's just a single click to update the client apps.
When I try to create a SQLite Database in the Xamarin Android Project, I get the following Exception.
System.Exception: Something went wrong in the build configuration.
This is the bait assembly, which is for referencing by portable
libraries, and should never end up part of the app. Reference the
appropriate platform assembly instead.
One thing I found already out is that I need SQLite.Net.SQLitePlatform for Android. I dont have the SQLite.Net Namespace.
I used the SQLite.net PCL NuGet package
https://www.nuget.org/packages/sqlite-net-pcl/
I am creating the DB Path in the MainActivity.cs of the Droid Project
var sqliteFilename = "timesheet.db3";
string libraryPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var path = Path.Combine(libraryPath, sqliteFilename);
In the Forms app I am trying to create the Database
database = new SQLiteConnection(databasePath);
database.CreateTable<TimeRecordEntity>();
please, I have a question about snap7.dll library. So long time I wanst be working in C#, so maybe I am doing something wrong. But is possible to use snap7 in C# WPF project as library or it was developed only for windows forms? Its stupid I know, but I am asking because I am not able to add snap7.dll into my project references. Thank you.
Downloaded and played around with the examples from http://snap7.sourceforge.net/
Looks like the console application doesn't reference the assembly directly.
This isn't a WPF vs Winforms thing. It is a managed vs unmanaged code thing.
There is a snap7.net.cs .net wrapper class file.
It references "snap7.dll" and exposes its functionality as a C# class. At runtime it will load the assembly using DllImport.
Copy both the snap7.net.cs file and the snap7.dll into your project.
Use the snap7 class methods/attributes in your code. Then update snap7.dll to copy to output directory, or use a post build event to copy the snap7.dll to your output directory.
EDIT: I want to restate you do NOT add reference to the snap7.dll directly using project -> references. The DllImport annotation of the wrapper class file will load it at runtime.