Android JetPack 2.1 released - Xamarin Support Added!

clock February 23, 2015 01:09 by author Administrator

As you may have see in our previous blog post, http://blog.androidjetpack.com/post/Android-DataGrid-Xamarin-Support-Added-Java-Binding-Project-Issues.aspx. we have been working on a Xamarin port of our Android JetPack DataGrid component. With 2.1 release, we have accomplished this!

API Changes

From an API perspective, there were a few changes, primarily to match the "Xamarin way" of doing things. Here are the API changes. They are very minimal, but if you are using sample code from previous versions, you may need to make these changes:

1) Removed com.flexicious.controls.core.IExtendedView#getEnabled() (Change this to .isEnabled())

2) Removed com.flexicious.controls.core.IExtendedView#setEnabled(java.lang.Boolean)

3) Removed com.flexicious.controls.interfaces.filters.IFilterControl.validateNow()

4) Minor interface changes to ISelectFilterControl, ITriStateCheckBoxFilterControl, IDataGridFilterColumn

5) Removed the toaster package, since we use built in Android Toast

6) Added setOnAllEventListener & getOnAllEventListener to FlexDataGrid. This allows you to do grid.AllEvent += delegate (Xamarin way, in case you dont want to use the regular event function call back mechanism). 

7) If you get errors in compiling StyleManager 

Please replace 

 grid.paddingBottom = 2;

              grid.paddingLeft = 2;

              grid.paddingRight = 2;

 

              grid.paddingTop = 2;

With: 

grid.cellPaddingBottom = 2;

              grid.cellPaddingLeft = 2;

              grid.cellPaddingRight = 2;

              grid.cellPaddingTop = 2;

 

8) You may also need to change .getEnabled to .isEnabled. 

These properties were renamed because they clashed with some Xamarin naming conventions


Most of these changes should not mean much to you, unless you are programming deep inside the exposed API.

Getting Started With Xamarin & Android JetPack

1) The first thing to do, is to add the usual resources to the drawable, raw, layout, folders, and making changes to AndroidManfiest.xml as demonstrated in the getting started guide. (http://www.androidjetpack.com/newdocs/html/AndroidJetPackAndroidDataGrid.html)

2) Second, is as usual, to add the reference to the XamarinStudioBindings.dll file that is included in the Sample Download

3) Third, in your Main.axml file, just add the FlexDataGrid component, similar to how it would be added in Android Studio or Eclipse. (http://www.androidjetpack.com/newdocs/html/AndroidJetPackAndroidDataGrid.html?PlacingtheAndroidDataGridinyourv.html) - You can see this in the file you downladed. 

4) In your MainActivity, you can get a handle to the grid, build it using a XML configuration, provide a Data Provider, and wire up event handlers. 

Lets take a quick look at the important pieces of the MainActivity:

using System;

using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Com.Flexicious.Nestedtreedatagrid;
using Com.Flexicious.Nestedtreedatagrid.Valueobjects;
using System.Collections.Generic;
using Java.IO;
using Java.Lang;
using Com.Flexicious.Nestedtreedatagrid.Events;
using Com.Flexicious.Nestedtreedatagrid.Interfaces;
using Com.Flexicious.Controls.Core;
using Android.Graphics;

namespace AndroidApp
{
    [Activity (Label = "AndroidApp", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        int count = 1;
        FlexDataGrid flexDataGrid;

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            // Set our view from the "main" layout resource
            SetContentView (Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            Button button = FindViewById<Button> (Resource.Id.myButton);
            
            button.Click += delegate {
                button.Text = string.Format ("{0} clicks!", count++);
            };

            //Here, we get a reference to the Android JetPack DataGrid component
            flexDataGrid = FindViewById<FlexDataGrid> (Resource.Id.flexDataGrid1);

            //Here, we setup a dataprovider - the objects in the DataProvider MUST inherit from Java.Lang.Object, OR expose 
            //themselves to the ACW using the EXPORT attribute
            IList<object> list = new List<object> ();
            for (int i = 0; i < 1000; i++) {
                list.Add(new NameValue("Name " + i, "Value " + i));
            }
            //HERE, we build the grid using the XML config in grid_config.xml raw resource
            BuildGrid(flexDataGrid, Resource.Raw.grid_config);
            //Now, we set the data provider on the grid.
            flexDataGrid.DataProvider=(list);

            //Finally, if you are using ItemRenderers, they cannot be set in XML, you need to use API to set them like below. 
            //Also, please ensure that the setData and getData methods are exported via the Java.Interop.Export attribute. 
            //flexDataGrid.GetColumnByDataField ("data").ItemRenderer = new ClassFactory (new TextInputRenderer(this).Class);
        
        }
        //This is an example of a CALLBACK function. The key is to ensure 1) Both the arguments and the return value inherit from Java.Lang.Object
        //And 2) That you add the Java.Interop.Export Attribute as shown below.
        [Java.Interop.Export("getCellBackground")]
        public Java.Lang.Object getCellBackground(IFlexDataGridCell cell) {

            if (!cell.RowInfo.IsDataRow.BooleanValue()) {
                return null;
            }
            if (cell.Column.DataField==("data")) {
                return new Java.Lang.Integer (Color.Red);// null;//Color.Red;
            } else if (cell.Text==("Name 1")) {
                return new Java.Lang.Integer (Color.Blue);// null;//Color.Red;
            }
            //this makes the grid use whatever color it would have by default.
            return null;
        }

        //This is an example of a Event Handler function. The key is to ensure 1) Both the arguments and the return value inherit from Java.Lang.Object
        //And 2) That you add the Java.Interop.Export Attribute as shown below.
        [Java.Interop.Export("onItemClick")]
        public  void onItemClick(FlexDataGridEvent e){
            Toast.MakeText(this"You Clicked on : "+((NameValue) e.Cell.RowInfo.Data).Label, ToastLength.Short).Show();
        }
        [Java.Interop.Export("onChange")]
        public  void onChange(FlexDataGridEvent e){
            Toast.MakeText(this"Grid Selection Changed : Items selected : " + e.Grid.SelectedObjects.Count, ToastLength.Short).Show();
        }

        /**
        * Takes a grid, and an XML configuration, loads the XML configuration into the Grid.
        * @param grid
        * @param resource
        */
        public void BuildGrid(FlexDataGrid grid, int resource) {
            grid.Delegate = (this);
            BufferedReader reader = new BufferedReader(new InputStreamReader(this
                .Resources.OpenRawResource(resource)));
            StringBuilder builder = new StringBuilder();
            string aux = "";
            try {
                while ((aux = reader.ReadLine()) != null) {
                    builder.Append(aux);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            string text = builder.ToString();
            grid.BuildFromXml(text);
        }


    
    }
}

 

 



Android DataGrid - Xamarin Support Added - Java Binding Project Issues

clock February 22, 2015 19:58 by author Administrator

One of the most frequent requests we are getting from customers evaluating our Android DataGrid product, is support for Xamarin.

Finally, after a long period of research, and overcoming some of the technical hurdles with cross JNI method calls, we are pleased to announce, that we now have a Binding DLL ready for Xamarin!

This is a feature a a lot of you had been asking for. The task was not easy, we encountered a number of technical hurdles. Most of them were fairly basic, but here are some that took a little head scratching. 

 

1) First, when we used the Xamarin Binding Project, any RequestTask based class we had, failed to convert to C# with the following errro :

Error Message : Error CS0534: does not implement inherited abstract member 'Android.OS.AsyncTask.DoInBackground(params Java.Lang.Object[])' (CS0534) (XamarinStudioBindings)

Solution: Turns out, this is a bug with Xamarin - see http://forums.xamarin.com/discussion/31668/android-java-binding-change-method-signature . There are multiple solutions proposed, the one that worked for us was to change:

protected virtual string DoInBackground (params  string[] p0) to protected override Java.Lang.Object DoInBackground (params  Java.Lang.Object[] p0) in the generated class. 

2) Second, for some reason, when pasting text into Xamarin Studio in the grid_config.xml, we got this :

Error Message : org.xml.sax.SAXParseException: Unexpected token (position:TEXT @1:2 in java.io.StringReader@45093440)

Solution : When opened in the HEX editor, there was indeed a wierd character at position zero. Removing the corrupt character from the file resovled this issue.

3) Finally, for those of you who are familiar with our API, the grid exposes a number of events, callback functions, etc. The problem is that with Xamarin C#, these methods are not exposed to the Android Callable Wrapper. This results in :

Error Message :  E/AndroidRuntime( 2506): Caused by: java.lang.NoSuchMethodException: m

Solution : The way to fix this is to add the Java.Interop.Export attribute to your code that gets called in xamarin [Export]. You will need to add Mono.Android.Export assembly to your References in your project. For example:

 [Java.Interop.Export("onChange")]

        public  void onChange(FlexDataGridEvent e){
            Toast.MakeText(this"Grid Selection Changed : Items selected : " + e.Grid.SelectedObjects.Count, ToastLength.Short).Show();
        }

 

4) The issue with the above, is that for some methods, you will get this

Error XA4209: Failed to create JavaTypeInfo for class:due to System.NullReferenceException: Object reference not set to an instance of an object

Solution : Ensure that the return type, as well as the parameters all inherit from Java.Lang.Object. For example, instead of returning Integer from a method, return Java.Lang.Integer. 

This post In a future post, we will go over the actual usage of the library dll. This post was mainly designed for those poor folks who are in the same position as us, trying to make a Xamarin dll out of a fairly large Android Library Jar.



AndroidJetPack Team Blog


Tag cloud