Friday, December 30, 2016

Advance JAVA

What is HashMap & Map ?

Map is an Interface and HashMap is class Implements Map


Map<K,V> is an interface, HashMap<K,V> is a class that implements Map.
you can do
Map<Key,Value> map = new HashMap<Key,Value>();

What are pass by reference and pass by value ?

Pass by reference means the passing the address itself rather than value, Pass by value means passing the copy of value to be passed

Difference between HashMap and HashTable ?

  • HashMap class roughly equivalent to HashTable except that it is unsynchronised and permits null.
  • (HashMap allows null to store as key,Value wheres as HashTable doesn't allows)
  • HashMap doesn't guarantees that order of the  map remains constant over time 
  • HashMap is unsynchronised where as HashTable is synchronised 
        Hashtable<String,String> hashtableobj = new Hashtable<String, String>();
        hashtableobj.put("Maga", "available");
        hashtableobj.put("Machi", "available");
        System.out.println("obj output :"+ hastable_obje);
 
        HashMap hashmapobj = new HashMap();
        hashmapobj.put("test ", "awesome");  
        hashmapobj.put("internal", "sake of marks"); 
        System.out.println("HashMap object output :"+hashmap_obj); 

Difference between Vector and Arraylist ?
Vector is synchronised and arraylist is not

Difference between Overloading and Overriding ?

1)
Method overloading is used to increase the readability of the program.
Method overriding is used to provide the specific implementation of the method that is already provided by its super class.
2)
Method overloading is performed within class.
Method overriding occurs in two classes that have IS-A (inheritance) relationship.
3)
In case of method overloading, parameter must be different.
In case of method overriding, parameter must be same.
4)
Method overloading is the example of compile time polymorphism.
Method overriding is the example of run time polymorphism.
5)
In java, method overloading can't be performed by changing return type of the method only. Return type can be same or different in method overloading. But you must have to change the parameter.
Return type must be same or covariant in method overriding.
Java Method Overloading example

  1. class OverloadingExample{  
  2. static int add(int a,int b){return a+b;}  
  3. static int add(int a,int b,int c){return a+b+c;}  
  4. }  
Java Method Overriding example 
  1. class Animal{  
  2. void eat(){System.out.println("eating...");}  
  3. }  
  4. class Dog extends Animal{  
  5. void eat(){System.out.println("eating bread...");}  
  6. }  

Wednesday, December 28, 2016

File upload using OkHttp and Cookie Manager in Android

OkHttp is a modern application network,  OkHttp will help making network calls efficiently, makes our stuffs load faster and saves the BandWidth.

Some of the advantages listed by OkHttp are :


  • Connection pooling reduces the request latency.
  • Transparent GZIP shrinks download sizes.
  • Response cashing avoids the network completely for repeat requests.
  • It supports both synchronous blocking calls & asych calls with callbacks .
  • OkHttp supports Android 2.3 and Above. For JAVA the minimum requirements is 1.7


    Here are the steps to Introduce the OkHttp an Http Client to your Android applications.

    Here are the steps to integrate the OkHttp library
    Step 1: Add the dependencies
       `compile 'com.squareup.okhttp3:okhttp:3.4.1`
    
        compile 'com.squareup.okhttp3:okhttp-urlconnection:3.0.0-RC1'`
    Step 2 : Import the following java classes one of your package

                 If your trying to upload the files/images using the cookie manager
    (Copy the code from following links and use it)

    File1 : Serializablehttpcookie
    File2 : Persistentcookiestore
    File3 : Htplogginginterceptor


    Step 3 : Make API requests

    using the following methods
    public static String sendRequest(Context context, String OPERATION, RequestBody requestBody) {
    
            String resp_str = null;
    
            Request request = new Request.Builder()
                    .url(context.getString(R.string.api_url) + OPERATION)
                    .addHeader("Content-Type", "application/x-www-form-urlencoded")
                    .method("POST", RequestBody.create(null, new byte[0]))
                    .post(requestBody)
                    .build();
    
            try {
                CookieHandler cookieHandler = new CookieManager(new PersistentCookieStore(context), CookiePolicy.ACCEPT_ALL);
                HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
                logging.setLevel(HttpLoggingInterceptor.Level.BODY);
    
                OkHttpClient okHttpClient = new OkHttpClient()
                        .newBuilder()
                        .cookieJar(new JavaNetCookieJar(cookieHandler))
                        .addInterceptor(logging)
                        .connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
                        .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                        .build();
    
    
    
                Response response = okHttpClient.newCall(request).execute();
    
                resp_str = response.body().string();
    
               response.body().close();
    
                LogDumper.e(TAG+"="+OPERATION, resp_str);
    
            } catch (IOException e) {
                e.printStackTrace();
            }
    
    
            return resp_str;
        }
    
    //Method to upload file with request body
        public static String upload(RequestBody requestBody, String OPERATION )
        {
            String response=null;
            try {
    
                CookieHandler cookieHandler = new CookieManager(new PersistentCookieStore(context), CookiePolicy.ACCEPT_ALL);
                HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
                logging.setLevel(HttpLoggingInterceptor.Level.BODY);
    
                OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                        .cookieJar(new JavaNetCookieJar(cookieHandler))
                        .addInterceptor(logging)
                        .connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
                        .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                        .build();
    
    
                Request request = new Request.Builder()
                        .url(context.getString(R.string.api_url) + OPERATION)
                        .addHeader("Content-Type", "multipart/form-data")
                        .post(requestBody)
                        .build();
    
    
                Response response1 = okHttpClient.newCall(request).execute();
    
                response =  response1.body().string();
                LogDumper.e(TAG+"="+OPERATION, response);
    
                response1.body().close();
    
    
            } catch (IOException e) {
                e.printStackTrace();
                return null ;
            }
    
            return response;
        }
    
    

Replace Deprecated HTTP client/mime by Okhttp/Retrofit library while making API calls in Android

Hope everyone know recently Google has did great change on networking API, and most effective one on developer side is org.apach    Apache

So now it is every Android Developer job to kick out their own methods/classes/interfaces which they created to
make network(using Apache http client/mime.) call during application execution

The alternate solution which every application uses is OkHttp or Retrofit

Hope your existing code base having network calls like :


Network call using http client/mime to POST params and get response

POST Method


 String response = null;
        try {
            loginapi_call = new URI(context.getString(R.string.api_url)
                    + operation);
            // Log.e(TAG, loginapi_call.toString());
            HttpClient client = HttpClientFactory.getThreadSafeClient(context);
            HttpPost request = new HttpPost();
            request.setURI(loginapi_call);
            request.addHeader("Content-Type", "application/x-www-form-urlencoded");

            request.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            HttpParams httpParameters = new BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(httpParameters, 20000);
            HttpConnectionParams.setSoTimeout(httpParameters, 30000);
            HttpConnectionParams.setTcpNoDelay(httpParameters, true);
            request.setParams(httpParameters);

            long i = System.currentTimeMillis();// Log to know the time diff
            response = client.execute(request, responseHandler);

            // response = client.execute(request, httpContext);
            long j = System.currentTimeMillis();// Log to know the time diff
            // Log.i("Time Taken", j-i+" ms");

            // //Log(TAG,operation + " successful, response length:"+
            // response.length());
        } catch (Exception e) {
            e.printStackTrace();
            // Log.i("Error !!!", "In Request");
        } finally {
            if (in != null)
                try {
                    in.close();
                } catch (IOException e) {
                }
        }

POST METHOD using OkHttp
 String resp_str = null;

        Request request = new Request.Builder()
                .url(context.getString(R.string.api_url) + OPERATION)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .method("POST", RequestBody.create(null, new byte[0]))
                .post(requestBody)
                .build();

        try {

            OkHttpClient okHttpClient = new OkHttpClient().newBuilder().connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).build();

            Response response = okHttpClient.newCall(request).execute();

            resp_str = response.body().string();


          //  Log.e(TAG, response.body().string());

        } catch (IOException e) {
            e.printStackTrace();
        }
Reason to switch new netwoking libary click here

Wednesday, December 14, 2016

Android APK size/Reduce Android APK Size/APK size is huge/How to reduce apk size in android studio

How to reduce apk size in android studio

Configure Your Build for APK Splits


To enable APK splits, add a splits {} block to your module-level build.gradle file. Within the splits {}block, provide a density {} block that specifies how Gradle should generate per-density APKs, or an abi {} block that specifies how Gradle should generate per-ABI APKs. You can provide both density and ABI blocks, and the build system will create a split APK for each density and ABI combination.

Configure density APK splits

To create separate APKs for different screen densities, add a density {} block inside your splits {} block. In your density {} block, provide a list of desired screen densities and compatible screen sizes. The list of compatible screen sizes should only be used if you need specific <compatible-screens> elements in each APK's manifest.
The following Gradle DSL options are used to configure per-density APK splits:
enable
If you set this element to true, Gradle generates APK splits based on the screen densities you define. The default value is false.
exclude
Specifies a comma-separated list of densities that Gradle should not generate separate APKs for. Use exclude if you want to generate APKs for most densities, but need to exclude a few densities that your app doesn't support.
reset()
Clears the default list of screen densities. Only use when combined with the include element to specify the densities you would like to add. The following snippet sets the list of densities to just ldpi and xxhdpi by calling reset() to clear the list, and then using include:
reset()  // clear the default list from all densities to no densities
include "ldpi", "xxhdpi" // specify the two densities we want to generate APKs for
include
Specifies a comma-separated list of densities that Gradle should generate APKs for. Only use in combination with reset() to specify an exact list of densities.
compatibleScreens
Specifies a comma-separated list of compatible screen sizes. This will inject a matching <compatible-screens> node in the manifest for each split APK. This optional setting provides a convenient way to manage both screen densities and screen sizes in the same build.gradle section, however using <compatible-screens> can limit the types of devices your app will work with. For alternative ways to support different screen sizes, see Support Multiple Screens.
Because each split APK that's based on screen density includes a <compatible-screens> tag with specific restrictions about which screen types the APK supports, even if you publish several APKs, some new devices will not match your multiple APK filters. As such, Gradle always generates an additional universal APK that contains assets for all screen densities and does not include a <compatible-screens> tag. You should publish this universal APK along with your split APKs to provide a fallback for devices that do not match the APKs with a <compatible-screens> tag.
The following example generates a separate APK for each screen density listed in Range of screens supported, except ldpixxhdpi, and xxxhdpi. This is done by using exclude to remove three densities from the default list of all densities:
android {
  ...
  splits {

    // Configures screen density split settings
    density {

      // Enables density APK splits
      enable true

      // Specifies a list of screen densities Gradle should not create APK splits for
      exclude "ldpi", "xxhdpi", "xxxhdpi"

      // Specifies a list of compatible screen size settings for the manifest
      compatibleScreens 'small', 'normal', 'large', 'xlarge'
    }
  }
}
For a list of density names and screen size names, see How to Support Multiple Screens. For more details on distributing your app to specific screen types and devices, see Distributing to Specific Screens.

Configure ABI APK splits

To create separate APKs for different ABIs, add an abi {} block inside your splits {} block. In your abi {} block, provide a list of desired ABIs.
The following Gradle DSL options are used to configure per-ABI APK splits:
enable
If you set this element to true, Gradle generates APK splits based on the ABIs you define. The default value is false
exclude
Specifies a comma-separated list of ABIs that Gradle should not generate separate APKs for. Use exclude if you want to generate APKs for most ABIs, but need to exclude a few ABIs that your app doesn't support.
reset()
Clears the default list of ABIs. Only use when combined with the include element to specify the ABIs you would like to add. The following snippet sets the list of ABIs to just x86 and mips by calling reset() to clear the list, and then using include:
reset()  // clear the default list from all ABIs to no ABIs
include "x86", "mips" // specify the two ABIs we want to generate APKs for
include
Specifies a comma-separated list of ABIs that Gradle should generate APKs for. Only use in combination with reset() to specify an exact list of ABIs.
universalApk
If true, Gradle generates a universal APK in addition to split APKs. A universal APK contains code and resources for all ABIs in a single APK. The default value is false. Note that this option is only available for per-ABI APK splits. Density APK splits always generate a universal APK that contains code and resources for all screen densities.
The following example generates a separate APK for each ABI: x86armeabi-v7a, and mips. This is done by using reset() to start with an empty list of ABIs, followed by include with a list of three ABIs that will each get an APK:
android {
  ...
  splits {

    // Configures screen ABI split settings
    abi {

      // Enable ABI APK splits
      enable true

      // By default all ABIs are included, so use reset() and include to specify that we only
      // want APKs for x86, armeabi-v7a, and mips

      // Resets the list of ABIs that Gradle should create APKs for to none
      reset()

      // Specifies a list of ABIs that Gradle should create APKs for
      include "x86", "armeabi-v7a", "mips"

      // Specify that we do not want to also generate a universal APK that includes all ABIs
      universalApk false
    }
  }
}
For a list of supported ABIs, see Supported ABIs.

Configure versioning of APK splits

By default, when Gradle generates APK splits, each APK will have the same version information, as specified in the module-level build.gradle file. Because the Google Play Store does not allow multiple APKs for the same app that all have the same version information, you need to ensure each split APK has its own unique versionCode before you upload to the Play Store.
You can configure your module-level build.gradle file to override the versionCode for every split APK. Assign a unique numeric value for each ABI and density used in APK splits, and then override the output version code with a value that combines defaultConfig.versionCode with the numeric value assigned to the density or ABI.
The following example creates a mapping that assigns a unique numeric value to each ABI being used for APK splits. Using this mapping, a per-split APK version code is created that combines the mapped ABI value with defaultConfig.versionCode. In this example, the split APK for the x86 ABI would get a versionCode of 304. If defaultConfig.versionCode iterates to 5, Gradle would assign a versionCode of 305 to the x86 split APK.
android {
  ...
  defaultConfig {
    ...
    versionCode 4
  }
  splits {
    ...
  }
}
// map for the version code that gives each ABI a value
ext.versionCodes = ['armeabi-v7a':1, mips:2, x86:3]
// For each APK output variant, override versionCode with a combination of
// ABI APK value * 100 + defaultConfig.versionCode
android.applicationVariants.all { variant ->
    // assign different version code for each output
    variant.outputs.each { output ->
        output.versionCodeOverride =
                project.versionCodes.get(output.getFilter(OutputFile.ABI)) * 100
                + android.defaultConfig.versionCode
    }
}
For more examples of alternate version code schemes, see Assigning version codes.

Build APK Splits


Once you configure your module-level build.gradle file to build APK splits, click Build > Build APK to build all APKs for the currently selected module in the Project pane. Gradle creates the APKs for each density or ABI into the project's build/outputs/apk/ directory.
Gradle builds an APK for each configured density or ABI split. If you've enabled splits for both densities and ABIs, Gradle will create an APK for each density and ABI combination. For example, the following build.gradle snippet enables building APK splits for mdpi and hdpi densities, and also x86 and mips ABIs:
...
  splits {
    density {
      enable true
      reset()
      include "mdpi", "hdpi"
    }
    abi {
      enable true
      reset()
      include "x86", "mips"
    }
  }
The output from the example configuration would include the following 4 split APKs:
  • app-hdpiX86-release.apk: Contains code and resources for hdpi density and x86 ABI only.
  • app-hdpiMips-release.apk: Contains code and resources for hdpi density and mips ABI only.
  • app-mdpiX86-release.apk: Contains code and resources for mdpi density and x86 ABI only.
  • app-mdpiMips-release.apk: Contains code and resources for mdpi density and mips ABI only.
Depending on how you've configured APK splits, Gradle will also generate a universal APK that contains code and resources for all densities or ABIs. For density APK splits, Gradle will always generate a universal APK that includes code and resources for all densities, in addition to the per-density APKs. For ABI splits, Gradle only generates an APK that includes code and resources for all ABIs if you specify universalApk true in the abi section of the splits {} block in your build.gradle file.

APK file name format

For APK splits, Gradle uses APK filenames using the following scheme:
modulename-screendensityABI-buildvariant.apk
The scheme components are:
modulename
Specifies the module name being built.
screendensity
If screen density APK splits are enabled, specifies the screen density for the APK, such as "mdpi".
ABI
If ABI APK splits are enabled, specifies the ABI for the APK, such as "x86". If both screen density and ABI APK splits are enabled, Gradle concatenates the density name with the ABI name, for example "mdpiX86". If universalApk is enabled for ABI APK splits, Gradle uses "universal" as the ABI portion of the universal APK filename.
buildvariant
Specifies the build variant being built, such as "debug".
For example, a debug build of "myApp" that has APK splits enabled for the mdpi screen density would use an APK filename of myApp-mdpi-debug.apk. A release build of "myApp" that has APK splits enabled for both the mdpi screen density and the x86 ABI would use an APK filename of myApp-mdpiX86-release.apk.