Thursday, 17 September 2015

Bottom Tabs with Fragment State PAger Adapter

Hi All, Today we learn about adding bottom tabs with fragment state pager adapter. Below code is generating four fragment pages, however you can modified it acocording to your need. Have fun :) Download Source Create a new project, and add MainApplication.java
import android.app.Application;
import android.content.Context;
public class MainApplication extends Application{
/**
* Context for Application
*/
private static Context sApplicationContext;
/**
* To get the context of the current activity
* @return Context of the current activity
*/
public static Context getsApplicationContext() {
return sApplicationContext;
}
/*
* Returning the context of the current activity
* @see android.app.Application#onCreate()
*/
@Override
public void onCreate(){
super.onCreate();
sApplicationContext = this;
}

}
Add HomeScreenActivity.java
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;

/**
* Home Screen Activity class, having Pager adapter and bottom tabs
* @author ABHISHEK
*/
public class HomeScreenActivity extends ActionBarActivity implements OnPageChangeListener, OnClickListener,
android.content.DialogInterface.OnClickListener {
/*
* Views of this Activity
*/
private ViewPager mPager = null;
private TextView[] mBottomTabTextView = new TextView[4];
private ImageView[] mBottomTabImageView = new ImageView[4];
private TextView[] mBottomTabNameTextView = new TextView[4];
private TextView mLogout = null;
private static final int NUMBER_OF_VIEW_TO_ALIVE = 4;

// Array of drawable for their corresponding states
private int[] mBottomImageResourceUnselected = { R.drawable.photo1, R.drawable.photo2, R.drawable.photo3,
R.drawable.photo4};
//private int[] mBottomImageResourceSelected = { R.drawable.home_selected, R.drawable.mycomic_selected,
// R.drawable.search_selected };
private int[] mBottomImageResourceSelected = { R.drawable.photo1, R.drawable.photo2, R.drawable.photo3,
R.drawable.photo4};

/**
* @param isMyComicRequestSend : false to start mycomic request
*/

private HomePagerAdapter mAdapter = null;
public static HomeScreenActivity sHomeScreen = null;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sHomeScreen = this;
setContentView(R.layout.home_screen_activity);
ActionBar actionBar = getSupportActionBar();
LayoutInflater mInflater = LayoutInflater.from(this);

View customView = mInflater.inflate(R.layout.home_screen_action_bar, null);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setCustomView(customView, new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT,
ActionBar.LayoutParams.MATCH_PARENT));
mLogout = (TextView) customView.findViewById(R.id.txt_view_log_out);
actionBar.setDisplayShowHomeEnabled(false); // remove app icon
actionBar.setDisplayShowTitleEnabled(false); // remove app title
actionBar.show();
initialize();
registerListener();

setTabSelected(0);
mAdapter = new HomePagerAdapter(getSupportFragmentManager());
mPager.setOffscreenPageLimit(NUMBER_OF_VIEW_TO_ALIVE);
mPager.setAdapter(mAdapter);
}

/*
* Clear the instance of comic detail screen, and delete the decrypted file
* @see android.support.v4.app.FragmentActivity#onResume()
*/
@Override
protected void onResume() {
super.onResume();

/*
* delete the Decrypted file if exist
*/
// File decryptedFile = new File(XpinnOffUtil.loadPreference(Constants.DECRYPTED_FILE_PATH));
//
// if(decryptedFile.exists()){
// decryptedFile.delete();
// XpinnOffUtil.clearPreference(Constants.DECRYPTED_FILE_PATH);
// XpinnOffUtil.clearPreference(Constants.DECRYPTED_FILE_KEY);
// }
}

/**
* Initialize activity views
*/
public void initialize() {
mPager = (ViewPager) findViewById(R.id.pager);
/*
* Initialize tab strips
*/
mBottomTabTextView[0] = (TextView) findViewById(R.id.txt_view_home_tab);
mBottomTabTextView[1] = (TextView) findViewById(R.id.txt_view_mycomic_tab);
mBottomTabTextView[2] = (TextView) findViewById(R.id.txt_view_free_tab);
mBottomTabTextView[3] = (TextView) findViewById(R.id.txt_view_search_tab);

/*
* Initialize bottom tab views
*/
mBottomTabImageView[0] = (ImageView) findViewById(R.id.img_view_home_tab);
mBottomTabImageView[1] = (ImageView) findViewById(R.id.img_view_mycomic_tab);
mBottomTabImageView[2] = (ImageView) findViewById(R.id.img_view_free_tab);
mBottomTabImageView[3] = (ImageView) findViewById(R.id.img_view_search_tab);
mBottomTabNameTextView[0] = (TextView) findViewById(R.id.txt_view_tab_home);
mBottomTabNameTextView[1] = (TextView) findViewById(R.id.txt_view_tab_mycomic);
mBottomTabNameTextView[2] = (TextView) findViewById(R.id.txt_view_tab_free);
mBottomTabNameTextView[3] = (TextView) findViewById(R.id.txt_view_tab_search);

}

/**
* Called to register Listeners
*/
public void registerListener() {
// Add loop to register listener for Bottom tab image views
for (int i = 0; i < 4; i++) {
mBottomTabImageView[i].setOnClickListener(this);
}
mPager.setOnPageChangeListener(this);
mLogout.setOnClickListener(this);
}

/**
* Called to set the tab selected
* @param iPosition : Position of the Tab to be selected
*/
public void setTabSelected(int iPosition) {
boolean state = false;
/*
* Add loop for Adding selected and unselected drawable for the image view
*/
for (int i = 0; i < 4; i++) {
if (i == iPosition) {
mBottomTabImageView[i].setImageDrawable(getResources().getDrawable(mBottomImageResourceSelected[i]));
mBottomTabNameTextView[i].setTextColor(getResources().getColor(R.color.dark_blue));
state = true;
} else {
mBottomTabImageView[i].setImageDrawable(getResources().getDrawable(mBottomImageResourceUnselected[i]));
mBottomTabNameTextView[i].setTextColor(getResources().getColor(R.color.black));
state = false;
}
mBottomTabTextView[i].setSelected(state);
}
}

/*
* @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageScrollStateChanged(int)
*/
@Override
public void onPageScrollStateChanged(int arg0) {
}

/*
* @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageScrolled(int, float, int)
*/
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {

}

/*
* @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageSelected(int)
*/
@Override
public void onPageSelected(int iPosition) {
/*
* if network is available
*/
//if position is 1 i.e mycomic and sMyComicRequest send is false
// then send my comic request
setTabSelected(iPosition);
}

/*
* Called on bottom image click
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View iView) {
/*
* if logout image is clicked
*/
if (iView.getId() == R.id.txt_view_log_out) {
showDialog();
}
/*
* if bottom tabs are clicked
*/
else {
setmPagerOnTabClick(iView.getId());
}
}

/**
* Called to set page position on corresponding image click
* @param iTabId : Bottom Tab (Image View) id
*/
public void setmPagerOnTabClick(int iTabId) {
/*
* Add loop to find the id
*/
for (int i = 0; i < 4; i++) {
/*
* If view id match, the set page position
*/
if (mBottomTabImageView[i].getId() == iTabId) {
mPager.setCurrentItem(i);
setTabSelected(i);
break;
}
}
}

/**
*Called to show Dialog for logout
*/
public void showDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("INFO");
builder.setMessage("EXIT_MESSAGE");
builder.setPositiveButton("OK", this);
builder.setNegativeButton("CANCEL", this);
builder.show();
}

/*
* Called on logout dialog click
* @see android.content.DialogInterface.OnClickListener#onClick(android.content.DialogInterface, int)
*/
@Override
public void onClick(DialogInterface iDialog, int iWhich) {
/*
* If ok button clicked then logout app
*/
if (iWhich == DialogInterface.BUTTON_POSITIVE) {
System.exit(0);
}
/*
* if cancel button clicked then hide the dialog
*/
else {
iDialog.dismiss();
}
}

/*
* Prompt message to logout
* @see android.support.v4.app.FragmentActivity#onBackPressed()
*/
@Override
public void onBackPressed() {
showDialog();
}

/*
* @see android.support.v4.app.FragmentActivity#onDestroy()
*/
@Override
protected void onDestroy() {
super.onDestroy();
sHomeScreen = null;
}
}
Add HomePagerAdapter.java
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;

/**
* View pager Adapter of {@link HomeScreenActivity}
* @author ABHISHEK
*/
public class HomePagerAdapter extends FragmentStatePagerAdapter {

/**
* Number of Fragment pages in the view pager
*/
private static final int NUMBER_OF_PAGES = 4;
private Fragment2 mFragment2 ;
private Fragment4 mFragment4 ;
private Fragment3 mFragment3 ;
private Fragment1 mFragment1;

/**
* @return : Instance of {@link Fragment3}
*/
public Fragment3 getmFragment3() {
return mFragment3;
}

/**
* @return : Instance of {@link Fragment2}
*/
public Fragment2 getFragment2() {
return mFragment2;
}

/**
* @return : Instance of {@link Fragment4}
*/
public Fragment4 getmFragment4() {
return mFragment4;
}

/**
* {@link HomePagerAdapter} {@link Constructor}
* @param fm : {@link FragmentManager} instance
*/
public HomePagerAdapter(FragmentManager fm) {

/*
* Instantiate view pager fragments
*/
super(fm);
if(mFragment1 == null){
mFragment1 = new Fragment1();
}
if (mFragment2 == null) {
mFragment2 = new Fragment2();
}
if (mFragment4 == null) {
mFragment4 = new Fragment4();
}
if (mFragment3 == null) {
mFragment3 = new Fragment3();
}
}

/*
* Called to get the selected fragment
* @see android.support.v4.app.FragmentPagerAdapter#getItem(int)
*/
@Override
public Fragment getItem(int iPosition) {

// Match the corresponding position
switch (iPosition) {
case 0:
return getmFragment1();
case 1:
return getFragment2();
case 2:
return getmFragment3();
case 3:
return getmFragment4();
default:
return null;
}
}

public Fragment1 getmFragment1() {
return mFragment1;
}

/*
* Called to get the number of fragment pages in the view pager
* @see android.support.v4.view.PagerAdapter#getCount()
*/
@Override
public int getCount() {
return NUMBER_OF_PAGES;
}
}
In Above code, we have created adapter for four fragments. Below are four fragments and their layout, and only single layout is used for all fragments. You can create your layouts as per your need Fragment1.java
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

public class Fragment1 extends Fragment{

private ImageView mImage;
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout, null);
mImage = (ImageView) view.findViewById(R.id.image);
mImage.setImageResource(R.drawable.photo1);
return view;
}
}

Fragment2.java

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

public class Fragment2 extends Fragment{

private ImageView mImage;
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout, null);
mImage = (ImageView) view.findViewById(R.id.image);
mImage.setImageResource(R.drawable.photo2);
return view;
}
}

Fragment3.java

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

public class Fragment3 extends Fragment{

private ImageView mImage;
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout, null);
mImage = (ImageView) view.findViewById(R.id.image);
mImage.setImageResource(R.drawable.photo3);
return view;
}
}

Fragment4.java

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

public class Fragment4 extends Fragment{

private ImageView mImage;
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout, null);
mImage = (ImageView) view.findViewById(R.id.image);
mImage.setImageResource(R.drawable.photo4);
return view;
}
}
Add below layouts in res/layout fragment_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</LinearLayout>
home_screen_action_bar.xml
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white" >

<TextView
android:id="@+id/txt_view_log_out"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:gravity="center_vertical"
android:padding="@dimen/ten"
android:text="@string/logout"
android:textColor="@color/black" />

</RelativeLayout>
home_screen_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/footer" />

<EditText
android:id="@+id/dummy_edt_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />

<LinearLayout
android:id="@+id/footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/grey_background"
android:orientation="vertical" >

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<TextView
android:id="@+id/txt_view_home_tab"
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_weight="1"
android:background="@drawable/strip_selector" />

<TextView
android:id="@+id/txt_view_mycomic_tab"
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_weight="1"
android:background="@drawable/strip_selector" />

<TextView
android:id="@+id/txt_view_free_tab"
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_weight="1"
android:background="@drawable/strip_selector" />

<TextView
android:id="@+id/txt_view_search_tab"
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_weight="1"
android:background="@drawable/strip_selector" />
</LinearLayout>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="horizontal" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/white"
android:orientation="vertical" >

<ImageView
android:id="@+id/img_view_home_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/photo1" />

<TextView
android:id="@+id/txt_view_tab_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/home" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/white"
android:orientation="vertical" >

<ImageView
android:id="@+id/img_view_mycomic_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/photo2" />

<TextView
android:id="@+id/txt_view_tab_mycomic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/mycomic" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/white"
android:orientation="vertical" >

<ImageView
android:id="@+id/img_view_free_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/photo3" />

<TextView
android:id="@+id/txt_view_tab_free"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/free" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/white"
android:orientation="vertical" >

<ImageView
android:id="@+id/img_view_search_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/photo4" />

<TextView
android:id="@+id/txt_view_tab_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/search" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

</RelativeLayout>
Add Selector in res/drawable
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@color/white" android:state_selected="false"/>
<item android:drawable="@color/bright_blue" android:state_selected="true"/>

</selector>
Add color file in res/value folder colors.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- Colors constants -->

<resources>

<color name = "white" >#FFFFFF</color>
<color name = "black" >#000000</color>
<color name = "grey_background" >#4F4F51</color>

<color name = "bright_blue" >#BBE5FF</color>
<color name = "dark_blue" >#1F7EC2</color>

</resources>
Add dimen file in res/values folder dimen.xml
<?xml version = "1.0" encoding = "utf-8"?>
<!-- Constants related with dimensions used in xmls -->

<resources>

<dimen name = "ten">10dp</dimen>

</resources>
Add strings file in res/values folder strings.xml
<!-- String constants used in xmls -->
<resources>

<string name = "app_name" >Test</string>
<string name = "logout" >Log Out</string>
<string name = "home" >Home</string>
<string name = "free" >Free </string>
<string name = "mycomic" >My Comics</string>
<string name = "search" >Search</string>
<string name = "cancel" >Cancel</string>
<string name = "ok" >OK</string>

</resources>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />

<application
android:name="com.example.test.MainApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.test.HomeScreenActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Note : All you need to add four images photo1.png, photo2.png, photo3.png, photo4.png  in res/drawable Download Source

a-look-over-manifest-attributes-used-in-google-play-filtering


                   When a user searches for an app in play store, Google play filtered his searches to provide him/her the best suited result for him/her. The google play get an idea about filtering, from the several types of app metadata and configuration settings, including manifest declarations, required libraries,architecture dependencies, and distribution controls set in the Google Play Developer Console, such as geographic targeting, pricing, and more. We will look into some manifest attribute, their purposes and their specialties.

1. <support-screens>
       This attribute is used to define the screen sizes of the devices, into which you supposed your application should be installed. Accordingly Google play filters your application and put it into the list of devices into which your application can be installed. As a general rule Google Play assume that smaller layout can be easily fit into the large screen devices. But not the larger layouts in the smaller devices. So thus, if any application declares support for normal screen size then Google Play allows that app to be installed for both normal and the larger screen size devices.
And If an application does not declare this attribute in their manifest , then Google Play picks up the default values, vary by API Levels
Suppose: The manifest declares <uses-sdk android:minSdkVersion="3"> and does not include a<supports-screens> element.
Result: Google Play will not show the app to a user of a small-screen device, but will show it to users of normal and large-screen devices, unless other filters apply.
Suppose: The manifest declares <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="4"> and does not include a<supports-screens> element.
Result: Google Play will show the app to users on all devices, unless other filters apply.
To Know, How to declare the <support-screens> attribute, see <support-screens>.
      1. <uses-configuration>
This attribute helps Google Play to filter the apps which have any special hardware requirement.
Suppose:The manifest includes <uses-configuration android:reqFiveWayNav="true" />, and a user is searching for apps on a device that does not have a five-way navigational control.
Result: Google Play will not show the app to the user.
Suppose: The manifest does not include a <uses-configuration>element.
Result: Google Play will show the app to all users, unless other filters apply.
To Know, How to declare the <uses-configuration> attribute, see <uses-configuration>

3. <uses-feature>
        If any application uses this attribute in their manifest, then Google Play categorized that app for the list of devices which satisfy the required device features. This Fuctionality was introduced in Android 2.0.

Suppose: The manifest includes <uses-feature android:name="android.hardware.sensor.light" />, and a user is searching for apps on a device that does not have a light sensor.

Result: Google Play will not show the app to the user.
An application may also require a specific Open-GL ES version support, using the 
 <uses-feature  android:openGlEsVersion="int"> attribute.

Suppose: An app requests multiple OpenGL-ES versions by specifying openGlEsVersion multiple times in the manifest.
Result: Google Play assumes that the app requires the highest of the indicated versions.
Suppose: An app requests OpenGL-ES version 1.1, and a user is searching for apps on a device that supports OpenGL-ES version 2.0.
Result: Google Play will show the app to the user, unless other filters apply. If a device reports that it supports OpenGL-ES version X, Google Play assumes that it also supports any version earlier than X.
Suppose: A user is searching for apps on a device that does not report an OpenGL-ES version (for example, a device running Android 1.5 or earlier).
Result: Google Play assumes that the device supports only OpenGL-ES 1.0. Google Play will only show the user apps that do not specify openGlEsVersion, or apps that do not specify an OpenGL-ES version higher than 1.0.
To Know, How to declare the <uses-feature> attribute, see <uses-feature>
      1. <uses-library>
If application uses this attribute in the manifest, then it means that the application wants that the specific shared library should be present on the devices. It creates a filter for the google play to show only those apps whose library need satisfy by the device.
Suppose: An app requires the com.google.android.maps library, and a user is searching for apps on a device that does not have the com.google.android.maps library.
Result: Google Play will not show the app to the user.
Suppose:The manifest does not include a <uses-library> element.
Result: Google Play will show the app to all users, unless other filters apply.
To Know, How to declare the <uses-library> attribute, see <uses-library>
      1. <uses-permission>
        If in any app the <uses-feature> attribute is not declared properly, then Google Play managed itself through <uses-permission> attribute whether the app has reqiurement of the hardware feature or not. For example, if an application requests the CAMERA permission but does not declare a <uses-feature> element for android.hardware.camera, Google Play considers that the application requires a camera and should not be shown to users whose devices do not offer a camera.
In general, if an application requests hardware-related permissions, Google Play assumes that the application requires the underlying hardware features, even though there might be no corresponding to <uses-feature>declarations. Google Play then sets up filtering based on the features implied by the <uses-feature> declarations.
For a list of permissions that imply hardware features, see the documentation for the <uses-feature> element.
      1. <uses-sdk>
        An application can require a minimum API level.
Minimum Framework Version (minSdkVersion)
Suppose: The manifest includes <uses-sdk android:minSdkVersion="3">, and the app uses APIs that were introduced in API Level 3. A user is searching for apps on a device that has API Level 2
Result: Google Play will not show the app to the user.
Suppose: The manifest does not include minSdkVersion, and the app uses APIs that were introduced in API Level 3. A user is searching for apps on a device that has API Level 2.
Result: Google Play assumes that minSdkVersion is "1" and that the app is compatible with all versions of Android. Google Play shows the app to the user and allows the user to download the app. The app crashes at runtime.
Because you want to avoid this second scenario, we recommend that you always declare a minSdkVersion. For details, see android:minSdkVersion.
Maximum Framework Version (maxSdkVersion)
Deprecated. Android 2.1 and later do not check or enforce the maxSdkVersion attribute, and the SDK will not compile if maxSdkVersion is set in an app's manifest. For devices already compiled with maxSdkVersion, Google Play will respect it and use it for filtering.
Declaring maxSdkVersion is not recommended. For details, see android:maxSdkVersion.
There are few attributes used in manifest as a filter for Google Play, but they trigger in exceptional cases. Used in some high – performance gamens and similar application, Most application should never used these filters.
Advanced Manifest Filters
1.<compatible-screens>
Google Play filters the application if the device screen size and density does not match any of the screen configurations (declared by a <screen> element) in the <compatible-screens> element.
Caution: Normally, you should not use this manifest element. It will resuce the user base for your application, instead of using this use <support-screens> manifest element (described above) to enable screen compatibility mode for screen configurations you have not accounted for with alternative resources.
2.<support-gl-texture>
Google Play filters the application unless one or more of the GL texture compression formats supported by the application are also supported by the device.
Reference :- Google Play Filters
Download :- Google Play Filtering

Google Play In App Billing

In App billing , a service which can be access through our app using an API provided by the google play app, which is already installed in the device.

This service can only be implemented in the applications which will publish through Google Play. Version 3 API is the currently latest version, and maintains very broad compatibility across the range of Android devices. In-app Billing Version 3 is supported on devices running Android 2.2 or higher that have the latest version of the Google Play store installed.

In App billing allow you to sell in-app products. In app-products can be any digital goods like in-game currency(i.e coins, fruits, diamonds which helps you to upgrade your gaming profile). We cant sell any physical goods through in-app billing, or any personel services which require physical delivery. Unlike Priced application, because if once an in-app product purchase, it can refund as there is no refund process provided by the google play.
So, for integrating In-App Billing in your application all you need to have a developer account in google play developer console. Below link will move you into developer console.

Publish Your APP


        If you already have a developer account there then it bit makes a sense that you have already publish some apps there, and just looking here to know how to integrate In-App Billing, So just skip the below para.
This is for all who are looking to create an developer account in google developer console, So for continue to publish your app with In-app Billing, you have to agree with the google terms, and have to paid a sum of $25, to make an account in the developer console. Once all the registration process completes. You can start with In-App Billing.
Download In-appBilling library from sdk manger, and Add AIDL (Android Interface Definition Language) file, to your project, which is an interface of In-app Billing version 3 service, we will use this for all billing request through IPC.
To get the AIDL file:
  1. Open the Android SDK Manager.
  2. In the SDK Manager, expand the Extras section.
  3. Select Google Play Billing Library.
  4. Click Install packages to complete the download.
The IinAppBillingService.aidl file will be installed to <sdk>/extras/google/play_billing/.
To add the AIDL to your project:
  1. Copy the IinAppBillingService.aidl file to your Android project.
    • If you are using Eclipse:
      1. If you are starting from an existing Android project, open the project in Eclipse. If you are creating a new Android project from scratch, click File > New > Android Application Project, then follow the instructions in the New Android Application wizard to create a new project in your workspace.
      2. In the /src directory, click File > New > Package, then create a package named com.android.vending.billing.
      3. Copy the IinAppBillingService.aidl file from <sdk>/extras/google/play_billing/ and paste it into the src/com.android.vending.billing/ folder in your workspace.
    • If you are developing in a non-Eclipse environment: Create the following directory/src/com/android/vending/billing and copy the IInAppBillingService.aidl file into this directory. Put the AIDL file into your project and use the Ant tool to build your project so that theIInAppBillingService.java file gets generated.

  2. Build your application. You should see a generated file named IInAppBillingService.java in the
Update Your Manifest File

For making your application to allow all in app purchases, add the below code in your projects manifest file
uses-permission android:name="com.android.vending.BILLING"
In the next three steps you will finished the In-app purchases tasks,
  1. Create a sevice connection to facillate messaging between your application and google play.
  2. Send Billing Request to google play application.
  3. Handle the synchronus response of your billing request.
Step 1: Bind to InAppBilling Service
IInAppBillingService mService;

ServiceConnection mServiceConn = new ServiceConnection() {
   @Override
   public void onServiceDisconnected(ComponentName name) {
       mService = null;
   }
   @Override
   public void onServiceConnected(ComponentName name, 
      IBinder service) {
       mService = IInAppBillingService.Stub.asInterface(service);
   }
};

Set an Intent of binding In-appBilling service in your activity's on create Method, and unregister it in your onDestroy message.
Note :- Use setPackage method to make your billing transactions safe. It ensures that the billing request generated is only for google play app and preventing other apps to intercepting those requests.
 
@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
  serviceIntent.setPackage("com.android.vending");
  bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
 
@Override
public void onDestroy() {
    super.onDestroy();
    if (mService != null) {
        unbindService(mServiceConn);
    }   
}

Step 2: Send Billing Request
Once your application is connected with the google play, now you can start all the purchase request for your in app products, you dont need to handle any transaction setup in your application code , in case if the user has not setup the transactions medium in their google play, google play itself handle the transactions setup. The user can find the number of purchasing items available to purchase, by calling a “Item available for puchase” query which we will disscuss in the next para. Once all the purchases gets sucessful google play recognizes that the user has ownership of that item and prevents him for further transaction with the same product id. You can define the process of consumption in your application for that in app product, and once the product gets consume it can be reset to purchase again.
For Querying Items Available For Purchase
      ArrayList<String> skuList = new ArrayList<String> (); 
     skuList.add("premiumUpgrade");
     skuList.add("gas");
    Bundle querySkus = new Bundle();
   querySkus.putStringArrayList(“ITEM_ID_LIST”, skuList);

These array list items are the product [I.e productID] for which you will make a transaction. This product id will be the same as when you will add the in-app product in your developer console account. We will disscuss it later that how to add the in app products from google developer console. For now you just assume that there is a in-app product already with the above specified product Ids.
To retrieve this information from Google Play, call the getSkuDetails method on the In-app Billing Version 3 API, and pass the method the In-app Billing API version (“3”), the package name of your calling app, the purchase type (“inapp”), and the Bundle that you created.
Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus);
make the above request in background, otherwise it will block your main thread.
In case of successful request , the response code will be BILLING_RESPONSE_RESULT_OK
This will help you to find out all the response code
To get the price of your in app product
int response = skuDetails.getInt("RESPONSE_CODE");
if (response == 0) {
   ArrayList<String> responseList  = skuDetails.getStringArrayList("DETAILS_LIST");
   for (String thisResponse : responseList) {
      JSONObject object = new JSONObject(thisResponse);
      String sku = object.getString("productId");
      String price = object.getString("price");
      if (sku.equals("premiumUpgrade")) mPremiumUpgradePrice = price;
      else if (sku.equals("gas")) mGasPrice = price;
   }
}
Call getStringArrayList method to get list of available items to purchase, the response will come in JSON Format string. Parse it to Json Objet and get the product price.
Step – 3 Purchasing an Item
Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(),
   sku, "inapp", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
Call getBuyIntent to make a purchase request, Pass in to the method the In-app Billing API version (“3”), the package name of your calling app, the product ID for the item to purchase, the purchase type (“inapp” or "subs"), and a developerPayload String. The developerPayloadString is used to specify any additional arguments that you want Google Play to send back along with the purchase information.
If the request is successful, the returned Bundle has a response code of BILLING_RESPONSE_RESULT_OK (0) and aPendingIntent that you can use to start the purchase flow. Next, extract a PendingIntent from the response Bundle with key BUY_INTENT.
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
To complete the purchase transaction, call the startIntentSenderForResult method and use thePendingIntent that you created. In this example, you are using an arbitrary value of 1001 for the request code
startIntentSenderForResult(pendingIntent.getIntentSender(), 1001,  
new Intent(),       Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
If the above request gets successful, you will get a JSON response of the transaction
'{ 
   "orderId":"12999763169054705758.1371079406387615", 
   "packageName":"com.example.app",
   "productId":"exampleSku",
   "purchaseTime":1345678900000,
   "purchaseState":0,
   "developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
   "purchaseToken":"rojeslcdyyiapnqcynkjyyjh"
 }'
Google play sends the above respnse to your pending intent to the onActivityResult method of your application.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
   if (requestCode == 1001) {           
      int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
      String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
      String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
        
      if (resultCode == RESULT_OK) {
         try {
            JSONObject jo = new JSONObject(purchaseData);
            String sku = jo.getString("productId");
            alert("You have bought the " + sku + ". Excellent choice, 
               adventurer!");
          }
          catch (JSONException e) {
             alert("Failed to parse purchase data.");
             e.printStackTrace();
          }
      }
   }
}

Querying for Purchased Items

You can make a call to get the list of items which are purchased by the user, the purchase request contains In-app Billing API version (“3”), the package name of your calling app, and the purchase type (“inapp” or "subs").
Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
The Google Play service returns only the purchases made by the user account that is currently logged in to the device. If the request is successful, the returned Bundle has a response code of 0. The response Bundle also contains a list of the product IDs, a list of the order details for each purchase, and the signatures for each purchase.
int response = ownedItems.getInt("RESPONSE_CODE");
if (response == 0) {
   ArrayList<String> ownedSkus =
      ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
   ArrayList<String>  purchaseDataList =
      ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
   ArrayList<String>  signatureList =
      ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE");
   String continuationToken = 
      ownedItems.getString("INAPP_CONTINUATION_TOKEN");
   
   for (int i = 0; i < purchaseDataList.size(); ++i) {
      String purchaseData = purchaseDataList.get(i);
      String signature = signatureList.get(i);
      String sku = ownedSkus.get(i);
  
      // do something with this purchase information
      // e.g. display the updated list of products owned by user
   } 
   // if continuationToken != null, call getPurchases again 
   // and pass in the token to retrieve more items
}
For the performance reasons, the above request only return upto 700 products, in one response. If the User has more purchases then google play include a string token mapped to the key INAPP_CONTINUATION_TOKEN in the response Bundle to indicate that more products can be retrieved. Your application can then make a subsequent getPurchases call, and pass in this token as an argument. Google Play continues to return a continuation token in the response Bundle until all products that are owned by the user has been sent to your app.
Consuming A Purchase
____________________________________________________________________
Once an in-app product gets purchased it is assumed as owned by the google play, and cannot be purchase again, until the request of comsumption is not send. Only Managed In-app product are consumable, but subscriptions are not.

int response = mService.consumePurchase(3, getPackageName(), token);

Its your responsibility to control and track how the in-app product is provisioned to the user. For example, if the user purchased in-game currency, you should update the player's inventory with the amount of currency purchased.