Tuesday 30 August 2011

SQLite

1. SQLite in Android

SQLite is an Open Source Database which is embedded into Android. SQLight supports standard relational database features like SQL syntax, transactions and prepared statements. In addition it requires only little memory at runtime (approx. 250 KByte).

Using SQLite in Android does not require any database setup or administration. You specify the SQL for working with the database and the database is automatically managed for you.

Working with databases in Android can be slow due to the necessary I/O. Therefore is it recommended to perform this task in an AsyncTask . Please see Android Background Processing Tutorial for details.

SQLite supports the data types TEXT (similar to String in Java), INTEGER (similar to long in Java) and REAL (similar to double in Java). All other types must be converted into on of these fields before saving them in the database. SQLight itself does not validate if the types written to the columns are actually of the defined type, you can write an integer into a string column.

If your application creates an database this database is saved in the directory "DATA/data/APP_NAME/databases/FILENAME". "DATA" is the path which Environment.getDataDirectory() returns, "APP_NAME" is your application name and "FILENAME" is the name you give the database during creation. Environment.getDataDirectory() usually return the SD card as location.

A SQlite database is private to the application which creates it. If you want to share data with other applications you can use a Content Provider.

2. SQLiteOpenHelper

To create and upgrade a database in your Android application you usually subclass "SQLiteOpenHelper". In this class you need to override the methods onCreate() to create the database and onUpgrade() to upgrade the database in case of changes in the database schema. Both methods receive an "SQLiteDatabase" object.

SQLiteOpenHelper provides the methods getReadableDatabase() and getWriteableDatabase() to get access to an "SQLiteDatabase" object which allows database access either in read or write mode.

For the primary key of the database you should always use the identifier "_id" as some of Android functions rely on this standard.

3. SQLiteDatabase and Cursor

"SQLiteDatabase" provides the methods insert(), update() and delete() and execSQL() method which allows to execute directly SQL. The object "ContentValues" allow to define key/values for insert and update. The key is the column and the value is the value for this column.

Queries can be created via the method rawQuery() which accepts SQL or query() which provides an interface for specifying dynamic data or SQLiteQueryBuilder. SQLiteBuilder is similar to the interface of an content provider therefore it is typically used in ContentProviders. A query returns always a "Cursor".

The method query has the parameters String dbName, int[] columnNames, String whereClause, String[] valuesForWhereClause, String[] groupBy, String[] having, String[] orderBy. If all data should be selected you can pass "null" as the where clause. The where clause is specified without "where", for example "_id=19 and summary=?". If several values are required via ? you pass them in the valuesForWhereClause array to the query. In general if something is not required you can pass "null", e.g. for the group by clause.

A Cursor represents the result of a query. To get the number of elements use the method getCount(). To move between individual data rows, you can use the methods moveToFirst() and moveToNext(). Via the method isAfterLast() you can check if there is still some data.

Wednesday 17 August 2011

Launching other app from my app

Launch other application of the device from your application:

Intent intent = getPackageManager().getLaunchIntentForPackage(packageName);
      intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
      intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
      if (null != intent) {
      try {
             startActivity(intent);
      } catch(Exception e) {  }
    }

Note: You need to know the package name to use the above code. For package name:


Getting Package Name of Installed app

Note: A lot of people need to fetch the package name, application name of the installed application on the device.Here is the code:

ArrayList<PackageInfo> res = new ArrayList<PackageInfo>();
PackageManager pm = ctx.getPackageManager();
List<PackageInfo> packs = pm.getInstalledPackages(0);

for(int i=0;i<packs.size();i++) {
    PackageInfo p = packs.get(i);
    String description = (String) p.applicationInfo.loadDescription(pm);
    String  label= p.applicationInfo.loadLabel(pm).toString();
    String packageName = p.packageName;
    String versionName = p.versionName;
    String versionCode = p.versionCode;
    String icon = p.applicationInfo.loadIcon(pm);
//Continue to extract other info about the app...
}

Note: Add this permission to the manifest file:

<uses-permission android:name="android.permission.GET_TASKS" />


Calling Programmatically

You can initiate call programmatically. Let's do it:

Intent call = new Intent(Intent.ACTION_CALL);
call.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
call.setData(Uri.parse("tel:" + number));
startActivity(call);

Note: Add the permission to the manifest file:
<uses-permission android:name="android.permission.CALL_PHONE" />

Monday 8 August 2011

Passing values from one Activity to another


Intent intent = new Intent(context, CalledActivity.class);
        intent.putExtra(key, value);
        startActivity(intent);
       
If you want some data back from called Activity then you can use startActivityForResult() as:

Intent intent = new Intent(context, CalledActivity.class);
        intent.putExtra(key, value);
        startActivityForResult(intent, requestCode);
       
In called activity you can set data as:

setResult(RESULT_OK, intent);

Note: Here you set the value in intent and pass it to setResult().       
       

On returning back to calling Activity you can get data by overriding:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == RESULT_OK){
            //Get data from Intent "data" and do your task here....
        }
    }
   
   
Note: You can pass primitive data type values thru Intent and if you want to pass other types then you have to use Bundle like this.

Bundle data = new Bundle();
        data.putIntArray(key, value);
        //same way you can set other values.......
//Now set this Bundle value to Intent as you do for primitive type....
Intent intent = new Intent(context, CalledActivity.class);
        intent.putExtra(data);
        startActivity(intent);

Receiving data in Activity:

//For primitive values:
DataType var_name = getIntent().getExtras().get(key);

//For Bundle values:
Bundle var_name = getIntent().getExtras().getBundle(key);


Contacts

Note: Here are some useful links:

Getting Contacts:







Using Contact Picker:


Inserting Contact:




Deleting Contacts:


Friday 5 August 2011

Adding Event to Calendar

Let's add events to calendar:

ContentResolver cr = getContentResolver();
       
//Find out which calendars exist...
Cursor cursor_calendar; // = cr.query(Uri.parse("content://com.android.calendar/calendars"), new String[]{ "_id",  "displayname" }, null, null, null);
if (Integer.parseInt(Build.VERSION.SDK) >= 8 ){
    cursor_calendar = cr.query(Uri.parse("content://com.android.calendar/calendars"), new String[]{ "_id", "displayname" }, null, null, null);
}
else{
    cursor_calendar = cr.query(Uri.parse("content://calendar/calendars"), new String[]{ "_id", "displayname" }, null, null, null);
}

cursor_calendar.moveToFirst();
String[] CalNamess = new String[cursor_calendar.getCount()];
int[] CalIdss = new int[cursor_calendar.getCount()];
for (int i = 0; i < CalNamess.length; i++) {
    CalIdss[i] = cursor_calendar.getInt(0);
    CalNamess[i] = cursor_calendar.getString(1);
    cursor_calendar.moveToNext();
}
cursor_calendar.close();

//Call this function to add event...
private void addEventToCalendar(int calender_id, String title, long start_date, long end_date){
   
    ContentValues cv = new ContentValues();
    cv.put("calendar_id", calender_id);
    cv.put("title", title);
    cv.put("dtstart", start_date );
    cv.put("hasAlarm", 1);
    cv.put("dtend", end_date);

    Uri newEvent ;
    if (Integer.parseInt(Build.VERSION.SDK) >= 8 ){
        newEvent = cr.insert(Uri.parse("content://com.android.calendar/events"), cv);
    }   
    else{
        newEvent = cr.insert(Uri.parse("content://calendar/events"), cv);
    }   

    if (newEvent != null)
    {
        long id = Long.parseLong( newEvent.getLastPathSegment() );
        ContentValues values = new ContentValues();
        values.put( "event_id", id );
        values.put( "method", 1 );
        values.put( "minutes", 0 ); // 15 minut Before
        if (Integer.parseInt(Build.VERSION.SDK) >= 8 )
            cr.insert( Uri.parse( "content://com.android.calendar/reminders" ), values );
        else
            cr.insert( Uri.parse( "content://calendar/reminders" ), values );
    }
}

Note: I tested this code at API level 10 and it worked fine.

Retrieving Events from Calendar

ContentResolver cr = getContentResolver();
       
//Find out which calendars exist...

Cursor cursor_calendar;
if (Integer.parseInt(Build.VERSION.SDK) >= 8 ){
    cursor_calendar = cr.query(Uri.parse("content://com.android.calendar/calendars"), new String[]{ "_id", "displayname" }, null, null, null);
}   
else{
    cursor_calendar = cr.query(Uri.parse("content://calendar/calendars"), new String[]{ "_id", "displayname" }, null, null, null);
}   

cursor_calendar.moveToFirst();
String[] CalNamess = new String[cursor_calendar.getCount()];
int[] CalIdss = new int[cursor_calendar.getCount()];
for (int i = 0; i < CalNamess.length; i++) {
    CalIdss[i] = cursor_calendar.getInt(0);
    CalNamess[i] = cursor_calendar.getString(1);
    cursor_calendar.moveToNext();
}
cursor_calendar.close();

//Find out stored events in Calendar...

Cursor cursor_event;
if (Integer.parseInt(Build.VERSION.SDK) >= 8 ){
  cursor_event = cr.query(Uri.parse("content://com.android.calendar/events"), new String[]{ "calendar_id", "title", "description", "dtstart", "dtend", "eventLocation" }, null, null, null);
else{
    cursor_event = cr.query(Uri.parse("content://calendar/events"), new String[]{ "calendar_id", "title", "description", "dtstart", "dtend", "eventLocation" }, null, null, null);
}
   
String add = null;
cursor_event.moveToFirst();
String[] CalNames = new String[cursor_event.getCount()];
int[] CalIds = new int[cursor_event.getCount()];
for (int i = 0; i < CalNames.length; i++) {
  CalIds[i] = cursor_event.getInt(0);
  CalNames[i] = "Event"+cursor_event.getInt(0)+": \nTitle: "+ cursor_event.getString(1)+"\nDescription: "+cursor_event.getString(2)+"\nStart Date: "+new Date(cursor_event.getLong(3))+"\nEnd Date : "+new Date(cursor_event.getLong(4))+"\nLocation : "+cursor_event.getString(5);
  if(add == null)
      add = CalNames[i];
  else{
      add += CalNames[i];
  }          
  cursor_event.moveToNext();
}
cursor_event.close();

Note: I tested this code on API level 10 and it is working fine.


Thursday 4 August 2011

Rounded Corner Button

Note: Here is rounded_corner_button.xml. Save it in your drawable folder and use it in place of image.

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
<corners android:radius="8dp" />
<gradient
    android:angle="45"
    android:startColor="#FFFF0000"
    android:endColor="#80FF00FF" />
<padding
    android:left="2dp"
    android:top="2dp"
    android:right="2dp"
    android:bottom="2dp" />
<solid
    android:color="#0f7fb6" />
</shape>


Enable - Disable Silent Mode

public void changeRingerMode(Context context){
   
AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
   
    /**
    * To Enable silent mode.....
    */
    audio.setRingerMode(AudioManager.RINGER_MODE_SILENT);
   
    /**
    * To Enable Ringer mode.....
    */
    audio.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
   
}


NotificationManager & Status Bar Icon

How to set the icon of the app in Device's Status Bar and do notification process? Here it is how to do it:

public static void notifyIcon(Context context){

NotificationManager notifier = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.your_app_notification, "", System.currentTimeMillis());

/**
*Setting these flags will stop clearing your icon
*from the status bar if the user does clear all 
*notifications.
*/
    notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
    RemoteViews contentView = new RemoteViews(context.getPackageName(), R.layout.custom_notification_layout);
    notification.contentView = contentView;
   
//If you want to open any activity on the click of the icon.

    Intent notificationIntent = new Intent(context, YourActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
    notification.contentIntent = contentIntent;
   
    notification.setLatestEventInfo(context, "title", null, contentIntent);
    notifier.notify(1, notification);

//To cancel the icon ...
    notifier.cancel(1);

}

Here is custom_notification_layout.xml

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

</LinearLayout>

Note: Don't forget to clear your app icon when appropriate If you set above flag.



Wednesday 3 August 2011

Custom List Adapter

Note: You want to customize your List Adapter as per your requirement then here is some useful code for you but  modify it as you require ....... It is just a trailor, rest is in your hands.

import java.util.Vector;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class YourAdapterName extends BaseAdapter{

private Context mContext;
private Vector mValuestoShow;

/**
 * Constructor to be called to initialize adapter with values.
 * @param context
 * @param vector
 */
public YourAdapterName(Context context, Vector vector){
    mContext = context;
    mValuestoShow = vector;
}

public int getCount() {
    if(null != mValuestoShow){
        return mValuestoShow.size();
    }
    return 0;
}

public Object getItem(int position) {
    if(position < mValuestoShow.size())
        return  mValuestoShow.get(position);
    else
        return null;
}

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

/**
 * This method can be override to enable/disable particular list row.
 */
@Override
public boolean isEnabled(int position) {
    //Write your code here......
    return super.isEnabled(position);
}

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder ;
    if(convertView == null){
        LayoutInflater li =(LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = li.inflate(R.layout.your_layout, null);
        holder = new ViewHolder();
        holder.txt_name = (TextView) convertView.findViewById(R.id.name_txt);
        convertView.setTag(holder);
    }else{
        holder = (ViewHolder) convertView.getTag();
    }
  
    /**
 * Use of enable method how to set different color for disabled row....
 * You can also customize your row background color or text color without using enable method
 * in the same way as below is done as per your conditions.
 */
    if(!isEnabled(position)){
        holder.txt_name.setBackgroundColor(mContext.getResources().getColor(R.color.color_code));
        holder.txt_name.setTextColor(mContext.getResources().getColor(R.color.white));
    }else{
        holder.txt_name.setBackgroundColor(mContext.getResources().getColor(R.color.color_code));
        holder.txt_name.setTextColor(mContext.getResources().getColor(R.color.black));
    }
  
    holder.txt_name.setText(getItem(position).toString());
  
    return convertView;
}

class ViewHolder {
    TextView txt_name;
}

}

your_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width = "fill_parent"
    android:layout_height = "wrap_content"
    android:padding = "10dp" >
   
<TextView
    android:id = "@+id/txt_type1"
    android:layout_width = "wrap_content"
    android:layout_height = "wrap_content" />
   
<TextView
    android:id = "@+id/txt_type2"
    android:layout_width = "wrap_content"
    android:layout_height = "wrap_content" />
   
<ImageView
    android:id = "@+id/image"
    android:src = "@drawable/image"
    android:layout_width = "wrap_content"
    android:layout_height = "wrap_content" />
           
</RelativeLayout>

Note:You can add more views like Button , ImageButton, EditText as per your need.



Accept - Reject Call

You can programmatically Accept or Reject Call and check if the call is active or not.

public static void callAnswer(Context context) throws Exception{
        try{
            TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
            Class c = Class.forName(manager.getClass().getName());
            Method m = c.getDeclaredMethod("getITelephony");
            m.setAccessible(true);
            ITelephony telephony = (ITelephony)m.invoke(manager);
            telephony.answerRingingCall();
        }catch(Exception e){
            Log.d("Exception caught", e.getMessage());          
        }
}

public static void callReject(Context context) throws Exception{
        try{
            TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
            Class c = Class.forName(manager.getClass().getName());
            Method m = c.getDeclaredMethod("getITelephony");
            m.setAccessible(true);
            ITelephony telephony = (ITelephony)m.invoke(manager);
            telephony.endCall();
        } catch(Exception e){
            Log.d("",e.getMessage());
        }
}

public static boolean isCallActive(Context context){
        AudioManager manager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
        if(manager.getMode()==AudioManager.MODE_IN_CALL){
            return true;
        }
        else{
            return false;
        }
}

Note: It worked for me till the platform 2.3.3.You need to include this file for this:


Tuesday 2 August 2011

Long - Lat - Address

How to fetch the Longitude, Latitude and Address of your current location? Let's do it:

LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
String provider = locationManager.getBestProvider(new Criteria(), true);
Location locations = locationManager.getLastKnownLocation(provider);
List<String>  providerList = locationManager.getAllProviders();
if(null!=locations && null!=providerList && providerList.size()>0){                   
double longitude = locations.getLongitude();
double latitude = locations.getLatitude();
Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());                   
try {
    List<Address> listAddresses = geocoder.getFromLocation(latitude, longitude, 1);
    if(null!=listAddresses&&listAddresses.size()>0){
        String _Location = listAddresses.get(0).getAddressLine(1);
    }
} catch (IOException e) {
    e.printStackTrace();
}
                   
}

Note: Add these permissions to your manifest file: 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 Use this for network-based location.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
 Use this for GPS based location but it includes network-based location property too.
You should use both for more versatile application.
 
 

GPRS Status

How to check if GPRS or Data Connection is enabled or not over the device? Let's do it:

public static boolean isDataConnectionAvailable(Context context){
        ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if(info == null)
            return false;

        return connectivityManager.getActiveNetworkInfo().isConnected();
 }

Note: Add permission to your manifest file:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />