Wednesday, September 10, 2014

Serialization behind the scene

In the post I am going to explain about the Binary Serialization internals.


With the Binary Serialization we can serialize any fields (Private, protected or public) which are not marked as NonSerializableAttribute.

FCL providers Formatter services and Formatters like BinaryFormatters to achieve serialization.
FormatterServices class provides some static methods to achieve Serialization and De-Serialization behind the scene , which are intern called by the Serialize and de-serialize methods of BinaryFormatter.

Let us look at the following Steps how Serialization and De-Serialization works using FormatterServices static methods.

Serialization:
·         public static MemberInfo[] GetSerializableMembers(
        Type type
        )
This method uses the reflection to get all the (private and public) instance fields and returns MemberInfo array.
·         The object being serialized and MemberInfo array passed to static method GetObjectData(Object obj, MemberInfo[] members). This methods returns array of objects where each element identifies the value of the field in the object being serialized.
·         Finally, the formatter then enumerates over the elements in the two arrays, writing each member's name and value to the byte stream.

De-Serialization:

·         public static Type GetTypeFromAssembly(
        Assembly assem,
        string name)
This method returns System.Type object indicating the type of object being De-Serialized

·         public static Object GetUninitializedObject(
        Type type)
This method allocates memory for the new object without calling constructor and all the object's bytes are initialized to null or 0.

·         The formatter now construct an object and initializes a MemberInfo array by calling GetSerializableMembers() method; This method returns set of the fields(Private and Protected also) that were serialized and that need to de-serialized.
·         The formatter now creates and initializes an object array from the data contained from the stream.
·         The reference to newly created object, MemberInfo array and object array data will be passed to PopulateObjectMembers (object obj, MemberInfo[] membrs, object[] data).
This method enumerates over the arrays, initializing each field to its corresponding value. At this point the object is completely De-serialized.

The above explanation is implemented in the below example.
Got help from:

 Special thanks to Jeffery Ritcher and MSDN for providing required internal details.

if any mistakes found in the blog, guide me correct direction

Tuesday, July 16, 2013

Add Custom Fonts to Web View Android


Add Custom Fonts to Web View Android

 

Some android phones wont support indic language display in web view in app. You can easily solve this  problem by adding indic font to assets folder. Assume added the font file has been added under the assets/fonts folder (kannada.ttf)


Create one WebTask class to download the web data, add CSS style ( which includes the font path ) to web view html content.


public static class WebTask extends AsyncTask<Void, Void, String> {
        private WeakReference<WebView> mWebView;
        private String mUrl;

        public WebTask(WebView webView, String url) {
            mWebView = new WeakReference<WebView>(webView);
            mUrl = url;
        }

        @Override
        protected String doInBackground(Void... params) {
            BufferedReader in = null;
            String data = null;

            try {
                HttpClient client = new DefaultHttpClient();
                URI website = new URI(mUrl);
                HttpGet request = new HttpGet();
                request.setURI(website);
                HttpResponse response = client.execute(request);
                response.getStatusLine().getStatusCode();
            //    in = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), HTTP.UTF_8));
                data = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);
                return data;
            } catch (Exception e) {
                return null;
            } finally {
                if (in != null) {
                    try {
                        in.close();
                        return data;
                    } catch (Exception e) {
                    }
                }
            }
        }

        @Override
        protected void onPostExecute(String result) {
            if (result != null) {
                try {
                    int hedpos = result.indexOf("</html>");
                    String style = Utility.getFontStyle();
                    StringBuilder builder = new StringBuilder(result);
                    builder = builder.insert(hedpos, style);
                    mWebView.get().loadDataWithBaseURL(null, builder.toString(), "text/html", "utf-8", "about:blank");
                } catch (Exception e) {
                    // TODO: handle exception
                }
            } else {
                // error occured
            }
        }
    }

public static String getFontStyle() {
        return "<style>@font-face {font-family: Kannda';src: url('file:///android_asset/fonts/Kannda.ttf');}body, h2, li, p, span, div{font-family: 'Kannda' !important;}</style>";
    }
Call the web task as follows:

    WebTask task = new WebTask(yourwebviewobject, Url);
            task.execute();
If anything wrong i am doing please let me know.

Monday, September 10, 2012

Folder zip/un-zip in Metro c#


using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;

namespace FileShare
{
    class FolderZip
    {
        /// <summary>
        /// ZipFolder and its sub folders
        /// </summary>
        /// <param name="tcpSocket"></param>
        async private static Task ZipFolderContents(StorageFolder sourceFolder, ZipArchive archive, string baseDirPath)
        {
            IReadOnlyList<StorageFile> files = await sourceFolder.GetFilesAsync();

            foreach (StorageFile file in files)
            {
                ZipArchiveEntry readmeEntry = archive.CreateEntry(GetCompressedFileName(baseDirPath, file));

                byte[] buffer = WindowsRuntimeBufferExtensions.ToArray(await FileIO.ReadBufferAsync(file));

                // And write the contents to it
                using (Stream entryStream = readmeEntry.Open())
                {
                    await entryStream.WriteAsync(buffer, 0, buffer.Length);
                }
            }

            IReadOnlyList<StorageFolder> subFolders = await sourceFolder.GetFoldersAsync();

            if (subFolders.Count() == 0) return;

            foreach (StorageFolder subfolder in subFolders)
                await ZipFolderContents(subfolder, archive, baseDirPath);
        }

        async public static Task ZipFolder(StorageFolder sourceFolder,  StorageFolder destnFolder,  string zipFileName)
        {
            StorageFile zipFile = await destnFolder.CreateFileAsync(zipFileName, CreationCollisionOption.ReplaceExisting);

            Stream zipToCreate = await zipFile.OpenStreamForWriteAsync();

            ZipArchive archive = new ZipArchive(zipToCreate, ZipArchiveMode.Update);
            await ZipFolderContents(sourceFolder, archive, sourceFolder.Path);
            archive.Dispose();
        }

        static private string GetCompressedFileName(string baseDirPath, StorageFile file)
        {
            return file.Path.Remove(0, baseDirPath.Length);
        }

        async public static Task UnZipFile(StorageFolder zipFileDirectory, string zipFilename, StorageFolder extractFolder = null)
        {
            if (extractFolder == null) extractFolder = zipFileDirectory;

            var folder = ApplicationData.Current.LocalFolder;

            using (var zipStream = await folder.OpenStreamForReadAsync(zipFilename))
            {
                using (MemoryStream zipMemoryStream = new MemoryStream((int)zipStream.Length))
                {
                    await zipStream.CopyToAsync(zipMemoryStream);

                    using (var archive = new ZipArchive(zipMemoryStream, ZipArchiveMode.Read))
                    {
                        foreach (ZipArchiveEntry entry in archive.Entries)
                        {
                            if (entry.Name != "")
                            {
                                using (Stream fileData = entry.Open())
                                {
                                    StorageFile outputFile = await extractFolder.CreateFileAsync(entry.FullName, CreationCollisionOption.ReplaceExisting);
                                    using (Stream outputFileStream = await outputFile.OpenStreamForWriteAsync())
                                    {
                                        await fileData.CopyToAsync(outputFileStream);
                                        await outputFileStream.FlushAsync();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }      
    }
}

Class can be as used follows:
 Windows.Storage.Pickers.FolderPicker fldPicker = new Windows.Storage.Pickers.FolderPicker();
  fldPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;                        fldPicker.FileTypeFilter.Add("*");

 StorageFolder sorceFolder = await fldPicker.PickSingleFolderAsync();

  await FolderZip.ZipFolder(sorceFolder, Windows.Storage.ApplicationData.Current.LocalFolder, "Sample.zip");
   await FolderZip.UnZipFile(Windows.Storage.ApplicationData.Current.LocalFolder, "Sample.zip");


For  UnZipFile we can pass third argument as null or skip for extraction in same folder.

If any mistakes i did suggest me to correct.

Thanks so much for reading my post.
 

Thursday, February 23, 2012

Indic langauge display in WP7

Hi,

I investigated on the how to display any language in WP7:
I used the following steps to display any language by using Unicode support: Source=http://informationmadness.com/technology/tech-tips/4127-how-to-read-hindi-gujarati-indian-languages-on-hp-touchpad.html
 1) Now we need to look for the arialuni.ttf under "C:\Windows\Fonts" folder. Most probably you will have this font. Copy that "arialuni.ttf" (keep the file name to all lowercase . remember its .ttf and not .TTF) on your desktop  and rename the file to "Unicode.ttf".
2)  Paste that file in your project , open the project in expression blend.
3) In the Textblock properties Select FontFamily Aerial Unicode MS and check emebed. Now the textblock xaml looks like this
<TextBlock TextWrapping="Wrap" FontSize="40"
         Name="textBlock1" Text="ಅನ೦ದ"
        VerticalAlignment="Top" FontFamily="/FontTest;component/fonts/Fonts.zip#Arial Unicode MS"  />

 Regards
Mahantesh

Hope this may helps to viewers.
 

Monday, January 2, 2012

Lazy list box in Windows phone 7.5 (Mango)

Most phone users are concerned about network usage. Network traffic comes at a premium, and a user's perception of the quality of your app depends a lot on its responsiveness. When it comes to fetching data from a network service, it should be done in the most efficient manner possible. Making the user wait while your app downloads giant reams of data doesn't cut it. It should, instead, be done in bite-sized chunks.
To make this easy for you, I have created a ScrollViewerMonitor which uses an Attached Property to monitor a ListBox and fetch data as the user needs it. It's as simple as adding an Attached Property to a control which contains a ScrollViewer, such as a ListBox, as shown in the following example:
<ListBox ItemsSource="{Binding Items}"
         u:ScrollViewerMonitor.AtEndCommand="{Binding FetchMoreDataCommand}" />
Notice the AtEndCommand. That's an Attached Property that allows you to specify a command to be executed when the user scrolls to the end of the list.

Source help to write this blog:
Lazy Loading

Use the following code to achieve and modify according to your Model class:

In c#:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using DanielVaughan.WindowsPhone7Unleashed;
using System.Collections.Generic;
using SnapDeal;
using System.Linq;
using System.Threading;
using System.Collections.ObjectModel;
using System.ComponentModel;
using SnapDeal.ViewModels;
using Microsoft.Phone.Controls;

namespaceLazy
{
    public class OptimizedListBox : ListBox, INotifyPropertyChanged
    {
        /// <summary>
        /// Max items to display in only scroll
        /// </summary>
        public int MaxCount { get; set; }

        public delegate void FetchDataEventHandler(object sender, ResponseArgs args);
        public event FetchDataEventHandler FetchData;

        public static readonly DependencyProperty ListProperty =
           DependencyProperty.Register(
               "ListItems",
               typeof(IDataModel),
               typeof(OptimizedListBox),
               null);


        public OptimizedListBox()
        {
            fetchMoreDataCommand = new DelegateCommand(
                obj =>
                {
                    if (busy)
                    {
                       return;
                    }
                    Busy = true;
                    if (FetchData != null)
                        FetchData(this, null);
                    else
                        Busy = false;
                });
            ScrollViewerMonitor.SetAtEndCommand(this, FetchMoreDataCommand);          
        }

        /// <summary>
        /// Actual items of list
        /// </summary>
        public IDataModel ListItems
        {
            get { return GetValue(ListProperty) as IDataModel; }
            set { SetValue(ListProperty, value); }
        }

        public void FetchCompleted(bool isUpdateNeeded)
        {
            Busy = false;

            if (!isUpdateNeeded)
                return;

            if (this.ListItems != null)
            {
                int start = this.Items.Count;
                int end = start + Constant.kMaxLoadItemCount;
                if (this.ListItems.GetType() == typeof(Zone))
                {
                    Zone loadedItems = this.ListItems as Zone;
                    if (end > loadedItems.Count() - 1)
                        end = loadedItems.Count();
                    for (int i = start; i < end; i++)
                    {
                        this.Items.Add(loadedItems[i]);
                    }
                }
            }
        }

        readonly DelegateCommand fetchMoreDataCommand;
        public ICommand FetchMoreDataCommand
        {
            get { return fetchMoreDataCommand; }
        }
            
        bool busy;
        public bool Busy
        {
            get { return busy; }
            set
            {
                if (busy != value)
                {
                    busy = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("Busy"));
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, e);
            }
        }
    }
}


In XAML:

 <local:OptimizedListBox x:Name="TodaysDealList" ListItems="{Binding TodaysDealList}" SelectionChanged="OnSelectDealItem" ItemContainerStyle="{StaticResource ListboxStretchStyle}" Margin="5, 0, 0,0"/>

To display the progress indicator just use the following line:

 <TextBlock Text="Loading..." Grid.Row="1" Style="{StaticResource LoadingStyle}" Foreground="White"
                               Visibility="{Binding Busy, ElementName=TodaysDealList,
                      Converter={StaticResource BooleanToVisibilityConverter}}"/>
The Max count indicates the how many items u want to load on each scroll, list items indicates  your actual items of list.(Hope you know about converters)
May be it will helpful for you.

-Mahantesh

Friday, July 8, 2011

unzip the file in wp7

How to unzip the file in wp7?

Hi, this is my first post about the programming and i dont want to explain theory things .. Just i want to post the c# code to unzip file .
the following code doesn't require the third party like sharpziplib.

using System.IO;
using System.Text;
using System.Collections.Generic;
using System.IO.IsolatedStorage;

namespace WP7UnzipFile
{
    public class UnZipper
    {
        internal void UnzipFile(string filePath)
        {
            StreamResourceInfo fileInfo = App.GetResourceStream(new Uri(filePath, UriKind.Relative));
            UnzipFile(ref fileInfo);
        }


        internal void UnzipFile(ref StreamResourceInfo fileInfo)
        {
            string[] fileNames = GetFileNamesFromZip(fileInfo.Stream);
            foreach (string fileName in fileNames)
            {
                StreamResourceInfo audioFile = App.GetResourceStream(fileInfo, new Uri(fileName, UriKind.Relative));
                if (audioFile != null)
                    SaveFile(audioFile.Stream, fileName);
            }
        }


        private void SaveFile(Stream stream, string relativefilePath)
        {
            //int lastSlashPos = relativefilePath.LastIndexOf('/');
            //int substringLen = relativefilePath.Length - relativefilePath.LastIndexOf('/');
            //string fileName = relativefilePath.Substring(lastSlashPos + 1, substringLen - 1);
            using (var appStore = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (appStore.FileExists(relativefilePath))
                    appStore.DeleteFile(relativefilePath);

                CreateDirectory(appStore, relativefilePath);
                using (IsolatedStorageFileStream isoStream = appStore.CreateFile(relativefilePath))
                {
                    byte[] buffer = new byte[stream.Length];
                    using (BinaryWriter fileWriter = new BinaryWriter(isoStream))
                    {
                        stream.Read(buffer, 0, (int)stream.Length);
                        fileWriter.Write(buffer);
                    }
                }
            }
        }

        private void CreateDirectory(IsolatedStorageFile appStore, string relativefilePath)
        {
            if (relativefilePath.Contains("/"))
            {
                int lastSlashPos = relativefilePath.LastIndexOf('/');
                int substringLen = relativefilePath.Length - relativefilePath.LastIndexOf('/');

                string directoryName = relativefilePath.Remove(lastSlashPos, substringLen);
                if (!string.IsNullOrEmpty(directoryName))
                    appStore.CreateDirectory(directoryName);
            }
        }

        /// <summary>
        /// Reads the file names from the header of the zip file
        /// </summary>
        /// <param name="zipStream">The stream to the zip file</param>
        /// <returns>An array of file names stored within the zip file. These file names may also include relative paths.</returns>
        private string[] GetFileNamesFromZip(System.IO.Stream zipStream)
        {
            List<string> names = new List<string>();
            BinaryReader reader = new BinaryReader(zipStream);
            while (reader.ReadUInt32() == 0x04034b50)
            {
                // Skip the portions of the header we don't care about
                reader.BaseStream.Seek(14, SeekOrigin.Current);
                uint compressedSize = reader.ReadUInt32();
                uint uncompressedSize = reader.ReadUInt32();
                int nameLength = reader.ReadUInt16();
                int extraLength = reader.ReadUInt16();
                byte[] nameBytes = reader.ReadBytes(nameLength);
                names.Add(Encoding.UTF8.GetString(nameBytes, 0, nameLength));
                reader.BaseStream.Seek(extraLength + compressedSize, SeekOrigin.Current);

            }
            // Move the stream back to the begining
            zipStream.Seek(0, SeekOrigin.Begin);
            return names.ToArray();

        }
    }

}


if written code creates any problem in Ur app.. Dont blame me..