Monday, 23 March 2015

Android Architecure

Overview


Android is a software package and Linux based operating system for mobile devices such as tablet computers and smartphones.

Android operating system is a stack of software components which is roughly divided into four main layers as shown below in the architecture diagram.


Android software stack

Linux kernel and a collection of C/C++ libraries are exposed through an
application framework which manages and provides the services for the application at run time.



Understand the Architecture layers in brief.


1. Application Layer.




Application Layer the topmost layer of android architecture contains all               android applications, the native applications provided with the particular Android implementation (for example web browser, contacts and email applications etc) and the third party applications installed by the user after purchasing the device.



2. Application Framework.



Android applications directly interacts with application framework. Application framework includes Android API's such as UI (User Interface), telephony, resources, locations, Content Providers (data) and package managers. It provides a lot of classes and interfaces for android application development. It also provides a generic abstraction for hardware access and manages the user interface and application resources.

Let's understand what actually framework API's do.

Activity Manager
    Used to manage complete activity life cycle of applications

Content Providers 
Used to manage the data sharing between two applications                                
Telephony Manager
    Used to manages all voice calls

Location Manager
    Used to manage the Locations obtained using GPS or cell tower                      
Resource Manager
    Used to manage the different types of resources used in android app    

Views                
    Used to construct the user interfaces for activities.

Notification Manager  
    Used to tell the user that something has happened in the background.



3. Libraries and Android run time


Libraries:-
It provides the different libraries useful for well functioning of android operating system. Libraries are written in java and C/C++ languages build specific for android operating system.


SQLite
 It is used to access data published by content providers and includes SQLite database management classes

SSL
 It is used to provide internet security

OpenGL
 It is used to provide Java interface to the OpenGL/ES 3D graphics rendering    API.

Media framework
 It is used to provides different media codecs which allow the recording and  playback of different media formats

WebKit
 It is the browser engine used to display internet content or HTML content

FreeType
 It is used for font support

Android run time.
 In android run time, there are core libraries and DVM (Dalvik Virtual Machine)  which is responsible to run android application. DVM is like JVM but it is  optimized for mobile devices. It consumes less memory and provides fast  performance.

Linux Kernel

Linux Kernel provides the basic system functionality such as process management, memory management and device management. Linux kernel also provides array of device drivers which make our task easier while interfacing the android with peripheral devices

Saturday, 28 February 2015

Activity life cycle in android

 Overview

Android Activity is the basic building block of an Android App. It’s a window that contains the user interface of your application. Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI with setContentView(View). But there can be activities without UI. In short, activity is a something that the user is able to see in an application and which is responsible for performing user interactions, operations etc.
Typically, one activity in an application is specified as the "main" activity, also called launcher activity, which is presented to the user when launching the application for the first time. Each activity in android has its own life throughout the application and so life-cycle methods. Below diagram illustrate about activity life-cycle in brief.

Acitivity Life Cycle Flow


OnCreate():-

Called when the activity is first created. This is where you should do all of your normal static set up — create views, bind data to lists, and so on. This method is passed a Bundle object containing the activity's previous state, if that state was captured (will see how to capture activity state lateron). Always followed by onStart().


onStart():-

Called just before the activity becomes visible to the user. Followed by onResume() if the activity comes to the foreground, or onStop() if it becomes hidden. We can also say the activity is partially visible to user in onStart().


onResume():-

Called just before the activity starts interacting with the user. At this point the activity is at the top of the activity stack, with user input going to it.
Always followed by onPause().


onPause():-

Called when the system is about to start resuming another activity. This method is typically used to commit unsaved changes to persistent data, stop animations, unregistering broadcast receivers and other things that may be consuming CPU or leads to memory leak, and so on. It should do whatever it does very quickly, because the next activity will not be resumed until it returns. 
Followed either by onResume() if the activity returns back to the front, or by onStop() if it becomes invisible to the user.


onStop():-

Called when the activity is no longer visible to the user. This may happen because it is being destroyed, or because another activity (either an existing one or a new one) has been resumed and is covering it. We can also say the activity is partially visible to user in onStop().
Followed either by onRestart() if the activity is coming back to interact with the user, or by onDestroy() if this activity is going away.


onRestart():-

Called after the activity has been stopped, just prior to it being started again. This method is always called after onStop() if and only if the app is not killed by system in onStop().
Always followed by onStart().


onDestroy():-

This is the method which will be called when your Activity is getting killed. This is the final call the Activity will receive in its Lifecycle.
When the user press back button on any Activity the foreground activity gets destroyed and control will return to the previous Activity.
But remember the fact, there is no guaranty that onDestroy will be called. Only when the system is low on resources or user press the back button or if you use finish() explicitly in your code, onDestroy gets called.

Let’s observe Activity life cycle methods under different circumstances.

When app launches

onCreate() --> onStart() -->  onResume()

When home button pressed

onPaused() --> onStop()

After pressed home button when again open app from recent task list or clicked on icon

onRestart() --> onStart() --> onResume()

When back button pressed and exit the app

onPaused() -- > onStop() --> onDestory()

When open app another app from notification bar or open settings

onPaused() --> onStop()

Back button pressed from another app or settings then used can see our app

onRestart() --> onStart() --> onResume()

When any dialog open on screen

onPause()

After dismiss the dialog or back button from dialog

onResume()

There are four states an activity can possibly exist:

Starting State
Running State
Paused State
Stopped state

Starting state involves:

Creating a new Linux process, allocating new memory for the new UI objects, and setting up the whole screen. So most of the work is involved here.

Running state involves:

It is the activity (state) that is currently on the screen. This state alone handles things such as typing on the screen, and touching & clicking buttons.

Paused state involves:

When an activity is not in the foreground and instead it is in the background, then the activity is said to be in paused state.

Stopped state involves:

A stopped activity can only be bought into foreground by restarting it and also it can be destroyed at any point in time.

The activity manager handles all these states in such a way that the user experience and performance is always at its best even in scenarios where the new activity is added to the existing activities


Now lets go practically into android life cycle.
I have written the two demo examples to understand the Android Life cycle in depth.
1) AndroidLifeCycleMine:- 






























                                        You can find the source code here ActivityLifeCycleProjectMine





2) AndroidLifeCycle demo in multiple situation:- 
This example iulstrate in brief about Activity states when another Activity comes in picture and when dialog appears on the Activity.
 

 

You can find the source code here ActivityLifeStates in different situations.

Now look towards Activity in a professional way. Because the professional minds are always key to "Invention". Below are some points about this topic which you may come across during an interview.

 What will be the Activity state when you press the menu option.

 Ans:- Paused state - and life cycle method onPause().

What if you call finish() method in various Activity callback methods.

 Ans:-  If finish() is called in oncreate() then directly onDestroy() will be called.

If  finish() is called in onStart() then onResume() will not be called and Obviously if onResumed is not called then onPause() will not be called it means after onStart() directly() onStope() and onDestroy() will called().

If finish() is called in onResume() then all life cycle methods followed by onResume() will be called.

If finish() is called in onPause() then all life cycle methods followed by onPause() will be called means onStope() and onDestroy().

If finish() is called in onStope() then all life cycle followed by onStope() will be called.

The onCreate() and onDestroy() methods are called only once throughout the activity lifecycle.

If you have any point about Activity which you feel the professional minds should know then please comment it.


Monday, 19 January 2015

GCM(Google Cloud Messaging) Integration in android

Work is under progress...
public interface APIResponseReceiver {

    int onDataReceived(String response);

    void getResult(int resultCode);
}






import android.content.Context;
import android.util.Log;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;


/** * Created by Yograj Shinde on 1/9/15,2:30 PM. */public class CallAPI {

    private final String TAG = "Mehboob";
    private Context mContext;
    private String response = "";
    private URL mUrl;
    private HttpURLConnection httpURLConnection;

    public CallAPI(Context context) {
        this.mContext = context;
    }

    /**     * This method will upload image and return response     */    public String uploadImage(String url, String imagePath, String keyName ,HashMap<String, String> postDataParams) {
        DataOutputStream dos;
        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary = "*****";
        int bytesRead, bytesAvailable, bufferSize;
        byte[] buffer;
        int maxBufferSize = 1024 * 1024; // 1 * 1024 * 1024
        File sourceFile = new File(imagePath);
        FileInputStream fileInputStream;
        response = "";

        try {
            mUrl = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            mUrl = null;
        }
        if (mUrl != null) {
            Log.d(TAG, "File path:- " + imagePath);
            if (sourceFile.isFile()) {
                try {
                    fileInputStream = new FileInputStream(sourceFile);

                    // Open a HTTP  connection to  the URL                    httpURLConnection = (HttpURLConnection) mUrl.openConnection();
                    httpURLConnection.setDoInput(true);
                    httpURLConnection.setDoOutput(true);
                    httpURLConnection.setUseCaches(false); // Don't use cached copy                    httpURLConnection.setRequestMethod("POST");
                    httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
                    httpURLConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

                    dos = new DataOutputStream(httpURLConnection.getOutputStream());

                    //Add HashMap Data here                   // dos.writeBytes(getPostDataString(postDataParams));                    for (Map.Entry<String, String> entry : postDataParams.entrySet()) {

                        // add parameters                        dos.writeBytes(twoHyphens + boundary + lineEnd);
                        dos.writeBytes("Content-Disposition: form-data; name=" + entry.getKey()
                                + lineEnd);
                        dos.writeBytes(lineEnd);

                        // assign value                        dos.writeBytes(entry.getValue());
                        dos.writeBytes(lineEnd);
                        dos.writeBytes(twoHyphens + boundary + lineEnd);
                    }

                    // send image                    dos.writeBytes(twoHyphens + boundary + lineEnd);
                    dos.writeBytes("Content-Disposition: form-data; name=\""+keyName+"\";filename=\"" + sourceFile.getName() + "\"" + lineEnd);
                    dos.writeBytes(lineEnd);

                    // create a buffer of  maximum size                    bytesAvailable = fileInputStream.available();

                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    buffer = new byte[bufferSize];

                    // read file and write it into form...                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                    while (bytesRead > 0) {
                        dos.write(buffer, 0, bufferSize);
                        bytesAvailable = fileInputStream.available();
                        bufferSize = Math.min(bytesAvailable, maxBufferSize);
                        bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                    }

                    // send multipart form data necessary after file data...                    dos.writeBytes(lineEnd);
                    dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

                    int serverResponseCode = httpURLConnection.getResponseCode();
                    Log.i(TAG, "Server Response Code:- " + serverResponseCode);
                    Log.i(TAG, "Server Response Message:- " + httpURLConnection.getResponseMessage());

                    InputStream inputStream = httpURLConnection.getInputStream();
                    response = convertStreamToString(inputStream);

                    //close the streams                    fileInputStream.close();
                    dos.flush();
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return response;
    }

    /**     * This method will call webservice and returns response     */    public String getAPIResponse(String url, HashMap<String, String> postDataParams) {
        response = "";
        try {
            mUrl = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            mUrl = null;
        }
        if (mUrl != null) {


            try {
                // Open a HTTP  connection to  the URL                httpURLConnection = (HttpURLConnection) mUrl.openConnection();
                httpURLConnection.setDoInput(true);
                httpURLConnection.setDoOutput(true);
                httpURLConnection.setUseCaches(false);
                httpURLConnection.setConnectTimeout(15000);
                httpURLConnection.setReadTimeout(20000);
                httpURLConnection.setRequestMethod("POST");
                httpURLConnection.setRequestProperty("Content-Type",
                        "application/x-www-form-urlencoded");
                DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());
                wr.writeBytes(getPostDataString(postDataParams));
                wr.flush();
                wr.close();
                InputStream inputStream = httpURLConnection.getInputStream();
                response = convertStreamToString(inputStream);
                httpURLConnection.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return response;
    }

    private String convertStreamToString(InputStream inputstream) {
        String line;
        StringBuilder total = new StringBuilder();
        BufferedReader rd = new BufferedReader(new InputStreamReader(
                inputstream));
        try {
            while ((line = rd.readLine()) != null) {
                total.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return total.toString();
    }

    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        if (params == null || params.isEmpty()) {
            result.append("");
        } else {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                if (first)
                    first = false;
                else                    result.append("&");

                result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
                result.append("=");
                result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            }
        }
        Log.d(TAG, "Param:- " + result.toString());
        return result.toString();
    }
}








package com.eeshana.qisma.network;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

import com.eeshana.qisma.R;
import com.eeshana.qisma.utilities.CommonUsage;
import com.eeshana.qisma.utilities.Config;

import java.util.HashMap;


/** * Created by Yograj Shinde on 23/7/15,12:58 PM. */public class MyAsyncTask {
    private Context mContext;
    private ProgressDialog pDialog;
    private CallAPI callAPI;
    private String mURL;
    private HashMap<String, String> arr_param = new HashMap<>();
    private APIResponseReceiver apiResponseReceiver;
    public static String errorMSG = "";
    private CommonUsage mCommonUsage;

    public MyAsyncTask(Context mContext, String url, HashMap<String, String> arr_param, APIResponseReceiver responseReceiver) {
        this.mContext = mContext;
        this.arr_param = arr_param;
        this.apiResponseReceiver = responseReceiver;
        mURL = url;
        mCommonUsage = CommonUsage.getCommonUsageObj(mContext);
        callAPI = new CallAPI(mContext);
        new MyAsync().execute(arr_param);
    }

    class MyAsync extends AsyncTask<HashMap<String, String>, Integer, Integer> {

        @Override        protected void onPreExecute() {
            super.onPreExecute();
            mCommonUsage.showProgressDialog(mContext.getResources().getString(R.string.please_wait));
        }

        @Override        protected Integer doInBackground(HashMap... params) {
            String response = "";
            int resultCode = Config.RESULT_FAIL;
            try {
                response = callAPI.getAPIResponse(mURL, params[0]);
            } catch (Exception e) {
                e.printStackTrace();
                response = "";
            }
            Log.d(Config.TAG, "API Response:- " + response);
            resultCode = apiResponseReceiver.onDataReceived(response);
            return resultCode;
        }


        @Override        protected void onPostExecute(Integer resultCode) {
            super.onPostExecute(resultCode);
            mCommonUsage.dismissmPdialog();

            switch (resultCode) {
                case Config.RESULT_SERVER_ERROR:
                    mCommonUsage.showToast(mContext.getResources().getString(R.string.response_null_error));
                    break;
                case Config.RESULT_PARSE_ERROR:
                    mCommonUsage.showToast(mContext.getResources().getString(R.string.response_parse_error));
                    break;
                case Config.RESULT_FAIL:
                    //mCommonUsage.showToast(errorMSG);                    Log.i("API Status","API Other that 1 msg"+errorMSG);
                    apiResponseReceiver.getResult(Config.RESULT_FAIL);
                    break;
                case Config.RESULT_SUCCESS:
                    apiResponseReceiver.getResult(Config.RESULT_SUCCESS);
                    break;
            }
        }
    }
}






@Overridepublic int onDataReceived(String response) {
    if (response == null || response.equalsIgnoreCase("")) {
        return Config.RESULT_SERVER_ERROR;
    } else {
        try {
            JSONObject jsonObjResult = new JSONObject(response.trim());
            int status = jsonObjResult.getInt("status");
            if (status == 1) {
                if (jsonObjResult.has("data"))
                {
                    
                }

                return Config.RESULT_SUCCESS;
            } else {
               

                Log.i("Got Status","0 here");
                String error;
                if (jsonObjResult.has("statusInfo")) {
                    error = jsonObjResult.getString("statusInfo");
                } else {
                    error = getResources().getString(R.string.response_fail_error);
                }
                MyAsyncTask.errorMSG = error;
                return Config.RESULT_FAIL;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Config.RESULT_PARSE_ERROR;
        }
    }
}



@Overridepublic void getResult(int resultCode) {

    if (resultCode == Config.RESULT_SUCCESS) {
       }
}




public interface Config {

    String GCM_SENDER_ID = "";
    String TAG = "Mehboob App";

    // Result codes    int RESULT_FAIL = 0;
    int RESULT_SUCCESS = 1;
    int RESULT_SERVER_ERROR = 2;
    int RESULT_PARSE_ERROR = 3;
}


HashMap<String, String> param = new HashMap<String, String>();
param.put(ParamKeys.FB_ID, object.getString("id").toString());

if (comObj.isDeviceHasNetwork()) {
    isFbLodgedIn = true;
    new MyAsyncTask(LoginActivity.this, WebServiceURL.VERIFY_FB_ID, param, LoginActivity.this);
} else {
    comObj.showToast(getString(R.string.no_internet_connection));
}




public class CommonUsage {

    private static Context _mContext;
    private static CommonUsage _commonUsageObj;
    private ProgressDialog mProgressDialog;

    public static SharedPreferences common_user_data;

    //Default constructor    public CommonUsage(){}

    public static CommonUsage getCommonUsageObj(Context con){

        _mContext = con;
        if(_commonUsageObj == null)
            _commonUsageObj = new CommonUsage();
            return _commonUsageObj;
    }


   /**
 * This method will print toast at the center of the screen * **/public void showToast(String msg)
{
    Toast tstObj = Toast.makeText(_mContext, msg, Toast.LENGTH_SHORT);
    tstObj.setGravity(Gravity.CENTER, tstObj.getXOffset()/ 2, tstObj.getYOffset()/ 2);
    tstObj.show();
}


/** * Checking for all possible Internet providers * Returns true if connected else fails * * **/
public boolean isDeviceHasNetwork()
{
    ConnectivityManager connectivity = (ConnectivityManager)_mContext.
            getSystemService(Context.CONNECTIVITY_SERVICE);

    if(connectivity != null){
        NetworkInfo[] info = connectivity.getAllNetworkInfo();
        if(info != null)
            for (int i = 0; i < info.length; i++) {
                if(info[i].getState() == NetworkInfo.State.CONNECTED){
                    return true;
                }
            }
    }
    return false;
}


/*** This method will show the processing dialog with given msg** **/
public void showProgressDialog(String msg)
{
    mProgressDialog = new ProgressDialog(_mContext);
    mProgressDialog.setMessage(msg);
    mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    mProgressDialog.setCancelable(false);
    mProgressDialog.setCanceledOnTouchOutside(false);
    if(!((Activity)_mContext).isFinishing()){
        mProgressDialog.show();
    }
}


/** * This method will close the processing dialog which is running now. * * **/public void dismissmPdialog()
{
    try{

        if(mProgressDialog!=null)
        {
            mProgressDialog.dismiss();
            Log.i("GeneralNeedLibM", "progressDialog dismissed successfully");
        }else{
            Log.i("GeneralNeedLibM", "progressDialog dismiss error You might be trying to dismiss the progress dialog" +
                    "which is created with different context Or the progressDialog which not at all created");
        }

    }catch(Exception e)
    {
        e.printStackTrace();
        Log.i("GeneralNeedLibM", ""+e);
        Log.i("GeneralNeedLibM", "progressDialog dismiss exception You might be trying to dismiss the progress dialog" +
                "which is created with different context");
    }


}
}


/*Just Validate empty EditText*/public static boolean Is_Empty_EditText(EditText et){

    String text = et.getText().toString().trim();
    if(text.isEmpty() || text.length()== 0){
        et.requestFocus();
        et.setError("Required!");
    }else{
        et.setError(null);
        return true;
    }

    return false;
}





Stripe Integration in android

Stripe is the simple and best way to accept mobile payments inside any android app.

Steps are as below.

1) First you need to import Stripe library and add it to your project.
   
    On stripe.com you will get the stripe library but it will be a gr-addle support library, you need to convert it to Android project structure. 

2) Add android SDK with API level-17 and android-support-v4 to you SDK if it's not added.
3) Create the Dialog to retrieve Card information from user with the Cancel and Done buttons.        
 
    Required information for card constructor is 
    Card No :- 16 digit, Expiry Date:- MM/YY and Card CVC No :- 3 digit.
    For testing you can use 
    Card No;- 4242 4242 4242 4242
    Expiry Date:- 12/25 (any date grater from current date)
    CVC No :- 123 (any three digits)
    
    if user clicks on the done button of Dialog then get the card info and assign it to the Following fields,

        /*It's better if you create all these fields globally in class*/
        private int cardExpMonth,cardExpYear;
private String cardNumber = "",cardCVC = "";
private static String publishKey = "";
private static Card card;

        In my class I have created this method top retrieve card info from Payment-dialog 
private void getCardInfo()
{
cardNumber = firstFourDigit.getText().toString() + secondFourDigit.getText().toString() 
+ thirdFourDigit.getText().toString() + fourthFourDigit.getText().toString();
cardCVC = ccvCode.getText().toString();
String [] dateMonth =  expiryDate.getText().toString().split("/");
if(!dateMonth[0].isEmpty())
{
cardExpMonth = Integer.parseInt(dateMonth[0]);
if(dateMonth.length == 2 && !dateMonth[1].isEmpty())
{
cardExpYear = Integer.parseInt(dateMonth[1]);
}
}

}

After Successfully retrieving the Card info you need to Validate the Card info creating the card constructor like this

private boolean ValidateCard()
{
//boolean status = false;
card = new Card(
   cardNumber,    // It's String type
   cardExpMonth, //It's int type 2digit
   cardExpYear,  //It's int type 2 digit
   cardCVC    // It's String type
);
                  /*card.validateNumber() will simply validate the 16 digit no provided by the user returns true if the card no is correct false if card no is wrong.*/
if(!card.validateNumber())
{
/*showToast is the method which will Toast the passed String, you can simply call the                            Toast.makeToast.... as well */ 
                        showToast(R.string.invaliCardNo);
return false;
}else if(!card.validateExpiryDate())
{
showToast(R.string.invalideCardDate);
return false;
}else if(!card.validateCVC())
{
showToast(R.string.invalideCardCvc);
return false;
}
return true;
}

4) Get the Publish_key from you server, the publish key is the Stripe account info key. Normally client will provide this key.

create the Stripe instance and call create Token methods like this.


                 try {
Stripe stripe = new Stripe(publishKey);
stripe.createToken(card, 
new TokenCallback() {
@Override
public void onSuccess(Token token) {
Log.i("This is the stripe token here", ""+token);
/*If you enter into onSuccess then Stripe token is created                                                                            successfully, Next pass this token to your Server with                                                                              server required information and if you got success result                                                                          from you server then payment is done successfully.*/
}
@Override
public void onError(Exception error) {
 // Show localized error message
Toast.makeText(getContext(), R.string.transactionError,                                                                         Toast.LENGTH_SHORT).show();
}
});
} catch (AuthenticationException e) {
e.printStackTrace();
}