Converting Kotlin app to Xamarin.Android application - c#

I am trying to translate a Kotlin (Android) application to Xamarin.Android application. I came across a function and not able to figure out what would be equivalent C# code would be.
fun loadDrawable(
activity: Activity,
imageUrl: String?,
#DrawableRes defaultImage: Int,
onLoaded: (image: Drawable) -> Unit) {
val imageToLoad = if (imageUrl.isNullOrEmpty()) defaultImage else imageUrl
Glide.with(activity)
.load(imageToLoad)
.error(defaultImage)
.centerCrop()
.into<CustomTarget<Drawable>>(object : CustomTarget<Drawable>() {
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
onLoaded(resource)
}
override fun onLoadCleared(placeholder: Drawable?) {
placeholder?.let { onLoaded(it) }
}
})
}
In the above function, I am not able to convert the last parameter (onLoaded: (image: Drawable) -> Unit) to the function.
This is how I am currently calling the above function in Kotlin
loadDrawable(requireActivity(), null, R.drawable.bg_default) {
_backgroundManager?.drawable = it
}
I would really appreciate if someone can help me figure out how to convert this code (or something equivalent in functionality in C#)
Thanks

I was able to achieve the same functionality using action delegate
Action<Drawable> onLoaded

Related

Swift Xcode AVMetadataMachineReadableCodeObject encoding versus C# Xamarin AVMetadataMachineReadableCodeObject

I am researching for a Barcode scanning application with iOS iPhone Camera.
I can use Swift to get the string data that I actually need from the image I scan. However, when using Xamarin with the Xamarin implementation of the AVFoundation.AVMetadataObject and AVMetadataMachineReadableCodeObject, I don't get all of the characters. The C# code appears to execute in the same way as the Swift code with two different results.
Example Xcode Swift:
if let metadataObject = metadataObjects.first {
guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
guard let stringValue = readableObject.stringValue else { return }
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
found(code: stringValue)
}
will render something like this: WHICH I WANT
[)>\u{1e}06\u{1d}1SMYDATA\u{1d}S1MYDATA\u{1d}1PMYDATA\u{1d}WMYDATA\u{1d}4LUS\u{1e}\u{4}
Example Xamarin Foundation Code:
var barcodeMetadataObject = transformedMetadataObject as AVMetadataMachineReadableCodeObject;
if (barcodeMetadataObject != null)
{
var barcodeOverlayPath = this.BarcodeOverlayPathWithCorners(barcodeMetadataObject.Corners);
metadataObjectOverlayLayer.Path = barcodeOverlayPath;
// If the metadata object has a string value, display it.
string textLayerString = null;
if (!string.IsNullOrEmpty(barcodeMetadataObject.StringValue))
{
textLayerString = barcodeMetadataObject.StringValue;
}
else
{
// TODO: add Descriptor (line 618 in original iOS sample)
}
will render something like this: WHICH I DO NOT WANT...I WANT THE ENTIRE CHARACTER SET
[)>061SMYDATAS1911500531PMYDATAWMYDATA
So I have this: (Xcode)
[)>\u{1e}06\u{1d}1SMYDATA\u{1d}S1MYDATA\u{1d}1PMYDATA\u{1d}WMYDATA\u{1d}4LUS\u{1e}\u{4}
Versus this:(Xamarin)
[)>061SMYDATAS1911500531PMYDATAWMYDATA
I am not understanding why the implementation in Xamarin would not be supplying all of the same characters of the scan when it essentially acts only as a wrapper.
Does anyone have any idea?

Parsing string as code in Unity3D (C#)

So I want to build this little code sandbox in Unity, which would allow me to teach students the basics of algorithmics and coding.
The idea would be for them to enter (very basic) code in a text box or something of the kind, and to observe the effects of their code onto objects present in a Unity scene. I'm pretty sure this has been done a million times, but I'd love to try my hand at this. The rub is, I have no idea where to start...
I guess the idea is that the string would be compiled into code & executed at runtime, at the press of a button.
I've read about numerous other questions on SO, and have come up with very diverse solutions such as using a C# parser, reflection, expression trees, CodeDom, etc.
From what I understood of all these (i.e., not much), CodeDom seemed more appropriate, but then I read that it only ran inside of Visual Studio and generated errors in public builds. So does that mean that this is going to be a problem within Unity3D (as it is based on Mono?)
Thank you for your help,
In the following case, you look for an existing method of the given name on the same script (you can easily convert it to another script or any script in the assembly (not recommended though)):
string actionStr = inputField.text;
Type t = this.GetType();
MethodInfo mi = t.GetMethod(actionStr);
if(mi == null)
{
ErrorMethod(actionStr + " method could not be found");
}else
{
mi.Invoke(this);
}
Another way would be to store all the methods in a dictionary (faster):
Dictionary<string, Action>dict = null;
void Start()
{
this.dict = new Dictionary<string, Action>();
this.dict.Add("dosomething", DoSomething);
}
void DoSomething(){}
public void OnActionCall(string inputFieldStr)
{
string str = inputFieldStr.ToLower();
if(this.dict.Contains(str) == false)
{
ErrorMethod(actionStr + " method could not be found");
return;
}
this.dict[str]();
}

ExcelDNA Parameter and Return Type Auto-conversion

I'd like to automatically try to convert input parameters from Excel-friendly types to ones that are useful in my AddIn and vice-versa back to Excel with the return values. For example, I'd like to define a an Excel function (as a C# method) like:
public static Vector<double> MyFunction(Vector<double> inputVector)
{
// do some stuff to inputVector
return inputVector
}
I'd like for it to convert my input params and return value 'behind the scenes', i.e. I define some generic conversion method for converting from object to Vector<double> and vice versa, and this is called before they are passed in/out of my defined method.
Is this possible? I found ParameterConversionConfiguration in the github repo but I'm not quite sure how to use it. Are there any examples or further documentation available? I can see that I might need to register my type conversions somehow, but I'm not sure how to proceed.
EDIT: After some more playing around, I did this to convert a return value from a Matrix to an array:
public class ExcellAddIn : IExcelAddIn
{
public void AutoOpen()
{
var conversionConfig = GetParameterConversionConfig();
}
static ParameterConversionConfiguration GetParameterConversionConfig()
{
var paramConversionConfig = new ParameterConversionConfiguration()
.AddReturnConversion((Matrix<double> value) => value.ToArray());
return paramConversionConfig;
}
}
But upon loading the .xll, Excel spits out an 'unsupported signature' error. Am I on the right track? What else do I need to do?
There's a complete sample add-in that uses these Excel-DNA Registration extensions here: https://github.com/Excel-DNA/Registration/tree/master/Source/Samples/Registration.Sample
Some details relevant to your question:
You actually need to get the function registrations, apply your conversion and the perform the registration in your AutoOpen:
public void AutoOpen()
{
var conversionConfig = GetParameterConversionConfig();
ExcelRegistration.GetExcelFunctions()
.ProcessParameterConversions(conversionConfig)
.RegisterFunctions();
}
You might want to suppress the default processing by adding an ExplicitRegistration='true' attribute in your .dna file:
<DnaLibrary Name="My Add-In" RuntimeVersion="v4.0" >
<ExternalLibrary Path="XXX.dll" ExplicitRegistration="true" .... />
</DnaLibrary>

Can someone share a sample code of iOS Xamarin PushKit in C#?

I am trying to implement PushKit in my ios app. However the Xamarin document for PushKit is very limited. Do you have a sample code how to use it in Xamarin C#? Thanks a lot.
You can get idea from following link
Swift Code
Binding
If you have pure swift code, then you can download sample code from below link.
Download
import UIKit
import PushKit
class AppDelegate: UIResponder, UIApplicationDelegate,PKPushRegistryDelegate{
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound]
application.registerForRemoteNotificationTypes(types)
self. PushKitRegistration()
return true
}
//MARK: - PushKitRegistration
func PushKitRegistration()
{
let mainQueue = dispatch_get_main_queue()
// Create a push registry object
if #available(iOS 8.0, *) {
let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
// Set the registry's delegate to self
voipRegistry.delegate = self
// Set the push type to VoIP
voipRegistry.desiredPushTypes = [PKPushTypeVoIP]
} else {
// Fallback on earlier versions
}
}
#available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
// Register VoIP push token (a property of PKPushCredentials) with server
let hexString : String = UnsafeBufferPointer<UInt8>(start: UnsafePointer(credentials.token.bytes),
count: credentials.token.length).map { String(format: "%02x", $0) }.joinWithSeparator("")
print(hexString)
}
#available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
// Process the received push
}
}

C# Namespace not found for DLL

Ok, I will preface this by saying I did do a look up and read a lot of similar questions and answers on here before posting this.
Background Info
Using Visual Studio Professional 2013
Goal:
This project is for my own amusement and to try to learn as much as I can.
I have a native C++ header file called BinaryTree.h which is just a simple data structure that uses recursive logic to build a binary search tree. It works quite well on its own.
I want to build a GUI in C# that uses this. (Its not really useful or practical, I just choose it, well because I wanted to. Also, while the logic inside the binary tree class is complex(ish), I only need to call 2 methods, a addNode method, and a toString method which return the max depth and number of nodes).
I choose using a c++/cli wrapper to accomplish this. Everything seemed to go well, the build was successful and a .dll file was created in the debug directory of my project.
Now, I started in on the C# side of things. I added the .dll file to references. However, when I typed in " using filename.dll;" I got an error saying "Type or namespace not found...".
To reiterate I did some researching. I found (it seemed in VS2010) that different target frameworks could cause this error. I checked mine, targets for both were net4.5, so that is not the problem.
Here is the code from my c++/cli wrapper. Perhaps it has something to do with using templates? Any help is appreciated.
#pragma once
#include "D:\Schoolwork 2015\Test Projects\CPPtoC#WrapperTest\CPPLogic\CPPLogic\BinaryTree.h"
using namespace System;
namespace BinaryTreeWrapper {
template<class Data>
public ref class BinaryTreeWrapperClass
{
public:
BinaryTreeWrapperClass(){ tree = new BinaryTree(); }
~BinaryTreeWrapperClass(){ this->!BinaryTreeWrapperClass(); }
!BinaryTreeWrapperClass(){ delete tree; }
//methods
void wrapperAddNode(Data)
{
tree->addNode(Data);
}
std::string wrapperToString()
{
return tree->toString();
}
private:
BinaryTree* tree;
};
}
Screenshot of the error:
EDIT
Ok, so here is a weird thing... my original file built just fine with the new code and produced a .dll file. However, I decided to try a fresh project since the namespace was still not being found. Upon moving the code over and trying to build, I've run into 4 errors:
Error 1 error C2955: 'BinaryTree' : use of class template requires template argument list
Error 2 error C2512: 'BinaryTree' : no appropriate default constructor available
Error 3 error C2662: 'void BinaryTree::addNode(Data)' : cannot convert 'this' pointer from 'BinaryTree' to 'BinaryTree &'
Error 4 error C2662: 'std::string BinaryTree::toString(void) const' : cannot convert 'this' pointer from 'BinaryTree' to 'const BinaryTree &'
I copied the code exactly, only changing the namespace to "TreeWrapper' and the class name to 'TreeWrapperClass'.
To help, I've include a snippet from my BinaryTree.h file. There is a bunch more that defines the 'NODE' class, but I didn't want to clutter it up more than i needed.
After further investigation, it appears the problem lies with using 'generic'. If I switch it all to 'template' it builds just fine, but then it can't be used as a reference in C# (getting the namespace error). I built a test project using very simple methods (no templates) and was able to use the .dll wrapper I made in C#. So the problem lies with templates and generics.
Last Edit
I've found if I change the code to initiate the template as 'int' it works just fine, and I can use it in C#. For example:
...
BinaryTreeWrapperClass(){ tree = new BinaryTree<int>(); }
....
private:
BinaryTree<int>* tree;
BinaryTree.h
template<class Data>
class BinaryTree
{
private:
Node<Data>* root;
unsigned int nNodes;
unsigned int maxDepth;
unsigned int currentDepth;
void traverse(Node<Data>*& node, Data data);
public:
BinaryTree();
~BinaryTree();
void addNode(Data);
std::string toString() const
{
std::stringstream sstrm;
sstrm << "\n\t"
<< "Max Depth: " << maxDepth << "\n"
<< "Number of Nodes: " << nNodes << "\n";
return sstrm.str(); // convert the stringstream to a string
}
};
template<class Data>
BinaryTree<Data>::BinaryTree() //constructor
{
//this->root = NULL;
this->root = new Node<Data>(); //we want root to point to a null node.
maxDepth = 0;
nNodes = 0;
}
template<class Data>
BinaryTree<Data>::~BinaryTree() //destructor
{
}
template<class Data>
void BinaryTree<Data>::addNode(Data data)
{
traverse(root, data); //call traverse to get to the node
//set currentDepth to 0
currentDepth = 0;
}
template<class Data>
void BinaryTree<Data>::traverse(Node<Data>*& node, Data data)
{
//increment current depth
currentDepth++;
if (node == NULL) //adds new node with data
{
node = new Node<Data>(data);
//increment nNode
nNodes++;
//increment maxDepth if current depth is greater
if (maxDepth < currentDepth)
{
maxDepth = currentDepth - 1; //currentDepth counts root as 1, even though its 0;
}
return;
}
else if (node->getData() >= data) //case for left, getData must be bigger. The rule is, if a number is equal to getData or greater, it is added to the left node
{
Node<Data>* temp = node->getLeftNode();
traverse(temp, data); //recursive call, going down left side of tree
node->setLeftNode(temp);
}
else if (node->getData() < data) //case for right, getData must be less
{
Node<Data>* temp = node->getRightNode();
traverse(temp, data);
node->setRightNode(temp);
}
return;
}
You're declaring a template, but are not actually instantiating it. C++/CLI templates are just like C++ templates - if you don't instantiate them, they just don't exist outside of the compilation unit.
You're looking for generics here (yes, C++/CLI has both templates and generics). And here's how you declare a generic in C++/CLI:
generic<class Data>
public ref class BinaryTreeWrapperClass
{
// ...
}
But you'll get stuck at this point for several reasons.
First, I'll include the parts which are OK:
generic<class Data>
public ref class BinaryTreeWrapperClass
{
public:
BinaryTreeWrapperClass(){ tree = new BinaryTree(); }
~BinaryTreeWrapperClass(){ this->!BinaryTreeWrapperClass(); }
!BinaryTreeWrapperClass(){ delete tree; }
private:
BinaryTree* tree;
};
You've got this right.
Next, let's look at:
std::string wrapperToString()
{
return tree->toString();
}
That's no good, since you're returning an std::string - you don't want to use that from C#, so let's return a System::String^ instead (using marshal_as):
#include <msclr/marshal_cppstd.h>
System::String^ wrapperToString()
{
return msclr::interop::marshal_as<System::String^>(tree->toString());
}
Here, that's much better for use in C#.
And finally, there's this:
void wrapperAddNode(Data)
{
tree->addNode(Data);
}
See... here you'll have to do some real interop. You want to pass a managed object to a native one for storage. The GC will get in your way.
The GC is allowed to relocate any managed object (move it to another memory location), but your native code is clueless about this. You'll need to pin the object so that the GC won't move it.
There are several ways to do this, and I don't know what BinaryTree::addNode looks like, but I'll just suppose it's BinaryTree::addNode(void*).
For long-term object pinning, you can use a GCHandle.
The full code looks like this:
generic<class Data>
public ref class BinaryTreeWrapperClass
{
public:
BinaryTreeWrapperClass()
{
tree = new BinaryTree();
nodeHandles = gcnew System::Collections::Generic::List<System::Runtime::InteropServices::GCHandle>();
}
~BinaryTreeWrapperClass(){ this->!BinaryTreeWrapperClass(); }
!BinaryTreeWrapperClass()
{
delete tree;
for each (auto handle in nodeHandles)
handle.Free();
}
void wrapperAddNode(Data data)
{
auto handle = System::Runtime::InteropServices::GCHandle::Alloc(
safe_cast<System::Object^>(data),
System::Runtime::InteropServices::GCHandleType::Pinned);
nodeHandles->Add(handle);
tree->addNode(handle.AddrOfPinnedObject().ToPointer());
}
System::String^ wrapperToString()
{
return msclr::interop::marshal_as<System::String^>(tree->toString());
}
private:
BinaryTree* tree;
System::Collections::Generic::List<System::Runtime::InteropServices::GCHandle>^ nodeHandles;
};
This allocates a GCHandle for each node, and stores it in a list in order to free it later. Freeing a pinned handle releases a reference to the object (so it becomes collectable if nothing else references it) as well as its pinned status.
After digging around I think I found the answer, although not definitively, so if anyone can chime in I would appreciate it. (Apologies in advance for any misuse of vocabulary, but I think I can get the idea across).
It seems the problem lies in the fundamental difference between templates in native C++ and generics. Templates are instantiated at compilation, and are considered a type. They cannot be changed at runtime, whereas generics can. I don't think there is an elegant way to solve that.
At least I accomplished one goal of my project, which was learning as much as I can haha. I was able to get c++/cli wrappers working for things without templates, and if I choose a type for the template before building the .dll (see above)
If anyone else has an idea please let me know.

Categories

Resources