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" />

Friday 22 January 2016

Dynamically Update Color of SeekBar

Hola Androidians!!

Have you ever wanted to design a seek bar which could update its color dynamically when you drag it??

Well I had done this some time back hope this helps :

In your layout.xml file declare the seekbar as below :

 <SeekBar  
         android:id="@+id/settings_seekbar_usage_stogare"  
         android:layout_width="match_parent"  
         android:layout_height="wrap_content"  
         android:progressDrawable="@drawable/seek_bar_bg"  
         android:thumb="@drawable/settings_seekbar_circle"  
         android:thumbOffset="20dp"  
         android:secondaryProgress="0" />  

seek_bar_bg.xml

 <?xml version="1.0" encoding="utf-8"?>  
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >  
   <item android:id="@android:id/background">  
     <shape android:shape="rectangle" >  
       <corners android:radius="5dp" />  
       <gradient  
         android:angle="270"  
         android:endColor="#FFFFFF"  
         android:startColor="#FFFFFF" />  
     </shape>  
   </item>  
   <item android:id="@+id/progressshape">  
     <clip>  
       <shape android:shape="rectangle" >  
         <corners android:radius="5dp" />  
         <gradient  
           android:angle="270"  
           android:endColor="#00ff00"  
           android:startColor="#00ff00" />  
       </shape>  
     </clip>  
   </item>  
 </layer-list>  

Progress Drawable : seek_bar_bg.png    ---->     


Finally, In your Fragment / Activity use the below code in onProgressChanged event of seekbar :

 @Override  
      public void onProgressChanged(SeekBar seekBar, int progress,  
                boolean fromUser) {  
           if(progress > 0)  
                seekbarProgressColor = progress / seekbarProgressValue;  
           System.out.println(seekbarProgressColor);  
           if(seekbarProgressColor <= 50){  
          setProgressBarColor(mSeekBarStorageLimit, Color.rgb( 255 - (255/100 * (100 - (int)(seekbarProgressColor* 2))), 255, 0));  
         }else{  
              setProgressBarColor(mSeekBarStorageLimit, Color.rgb( 255, 255 - (255/100 * (int)((seekbarProgressColor - 50)*2)), 0));  
         }  
      }  
 //Function responsible to change the color of seekbar  
 public void setProgressBarColor(SeekBar seakBar, int newColor){  
          LayerDrawable ld = (LayerDrawable) seakBar.getProgressDrawable();  
          ClipDrawable d1 = (ClipDrawable) ld.findDrawableByLayerId(R.id.progressshape);  
          d1.setColorFilter(newColor, PorterDuff.Mode.SRC_IN);  
        }  

DONE!! Enjoy :-)