Sunday 17 March 2019

Chain of Responsibility Design Pattern

Today lets talk about my favourite subject "Design Patterns".

When it comes to design pattern, no one does the job better than "SourceMaking"(https://sourcemaking.com/design_patterns/)

And if you are bored of this creepy creature spelling out some binaries, our dear "Rocket Raccoon" AKA Triangle Faced Monkey, does explain the topic very well as "Refactoring Guru" (https://refactoring.guru/design-patterns/)

Today I will discuss about one of the behavioural design pattern : CHAIN OF RESPONSIBILITY.

We always argue, why do we even need design pattern? few people admit that they don't remember using one. Well few argue that it reduces readability and un-necessarily makes it complicated, when same thing can be achieved with less effort and time in a simpler approach.

Well, I'd say no one should right dirty code just to make it readable. So I decide to bug people with complex code so that we all learn design patterns.

I'm going to take a very simple example and this might not be the best use case.
(Note : Design Patterns are used to solve complex business problems which other wise will require too much dirty code and more maintenance.)

Without wasting any more time lets BEGIN!!!

Have you ever come across this code :

       
if(priority4 is available)

{
  // Execute
}

if(priority3 is available)
{
   // Execute
}

if(priority2 is available)
{
  // Execute
}

if(priority1 is available)
{
  // Execute
}


The worst part is, if you have any additional conditions that may emerge in the future, all those needs to be added here as well. Now you can argue that is readable but are you proud of yourself now ?? :p

So here comes the saviour, the prince of peace : the chain of responsibility

Let's say you have enum with 5 types and at run time, based on the different conditions, you want to set the enum type. Lets see how we can achieve this using this pattern:

We create a class called EnumObjectSelector

    public abstract class EnumObjectSelector

    {
        ///    The parent object type which is an enum. Set based on conditions/rules.
        public static EnumType ObjectType;
        
        ///    The next rule to check / verify.
        private EnumObjectSelector _nextRule;

        ///    Sets the next/successor rule to check in the sequence.
        public void SetSuccessorRule(EnumObjectSelector nextRule)
        {
           _nextRule = nextRule;
        }

        ///    The method used to execute the rule.
        public virtual EnumType ExecuteRule(Model model)
        {
            if(null != nextRule)
            {
                return _nextRule.ExecuteRule(model);
            }
            return ObjectType;
        }
    }

    ///    The Primary rule.
    public class PrimaryRule : EnumObjectSelector

    {
        ///    Constructor.
        ///    Initialise the sequence of the rule to be checked.
        public PrimaryRule()
        {
            Priority4Rule priority4Rule = new Priority4Rule();
            SetSuccessorRule(priority4Rule);

            Priority3Rule priority3Rule = new Priority3Rule();
            priority4Rule.SetSuccessorRule(Priority3Rule);

            Priority2Rule priority2Rule = new Priority2Rule();
            Priority3Rule.SetSuccessorRule(priority2Rule);

            Priority1Rule priority1Rule = new Priority1Rule();
            priority2Rule.SetSuccessorRule(priority1Rule);
        }

        public override EnumType ExecuteRule(Model model)
        {
            if(model.isType5)
            {
                ObjectType = EnumType.ObjectType5;
            }
            return base.ExecuteRule(model);
        }
    }
   
    ///    The priority 4 rule.
    public class Priority4Rule : EnumObjectSelector
    {
        public override EnumType ExecuteRule(Model model)
        {
            if (model.isType4)
            {
                ObjectType = EnumType.ObjectType4;
            }
            return base.ExecuteRule(model);
        }
    }

    ///    The Priority 3 rule.
    public class Priority3Rule : EnumObjectSelector
    {
       public override EnumType ExecuteRule(Model model)

        {
           if (model.isType3)
           {
               ObjectType = EnumType.ObjectType3;
           }
            return base.ExecuteRule(model);
        }
    }

    ///    The Priority 2 rule.
    public class Priority2Rule : EnumObjectSelector
    {
        public override EnumType ExecuteRule(Model model)
        {
            if (model.isType2)
            {
                ObjectType = EnumType.ObjectType2;
            }
            return base.ExecuteRule(model);
        }
    }


    ///    The Priority 1 rule.
    public class Priority1Rule : EnumObjectSelector
    {
        public override EnumType ExecuteRule(Model model)
        {
            if (model.isType1)
            {
                ObjectType = EnumType.ObjectType1;
            }
            return base.ExecuteRule(model);
        }
    }

Now in the main class we just invoke this chain of responsibility as below :


// This model object is holding data for the respective view model.
var model = new MyModel(); 
 
// Populate the model object with the data.
model.property1 = value; etc...


// Initiate the chain of responsibility
EnumObjectSelector primaryRule = new PrimaryRule();

var desiredModelObject = primaryRule.ExecuteRule(model);

To summarise :
1. We converted all if to Rules.
2. We created EnumObjectSelector the class representing chain of responsibility.
3. We created ExecuteRule method which takes care of executing next/successor rule.
4. We created PrimaryRule and added a constructor. Here we created a linkedlist / chains of rules in the respective order of execution.
5. In the main class where our business logic resides, where we have all the if loops, we invoke the chain of responsibility.

Thus we have successfully replaced all if loops with just one line. If at a later stage we see a scope for addition/updation/deletion of any rules, we just have to modify our "ParentObjectSelector" class by adding new or updating the existing rules.

Thank you for visiting my blog and I hope it was useful. I recommend you to go through "SourceMaking" or "Refactoring Guru" for learning other design patterns.

Please leave your comments and valuable feedback to help me improve and contribute more. You can also visit my Github repo (https://github.com/89Ash) which I'm building with some sample projects.



Saturday 17 March 2018

Multiselect list view using Xamarin Forms

Hi all,

Here in this post I'm going to demonstrate how to create a multi select listview in Xamarin Forms, designed for both iOS and Android.

The Listview comprises of an image, textview and a check box icon. Allowing the user to select multiple options. At the end of the listview there is a button used to save the selection.

Since there is no control as CHECKBOX offered by XAML, I used an Image and I rendered the checked and un-checked images on click of the image view. However you can even use custom renders to design a checkbox for both iOS and Android.

So that's said, lets start cooking  : I'm using Visual Studio for MAC

First create an Xamarin Forms project :


After creating the project, the folder structure should look like below :


In the above you can see, three folders are created :
1. PCL (MultiselectListView) 
2. Android (MultiselectListView.Droid)
3. iOS (MultiselectListView.iOS)

The UI and the backend logic of the forms application goes into PCL project making it deployable on both platforms.

The iOS and Android project here have the native bindings required to deploy the app into appropriate platforms.

In this project we are only adding the image required for the app into iOS and Android project and rest all our code will reside in the PCL project.

Now we will create the UI for the listview. Add the following code to MultiselectListViewPage.xaml


xml version="1.0" encoding="utf-8"?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MultiselectListView" x:Class="MultiselectListView.MultiselectListViewPage">

    <ContentPage.Content>

        <StackLayout Orientation="Vertical" Spacing="20">

            <Label x:Name="HeaderLabel" 

                   Margin="14,17,20,0" 

                   HeightRequest="54"

                   WidthRequest="350"

                   HorizontalTextAlignment="Center" 

                   Text="This is a custom ListView!!" 

                   FontSize="21"

                   TextColor="Black"

                   HorizontalOptions="CenterAndExpand" />

            <StackLayout x:Name="ListViewLayout" 

                   Spacing="10" 

                   Orientation="Vertical" 

                   VerticalOptions="FillAndExpand" 

                   HorizontalOptions="FillAndExpand">

                <ListView x:Name="MultiSelectListView" SeparatorVisibility="None" 

                          Margin="0"

                          RowHeight="55"

                          ItemSelected="OnItemSelected"

                          ItemTapped="OnItemTapped"

                          BackgroundColor="Transparent"

                          HasUnevenRows="True">

                    <ListView.ItemTemplate>

                        <DataTemplate>

                            <ViewCell>

                                <Frame WidthRequest="327" Padding="2" CornerRadius="07" HasShadow="false" BackgroundColor="Silver" Margin="24,10,34,0" HorizontalOptions="CenterAndExpand" VerticalOptions="StartAndExpand">

                                    <Frame WidthRequest="327" Padding="0" CornerRadius="07" HasShadow="false" OutlineColor="Transparent">

                                        <StackLayout WidthRequest="327" Orientation="Horizontal" Spacing="0">

                                            <Image x:Name="ItemImage" HeightRequest="30" WidthRequest="32" Source="{Binding ItemImage}" Margin="58,0,0,0" HorizontalOptions="Start" />

                                            <Label x:Name="ItemName" HeightRequest="30" WidthRequest="106" FontSize="20" Margin="22,0,0,0" Text="{Binding ItemName}" TextColor="Gray"  VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" />

                                            <Image x:Name="ItemCheckbox" HeightRequest="27" WidthRequest="31" Source="{Binding CheckboxImage}" Margin="24,0,0,0" VerticalOptions="CenterAndExpand" HorizontalOptions="EndAndExpand"></Image>

                                        </StackLayout>

                                    </Frame>

                                </Frame>

                            </ViewCell>

                        </DataTemplate>

                    </ListView.ItemTemplate>

                </ListView>

                <StackLayout>

                    <Button Text="Done" TextColor="White" HeightRequest="62" WidthRequest="201" Clicked="SelectItems" VerticalOptions="EndAndExpand" HorizontalOptions="CenterAndExpand" BackgroundColor="#3DBDA0" Margin="0,0,0,62"/>

                </StackLayout>

            </StackLayout>

        </StackLayout>

    </ContentPage.Content>

</ContentPage>

In the above code, we have created the ListView and there we defined "ViewCell" with three elements :
1. Image
2. Text
3. Checkbox

We have also bound these elements with our Model class object using "{Binding" property.

Also we have defined the two events for ListView OnItemSelected and OnItemTapped 

Now lets create our Model class. Create an empty class and name it as ListClass as shown below :


Add the following code :

using System;
namespace MultiselectListView
{
    public class ListItem
    {
        
        //  Item Name.       
        public string ItemName { get; set; }
 
        //  Item Image.
        public string ItemImage { get; set; }

        //  Selection Image.
        public string CheckboxImage { get; set; }
    }
}

Please make sure the name given in the "{Binding" should exactly be same as the Model class attribute name.

Now we have to write our logic in the MultiselectListViewPage.cs class. This is a generated class attached to MultiselectListViewPage.xaml

Our MultiselectListViewPage.cs will look like below :


using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Xamarin.Forms;

namespace MultiselectListView
{
    public partial class MultiselectListViewPage : ContentPage
    {
        
        private readonly ObservableCollection<ListItem> multiSelectListItems;

        /// <summary>
        ///     Object used to identify if the user tappep on a selected cell.
        /// </summary>
        private bool _isSelectedItemTap;

        /// <summary>
        ///     Object holding the reference of current user selection.
        /// </summary>
        private int _selectedItemIndex;

        private IList<ListItem> selectedItems = new List<ListItem>();


        public MultiselectListViewPage()
        {
            InitializeComponent();
            BindingContext = this;
            multiSelectListItems = new ObservableCollection<ListItem>();
            multiSelectListItems.Add(new ListItem()
            {
                CheckboxImage = "icons8_unchecked_checkbox.png",
                ItemImage = "icons8_level_1",
                ItemName = "Item1"
                    

            });

            multiSelectListItems.Add(new ListItem()
            {
                CheckboxImage = "icons8_unchecked_checkbox.png",
                ItemImage = "icons8_level_1",
                ItemName = "Item2"


            });

            multiSelectListItems.Add(new ListItem()
            {
                CheckboxImage = "icons8_unchecked_checkbox.png",
                ItemImage = "icons8_level_1",
                ItemName = "Item3"


            });

            multiSelectListItems.Add(new ListItem()
            {
                CheckboxImage = "icons8_unchecked_checkbox.png",
                ItemImage = "icons8_level_1",
                ItemName = "Item4"


            });

            multiSelectListItems.Add(new ListItem()
            {
                CheckboxImage = "icons8_unchecked_checkbox.png",
                ItemImage = "icons8_level_1",
                ItemName = "Item5"


            });

            MultiSelectListView.ItemsSource = multiSelectListItems;
        }

        /// <summary>
        ///     Method called when an item in the Listview is selected.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="args">Args.</param>
        private void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
        {
            _isSelectedItemTap = true;
            _selectedItemIndex = multiSelectListItems.IndexOf((ListItem)args.SelectedItem);
            multiSelectListItems[_selectedItemIndex].CheckboxImage = multiSelectListItems[_selectedItemIndex].CheckboxImage
                .Equals("icons8_unchecked_checkbox.png")
                ? "icons8_checked_checkbox.png"
                : "icons8_unchecked_checkbox.png";
            
        }

        /// <summary>
        ///     Method called when an item in the Listview is tapped.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="itemTappedEventArgs">Args.</param>
        private void OnItemTapped(object sender, ItemTappedEventArgs itemTappedEventArgs)
        {
            if (!_isSelectedItemTap && null != itemTappedEventArgs.Item)
            {
                multiSelectListItems.IndexOf((ListItem)itemTappedEventArgs.Item);
                multiSelectListItems[_selectedItemIndex].CheckboxImage = multiSelectListItems[_selectedItemIndex].CheckboxImage
                    .Equals("icons8_unchecked_checkbox.png")
                    ? "icons8_checked_checkbox.png"
                    : "icons8_unchecked_checkbox.png";
                
            }

            MultiSelectListView.ItemsSource = null;
            MultiSelectListView.ItemsSource = multiSelectListItems;
            _isSelectedItemTap = false;

        }

        /// <summary>
        ///     Method used to identify and configure the selected program as Tinnitus programs.
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="eventArgs">Event args</param>
        private void SelectItems(object sender, EventArgs eventArgs)
        {
            selectedItems = new List<ListItem>();
            string message = "";
            for (int index = 0; index < multiSelectListItems.Count; index++)
            {
                // The selected items will have the active image.
                // This is the paramter used to identify the selected programs to be configured as Tinnitus.
                if (multiSelectListItems[index].CheckboxImage.Equals("icons8_checked_checkbox.png"))
                {
                    selectedItems.Add(multiSelectListItems[index]);
                    message += index+" ";
                }
            }

            DisplayAlert("Items Selected", message,"OK");

            //Navigate to next page.
            //Navigation.PushAsync(new NextPage());
        }
    }
}




In the above class I have used two methods OnItemTapped and OnItemSelected.

If only OnItemSelected is used, then clicking on the selected row will just highlight and "OnItemSelected" method is not called/invoked again.

This is the reason I've added "OnItemTapped" also. By doing so, whenever user clicks on any unselected listview row, both the methods get called and when the user clicks on an already selected row, only "OnItemTapped" is called.

Inside "OnItemTapped" I've used my logic with help of class level bool flags to determine user action and handle the selection of user and update UI accordingly.

I've added a button "DONE" at the end of listview. After selecting the items, clicking on the "DONE" button displays an alert with the selected index.

That's it!!! Now time to play with the app.

Refer below screenshots to see how the app looks on both platforms :

Android :



iOS :





Please note : 

To update the ListView I'm resetting the itemsource of ListView. However you can use the INotifyPropertyChanged in your model class and try updating the ListView.

ObservableCollectionChanged is not an ideal callback to use here. This is because, it is only called on adding new items to collection and not updating the current items in the collection.

That's all guys!!! Hope this tutorial helps you in understanding the ListView behavior in Forms.

Saturday 7 January 2017

Xamarin Android - Display all installed apps in ListView

Hi all, few months ago I started working on Xamarin Android apps.

It takes a little time because we need to code in C# instead of java, there are few syntactical changes when compared to Native android development. Eg : Few Methods are converted to attributes and handling click events using delegates and stuff like that.

The first thing I did was to develop a sample project to read all the packages installed and display on  a custom ListView.

This way we learn :

1. Creating and accessing the views in Xamarin.
2. Creating a custom List Adapter for our Activity.
3. Writing the Activity Class and registering events.
4. Displaying a simple Toast Message.

However creating the Android Project, Deploying the apk on device is all as same as Native Android and IDE gives similar options which feels familiar. I use the Visual Studio for developing this app.

Lets Start :

Create an Activity Class MainActivty.cs

The class has following methods :

1. getInstalledApplicationsList - Reads and adds the package name to an ArrayList.

2. importInstalledAppsData - Read app name and app icon from individual packages.

3. successCallBack - Populate the Listview with the retrieved list and register On item click of the list to display the package name as a Toast message.

 using System;
using System.Collections;
using System.Collections.Generic;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Graphics.Drawables;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using PackageName.Src;

namespace PackageName
{
    [Activity(Label = "PackageName", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        int count = 1;
        List<AppDao> appList = new List<AppDao>();
        ArrayList packageName = new ArrayList();
        private ListView lvApps;
        private PackageAdapter packageAdapter;
        private Context mContext;
        private ProgressDialog _progressDialog;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            mContext = this;
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);
            lvApps = FindViewById<ListView>(Resource.Id.lv_apps);

            _progressDialog = new ProgressDialog(this);
            _progressDialog.SetMessage("Fetching apps list");
            _progressDialog.SetTitle("Please wait...");
            _progressDialog.SetCancelable(false);
            _progressDialog.Show();
            new GetAppsTask(this).Execute();

        }

        public IList<ApplicationInfo> getInstalledApplicationsList(PackageManager pm)
        {
            IList<ApplicationInfo> packages = pm.GetInstalledApplications(PackageInfoFlags.MetaData);

            foreach (var value in packages)
            {
                packageName.Add(value.PackageName);
            }

            return packages;
        }

        public void importInstalledAppsData()
        {

            PackageManager pkgManager = this.ApplicationContext.PackageManager;
            IList<ApplicationInfo> packages = getInstalledApplicationsList(pkgManager);
            int count = 0;
            foreach (ApplicationInfo packageInfo in packages)
            {
                AppDao appDao = new AppDao();
                appDao.AppName = (String)pkgManager.GetApplicationLabel(packageInfo);
                appDao.AppIcon = (Drawable) pkgManager.GetApplicationIcon(packageInfo);

                appList.Add(appDao);
                count++;
            }
        }

        public void successCallBack()
        {
            packageAdapter = new PackageAdapter(this, appList);
            lvApps.Adapter = packageAdapter;

            lvApps.ItemClick += delegate(object sender, AdapterView.ItemClickEventArgs e)
            {
                Toast.MakeText(this, packageName[e.Position].ToString(), ToastLength.Short).Show();
            };
            _progressDialog.Hide();
        }

    }
}

Create an AsyncTask to Fetch all package names

The Task is called from the main activity and once completes the successCallBack of MainActivity is called

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace PackageName.Src
{
    class GetAppsTask : AsyncTask
    {
        private MainActivity _context;

        public GetAppsTask(MainActivity context)
        {
            _context = context;
        }

        protected override void OnPreExecute()
        {
            base.OnPreExecute();
            
        }

        protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params)
        {
            _context.importInstalledAppsData();
            return true;
        }

        protected override void OnPostExecute(Java.Lang.Object result)
        {
            base.OnPostExecute(result);
            _context.successCallBack();
            
        }
    }
}

Create an Model class

The model has two attributes app icon and app name.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace PackageName
{
    class AppDao
    {
        public string AppName { get; set; }
        public Drawable AppIcon { get; set; }
    }
}

Create an Custom List Adapter class

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Object = Java.Lang.Object;

namespace PackageName
{
    class PackageAdapter : BaseAdapter
    {

        List<AppDao> _appsList = new List<AppDao>();
        Activity _activity;

        public PackageAdapter(Activity activity, List<AppDao> appsList)
        {
            this._activity = activity;
            foreach (var value in appsList)
            {
                _appsList.Add(value);
            }
            

        }

        public override Object GetItem(int position)
        {
            return (Object) _appsList[position].ToString();
        }

        public override long GetItemId(int position)
        {
            return position;
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            var view = convertView ?? _activity.LayoutInflater.Inflate(
            Resource.Layout.List_row, parent, false);
            var appName = view.FindViewById<TextView>(Resource.Id.tv_appName);
            var appImage = view.FindViewById<ImageView>(Resource.Id.iv_app);
            appName.Text = _appsList[position].AppName;
            appImage.SetImageDrawable(_appsList[position].AppIcon);

                
            return view;
        }

        public override int Count
        {
            get { return _appsList.Count; }
        }
    }
}

Create Layout files

The main layout and the row to be inflated in  listview.

Main.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ListView
        android:id="@+id/lv_apps"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

List_row.axml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#FF89C9E1"
    android:padding="8dp">
    <ImageView
        android:id="@+id/iv_app"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:padding="5dp"
        android:src="@drawable/icon"
        android:layout_alignParentLeft="true" />
    <TextView
        android:id="@+id/tv_appName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_toRightOf="@+id/iv_app"
        android:gravity="left|center"
        android:textSize="14dip"
        android:textColor="#000000"
        android:text="App Name" />
</RelativeLayout>

Sunday 14 February 2016

Using Charles (Web Proxy Tool) for Android

Hi Everyone,

Its been an year now that we are using the beautiful beautiful Web Proxy Tool - Charles in our project.  It really saved a lot of time with its cool features to test the API's.

I would like to thank my teammates  Bharatesh and Smita for letting me know about this tool and its now my turn to pass on the Knowledge to the rest.

In this post I'll briefly explain how to set it up quickly and also you will see how to use its features.

(PLEASE SKIP TO 1.3 for Set up Guidlines and Using Charles with Android)


1.1 OK now for those and most, WTHell is Charles ??

- Well, Its web proxy which runs on your system. You Configure your Browser or in our case Phone so that you route all the requests via Charles Proxy. Charles will monitor and record all the requests and response being sent and received.

Why Charles ??

- What will you do if you want to check all the response codes 200 - 500 in client when the API is up and running fine ?
- What if you had to change the request after hitting the URL / Change the response to see how app behaves ?
- What if you had a dummy response which was enough for today but now API is down ? - Sit Idle, have a cup of coffee :p

1.2 Solution: 

For all the above we used to hardcode and mess up the code and later at some point when API's up change the code to point to actual API. Then face the regression issues , argue it was working fine, DAMN!!!

Using Charles, no more. With Charles we don't touch our code and play with API as we need.

1.3 Set UP :

Download and install Charles from this link: https://www.charlesproxy.com/download/latest-release/




1) Go to proxy and then SSL and add the URL's you need to record / use for debugging.


2) Select SSL From Proxy Settings:

3) Click on Highlighted ADD icon and add the Host and Port. Eg : Host : dvp.ex..... Port : 443

Remember, the host address is the one which we will be hitting via Phone.



On Android :

1) Connect the Phone to Same Wifi your system is connected to.

2) Search for Install Charles Certificate in WebBrowser in Android Phone and click on highlighted link :


3) Scroll Down the page and click on link in highlighted box.

                

4) Click on highlighted "Here" link to install Charles Certificate on Phone.

      

5) After Installing go to Settings - Security - Trusted Credentials and under User Tab you can see the installed Charles Certificate

        


6) Now Go to Wifi Settings and set the proxy as IP address of your system and port as 8888




Now all the Requests from your phone can be monitored in Charles as it will be routed via Proxy.

Lets see how it looks in real time :

In my app I hit the URL and as you see the Charles recorded it and gave me the entire details of the same.

You can see the URL, Request Headers, Response and Response Code. 
Just Click on appropriate tabs to access the details.




Now the most useful Part : DEBUGGING

Yes, Charles allows us to Edit the request and response. Eg: After the app hits a request to authenticate by sending UserName and Password. In Charles you could modify the value of the fields before they reach the destination.

Also when response comes back as a JSON / text etc, you could change it to any value you wish and also change the response code. Like you received 200 and wanted the app to test the 500, then just edit in Charles and say execute.

Please see below the Screenshots for the same : (Select an endpoint and click on Breakpoints to edit the request and response.)

      

As shown below the Red Up Arrow indicate request breakpoint. Use the specific tabs, edit the required fields and click execute.


Same goes for editing the response. See Below




MORE!!!

There are few more which I would like you guys to explore and watch for your self.  One I will state below :-)

It even allows you to map the LOCAL DATA you saved in disk like JSON data and then displays the same as response. This usually helps when API's are down or not yet ready and you have a dummy data to be loaded as a response.

This way there is not code change required for the client app as it will still be pointing to same endpoints and when API's are UP, the actual data starts flowing in.

SUMMARY :

Its Awesome, time saving, requires no code changes and that's why,  ITS PAID !!

You can use the trial version like I do and for few lucky people Organization pays for them and for few CRACK JACKS, Gamers we know how to use things for free without paying :p

That's all folks, I hope that was helpful.

Please leave your comments, suggestions and I would love to take them. Most Important think Keep Sharing Knowledge guys !!!




Sunday 31 January 2016

Opening Sandbox file in External apps using Content Provider


SANDBOX is application's private space, this is where you can save all your application specific data safely. (Unless device is ROOTED)

Yes, before we see how to use it, why actually we need a content provider and how can it help us ?

What if you had to download files from an FTP server and save in your private space and open them at later point, for files like Images, music and text you could easily create your own custom in-app viewers.

Problem if  you need to open a .pdf, a word document or an .xls ect. you will depend on external apps, but since the files are saved in your application memory you can't see them in your sdcard or can't browse them in the external viewer apps.

Solution to this problem is CONTENT PROVIDER, yes!! This allows you to share your private files with external apps so that you can preview / edit based on the permission you define.

Below is a quick code snippet of how it can be implemented :

Create a java class : MyContentProvider.java


public class MyContentProvider extends ContentProvider {     private static final String CLASS_NAME = your defined name;     // The authority is the symbolic name for the provider class     public static final String AUTHORITY = your defined name;     // UriMatcher used to match against incoming requests     private UriMatcher uriMatcher;     @Override     public boolean onCreate() {         uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);         // Add a URI to the matcher which will match against the form         // 'content://com.ashray.example.activity.contentprovider.provider/*'         // and return 1 in the case that the incoming Uri matches this pattern         uriMatcher.addURI(AUTHORITY, "*", 1);         return true;     }     @Override     public ParcelFileDescriptor openFile(Uri uri, String mode)             throws FileNotFoundException {         String LOG_TAG = CLASS_NAME + " - openFile";         Log.v(LOG_TAG,  "Called with uri: '" + uri + "'." + uri.getLastPathSegment());         // Check incoming Uri against the matcher         switch (uriMatcher.match(uri)) {           // If it returns 1 - then it matches the Uri defined in onCreate         case 1:         String fileLocation = "";             // The desired file name is specified by the last segment of the path             // E.g. 'content://com.ashray.example.activity.contentprovider/Abc.txt'             // Take this and build the path to the file         Preference preferences = Preferences.getInstance(YourActivity.getBaseContext());         fileLocation = directorypath +''/"+ uri.getLastPathSegment();         }             // Create & return a ParcelFileDescriptor pointing to the file             // Note: Here we use Read-Write but we can restrict it to Read-Only             ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(                     fileLocation), ParcelFileDescriptor.MODE_READ_WRITE);                       return pfd;             // Otherwise unrecognized Uri         default:             Log.v(LOG_TAG, "Unsupported uri: '" + uri + "'.");             throw new FileNotFoundException("Unsupported uri: "                     + uri.toString());         }     }     // //////////////////////////////////////////////////////////////     // Below methods are not used.     // //////////////////////////////////////////////////////////////     @Override     public int update(Uri uri, ContentValues contentvalues, String s,             String[] as) {         return 0;     }     @Override     public int delete(Uri uri, String s, String[] as) {         return 0;     }     @Override     public Uri insert(Uri uri, ContentValues contentvalues) {         return null;     }     @Override     public String getType(Uri uri) {         return null;     }     @Override     public Cursor query(Uri uri, String[] projection, String s, String[] as1,             String s1) {         return null;     } }

In Activity call the Intent to open the file in external app : The content provider will handle creating a ParcelFileDescriptor pointing to the file, creating a bridge for external app to access the file.

// Eg : To open a Powerpoint file

The below code will either open the file directly in a app which can handle powerpoint files - If only one app is installed in device which can read ppt files.

OR

Show user a list of apps t choose from if multiple apps capable of handling power-point  are installed
in the app


String localFile = path of file to open.

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setDataAndType(Uri.fromFile(localFile), "application/vnd.ms-powerpoint");

startActivity(intent);


Finally in Manifest file declare the provider, inside the application tag

<provider
            android:name="com.ashray.example.contentprovider.MyContentProvider"
            android:authorities="com.ashray.example.contentprovider.provider"
            android:grantUriPermissions="true"
            android:exported="true" />

Permissions :

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />