Friday, 2 March 2012

UI desgining in Android (GOOD PRACTISES)

Android runs on  variety of devices that offer different screen sizes and densities.
When ever we designing a User interface it should fit in all devices. Follow Some good practice that will help you while developing Universal builds.


        So here are some good practices which developers  can adapt which will make a lot of difference.

       
        1) Designing the UI through XML
        2) Designing the UI through Code
        3)
Keeping Some Good Coding Designs
  

   1) The way you are Designing the UI through Xml.
                    
                          When Ever you receive a wire frame or design document  you need to decide what are the components that i can developed through XML. Designing the UI through XML is the best practice for Screen Compatibility.

 Here are some good practices for designing the UI through XML

  1) Do not use AbsoluteLayout in XML . Most Preferred is Relative Layout So that whole inner child views will be related to the parent or other neighboring view components.
 Which will give a tight coupling between view components and they will be in right place irrespective of all screens.
        NOTE: DON'T ALLOW ANY CHILD VIEWS OR COMPONENTS IN FREE FLOW MANNER


  2) Don't use 'px' pixel hard coding in your xml always use 'dp' density pixel in XML's

  3) Use Wrap_content and Fill_parent(match_parent) for your layout dimensions but in some situation if you strictly want to  hardcode the layout dimensions then do it with 'dp'

  4) Try to avoid too much usage of margins and paddings. Use it in wise manner (Eg: if you want to place a view in center use allign_center = true instead of giving top and left margins stuffs)

  5) Don't Hard Code any text to the Graphics Unless it is kind of a rare font and Color. This will help to reduce the amount of graphics in the project.
      NOTE : GRAPHICS AND THE UI WIDGETS WHICH WE ARE USING IN THE LAYOUTS SHOULD BE LOOSELY COUPLED

  2) The way you are designing the UI through code.



      Obviously you need to follow all the best practices which specified in XML designing. Additional one thing we need to keep in mind as you see in XML we are forced at some situation where we need to hard code the dimensions with 'dp'. Like that in code also   we need to hard code in that case the value which is hard coded should be multiplied by the SCALE factor

  SCALE is nothing but Getting the screen's density. And it can be derived from  DisplayMeterics object

   //Getting the screen density in runtime
   final float SCALE= getResources().getDisplayMetrics().density;
    
low-density screen Scale  = 0.75
 medium-density screen   Scale  = 1.0
high-density screen Scale  = 1.5
extra high-density screen Scale = 2.0
     
     Usage: If you are setting some margins to a Layout params below you are hardcoding 25 make sure it is SCALED

          //loginParams.setMargin(0,25,0,0);     -not right
          // loginParams.setMargin(0,(int)SCALE * 25,0,0);

 and of course try to identify those components which can be reused in other screens, develop that UI as a separate components so that it can be reused which is a good practice.
  If you are very good in JAVA OOPS concept then you can do lot of magics in  code. You can apply POLYMORPHISM and INHERITANCE a lot while making reusable UI components through code

In xml also you  can use <include> tag to including the reusable xml components. Eg: In some Navigational Apps you can see  the top bar will be same in some screen. So all you can do is created the top bar as a separate XML and try to include in other screens using <include> tag.

 <include layout=name />

  3) Keeping Some Good Coding Designs
     Now a days and also in future most of the android builds which is going to reside in market will be universal builds
    In that case we developers will have some challenges which we need to overcome with some smart code design architecture . As you all know in android what ever resources we are using in the project whether it may be different types of drawable for several resolution or screen size or even layout for different stuffs . All these can be accessed in our code through R.java file. We need to utilize these and make our code in good format

         If we are working on a universal build . We need to make lot of run times checks in the code in order to decide which layout to be loaded or which drawable to be loaded that kind of stuff.
 Basically there will be a bunch of runtime checks to choose which resource should be loaded
   In these kind of scenarios we need to be smart in such a way that in our code we need to keep 2 main files

   say DeviceConfigurationManager.java
             //This java file should be a single ton class which should be initialized in the entry point of your app and can be accessed across the application from any class maintaing same instance. In this we need all the helper functions to determine the physical environment where the app is going to interact such as screen size, device os version, resolution, screen height, screen width, device name, manufacturer name, and also you can write a small  helper function in this file to determine what inch it is 10" or 7 or" or 8" what ever may be, try to add lot of helper functions by maximum utilization of Display Meterics class,Configuration Class etc in Android.

   say ResourceSelectionManager.java
          //This java file should be a single ton class which should be initialized in the entry point of your app and can be accessed across the application from any class mainting same instance.. This file mainly contains all the runtime checks in the application ,here you can write bunch of helper function that decides which resources should be loaded it will return unique int (which you can see in R.java) i.e., R.layout.lay_name or R.drawable.drw_name or what ever stuff, keep in mind don't return any View Object make sure it should return only the R.java reference ID (Unique Integer). If you return View Object itself it will lead to some memory leak.


   e.g. :
               if(//7inch pro){
                      setContentView(R.layout.loginview_7);
                  }
              elseif(//7ich landscape){
                     setContentView(R.id.loginview_7_landscape);
               }
              elseif(10 inch por){
setContentView(R.id.loginview_10_landscape)
             
}
      elseif(10 inch land){
setContentView(R.id.loginview_10_landscape)
             
}

       here you can see trying to set a login layout with some runtime checks this is a single scenario when we are playing with universal build bunch of these kind of runtime checks will be there in the whole application which will mess up your code and make them very difficult to debug and maintain . If it is a big project then things will be more complicated. Instead of that all you have to do is


             setContentView(ResourceSelectionManger.getInstance().getLoginView()); //

              its enough the function will give you a unique integer that loads the appropriate resource.

             you can then move your runtime checks into ResourceSelectionManger.getInstance().getLoginView(); function . Like this move all your runtimes checks into ResourceSelectionManager.java and give some good documentation to each   function residing in this file. And enhance the importance of this file to a app configuration level. So when ever if you find any weird UI issue or functionality issues in some devices  all you have to do is fetch the api docs of ResourceSelectionManager.java and find out the function . Put the debugger in that function and you can see what is the issue
This will give you a good control and maintenance over the code when we are developing universal builds.

   NOTE: Also try to avoid hardcoding of Magic Numbers in the code . Suppose if you want to perform some operation if user touches on the middle of the screen

         if(touch x==300 && y==200){   //wrong approach
                //do this
          }
      its wrong always try to come up with some formula that determines this number
             e.g. instead of 300  (getDeviceHeight/2) or what ever may be Construct a formula in such a way that it will work in all physical screen size.


       Keep these kind of stuffs while coding it will help you a lot.

 Regards
 Roger

Tuesday, 28 February 2012

error: Obsolete Build.xml Need to delete or regenerate


   A Small Info

   If you are trying to build the project using ant scripts which points to your customized Build.xml . In that case if anyone  getting an "error: Obsolete Build.xml Need to delete or regenerate"  All you have to Do it

  1) Check your ADT version because android changed the ant scripts and there building architecture  tools from ADT 14 onwards  http://tools.android.com/recent/buildchangesinrevision14

  All you have to do his  replace the 'tools' folder in your current SDK with 'tools' folder in a SDK which is less than revision 14

 then go the cmd shell

 -> go to your tools path (always prefer to set as environment variable so that you can access the SDK_PATH easily ,In Linux edit .bashrc in Mac you can create .env text file or in Windows Enviornment path tab)

    from there trigger 'android update project -p <your project path>'
  
   if it asks to set the target ID

  all you have to do is take a back step and trigger "android list targets" from the same tool path it will show the targetID in cmd prompt

 so you can add that  targetID to your update comment

   'android update project -t<ID> -p<project path>' there goes it will automatically update the local.properties file and your build properties

 Then you are in the good shape to build  your project through build.xml .......

 Thanks
 Roger Gasper

Monday, 6 February 2012

Memory Mangement In Java And in Android Tech


Many of the android Developers are get into this night mare OUT OF MEMORY ERROR or Bitmap Exceeds VM Budget
This situation will arise due to following reasons

 1) When you are dealing with large Bitmaps or Images
 2) When you are trying to rotate the device continuously
 3) When you are using unnecessary Object and increasing the heap memory

   Among  three scenarios the first two are culprits third one we can catch it by using some memory profiler tools and able to fix it.
 
  How we can get rid of OOME?First two scenarios are happening quite often

             It is not a mistake from Developer it is bug from Android OS code because the Dalvik Virtual Memory limits the amount of memory that any Android application can use to either 16 or 24MB. And there is no way to change this allocation pro grammatically. Only way is to alter the OS Code and recompile But that is far from our hands as millions of users using the application we cant tell them to recompile the OS to run this application . But the Vendors like Samsung,Motorola or those who are collaborating   with Goggle can make this happen.
   Iphone developers are safe in this area as they have the leverage to release the memory after use since Objective C is providing
 
           Ok Now lets move to the first two points in Detail and the solution which we can do from our side

    1) Dealing with large Bitmaps

                    Now 16MB is enough to run even a complicated game but even though the VM runs out of memory this is because the OS is not releasing the bitmaps objects properly once the program is through with them. The only way the OS will release the memory when the application ends,and even it takes some time So lets see what are the solution to fix this


    a) Reducing the Size of Bitmap
                        This Solution involves scaling the bitmap and reducing the amount of memory usage but this will not solve the problem, it simply minimises its impact. This solution will work out if you are using very few bitmaps or images

    b) Bitmap.recycle()
                        This is good practice  of programming when ever you are trying to deal with the bitmaps call Bitmap.recycle() this will immediately mark a bitmap for garbage collection if you are using collection of bitmaps don't forgot to call individually. But as this will also not giving a concrete solution as Java Garbage Collector is a low priority thread we don't know when it will collect the object. But its a good practice which will solve to an extend

    c) Utilize the Data Structures in Java

                Suppose you are working with some multiple images make sure all bitmaps are in a Data structure so that all bitmaps are properly managed. Because sometimes even one Bitmap is enough to create the issue so whether it is a activity or back end Java class if you are dealing with multiple images there should be a function like this freeBitmapsUsed() and also make sure to override the finalize() method so that we can make sure that it is properly collected by the JVM
                           // call in order to free memory of Bitmap objects
        public void freeBitmapsUsed() {
                    //traverse the data structure
            for(Bitmap image: mImages) {
                // also, it's better to check whether it is recycled or not
                if(image != null && !image.isRecycled()) {
                    image.recycle();
                    image = null; // null reference
                }
            }
        }
                

          // the destructor should also handle the memory in case it still holds memory
        protected void finalize() {
            freeBitmaps();
        }

          Lets move to the Second Scenario

       2) When you are trying to rotate the device continuously
                           These is a serious OOME issue which almost all the developers faced a fast switching between the screen modes portrait/landscape. Why it is happening?
           Its impact will be very high when that UI is constructed through code, or if that UI contains some large bitmaps, or it contains some complex canvas drawings.
            These is a pure memory leak issue which we need to blame ourselves. Keeping in mind that you are Java developer not in a program where you have the span  to deal with memory a lot
                First suggestion  you have to see requirement if that UI can be developed through xml then go for it that is the best practise  because keeping  different xmls in portrait and Landscape folders its  a good android approach because OS itself will take care lot of de allocation no need to worry too much but there are certain circumstances where we need to create the UI through code or even we need to draw through canvas in that case we need to be little bit care. Whenever fast switching between the modes crash will happen.

           It is happening mainly because you are referencing you context ie, your Screen Instance to a long time

            That is when ever you are switching the modes from portrait to landscape and vice versa android is recreating your views it is taking the portrait layouts and resoures everything and literally recreating the view
           So keeping this in mind Whenever a rotation happens we need to make sure there should not be any obstacle in our activity/UI which prevents the garbage collector from collecting that pointer/Screen Instance/ActvityContext
           ie, You should not hold any static reference to Activity context. Playing with activity context needs to be careful at your risk a simple example

                
                    private static Drawable sBackground;
 
@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);
 
  TextView label = new TextView(this);
  label.setText("Leaks are bad");
 
  if (sBackground == null) {
    sBackground = getDrawable(R.drawable.large_bitmap);
  }
  label.setBackgroundDrawable(sBackground);
 
  setContentView(label);
}



                   Its a pure memory leak code ,here you can see that Drawable is statically referenced. But you can see there is no direct reference to activity context. Still when you rotate the phone you can see a memory leak
 that is your drawable sBackground points to label which in turns created from the context new TextView(this); so when ever rotating the device by default GC_CONCURRENT will call which try to deallocate the context  but it cant deallocate this activity instance as one of its child ie, sBackground is statically referenced so what happens when you are continuously switching the mode to quite a long time you will get crash OOM by showing exceeds VM memory budget, ie, 16 or 24MB because your heap memory is increased on every switching

     So make sure your context ie, a pointer which holds the whole complex UI component in fact this screen pointer in android which consumes a lot of your memory so play in safe mode with your activity context don't make any static reference directly or indirectly to this pointer which leaks your memory

     

                You can see here let take right side as portrait and left side as Landscape  the root one is our Activity Context/Screen Pointer  . Your View is created by Lot of View Groups and Child Group if any of your View Group Components or View Child's is statically referenced then you are trapped. The moment when you switch it portrait mode OS recreates the whole View with revised layouts and images then it will try to reallocate the portrait context in that moment if you are making any hinderance through code you will encounter with the issue

     Here another thing you need to notice the root pointer will be the summation of all spaces allocated by the View Components and View Child's then you can imagine its importance these statistics you can be clearly identified when you load a binary .hprof file to MAT tool in eclipse which i specified as last of this article



          I already specified below an example log cat when ever you are on a leaking code when you make orientation in screen you can see in logcat the leaked memory status you can see your heap free statistics decreasing for more info you can see below log cat explanations




         Thanks to Google as i had noticed from Honey Comb onwards they are collecting the bitmap object in right manner as they move this task from GC_EXTERNAL_ALLOC to GC_CONCURRENT you can see that in log cat so there will not be much out of memory issue  due to bitmap from Honey Comb onwards but still the second matter about Context leaking on Screen Orientation is there so we need to take care that

    Best way to analyze this memory leaks are put a tight monitoring on the logcats coming you can see that just put adb logcatt filter by giving the process id in command prompt


    eg: D/dalvikvm(9050): GC_CONCURRENT freed 2049k, 65% free 3751K/9991k, external 4703k/5261k, paused 2ms+2ms

         Just anlayze the message
     First one is reason for Garbage Collection there are 5 reasons when a GC calls

     GC_CONCURRENT :
               It is a collection which will be kicked by the OS itself when they seems that
   the heap is touching the VM budget (16/24mb) and it is a safe collection now after honeycomb they moved bitmaps into this category which is a good sign for developers they will take care its deallocation but keep in mind don't make any static reference to bitmaps allow them to deallocate properly without any hindrance

     GC_FOR_MALLOC:
             This is basically the OS cant able to finish the Concurrent garbage collection in time so that your application needs some memory in that case OS calls GC_FOR_MALLOC which will deallocate some memory from outside your application and make sure it makes the room for you

     GC_EXTERNAL_ALLOC:
     which will not be seen from Honeycomb because in older version they were used this for pixel allocation in Bitmaps which is a problem for developers but now they moved this to GC_CONCURRENT from honeycomb onwards

    GC_HPROG_DUMP_HEAP:
    Which you will see when you trying to dump the heap memory binary data to a .hprof file which is useful i will discuss in last of this article

     GC_EXPLICIT:
       That is developer when explicitly calls to collect that is our System.gc();
   
other message comments are

      freed 2049k: that is you can see amount of memory freed from this collection you can see here 2049k

     
     65% free 3751K/9991k: that is our heap statistics 65% are free now using 3751 out of 9991k

     external 4703k/5261k: that is as i said the memory which they externally allocated for storing the pixel buffers in below Honeycomb version

     paused 2ms+2ms: the time taken to GC to complete its operation if your heap is small it will take less time other wise long time.


     So monitoring the log is a basic way but it is difficult and tedious so what you can do is you have the option in Eclipse tool where you can dump the heap memory and save in your local machine in .hprof format then Download the Eclipse Memory Analyzer (MAT) from http://eclipse.org/mat and load the .hprof file which you saved. There goes you can see the statistics and you can find out the memory leaks everything. And also be handy with ActivityManager.getMemoryClass() which helps at the time of Development.

Thanks
Roger Gasper