Wednesday, January 15, 2014

New UI features and design guidelines for Android 4.4 KitKat

Android Design in Action: New in Android 4.4

Example of ViewAnimator

android.widget.ViewAnimator is a subclass of FrameLayout container that will perform animations when switching between its views.





<LinearLayout 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:orientation="vertical"
    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:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

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

        <Button
            android:id="@+id/prev"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="previous" />

        <Button
            android:id="@+id/next"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="next" />
    </LinearLayout>

    <ViewAnimator
        android:id="@+id/viewanimator"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView 1" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button 2" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button 3" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:gravity="center" >

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="- Button 4 -" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="LinearLayout 4" />
        </LinearLayout>
    </ViewAnimator>

</LinearLayout>



package com.example.androidviewanimator;

import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ViewAnimator;

public class MainActivity extends Activity {
 
 Button buttonPrev, buttonNext;
 ViewAnimator viewAnimator;
 
 Animation slide_in_left, slide_out_right;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  buttonPrev = (Button)findViewById(R.id.prev);
  buttonNext = (Button)findViewById(R.id.next);
  viewAnimator = (ViewAnimator)findViewById(R.id.viewanimator);
  
  slide_in_left = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);
  slide_out_right = AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right);
  
  viewAnimator.setInAnimation(slide_in_left);
  viewAnimator.setOutAnimation(slide_out_right);
  
  buttonPrev.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {
    viewAnimator.showPrevious();
   }});
  
  buttonNext.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {
    viewAnimator.showNext();
   }});
 }

}

Example to implement Android TextSwitcher

android.widget.TextSwitcher is a specialized ViewSwitcher that contains only children of type TextView. A TextSwitcher is useful to animate a label on screen. Whenever setText(CharSequence) is called, TextSwitcher animates the current text out and animates the new text in.


Example of TextSwitcher
Example code to implement TextSwitcher.

package com.example.androidtextswitcher;

import com.example.androidviewanimator.R;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.Typeface;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.ViewSwitcher.ViewFactory;

public class MainActivity extends Activity {

 Button buttonNext;
 TextSwitcher textSwitcher;

 Animation slide_in_left, slide_out_right;

 String[] TextToSwitched = { "Sunday", "Monday", "Tuesday", "Wednesday",
   "Thursday", "Friday", "Saturday" };
 int curIndex;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  buttonNext = (Button) findViewById(R.id.next);
  textSwitcher = (TextSwitcher) findViewById(R.id.textswitcher);

  slide_in_left = AnimationUtils.loadAnimation(this,
    android.R.anim.slide_in_left);
  slide_out_right = AnimationUtils.loadAnimation(this,
    android.R.anim.slide_out_right);

  textSwitcher.setInAnimation(slide_in_left);
  textSwitcher.setOutAnimation(slide_out_right);
  
  textSwitcher.setFactory(new ViewFactory(){

   @Override
   public View makeView() {
    TextView textView = new TextView(MainActivity.this);
    textView.setTextSize(30);
    textView.setTextColor(Color.RED);
    textView.setGravity(Gravity.CENTER_HORIZONTAL);
    textView.setTypeface(Typeface.DEFAULT_BOLD);
    textView.setShadowLayer(10, 10, 10, Color.BLACK);
    return textView;
   }});

  curIndex = 0;
  textSwitcher.setText(TextToSwitched[curIndex]);

  buttonNext.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    if(curIndex == TextToSwitched.length-1){
     curIndex = 0;
     textSwitcher.setText(TextToSwitched[curIndex]);
    }else{
     textSwitcher.setText(TextToSwitched[++curIndex]);
    }
   }
  });
 }

}



<LinearLayout 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:orientation="vertical"
    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:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <TextSwitcher
        android:id="@+id/textswitcher"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/next"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="next" />

</LinearLayout>

Android example: ImageSwitcher

A simple example to implement ImageSwitcher.


Example of ImageSwitcher


package com.example.androidimageswitcher;

import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.ViewSwitcher.ViewFactory;

public class MainActivity extends Activity {

 Button buttonNext;
 ImageSwitcher imageSwitcher;

 Animation slide_in_left, slide_out_right;

 int imageResources[] = { 
   android.R.drawable.ic_dialog_alert,
   android.R.drawable.ic_dialog_dialer,
   android.R.drawable.ic_dialog_email,
   android.R.drawable.ic_dialog_info, 
   android.R.drawable.ic_dialog_map };

 int curIndex;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  buttonNext = (Button) findViewById(R.id.next);
  imageSwitcher = (ImageSwitcher) findViewById(R.id.imageswitcher);

  slide_in_left = AnimationUtils.loadAnimation(this,
    android.R.anim.slide_in_left);
  slide_out_right = AnimationUtils.loadAnimation(this,
    android.R.anim.slide_out_right);

  imageSwitcher.setInAnimation(slide_in_left);
  imageSwitcher.setOutAnimation(slide_out_right);

  imageSwitcher.setFactory(new ViewFactory() {

   @Override
   public View makeView() {

    ImageView imageView = new ImageView(MainActivity.this);
    imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);

    LayoutParams params = new ImageSwitcher.LayoutParams(
      LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

    imageView.setLayoutParams(params);
    return imageView;

   }
  });

  curIndex = 0;
  imageSwitcher.setImageResource(imageResources[curIndex]);

  buttonNext.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    if (curIndex == imageResources.length - 1) {
     curIndex = 0;
     imageSwitcher.setImageResource(imageResources[curIndex]);
    } else {
     imageSwitcher.setImageResource(imageResources[++curIndex]);
    }
   }
  });
 }

}



<LinearLayout 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:orientation="vertical"
    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:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <ImageSwitcher
        android:id="@+id/imageswitcher"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

    <Button
        android:id="@+id/next"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="next" />

</LinearLayout>

Good official lessons teach Caching Bitmaps and Managing Bitmap Memory

When your app have to load a number of bitmap, memory allocation will get complicated. Here is official lessons from developer.android.com.

  • Caching Bitmaps teach you using a memory and disk bitmap cache to improve the responsiveness and fluidity of your UI when loading multiple bitmaps.
  • Managing Bitmap Memory teach specific things you can do to facilitate garbage collection and bitmap reuse.
Also, the video Bitmap Allocation by DevBytes introduce how to speed up bitmap loading and reduce garbage collection by reusing existing bitmaps.

Example of ViewFlipper

android.widget.ViewFlipper is a simple ViewAnimator that will animate between two or more views that have been added to it. Only one child is shown at a time. If requested, can automatically flip between each child at a regular interval.


Example of ViewFlipper


<LinearLayout 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:orientation="vertical"
    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:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

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

        <Button
            android:id="@+id/prev"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="previous" />

        <Button
            android:id="@+id/next"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="next" />
    </LinearLayout>

    <ViewFlipper
        android:id="@+id/viewflipper"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="vertical" >

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="- Button 2 -" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="LinearLayout 2" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="vertical" >

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Enter something" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="LinearLayout 3" />
        </LinearLayout>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="ViewFlipper is a simple ViewAnimator that 
     will animate between two or more views that 
     have been added to it. Only one child is shown 
     at a time. If requested, can automatically 
     flip between each child at a regular interval." />
    </ViewFlipper>

</LinearLayout>


package com.example.androidviewflipper;

import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ViewFlipper;

public class MainActivity extends Activity {

 Button buttonPrev, buttonNext;
 ViewFlipper viewFlipper;

 Animation slide_in_left, slide_out_right;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  buttonPrev = (Button) findViewById(R.id.prev);
  buttonNext = (Button) findViewById(R.id.next);
  viewFlipper = (ViewFlipper) findViewById(R.id.viewflipper);

  slide_in_left = AnimationUtils.loadAnimation(this,
    android.R.anim.slide_in_left);
  slide_out_right = AnimationUtils.loadAnimation(this,
    android.R.anim.slide_out_right);

  viewFlipper.setInAnimation(slide_in_left);
  viewFlipper.setOutAnimation(slide_out_right);

  buttonPrev.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    viewFlipper.showPrevious();
   }
  });

  buttonNext.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    viewFlipper.showNext();
   }
  });
  ;
 }

}

Bi-direction sliding ViewFlipper

Last exercise show a Example of ViewFlipper. It always slide from left to right, no matter you click previous or next button. In this exercise, we will implement bi-direction sliding. Slide to right if you click next button, slide left if you click previous button. This technique can also be applied on ViewAnimator, TextSwitcher, ImageSwitcher and ViewSwitcher.


Bi-direction sliding ViewFlipper

Create /res/anim/ folder, and create the following XMLs to define the animation.

slide_in_left.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 <translate android:fromXDelta="-50%p" android:toXDelta="0"
            android:duration="1000"/>
 <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="1000" />
</set>


slide_in_right.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 <translate android:fromXDelta="50%p" android:toXDelta="0"
            android:duration="1000"/>
 <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="1000" />
</set>


slide_out_left.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 <translate android:fromXDelta="0" android:toXDelta="-50%p"
            android:duration="1000"/>
 <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
            android:duration="1000" />
</set>


slide_out_right.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 <translate android:fromXDelta="0" android:toXDelta="50%p"
            android:duration="1000"/>
 <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
            android:duration="1000" />
</set>


Modify layout file, all child View of <ViewFlipper> have android:layout_width="match_parent".

<LinearLayout 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:orientation="vertical"
    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:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

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

        <Button
            android:id="@+id/prev"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="previous" />

        <Button
            android:id="@+id/next"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="next" />
    </LinearLayout>

    <ViewFlipper
        android:id="@+id/viewflipper"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="vertical" >

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="- Button 2 -" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="LinearLayout 2" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="vertical" >

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Enter something" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="LinearLayout 3" />
        </LinearLayout>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="ViewFlipper is a simple ViewAnimator that 
     will animate between two or more views that 
     have been added to it. Only one child is shown 
     at a time. If requested, can automatically 
     flip between each child at a regular interval." />
    </ViewFlipper>

</LinearLayout>


Main code;

package com.example.androidviewflipper;

import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ViewFlipper;

public class MainActivity extends Activity {

 Button buttonPrev, buttonNext;
 ViewFlipper viewFlipper;

 Animation slide_in_left, slide_out_right;
 Animation slide_in_right, slide_out_left;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  buttonPrev = (Button) findViewById(R.id.prev);
  buttonNext = (Button) findViewById(R.id.next);
  viewFlipper = (ViewFlipper) findViewById(R.id.viewflipper);

  slide_in_left = AnimationUtils.loadAnimation(this,
    R.anim.slide_in_left);
  slide_out_right = AnimationUtils.loadAnimation(this,
    R.anim.slide_out_right);
  
  slide_in_right = AnimationUtils.loadAnimation(this,
    R.anim.slide_in_right);
  slide_out_left = AnimationUtils.loadAnimation(this,
    R.anim.slide_out_left);
  
  //viewFlipper.setInAnimation(slide_in_left);
  //viewFlipper.setOutAnimation(slide_out_right);

  buttonPrev.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    viewFlipper.setInAnimation(slide_in_right);
    viewFlipper.setOutAnimation(slide_out_left);
    viewFlipper.showPrevious();
   }
  });

  buttonNext.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    viewFlipper.setInAnimation(slide_in_left);
    viewFlipper.setOutAnimation(slide_out_right);
    viewFlipper.showNext();
   }
  });
  ;
 }
}

How to build Open JavaFX for Android

Here (https://blogs.oracle.com/jfxprg/entry/how_to_build_open_javafx) is a short recipe for baking JavaFX for Android dalvik. Just a few ingredients needed but each one requires special care

Android Programming: Pushing the Limits

Unleash the power of the Android OS and build the kinds of brilliant, innovative apps users love to use

If you already know your way around the Android OS and can build a simple Android app in under an hour, this book is for you. If you’re itching to see just how far you can push it and discover what Android is really capable of, it’s for you. And if you’re ready to learn how to build advanced, intuitive, innovative apps that are a blast to use, this book is definitely for you.
From custom views and advanced multi-touch gestures, to integrating online web services and exploiting the latest geofencing and activity recognition features, ace Android developer, Erik Hellman, delivers expert tips, tricks and little-known techniques for pushing the Android envelope so you can:
  • Optimize your components for the smoothest user experience possible
  • Create your own custom Views
  • Push the boundaries of the Android SDK
  • Master Android Studio and Gradle
  • Make optimal use of the Android audio, video and graphics APIs
  • Program in Text-To-Speech and Speech Recognition
  • Make the most of the new Android maps and location API
  • Use Android connectivity technologies to communicate with remote devices
  • Perform background processing
  • Use Android cryptography APIs
  • Find and safely use hidden Android APIs
  • Cloud-enable your applications with Google Play Services
  • Distribute and sell your applications on Google Play Store

Learn how to unleash the power of Android and transform your apps from good to great in Android Programming: Pushing the Limits.

Java Programming for Android Developers For Dummies

Get started creating Android apps with Java in no time!

The demand for Android apps is not slowing down but many mobile developers who want to create Android apps lack the necessary Java background. This beginner guide gets you up and running with using Java to create Android apps with no prior knowledge or experienced necessary!
  • Shows you the basic Java development concepts and techniques that are necessary to develop Android apps
  • Explores what goes into creating an Android app to give you a better understanding of the various elements
  • Addresses how to deal with standard programming challenges and debugging

Beginning Android Programming with Java For Dummies puts you well on your way toward creating Android apps quickly with Java.

Download The Windows Getting Started Guide



The Windows Getting Started Guide
This guide will point you to the right developer tools, tutorials, and resources. Jump in. The next generation is what you make it.

Download here.

and more resources on Microsoft Student web site

Using GestureDetector to detect user swipe, onFling()

Previous exercise demonstrate "Bi-direction sliding ViewFlipper" controlled by buttons. This exercise show how to implements GestureDetector.OnGestureListener to detect user swipe to update ViewFlipper.


Using GestureDetector to detect user swipe



package com.example.androidviewflipper;

import android.os.Bundle;
import android.app.Activity;
import android.support.v4.view.GestureDetectorCompat;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.Toast;
import android.widget.ViewFlipper;

public class MainActivity extends Activity implements 
 GestureDetector.OnGestureListener {
 
 private GestureDetectorCompat mDetector;

 Button buttonPrev, buttonNext;
 ViewFlipper viewFlipper;

 Animation slide_in_left, slide_out_right;
 Animation slide_in_right, slide_out_left;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  mDetector = new GestureDetectorCompat(this,this);

  buttonPrev = (Button) findViewById(R.id.prev);
  buttonNext = (Button) findViewById(R.id.next);
  viewFlipper = (ViewFlipper) findViewById(R.id.viewflipper);

  slide_in_left = AnimationUtils.loadAnimation(this,
    R.anim.slide_in_left);
  slide_out_right = AnimationUtils.loadAnimation(this,
    R.anim.slide_out_right);
  
  slide_in_right = AnimationUtils.loadAnimation(this,
    R.anim.slide_in_right);
  slide_out_left = AnimationUtils.loadAnimation(this,
    R.anim.slide_out_left);
  
  //viewFlipper.setInAnimation(slide_in_left);
  //viewFlipper.setOutAnimation(slide_out_right);

  buttonPrev.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    viewFlipper.setInAnimation(slide_in_right);
    viewFlipper.setOutAnimation(slide_out_left);
    viewFlipper.showPrevious();
   }
  });

  buttonNext.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    viewFlipper.setInAnimation(slide_in_left);
    viewFlipper.setOutAnimation(slide_out_right);
    viewFlipper.showNext();
   }
  });
  ;
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  this.mDetector.onTouchEvent(event);
  return super.onTouchEvent(event);
 }

 @Override
 public boolean onDown(MotionEvent arg0) {
  // TODO Auto-generated method stub
  return false;
 }

 @Override
 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
   float velocityY) {
  float sensitvity = 50;
  
  if((e1.getX() - e2.getX()) > sensitvity){
   viewFlipper.setInAnimation(slide_in_right);
   viewFlipper.setOutAnimation(slide_out_left);
   viewFlipper.showPrevious();
   Toast.makeText(MainActivity.this, 
     "Previous", Toast.LENGTH_SHORT).show();
  }else if((e2.getX() - e1.getX()) > sensitvity){
   viewFlipper.setInAnimation(slide_in_left);
   viewFlipper.setOutAnimation(slide_out_right);
   viewFlipper.showNext();
   Toast.makeText(MainActivity.this, 
     "Next", Toast.LENGTH_SHORT).show();
  }
  
  return true;
 }

 @Override
 public void onLongPress(MotionEvent e) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
   float distanceY) {
  // TODO Auto-generated method stub
  return false;
 }

 @Override
 public void onShowPress(MotionEvent e) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public boolean onSingleTapUp(MotionEvent e) {
  // TODO Auto-generated method stub
  return false;
 }

}


Keep using the layout and animation XML files in last exercise.

Detect Gesture by implementing GestureDetector.SimpleOnGestureListener

This example show how to detect user gesture by implementing GestureDetector.SimpleOnGestureListener. It have the same result as last exercise of "GestureDetector".


Example of using GestureDetector.SimpleOnGestureListener

GestureDetector.SimpleOnGestureListener provides an implementation for all of the on<TouchEvent> methods by returning false for all of them. Thus we can override only the methods we care about. In our application, we have to detect onFling() only. So we can extend GestureDetector.SimpleOnGestureListener instead of implementing the GestureDetector.OnGestureListener interface.

MainActivity.java

package com.example.androidviewflipper;

import android.os.Bundle;
import android.app.Activity;
import android.support.v4.view.GestureDetectorCompat;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.Toast;
import android.widget.ViewFlipper;

public class MainActivity extends Activity{
 
 private GestureDetectorCompat mDetector;

 Button buttonPrev, buttonNext;
 ViewFlipper viewFlipper;

 Animation slide_in_left, slide_out_right;
 Animation slide_in_right, slide_out_left;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  mDetector = new GestureDetectorCompat(this, new MyGestureListener());

  buttonPrev = (Button) findViewById(R.id.prev);
  buttonNext = (Button) findViewById(R.id.next);
  viewFlipper = (ViewFlipper) findViewById(R.id.viewflipper);

  slide_in_left = AnimationUtils.loadAnimation(this,
    R.anim.slide_in_left);
  slide_out_right = AnimationUtils.loadAnimation(this,
    R.anim.slide_out_right);
  
  slide_in_right = AnimationUtils.loadAnimation(this,
    R.anim.slide_in_right);
  slide_out_left = AnimationUtils.loadAnimation(this,
    R.anim.slide_out_left);

  buttonPrev.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    viewFlipper.setInAnimation(slide_in_right);
    viewFlipper.setOutAnimation(slide_out_left);
    viewFlipper.showPrevious();
   }
  });

  buttonNext.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View arg0) {
    viewFlipper.setInAnimation(slide_in_left);
    viewFlipper.setOutAnimation(slide_out_right);
    viewFlipper.showNext();
   }
  });
  ;
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  this.mDetector.onTouchEvent(event);
  return super.onTouchEvent(event);
 }

 class MyGestureListener extends GestureDetector.SimpleOnGestureListener {

  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
    float velocityY) {
   float sensitvity = 50;
   
   if((e1.getX() - e2.getX()) > sensitvity){
    viewFlipper.setInAnimation(slide_in_right);
    viewFlipper.setOutAnimation(slide_out_left);
    viewFlipper.showPrevious();
    Toast.makeText(MainActivity.this, 
      "Previous", Toast.LENGTH_SHORT).show();
   }else if((e2.getX() - e1.getX()) > sensitvity){
    viewFlipper.setInAnimation(slide_in_left);
    viewFlipper.setOutAnimation(slide_out_right);
    viewFlipper.showNext();
    Toast.makeText(MainActivity.this, 
      "Next", Toast.LENGTH_SHORT).show();
   }
   
   return true;
  }
    }
}


Keep using the layout and animation XML files in the exercise of "Bi-direction sliding ViewFlipper".

ActionBarCompat with ShareActionProvider

This exercise implement MenuItem of Share action in ActionBarCompat, and ShareActionProvider to share text if user click on the Share on the Share item. Base on last exercise "Handle onOptionsItemSelected() for ActionBarCompat".


ActionBarCompat with Share ShareActionProvider
ActionBarCompat with Share ShareActionProvider

Modify /res/menu/main.xml to add new item of action_share.

<menu 
    xmlns:myapp="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android" >

 <item
        android:id="@+id/action_share"
        android:title="Share"
        myapp:actionProviderClass="android.support.v7.widget.ShareActionProvider"
        myapp:showAsAction="always|withText" />
    <item
        android:id="@+id/action_settings"
        myapp:showAsAction="always|withText"
        android:title="@string/action_settings"/>

</menu>

MainActivity.java.

package com.example.testactionbarcompat;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.ShareActionProvider;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {
 
 private ShareActionProvider myShareActionProvider;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        
        //add MenuItem(s) to ActionBar using Java code
        MenuItem menuItem_Info = menu.add(0, R.id.menuid_info, 0, "Info");
        menuItem_Info.setIcon(android.R.drawable.ic_menu_info_details);
        MenuItemCompat.setShowAsAction(menuItem_Info, 
          MenuItem.SHOW_AS_ACTION_ALWAYS|MenuItem.SHOW_AS_ACTION_WITH_TEXT);
        
        //Handle share menu item
        MenuItem shareItem = menu.findItem(R.id.action_share);
        myShareActionProvider = (ShareActionProvider)
          MenuItemCompat.getActionProvider(shareItem);
        setShareIntent();
        
        return true;
    }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  // TODO Auto-generated method stub
  //return super.onOptionsItemSelected(item);
  switch (item.getItemId()) {
        case R.id.action_settings: 
         //match with /res/menu/main.xml
            Toast.makeText(this, "Setting", Toast.LENGTH_SHORT).show();
            return true;
        case R.id.menuid_info:  
         //match with defined in onCreateOptionsMenu()
         Toast.makeText(this, "Info", Toast.LENGTH_SHORT).show();
            return true;
        default:
            return super.onOptionsItemSelected(item);    
  }
 }
    
 //Set the share intent
 private void setShareIntent(){
  
  Intent intent = new Intent(Intent.ACTION_SEND);
  intent.setType("plain/text");
  intent.putExtra(Intent.EXTRA_TEXT, "Hello from android-er.blogspot.com"); 

  myShareActionProvider.setShareIntent(intent); 
 }

}

ActionBarCompat with ShareActionProvider to update dynamic content

Last exercise "ActionBarCompat with ShareActionProvider" setup share content in onCreateOptionsMenu(). The share data will not be updated after then. In this exercise, ShareIntent will be updated when user update content.

In my experiment, onOptionsItemSelected() will not be called when Share menu item clicked. So a TextWatcher is implemented when any EditText changed, to update ShareIntent.


ActionBarCompat with ShareActionProvider to update dynamic content
ActionBarCompat with ShareActionProvider to update dynamic content
Modify layout to add EditTexts for user to enter email address, title and content.

<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    
    <EditText 
        android:id="@+id/fieldemailaddress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textEmailAddress"
        android:hint="email address" />
    <EditText 
        android:id="@+id/fieldemailtitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hello from android-er.blogspot.com" 
        android:hint="email title"/>
    <EditText 
        android:id="@+id/fieldemailcontent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:hint="email content"/>

</LinearLayout>

/res/menu/main.xml, same as before.

<menu 
    xmlns:myapp="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android" >

 <item
        android:id="@+id/action_share"
        android:title="Share"
        myapp:actionProviderClass="android.support.v7.widget.ShareActionProvider"
        myapp:showAsAction="always|withText" />
    <item
        android:id="@+id/action_settings"
        myapp:showAsAction="always|withText"
        android:title="@string/action_settings"/>

</menu>

MainActivity.java

package com.example.testactionbarcompat;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.ShareActionProvider;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {
 
 EditText fieldEmailAddress, fieldEmailTitle, fieldEmailContent;
 
 private ShareActionProvider myShareActionProvider;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        fieldEmailAddress = (EditText)findViewById(R.id.fieldemailaddress);
        fieldEmailTitle = (EditText)findViewById(R.id.fieldemailtitle);
        fieldEmailContent = (EditText)findViewById(R.id.fieldemailcontent);
        
        fieldEmailAddress.addTextChangedListener(myTextWatcher);
        fieldEmailTitle.addTextChangedListener(myTextWatcher);
        fieldEmailContent.addTextChangedListener(myTextWatcher);
    }

    /*
     * update ActionProvider by calling setShareIntent()
     * When any EditText changed
     */
    TextWatcher myTextWatcher = new TextWatcher(){

  @Override
  public void afterTextChanged(Editable s) {
   setShareIntent();
  }

  @Override
  public void beforeTextChanged(CharSequence s, int start, 
    int count, int after) {}

  @Override
  public void onTextChanged(CharSequence s, int start, 
    int before, int count) {}
 };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        
        //add MenuItem(s) to ActionBar using Java code
        MenuItem menuItem_Info = menu.add(0, R.id.menuid_info, 0, "Info");
        menuItem_Info.setIcon(android.R.drawable.ic_menu_info_details);
        MenuItemCompat.setShowAsAction(menuItem_Info, 
          MenuItem.SHOW_AS_ACTION_ALWAYS|MenuItem.SHOW_AS_ACTION_WITH_TEXT);
        
        //Handle share menu item
        MenuItem shareItem = menu.findItem(R.id.action_share);
        myShareActionProvider = (ShareActionProvider)
          MenuItemCompat.getActionProvider(shareItem);
        setShareIntent();
        
        //return true;
        return super.onCreateOptionsMenu(menu);
    }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  // TODO Auto-generated method stub
  //return super.onOptionsItemSelected(item);
  switch (item.getItemId()) {
  case R.id.action_share: 
   //It never called in my experiment
   Toast.makeText(this, "Share", Toast.LENGTH_SHORT).show();
   setShareIntent();
   return false;
        case R.id.action_settings: 
         //match with /res/menu/main.xml
            Toast.makeText(this, "Setting", Toast.LENGTH_SHORT).show();
            return true;
        case R.id.menuid_info:  
         //match with defined in onCreateOptionsMenu()
         Toast.makeText(this, "Info", Toast.LENGTH_SHORT).show();
            return true;
        default:
            return super.onOptionsItemSelected(item);    
  }
 }
    
 //Set the share intent
 private void setShareIntent(){
  
  Intent intent = new Intent(Intent.ACTION_SEND);
  intent.setType("plain/text");
  intent.putExtra(Intent.EXTRA_EMAIL, 
    new String[]{fieldEmailAddress.getText().toString()}); 
  intent.putExtra(Intent.EXTRA_SUBJECT, 
    fieldEmailTitle.getText().toString());
  intent.putExtra(Intent.EXTRA_TEXT, 
    fieldEmailContent.getText().toString()); 

  myShareActionProvider.setShareIntent(intent); 
 }

}

Install the new Google Mobile Ads SDK for Android

Google have made some big changes recently to the SDK for Android; it's now included as part of Google Play services 4.0.

If you're an Android developer you'll be familiar with Google Play services, a unified platform which makes it easy to integrate Google features into your Android apps, delivered through the Play Store and updated at regular intervals. Now that AdMob is part of the package, a key benefit is that changes to the Google Mobile Ads SDK for Android get pushed seamlessly to users through Google Play services. For most SDK updates you don’t need to update your apps each time it changes, saving you development time. Follow these instructions to install the SDK. 

Implement Socket on Android to communicate with Raspberry Pi

There is a post "Java exercise - Implement client and server to communicate using Socket" in my another blog, Hello Raspberry Pi. In which, both host (implement ServerSocket and Socket) and client (implement Socket) are run on Raspberry Pi to setup communication between application via socket. Actually both the host and client can run on any PC with Java.

The client side in the post is ported to Android in this exercise, setup Socket in AsyncTask, to communicate with Raspberry Pi. The updated version of Host (run socket operation in background thread) run on Raspberry Pi or any other PC is here.


Implement Socket on Android to communicate with Raspberry Pi
Implement Socket on Android
MainActivity.java

package com.example.androidclient;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {
 
 TextView textResponse;
 EditText editTextAddress, editTextPort; 
 Button buttonConnect, buttonClear;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  editTextAddress = (EditText)findViewById(R.id.address);
  editTextPort = (EditText)findViewById(R.id.port);
  buttonConnect = (Button)findViewById(R.id.connect);
  buttonClear = (Button)findViewById(R.id.clear);
  textResponse = (TextView)findViewById(R.id.response);
  
  buttonConnect.setOnClickListener(buttonConnectOnClickListener);
  
  buttonClear.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    textResponse.setText("");
   }});
 }
 
 OnClickListener buttonConnectOnClickListener = 
   new OnClickListener(){

    @Override
    public void onClick(View arg0) {
     /*
      * You have to verify editTextAddress and
      * editTextPort are input as correct format.
      */
     
     MyClientTask myClientTask = new MyClientTask(
       editTextAddress.getText().toString(),
       Integer.parseInt(editTextPort.getText().toString()));
     myClientTask.execute();
    }};

 public class MyClientTask extends AsyncTask<Void, Void, Void> {
  
  String dstAddress;
  int dstPort;
  String response;
  
  MyClientTask(String addr, int port){
   dstAddress = addr;
   dstPort = port;
  }

  @Override
  protected Void doInBackground(Void... arg0) {
   
   try {
    Socket socket = new Socket(dstAddress, dstPort);
    InputStream inputStream = socket.getInputStream();
    ByteArrayOutputStream byteArrayOutputStream = 
                  new ByteArrayOutputStream(1024);
    byte[] buffer = new byte[1024];
    
    int bytesRead;
             while ((bytesRead = inputStream.read(buffer)) != -1){
                 byteArrayOutputStream.write(buffer, 0, bytesRead);
             }
             
             socket.close();
             response = byteArrayOutputStream.toString("UTF-8");
    
   } catch (UnknownHostException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   return null;
  }

  @Override
  protected void onPostExecute(Void result) {
   textResponse.setText(response);
   super.onPostExecute(result);
  }
  
 }

}


Layout

<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    <EditText 
        android:id="@+id/address"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="dstAddress" />
    <EditText 
        android:id="@+id/port"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="dstPort" />
    <Button 
        android:id="@+id/connect"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Connect..."/>
    <Button 
        android:id="@+id/clear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Clear"/>
    <TextView
        android:id="@+id/response"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>


AndroidManifest.xml have to be modified to add <uses-permission android:name="android.permission.INTERNET"/>

Learning Mobile App Development: A Hands-on Guide to Building Apps with iOS and Android

Learning Mobile App Development: A Hands-on Guide to Building Apps with iOS and Android
- The Only Tutorial Covering BOTH iOS and Android—for students and professionals alike!

 Now, one book can help you master mobile app development with both market-leading platforms: Apple’s iOS and Google’s Android. Perfect for both students and professionals, Learning Mobile App Development is the only tutorial with complete parallel coverage of both iOS and Android. With this guide, you can master either platform, or both—and gain a deeper understanding of the issues associated with developing mobile apps.
You’ll develop an actual working app on both iOS and Android, mastering the entire mobile app development lifecycle, from planning through licensing and distribution.
Each tutorial in this book has been carefully designed to support readers with widely varying backgrounds and has been extensively tested in live developer training courses. If you’re new to iOS, you’ll also find an easy, practical introduction to Objective-C, Apple’s native language.
All source code for this book, organized by chapter, is available at https://github.com/LearningMobile/BookApps
Coverage includes
  • Understanding the unique design challenges associated with mobile apps
  • Setting up your Android and iOS development environments
  • Mastering Eclipse development tools for Android and Xcode 5 tools for iOS
  • Designing interfaces and navigation schemes that leverage each platform’s power
  • Reliably integrating persistent data into your apps
  • Using lists (Android) or tables (iOS) to effectively present data to users
  • Capturing device location, displaying it, and using it in your apps
  • Accessing hardware devices and sensors
  • Publishing custom apps internally within an organization
  • Monetizing your apps on Apple’s AppStore or the Google Play marketplace, as well as other ways of profiting from app development, such as consulting and developer jobs

Creating Dynamic UI with Android Fragments

Creating Dynamic UI with Android Fragments
Leverage the power of Android fragments to develop dynamic user interfaces for your apps
Overview
  • Learn everything you need to know to provide dynamic multi-screen UIs within a single activity
  • Integrate the rich UI features demanded by today’s mobile users
  • Understand the basics of using fragments and how to use them to create more adaptive and dynamic user experiences
In Detail
To create a dynamic and multi-pane user interface on Android, you need to encapsulate UI components and activity behaviors into modules that you can swap into and out of your activities. You can create these modules with the fragment class, which behaves somewhat like a nested activity that can define its own layout and manage its own lifecycle. When a fragment specifies its own layout, it can be configured in different combinations with other fragments inside an activity to modify your layout configuration for different screen sizes (a small screen might show one fragment at a time, but a large screen can show two or more).
Creating Dynamic UI with Android Fragments shows you how to create modern Android applications that meet the high expectations of today’s users. You will learn how to incorporate rich navigation features like swipe-based screen browsing and how to create adaptive UIs that ensure your application looks fantastic whether run on a low cost smartphone or the latest tablet.
This book looks at the impact fragments have on Android UI design and their role in both simplifying many common UI challenges and providing new ways to incorporate rich UI behaviors.
You will learn how to use fragments to create UIs that automatically adapt to device differences. We look closely at the roll of fragment transactions and how to work with the Android back stack. Leveraging this understanding, we then explore several specialized fragment-related classes like ListFragment and DialogFragment as well as rich navigation features like swipe-based screen browsing.
What you will learn from this book
  • Understand the role and capabilities of fragments
  • Explore the fragment-oriented features of Android Studio
  • Create an app UI that works effectively on smartphones and tablets
  • Use fragments to create engaging navigation capabilities like swipe-based screen browsing
  • Work with special purpose fragment classes like ListFragment and DialogFragment
  • Dynamically manage fragments using the FragmentTransaction class
  • Learn appropriate application design for communicating between fragments
  • Efficiently handle fragment creation and lifecycle
  • Simplify cross-thread UI handling with fragments
  • Form multi-screen UIs that run within a single activity
Approach
A fast-paced tutorial that guides you through everything you need to know about dynamic UI design for Android devices.
Who this book is written for

This book is for developers with a basic understanding of Android programming who would like to improve the appearance and usability of their applications. Whether you’re looking to create a more interactive user experience, create more dynamically adaptive UIs, provide better support for tablets and smartphones in a single app, reduce the complexity of managing your app UIs, or you are just trying to expand your UI design philosophy, then this book is for you.

Android Security Cookbook

Android Security Cookbook
Practical recipes to delve into Android's security mechanisms by troubleshooting common vulnerabilities in applications and Android OS versions
Overview
  • Analyze the security of Android applications and devices, and exploit common vulnerabilities in applications and Android operating systems
  • Develop custom vulnerability assessment tools using the Drozer Android Security Assessment Framework
  • Reverse-engineer Android applications for security vulnerabilities
  • Protect your Android application with up to date hardening techniques
In Detail
Android Security Cookbook discusses many common vulnerabilities and security related shortcomings in Android applications and operating systems. The book breaks down and enumerates the processes used to exploit and remediate these vulnerabilities in the form of detailed recipes and walkthroughs.
The book also teaches readers to use an Android Security Assessment Framework called Drozer and how to develop plugins to customize the framework.
Other topics covered include how to reverse-engineer Android applications to find common vulnerabilities, and how to find common memory corruption vulnerabilities on ARM devices. In terms of application protection this book will show various hardening techniques to protect application components, the data stored, secure networking. In summary, Android Security Cookbook provides a practical analysis into many areas of Android application and operating system security and gives the
What you will learn from this book
  • Set up the Android development tools and frameworks
  • Engage in Application security concepts
  • Use the Drozer Android Security Assessment Framework
  • Customize and develop your own plugins for the Drozer Framework
  • Exploit, enumerate, and analyze common application level exploits
  • Protect applications from common vulnerabilities and exploits
  • Reverse-engineer applications for common code level vulnerabilities
  • Secure application networking, SSL/TLS
  • Encryption to protect application data
Approach
"Android Security Cookbook' breaks down and enumerates the processes used to exploit and remediate Android app security vulnerabilities in the form of detailed recipes and walkthroughs.
Who this book is written for

"Android Security Cookbook" is aimed at anyone who is curious about Android app security and wants to be able to take the necessary practical measures to protect themselves; this means that Android application developers, security researchers and analysts, penetration testers, and generally any CIO, CTO, or IT managers facing the impeding onslaught of mobile devices in the business environment will benefit from reading this book.

VelocityTracker, track the velocity of touch events

It's a example of using Android's VelocityTracker. It's a helper for tracking the velocity of touch events, for implementing flinging and other such gestures. Use obtain() to retrieve a new instance of the class when you are going to begin tracking. Put the motion events you receive into it with addMovement(MotionEvent). When you want to determine the velocity call computeCurrentVelocity(int) and then call getXVelocity(int) and getYVelocity(int) to retrieve the velocity for each pointer id.



VelocityTracker
Example of using Android's VelocityTracker


package com.example.androidvelocitytracker;

import android.os.Bundle;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

 TextView textAvtion, textVelocityX, textVelocityY, 
  textMaxVelocityX, textMaxVelocityY;
 VelocityTracker velocityTracker = null;
 
 float maxXVelocity;
 float maxYVelocity;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  textAvtion = (TextView) findViewById(R.id.action);
  textVelocityX = (TextView) findViewById(R.id.velocityx);
  textVelocityY = (TextView) findViewById(R.id.velocityy);
  textMaxVelocityX = (TextView) findViewById(R.id.maxvelocityx);
  textMaxVelocityY = (TextView) findViewById(R.id.maxvelocityy);
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  
  int action = event.getActionMasked();

  switch (action) {
  case MotionEvent.ACTION_DOWN:
   if (velocityTracker == null) {
    velocityTracker = VelocityTracker.obtain();
   } else {
    velocityTracker.clear();
   }
   velocityTracker.addMovement(event);
   maxXVelocity = 0; 
   maxYVelocity = 0;
   
   textVelocityX.setText("X-velocity (pixel/s): 0");
   textVelocityY.setText("Y-velocity (pixel/s): 0");
   textMaxVelocityX.setText("max. X-velocity: 0");
   textMaxVelocityY.setText("max. Y-velocity: 0");
   
   break;
  case MotionEvent.ACTION_MOVE:
   velocityTracker.addMovement(event);
   velocityTracker.computeCurrentVelocity(1000); 
   //1000 provides pixels per second
   
   float xVelocity = velocityTracker.getXVelocity();
   float yVelocity = velocityTracker.getYVelocity();
   
   if(xVelocity > maxXVelocity){
    //max in right side
    maxXVelocity = xVelocity;
   }
   
   if(yVelocity > maxYVelocity){
    //Max in down side
    maxYVelocity = yVelocity;
   }
   
   textVelocityX.setText("X-velocity (pixel/s): " + xVelocity);
   textVelocityY.setText("Y-velocity (pixel/s): " + yVelocity);
   textMaxVelocityX.setText("max. X-velocity: " + maxXVelocity);
   textMaxVelocityY.setText("max. Y-velocity: " + maxYVelocity);

   break;
  case MotionEvent.ACTION_UP:
  case MotionEvent.ACTION_CANCEL:
   velocityTracker.recycle();
   break;
  }

  return true;
 }

}


<LinearLayout 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:orientation="vertical"
    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:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/action"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/velocityx"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/maxvelocityx"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/velocityy"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/maxvelocityy"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

Get the Android version of device

The static final int Build.VERSION.SDK_INT store user-visible SDK version of the framework; its possible values are defined in Build.VERSION_CODES.

This exercise use Android's SparseArrays to store SDK_INT-Build.VERSION_CODES pairs. SparseArrays map integers to Objects. Unlike a normal array of Objects, there can be gaps in the indices. It is intended to be more memory efficient than using a HashMap to map Integers to Objects, both because it avoids auto-boxing keys and its data structure doesn't rely on an extra entry object for each mapping.



Get the Android version of device
Get the Android version of device


package com.example.androidversion;

import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.util.SparseArray;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

 static SparseArray<String> arrayVC = new SparseArray<String>();
    static {
        arrayVC.append(VERSION_CODES.BASE, "The original, first, version of Android.");
        arrayVC.append(VERSION_CODES.BASE_1_1, "First Android update, officially called 1.1");
        arrayVC.append(VERSION_CODES.CUPCAKE, "Android 1.5");
        arrayVC.append(VERSION_CODES.CUR_DEVELOPMENT, "Magic version number...");
        arrayVC.append(VERSION_CODES.DONUT, "Android 1.6");
        arrayVC.append(VERSION_CODES.ECLAIR, "Android 2.0");
        arrayVC.append(VERSION_CODES.ECLAIR_0_1, "Android 2.0.1");
        arrayVC.append(VERSION_CODES.ECLAIR_MR1, "Android 2.1");
        arrayVC.append(VERSION_CODES.FROYO, "Android 2.2");
        arrayVC.append(VERSION_CODES.GINGERBREAD,"Android 2.3");
        arrayVC.append(VERSION_CODES.GINGERBREAD_MR1, "Android 2.3.3");
        arrayVC.append(VERSION_CODES.HONEYCOMB, "Android 3.0");
        arrayVC.append(VERSION_CODES.HONEYCOMB_MR1, "Android 3.1");
        arrayVC.append(VERSION_CODES.HONEYCOMB_MR2, "Android 3.2");
        arrayVC.append(VERSION_CODES.ICE_CREAM_SANDWICH,"Android 4.0");
        arrayVC.append(VERSION_CODES.ICE_CREAM_SANDWICH_MR1,"Android 4.0.3");
        arrayVC.append(VERSION_CODES.JELLY_BEAN, "Android 4.1");
        arrayVC.append(VERSION_CODES.JELLY_BEAN_MR1, "Android 4.2");
        arrayVC.append(VERSION_CODES.JELLY_BEAN_MR2, "Android 4.3");
        arrayVC.append(VERSION_CODES.KITKAT, "Android 4.4");
    }

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  //setContentView(R.layout.activity_main);
  
  TextView textView = new TextView(this);
  setContentView(textView);
  
  int version = Build.VERSION.SDK_INT;
  String BuildVersion = arrayVC.get(version, "unknown");
  
  textView.setText(BuildVersion);
 }

}

VelocityTracker and VelocityTrackerCompat

The post "VelocityTracker, track the velocity of touch events" for one touch point tracking using VelocityTracker. Together with android.support.v4.view.VelocityTrackerCompat (Helper for accessing features in VelocityTracker introduced after API level 4 in a backwards compatible fashion), we can track velocity for multi-touch tracking on post-HONEYCOMB device.






package com.example.androidvelocitytracker;

import android.os.Build;
import android.os.Bundle;
import android.os.Build.VERSION_CODES;
import android.support.v4.view.VelocityTrackerCompat;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

 TextView textAvtion, textVelocityX0, textVelocityY0,
  textVelocityX1, textVelocityY1;
 TextView textVersion;
 VelocityTracker velocityTracker = null;
 
 static SparseArray<String> arrayVC = new SparseArray<String>();
    static {
        arrayVC.append(VERSION_CODES.BASE, "The original, first, version of Android.");
        arrayVC.append(VERSION_CODES.BASE_1_1, "First Android update, officially called 1.1");
        arrayVC.append(VERSION_CODES.CUPCAKE, "Android 1.5");
        arrayVC.append(VERSION_CODES.CUR_DEVELOPMENT, "Magic version number...");
        arrayVC.append(VERSION_CODES.DONUT, "Android 1.6");
        arrayVC.append(VERSION_CODES.ECLAIR, "Android 2.0");
        arrayVC.append(VERSION_CODES.ECLAIR_0_1, "Android 2.0.1");
        arrayVC.append(VERSION_CODES.ECLAIR_MR1, "Android 2.1");
        arrayVC.append(VERSION_CODES.FROYO, "Android 2.2");
        arrayVC.append(VERSION_CODES.GINGERBREAD,"Android 2.3");
        arrayVC.append(VERSION_CODES.GINGERBREAD_MR1, "Android 2.3.3");
        arrayVC.append(VERSION_CODES.HONEYCOMB, "Android 3.0");
        arrayVC.append(VERSION_CODES.HONEYCOMB_MR1, "Android 3.1");
        arrayVC.append(VERSION_CODES.HONEYCOMB_MR2, "Android 3.2");
        arrayVC.append(VERSION_CODES.ICE_CREAM_SANDWICH,"Android 4.0");
        arrayVC.append(VERSION_CODES.ICE_CREAM_SANDWICH_MR1,"Android 4.0.3");
        arrayVC.append(VERSION_CODES.JELLY_BEAN, "Android 4.1");
        arrayVC.append(VERSION_CODES.JELLY_BEAN_MR1, "Android 4.2");
        arrayVC.append(VERSION_CODES.JELLY_BEAN_MR2, "Android 4.3");
        arrayVC.append(VERSION_CODES.KITKAT, "Android 4.4");
    }

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  textAvtion = (TextView) findViewById(R.id.action);
  textVelocityX0 = (TextView) findViewById(R.id.velocityx0);
  textVelocityY0 = (TextView) findViewById(R.id.velocityy0);
  textVelocityX1 = (TextView) findViewById(R.id.velocityx1);
  textVelocityY1 = (TextView) findViewById(R.id.velocityy1);
  
  textVersion = (TextView)findViewById(R.id.version);
  int version = Build.VERSION.SDK_INT;
  String BuildVersion = arrayVC.get(version, "unknown");
  textVersion.setText(BuildVersion);
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  
  int action = event.getActionMasked();
  int index = event.getActionIndex();
        int pointerId = event.getPointerId(index);

  switch (action) {
  case MotionEvent.ACTION_DOWN:
   if (velocityTracker == null) {
    velocityTracker = VelocityTracker.obtain();
   } else {
    velocityTracker.clear();
   }
   velocityTracker.addMovement(event);
   
   if(pointerId == 0){
    textVelocityX0.setText("X-velocity (pixel/s): 0");
    textVelocityY0.setText("Y-velocity (pixel/s): 0");
   }else if(pointerId == 1){
    textVelocityX1.setText("X-velocity (pixel/s): 0");
    textVelocityY1.setText("Y-velocity (pixel/s): 0");
   }
   
   break;
  case MotionEvent.ACTION_MOVE:
   velocityTracker.addMovement(event);
   velocityTracker.computeCurrentVelocity(1000); 
   //1000 provides pixels per second
   
   float xVelocity = VelocityTrackerCompat.getXVelocity(
     velocityTracker, pointerId);
   
   float yVelocity = VelocityTrackerCompat.getYVelocity(
     velocityTracker, pointerId);
   
   if(pointerId == 0){
    textVelocityX0.setText("X-velocity (pixel/s): " + xVelocity);
    textVelocityY0.setText("Y-velocity (pixel/s): " + yVelocity);
   }else if(pointerId == 1){
    textVelocityX1.setText("X-velocity (pixel/s): " + xVelocity);
    textVelocityY1.setText("Y-velocity (pixel/s): " + yVelocity);
   }
   
   break;
  case MotionEvent.ACTION_UP:
  case MotionEvent.ACTION_CANCEL:
   velocityTracker.recycle();
   break;
  }

  return true;
 }

}


<LinearLayout 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:orientation="vertical"
    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:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    
    <TextView
        android:id="@+id/version"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/action"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

 <TextView
        android:text="pointer 0"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/velocityx0"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/velocityy0"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
 <TextView
        android:text="pointer 1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/velocityx1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/velocityy1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>