Sunday, January 27, 2013

Android Content Provider / Preferences/Sqlite db (CURD)/ Feed Example

In this Given Example there is a scope to learn about lot of things like RSSfeeds + content providers +Sqlit db executions+ shared preferences + the perfect object orientation with Java.

i learnt this example from the popular android book Professional Android by Reto Meier, i picked this example from the same book as well and there is no great modification is there. please make an Android project and copy the following given code there

1)  src/com/jitesh/earthquake/Earthquake.java (Main activity class)


package com.jitesh.earthquake;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;



import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.location.Location;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.MenuItem;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

public class Earthquake extends Activity {

  static final private int MENU_UPDATE = Menu.FIRST;
  static final private int MENU_PREFERENCES = Menu.FIRST+1;
  static final private int QUAKE_DIALOG = 1;
  private static final int SHOW_PREFERENCES = 1;

  ListView earthquakeListView;
  ArrayAdapter<Quake> aa;
  ArrayList<Quake> earthquakes = new ArrayList<Quake>();
   
  Quake selectedQuake;
 
  int minimumMagnitude = 0;
  boolean autoUpdate = false;
  int updateFreq = 0;

  @Override
  public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.main);

    earthquakeListView = (ListView)this.findViewById(R.id.earthquakeListView);

    earthquakeListView.setOnItemClickListener(new OnItemClickListener() {
      public void onItemClick(AdapterView _av, View _v, int _index, long arg3) {
        selectedQuake = earthquakes.get(_index);
        showDialog(QUAKE_DIALOG);
      }
    });

    int layoutID = android.R.layout.simple_list_item_1;
     aa = new ArrayAdapter<Quake>(this, layoutID , earthquakes);
    earthquakeListView.setAdapter(aa);

    loadQuakesFromProvider();

    updateFromPreferences();
    refreshEarthquakes();
  }
 
  private void refreshEarthquakes() {
 // Get the XML
 URL url;
 try {
   String quakeFeed = getString(R.string.quake_feed);
   url = new URL(quakeFeed);
       
   URLConnection connection;
   connection = url.openConnection();
     
   HttpURLConnection httpConnection = (HttpURLConnection)connection;
   int responseCode = httpConnection.getResponseCode();

   if (responseCode == HttpURLConnection.HTTP_OK) {
     InputStream in = httpConnection.getInputStream();
       
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
     DocumentBuilder db = dbf.newDocumentBuilder();

     // Parse the earthquake feed.
     Document dom = db.parse(in);    
     Element docEle = dom.getDocumentElement();
     
     // Clear the old earthquakes
     earthquakes.clear();
     loadQuakesFromProvider();
   
     // Get a list of each earthquake entry.
     NodeList nl = docEle.getElementsByTagName("entry");
     if (nl != null && nl.getLength() > 0) {
       for (int i = 0 ; i < nl.getLength(); i++) {
         Element entry = (Element)nl.item(i);
         Element title = (Element)entry.getElementsByTagName("title").item(0);
         Element g = (Element)entry.getElementsByTagName("georss:point").item(0);
         Element when = (Element)entry.getElementsByTagName("updated").item(0);
         Element link = (Element)entry.getElementsByTagName("link").item(0);

         String details = title.getFirstChild().getNodeValue();
         String hostname = "http://earthquake.usgs.gov";
         String linkString = hostname + link.getAttribute("href");

         String point = g.getFirstChild().getNodeValue();
         String dt = when.getFirstChild().getNodeValue();
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
         Date qdate = new GregorianCalendar(0,0,0).getTime();
         try {
           qdate = sdf.parse(dt);
         } catch (ParseException e) {
           e.printStackTrace();
         }

         String[] location = point.split(" ");
         Location l = new Location("dummyGPS");
         l.setLatitude(Double.parseDouble(location[0]));
         l.setLongitude(Double.parseDouble(location[1]));

         String magnitudeString = details.split(" ")[1];
         int end =  magnitudeString.length()-1;
         double magnitude = Double.parseDouble(magnitudeString.substring(0, end));
           
         details = details.split(",")[1].trim();
           
         Quake quake = new Quake(qdate, details, l, magnitude, linkString);

         // Process a newly found earthquake
         addNewQuake(quake);
       }
     }
   }
 } catch (MalformedURLException e) {
   e.printStackTrace();
 } catch (IOException e) {
   e.printStackTrace();
 } catch (ParserConfigurationException e) {
   e.printStackTrace();
 } catch (SAXException e) {
   e.printStackTrace();
 }
 finally {
 }
}

  private void addNewQuake(Quake _quake) {
 ContentResolver cr = getContentResolver();
 // Construct a where clause to make sure we donĂ•t already have this
 // earthquake in the provider.
 String w = EarthquakeProvider.KEY_DATE + " = " + _quake.getDate().getTime();

 // If the earthquake is new, insert it into the provider.
 if (cr.query(EarthquakeProvider.CONTENT_URI, null, w, null, null).getCount()==0){
   ContentValues values = new ContentValues();  

   values.put(EarthquakeProvider.KEY_DATE, _quake.getDate().getTime());
   values.put(EarthquakeProvider.KEY_DETAILS, _quake.getDetails());

   double lat = _quake.getLocation().getLatitude();
   double lng = _quake.getLocation().getLongitude();
   values.put(EarthquakeProvider.KEY_LOCATION_LAT, lat);
   values.put(EarthquakeProvider.KEY_LOCATION_LNG, lng);
   values.put(EarthquakeProvider.KEY_LINK, _quake.getLink());
   values.put(EarthquakeProvider.KEY_MAGNITUDE, _quake.getMagnitude());

   cr.insert(EarthquakeProvider.CONTENT_URI, values);
   earthquakes.add(_quake);

   addQuakeToArray(_quake);
 }
}

private void addQuakeToArray(Quake _quake) {
 if (_quake.getMagnitude() > minimumMagnitude) {
   // Add the new quake to our list of earthquakes.
   earthquakes.add(_quake);

   // Notify the array adapter of a change.
   aa.notifyDataSetChanged();
 }
}

private void loadQuakesFromProvider() {
      // Clear the existing earthquake array
      earthquakes.clear();

      ContentResolver cr = getContentResolver();

      // Return all the saved earthquakes
      Cursor c = cr.query(EarthquakeProvider.CONTENT_URI, null, null, null, null);

      if (c.moveToFirst()) {
        do {
          // Extract the quake details.
          Long datems = c.getLong(EarthquakeProvider.DATE_COLUMN);
          String details = c.getString(EarthquakeProvider.DETAILS_COLUMN);
          Float lat = c.getFloat(EarthquakeProvider.LATITUDE_COLUMN);
          Float lng = c.getFloat(EarthquakeProvider.LONGITUDE_COLUMN);
          Double mag = c.getDouble(EarthquakeProvider.MAGNITUDE_COLUMN);
          String link = c.getString(EarthquakeProvider.LINK_COLUMN);

          Location location = new Location("dummy");
          location.setLongitude(lng);
          location.setLatitude(lat);

          Date date = new Date(datems);

          Quake q = new Quake(date, details, location, mag, link);
          addQuakeToArray(q);
        } while(c.moveToNext());
      }
    }
   
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
      super.onCreateOptionsMenu(menu);

      menu.add(0, MENU_UPDATE, Menu.NONE, R.string.menu_update);
      menu.add(0, MENU_PREFERENCES, Menu.NONE, R.string.menu_preferences);

      return true;
    }
           
    public boolean onOptionsItemSelected(MenuItem item) {
      super.onOptionsItemSelected(item);

      switch (item.getItemId()) {
        case (MENU_UPDATE): {
          refreshEarthquakes();
          return true;
        }
        case (MENU_PREFERENCES): {
          Intent i = new Intent(this, Preferences.class);
          startActivityForResult(i, SHOW_PREFERENCES);
          return true;
        }
      }
      return false;
    }
   
    @Override
    public Dialog onCreateDialog(int id) {
      switch(id) {
        case (QUAKE_DIALOG) :
          LayoutInflater li = LayoutInflater.from(this);
          View quakeDetailsView = li.inflate(R.layout.quake_details, null);

          AlertDialog.Builder quakeDialog = new AlertDialog.Builder(this);
          quakeDialog.setTitle("Quake Time");
          quakeDialog.setView(quakeDetailsView);
          return quakeDialog.create();
      }
      return null;
    }

    @Override
    public void onPrepareDialog(int id, Dialog dialog) {
      switch(id) {
        case (QUAKE_DIALOG) :
          SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
          String dateString = sdf.format(selectedQuake.getDate());
          String quakeText = "Magnitude " + selectedQuake.getMagnitude() +
                             "\n" + selectedQuake.getDetails()  + "\n" +
                             selectedQuake.getLink();

          AlertDialog quakeDialog = (AlertDialog)dialog;
          quakeDialog.setTitle(dateString);
          TextView tv = (TextView)quakeDialog.findViewById(R.id.quakeDetailsTextView);
          tv.setText(quakeText);

          break;
      }
    }
   
    private void updateFromPreferences() {
      Context context = getApplicationContext();
      SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

      minimumMagnitude = Integer.parseInt(prefs.getString(Preferences.PREF_MIN_MAG, "0"));
      updateFreq = Integer.parseInt(prefs.getString(Preferences.PREF_UPDATE_FREQ, "0"));
      autoUpdate = prefs.getBoolean(Preferences.PREF_AUTO_UPDATE, false);
    }
   
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      if (requestCode == SHOW_PREFERENCES)
        if (resultCode == Activity.RESULT_OK) {
          updateFromPreferences();
          refreshEarthquakes();
        }
    }
}

2)  src/com/jitesh/earthquake/EarthquakeProvider.java (Content Provider)


package com.jitesh.earthquake;

import android.content.*;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

public class EarthquakeProvider extends ContentProvider {

public static final Uri CONTENT_URI = Uri
.parse("content://com.jitesh.provider.earthquake/earthquakes");

@Override
public boolean onCreate() {
Context context = getContext();

earthquakeDatabaseHelper dbHelper = new earthquakeDatabaseHelper(
context, DATABASE_NAME, null, DATABASE_VERSION);
earthquakeDB = dbHelper.getWritableDatabase();
return (earthquakeDB == null) ? false : true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sort) {

SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

qb.setTables(EARTHQUAKE_TABLE);

// If this is a row query, limit the result set to the passed in row.
switch (uriMatcher.match(uri)) {
case QUAKE_ID:
qb.appendWhere(KEY_ID + "=" + uri.getPathSegments().get(1));
break;
default:
break;
}

// If no sort order is specified sort by date / time
String orderBy;
if (TextUtils.isEmpty(sort)) {
orderBy = KEY_DATE;
} else {
orderBy = sort;
}

// Apply the query to the underlying database.
Cursor c = qb.query(earthquakeDB, projection, selection, selectionArgs,
null, null, orderBy);

// Register the contexts ContentResolver to be notified if
// the cursor result set changes.
c.setNotificationUri(getContext().getContentResolver(), uri);

// Return a cursor to the query result.
return c;
}

@Override
public Uri insert(Uri _uri, ContentValues _initialValues) {
// Insert the new row, will return the row number if
// successful.
long rowID = earthquakeDB.insert(EARTHQUAKE_TABLE, "quake",
_initialValues);

// Return a URI to the newly inserted row on success.
if (rowID > 0) {
Uri uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
getContext().getContentResolver().notifyChange(uri, null);
return uri;
}
throw new SQLException("Failed to insert row into " + _uri);
}

@Override
public int delete(Uri uri, String where, String[] whereArgs) {
int count;

switch (uriMatcher.match(uri)) {
case QUAKES:
count = earthquakeDB.delete(EARTHQUAKE_TABLE, where, whereArgs);
break;

case QUAKE_ID:
String segment = uri.getPathSegments().get(1);
count = earthquakeDB.delete(EARTHQUAKE_TABLE,
KEY_ID
+ "="
+ segment
+ (!TextUtils.isEmpty(where) ? " AND (" + where
+ ')' : ""), whereArgs);
break;

default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}

getContext().getContentResolver().notifyChange(uri, null);
return count;
}

@Override
public int update(Uri uri, ContentValues values, String where,
String[] whereArgs) {
int count;
switch (uriMatcher.match(uri)) {
case QUAKES:
count = earthquakeDB.update(EARTHQUAKE_TABLE, values, where,
whereArgs);
break;

case QUAKE_ID:
String segment = uri.getPathSegments().get(1);
count = earthquakeDB.update(EARTHQUAKE_TABLE, values,
KEY_ID
+ "="
+ segment
+ (!TextUtils.isEmpty(where) ? " AND (" + where
+ ')' : ""), whereArgs);
break;

default:
throw new IllegalArgumentException("Unknown URI " + uri);
}

getContext().getContentResolver().notifyChange(uri, null);
return count;
}

@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case QUAKES:
return "vnd.android.cursor.dir/vnd.jitesh.earthquake";
case QUAKE_ID:
return "vnd.android.cursor.item/vnd.jitesh.earthquake";
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}

// Create the constants used to differentiate between the different URI
// requests.
private static final int QUAKES = 1;
private static final int QUAKE_ID = 2;

private static final UriMatcher uriMatcher;

// Allocate the UriMatcher object, where a URI ending in 'earthquakes' will
// correspond to a request for all earthquakes, and 'earthquakes' with a
// trailing '/[rowID]' will represent a single earthquake row.
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher
.addURI("com.jitesh.provider.Earthquake", "earthquakes", QUAKES);
uriMatcher.addURI("com.jitesh.provider.Earthquake", "earthquakes/#",
QUAKE_ID);
}

// The underlying database
private SQLiteDatabase earthquakeDB;

private static final String TAG = "EarthquakeProvider";
private static final String DATABASE_NAME = "earthquakes.db";
private static final int DATABASE_VERSION = 1;
private static final String EARTHQUAKE_TABLE = "earthquakes";

// Column Names
public static final String KEY_ID = "_id";
public static final String KEY_DATE = "date";
public static final String KEY_DETAILS = "details";
public static final String KEY_LOCATION_LAT = "latitude";
public static final String KEY_LOCATION_LNG = "longitude";
public static final String KEY_MAGNITUDE = "magnitude";
public static final String KEY_LINK = "link";

// Column indexes
public static final int DATE_COLUMN = 1;
public static final int DETAILS_COLUMN = 2;
public static final int LONGITUDE_COLUMN = 3;
public static final int LATITUDE_COLUMN = 4;
public static final int MAGNITUDE_COLUMN = 5;
public static final int LINK_COLUMN = 6;

// Helper class for opening, creating, and managing database version control
private static class earthquakeDatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_CREATE = "create table "
+ EARTHQUAKE_TABLE + " (" + KEY_ID
+ " integer primary key autoincrement, " + KEY_DATE
+ " INTEGER, " + KEY_DETAILS + " TEXT, " + KEY_LOCATION_LAT
+ " FLOAT, " + KEY_LOCATION_LNG + " FLOAT, " + KEY_MAGNITUDE
+ " FLOAT, " + KEY_LINK + " TEXT);";

public earthquakeDatabaseHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");

db.execSQL("DROP TABLE IF EXISTS " + EARTHQUAKE_TABLE);
onCreate(db);
}
}
}

3) src/com/jitesh/earthquake/Preferences.java (Shared Preferences Use)


package com.jitesh.earthquake;



import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceActivity;

public class Preferences extends PreferenceActivity {

  public static final String PREF_AUTO_UPDATE = "PREF_AUTO_UPDATE";
  public static final String PREF_MIN_MAG = "PREF_MIN_MAG";
  public static final String PREF_UPDATE_FREQ = "PREF_UPDATE_FREQ";

  SharedPreferences prefs;

  @Override
  public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    addPreferencesFromResource(R.xml.userpreferences);
  }
}



4)  src/com/jitesh/earthquake/Quake.java ( supporting Quake setter and getter java class)

package com.jitesh.earthquake;

import java.util.Date;
import java.text.SimpleDateFormat;
import android.location.Location;

public class Quake {
  private Date date;
  private String details;
  private Location location;
  private double magnitude;
  private String link;

  public Date getDate() { return date; }
  public String getDetails() { return details; }
  public Location getLocation() { return location; }
  public double getMagnitude() { return magnitude; }
  public String getLink() { return link; }
  
  public Quake(Date _d, String _det, Location _loc, double _mag, String _link) {
    date = _d;
    details = _det;
    location = _loc;
    magnitude = _mag;
    link = _link;
  }

  @Override
  public String toString() {
    SimpleDateFormat sdf = new SimpleDateFormat("HH.mm");
    String dateString = sdf.format(date);
    return dateString + "<=> " + magnitude + "<=>" + details;
  }
}

5) res/layout/main.xml 

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

6) res/layout/quake_details.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:padding="10dp">
  <TextView
    android:id="@+id/quakeDetailsTextView"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:textSize="14sp"
    android:autoLink="all"
  />
</LinearLayout>

7)res/values/arrays.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string-array name="update_freq_options">
    <item>Every Minute</item>
    <item>5 minutes</item>
    <item>10 minutes</item>
    <item>15 minutes</item>
    <item>Every Hour</item>
  </string-array>

  <string-array name="magnitude">
    <item>3</item>
    <item>5</item>
    <item>6</item>
    <item>7</item>
    <item>8</item>
  </string-array>

  <string-array name="magnitude_options">
    <item>3</item>
    <item>5</item>
    <item>6</item>
    <item>7</item>
    <item>8</item>
  </string-array>

  <string-array name="update_freq_values">
    <item>1</item>
    <item>5</item>
    <item>10</item>
    <item>15</item>
    <item>60</item>
  </string-array>
</resources>

8) res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="app_name">Earthquake</string>
  <string name="quake_feed">
    http://earthquake.usgs.gov/eqcenter/catalogs/1day-M2.5.xml
  </string>
  <string name="menu_update">Refresh Earthquakes</string>
  <string name="auto_update_prompt">Auto Update?</string>
  <string name="update_freq_prompt">Update Frequency</string>
  <string name="min_quake_mag_prompt">Minimum Quake Magnitude</string>
  <string name="menu_preferences">Preferences</string>
</resources>

9)res/xml/userpreferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
  xmlns:android="http://schemas.android.com/apk/res/android">
  <CheckBoxPreference
    android:key="PREF_AUTO_UPDATE"
    android:title="Auto refresh"
    android:summary="Select to turn on automatic updating" 
    android:defaultValue="true"
  />                        
  <ListPreference
   android:key="PREF_UPDATE_FREQ"
   android:title="Refresh frequency"
   android:summary="Frequency at which to refresh earthquake list"
   android:entries="@array/update_freq_options"
   android:entryValues="@array/update_freq_values"
   android:dialogTitle="Refresh frequency"
   android:defaultValue="60"
  />
  <ListPreference
    android:key="PREF_MIN_MAG"
    android:title="Minimum magnitude"
    android:summary="Select the minimum magnitude earthquake to report"
    android:entries="@array/magnitude_options"
    android:entryValues="@array/magnitude"
    android:dialogTitle="Magnitude"
    android:defaultValue="3"
  />
</PreferenceScreen>

10) maifest file configurations

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.jitesh.earthquake"
  android:versionCode="1"
  android:versionName="1.0">
  <application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".Earthquake" android:label="@string/app_name">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <activity android:name=".Preferences" 
      android:label="Earthquake Preferences">
    </activity>
    <provider android:name=".EarthquakeProvider"
          android:authorities="com.jitesh.provider.earthquake" />
  </application>
  <uses-sdk android:minSdkVersion="7" />
  <uses-permission android:name="android.permission.INTERNET"/>
</manifest> 


after running the application on emulator we can see the output as follows as per the given below screen shots










Saturday, January 26, 2013

Android Content Provider

Content Provider==>


Every application has its own sandbox and cannot access data from other applications. If  access to functions not provided by its own sandbox is required, the application must explicitly declare permission upfront before installation.Android provides an interface called ContentProvider to act as a bridge between applications, enabling them to share and change each other’s data.A content provider allows a clean separation between the application layer and data layer. It requires a permission setting in the AndroidManifest XML file and can be accessed using a simple URI model. Some native databases Android makes available as content.

Creating a Custom Content Provider
After getting a sense of how to use a content provider, it is time to integrate one into the diary project used in previous recipes.This recipe shows how to expose diary entries to other selected applications.A custom content provider just extends the Android ContentProvider class, which contains six methods to optionally override:


> query()—Allows third-party applications to retrieve content.
> insert()—Allows third-party applications to insert content.
> update()—Allows third-party applications to update content.
> delete()—Allows third-party applications to delete content.
> getType()—Allows third-party applications to read each of URI structures supported.
> onCreate()—Creates a database instance to help retrieve the content.


import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.widget.TextView;

public class DataStorageTester extends Activity {
    /** Called when the activity is first created. */
TextView tv;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tv = (TextView) findViewById(R.id.output);
         String myUri = "content://com.jitesh.datastorage/diaries";
    Uri CONTENT_URI = Uri.parse(myUri);
        ContentResolver crInstance = getContentResolver(); //get a content Resolver instance
        Cursor c = crInstance.query(CONTENT_URI, null, null, null, null);
        startManagingCursor(c);
        StringBuilder sb = new StringBuilder();
        if(c.moveToFirst()){
        do{
        sb.append(c.getString(1)).append("\n");
       
        }while(c.moveToNext());
        }
        tv.setText(sb.toString());
       
    }
}



Thursday, January 24, 2013

Android Sliding Drawer Functionality

Android Sliding Drawer is an attractive bone in android for giving  a great feel and look to application. for this purpose


Create a project named SlidingDrawerDemo and copy this java code into SlidingDrawerDemo .java


package com.jitesh.slidingdrawerdemo;


import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SlidingDrawer;
import android.widget.Toast;
import android.widget.SlidingDrawer.OnDrawerCloseListener;
import android.widget.SlidingDrawer.OnDrawerOpenListener;

public class SlidingDrawerDemo extends Activity implements OnClickListener {

    Button slideButton,b1, b2,b3,b4;
    SlidingDrawer slidingDrawer;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        slideButton = (Button) findViewById(R.id.slideButton);
        slidingDrawer = (SlidingDrawer) findViewById(R.id.SlidingDrawer);
        b1 = (Button) findViewById(R.id.Button01);
        b2 = (Button) findViewById(R.id.Button02);
        b3 = (Button) findViewById(R.id.Button03);
        b4 = (Button) findViewById(R.id.Button04);

        b1.setOnClickListener(this);
        b2.setOnClickListener(this);
        b3.setOnClickListener(this);
        b4.setOnClickListener(this);

        slidingDrawer.setOnDrawerOpenListener(new OnDrawerOpenListener() {
            public void onDrawerOpened() {
                slideButton.setBackgroundResource(R.drawable.closearrow);
            }
        });

        slidingDrawer.setOnDrawerCloseListener(new OnDrawerCloseListener() {
            public void onDrawerClosed() {
                slideButton.setBackgroundResource(R.drawable.openarrow);
            }
        });
    }

    public void onClick(View v) {
        Button b = (Button)v;
        Toast.makeText(SlidingDrawerDemo.this, b.getText() + " Clicked", Toast.LENGTH_SHORT).show();
    }
}

correspondingly the android main.xml is represented the following elements 


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LinearLayout01"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:gravity="bottom"
    android:background="@drawable/bkg1">

    <TextView
        android:text="SlidingViewer Demo By Jitesh"
        android:gravity="center|center_vertical"
        android:textColor="#ff0000"
        android:textSize="25sp"
        android:textStyle="bold|italic"
        android:id="@+id/TextView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </TextView>

    <SlidingDrawer
        android:layout_width="wrap_content"
        android:id="@+id/SlidingDrawer"
        android:handle="@+id/slideButton"
        android:content="@+id/contentLayout"
        android:padding="10dip"
        android:layout_height="250dip"
        android:orientation="vertical">
         
        
            <Button android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/slideButton"
                android:background="@drawable/openarrow">
            </Button>
            <LinearLayout
                android:layout_width="wrap_content"
                android:id="@+id/contentLayout"
                android:orientation="vertical"
                android:gravity="center"
                android:padding="10dip"
                android:background="@drawable/android"
                android:layout_height="wrap_content">
                
            <Button
                android:id="@+id/Button01"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/yellow_button"
                android:layout_margin="2dp"
                android:text="Option1">
            </Button>
            <Button
                android:id="@+id/Button02"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/blue_button"
                android:layout_margin="2dp"
                android:text="Option2"></Button>
            <Button android:id="@+id/Button03"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_margin="2dp"
                android:background="@drawable/yellow_button"
                android:text="Option3">
            </Button>
            <Button android:id="@+id/Button04"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_margin="2dp"
                android:background="@drawable/blue_button"
                android:text="Option4">
            </Button>
           
        </LinearLayout>
    </SlidingDrawer>
</LinearLayout>







the used resource images are as follows

Android Fragment at 2.3

Make a project with the name HelloFragment and creat main class as MainActivity having the code


package jitesh.fragmentexample;

import jitesh.fragmentexample.R;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

make the layout main.xml as


<?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="horizontal" >
    <fragment
        android:id="@+id/frag_series"
        android:layout_width="200dip"
        android:layout_height="match_parent"
       
        class="jitesh.fragmentexample.ListFrag" />
    <fragment
        android:id="@+id/frag_capt"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="jitesh.fragmentexample.DetailFrag" />
</LinearLayout>

now create a claass ListFrag.java with the code


package jitesh.fragmentexample;

import jitesh.fragmentexample.R;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class ListFrag extends ListFragment{

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

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String[] values = new String[] { "Amit", "Nitin", "Chintan", "Lakshami", "Jitesh"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, values);
setListAdapter(adapter);
}

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
String item = (String) getListAdapter().getItem(position);
DetailFrag frag = (DetailFrag) getFragmentManager().findFragmentById(R.id.frag_capt);
if (frag != null && frag.isInLayout()) {
frag.setText(getCapt(item));
}
}

private String getCapt(String ship) {
if (ship.toLowerCase().contains("amit")) {
return "Amit ";
}
if (ship.toLowerCase().contains("nitin")) {
return "Nitin";
}
if (ship.toLowerCase().contains("chintan")) {
return "Chintan";
}
if (ship.toLowerCase().contains("lakshami")) {
return "Lakshami";
}
if (ship.toLowerCase().contains("jitesh")) {
return "Jitesh";
}
return "Jitesh Upadhyay";
}
}


create another class DetailFrag.java with code 

package jitesh.fragmentexample;


import jitesh.fragmentexample.R;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class DetailFrag extends Fragment{

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

}

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.detail_fragment, container, false);
return view;
}

public void setText(String item) {
TextView view = (TextView) getView().findViewById(R.id.captain);
view.setText(item);
}
}


the detail_fragment.xml has following elements

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/captain"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="center_horizontal|center_vertical"
        android:layout_marginTop="20dip"
        android:text="Jitesh Upadhyay"
        
        android:textSize="30dip" />
</LinearLayout>

the manifest should look like this

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jitesh.fragmentexample"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
         <activity
            android:name=".DetailActivity" >
        </activity>
    </application>

</manifest>

please follow the directory structure and dependencies for smooth running of the given code




Tuesday, January 22, 2013

Android BoradCast Reciever

Broadcast Receiver :


A broadcast receiver listens for relevant broadcast messages to trigger an event. Some examples of broadcasted events already sent from the OS are
> The camera button was pressed.
> The battery is low.
> A new application was installed.
A user-generated component can also send a broadcast, such as:
> A calculation was finished.
> A particular thread has started.

make a project with the name SimpleBoradcastReciever


src/com/jitesh/simplebroadcastreceiverer/SimpleActivity.java




package com.jitesh.simplebroadcastreceiver;


import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

public class SimpleActivity extends Activity {
    SimpleBroadcastReceiver intentReceiver =
        new SimpleBroadcastReceiver();

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

        IntentFilter intentFilter =
            new IntentFilter(Intent.ACTION_CAMERA_BUTTON);
        intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        registerReceiver(intentReceiver, intentFilter);

    }

    @Override
    protected void onDestroy() {
        unregisterReceiver(intentReceiver);
        super.onDestroy();
    }  
}

src/com/jitesh/simplebroadcastreceiverer/SimpleBroadcastReceiver .java


package com.jitesh.simplebroadcastreceiver;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class SimpleBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context rcvContext, Intent rcvIntent) {
        String action = rcvIntent.getAction();
        if (action.equals(Intent.ACTION_CAMERA_BUTTON)) {
            rcvContext.startService(new Intent(rcvContext,
                    SimpleService2.class));
        }
    }
}


src/com/jitesh/simplebroadcastreceiverer/SimpleService2  .java


package com.jitesh.simplebroadcastreceiver;


import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;

public class SimpleService2 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();      
    }
}


main.xml


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


manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jitesh.simplebroadcastreceiver"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".SimpleActivity"
            android:label="@string/title_activity_simple" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".SimpleService2" >
        </service>

        <receiver
            android:name=".SimpleBroadcastReceiver"
            android:enabled="true" >
        </receiver>
    </application>

</manifest>


Android Dialogs



Alerts provide a quick message to the user outside of the application’s main UI. It can be
in an overlay window such as a Toast or AlertDialog box. It can also be in the notification
bar at the top of the screen.




The Toast method has been introduced in the previous chapter in a compact form:
Toast.makeText(this, "text", Toast.LENGTH_SHORT).show();
It can also be written as a multiline command:
Toast tst = Toast.makeText(this, "text", Toast.LENGTH_SHORT);
tst.show();






Using an Alert Dialog Box
Providing a user with an alert and up to three buttons


AlertDialog dialog = new AlertDialog.Builder(this).create();
dialog.setMessage("Your final score: " + mScore + "/" + PERFECT_SCORE);
dialog.setButton(DialogInterface.BUTTON_POSITIVE, "Try this level again",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mScore = 0;
start_level();
}
});
dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Advance to next level",
new DialogInterface.OnClickListener() {