Jul 31, 2013

Android NotificationListenerService Example

Introduction
NotificationListenerService is introduced in Android 4.3 (API 18). It allows an application to receive information about notifications as it creates or removes. NotificationListenerService class is derived from the Service class. It has two abstract methods namely 1. onNotificationPosted 2. onNotificationRemoved.  
To use NotificationListenerService, we need to create a java file which extends NotificationListenerService and implement two callback methods. Both methods have a parameter named "sbn", which is an object of StatusBarNotification class. StatusBarNotification provides necessary information about Notifications.

NotificationListenerService provides facility to fetch active notifications using getActiveNotifications and also provides a feature to remove notifications using cancelAllNotifications. 

Useful Methods
1. NotificationListenerService
    onNotificationPosted()
    onNotificationRemoved()
    cancelAllNotifications()
    getActiveNotifications()
2. StatusBarNotification
    getId()
    getNotification()
    getPackageName()
    getPostTime()
    isClearable()
    isOngoing()

Note
User require to enable notification permission from "Settings > Security > Notification access".

Source Code of NotificationListenerService
Worth to see the source code, If you hare curious. It has two java files and two AIDL files 
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/service/notification

Example
This is simple example of NotificationListenerService, It has simple UI contain three buttons and one textview. 

  • Create Notification - It will create simple notification so that we can test onNotificationPosted event
  • Clear All Notification - It will create all notification in notificationbar
  • List of Notification - It will display notification list in textview
  • TextView - display notification events and list of notification.

This example has Activity, Service and BroadcastReceiver. BroadcastReceiver used for communication between activity and service. We can't access cancelAllNotifications() and getActiveNotifications() methods from activity directly so I use BroadcastReceivers.

Screenshots



Source Code

1. MainActivity.java
package com.kpbird.nlsexample;

import android.app.Activity;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView txtView;
    private NotificationReceiver nReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        txtView = (TextView) findViewById(R.id.textView);
        nReceiver = new NotificationReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE");
        registerReceiver(nReceiver,filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(nReceiver);
    }



    public void buttonClicked(View v){

        if(v.getId() == R.id.btnCreateNotify){
            NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            NotificationCompat.Builder ncomp = new NotificationCompat.Builder(this);
            ncomp.setContentTitle("My Notification");
            ncomp.setContentText("Notification Listener Service Example");
            ncomp.setTicker("Notification Listener Service Example");
            ncomp.setSmallIcon(R.drawable.ic_launcher);
            ncomp.setAutoCancel(true);
            nManager.notify((int)System.currentTimeMillis(),ncomp.build());
        }
        else if(v.getId() == R.id.btnClearNotify){
            Intent i = new Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_SERVICE_EXAMPLE");
            i.putExtra("command","clearall");
            sendBroadcast(i);
        }
        else if(v.getId() == R.id.btnListNotify){
            Intent i = new Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_SERVICE_EXAMPLE");
            i.putExtra("command","list");
            sendBroadcast(i);
        }


    }

    class NotificationReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            String temp = intent.getStringExtra("notification_event") + "n" + txtView.getText();
            txtView.setText(temp);
        }
    }



}

2. NLService.java
package com.kpbird.nlsexample;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;

public class NLService extends NotificationListenerService {

    private String TAG = this.getClass().getSimpleName();
    private NLServiceReceiver nlservicereciver;
    @Override
    public void onCreate() {
        super.onCreate();
        nlservicereciver = new NLServiceReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_SERVICE_EXAMPLE");
        registerReceiver(nlservicereciver,filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(nlservicereciver);
    }

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {

        Log.i(TAG,"**********  onNotificationPosted");
        Log.i(TAG,"ID :" + sbn.getId() + "t" + sbn.getNotification().tickerText + "t" + sbn.getPackageName());
        Intent i = new  Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE");
        i.putExtra("notification_event","onNotificationPosted :" + sbn.getPackageName() + "n");
        sendBroadcast(i);

    }

    @Override
    public void onNotificationRemoved(StatusBarNotification sbn) {
        Log.i(TAG,"********** onNOtificationRemoved");
        Log.i(TAG,"ID :" + sbn.getId() + "t" + sbn.getNotification().tickerText +"t" + sbn.getPackageName());
        Intent i = new  Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE");
        i.putExtra("notification_event","onNotificationRemoved :" + sbn.getPackageName() + "n");

        sendBroadcast(i);
    }

    class NLServiceReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            if(intent.getStringExtra("command").equals("clearall")){
                    NLService.this.cancelAllNotifications();
            }
            else if(intent.getStringExtra("command").equals("list")){
                Intent i1 = new  Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE");
                i1.putExtra("notification_event","=====================");
                sendBroadcast(i1);
                int i=1;
                for (StatusBarNotification sbn : NLService.this.getActiveNotifications()) {
                    Intent i2 = new  Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE");
                    i2.putExtra("notification_event",i +" " + sbn.getPackageName() + "n");
                    sendBroadcast(i2);
                    i++;
                }
                Intent i3 = new  Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE");
                i3.putExtra("notification_event","===== Notification List ====");
                sendBroadcast(i3);

            }

        }
    }

}

3. activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Create Notification"
            android:id="@+id/btnCreateNotify"
            android:onClick="buttonClicked"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true"/>



    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Clear All Notification"
            android:id="@+id/btnClearNotify"
            android:onClick="buttonClicked"
            android:layout_below="@+id/btnCreateNotify"
            android:layout_alignLeft="@+id/btnCreateNotify"
            android:layout_alignRight="@+id/btnCreateNotify"/>

    <ScrollView android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_alignParentBottom="true"
                android:layout_alignRight="@+id/btnListNotify"
                android:layout_below="@+id/btnListNotify"
                android:layout_alignLeft="@+id/btnListNotify">

        <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:text="NotificationListenerService Example"
                android:id="@+id/textView"
                />


    </ScrollView>

    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="List of Notification"
            android:id="@+id/btnListNotify"
            android:onClick="buttonClicked"
            android:layout_below="@+id/btnClearNotify"
            android:layout_alignLeft="@+id/btnClearNotify"
            android:layout_alignRight="@+id/btnClearNotify"/>
</RelativeLayout>

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

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.kpbird.nlsexample.MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <service android:name="com.kpbird.nlsexample.NLService"
                 android:label="@string/app_name"
                 android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
            <intent-filter>
                <action android:name="android.service.notification.NotificationListenerService" />
            </intent-filter>
        </service>
    </application>

</manifest>



User following code to open Notification Access setting screen
Intent intent=new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
startActivity(intent);

Download Source Code from GitHub 

continue reading Android NotificationListenerService Example

Jul 25, 2013

Android 4.3 API Changes

src : http://media.heavy.com/media/2013/05/nexus-4-android-4.31.jpg

Android 4.3, API Level 18.

Major Features
1. Performance Improvement
2. Support OpenGL ES 3.0
3. Hardware accelerated 2D rendering
4. Multithreading across multiple CPU cores
5. Enhanced Bluetooth Connectivity
6. Support for Restricted Profiles (Good for parents)
7. Optimised Location and Sensor
8. Hardware geofencing
9. VP8 encoding
10. Media muxer
11. Access to notification ( Notification listener service)
12. Improve Right to Left language
13. Utilities for localisation
14. Enterprise and Security
15. New ways to Analyse Performance
16. On-screen GPU profiling
17. And more.

API Difference
Android 4.3 (API Level 18) released yesterday.The overall difference between API Levels 17 and 18 is approximately 1.64%.

Following Table illustrated difference between API Level 17 and 18 

Type Additions Changes Removals Total
Packages 2 37 0 39
Classes and Interfaces 61 108 36 205
Constructors 4 1 0 5
Methods 155 44 4 203
Fields 131 25 1 157
Total 353 215 41 609

API Difference Package Wise

Following Table represent difference in packages
continue reading Android 4.3 API Changes

Jul 23, 2013

Android ActivityRecognition Example


Introduction
Activity Recognition is very interesting API, It can open a gate of whole new kind of application and so helps to optimise existing apps, Activity Recognition is very simple API, It recognises four activities 1] In vehicle,2] On bicycle, 3] On foot and 4] Still. 

Location based application can take advantage of Activity Recognition API to optimise, accurate and battery efficient application with combination of Fused Location providers. Normally location based application fetch location periodically and push to the server, which is not optimise, Based on user's activity we can increase, decrease or stop location request.

Useful Methods
1. ActivityRecognitionClient
  • connect()
  • disconnect()
  • requestActivityUpdates()
  • removeActivityUpdates()
2. ActivityRecognitionResult
  • hasResult()
  • extractResult()
  • getMostProbableActivity().getType()
  • getMostProbableActivity().getConfidence()
Process
Let's understand with this diagram


1] Following operation needs to be done in Activity
  • Check availability of Google Play Service using "isGooglePlayServiceAvailable" function
  • If Google Play Service is available then do following steps
    • Implements ConnectCallback and OnConnectionFailedListener
    • Create Object of ActivityRecognitionClient 
    • Call connect() method using object of ActivityRecognitionClient.
    • onConnect method will call after connection is established between app and Google Play service. In this method we should start request for Activity Recognition.
    • Create and register BroadcastReceiver.
  • In Destroy method 
    • We need to remove activityupdates, disconnect with Google Play Service and remove BroadcastReceiver. 
2] In this example I am using BroadcastReceiver to pass ActivityRecognition data from IntentService to Activity. You can use any other technique as per requirement.

3] Google Play Service pass ActivityRecognitionResult object through Intent in IntentService.
4] Fire a BroadcastReceiver with Activity Type and Confidence.
5] Activity receives data and displays in TextView.

Application Screenshot

Source Code

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

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="17" />

    <uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        
        <activity
            android:name="com.kpbird.myactivityrecognition.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/tvActivity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:text="@string/hello_world" />

</RelativeLayout>

MainActivity.java
package com.kpbird.myactivityrecognition;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.ActivityRecognitionClient;

public class MainActivity extends Activity implements GooglePlayServicesClient.ConnectionCallbacks,GooglePlayServicesClient.OnConnectionFailedListener {

 private ActivityRecognitionClient arclient;
 private PendingIntent pIntent;
 private BroadcastReceiver receiver;
 private TextView tvActivity;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  tvActivity = (TextView) findViewById(R.id.tvActivity);
  
  int resp =GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
  if(resp == ConnectionResult.SUCCESS){
   arclient = new ActivityRecognitionClient(this, this, this);
   arclient.connect();
   
   
  }
  else{
   Toast.makeText(this, "Please install Google Play Service.", Toast.LENGTH_SHORT).show();
  }
  
  receiver = new BroadcastReceiver() {
      @Override
      public void onReceive(Context context, Intent intent) {
       String v =  "Activity :" + intent.getStringExtra("Activity") + " " + "Confidence : " + intent.getExtras().getInt("Confidence") + "n";
       v += tvActivity.getText();
       tvActivity.setText(v);
      }
    };
    
   IntentFilter filter = new IntentFilter();
   filter.addAction("com.kpbird.myactivityrecognition.ACTIVITY_RECOGNITION_DATA");
   registerReceiver(receiver, filter);
  
 }
 
 
 @Override
 protected void onDestroy() {
  super.onDestroy();
  if(arclient!=null){
   arclient.removeActivityUpdates(pIntent);
   arclient.disconnect();
  }
  unregisterReceiver(receiver);
 }
 
 @Override
 public void onConnectionFailed(ConnectionResult arg0) {
  Toast.makeText(this, "Connection Failed", Toast.LENGTH_SHORT).show();
 }
 @Override
 public void onConnected(Bundle arg0) {
  Intent intent = new Intent(this, ActivityRecognitionService.class);
  pIntent = PendingIntent.getService(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
  arclient.requestActivityUpdates(1000, pIntent);   
 }
 @Override
 public void onDisconnected() {
 }

 
}


ActivityRecognitionService.java
package com.kpbird.myactivityrecognition;

import com.google.android.gms.location.ActivityRecognitionResult;
import com.google.android.gms.location.DetectedActivity;

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

public class ActivityRecognitionService extends IntentService  {

 private String TAG = this.getClass().getSimpleName();
 public ActivityRecognitionService() {
  super("My Activity Recognition Service");
 }

 @Override
 protected void onHandleIntent(Intent intent) {
  if(ActivityRecognitionResult.hasResult(intent)){
   ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
   Log.i(TAG, getType(result.getMostProbableActivity().getType()) +"t" + result.getMostProbableActivity().getConfidence());
   Intent i = new Intent("com.kpbird.myactivityrecognition.ACTIVITY_RECOGNITION_DATA");
   i.putExtra("Activity", getType(result.getMostProbableActivity().getType()) );
   i.putExtra("Confidence", result.getMostProbableActivity().getConfidence());
   sendBroadcast(i);
  }
 }
 
 private String getType(int type){
  if(type == DetectedActivity.UNKNOWN)
   return "Unknown";
  else if(type == DetectedActivity.IN_VEHICLE)
   return "In Vehicle";
  else if(type == DetectedActivity.ON_BICYCLE)
   return "On Bicycle";
  else if(type == DetectedActivity.ON_FOOT)
   return "On Foot";
  else if(type == DetectedActivity.STILL)
   return "Still";
  else if(type == DetectedActivity.TILTING)
   return "Tilting";
  else
   return "";
 }

}

Download Source Code from Github

References
continue reading Android ActivityRecognition Example

Jul 22, 2013

10 Things about good and not good programmers

Disclaimer : This is my thought, What I am thinking about good and not good programmers, It might not be applicable in every situation or condition. Don’t take it personally if your behaviour falls in not good developers.

It has been nearly 6 years since my debut in the software industry. I have written lots of code and developed applications for various domains and platforms.

I’ve learnt a lot of new tools and techniques, and my learning in ongoing,  but many times I question myself,  “Am I a good developer or a bad developer” ?

Good Developer
1. In-depth Understanding of programming language 
2. Think in code / programming / logical way
3. Write simple code that other programmers can understand 
4. Don't hesitate to delete the code
5. Experiment new tools and techniques
6. Always have side project for trials
7. Pursuit for perfect code
8. Think about flexibility 
9. Develop own tools 
10. Write Blog about their work

Not good Developer
1. Poor understanding of programming language 
2. Poor analytical and logical skills
3. Write unstructured, unorganised and ugly code
4. Never discuss about technical stuff with friends and colleague
5. Lack of self upgrade 
6. Unable to think about interlinked code (normally open more bugs when fix one )
7. Don't care about optimisation and memory management
8. Locked in stereo type of coding 
9. They complete Tasks only
10. They will wait until the 100% details are available.

continue reading 10 Things about good and not good programmers

Jul 18, 2013

How to develop google plus app like bottom menu ?

How to develop Google+ app like bottom menu ?
Google+ app detects scroll direction to maintain visibility of bottom menu bar. When user scroll up content, bottom menu will hide with animation so that user can see the new item coming up from the bottom. When user scroll down, bottom menu bar will visible so that user can access menus available in bottom menu bar.

We can achieve same functionality using Animation, Fragment as bottom menu bar and onscrolllistener event of ListView. 

 

Step 1: Create Android Project in your favourite IDE

Step 2: Create Fragment for Bottom Menu, 
  • Create new java file named "BottomFragmentMenu.java"
  • Create new layout named "bottom_menu.xml" for the bottom menu fragment
  • Implement onCreateView method in BottomFragmentMenu.java and inflate bottom_menu.xml
  • Fetch ImageButton object from the view
  • Implement and set click listener of buttons
BottomFragmentMenu.java
package com.kpbird.bottommenubar;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.Toast;

public class BottomMenuFragment extends Fragment implements OnClickListener {

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
  View view = inflater.inflate(R.layout.bottom_menu, container,false);
  ImageButton b1 =(ImageButton)view.findViewById(R.id.imageButton1);
  ImageButton b2 =(ImageButton)view.findViewById(R.id.imageButton2);
  ImageButton b3 =(ImageButton)view.findViewById(R.id.imageButton3);
  ImageButton b4 =(ImageButton)view.findViewById(R.id.imageButton4);

  b1.setOnClickListener(this);
  b2.setOnClickListener(this);
  b3.setOnClickListener(this);
  b4.setOnClickListener(this);
  
  return view;
 }

 @Override
 public void onClick(View v) {
  switch(v.getId()){
  case R.id.imageButton1:
   Toast.makeText(getActivity() ,"Button 1 clicked", Toast.LENGTH_LONG).show();
   break;
  case R.id.imageButton2:
   Toast.makeText(getActivity() ,"Button 2 clicked", Toast.LENGTH_LONG).show();
   break;
  case R.id.imageButton3:
   Toast.makeText(getActivity() ,"Button 3 clicked", Toast.LENGTH_LONG).show();
   break;
  case R.id.imageButton4:
   Toast.makeText(getActivity() ,"Button 4 clicked", Toast.LENGTH_LONG).show();
   break;
  }
 }
}
bottom_menu.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="wrap_content"
    android:background="#80666666"
    android:gravity="center_horizontal"
    android:orientation="horizontal" >

    <ImageButton
        android:id="@+id/imageButton1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:layout_margin="5dp"
        android:src="@drawable/button1" />

    <ImageButton
        android:id="@+id/imageButton2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:layout_margin="5dp"
        android:src="@drawable/button2" />

    <ImageButton
        android:id="@+id/imageButton3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:layout_margin="5dp"
        android:src="@drawable/button3" />

    <ImageButton
        android:id="@+id/imageButton4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:layout_margin="5dp"
        android:src="@drawable/button4" />

</LinearLayout>

Step 3: Create Animation for Bottom Menu, we require two animations 1 entry.xml and 2. exit.xml respectively for to make fragment visible and hide. It's very simple Object Animator with translationY property, If you are developing app for Android 2.3, you can use translate animation. 

entry.xml
<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/linear"
    android:valueFrom="100"
    android:valueTo="0"
    android:propertyName="translationY"
    android:duration="@android:integer/config_shortAnimTime" />

exit.xml
<?xml version="1.0" encoding="utf-8" ?>
<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/linear"
    android:valueFrom="0"
    android:valueTo="100"
    android:propertyName="translationY"
    android:duration="@android:integer/config_shortAnimTime"/>


Step 4: Let's modify activity_main.xml and  MainActivity.java files to have real action.
  • Open activity_main.xml and add ListView (with match_parent height and width) and add fragment (with match_parent width, wrap_content hight and align parent bottom).
  • Open MainActivity.java and populate ListView with countries, In this example I am using ArrayAdapter and String Array (from strings.xml).
  • Implement OnScrollListener of ListView, In onScroll method we just need to calculate whether user fling down or up, We need to hide bottom fragment when user scroll down and visible when user scroll up.
MainActivity.java
package com.kpbird.bottommenubar;

import android.app.Activity;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.util.Log;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends Activity implements OnScrollListener{

 private String TAG = this.getClass().getSimpleName();
 private ListView listview;
 private BottomMenuFragment bmfragment;
 private int lastposition;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  listview = (ListView) findViewById(R.id.listview);
  String[] countries = getResources().getStringArray(R.array.countries_array);
  ArrayAdapter<String> aa = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, countries);
  listview.setAdapter(aa);
  listview.setOnScrollListener(this);
  
  bmfragment = (BottomMenuFragment) getFragmentManager().findFragmentById(R.id.fragment_bottom_menu);
  
 }
 @Override
 public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
   int currentPosition = view.getFirstVisiblePosition();
         if(currentPosition > lastposition) {
             //scroll down
          Log.i(TAG,"on Scroll Down");
          FragmentTransaction ft = getFragmentManager().beginTransaction();
          ft.setCustomAnimations(R.animator.enter, R.animator.exit);
       ft.hide(bmfragment);
       ft.commit();
         }
         if(currentPosition < lastposition) {
             //scroll up
          Log.i(TAG,"on Scroll Up");
          FragmentTransaction ft = getFragmentManager().beginTransaction();
          ft.setCustomAnimations(R.animator.enter, R.animator.exit);
       ft.show(bmfragment);
       ft.commit();
         }
         lastposition = currentPosition;
 }
 @Override
 public void onScrollStateChanged(AbsListView view, int scrollState) {
  
 }
}

Download Source from Github.com



continue reading How to develop google plus app like bottom menu ?