Friday 4 August 2017

Localization implementation in android apps

The Language translation for the android apps to support the Localization.

In android apps, if you want to support multiple languages then you have to provide the strings.xml file for every language . Now this file is to be there in the values folder for the languages .
The pattern to create a language folder is

values-<language code>-<country code>

→ language code is a 2 alphabets code that signifies the language like es for Spanish
→ country code is again a 2 alphabet code that signifies the country or the region in the country like IN for India, US for america.
→ region can also be defined for a language being used in more than one regions in a countries with a 'r' prefix to the country code.

Examples of values folder -

values-en-US → this is for english language in USA
values-it_IT → for italian in Italy
values-it-CH → for italian in Switzerland.

Now to generate such files is a cumbersome task if you tend to do it all on your own.

So here is a method to generate the strings.xml file for every language . What we need to do prior to it is make a list of all the strings used in the app like this


Play
Share
Details
Hide
OK
File name :
TimeStamp :
Location :

Now in this file you may keep changing the translations in all languages like chinese simplified

分享
细节
隐藏
文件名 :
时间戳
位置 :


So finally we make values folder in our app res like this for chinese simplified → values-zh_CN with the strings.xml file from the common values folder so that its having the tags in the proper format .
Like :
<string name="play">Play</string>
<string name="share">Share</string>
<string name="details">Details</string>
<string name="Hide">Hide</string>
<string name="generic_ok">OK</string>
<string name="fileName">File name :</string>
<string name="timestamp">TimeStamp :</string>
<string name="location">Location :</string>


Now here is the Java program that we may use to generate the localized folder for chinese language with the <string> tags in it . What we are doing hers is just replacing the value in the string tag in the above sequence itself

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


public class Mainclass {

public static void main(String argv[]) {

BufferedReader br = null;
FileReader fr = null;

try {
File readFromFile = new File("D:/Localization/strings.xml");

fr = new FileReader(readFromFile);
br = new BufferedReader(fr);

String sCurrentLine;

File fXmlFile = new File("D:/app/src/main/res/values-zh-rCN/strings.xml");

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);

doc.getDocumentElement().normalize();

NodeList nList = doc.getElementsByTagName("string");

System.out.println("----------------------------");

for (int temp = 0; temp < nList.getLength(); temp++) {

if(temp!=1){
Node nNode = nList.item(temp);
sCurrentLine = br.readLine();
nNode.setTextContent(sCurrentLine);
}

}
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(fXmlFile.getAbsolutePath()));
transformer.transform(source, result);

System.out.println("Done");
}
catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {

if (br != null)
br.close();

if (fr != null)
fr.close();

} catch (IOException ex) {
ex.printStackTrace();
}

}


}
}


Now this reads the chinese language strings from the strings.xml file and keeps replacing the content in the values-zh_CN/strings.xml file to make the chinese localized strings.xml file.

Few locale codes that I have in my glossary are :


Language codes can be found here : http://www.science.co.il/language/Locale-codes.php

Language / Locale Supported since version

English, US (en_US) 1.1
German, Germany (de_DE) 1.1
Chinese, PRC (zh_CN) 1.5
Chinese, Taiwan (zh_TW) 1.5
Czech, Czech Republic (cs_CZ) 1.5
Dutch, Belgium (nl_BE) 1.5
Dutch, Netherlands (nl_NL) 1.5
English, Australia (en_AU) 1.5
English, Britain (en_GB) 1.5
English, Canada (en_CA) 1.5
English, New Zealand (en_NZ) 1.5
English, Singapore(en_SG) 1.5
French, Belgium (fr_BE) 1.5
French, Canada (fr_CA) 1.5
French, France (fr_FR) 1.5
French, Switzerland (fr_CH) 1.5
German, Austria (de_AT) 1.5
German, Liechtenstein (de_LI) 1.5
German, Switzerland (de_CH) 1.5
Italian, Italy (it_IT) 1.5
Italian, Switzerland (it_CH) 1.5
Japanese (ja_JP) 1.5
Korean (ko_KR) 1.5
Polish (pl_PL) 1.5
Russian (ru_RU) 1.5
Spanish (es_ES) 1.5
Arabic, Egypt (ar_EG) 2.3
Arabic, Israel (ar_IL) 2.3
Bulgarian, Bulgaria (bg_BG) 2.3
Catalan, Spain (ca_ES) 2.3
Croatian, Croatia (hr_HR) 2.3
Danish, Denmark(da_DK) 2.3
English, India (en_IN) 2.3
English, Ireland (en_IE) 2.3
English, Zimbabwe (en_ZA) 2.3
Finnish, Finland (fi_FI) 2.3
Greek, Greece (el_GR) 2.3
Hebrew, Israel (iw_IL)* 2.3
Hindi, India (hi_IN) 2.3
Hungarian, Hungary (hu_HU) 2.3
Indonesian, Indonesia (in_ID)* 2.3
Latvian, Latvia (lv_LV) 2.3
Lithuanian, Lithuania (lt_LT) 2.3
Norwegian-Bokmål, Norway(nb_NO) 2.3
Portuguese, Brazil (pt_BR) 2.3
Portuguese, Portugal (pt_PT) 2.3
Romanian, Romania (ro_RO) 2.3
Serbian (sr_RS) 2.3
Slovak, Slovakia (sk_SK) 2.3
Slovenian, Slovenia (sl_SI) 2.3
Spanish, US (es_US) 2.3
Swedish, Sweden (sv_SE) 2.3
Tagalog, Philippines (tl_PH) 2.3
Thai, Thailand (th_TH) 2.3
Turkish, Turkey (tr_TR) 2.3
Ukrainian, Ukraine (uk_UA) 2.3

Vietnamese, Vietnam (vi_VN) 2.3

Monday 8 May 2017

Making custom View in Android

Custom Views is something that makes the look and feel of application more good. This is a field in which I started my research recently to get better hold in it. So here we have got a multi color custom view . With the help of this tutorial , you can get the complete ides of how to make a custom view like pie chart , donut view, raindow etc.
Its really fun when you understand something so easily , that you thought earlier to be very tough .

Lets begin ..

To start with we need to have a custom style declared in the attributes . For this we make a new file in the values folder named "attrs.xml".
   

<?xml version="1.0" encoding="utf-8"?><resources>
    <declare-styleable name="CustomMultiColorView">
        <attr name="radius" format="dimension"/>
    </declare-styleable>
</resources>


For implementing the custom view we need to have a class extending the View class and overriding the onDraw() of it to draw the actual view .In this custom class, we need to have one of the constructor from the View class to make the initialisation of the default values.

The class is named CustomMultiColorView.java  and looks like this :

public class CustomMultiColorView extends View {

    public CustomMultiColorView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
@Overrideprotected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
}
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

  }

In this class,  the default constructor is taken with two arguments. The AttributeSet will help us to fetch the defaults and the structure from the attrs.xml. The paint object is initialised with the deaults in here too to perform the actual drawing on the canvas . The constructor definition looks some what like this :

public CustomMultiColorView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.CustomMultiColorView);
    try {
        radius = typedArray.getDimension(R.styleable.CustomMultiColorView_radius, 20.0f);
    } finally {
        typedArray.recycle();
    }
    paint = new Paint();
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(radius/13.0f);
    paint.setAntiAlias(true);// for crisper edges
    outerCircle = new RectF(); // for making the outer circle 
    innerCircle = new RectF();  // for making the inner circle
}

Now the main part , the drawing of the object . Since we will be providing shadow to the object so we need to initialise the setShadowLayer for the paint object .
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    paint.setShader(null); //pass null to clear any previous color or shader    float adjust = (0.0095f*radius);
    paint.setShadowLayer(8,adjust,-adjust,0xaa000000);

    setLayerType(LAYER_TYPE_SOFTWARE, paint);
    //this makes a space for the outer circle with some padding from the border    
    // in that area we display the shadow, to avoid the circle to look cut opn edges    adjust= (0.076f* radius);
    outerCircle.set(adjust, adjust , radius*2 - adjust, radius*2 -adjust);
    adjust= (0.076f* radius);
    innerCircle.set(adjust, adjust , radius*2 - adjust, radius*2 -adjust);

    setGradient(0xff84BC3D,0xff5B8829);
    drawCircle(canvas,paint,0,60);

    setGradient(0xffe04a2f,0xffB7161B);
    drawCircle(canvas,paint,60,60);

    setGradient(0xff4AB6C1,0xff2182AD);
    drawCircle(canvas,paint,120,60);

    setGradient(0xffFFFF00,0xfffed325);
    drawCircle(canvas,paint,180,60);

    setGradient(0xffe04a2f,0xffB7161B);
    drawCircle(canvas,paint,240,60);
    
    setGradient(0xff4AB6C1,0xff2182AD);
    drawCircle(canvas,paint,300,60);
}

private void setGradient(int i, int i1) {
    paint.setShader(new RadialGradient(radius,radius,radius-10, i,i1, Shader.TileMode.CLAMP));
}

private void drawCircle(Canvas canvas, Paint paint, int i, float v) {
    canvas.drawArc(outerCircle,i,v,false,paint);
}
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int desiredHeight = (int)radius*2;
    int desiredWidth = (int)radius*2;

    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    int width ; int height;

    if(widthMode ==MeasureSpec.EXACTLY)
        width = widthSize;
    else if(widthMode == MeasureSpec.AT_MOST)
        width = Math.min(desiredWidth,widthSize);
    else        width = desiredWidth;
    if(heightMode ==MeasureSpec.EXACTLY)
        height = heightSize;
    else if(heightMode == MeasureSpec.AT_MOST)
        height = Math.min(desiredHeight, heightSize);
    else        height = desiredHeight;

    //MUST CALL THIS TO SET THE FINAL DIMENSIONS    setMeasuredDimension(width,height);

}

The xml looks something like this :


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    
xmlns:app="http://schemas.android.com/apk/res-auto"    
xmlns:customViews ="http://schemas.android.com/apk/res/sample.com.customviewtutorial"    
xmlns:tools="http://schemas.android.com/tools"    
android:layout_width="match_parent"    
android:layout_height="match_parent"    
android:orientation="vertical"    
tools:context="sample.com.customviewtutorial.MainActivity">
    
    <sample.com.customviewtutorial.DonutView        
android:id="@+id/circle_view"        
android:layout_width="wrap_content"        
android:layout_height="wrap_content"        
android:layout_gravity="center"        
customViews:radius = "90dp"/>
</LinearLayout>


The resultant to this is a view that looks something like this




As you can see we have multi colored circle with shadow for each color beside it inwards and outwards.
The angle sent in the setGradient() set the gradient color and the drawCircle() functions marks the drawing of the arc from and to the angle entered .


Stay tuned with us .. In next tutorial I will write on how to rotate this .

Monday 6 February 2017

Remove extra spaces from an image

Remove extra spaces from an image 


I required an image with no side spaces as I had one with. So after going througha lot of help over the internet i could find a portion removal code. And now finally I have my code for the all four side spaces removal.
Here we go :


public static Bitmap TrimBitmap(Bitmap bmp) {
    int imgHeight = bmp.getHeight();
    int imgWidth  = bmp.getWidth();


    //TRIM WIDTH - LEFT
    int startWidth = 0;
    for(int x = 0; x < imgWidth; x++) {
        if (startWidth == 0) {
            for (int y = 0; y < imgHeight; y++) {
                if (bmp.getPixel(x, y) != Color.TRANSPARENT) {
                    startWidth = x;
                    break;
                }
            }
        } else break;
    }


    //TRIM WIDTH - RIGHT
    int endWidth  = 0;
    for(int x = imgWidth - 1; x >= 0; x--) {
        if (endWidth == 0) {
            for (int y = 0; y < imgHeight; y++) {
                if (bmp.getPixel(x, y) != Color.TRANSPARENT) {
                    endWidth = x;
                    break;
                }
            }
        } else break;
    }



    //TRIM HEIGHT - TOP
    int startHeight = 0;
    for(int y = 0; y < imgHeight; y++) {
        if (startHeight == 0) {
            for (int x = 0; x < imgWidth; x++) {
                if (bmp.getPixel(x, y) != Color.TRANSPARENT) {
                    startHeight = y;
                    break;
                }
            }
        } else break;
    }



    //TRIM HEIGHT - BOTTOM
    int endHeight = 0;
    for(int y = imgHeight - 1; y >= 0; y--) {
        if (endHeight == 0 ) {
            for (int x = 0; x < imgWidth; x++) {
                if (bmp.getPixel(x, y) != Color.TRANSPARENT) {
                    endHeight = y;
                    break;
                }
            }
        } else break;
    }


    return Bitmap.createBitmap(
            bmp,
            startWidth,
            startHeight,
            endWidth - startWidth,
            endHeight - startHeight
    );

}


Explanation: For each side of the image, a FOR loop is run to check if pixels does not contains transparent color, returning the first non-transparent pixel useful coordinate. This is done elaborating coordinates using as a base the opposite dimension than the dimension to trim: to find y, scan x for every y.
To check where the Vertical-Top blank space ends, it runs the following steps:
1. Starting is from the top row (y=0)
2. Checks all the columns of the row (x from 0 to imageWidth)
3. If a non-transparent pixel is found, break the loop and save the y coordinate. Otherwise continue.
4. At the ending of the columns, go to the next row (y+1) and start checking columns agains. Break if a non-transparent pixel has already been found.

Similiar methods are used for the other dimensions, only changing the direction of the scan.
Once obtained the 4 coordinates for the first useful pixels of the image, the Bitmap.createBitmapmethod is invoked, with the original bitmap as a base image, and the useful pixels coordinates as Top-Left and Bottom-Right limits for the resize.


Note 1: It is useful to note that the coordinates 0, 0 equals to Top-Left.
Note 2: The ending width and height in Bitmap.createBitmap are reduced by the new starting relative coordinate, otherwise the new image will have the boundaries wrongly pushed bottom-right. Figure it like this: you have an image 100x100px, so with ending coordinates 100,100. Changing the starting coordinates to 50,50 will bring the ending coordinates of your elaboration rectangle to 150,150 (100 original coordinate + 50 of modified starting point), pushing it outside the original image boundaries. To avoid this, the new ending coordinate is reduced by the new starting coordinate (100 + 50 new starting coord - 50 new starting coord adjustment)
Note 3: in the original answer, a check for all the pixels in a given direction is run using the same dimension of the coordinate to find, returning the most advanced useful pixel. Checking the opposite dimension and stopping at the first useful pixel increased performances.

Sunday 5 February 2017

Multiple dialogs creation in Android

Multiple dialogs creation in Android is a common problem .Let's seek solution to it

Today we will discuss on how to avoid creation of multiple dialog from the same piece of code.

The key is to maintain a counter and if its 0 , that means no dialog is showing now then only show a dialog. And on every dismissal of the dialog we reduce that counter to maintain the count of the dialog shown . That means at one time it should be not more than one .
 
   //the counter to maintain the showing status of the dialog
   private static int dialog_count =0;
    private Dialog dialog=null;
   
    public void showAlertDialog(final Context context, Activity activity) {

        ListAdapter arrayAdapter;
        final ArrayList<Language> arraylist = new ArrayList<>();
        Integer[] imageId = {
                R.drawable.british_english_flag,
                R.drawable.swedish_flag_small,
                R.drawable.italian_flag
        };

        final String[] languages = context.getResources().getStringArray(R.array.language_list);
        for (int i = 0; i < languages.length; i++) {
            Language langObj = new Language(languages[i].substring(3, languages[i].length()), imageId[i]);
            arraylist.add(langObj);
        }
        arrayAdapter = new LanguageArrayAdpater(activity, arraylist);

        dialog = new Dialog(mContext);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);

     
        View view = mActivity.getLayoutInflater().inflate(R.layout.dialog_layout, null);

        ListView lv = (ListView) view.findViewById(R.id.listView_language);
        TextView tv_header = (TextView) view.findViewById(R.id.dialog_header);
        tv_header.setTypeface(Utility.setTypeFace(Defines.font_OpenSansRegular));

        lv.setAdapter(arrayAdapter);

        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String selectedVal = arraylist.get(position).getName();
                Log.d(TAG, "chosen " + selectedVal);
                dialog.dismiss();
//if an item is selected and the dialog was showing then reduce the dialog counter and perform the required action
                if(dialog_count>0)
                    dialog_count--;
                saveInPrefs(languages,context, position, selectedVal);
            }
        });

        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {
                System.out.println("dialog count dismissing :"+ dialog_count);
//if the dialog was cancelable then on dismissing it we reduce the count so that we have proper data in the counter
                if(dialog_count>0)
                    dialog_count--;
                System.out.println("dialog count dismissed :"+ dialog_count);
            }
        });
        dialog.setContentView(view);
//show the dialog only if we have no dialog showing currently.
        if(dialog_count==0) {
            dialog.show();
            dialog_count++;
        }

To show dialog from outside the activity Android

To show dialog from outside the activity



Suppose you have a requirement to show the dialog from outside the activity or to show dialog from more than one activity or fragment .
So the efficient solution to it is to show it from a common method in some file .For this an approach that I found is to just implement the function call to show the dialog in a common file and make a call to it from all of your required places.


This looks good . But what if on the basis of the response “YES”, or “NO”, selected by the user requires you to perform some functionality on the calling class view ,like calling an api or updating the activity views. Then we will required to implement a callback for the selected result.


Example here shows a function showing the list of chocolates in a dialog . The list contains an image an text on the right of it.
The layout I made is :


<?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"
   android:background="@color/bgcolour_sharepoints">


  <TextView
      android:id="@+id/dialog_header"
      android:textColor="@color/black"
      android:textSize="18sp"
      android:padding="@dimen/margin_10dp"
      android:layout_width="match_parent"
      android:text="@string/select_language"
      android:layout_height="wrap_content" />
  <View
     android:background="@color/black"
      android:layout_width="match_parent"
      android:layout_height="1dp"/>
  <ListView
      android:id="@+id/listView_chocolate"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"/>
</LinearLayout>


Function to show the dialog :
String selectedVal ;
   public void showChocListDialog(final Context context, Activity activity) {


       ListAdapter arrayAdapter;
       final ArrayList<Chocolate> arraylist = new ArrayList<>();
//these drawables are present in the drawable folder
       Integer[] imageId = {
               R.drawable.silk,
               R.drawable.dairymilk
       };


// chocolates_list is a string array in the strings.xml file
       final String[] chocolates= context.getResources().getStringArray(R.array.chocolates_list);
       for (int i = 0; i < chocolates.length; i++) {
           Language chocObj = new Language(languages[i].substring(3, languages[i].length()), imageId[i]);
           arraylist.add(chocObj);
       }
       arrayAdapter = new ChocolateArrayAdpater(activity, arraylist);


       dialog = new Dialog(mContext);
       dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);


      View view = mActivity.getLayoutInflater().inflate(R.layout.dialog_layout, null);


       ListView lv = (ListView) view.findViewById(R.id.listView_chocolate);
       TextView tv_header = (TextView) view.findViewById(R.id.dialog_header);
       lv.setAdapter(arrayAdapter);


       lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
           @Override
           public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
               selectedVal = arraylist.get(position).getName();
//will dicsuss about this line later.    
mListener._func_chocolateSetup();
               Log.d(TAG, "chosen " + selectedVal);
               dialog.dismiss();      
           }
       });
       dialog.setContentView(view);
       dialog.show();
   }


The above function shows how to display a dialog with a list view of items . Items contains an imageview and a text view . On clicking the an item from the list , we save the selected item in a variable to be used later .
Note : This method is written in a common class , u can name it anything like Utility or Utils, Common as per your conveniece.


As you can see we have used a model class in this named Chocolate and an array adapter named ChocolateArrayAdapater , well this is required to populate the list .
Their definition is as below:


   static Chocolate {
       private String name;
       private int image_id;


       Chocolate(String name, int imageid) {
           this.name = name;
           this.image_id = imageid;
       }


       public String getName() {
           return name;
       }


       public void setName(String name) {
           this.name = name;
       }


       int getImage_id() {
           return image_id;
       }


       public void setImage_id(int image_id) {
           this.image_id = image_id;
       }
   }


//the array adpater definition
   private class ChocolateArrayAdpater extends ArrayAdapter<Chocolate> {


       private final List<Chocolate> list;
       private final Activity context;


       class ViewHolder {
           protected TextView name;
           ImageView iv_country;
       }


       ChocolateArrayAdpater(Activity context, List<Chocolate> list) {
           super(context, R.layout.Chocolate_row, list);
           this.context = context;
           this.list = list;
       }


       @NonNull
       @Override
       public View getView(int position, View convertView, ViewGroup parent) {
           View view;
           if (convertView == null) {
               LayoutInflater inflator = context.getLayoutInflater();
               view = inflator.inflate(R.layout.Chocolate_row, null);
               final ChocolateArrayAdpater.ViewHolder viewHolder = new ChocolateArrayAdpater.ViewHolder();
               viewHolder.name = (TextView) view.findViewById(R.id.list_value);
               viewHolder.iv_country = (ImageView) view.findViewById(R.id.iv_country);
               view.setTag(viewHolder);
           } else {
               view = convertView;
           }


           ChocolateArrayAdpater.ViewHolder holder = (ChocolateArrayAdpater.ViewHolder) view.getTag();
           holder.name.setText(list.get(position).getName());
           holder.iv_country.setBackgroundDrawable(context.getResources().getDrawable(list.get(position).getImage_id()));
           return view;
       }
   }


No for multiple activity or fragment to interact with this piece of code in the Common class we needs a mediator , this cannot be done directly.
So we define and interface in the same Common Class in our project like this :


   public interface I_Chocolatestup
   {
       void _func_chocolateSetup();
   }


In the common class for interaction with the activities and fragments in your app , we do this :


//the mListener to initialize the class which will receive the call back
  private I_Chocolatestup mListener;
   private final Context mContext;
   private final Activity mActivity;
   public Utility(Context context, I_Chocolatestup listener,Activity mActivity) {
       mContext = context;
       mListener = listener;
       this.mActivity = mActivity;
   }


Remember we wrote a line in the function to show the dialog which we wrote to discuss later . now is the correct time.
mListener._func_chocolateSetup();


This is meant to call the class that will intialiaze its context in the Utility() so that the class gets the callback to perform the action based on the selected values.


Till this point all of the code is to be in the Common Utility class


Now is the part for the Activity/Fragment  class.


For all the classes that want to display this dialog , we implement this interface in them like this:


public class ChocolateSelectionActivity extends WifogFragmentActivity implements Utility.I_Chocolatestup


So we have to override the function in the interface :
   @Override
   public void _func_chocolateSetup() {
     //perform your action whatever you want
   }


Now the final and climax line to trigger the showing of the dialog and initializing the context to the listener to get the call back :


Utility utilObj;
utilObj = new Utility(this,this,this);
utilObj.showChocolateListDialog(this.getActivity(), this.getActivity());


Finally its done. Now use the showChocolateListDialog() as  many places as you want without redundant codes in the classes .


In next blog I will tell you on how can you avoid creation of multiple dialogs from same piece of code.

Localization implementation in android apps

The Language translation for the android apps to support the Localization. In android apps, if you want to support multiple languages ...