Search This Blog

Sunday, 30 December 2012

End of year 2012 , A new beginning and challenge for mobile world

2012 ends on high note. So many ups and downs for market player in mobile industry. Some went down and some on rise in market. While iPhone seems loosing its plot in sales of smartphone but its remains highest benefit for developer. Android is growing at horse pace and steadily replacing iPhone monopoly in smartphone market. Lets discuss some key features in 2012 in terms of mobile market share, innovation and coming hopes

Android increasing its market share, iPhone still in competition

Android market size is increasing at horse pace. Not only its application are increasing even android phone are selling four times than iPhone. After four android device, one iPhone sells now. Two tiger remains in battles in form of android and iPhone. Blackberry goes on down. Now every one is waiting for Blackberry's new invention blackberry 10. They have launch beta version. Its make some chances for blackberry to come back in market. And windows phone experiment of Microsoft seems to be failed even though having best User interface

New invention and ambitious project

Android start in Tablet market and start capturing market. Amazon kindle fire, Micro-max, Samsung and many other starts making tablet on very low price. Apple start iPad mini. Rather being successful, iPad mini does not being so successful.
 iPad mini face huge competition from android low price tablet. Samsung ambitious project Samsung S3, Galaxy note was ruling the party in smart phone in 2012. Samsung Galaxy camera is a new innovation at ending of 2012 and smart watch also join the kitty

Development front expanded for developer

Cross platform development gave a new way to developer to bring their skills to next level. Using common tools for android, iOS, Blackberry makes user life easy. Its reduce the cost and effort. Using Phone Gap and other cross platform does not looks good compare to native application. But most application work well with them. Blackberry 10 support for android application gives a chance to increase our application exposure.


Sunday, 16 December 2012

Swipe screen navigation using Fragment and View pager in android application

Swiping screens in android application gives a interactive look to application. Using activity its quite difficult as it need some animations. But solution is to use Viewpager (it has default behavior of swipe left right). In ViewPager, attach fragment and its done.

Requirement of this tutorial will be

And Result will be like this video



Let move into depth, This result contain few steps to achieve it

Step 1) Make one fragment activity. This activity xml should contain one ViewPager. Using FragmentPagerAdapter we will add all fragment inside a ViewPager


 package com.horizontalscrollviewwithpageindicator;

import java.util.Vector;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.widget.Toast;

import com.fragmentadapter.FragmentAdapter;
import com.fragmentclass.FragmentOne;
import com.fragmentclass.FragmentThree;
import com.fragmentclass.FragmentTwo;

public class FragmentMainActivity extends FragmentActivity {
 @Override
 protected void onCreate(Bundle arg0) {
  super.onCreate(arg0);
  setContentView(R.layout.activity_main);
  Vector<Fragment> fragments = new Vector<Fragment>();
  FragmentOne fragmentOne = new FragmentOne();
  Bundle bundle = new Bundle();
  bundle.putString(
    "url",
    "https://lh6.googleusercontent.com/-jZgveEqb6pg/"
      + "T3R4kXScycI/AAAAAAAAAE0/xQ7CvpfXDzc/s1024/sample_image_01.jpg");
  fragmentOne.setArguments(bundle);
  fragments.add(fragmentOne);

  FragmentTwo fragmenttwo = new FragmentTwo();
  bundle.putString(
    "url",
    "https://lh3.googleusercontent.com/"
      + "-WujkdYfcyZ8/T3R4qrIMGUI/AAAAAAAAAGk/277LIdgvnjg/s1024/sample_image_15.jpg");
  fragmenttwo.setArguments(bundle);
  fragments.add(fragmenttwo);

  FragmentThree fragmenthree = new FragmentThree();
  fragmenthree.setArguments(bundle);
  fragments.add(fragmenthree);

  ViewPager myPager = (ViewPager) findViewById(R.id.myfivepanelpager);
  FragmentAdapter adapter = new FragmentAdapter(
    getSupportFragmentManager(), fragments);
  myPager.setAdapter(adapter);
  myPager.setCurrentItem(0);

  myPager.setOnPageChangeListener(new OnPageChangeListener() {

   @Override
   public void onPageSelected(int arg0) {
    Toast.makeText(FragmentMainActivity.this,
      "Page Selected " + arg0, Toast.LENGTH_LONG).show();
   }

   @Override
   public void onPageScrolled(int arg0, float arg1, int arg2) {
   }

   @Override
   public void onPageScrollStateChanged(int arg0) {
   }
  });
 }
}

Step 2) Create one FragementPagerAdapter to add data (say Fragment here) to swipe this

package com.fragmentadapter;

import java.util.Vector;

import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.View;
import android.view.ViewGroup;

public class FragmentAdapter extends FragmentPagerAdapter {

 FragmentManager mManager;
 Vector<Fragment> localFragmentArray;

 public FragmentAdapter(FragmentManager fm, Vector<Fragment> loadFragment) {
  super(fm);
  localFragmentArray = loadFragment;
  mManager = fm;
 }

 @Override
 public Fragment getItem(int arg0) {
  return localFragmentArray.get(arg0);
 }

 @Override
 public int getCount() {
  return localFragmentArray.size();
 }

 @Override
 public void destroyItem(ViewGroup container, int position, Object object) {
  this.notifyDataSetChanged();
 }

 @Override
 public Object instantiateItem(ViewGroup container, int position) {
  return super.instantiateItem(container, position);
 }

 @Override
 public boolean isViewFromObject(View arg0, Object arg1) {
  return super.isViewFromObject(arg0, arg1);
 }

 @Override
 public Parcelable saveState() {
  return super.saveState();
 }

}

Step 3) Create some Fragment Class and add these inside Apdater. Download the code and see how i have added Fragment inside ViewPager


Download Code

Saturday, 15 December 2012

Custom Loader : Loading data using Loader Manager in android asynchronously

Loader is useful while maintaining life cycle of activity and avoiding performing big task again and again. Loader provide a way to keep old data while changing orientation. Every loader has its own unique ID and its created only once. Next time it will use the previous instance.

Loader is discussed at various place but creating your own custom loader is the topic remains to discuss. Let take one case where loader is useful in android

  Suppose application download data from network and show inside a list. suddenly user change phone orientation. Data will start downloading again. To avoid this case, Loader are right thing to use

Loader life cycle include three method

  • public Loader<DataHandler> onCreateLoader(int arg0, Bundle arg1) , called when loader initialize once only
  • public void onLoadFinished(Loader<DataHandler> arg0, DataHandler arg1) every time when applciation interact with Loader. And return data

Note: Here DataHandler is application custom class

  • public void onLoaderReset(Loader<DataHandler> arg0)  to change UI and remove previous view

Now this article will include steps and description to create its own custom loader . It had one list fragment. And after download data using AsyncTaskLoader<DataHandler>, we shows data inside List Fragment

1) One fragment activity is base activity that include on list fragment inside main frame layout
2) Now create List Fragment and initialize the Loader with Loader manager like         

 getActivity().getSupportLoaderManager().initLoader(10, null, this). 

Loader manager has three argument Loader _ID, Bundle data and LoaderManager.LoaderCallbacks<DataHandler>. Now it will force you to override required method of       Loader Manager callback

First will be create loader, here we start one Asynchronous Loader to load data. 


  @Override
public Loader<DataHandler> onCreateLoader(int arg0, Bundle arg1) {
AsynChro asynChro = new AsynChro(ListFragmentExp.this.getActivity());
asynChro.forceLoad();
return asynChro;
}

Loader reset call everytime it interact with loader

@Override
public void onLoaderReset(Loader<DataHandler> arg0) {
mlisListView.setAdapter(null);
}

Loader loaded then it call this method , return with data everytime once it downloaded


       @Override
public void onLoadFinished(Loader<DataHandler> arg0, DataHandler arg1) {
mlisListView.setAdapter(new DataBinder(getActivity(), arg1.getData()));
setListShown(true);
}

3) Once we downloaded data, we just have traditional way to set it inside List Fragment using BaseAdapter

                                   

  

These above images show how loader maintain life cycle of data when you change your orientation . LoaderManager can return any kind of data. Here i have my custom class DataHolder and i am returning data as DataHolder

So Lets go step by step with loader in coding

Activity Class for initiation


package com.loader;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.widget.FrameLayout;

public class MainActivity extends FragmentActivity{
    FragmentTransaction mTFragmentTransaction;
    FragmentManager mManFragmentManager;
    ListFragmentExp mListFragment;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListFragment = new ListFragmentExp();
        FrameLayout cursor = (FrameLayout) findViewById(R.id.listFragment);
        mManFragmentManager = getSupportFragmentManager();

        if (mManFragmentManager.findFragmentByTag("Tag") == null) {
            mTFragmentTransaction = mManFragmentManager.beginTransaction();
            mTFragmentTransaction.add(cursor.getId(), mListFragment, "Tag");
            mTFragmentTransaction.commit();
        }
    }
}


A List Fragment loading data using LoaderManager and displaying


package com.loader;

import java.util.ArrayList;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;

public class ListFragmentExp extends ListFragment implements
        LoaderManager.LoaderCallbacks<DataHandler> {

    // This is the Adapter being used to display the list's data.
    BaseAdapter mAdapter;
    public static ListView mlisListView;
    // If non-null, this is the current filter the user has provided.
    String mCurFilter;

    public static FragmentActivity mAcFragmentActivity;

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mAcFragmentActivity = getActivity();
        // Give some text to display if there is no data. In a real
        // application this would come from a resource.
        setEmptyText("No phone numbers");

        // Create an empty adapter we will use to display the loaded data.
        setListAdapter(mAdapter);

        // Start out with a progress indicator.
        setListShown(false);
        mlisListView = getListView();
        getActivity().getSupportLoaderManager().initLoader(10, null, this);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public Loader<DataHandler> onCreateLoader(int arg0, Bundle arg1) {
        AsynChro asynChro = new AsynChro(ListFragmentExp.this.getActivity());
        asynChro.forceLoad();
        return asynChro;
    }

    @Override
    public void onLoadFinished(Loader<DataHandler> arg0, DataHandler arg1) {
        mlisListView.setAdapter(new DataBinder(getActivity(), arg1.getData()));
        setListShown(true);
    }

    @Override
    public void onLoaderReset(Loader<DataHandler> arg0) {
        mlisListView.setAdapter(null);
    }

    public static class AsynChro extends AsyncTaskLoader<DataHandler> {

        DataHandler mHaDataHandler;

        public AsynChro(Context context) {
            super(context);
            mHaDataHandler = new DataHandler();
        }

        @Override
        public DataHandler loadInBackground() {
            ArrayList<String> temp = new ArrayList<String>();
            for (int i = 0; i < 100; i++) {
                temp.add("Counting-----" + i);
            }
            try {
                synchronized (this) {
                    wait(5000);
                }
            } catch (Exception e) {
                e.getMessage();
            }
            mHaDataHandler.setData(temp);
            return mHaDataHandler;
        }

        @Override
        public void deliverResult(DataHandler data) {
            super.deliverResult(data);
            mlisListView.setAdapter(new DataBinder(mAcFragmentActivity, data
                    .getData()));
        }
    }

}


And finally one object to save data. I make DataHandler class to save data


package com.loader;

import java.util.ArrayList;

public class DataHandler {

    ArrayList<String> mListStrings = new ArrayList<String>();

    public void setData(ArrayList<String> temp) {
        mListStrings = temp;
    }

    public ArrayList<String> getData() {
        return mListStrings;
    }
}
Now Binding all data inside a List Fragment using BaseAdapter


package com.loader;

import java.util.ArrayList;

import android.graphics.Color;
import android.support.v4.app.FragmentActivity;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class DataBinder extends BaseAdapter {
    ArrayList<String> mLisArrayList;

    FragmentActivity mAtcFragmentActivity;

    public DataBinder(FragmentActivity mActivity, ArrayList<String> mList) {
        mLisArrayList = mList;
        mAtcFragmentActivity = mActivity;
    }

    @Override
    public int getCount() {
        return mLisArrayList.size();
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        TextView mTextView;
        if (convertView == null) {
            mTextView = new TextView(mAtcFragmentActivity);

            mTextView.setLayoutParams(new ListView.LayoutParams(
                    LayoutParams.FILL_PARENT, 60));
            mTextView.setGravity(Gravity.CENTER_HORIZONTAL
                    | Gravity.CENTER_VERTICAL);
            mTextView.setTextSize(20);
            mTextView.setBackgroundColor(Color.GRAY);
            mTextView.setTextColor(Color.GREEN);
            convertView = mTextView;
        } else {
            mTextView = (TextView) convertView;
        }
        mTextView.setText(mLisArrayList.get(position));
        return convertView;
    }
}

Feel free to download code

Download Source Code

Monday, 3 December 2012

Android game development : Moving or scrolling background


In game development in android, before we go further let have a look what we had achieved

    1) Basic science of game programming
    2) Creating surface to draw
    3) Creating dynamic object on surface and moving them

But in general , every game does not move their character much . They moves their background. But when a person plays, its seems everything is moving around. In android we draw an background with one bitmap.  And we start slowly moving background. This is important part game development.

Suppose one's want to develop a game in which, one's have one actor who's running all the way. Then real game scenerio will be like that

  • Animate actor on same place
  • Move the background in opposite direction

Moving background is quite simple, we scroll one image to some position and same image's another instance to respective direction to cover the space left by first one. and so on.......
This process need same image to draw continueously two times to fill the gap and never ending scrolling or moving of background

Look at the respective code in which backGround bitmap is background of canvas.....

 /**
  * Draws current state of the game Canvas.
  */
 private int mBGFarMoveX = 0;
 private int mBGNearMoveX = 0;

 private void doDrawRunning(Canvas canvas) {
  // decrement the far background
  mBGFarMoveX = mBGFarMoveX - 1;
  // decrement the near background
  mBGNearMoveX = mBGNearMoveX - 4;
  // calculate the wrap factor for matching image draw
  int newFarX = backGround.getWidth() - (-mBGFarMoveX);
  // if we have scrolled all the way, reset to start
  if (newFarX <= 0) {
   mBGFarMoveX = 0;
   // only need one draw
   canvas.drawBitmap(backGround, mBGFarMoveX, 0, null);
  } else {
   // need to draw original and wrap
   canvas.drawBitmap(backGround, mBGFarMoveX, 0, null);
   canvas.drawBitmap(backGround, newFarX, 0, null);
  }
  }


                 

Download Source

Saturday, 1 December 2012

Video recording application in android

We can take video from android default intent also but customization becomes impossible as it has its own limitation. So we need to make our own camera application in android to capture video. It will work as camcorder also. Making camera application in android , is bit complicated task if we do not understand it step by step

It need these three thing


  • SurfaceView to give one platform to show material
  • Camera to show material on surface provided by surfaceview
  • And a media recorder to record the video provided by camera and surface view

So let make one layout, which have one surfaceview class inside it and start with surfaceview


  • surfaceview called surfaceCreated(SurfaceHolder arg0) very first time. So we need to open camera here. Handle the case where camera is not able to work properly
 @Override
 public void surfaceCreated(SurfaceHolder arg0) {
  camera = openFrontFacingCamera();
  if (camera != null) {
   try {
    camera.setPreviewDisplay(holder);
   } catch (IOException e) {
    camera.release();
    camera = null;
   }
  } else {
   Toast.makeText(act, "Problem in opening Camera.", Toast.LENGTH_LONG)
     .show();
   act.finish();
  }
 }

  • Now camera is ready. Once surfaceChanged(SurfaceHolder arg0, int format, int height,int width), we will instantiate the MediaRecorder and attach all thing to capture video properly. It important to remember that camera attribute is need to be set in a order but their value may differ

 @Override
 public void surfaceChanged(SurfaceHolder arg0, int format, int height,
   int width) {
  Camera.Size previewSize = null;
  try {
   Camera.Parameters parameters = camera.getParameters();
   List<Camera.Size> supportSize = parameters
     .getSupportedPreviewSizes();
   if (supportSize != null) {
    previewSize = getOptimalPreviewSize(supportSize, width, height);
   }
   parameters.setPreviewSize(previewSize.width, previewSize.height);
   parameters.set("orientation", "portrait");
   camera.setPreviewDisplay(arg0);
   camera.setParameters(parameters);
   camera.startPreview();
   camera.unlock();
   m_recorder.setPreviewDisplay(arg0.getSurface());
   m_recorder.setCamera(camera);
   m_recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
   m_recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
   m_recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
   m_recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
   m_recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
   m_recorder.setMaxDuration(90000);
   m_recorder.setOnInfoListener(oninfoLis);
   m_recorder.setVideoSize(previewSize.width, previewSize.height);
   m_recorder.setVideoFrameRate(30);

   m_recorder.setVideoEncodingBitRate(500);
   m_recorder.setAudioEncodingBitRate(128);
   m_recorder.setOutputFile("/mnt/sdcard/myfile"
     + SystemClock.elapsedRealtime() + ".mp4");
   m_recorder.prepare();
   m_recorder.start();
  } catch (IllegalStateException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  } catch (Exception e) {
   e.getMessage();
  }
 } 
  • But most important is to get optimal preview display to camera. For one device there may be more than one preview display so we need use best among them to capture good quality video


         private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
  final double ASPECT_TOLERANCE = 0.1;
  double targetRatio = (double) w / h;
  if (sizes == null)
   return null;
  Size optimalSize = null;
  double minDiff = Double.MAX_VALUE;
  int targetHeight = h;
  for (Size size : sizes) {
   double ratio = (double) size.width / size.height;
   if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
    continue;
   if (Math.abs(size.height - targetHeight) < minDiff) {
    optimalSize = size;
    minDiff = Math.abs(size.height - targetHeight);
   }
  }
  if (optimalSize == null) {
   minDiff = Double.MAX_VALUE;
   for (Size size : sizes) {
    if (Math.abs(size.height - targetHeight) < minDiff) {
     optimalSize = size;
     minDiff = Math.abs(size.height - targetHeight);
    }
   }
  }
  return optimalSize;
 }

So this article shows how to capture video with out default intent. Video quality may vary according to device resolution. and you need to set Video Frame Rate according to you device type. I have found this limit on android developer site



SD (Low quality)SD (High quality)HD (Not available on all devices)
Video codecH.264 Baseline ProfileH.264 Baseline ProfileH.264 Baseline Profile
Video resolution176 x 144 px480 x 360 px1280 x 720 px
Video frame rate12 fps30 fps30 fps
Video bitrate56 Kbps500 Kbps2 Mbps
Audio codecAAC-LCAAC-LCAAC-LC
Audio channels1 (mono)2 (stereo)2 (stereo)
Audio bitrate24 Kbps128 Kbps192 Kbps

 Download Source Code

Android News and source code