Service Tutorial in android Part-II


Continued from service tutorial-I…,

3. Service using Messenger:

Now i am going to explain Working with messengers in service:

If you need to be able to write a Service that can perform complicated communication with clients in remote processes (beyond simply the use of Context.startService to send commands to it), then you can use the Messenger class instead of writing full AIDL files.

An example of a Service that uses Messenger as its client interface is shown here. First is the Service itself, publishing a Messenger to an internal Handler when bound:


public class MessengerService extends Service {
 /** Command to the service to display a message */
 static final int MSG_SAY_HELLO = 1;

/**
 * Handler of incoming messages from clients.
 */
 class IncomingHandler extends Handler {
 @Override
 public void handleMessage(Message msg) {
 switch (msg.what) {
 case MSG_SAY_HELLO:
 Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
 break;
 default:
 super.handleMessage(msg);
 }
 }
 }

/**
 * Target we publish for clients to send messages to IncomingHandler.
 */
 final Messenger mMessenger = new Messenger(new IncomingHandler());

/**
 * When binding to the service, we return an interface to our messenger
 * for sending messages to the service.
 */
 @Override
 public IBinder onBind(Intent intent) {
 Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
 return mMessenger.getBinder();
 }
 }

—————————————————————————————————
If we want to make this service run in a remote process (instead of the standard one for its .apk), we can use android:process in its manifest tag to specify one:

<service android:name=”MessengerService”
android:process=”:remote” />

Note that the name “remote” chosen here is arbitrary, and you can use other names if you want additional processes. The ‘:’ prefix appends the name to your package’s standard process name.

With that done, clients can now bind to the service and send messages to it. Note that this allows clients to register with it to receive messages back as well:


public class ServiceUsingMessangerActivity extends Activity {
 /** Messenger for communicating with the service. */
 Messenger mService = null;

/** Flag indicating whether we have called bind on the service. */
 boolean mBound;

/**
 * Class for interacting with the main interface of the service.
 */
 private ServiceConnection mConnection = new ServiceConnection() {
 public void onServiceConnected(ComponentName className, IBinder service) {
 // This is called when the connection with the service has been
 // established, giving us the object we can use to
 // interact with the service. We are communicating with the
 // service using a Messenger, so here we get a client-side
 // representation of that from the raw IBinder object.
 mService = new Messenger(service);
 mBound = true;
 }

public void onServiceDisconnected(ComponentName className) {
 // This is called when the connection with the service has been
 // unexpectedly disconnected -- that is, its process crashed.
 mService = null;
 mBound = false;
 }
 };

public void sayHello(View v) {
 if (!mBound) return;
 // Create and send a message to the service, using a supported 'what' value
 Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
 try {
 mService.send(msg);
 } catch (RemoteException e) {
 e.printStackTrace();
 }
 }

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

@Override
 protected void onStart() {
 super.onStart();
 // Bind to the service
 bindService(new Intent(this, MessengerService.class), mConnection,Context.BIND_AUTO_CREATE);
 }

@Override
 protected void onStop() {
 super.onStop();
 // Unbind from the service
 if (mBound) {
 unbindService(mConnection);
 mBound = false;
 }
 }
 }

4. Service using Remote AIDL files:

Each application in Android runs in its own process. An application cannot directly access another application’s memory space. This is called application sand-boxing.

In order to allow cross-application communication, Android provides an implementation of interprocess communication (IPC) protocol. IPC protocols tend to get complicated because of all the marshaling/un marshaling of data that is necessary.

To help with this, Android provides Android Interface Definition Language, or AIDL. It is a lightweight implementation of IPC using a syntax that is very familiar to Java developers, and a tool that automates the stub creation.

In order to allow for one application to call into another, we typically have to:

1. Define the AIDL interface:

AIDL interface looks like a general java interface.By default,AIDL supports the following data types:

-> All primitive types in java (such as int,long,char,boolean)

2. Implement the interface:

3. Expose the interface to clients.

IMyInterface.aidl:

package com.ramesh.services.aidl.demo;

interface IMyInterface
{
 void setUserName(in String name);
 String getName();
}

ServiceUsingAidl.java:

public class ServiceUsingAidl extends Service {

private String userName;

@Override
 public IBinder onBind(Intent intent) {
 return mBinder;
 }

private IMyInterface.Stub mBinder = new IMyInterface.Stub() {

@Override
 public void setUserName(String name) throws RemoteException {

userName = name;
 }

@Override
 public String getName() throws RemoteException {
 return userName;
 }
 };
}

AidlDemo.java:


public class AidlDemo extends Activity {

public static final String TAG = "Aidl Demo";
 private IMyInterface mService;

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

Intent serviceIntent = new Intent(this, ServiceUsingAidl.class);
 bindService(serviceIntent, conn, Service.BIND_AUTO_CREATE);

Button btn = (Button) findViewById(R.id.button1);
 btn.setOnClickListener(setNameListener);

Button btn2 = (Button) findViewById(R.id.button1);
 btn2.setOnClickListener(getNameListener);

}

private ServiceConnection conn = new ServiceConnection() {

@Override
 public void onServiceDisconnected(ComponentName name) {
 Log.i(TAG, "Service disconnected.");
 }

@Override
 public void onServiceConnected(ComponentName name, IBinder service) {
 Log.i(TAG, "Service connected.");
 mService = (IMyInterface) service;
 }
 };

private OnClickListener setNameListener = new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 if (mService != null) {
 try {
 mService.setUserName("Andorid world");
 } catch (RemoteException e) {
 e.printStackTrace();
 }
 }
 }
 };
 private OnClickListener getNameListener = new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 if (mService != null) {
 try {
 String str = mService.getName();
 Toast.makeText(AidlDemo.this, str, Toast.LENGTH_SHORT)
 .show();
 } catch (RemoteException e) {
 e.printStackTrace();
 }
 }
 }
 };
}

In manifest, we add service like a simple service.

5. IntentService:

While the base class for creating a Service is the Service class you can also implement IntentService. The IntentService is used to perform a certain task in the background. Once done, the instance of IntentService terminate itself automatically. Examples for its usage would be to download a certain resources from the Internet. The IntentService class offers the onHandleIntent() method which will be asynchronously called by the Android system.

                                           It is advisable to use thread/asynTask or Service to handle long running task such as file I/O, internet access etc. IntentService is simple, easy to use and take care of many hectic tasks for You.Read more about IntentService at developer.android. A simple use case of the topic can be:

  • Your activity send a web request to IntentService to process
  • Your IntentService execute that request using DefaultHttpClient
  • And Return results (whatever, true,false list of objects/records etc) back to the calling activity

Now the task is to return the results back to the activity.  There are two options available either we can use Broadcast receiver or ResultReceiver

  1. Broadcast should be used if you want to send data/notifications across applications, whenever you send broadcast its sent system wide read more about broadcast receivers at developer.android.
  2. Result receiver is an interface you implement and pass it to the intentService through putExtra. IntentService then fetch this object and call its receiver.send function to send anything (in bundle) to calling activity[who started the intentservice]. Result receiver has preference over broadcast receivers if your all communication is internal to your application.
public class CheckIntentService extends IntentService {

private int count;
 public static final int INIT = 1;
 public static final int RUNNING = 2;
 public static final int END = 3;

public CheckIntentService()
 {
 super("Downloading");
 }

@Override
 protected void onHandleIntent(Intent intent) {
 count = 0;
 ResultReceiver receiver = intent.getParcelableExtra("receiver");
 Bundle bundle = new Bundle();
 bundle.putString("message", "Init the service");

receiver.send(INIT, bundle);

bundle = new Bundle();

while (count < 10) {
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 bundle.putString("message", "Running the service");
 bundle.putInt("count", count);
 receiver.send(RUNNING, bundle);
 count++;
 }
 bundle = new Bundle();
 bundle.putString("message", "End of the service");
 bundle.putInt("count", count);
 receiver.send(END, bundle);
 }
}

public class IntentServiceDemo extends Activity {

public static final String TAG = "IntentServiceDemo";

// private ResultReceiver receiver = new ResultReceiver(new Handler()) ;
 ResultReceiver r = new ResultReceiver(new Handler()) {
 @Override
 protected void onReceiveResult(int resultCode, Bundle resultData) {
 String str = "";
 if (resultCode == CheckIntentService.INIT) {
 str = resultData.getString("message");
 Log.i(TAG, str);
 } else if (resultCode == CheckIntentService.RUNNING
 || resultCode == CheckIntentService.END) {
 str = resultData.getString("message");
 int count = resultData.getInt("count", 0);
 Log.i(TAG, "message:" + str);
 Log.i(TAG, "count:" + count);
 }

}
 };

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

setContentView(R.layout.main);

findViewById(R.id.button1).setOnClickListener(new OnClickListener() {

@Override
 public void onClick(View v) {

Intent intentService = new Intent(IntentServiceDemo.this,
 CheckIntentService.class);
 intentService.putExtra("receiver", r);
 startService(intentService);

}
 });

}

}

Note:  Don’t use constructor with parameter in IntentService extended class.It shows an exception.

public CheckIntentService(String name)
{
super(“Downloading”);
}

 
Feel free to comment on my posts.............

Service Tutorial in android Part-I


Service:

A service is a task that runs in the background without the user’s direct interaction, similar to a Unix daemon. For example, consider a music player. The music may be started by an activity, but you want it to keep playing even when the user has moved on to a different program. So, the code that does the actual playing should be in a service. Later,another activity may bind to that service and tell it to switch tracks or stop playing. Android comes with many services built in, along with convenient APIs to access them.

      A Service is a component which runs in the background, without interacting with the user. Every developer can create new Services in his application. Services support true multitasking for Android, as they can run in their own process. If you use threads in Activities their are still connected to the life-cycle of Activities and the Android system may decide to terminate them at any point in point.

For information about services:  http://developer.android.com/reference/android/app/Service.html#RemoteMessengerServiceSample

The following topics are covered in this topic.

  1. Local Services
  2. Service using Binder
  3. Service using Messanger
  4. Serivice using Remote AIDL files
  5. Intent Service

1. Local Services:

We can start the service in two ways .

step 1:
Intent intent=new Intent(context,ServiceClassName.class);
startService(intent);
step 2:
Intent intent=new Intent(“com.ramesh.myservice.ACTION”);
startService(intent);

When we start service using step 2, make sure that adding the action in manifest file.


<service android:name="BindingService" >
 <intent-filter>
 <action android:name="com.ramesh.myservice.ACTION" >
 </action>
 </intent-filter>
 </service>

SimpleService.java:

 public class SimpleService extends Service
 {
 @Override
 public IBinder onBind(Intent arg0)
 {
 return null;
 }
 @Override
 public void onCreate()
 {
 super.onCreate();
 Toast.makeText(this,"Service created ...", Toast.LENGTH_LONG).show();
 }
 @Override
 public void onDestroy() {
 super.onDestroy();
 Toast.makeText(this, "Service destroyed ...", Toast.LENGTH_LONG).show();
 }
 }

In Activity take two buttons for testing , start the service with one button and stop the service with another.

You can choose one of the two steps to start the service.

2. Services using binder:

In Activity we are going to the bind service to communicating with it.

1. In oncreate method, we are binding the service using following statement.

bindService(new Intent(this, BindingService.class), conn,
Service.BIND_AUTO_CREATE);

2.Make sure that unbind the service connection  in onDestroy method Otherwise it gives service connection leaked exception.

  unbindService(conn);

3.When create the IBinder in service, its better to use WeakReference.This bug is mentioned in this blog.

private MyBinder mService;

 private ServiceConnection conn = new ServiceConnection()
 {
 @Override
 public void onServiceDisconnected(ComponentName name)
 {
 //service is disconnected!
 }

@Override
 public void onServiceConnected(ComponentName name, IBinder service)
 {
 //Service is connected.
 mService = (MyBinder) service;
 ((Button)findViewById(R.id.button1)).setText(mService.getName());
 mService.setName("Joy!");
 }
 };

/***BindingService.java:***/

public class BindingService extends Service {

public static final String MY_CUSTOM_ACTION = "com.ramesh.myservice.ACTION";
 private MyBinder<BindingService> binder;
 private String name = "Hi";

@Override
 public IBinder onBind(Intent intent) {
 binder = new MyBinder<BindingService>(this);
 return binder;
 }

@Override
 public int onStartCommand(Intent intent, int flags, int startId) {
 return START_STICKY;
 }

public class MyBinder<T> extends Binder implements IMybinder {
 private WeakReference<T> mService;

public MyBinder(T service) {
 mService = new WeakReference<T>(service);
 }

public T getService() {
 return mService.get();
 }

@Override
 public String getName() {

Random r = new Random();
 return name + "=> your lucky number is:" + r.nextInt(100);
 }

@Override
 public void setName(String newname) {
 name = newname;
 }
 }
}

 /** Interface setting the name and getting the name.**/

 public interface IMybinder
 {
 public String getName();

 public void setName(String name);
 }

Continue to be service tutorial-II…..

Custom spinner widget in android ?


Android Spinner has problems like.,

1.OnItemSelected listener will be fired when data is loadint at first time.

2.We can’t give label to the spinner(by default text).

Hbspinner.java overcomes this problems as per our basic need.

==>Hbspinner extends from button.It is added more methods seems to be Android spinner

==>Hbspinner provides Four types of spinners

=>Normal spinner: which is working just like Android spinner.

=>singleChoice spinner: spinner populates with single choice items.

=>multipleChoice spinner: spinner populates with multi choice items(with checkboxes).you can select more items

=>spinner using adapter:spinner is populating by using adapter.(in my example i am using android default layout: “android.R.layout.select_dialog_item”)

attr.xml:

<pre><?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="spinner">
 <attr name="spinnervaluearray" format="reference" />
 <attr name="prompt" format="string" />
 <attr name="src" format="reference" />
 <attr name="mode">
 <enum name="single" value="0" />
 <enum name="multiple" value="1" />
 <enum name="single_radio" value="2" />
 </attr>
 </declare-styleable>

</resources>

In layout/main.xml ,your declaration should be like this.


<pre><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:pref="http://schemas.android.com/apk/res/com.ramesh.spinner.demo"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:gravity="center"
 android:orientation="vertical" >
<com.ramesh.spinner.demo.HbSpinner
 android:id="@+id/hbSpinner2"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:drawableRight="@drawable/arrow_down_float"
 android:text="Using Xml Attributes for Spinner "
 pref:mode="single"
 pref:prompt="Web Development"
 pref:spinnervaluearray="@array/web"
 pref:src="@drawable/ic_launcher" />
</LinearLayout>

Hbspinner.java:


package com.ramesh.spinner.demo;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;

public class HbSpinner extends Button {

private AlertDialog dialog;
 private final static int INVALID = -1;
 private CharSequence[] singeItems;
 private OnSingleItemCallback listener;
 private static OnMultiItemsSelectionCallback multilistener;
 private String title = null;
 private int icon = INVALID;
 private Drawable iconDrawable;
 private int mMode;
 public static final int SINGLE = 0;
 public static final int MULTIPLE = 1;
 public static final int SINGLE_RADIO = 2;

public HbSpinner(Context context) {
 super(context, null);
 }

public HbSpinner(Context context, AttributeSet attrs) {
 super(context, attrs);
 if (attrs != null) {
 TypedArray a = getResources().obtainAttributes(attrs,
 R.styleable.spinner);
 int count = a.getIndexCount();

for (int i = 0; i < count; i++) {
 int type = a.getIndex(i);
 switch (type) {
 case R.styleable.spinner_mode: {
 setChoiceMode(a.getInt(type, 0));
 }
 break;
 case R.styleable.spinner_spinnervaluearray: {
 singeItems = a.getTextArray(type);
 }
 break;
 case R.styleable.spinner_prompt: {
 title = a.getString(type);
 }
 break;
 case R.styleable.spinner_src: {
 iconDrawable = a.getDrawable(type);
 }
 break;
 default:
 break;
 }
 }
 a.recycle();
 }

init();
 }

public void init() {
 setOnClickListener(onClick);
 }

public void setDefaultText(String string) {
 if (string != null)
 this.setText(string);
 }

public void setIcon(int icon) {
 this.icon = icon;
 }

public void setChoiceMode(int mode) {
 if (mode < 3 && mode > INVALID)
 mMode = mode;
 // else
 // new Exception(new Throwable("Illegal Mode selection"));
 }

public void setPrompt(String title) {
 this.title = title;
 }

public void setSingleDataItems(String[] items) {
 singeItems = items;
 mMode = SINGLE;

}

/**
 * Set on single items selection.
 *
 * @param callback
 */
 public void setOnSingleItemSelectedListener(OnSingleItemCallback callback) {
 listener = callback;
 }

/**
 * Set on Multiple items selection
 *
 * @param listener
 */
 public void setOnMultiItemSelectedListener(
 OnMultiItemsSelectionCallback listener) {
 multilistener = listener;
 }

@Override
 protected void onDetachedFromWindow() {
 super.onDetachedFromWindow();
 if (dialog != null && dialog.isShowing())
 dialog.dismiss();
 }

public OnClickListener onClick = new View.OnClickListener() {

@Override
 public void onClick(View v) {

if (adapter != null) {
 popupSpinnerAdapter();
 } else if (SINGLE == mMode) {
 popupSingleSpinner();
 } else if (mMode == MULTIPLE) {
 popupMultipleSpinner();
 } else if (mMode == SINGLE_RADIO) {
 popupSingleRadioSpinner();
 }
 }
 };

public CharSequence[] getItems() {
 return singeItems;
 }

private void popupSingleSpinner() {
 if (dialog != null && dialog.isShowing())
 dialog.dismiss();
 if (singeItems.length == 0) {
 singeItems = new String[] { "" };
 }

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
 if (title != null)
 builder.setTitle(title);
 if (icon != INVALID) {
 builder.setIcon(icon);
 } else if (iconDrawable != null) {
 builder.setIcon(iconDrawable);
 }
 builder.setItems(singeItems, onDialogClick);
 dialog = builder.create();
 dialog.show();
 }

private void popupMultipleSpinner() {
 if (dialog != null && dialog.isShowing())
 dialog.dismiss();
 if (singeItems.length == 0) {
 singeItems = new String[] { "" };
 }

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
 if (title != null)
 builder.setTitle(title);
 if (icon != INVALID) {
 builder.setIcon(icon);
 } else if (iconDrawable != null) {
 builder.setIcon(iconDrawable);
 }
 builder.setMultiChoiceItems(singeItems, null, onMultiClick);

builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {

@Override
 public void onClick(DialogInterface dialog, int which) {
 if (multilistener != null && checkedPositions.length > 0) {
 multilistener.setMultiSelectedItemsCallback(HbSpinner.this,
 checkedPositions);
 checkedPositions = new int[0];
 }
 }
 });
 builder.setNegativeButton("Cancel", null);

dialog = builder.create();
 dialog.show();
 dialog.getListView().setOnItemClickListener(onItemSelected);

}

public DialogInterface.OnClickListener onDialogClick = new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {
 if (mMode == SINGLE_RADIO)
 checkedItem = which;

if (listener != null)
 listener.onItemSelectedListener(HbSpinner.this,
 singeItems[which], which);
 HbSpinner.this.setText(singeItems[which]);
 dialog.dismiss();
 }
 };
 public DialogInterface.OnMultiChoiceClickListener onMultiClick = new DialogInterface.OnMultiChoiceClickListener() {

@Override
 public void onClick(DialogInterface dialog, int which, boolean isChecked) {

}
 };

private int[] checkedPositions = new int[0];
 public OnItemClickListener onItemSelected = new OnItemClickListener() {
 @Override
 public void onItemClick(AdapterView<?> arg0, View arg1, int position,
 long arg3) {
 ListView view = (ListView) arg0;
 SparseBooleanArray sp = view.getCheckedItemPositions();
 checkedPositions = new int[sp.size()];
 for (int i = 0; i < sp.size(); i++)
 checkedPositions[i] = sp.keyAt(i);
 }
 };

private int checkedItem = INVALID;

private void popupSingleRadioSpinner() {
 if (dialog != null && dialog.isShowing())
 dialog.dismiss();
 if (singeItems.length == 0) {
 singeItems = new String[] { "" };
 }

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
 if (title != null)
 builder.setTitle(title);
 if (icon != INVALID) {
 builder.setIcon(icon);
 } else if (iconDrawable != null) {
 builder.setIcon(iconDrawable);
 }
 builder.setSingleChoiceItems(singeItems, checkedItem, onDialogClick);
 dialog = builder.create();
 dialog.show();
 }

public ListAdapter adapter;

public void setAdapter(ListAdapter adapter,
 HbSpinnerAdapterCallback callbackAdapter) {
 this.adapter = adapter;
 this.callbackAdapter = callbackAdapter;
 }

private void popupSpinnerAdapter() {
 if (dialog != null && dialog.isShowing())
 dialog.dismiss();
 AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
 if (title != null)
 builder.setTitle(title);
 if (icon != INVALID) {
 builder.setIcon(icon);
 } else if (iconDrawable != null) {
 builder.setIcon(iconDrawable);
 }
 builder.setAdapter(adapter, new DialogInterface.OnClickListener() {

@Override
 public void onClick(DialogInterface dialog, int which) {
 if (callbackAdapter != null)
 callbackAdapter.onItemselectionAdapter(HbSpinner.this,
 which);
 }
 });// setSingleChoiceItems(singeItems,
 // builder.setItems(singeItems, onDialogClick);
 dialog = builder.create();
 dialog.show();
 }

public void setOnAdapterItemSelectionListener(
 HbSpinnerAdapterCallback callback) {
 callbackAdapter = callback;
 }

public ListAdapter getAdapter() {
 return adapter;
 }

HbSpinnerAdapterCallback callbackAdapter;

interface HbSpinnerAdapterCallback {
 /**
 * Adapter items selection callback
 *
 * @param spinner
 * {@link HbSpinner}
 * @param position
 * clicked position
 */
 public void onItemselectionAdapter(HbSpinner spinner, int position);
 }

interface OnMultiItemsSelectionCallback {

/**
 * Multiple items selection callback
 *
 * @param spinner
 * {@link HbSpinner}
 * @param checked
 * integer array which contains checked indexes
 */
 public void setMultiSelectedItemsCallback(HbSpinner spinner,
 int[] checked);
 }

interface OnSingleItemCallback {
 /**
 * Single items selection callback
 *
 * @param spinner
 * {@link HbSpinner}
 * @param selectedItem
 * selected item
 * @param position
 * selected position
 */
 public void onItemSelectedListener(HbSpinner spinner,
 CharSequence selectedItem, int position);
 }
}

you can find the source code here.
Screenshot:

screen shot

Custom spinner widget

Custom xml layouts in android .


i’ll walk through you how to use the styles and implementing the custom layouts in android.
You can learn the following concepts:

  1. Styles: Styles are used to simplifies our code in xml layout and complexity.
  2. Attributes: Here we can learn the usage of custom attributes.In my example i am creating rating bar.I am introducing in this example, level-list which is used to show the ratings icons.
  3. Level-list: A Drawable that manages a number of alternate Drawables, each assigned a maximum numerical value. Setting the level value of the drawable with setLevel() loads the drawable resource in the level list that has a android:maxLevel value greater than or equal to the value passed to the method.
  4. How to decalare custom layouts in Xml.
  5. How to accept the custom attributes and its values for custom layout in Xml.
Code Explanation:
—————–
  • When we are creating custom layouts we need to define constructor with 2 or 3 parameters.
  • In init() , reading the values which are defined in xml layout and which are defined with custom attributes .Custom attributes are available with attributesParentname_yourAttibutesName (in my example: R.styleable.customratingbar_rating).
  • In switch case first argument is R.styleable.customratingbar_rating, is used to get the current rating.
  • Second argument R.styleable.customratingbar_src, is used to read level-list Xml.
  • Last argument is R.styleable.customratingbar_max, is used to set the maximum rating.
  • ImageView#setImageLevel() is used to load the drawable resource in the level list.

res/values/attr.xml:


<?xml version="1.0" encoding="utf-8"?>
<resources >
 <declare-styleable name="customratingbar">
 <attr name="rating" format="integer"/>
 <attr name="max" format="integer"/>
 <attr name="src" format="reference"/>
 </declare-styleable>

</resources>

res/layout/main.xml:


<!--xmlns:pref="http://schemas.android.com/apk/res/"com.ramesh.customratingbar.demo" is application packag name and pref is your prefix to identify the attributes and assinging the values.-->
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:pref="http://schemas.android.com/apk/res/com.ramesh.customratingbar.demo"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical" >

<com.ramesh.customratingbar.demo.CustomRatingBar
 android:id="@+id/customRatingBar1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 pref:max="5"
 pref:rating="1"
 pref:src="@drawable/layer_list_demo" />

</LinearLayout>

CustomRatingBar.java:

public class CustomRatingBar extends ImageView {

private int currentRating = 0;
 private int maxRating = 0;
 private int ratingResId;
 private LevelListDrawable drawable;
 private OnRatingBarChangeListener listener;

public CustomRatingBar(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 init(context, attrs);
 }

public CustomRatingBar(Context context, AttributeSet attrs) {
 super(context, attrs);
 init(context, attrs);
 }

public void init(Context context, AttributeSet attrs) {
 setOnTouchListener(onTouch);
 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.customratingbar);
 final int n = a.getIndexCount();
 for (int i = 0; i < n; ++i) {
 int attr = a.getIndex(i);
 switch (attr) {
 case R.styleable.customratingbar_rating:
 currentRating = a.getInt(attr, 0);
 setRating(currentRating);
 break;
 case R.styleable.customratingbar_src:
 ratingResId = a.getResourceId(attr, 0);
 try {
 drawable = (LevelListDrawable) LevelListDrawable
 .createFromXml(getResources(), getResources()
 .getXml(ratingResId));
 } catch (NotFoundException e) {
 e.printStackTrace();
 } catch (XmlPullParserException e) {
 e.printStackTrace();
 } catch (IOException e) {
 e.printStackTrace();
 }

setRatingDrawable(drawable);
 break;
 case R.styleable.customratingbar_max:
 maxRating = a.getInt(attr, 0);
 setMax(maxRating);
 break;

}
 }
 a.recycle();
 }

@Override
 public void setImageLevel(int level) {
 super.setImageLevel(level);
 currentRating = level;
 }

public void setRating(int rating) {
 setImageLevel(rating);
 }

public void setRatingDrawable(Drawable drawable) {
 setImageDrawable(drawable);
 }

public void setRatingDrawable(int ratingResId) {

this.ratingResId = ratingResId;
 setImageResource(ratingResId);
 }

public void setMax(int max) {
 maxRating = max;
 }

public void setOnRatingListener(OnRatingBarChangeListener listener) {
 this.listener = listener;
 }

interface OnRatingBarChangeListener {
 public void setOnRatingChageListener(CustomRatingBar ratingbar,
 int rating);
 }

public OnTouchListener onTouch = new OnTouchListener() {

@Override
 public boolean onTouch(View v, MotionEvent event) {
 float rawX = event.getX();
 if (event.getAction() == MotionEvent.ACTION_MOVE) {
 float width = CustomRatingBar.this.getWidth();
 if (width > 0)
 {
 float tem1 = (rawX / width) * 100 * maxRating;
 int perc = (int) tem1 / 100;
 if (perc <= maxRating && perc >= 0) {
 currentRating = perc + 1;
 currentRating = currentRating > maxRating ? maxRating
 : currentRating;
 setImageLevel(currentRating);
 }
 }
 }
 if (event.getAction() == MotionEvent.ACTION_UP) {
 float width = CustomRatingBar.this.getWidth();
 if (width > 0) {
 float temp = (rawX / width) * maxRating;
 int perc = (int) temp;
 if (perc <= maxRating && perc >= 0) {
 currentRating = perc + 1;
 currentRating = currentRating > maxRating ? maxRating
 : currentRating;
 setImageLevel(currentRating);
 listener.setOnRatingChageListener(CustomRatingBar.this,
 currentRating);
 }
 }
 }

return true;
 }
 };
}

Referred Links:

http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/

https://staticallytyped.wordpress.com/tag/layer-list-level-list-android-custom-views-resources/

http://iserveandroid.blogspot.in/2010/10/progress-bar-implementation-using-level.html

you can download the source code here.

Screenshot here:

custom xml layout

custom xml layout

 

 

Understanding Android Themes and Styles


Custom Thems and Styles

Brain Flush

I don’t know how many hours I’ve spent struggling with Android’s theme engine, trying to figure out — mostly by trial and error — how styles are applied and how to properly define them (let’s be honest: the documentation on styles in Android is a bit lacking). I thought it may be worth sharing what I’ve found out so far, in order to save my fellow Android developers from baldness due to ripped out hair (I sure lost some). This is a work in progress (so is Android), and some information may be inaccurate. If you find anything that you think is wrong or unclear, please let me know by dropping a line in the comments section. On another note, I assume that you have read the reference documentation on Android styles, if not, you should do that now.

What are Android styles?

A style in Android is a…

View original post 1,386 more words

You Can Win by Shiv Khera!


You can win”, by Shiv Khera, is a storehouse of inspiration and knowledge. The book contains the golden rules for achieving success. It also inspires the readers to become good human beings.
Being successful is not the only achievement. The book strives to instill sterling qualities of head and heart that are the indispensable characteristics of a good human being. The book helps the readers in achieving success and building pleasant personalities.

“You can win” contains eleven chapters, equally important and relevant. The chapters are motivating, inspirational and stimulating. The book contains the important principles and axioms that are required to construct a pleasant personality. Positive attitude, motivation, self-esteem, pleasing personality, values and vision are aspects covered thoroughly in the book.

Positive attitude is a critical factor in success. The author has effectively explained the benefits of positive attitude. The author has also included an action plan which would help the readers to develop a positive attitude. He has also enumerated the steps required to build a positive attitude.

The author motivates the readers by incorporating winning strategies in his book. Various examples, stories and anecdotes are included in the book. The author has used these examples and stories to bring home his point. The anecdotes included in the book are highly motivating and inspirational.

The author strives to provide the readers with the right values and vision for achieving success. The author emphasizes on the fact that being a successful person is not enough. Being a good human being is equally important according to the author. The book helps the readers to remove the hurdles that block the path to success.

The book is an international best seller because of its top class content. I recommend this book to all those who wish to achieve success in life. The language used by the author is simple and flowing.

Read MoreYou can Win in pdf format.

ViewStub in Android .


ViewStub         

            A ViewStub is a dumb and lightweight view. It has no dimension, it does not draw anything and does not participate in the layout in any way. This means a ViewStub is very cheap to inflate and very cheap to keep in a view hierarchy. A ViewStub can be best described as a lazy include. The layout referenced by a ViewStub is inflated and added to the user interface only when you decide so. 

What is the difference between ViewStub and <include /> tag ?

                     The < include /> will just include the xml contents in your base xml file as if the whole thing was just a single big file. It’s a nice way to share layout parts between different layouts.The < ViewStub /> is a bit different because it is not directly included, and will be loaded only when you actually use it/need it, i.e, when you set it’s visibility to “true”. This a nice optimization because you could have a complex layout with tons of small views or headers anywhere, and still have your Activity load up really fast. Once you use one of those views, it’ll be loaded.
 

Example:

ViewStubTestActivity.java:
public class ViewStubTestActivity extends Activity implements OnClickListener {

/**
 * Reference to {@link ViewStub}
 */
 private View stub;

/** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 findViewById(R.id.button1).setOnClickListener(this);
 }

@Override
 public void onClick(View v) {
 new LazyLoading().execute();
 }

public class LazyLoading extends AsyncTask {
 @Override
 protected void onPreExecute()
 {
 if (stub == null) {
 stub = ((ViewStub) findViewById(R.id.vsHeader)).inflate();
 ((ProgressBar) stub.findViewById(R.id.progressBar1))
 .setIndeterminate(true);
 } else {
 stub.setVisibility(View.VISIBLE);
 }
 }

@Override
 protected Void doInBackground(Void... params) {
 try {
 Thread.sleep(2000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 return null;
 }

@Override
 protected void onPostExecute(Void result) {
 stub.setVisibility(View.GONE);
 }

}
}

Main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical" ></p>
<Button
 android:id="@+id/button1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Click Me" /></p>
<ViewStub
 android:id="@+id/vsHeader"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:inflatedId="@+id/inflatedview"
 android:layout="@layout/stub" /></p>
</LinearLayout>



stub.xml:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical" ></p>

<ProgressBar
 android:id="@+id/progressBar1"
 style="?android:attr/progressBarStyleHorizontal"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:indeterminate="true"
 />
</LinearLayout>

Note: ViewStub can’t be used more than once.

View stub screenshot.

References:http://www.technotalkative.com/android-viewstub-example/http://android-developers.blogspot.in/2009/03/android-layout-tricks-3-optimize-with.html

Android custom image gallery with checkbox in grid to select multiple


I would like to reblog this post.

Vikas Patel's Blog

Some times we may require to select multiple images from gallery. So using the following method you will be able to select multiple images. Additionally it will also remove gallery app dependency.

It may not be sufficient method as I need to maintain two array in this activity, but it could vary on requirements. Please comment if you have any suggestion in code.

Main.xml

galleryitem.xml

AndroidCustomGalleryActivity.java

Download full source code:
Download

Update: need more features? see my open source project
Update: Please remove code that closes cursor. As this will not work in Android 4.0 and newer.

http://vikaskanani.wordpress.com/android-custom-gallery-and-instant-upload-project/

 

 

 

 

View original post

Questions and Answers in Android ?


Que 1: Describe the APK format. 
Ans:

  • Android application package file (APK) is the file format used to distribute and install application software and middleware onto the Google Android operating system. (Same as .exe in windows)
  • Each Android application is compiled and packaged in a single file that includes all of the application’s code (.dex files), resources, assets, and manifest file.
  •  The application package file can have any name but must use the .apk extension

Que 2: What is activity? 
Ans:

  • Activity is a single screen in application.
  • It is derived from Activity class and support JAVA code.
  • You can put view by using setContentView(View) method.
  • Most commonly, an activity is visibly represented by a full screen window that can receive and handle UI events and perform complex tasks. Though an Activity is typically full screen, it can also be floating or transparent.

Que 3: What is intent? 
Ans: 

  • An Intent object is an instance of Intent.
  • A message object that you can use to launch or communicate with other applications/activities asynchronously.
  •  It includes several criteria fields that you can supply, to determine what application/activity receives the Intent and what the receiver does when handling the Intent. Available criteria include include the desired action, a category, a data string, the MIME type of the data, a handling class, and others.

Que 4: What is an action? 
Ans:

  • A description of something that an Intent sender wants done.
  • An action is a string value assigned to an Intent.
  • Action strings can be defined by Android or by a third-party developer.
  • For example, android.intent.action.VIEW for a Web URL

Que 5: How is nine-patch image different from a regular bitmap? 
Ans:

  • It is a resizable bitmap resource that can be used for backgrounds or other images on the device.
  •  The NinePatch class permits drawing a bitmap in nine sections. The four corners are unscaled; the four edges are scaled in one axis, and the middle is scaled in both axes.
  • We can create 9-patch images by using Draw 9-patch tool.

Que 6: Explain Draw 9-patch tool.

Ans:
  • The Draw 9-patch tool allows you to easily create a Ninepatch graphic using a WYSIWYG editor.

Que 7: What is a resource ? 
Ans:

  • A user-supplied XML(Strings/Animations/Colors), bitmap, or other file, injected into the application build process, which can later be loaded from code.

Ques 8: What is the difference between Service and Thread? 
Ans: 

  • Service is like an Activity but has no interface. Probably if you want to fetch the weather for example you won’t create a blank activity for it, for this you will use a Service.
  • It is also known as Background Service because it performs tasks in background.
  • A Thread is a concurrent unit of execution. You need to know that you cannot update UI from a Thread. You need to use a Handler for this, but read further.

Ques 9: What is View ? 
Ans: 

  • A View occupies a rectangular area on the screen and is responsible for drawing and event handling.
  • View is the base class for widgets, , which are used to create interactive UI components (buttons, text fields, etc.).

Ques 10: What is ViewGroup ?

Ans:
  • A ViewGroup is a special view that can contain other views (called children.)
  • The view group is the base class for layouts and views containers.
  • This class also defines the class  ViewGroup.LayoutParams which serves as the base class for layouts parameters.