Sunday, June 14, 2015

Android Activity and Fragment Transition

Its very obvious to have a question "What is a Transition?"

Transition(s) is(are) is a new feature in android development which provide convenient APIs for animating between different UI states in application. This feature  was introduced in KitKat.

This framework is built around two key features-
  1. Scene  - A Scene defines a state of an application's UI.
  2. Transition - Transition basically is animated changes between two screens.
When Scene changes, a transition has to do two main works -
  1. Capture the state of each view in both start and end scene.
  2. Create an animation based on the differences that will animate views from old scene to new scene.
For Demo just consider an Screen which fades its views in or out when user interact with screen.
this can be achieved by below code easily.

public class FadeActivity extends Activity implements View.OnClickListener {
       
       private ViewGroup mGroupColor;
       private View mColor1View, mColor2View, mColor3View, m4View;
      
      @Override
       protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState); 
             setContentView(R.layout.activity_main);

             mGroupColor= (ViewGroup) findViewById(R.id.group_color_layout);
             mColor1View = findViewById(R.id.color_one);
             mColor2View = findViewById(R.id.color_two);
             mColor3View = findViewById(R.id.color_three);
             mColor4View = findViewById(R.id.color_four);

             mRootView.setOnClickListener(this);
      }
     
      @Override
       public void onClick(View v) { 
              TransitionManager.beginDelayedTransition(mGroupView, new Fade()); 
               toggleVisibility(mColor1View, mColor2View, mColor3View, mColor4View);
       }

       private static void toggleVisibility(View... views) {
              for (View view : views) {
                     boolean isVisible;
                     if(view.getVisibility() == View.VISIBLE)
                             isVisible=true;
                     if(isVisible)
                             view.setVisibility(View.INVISIBLE);
                     else  view.setVisibility(View.VISIBLE);
             }
       }
}


If I click  beginDelayedTransition() method got called in which scene root and a Fade transition passed as the arguments. And imminently captureStartValues() method got called for each view in the scene and the transition records each view's visibility.When the call returns, each view's visibility in the scene is changing from VISIBLE to INVISIBLE.
On the next display frame, captureEndValues() method got called for each view in the scene and the transition records each view's new updated visibility.
Then createAnimator() method will be called. And the transition observes start and end values of each view and notices a difference(views are VISIBLE in the start scene but INVISIBLE in the end).
The Fade transition uses this information to create and return an AnimatorSet that will fade each view's alpha property to 0f.
Returned animator will be run by framework and all views to gradually fade out of the screen.


Now we will see how this can be done using Lollipop's new Activity and Fragment transition APIs.


Activity & Fragment Transitions in Lollipop

In Android 5.0 and above transitions can  while switching between Activities or Fragments.

Lets Discuss the procedure to implement transition between activities(fragments).


FirstActivity is starting SecondActivity by startActivity() method.

Since Activity transition APIs provide exit, enter, return, and reenter transitions.
In Our case we can describe it as below:
  1. FirstActivity's exit transition determines how views in FristActivity are animated when FristActivity calls SecondActivity.
  2. SecondActivity's enter transition determines how views in SecondActivty are animated when FristActivity calls SecondActivity.
  3. SecondActivity's return transition determines how views in SecondActivity are animated when SecondActivity returns to fristActivity.
  4. FirstActiivty's reenter transition determines how views in fristActivity are animated when SecondActivty returns to FristActivity. 

At last transition framework apply APIs for these above two activities.
Two types of transition will be applied on this process
  1. Content Transition  - it determines how non shared views (transitioning views) enter and exit the Actvity Scene.
  2. Shared Element Transition -  it determines   how shared views (hero views) are animated between activities.

The exit and reenter content transitions for FirstActivity (the calling activity) are both null.
We can tell because the non-shared views in FirstActivty are not animated when the user exits and reenters the activity.
The enter content transition for SecondActivity(the called activity) uses a custom slide-in transition that shuffles the list items into place from the bottom of the screen.
The return content transition for SecondActivity is a TransitionSet that plays two child transitions in parallel: a Slide(Gravity.TOP) transition targeting the views in the top half of the activity and a Slide(Gravity.BOTTOM) transition targeting the views in the bottom half of the activity. The result is that the activity appears to "break in half" when the user clicks the back button and returns to FristrActivity.
The enter and return shared element transitions both use a ChangeImageTransform, causing the ImageView to be animated seamlessly between the two activities.

Creating a basic Activity transition is relatively easy using the new Lollipop APIs. Summarized below are the steps you must take in order to implement one in your application. In the posts that follow, we will go through much more advanced use-cases and examples, but for now the next two sections will serve as a good introduction:
Enable the new transition APIs by requesting the Window.FEATURE_ACTIVITY_TRANSITIONS window feature in your called and calling Activities, either programmatically or in your theme's XML.
Material-themed applications have this flag enabled by default.

To start an Activity transition with content transitions and shared elements, call the startActivity(Context, Bundle) method and pass the following Bundle as the second argument:

ActivityOptions.makeSceneTransitionAnimation(activity, pairs).toBundle();

where pairs is an array of Pair<View, String> objects listing the shared element views and names that you'd like to share between activities.

Don't forget to give your shared elements unique transition names, either programatically or in XML. Otherwise, the transition will not work properly!


To programatically trigger a return transition, call finishAfterTransition() instead of finish().


By default, material-themed applications have their enter/return content transitions started a tiny bit before their exit/reenter content transitions complete, creating a small overlap that makes the overall effect more seamless and dramatic. If you wish to explicitly disable this behavior, you can do so by calling the setWindowAllowEnterTransitionOverlap() and setWindowAllowReturnTransitionOverlap() methods or by setting the corresponding attributes in your theme's XML.

Same way the Fragment Transition API

If we are working with Fragment transitions, the API is similar with a few small differences:

Content exit, enter, reenter, and return transitions should be set by calling the corresponding methods in the Fragment class or as attributes in your Fragment's XML tag.
Shared element enter and return transitions should be set by calling the corresponding methods in the Fragment class or as attributes in your Fragment's XML.
Whereas Activity transitions are triggered by explicit calls to startActivity() and finishAfterTransition(), Fragment transitions are triggered automatically when a fragment is added, removed, attached, detached, shown, or hidden by a FragmentTransaction.
Shared elements should be specified as part of the FragmentTransaction by calling the addSharedElement(View, String) method before the transaction is committed.

Lots of thanks for reading.. Hope its helpful!

Tuesday, June 9, 2015

Navigation View by official Design Support Library


Android 5.0 Lollipop was one of the most significant Android releases ever, in no small part due to the introduction of material design, a new design language that refreshed the entire Android experience.
And detailed spec is a great place to start to adopt material design, but we understand that it can be a challenge for developers, particularly ones concerned with backward compatibility. With a little help from the new Android Design Support Library, we’re bringing a number of important material design components to all developers and to all Android 2.1 or higher devices.

Navigation View

The navigation drawer can be an important focal point for identity and navigation within your app and consistency in the design here can make a considerable difference in how easy your app is to navigate, particularly for first time users.



NavigationView makes this easier by providing the framework you need for the navigation drawer as well as the ability to inflate your navigation items through a menu resource.

To start off please include these libraries in the dependencies section of your build.gradle file:
     compile 'com.android.support:appcompat-v7:22.2.0'
     compile 'com.android.support:design:22.2.0'

     (An Example of Tabs in Material Design Previous Blog)

You use NavigationView as DrawerLayout’s drawer content view with a layout such as:

<android.support.v4.widget.DrawerLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:fitsSystemWindows="true">
             <!-- your content layout -->
             
             <android.support.design.widget.NavigationView
               android:layout_width="wrap_content"
               android:layout_height="match_parent"
               android:layout_gravity="start"
               app:headerLayout="@layout/drawer_header"
               app:menu="@menu/drawer"/>
</android.support.v4.widget.DrawerLayout>


You’ll note two attributes for NavigationView: app:headerLayout controls the (optional) layout used for the header.app:menu is the menu resource inflated for the navigation items (which can also be updated at runtime). NavigationViewtakes care of the scrim protection of the status bar for you, ensuring that your NavigationView interacts with the status bar appropriately on API21+ devices.

The simplest drawer menus will be a collection of checkable menu items:


<group android:checkableBehavior="single">

   <item android:id="@+id/navigation_item_1" 
     android:checked="true"
     android:icon="@drawable/ic_android"
     android:title="@string/navigation_item_1"/>
   <item android:id="@+id/navigation_item_2"
     android:icon="@drawable/ic_android"
     android:title="@string/navigation_item_2"/>
</group>

The checked item will appear highlighted in the navigation drawer, ensuring the user knows which navigation item is currently selected.

You can also use subheaders in your menu to separate groups of items:

<item android:id="@+id/navigation_subheader"
  android:title="@string/navigation_subheader">
  
        <menu>
            <item android:id="@+id/navigation_sub_item_1"
              android:icon="@drawable/ic_android"
              android:title="@string/navigation_sub_item_1"/>
           
          <item android:id="@+id/navigation_sub_item_2"
            android:icon="@drawable/ic_android"
            android:title="@string/navigation_sub_item_2"/>
     </menu>
</item>


You’ll get callbacks on selected items by setting a OnNavigationItemSelectedListener using setNavigationItemSelectedListener().
This provides you with the MenuItem that was clicked, allowing you to handle selection events, changed the checked status, load new content, programmatically close the drawer, or any other actions you may want.

Sunday, June 7, 2015

Android Tabs with ViewPager and Fragments





One of the best things about technology is that it keeps on changing. On the same lines recently some significant improvements were made for Android by the means of support library.
The new Design Support Library was included in the support repository. This new Android Design Support library features many new UI components like snackbars, floating action buttons and of-course it significantly improves the implementation of Android Tabs. Since Android design support library contains many new UI widgets which were introduced as concepts with material design.
I would write separate tutorials for each one of those. Here lets concentrate on the Android tabs example.

Earlier to make tabs in Android, action bar was used. But now with API 21 onwards it has been deprecated. An alternative way to make tabs with full backward support was to use SlidingTabLayout and SlidingTabStripclasses. But now with Android Design Support Library making swipe tabs has become even more simpler. In this Android Tabs example lets explore the power of new design support library.

Making an Android Tabs by using Android Design Support Library

Tab type navigation mode is a very common design pattern among android apps. But since Android’s 5.0 release, material design came in to picture and allot of changes were made in various APIs. Resulting the deprecation of action bar. Although a new API, Android Toolbar was released to replace it. Due to this change, new APIs for android tabs were also released through the design support library recently. The main class used for displaying tabs through these new APIs is Android TabLayout.
In this Android Tab example we would make a screen with three tabs using these new APIs for tabs with Fragments and a ViewPager which would look like the image below:








To start off please include these libraries in the dependencies section of your build.gradle file:

     compile 'com.android.support:appcompat-v7:22.2.0'
     compile 'com.android.support:design:22.2.0'


Now since we will be using Android Toolbar and TabLayout classes to show tabs, lets remove the action bar from layout by using styles:

<resources>
<!-- Base application theme. -->
       <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
              <!-- your app branding color for the app bar -->
              <item name="colorPrimary">#3F51B5</item>
              <!-- darker variant for the status bar and contextual app bars -->
              <item name="colorPrimaryDark">#303F9F</item>
              <!-- theme UI controls like checkboxes and text fields -->
              <item name="colorAccent">#FF4081</item>
     </style>
</resources>

Next, to display Android tabs with fragment and ViewPager, lets define three simple fragments and their layouts:

TabLayoutFragmentOne.java

public class TabLayoutFragmentOne extends Fragment {
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                 return inflater.inflate(R.layout.tab_fragment_layout_one, container, false);
        }
}

tab_fragment_layout_one.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:orientation="vertical">
        <TextView
          android:id="@+id/textView"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_centerInParent="true"
          android:text="Tab 1"
          android:textAppearance="?android:attr/textAppearanceLarge"/>

</RelativeLayout>

TabLayoutFragmentTwo.java

public class TabLayoutFragmentTwo extends Fragment {
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                 return inflater.inflate(R.layout.tab_fragment_layout_two, container, false);
        }
}

tab_fragment_layout_two.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:orientation="vertical">
        <TextView
          android:id="@+id/textView"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_centerInParent="true"
          android:text="Tab 2"
          android:textAppearance="?android:attr/textAppearanceLarge"/>

</RelativeLayout>

TabLayoutFragmentThree.java

public class TabLayoutFragmentThree extends Fragment {
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                 return inflater.inflate(R.layout.tab_fragment_layout_three, container, false);
        }
}

tab_fragment_layout_three.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:orientation="vertical">
        <TextView
          android:id="@+id/textView"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_centerInParent="true"
          android:text="Tab 3"
          android:textAppearance="?android:attr/textAppearanceLarge"/>

</RelativeLayout>


Now that we have all the tab fragments defined, lets define a view pager adapter for the swipe tabs feature:

PagerAdapter.java

public class PagerAdapter extends FragmentStatePagerAdapter {
       int mNumOfTabs;

      public PagerAdapter(FragmentManager fm, int NumOfTabs) {
                  super(fm);
                  this.mNumOfTabs = NumOfTabs;
      }

     @Override
      public Fragment getItem(int position) {
                switch (position) {
                       case 0:
                              TabLayoutFragmentOne tab1 = new TabLayoutFragmentOne();
                               return tab1;
                       case 1:
                               TabLayoutFragmentTwo tab2 = new TabLayoutFragmentTwo();
                                return tab2;
                       case 2:
                               TabLayoutFragmentThree tab3 = new TabLayoutFragmentThree();
                                return tab3;
                       default:
                               return null;
              }
    }

     @Override
      public int getCount() {
                       return mNumOfTabs;
      }
}

In the view state pager adapter above, you may see that I have just initialized the fragments as per their location. Next lets define the layout for main activity where all these tabs would be displayed.

Displaying Tabs using Android TabLayout


main_layout.xml

<RelativeLayout
   android:id="@+id/main_layout"
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity">

       <include layout="@layout/custom_action_bar"/>

      <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/toolbar"
        android:background="#aaffffff"
        android:elevation="6dp"
        android:minHeight="?attr/actionBarSize"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

    <android.support.v4.view.ViewPager
      android:id="@+id/pager"
      android:layout_width="match_parent"
      android:layout_height="fill_parent"
      android:layout_below="@id/tab_layout"/>

</RelativeLayout>

Earlier tabs were added to the action bar through code. But as you can see in this Android tabs example layout above we are using Toolbar and the TabLayout separately to display tabs. Also please note a view pager is also added, which would be attached to this TabLayout in the activity below through code.

MainActivity.java

public class MainActivity extends AppCompatActivity {

      @Override
       protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);

            TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
            tabLayout.addTab(tabLayout.newTab().setText("Once"));
            tabLayout.addTab(tabLayout.newTab().setText("Monthly"));
            tabLayout.addTab(tabLayout.newTab().setText("Yearly"));
            tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);

            final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
            final PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
            viewPager.setAdapter(adapter);
            viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
            tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
                     @Override
                     public void onTabSelected(TabLayout.Tab tab) {
                     viewPager.setCurrentItem(tab.getPosition());
                     }

                    @Override
                    public void onTabUnselected(TabLayout.Tab tab) {

                    }

                    @Override
                    public void onTabReselected(TabLayout.Tab tab) {

                    }
           });
       }

 }


Hope this helps.

Monday, June 1, 2015

"Do Not Disturb" mode in Android M

Lollipop's interruptions system has been consolidated under a new feature — Do Not Disturb. 
In the first Android M developer preview, DND mode can be to toggled through the quick settings menu in the notification shade, and tapping this new icon allows you to change between the various modes.




  1. Priority only works like Lollipop's priority mode, letting you block all interruptions except those from people and apps you consider important.
  2. Total silence works like the "none" setting in Lollipop, blocking everything including alarms.
  3. Alarms only is new in M and blocks everything except alarms.
In the first developer preview the option to switch between these modes is only available in the quick settings area, not through the Settings app.
The Settings > Sound & notification > Do not disturb menu is just used to set what gets through in "Priority only" mode, and control automatic DND rules.


Mute mode in Android M

While it isn't labeled as such, mute mode is basically back in the current M preview. Provided DND mode isn't enabled, pressing the volume down key again with the volume level set to vibrate will activate the "alarms only" DND mode until you specify otherwise. This means you won't be interrupted by calls, emails and other notifications overnight, but your alarms will still fire the next morning.


Monday, May 4, 2015

Multidex issue in Android Development

Times Now Android App is one of the most feature-rich apps available for Android.
With features like Push Notifications, News Feed, Recording Videos and Uploading, Linking with Google(Plus), Twitter and Facebook and an embedded version of Times Now Newshour (a complete app in its own right) all working together in real-time, the complexity and volume of code creates technical challenges that few, if any, other Android developers face--especially on older versions of the platform.

One of these challenges is related to the way Android's runtime engine, the Dalvik Virtual Machine, handles Java methods.
This App caused the number of Java methods drastically increase.

As we were testing we faced a bug related to over 65k Methods (Too many methods issue) .


After a bit of panic, we realized that we could work around this problem by breaking our app into multiple dex files, using the technique described here,  which focuses on using secondary dex files for extension modules, not core parts of the app.

However, there was no way we could break our app up this way--too many of our classes are accessed directly by the Android framework and different SDKs .
This wasn't normally possible, but we examined the Android source code and used Java reflection to directly modify some of its internal structures.
We were certainly glad and grateful that Android is open source—otherwise, this change wouldn’t have been possible.

We tried various techniques to reclaim space, including aggressive use of ProGuard/MinifyEnabled and source code transformations to reduce our method count.
Nothing we tried had a significant impact, and we still needed to write many more methods to support all of the rich content types in our new and improved news feed and timeline.

As it stood with our code, It was not easy to release our App TimesNow version 1.0.0.
It seemed like we would have to choose between cutting significant features from the app.
Nothing seemed acceptable. We needed a better solution.

Then we decided having multiple dex files in our APK,
We tried a lot solutions but were not getting success. And finally after a lot work we got the solution..
We built code and ran it on device, it ran successfully, this gave a smile on our face and self confidence that we handled a big problem which was not handled by many developers till now.

So Here we are giving tips/instructions to handle this problem if you will ever face it.

1. Create a text file (with name multidex.keep) in app module of project at the level of src and libs.
    Copy and paste these lines of code in your this created text file

Level of multidex.keep file in your project

android/support/multidex/BuildConfig/class
android/support/multidex/MultiDex$V14/class
android/support/multidex/MultiDex$V19/class
android/support/multidex/MultiDex$V4/class
android/support/multidex/MultiDex/class
android/support/multidex/MultiDexApplication/class
android/support/multidex/MultiDexExtractor$1/class
android/support/multidex/MultiDexExtractor/class
android/support/multidex/ZipUtil$CentralDirectory/class
android/support/multidex/ZipUtil/class

2. Edit your build.gradle file and add following blue bold lines

android {
    minSdkVersion 16
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "your.package.name"
        ..........    }

    buildTypes {
        release {
         .............................
        }
    }
// Inside android part of build.gradle
    dexOptions {
        preDexLibraries = false
    }

}
.............
............

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
     ..................

// Inside dependencies part of build.gradle
    compile 'com.android.support:multidex:1.0.1'
    ..............
}


// Outside android part of build.gradle
afterEvaluate {
    tasks.matching {
        it.name.startsWith('dex')
    }.each { dx ->
        if (dx.additionalParameters == null) {
            dx.additionalParameters = []
        }
        dx.additionalParameters += '--multi-dex'
        dx.additionalParameters += "--main-dex-list=$projectDir/multidex.keep".toString()
    }

     ........
     .......
}

3.  Edit your Application class and add following blue bold lines

public class MyApp extends MultiDexApplication {
  ....
  ....
}


And Now You are done with this issue.
Refer developer website here to read more about this issue and handling it.

Thanks a lot for this much patience.