How do I use the AppGlideModule in Xamarin.Android? - c#

Using the Glide library on Xamarin.Android, I was hoping someone could shed some light on how to use the AppGlideModule. According to the documentation, I need to register my custom ModelLoader using the AppGlideModule.
Here is a link to the example in the Glide documentation:
http://bumptech.github.io/glide/tut/custom-modelloader.html#writing-the-modelloader
Here is my custom AppGlideModule class:
public class MyCustomGlideModule : AppGlideModule
{
public override void ApplyOptions(Context context, GlideBuilder builder)
{
base.ApplyOptions(context, builder);
}
public override void RegisterComponents(Context context, Glide glide, Registry registry)
{
registry.Prepend(
Java.Lang.Class.FromType(typeof(Java.IO.OutputStream)),
Java.Lang.Class.FromType(typeof(Drawable)),
new MyCustomImageStreamModelLoaderFactory()
);
}
}
I don't know if it's necessary, but if you'd like to see the classes I made for the ModelLoader, please let me know in the comments.

Old question but here is the trick. You will need to create an Android/Java library that contains an AppGlideModule wrapper. This library contains nothing else and is simply used to generate the GlideApp class. It needs to contain a static instance of your final AppGlideModule. Basically, it will look like this :
#GlideModule
public class XamarinGlideModule extends AppGlideModule {
public static AppGlideModule InjectedModule;
#Override
public void registerComponents(Context context, Glide glide, Registry registry) {
if(InjectedModule != null) {
InjectedModule.registerComponents(context, glide, registry);
}
}
}
You will then need to wrap this library in an Android binding library. Nothing is worthy of mention in this step, simply drop your built AAR in the binding project, add the matching version of the Glide Nuget and build.
You can then add a reference to that binding library in your app project. In your Android Application class, you will need to setup the InjectedModule static property to inject your Xamarin implementation. You must do this before any call to Glide, something similar to this :
public override void OnCreate()
{
base.OnCreate();
XamarinGlideModule.InjectedModule = new MyLoaderModule();
var temp = GlideApp.Get(this); // Init Glide, it will register your Xamarin module
}

Now there's one more option to use custom glide module from C# code. Just install package of this project:
https://github.com/KDD-Digital-Healthcare-GmbH/Kdd.Glide.AppModuleInjector
NOTE: if you need custom AppModule for glide just to accept self-signed certificates, you can install this package as well, it already has implementation of such module:
https://github.com/KDD-Digital-Healthcare-GmbH/Kdd.Glide.UnsafeUrlLoadingAppGlideModule

Related

Use android package manager in Xamarin.Forms

Trying to check if a particular application is installed in the android phone or not.
In android studio, I used Package manager to get the installation status of the application. But I need to use Xamarin.Forms for development.
yes,you could use DependencyService to achive this:
first,define a Interface :
public interface IsInstallApplication
{
bool IsInstall(string packageName);
}
then in Droid.project create a class which implement the interface :
[assembly: Dependency(typeof(AndroidIsInstallApplication))]// do not miss the line
namespace App18.Droid
{
class AndroidIsInstallApplication : IsInstallApplication
{
public bool IsInstall(string packageName)
{
... //here you could use Package manager to get the installation status of the application like in native android
return true;
}
}
}
finally you could call it in you page like :
DependencyService.Get<IsInstallApplication>().IsInstall(packageName);

Is there a cleaner method of making COM visible applications?

Given a specific class:
public class Klass
{
public int value;
public void doSomething(){
return;
}
}
To make said class COM visible, as far as I know, one needs to do a few things:
Import System.Runtime.InteropServices
Create an interface for the class.
Extend the interface created.
Create 2 unique GUIDs, one for the Interface and another for the class.
Add Dispatch IDs to the interface.
Producing something like:
[Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
public interface IKlass
{
[DispId(0)]
public int value;
[DispId(1)]
public void doSomething();
}
[Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938"),
ClassInterface(ClassInterfaceType.None)]
public class Klass : IKlass
{
public int value;
public void doSomething(){
return;
}
}
The resulting code looks utterly gross in my opinion... The question is, is there a simple cleaner method of creating these COM interfaces? I can imagine modifying the build process myself to give a interop feature. E.G.
public interop class Klass
{
public interop int value;
//...
}
However, this is non-standard, which has it's issues as well. Is there anything built-in to Visual Studio / C# that I can use to make building COM interfaces easier/cleaner?
As suggested by Zohar Peled the best way is to use RegAsm.exe:
Create some C# class library "TestProject":
using System.Windows.Forms;
namespace TestProject
{
// Note. Only public classes are exported to COM!
public class Test
{
// Note. Only public methods are exported to COM!
public void testIt() {
MessageBox.Show("Yellow world");
}
}
}
IMPORTANT:
Only public classes are exported to COM. And only public methods of these classes are available via a COM object instance.
Sign the project.
In AssemblyInfo.cs set [assembly: ComVisible(false)] to [assembly: ComVisible(true)]. Note: You can also use attribute [ComVisible(true)] before each class you want to expose to COM. This just sets the default to true making it easier to work with if building an API
Build the project.
Run regasm. Remember to use the correct version of Regasm (32-bit/64-bit) and the version for your .NET framework:
# .NET v4.5 64-bit
"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe" -tlb -codebase "C:\Users\sancarn\Desktop\tbd\TestProject\TestProject\bin\Debug\TestProject.dll" -verbose
# .NET v4.5 32-bit
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe" -tlb -codebase "C:\Users\sancarn\Desktop\tbd\TestProject\TestProject\bin\Debug\TestProject.dll" -verbose
...
Regasm should output something like this:
Microsoft .NET Framework Assembly Registration Utility version 4.7.3056.0
for Microsoft .NET Framework version 4.7.3056.0
Copyright (C) Microsoft Corporation. All rights reserved.
Types registered successfully
Type 'TestProject.Test' exported.
Assembly exported to 'C:\Users\sancarn\Desktop\tbd\TestProject\TestProject\bin\Debug\TestProject.tlb', and the type library was registered successfully
Now you can test the file in VBScript for example:
Dim o As Object
Set o = CreateObject("TestProject.Test")
Call o.testIt
Sancarn answers your question, but note that this makes ALL COM-compatible classes in your project COM-visible as well, which you might not want (see here and here). If you do not explicitly set the UUIDs you are opening yourself up to problems when you deploy if you access the classes with early-bound clients like VB or VBA (not VBScript, which is late-bound).
Yes it's not "clean" but neither is COM, especially when you want to expose it to late-binding clients live VBScript.
I would also change your public field to a property, which is more standard for public members:
[Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
public interface IKlass
{
[DispId(0)]
public int value {get; set;}
[DispId(1)]
public void doSomething();
}

Cant find IConnectionIdFactory in my assembly

I am trying to extend my CreateConnectionId function to add custom logic when creating ConnectionId's in signalR
public class MyConnectionFactory : IConnectionIdFactory
{
public string CreateConnectionId(IRequest request){
//Code Goes Here
}
}
but IConnectionIdFactory will not be resolved in my intellisense because it cannot find it in my assembly. I have the following References in my References folder:
SignalR, SignalR.Hosting.AspNet, SignalR.Ninject
It was renamed in a recent version. The IConnectionIdFactory interface was renamed to IConnectionIdGenerator.
You can find the interface under the SignalRnamespace.
Your code should look like this instead:
public class MyConnectionFactory : IConnectionIdGenerator
{
public string GenerateConnectionId(IRequest request)
{
return "some generated ID";
}
}
I'm guessing you're looking at some old samples somewhere? What version of SignalR are you referencing? I believe that's a rather old interface pre-dating the MessageBus rework that was done. I believe the interface you're looking for now is IIdGenerator.

Where does OnAfterInstall event go?

I've had serious problems on how to solve this: I don't know where the OnAfterInstall event goes.
Let me explain myself. I created a C# project which compiles perfectly and built in Release mode. After that, I've created a Setup Project using the wizard. I have added an extra dialog, which lets the user choose between two languages. Now, my problem is that I want to store that language into the registry (or app.config file, the easier the better), and I've read that you need to detect it within the OnAfterInstall method in an inherited class of Installer.
Now, where should I put that class? Logic tells me it goes in the C# project, but it complains that neither Context nor Installer class exist. When I add this class to the Setup Project, it doesn't complain, but it doesn't work after that. Here's the class.
using System;
using System.Configuration.Install;
public class Install : Installer
{
public Install()
{
}
protected override void OnAfterInstall(IDictionary savedState)
{
string lang = Context.Parameters["lang"];
RegistryKey key = Registry.LocalMachine;
using (key = key.CreateSubKey(#"SOFTWARE\MyCompany\MyApp"))
{
key.SetValue("lang", lang);
key.Close();
}
base.OnAfterInstall(savedState);
}
}
PS: I'm already passing lang as CustomActionData using /lang=[LANG] (where LANG is the radio value)
First, you should add the RunInstallerAttribute to you class.
[RunInstaller(true)]
public class Install : Installer
...
Next, put the installer in a separate project (class library), e.g. MyCustomInstaller.
Finally, add the primary output of this project to a custom action in the custom actions editor of the setup project.
It's up to you in which custom action you want to use.

Dependency Injection - Choose DLL and class implementation at runtime through configuration file

I've an API DLL (API.dll, for example) which, in addition to many other thinks, makes available an abstract class (AbstractClass).
Now making use of that AbstractClass I've implemented it on two different dlls:
First.API.Implementation.dll with ConcreteImplementation1
Second.API.Implementation.dll with ConcreteImplementation2
Both ConcreteImplementation1 and ConcreteImplementation2 are implementation of the same abstract class.
What I want is an application where I can choose which of those two dlls to use and, through that, choose which implementation to use without the user having to change anything within the code and, if possible, without stopping the application.
Some configuration file where I can bring the application to use whatever implementation I want. Something like:
<appconfiguration>
<implementation_to_use>
<dll>First.API.Implementation.dll</dll>
<class>ConcreteImplementation1</class>
</implementation_to_use>
</appconfiguration>
I know near to nothing about dependency injection, apart from its concept, but I guess thats the perfect fit for this task.
I've researched several DI/IoC libraries but I'm not familiar with all the concepts and names. I can use whatever library I want. For what I can say these are the most used: StructureMap, Ninject and Sprint.NET
Moreover, apart from all the dlls and implementation I need to indicate a file to be used by that application. Can I indicate its path in that same file?
I just need some tips and directions to implement such a thing. Some examples using one of those libraries, would be awesome.
Thanks.
To get you started using StructureMap, create a console application, include in it:
structuremap.config:
<?xml version="1.0" encoding="utf-8" ?>
<StructureMap MementoStyle="Attribute">
<DefaultInstance
PluginType="DemoIoC.AbstractBase,DemoIoC"
PluggedType="DemoIoC.ConcreteImplementation1,DemoIoC"
Scope="Singleton" />
</StructureMap>
The PluginType and PluggedType attributes are "FullyQualifiedClassName,AssemblyName"
By default it will look for assemblies in the executable folder, I'm not sure how you would specify another location for the assemblies
There are plenty of options for Scope, e.g. Singleton, Transient, etc
Program.cs:
namespace DemoIoC
{
using System;
using StructureMap;
public static class Program
{
public static void Main(string[] args)
{
// here you initialize structuremap from the config file.
// You could probably use a FileSystemWatcher to reinitialize
// whenever the structuremap.config file changes
ObjectFactory.Initialize(x =>
{
x.UseDefaultStructureMapConfigFile = true;
});
var concrete = ObjectFactory.GetInstance<AbstractBase>();
concrete.Method1();
Console.ReadKey(true);
}
}
}
AbstractBase.cs:
namespace DemoIoC
{
public abstract class AbstractBase
{
public abstract void Method1();
}
}
ConcreteImplementation1.cs:
namespace DemoIoC
{
using System;
public class ConcreteImplementation1 : AbstractBase
{
public override void Method1()
{
Console.WriteLine("Called ConcreteImplementation1");
}
}
}

Categories

Resources