Friday, April 12, 2013

Android automatically detect internet connection status

If you have an android application that needs to sync data with a backend server but doesn't need the internet to be available all the time for it to work then you must know at all times whether your app has access to internet or not. As soon as you have internet connection you can get latest data from the server or post any changes saved in your app using HTTP service. In this example we extend the BroadcastReceiver to listen for any changes in network status and then find out whether the app has internet at that time. Please note that you have to specify the ACCESS_NETWORK_STATE in your android manifest permissions for this to work otherwise you will get java.lang.SecurityException: ConnectivityService: Neither user XXXXX nor current process has android.permission.ACCESS_NETWORK_STATE.

Android Application Manifest



















Android Application Layout






Android Application Main Activity

package com.samplecode;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

private static final String LOG_TAG = "CheckNetworkStatus";
private NetworkChangeReceiver receiver;
private boolean isConnected = false;
private TextView networkStatus;

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

IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
receiver = new NetworkChangeReceiver();
registerReceiver(receiver, filter);

networkStatus = (TextView) findViewById(R.id.networkStatus);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

@Override
protected void onDestroy() {
Log.v(LOG_TAG, "onDestory");
super.onDestroy();

unregisterReceiver(receiver);

}


public class NetworkChangeReceiver extends BroadcastReceiver {

@Override
public void onReceive(final Context context, final Intent intent) {

Log.v(LOG_TAG, "Receieved notification about network status");
isNetworkAvailable(context);

}


private boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
if(!isConnected){
Log.v(LOG_TAG, "Now you are connected to Internet!");
networkStatus.setText("Now you are connected to Internet!");
isConnected = true;
//do your processing here ---
//if you need to post any data to the server or get status
//update from the server
}
return true;
}
}
}
}
Log.v(LOG_TAG, "You are not connected to Internet!");
networkStatus.setText("You are not connected to Internet!");
isConnected = false;
return false;
}
}


}



Android automatically detect internet connection statusAndroid Internet connection status

Saturday, April 6, 2013

jQuery AJAX request and response example - Java Servlets, MySQL and JSON

Why not make AJAX request using plain JavaScript. Well guess what it's not programmer friendly, that's where all these JavaScript frameworks such as jQuery, ExtJs, Dojo etc. are good at. They encapsulate a lot of the underlying technology and provide us programmers with clean API's that has lot of config options and event triggers to handle anything from a simple form submit to something more complicated.


The method for AJAX request is jQuery.ajax( url [, settings] )

The $.ajax() method returns the jqXHR object. URL is a string containing the URL to which the request is sent and settings are a set of key/value pairs that configure the Ajax request. All settings are optional.


In this tutorial we are going to cover the following topics ...

  • Capture form data and send that to the Server using AJAX request
  • Intercept the request before it was sent and add some extra parameters
  • Check if our request to server was successful or not
  • Display the JSON response from the Server
  • Setup connection to MySQL from Tomcat Server
  • Create Java Servlets to process our AJAX request and access MySQL database 

jQuery AJAX request and response tutorial using Java Servlets
jQuery AJAX request and response tutorial using Java Servlets
jQuery AJAX request and response tutorial using Java Servlets
We have created a form that takes a country code and then makes an AJAX request to get more information about the country if the country code is valid. Also we intercept the request using beforeSend config to add some dummy data to the request and disable the SUBMIT button until we receive a response from the server. After we receive the response we display the results inside the ajaxResponse DIV tag.


Application HTML file - index.html


jQuery Ajax POST data Request and Response Example












jQuery Ajax Form data Submit Request















Response from jQuery Ajax Request





Application JavaScript file using jQuery - apps.js

$(document).ready(function() {

//Stops the submit request
$("#myAjaxRequestForm").submit(function(e){
e.preventDefault();
});

//checks for the button click event
$("#myButton").click(function(e){

//get the form data and then serialize that
dataString = $("#myAjaxRequestForm").serialize();

//get the form data using another method
var countryCode = $("input#countryCode").val();
dataString = "countryCode=" + countryCode;

//make the AJAX request, dataType is set to json
//meaning we are expecting JSON data in response from the server
$.ajax({
type: "POST",
url: "CountryInformation",
data: dataString,
dataType: "json",

//if received a response from the server
success: function( data, textStatus, jqXHR) {
//our country code was correct so we have some information to display
if(data.success){
$("#ajaxResponse").html("");
$("#ajaxResponse").append("Country Code: " + data.countryInfo.code + "
");
$("#ajaxResponse").append("Country Name: " + data.countryInfo.name + "
");
$("#ajaxResponse").append("Continent: " + data.countryInfo.continent + "
");
$("#ajaxResponse").append("Region: " + data.countryInfo.region + "
");
$("#ajaxResponse").append("Life Expectancy: " + data.countryInfo.lifeExpectancy + "
");
$("#ajaxResponse").append("GNP: " + data.countryInfo.gnp + "
");
}
//display error message
else {
$("#ajaxResponse").html("

Country code in Invalid!

");
}
},

//If there was no resonse from the server
error: function(jqXHR, textStatus, errorThrown){
console.log("Something really bad happened " + textStatus);
$("#ajaxResponse").html(jqXHR.responseText);
},

//capture the request before it was sent to server
beforeSend: function(jqXHR, settings){
//adding some Dummy data to the request
settings.data += "&dummyData=whatever";
//disable the button until we get the response
$('#myButton').attr("disabled", true);
},

//this is called after the response or error functions are finsihed
//so that we can take some action
complete: function(jqXHR, textStatus){
//enable the button
$('#myButton').attr("disabled", false);
}

});
});

});

Application config file - web.xml


jQuery_Ajax_Request

index.html
index.htm
index.jsp
default.html
default.htm
default.jsp


Get Information about Country - jQuery Ajax Request
CountryInformation
CountryInformation
com.as400samplecode.CountryInformation


CountryInformation
/CountryInformation





jQuery AJAX request and response tutorial using Java Servlets

Application context file for MySQL connection - context.xml




Java bean containing Country Information - Country.java

package com.as400samplecode;

public class Country {

String code = null;
String name = null;
String continent = null;
String region = null;
Double lifeExpectancy = null;
Double gnp = null;

public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContinent() {
return continent;
}
public void setContinent(String continent) {
this.continent = continent;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public Double getLifeExpectancy() {
return lifeExpectancy;
}
public void setLifeExpectancy(Double lifeExpectancy) {
this.lifeExpectancy = lifeExpectancy;
}
public Double getGnp() {
return gnp;
}
public void setGnp(Double gnp) {
this.gnp = gnp;
}


}

Java Servlet processing jQuery AJAX request - CountryInformation.java

package com.as400samplecode;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

public class CountryInformation extends HttpServlet {

private static final long serialVersionUID = 1L;

public CountryInformation() {
super();
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String countryCode = request.getParameter("countryCode");

PrintWriter out = response.getWriter();
response.setContentType("text/html");
response.setHeader("Cache-control", "no-cache, no-store");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "-1");

response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST");
response.setHeader("Access-Control-Allow-Headers", "Content-Type");
response.setHeader("Access-Control-Max-Age", "86400");

Gson gson = new Gson();
JsonObject myObj = new JsonObject();

Country countryInfo = getInfo(countryCode);
JsonElement countryObj = gson.toJsonTree(countryInfo);
if(countryInfo.getName() == null){
myObj.addProperty("success", false);
}
else {
myObj.addProperty("success", true);
}
myObj.add("countryInfo", countryObj);
out.println(myObj.toString());

out.close();

}

//Get Country Information
private Country getInfo(String countryCode) {

Country country = new Country();
Connection conn = null;
PreparedStatement stmt = null;
String sql = null;

try {
Context ctx = (Context) new InitialContext().lookup("java:comp/env");
conn = ((DataSource) ctx.lookup("jdbc/mysql")).getConnection();

sql = "Select * from COUNTRY where code = ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1, countryCode.trim());
ResultSet rs = stmt.executeQuery();

while(rs.next()){
country.setCode(rs.getString("code").trim());
country.setName(rs.getString("name").trim());
country.setContinent(rs.getString("continent").trim());
country.setRegion(rs.getString("region").trim());
country.setLifeExpectancy(rs.getString("lifeExpectancy") == null ? new Double(0) : Double.parseDouble(rs.getString("lifeExpectancy").trim()));
country.setGnp(rs.getString("gnp") == null ? new Double(0) : Double.parseDouble(rs.getString("gnp").trim()));
}

rs.close();
stmt.close();
stmt = null;


conn.close();
conn = null;

}
catch(Exception e){System.out.println(e);}

finally {

if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlex) {
// ignore -- as we can't do anything about it here
}

stmt = null;
}

if (conn != null) {
try {
conn.close();
} catch (SQLException sqlex) {
// ignore -- as we can't do anything about it here
}

conn = null;
}
}

return country;

}

}
 
Create the database like that
 
 
You can download the source code JQuery Ajax Request with Mysql

Thursday, April 4, 2013

Android Database Content Provider Example using SQLite Database

Android applications can access data directly from a SQLite database using the database helper but for other applications to get access to the same data you have to create a Content Provider. Content Providers encapsulate the data access, provide security using the Android Manifest and standardize the access via a Content URI. If the data is used only by your application there is no need to create a content provider but you can always do that in case a need that arises in the future.

The contentProvider must implement the following methods query(), insert(), update(), delete(), getType() and onCreate() to provide access to the underlying data. If you don't implement the delete method just send an exception to let the application know or if you don't get an URI match. If you have done SQLite database access using the database helper you will find there is not much difference here. All you have to do it create a provider that matches URIs and then figures out what to do with the request.

In this example we will create a simple maintenance program to maintain a list of countries. The access to the country database will be thru the Content Provider that will implement all the CRUD functions. On the screen we will display an existing list of countries and let the user add, update and delete a country. Here is the step by step process to implement the above mentioned functionality using the Content Provider.

Step 1: Create the SQLite database Object - CountriesDb.java

package com.as400samplecode;

import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

public class CountriesDb {

public static final String KEY_ROWID = "_id";
public static final String KEY_CODE = "code";
public static final String KEY_NAME = "name";
public static final String KEY_CONTINENT = "continent";

private static final String LOG_TAG = "CountriesDb";
public static final String SQLITE_TABLE = "Country";

private static final String DATABASE_CREATE =
"CREATE TABLE if not exists " + SQLITE_TABLE + " (" +
KEY_ROWID + " integer PRIMARY KEY autoincrement," +
KEY_CODE + "," +
KEY_NAME + "," +
KEY_CONTINENT + "," +
" UNIQUE (" + KEY_CODE +"));";

public static void onCreate(SQLiteDatabase db) {
Log.w(LOG_TAG, DATABASE_CREATE);
db.execSQL(DATABASE_CREATE);
}

public static void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(LOG_TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS " + SQLITE_TABLE);
onCreate(db);
}

}

Step 2: Create the SQLite database Helper - MyDatabaseHelper.java

package com.as400samplecode;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MyDatabaseHelper extends SQLiteOpenHelper {

private static final String DATABASE_NAME = "TheWorld";
private static final int DATABASE_VERSION = 1;

MyDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

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

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
CountriesDb.onUpgrade(db, oldVersion, newVersion);
}


}

Step 3: Create the ContentProvider - MyContentProvider.java

package com.as400samplecode;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

public class MyContentProvider extends ContentProvider{

private MyDatabaseHelper dbHelper;

private static final int ALL_COUNTRIES = 1;
private static final int SINGLE_COUNTRY = 2;

// authority is the symbolic name of your provider
// To avoid conflicts with other providers, you should use
// Internet domain ownership (in reverse) as the basis of your provider authority.
private static final String AUTHORITY = "com.as400samplecode.contentprovider";

// create content URIs from the authority by appending path to database table
public static final Uri CONTENT_URI =
Uri.parse("content://" + AUTHORITY + "/countries");

// a content URI pattern matches content URIs using wildcard characters:
// *: Matches a string of any valid characters of any length.
// #: Matches a string of numeric characters of any length.
private static final UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, "countries", ALL_COUNTRIES);
uriMatcher.addURI(AUTHORITY, "countries/#", SINGLE_COUNTRY);
}

// system calls onCreate() when it starts up the provider.
@Override
public boolean onCreate() {
// get access to the database helper
dbHelper = new MyDatabaseHelper(getContext());
return false;
}

//Return the MIME type corresponding to a content URI
@Override
public String getType(Uri uri) {

switch (uriMatcher.match(uri)) {
case ALL_COUNTRIES:
return "vnd.android.cursor.dir/vnd.com.as400samplecode.contentprovider.countries";
case SINGLE_COUNTRY:
return "vnd.android.cursor.item/vnd.com.as400samplecode.contentprovider.countries";
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}

// The insert() method adds a new row to the appropriate table, using the values
// in the ContentValues argument. If a column name is not in the ContentValues argument,
// you may want to provide a default value for it either in your provider code or in
// your database schema.
@Override
public Uri insert(Uri uri, ContentValues values) {

SQLiteDatabase db = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case ALL_COUNTRIES:
//do nothing
break;
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
long id = db.insert(CountriesDb.SQLITE_TABLE, null, values);
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(CONTENT_URI + "/" + id);
}

// The query() method must return a Cursor object, or if it fails,
// throw an Exception. If you are using an SQLite database as your data storage,
// you can simply return the Cursor returned by one of the query() methods of the
// SQLiteDatabase class. If the query does not match any rows, you should return a
// Cursor instance whose getCount() method returns 0. You should return null only
// if an internal error occurred during the query process.
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {

SQLiteDatabase db = dbHelper.getWritableDatabase();
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(CountriesDb.SQLITE_TABLE);

switch (uriMatcher.match(uri)) {
case ALL_COUNTRIES:
//do nothing
break;
case SINGLE_COUNTRY:
String id = uri.getPathSegments().get(1);
queryBuilder.appendWhere(CountriesDb.KEY_ROWID + "=" + id);
break;
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}

Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, sortOrder);
return cursor;

}

// The delete() method deletes rows based on the seletion or if an id is
// provided then it deleted a single row. The methods returns the numbers
// of records delete from the database. If you choose not to delete the data
// physically then just update a flag here.
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {

SQLiteDatabase db = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case ALL_COUNTRIES:
//do nothing
break;
case SINGLE_COUNTRY:
String id = uri.getPathSegments().get(1);
selection = CountriesDb.KEY_ROWID + "=" + id
+ (!TextUtils.isEmpty(selection) ?
" AND (" + selection + ')' : "");
break;
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
int deleteCount = db.delete(CountriesDb.SQLITE_TABLE, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return deleteCount;
}

// The update method() is same as delete() which updates multiple rows
// based on the selection or a single row if the row id is provided. The
// update method returns the number of updated rows.
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case ALL_COUNTRIES:
//do nothing
break;
case SINGLE_COUNTRY:
String id = uri.getPathSegments().get(1);
selection = CountriesDb.KEY_ROWID + "=" + id
+ (!TextUtils.isEmpty(selection) ?
" AND (" + selection + ')' : "");
break;
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
int updateCount = db.update(CountriesDb.SQLITE_TABLE, values, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return updateCount;
}

}

Step 4: Row Layout for Country Display - country_info.xml


















Step 5: Main Layout with ListView - activity_main.xml




Step 6: Main Activity using LoaderManager for Country List - MainActivity.java

The list of countries is displayed in a ListView using the CursorLoader that queries the ContentResolver and returns a Cursor. This class implements the Loader protocol in a standard way for querying cursors, building on AsyncTaskLoader to perform the cursor query on a background thread so that it does not block the application's UI. After the loader has finished its loading just swap the new cursor from the Content Provider and return the old Cursor.
package com.as400samplecode;

import android.os.Bundle;
import android.app.Activity;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
import android.app.LoaderManager;

public class MainActivity extends Activity implements
LoaderManager.LoaderCallbacks{

private SimpleCursorAdapter dataAdapter;

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

displayListView();

Button add = (Button) findViewById(R.id.add);
add.setOnClickListener(new OnClickListener() {

public void onClick(View v) {
// starts a new Intent to add a Country
Intent countryEdit = new Intent(getBaseContext(), CountryEdit.class);
Bundle bundle = new Bundle();
bundle.putString("mode", "add");
countryEdit.putExtras(bundle);
startActivity(countryEdit);
}
});

}

@Override
protected void onResume() {
super.onResume();
//Starts a new or restarts an existing Loader in this manager
getLoaderManager().restartLoader(0, null, this);
}

private void displayListView() {


// The desired columns to be bound
String[] columns = new String[] {
CountriesDb.KEY_CODE,
CountriesDb.KEY_NAME,
CountriesDb.KEY_CONTINENT
};

// the XML defined views which the data will be bound to
int[] to = new int[] {
R.id.code,
R.id.name,
R.id.continent,
};

// create an adapter from the SimpleCursorAdapter
dataAdapter = new SimpleCursorAdapter(
this,
R.layout.country_info,
null,
columns,
to,
0);

// get reference to the ListView
ListView listView = (ListView) findViewById(R.id.countryList);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
//Ensures a loader is initialized and active.
getLoaderManager().initLoader(0, null, this);


listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
Cursor cursor = (Cursor) listView.getItemAtPosition(position);

// display the selected country
String countryCode =
cursor.getString(cursor.getColumnIndexOrThrow(CountriesDb.KEY_CODE));
Toast.makeText(getApplicationContext(),
countryCode, Toast.LENGTH_SHORT).show();

String rowId =
cursor.getString(cursor.getColumnIndexOrThrow(CountriesDb.KEY_ROWID));

// starts a new Intent to update/delete a Country
// pass in row Id to create the Content URI for a single row
Intent countryEdit = new Intent(getBaseContext(), CountryEdit.class);
Bundle bundle = new Bundle();
bundle.putString("mode", "update");
bundle.putString("rowId", rowId);
countryEdit.putExtras(bundle);
startActivity(countryEdit);

}
});

}

// This is called when a new Loader needs to be created.
@Override
public Loader onCreateLoader(int id, Bundle args) {
String[] projection = {
CountriesDb.KEY_ROWID,
CountriesDb.KEY_CODE,
CountriesDb.KEY_NAME,
CountriesDb.KEY_CONTINENT};
CursorLoader cursorLoader = new CursorLoader(this,
MyContentProvider.CONTENT_URI, projection, null, null, null);
return cursorLoader;
}

@Override
public void onLoadFinished(Loader loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
dataAdapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
dataAdapter.swapCursor(null);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}

Step 7: Detail Layout for Insert,Update and Delete - detail_page.xml





















Step 8: Detail Activity implementing CRUD operations - CountryEdit.java

package com.as400samplecode;

import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

public class CountryEdit extends Activity implements OnClickListener{

private Spinner continentList;
private Button save, delete;
private String mode;
private EditText code, name;
private String id;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detail_page);

// get the values passed to the activity from the calling activity
// determine the mode - add, update or delete
if (this.getIntent().getExtras() != null){
Bundle bundle = this.getIntent().getExtras();
mode = bundle.getString("mode");
}

// get references to the buttons and attach listeners
save = (Button) findViewById(R.id.save);
save.setOnClickListener(this);
delete = (Button) findViewById(R.id.delete);
delete.setOnClickListener(this);

code = (EditText) findViewById(R.id.code);
name = (EditText) findViewById(R.id.name);


// create a dropdown for users to select various continents
continentList = (Spinner) findViewById(R.id.continentList);
ArrayAdapter adapter = ArrayAdapter.createFromResource(this,
R.array.continent_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
continentList.setAdapter(adapter);

// if in add mode disable the delete option
if(mode.trim().equalsIgnoreCase("add")){
delete.setEnabled(false);
}
// get the rowId for the specific country
else{
Bundle bundle = this.getIntent().getExtras();
id = bundle.getString("rowId");
loadCountryInfo();
}

}

public void onClick(View v) {

// get values from the spinner and the input text fields
String myContinent = continentList.getSelectedItem().toString();
String myCode = code.getText().toString();
String myName = name.getText().toString();

// check for blanks
if(myCode.trim().equalsIgnoreCase("")){
Toast.makeText(getBaseContext(), "Please ENTER country code", Toast.LENGTH_LONG).show();
return;
}

// check for blanks
if(myName.trim().equalsIgnoreCase("")){
Toast.makeText(getBaseContext(), "Please ENTER country name", Toast.LENGTH_LONG).show();
return;
}


switch (v.getId()) {
case R.id.save:
ContentValues values = new ContentValues();
values.put(CountriesDb.KEY_CODE, myCode);
values.put(CountriesDb.KEY_NAME, myName);
values.put(CountriesDb.KEY_CONTINENT, myContinent);

// insert a record
if(mode.trim().equalsIgnoreCase("add")){
getContentResolver().insert(MyContentProvider.CONTENT_URI, values);
}
// update a record
else {
Uri uri = Uri.parse(MyContentProvider.CONTENT_URI + "/" + id);
getContentResolver().update(uri, values, null, null);
}
finish();
break;

case R.id.delete:
// delete a record
Uri uri = Uri.parse(MyContentProvider.CONTENT_URI + "/" + id);
getContentResolver().delete(uri, null, null);
finish();
break;

// More buttons go here (if any) ...

}
}

// based on the rowId get all information from the Content Provider
// about that country
private void loadCountryInfo(){

String[] projection = {
CountriesDb.KEY_ROWID,
CountriesDb.KEY_CODE,
CountriesDb.KEY_NAME,
CountriesDb.KEY_CONTINENT};
Uri uri = Uri.parse(MyContentProvider.CONTENT_URI + "/" + id);
Cursor cursor = getContentResolver().query(uri, projection, null, null,
null);
if (cursor != null) {
cursor.moveToFirst();
String myCode = cursor.getString(cursor.getColumnIndexOrThrow(CountriesDb.KEY_CODE));
String myName = cursor.getString(cursor.getColumnIndexOrThrow(CountriesDb.KEY_NAME));
String myContinent = cursor.getString(cursor.getColumnIndexOrThrow(CountriesDb.KEY_CONTINENT));
code.setText(myCode);
name.setText(myName);
continentList.setSelection(getIndex(continentList, myContinent));
}


}

Step 9: Define Strings and Arrays - strings.xml



SQLite Database Content Provider
Settings

Add a new Country
Country Information
Code
Name
Save
Delete
Choose Continent


Africa
Antartica
Asia
Europe
North America
Oceania
South America



Step 10: Define Android Manifest file
















 


Android Database Content Provider Example
Android Database Content Provider Insert Record
Android ListView using CursorLoader and Content Provider

Android ViewFlipper Animation example

ViewFlipper is a subclass of ViewAnimator that makes it easy to animate a bunch of views that are added to it. It only displays one child view at a time and you can also set it to rotate the views automatically. Just keep in mind that if you have duration set for your animation alpha then the flipper duration should be greater than that otherwise the view will change even before it completely comes into focus.

String Resource - strings.xml



ViewFlipper
Settings

#ffe4c4
#cdc9c9
#f0fff0


Animation Resource - anim/slide_in_left.xml





Animation Resource - anim/slide_out_left.xml





Layout Resource for the Main Activity





















Main Activity

package com.example.viewflipper;

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

public class MainActivity extends Activity implements OnClickListener{

private ToggleButton myToggleButton;
private Button previousView, nextView;
private Animation slide_in_left, slide_in_right, slide_out_left, slide_out_right;

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

//get references to our buttons and toogle button
myToggleButton = (ToggleButton) findViewById(R.id.toggleButton);
previousView = (Button) findViewById(R.id.previousView);
nextView = (Button) findViewById(R.id.nextView);

//attach onClick listeners to the buttons
myToggleButton.setOnClickListener(this);
previousView.setOnClickListener(this);
nextView.setOnClickListener(this);

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

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

@Override
public void onClick(View v) {

//get reference to the view flipper
ViewFlipper myViewFlipper = (ViewFlipper) findViewById(R.id.myViewFlipper);
//set the animation for the view that enters the screen
myViewFlipper.setInAnimation(slide_in_right);
//set the animation for the view leaving th screen
myViewFlipper.setOutAnimation(slide_out_left);

switch (v.getId()) {
case R.id.nextView:
//show the next view
myViewFlipper.showNext();
break;

case R.id.previousView:
//show the next view
myViewFlipper.setInAnimation(slide_in_left);
myViewFlipper.setOutAnimation(slide_out_right);
myViewFlipper.showNext();
break;

case R.id.toggleButton:

if(myToggleButton.isChecked()){
//set flipper interval
myViewFlipper.setFlipInterval(6000);
//start flipping the views
myViewFlipper.startFlipping();
}
else{
//stop flipping the views
myViewFlipper.stopFlipping();
}
break;

}
}

}



Android ViewFlipper Animation exampleAndroid ViewFlipper new ViewAndroid ViewFlipper auto flip

You can download the source code View Flipper

Handling Shake Events

Here is my implementation of shake detection for android.

package com.android.sensor;

import java.util.List;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;

public class AccelerometerListener implements SensorEventListener {

private SensorManager sensorManager;
private List sensors;
private Sensor sensor;
private long lastUpdate = -1;
private long currentTime = -1;

private float last_x, last_y, last_z;
private float current_x, current_y, current_z, currenForce;
private static final int FORCE_THRESHOLD = 900;
private final int DATA_X = SensorManager.DATA_X;
private final int DATA_Y = SensorManager.DATA_Y;
private final int DATA_Z = SensorManager.DATA_Z;

public AccelerometerListener(Activity parent) {
SensorManager sensorService = (SensorManager) parent.getSystemService(Context.SENSOR_SERVICE);
this.sensorManager = sensorManager;
this.subscriber = subscriber;
this.sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
if (sensors.size() > 0) {
sensor = sensors.get(0);
}
}
public void start () {
if (sensor!=null) {
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
}
}

public void stop () {
sensorManager.unregisterListener(this);
}

public void onAccuracyChanged(Sensor s, int valu) {


}
public void onSensorChanged(SensorEvent event) {

if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER || event.values.length < 3)
return;

currentTime = System.currentTimeMillis();

if ((currentTime - lastUpdate) > 100) {
long diffTime = (currentTime - lastUpdate);
lastUpdate = currentTime;

current_x = event.values[DATA_X];
current_y = event.values[DATA_Y];
current_z = event.values[DATA_Z];

currenForce = Math.abs(current_x+current_y+current_z - last_x - last_y - last_z) / diffTime * 10000;

if (currenForce > FORCE_THRESHOLD) {

// Device has been shaken now go on and do something
// you could now inform the parent activity ...

}
last_x = current_x;
last_y = current_y;
last_z = current_z;

}
}

}

Wednesday, April 3, 2013

Android ListView Checkbox Example - OnItemClickListener() and OnClickListener()

In this example we are going to place a Checkbox inside the ListView row along with some Text. The concept is the same if you want to place a button or an image or all of them. The first issue that I faced when placing a Checkbox is the OnItemClickListener stopped working. To get around that you have to specify android:focusable="false" and android:focusableInTouchMode="false" for your checkbox view. Now to listen for the click event on the checkbox you have attach the OnClickListener when the you are inflating the custom layout inside your getView() method. To find out what all checkboxes are selected just loop thru the ArrayList that is being maintained by listening to the onClick event for the checkbox.

Source for Activity - ListViewCheckboxesActivity.java

package com.as400samplecode;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class ListViewCheckboxesActivity extends Activity {

MyCustomAdapter dataAdapter = null;

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

//Generate list View from ArrayList
displayListView();

checkButtonClick();

}

private void displayListView() {

//Array list of countries
ArrayList countryList = new ArrayList();
Country country = new Country("AFG","Afghanistan",false);
countryList.add(country);
country = new Country("ALB","Albania",true);
countryList.add(country);
country = new Country("DZA","Algeria",false);
countryList.add(country);
country = new Country("ASM","American Samoa",true);
countryList.add(country);
country = new Country("AND","Andorra",true);
countryList.add(country);
country = new Country("AGO","Angola",false);
countryList.add(country);
country = new Country("AIA","Anguilla",false);
countryList.add(country);

//create an ArrayAdaptar from the String Array
dataAdapter = new MyCustomAdapter(this,
R.layout.country_info, countryList);
ListView listView = (ListView) findViewById(R.id.listView1);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);


listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Country country = (Country) parent.getItemAtPosition(position);
Toast.makeText(getApplicationContext(),
"Clicked on Row: " + country.getName(),
Toast.LENGTH_LONG).show();
}
});

}

private class MyCustomAdapter extends ArrayAdapter {

private ArrayList countryList;

public MyCustomAdapter(Context context, int textViewResourceId,
ArrayList countryList) {
super(context, textViewResourceId, countryList);
this.countryList = new ArrayList();
this.countryList.addAll(countryList);
}

private class ViewHolder {
TextView code;
CheckBox name;
}

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

ViewHolder holder = null;
Log.v("ConvertView", String.valueOf(position));

if (convertView == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.country_info, null);

holder = new ViewHolder();
holder.code = (TextView) convertView.findViewById(R.id.code);
holder.name = (CheckBox) convertView.findViewById(R.id.checkBox1);
convertView.setTag(holder);

holder.name.setOnClickListener( new View.OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v ;
Country country = (Country) cb.getTag();
Toast.makeText(getApplicationContext(),
"Clicked on Checkbox: " + cb.getText() +
" is " + cb.isChecked(),
Toast.LENGTH_LONG).show();
country.setSelected(cb.isChecked());
}
});
}
else {
holder = (ViewHolder) convertView.getTag();
}

Country country = countryList.get(position);
holder.code.setText(" (" + country.getCode() + ")");
holder.name.setText(country.getName());
holder.name.setChecked(country.isSelected());
holder.name.setTag(country);

return convertView;

}

}

private void checkButtonClick() {


Button myButton = (Button) findViewById(R.id.findSelected);
myButton.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
StringBuffer responseText = new StringBuffer();
responseText.append("The following were selected...\n");

ArrayList countryList = dataAdapter.countryList;
use for loop i=0 to < countryList.size(){
Country country = countryList.get(i);
if(country.isSelected()){
responseText.append("\n" + country.getName());
}
}

Toast.makeText(getApplicationContext(),
responseText, Toast.LENGTH_LONG).show();

}
});

}

}

Source for POJO - Country.java

 

package com.as400samplecode;

public class Country {

String code = null;
String name = null;
boolean selected = false;

public Country(String code, String name, boolean selected) {
super();
this.code = code;
this.name = name;
this.selected = selected;
}

public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}

}

Source for Main Screen Layout - main.xml

 







Source for Custom List Layout - country_info.xml

 








Source for application variables - strings.xml

 



ListView Checkboxes

Some North American Countries!



Source for application manifest - AndroidManifest.xml

 


















Android ListView Checkbox Example
Android ListView Checkbox Example
Android ListView Checkbox Example

Android SQLITE query selection example

In this example we are going to learn how to create a SQLite database adapter that will perform the basic operations such as creating the table, upgrading the database as well as providing access to the data based on given input parameters. SQLiteDatabase has methods to create, delete, execute SQL commands, and perform other common database management tasks.  To query a given table and return a Cursor over the result set you can use the following method.

  • public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)

Parameters
  • table 
    • The table name to compile the query against.
  • columns 
    • A list of which columns to return. Passing null will return all columns, which is discouraged to prevent reading data from storage that isn't going to be used.
  • selection 
    • A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
  • selectionArgs 
    • You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.
  • groupBy 
    • A filter declaring how to group rows, formatted as an SQL GROUP BY clause (excluding the GROUP BY itself). Passing null will cause the rows to not be grouped.
  • having 
    • A filter declare which row groups to include in the cursor, if row grouping is being used, formatted as an SQL HAVING clause (excluding the HAVING itself). Passing null will cause all row groups to be included, and is required when row grouping is not being used.
  • orderBy 
    • How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order, which may be unordered.
  • limit 
    • Limits the number of rows returned by the query, formatted as LIMIT clause. Passing null denotes no LIMIT clause.
Returns
  • A Cursor object, which is positioned before the first entry. Note that Cursors are not synchronized


package com.as400samplecode.Util;

import java.io.StringReader;
import java.util.ArrayList;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import android.util.Log;

public class OrderDetailDbAdapter {

public static final String KEY_ROWID = "_id";
public static final String KEY_STATUS = "statusCode";
public static final String KEY_COMPANY = "company";
public static final String KEY_ORDER = "orderNumber";
public static final String KEY_SEQ = "sequence";
public static final String KEY_ITEM = "item";
public static final String KEY_DESCRIPTION = "description";
public static final String KEY_QUANTITY = "quantity";
public static final String KEY_PRICE = "price";

private static final String TAG = "OrderDetailDbAdapter";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;

private static final String DATABASE_NAME = "OrderDatabase";
private static final String SQLITE_TABLE = "OrderDetail";
private static final int DATABASE_VERSION = 1;

private static final String DATABASE_CREATE =
"CREATE TABLE " + SQLITE_TABLE + " (" +
KEY_ROWID + " integer PRIMARY KEY autoincrement," +
KEY_STATUS + "," +
KEY_COMPANY + "," +
KEY_ORDER + "," +
KEY_SEQ + "," +
KEY_ITEM + "," +
KEY_DESCRIPTION + "," +
KEY_QUANTITY + "," +
KEY_PRICE + "," +
" UNIQUE (" + KEY_COMPANY + "," + KEY_ORDER + "," + KEY_SEQ + "," + KEY_ITEM +"));";


private final Context mCtx;

private static class DatabaseHelper extends SQLiteOpenHelper {

DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}


@Override
public void onCreate(SQLiteDatabase db) {
Log.w(TAG, DATABASE_CREATE);
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 " + SQLITE_TABLE);
onCreate(db);
}
}

public OrderDetailDbAdapter(Context ctx) {
this.mCtx = ctx;
}

public OrderDetailDbAdapter open() throws SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}

public void close() {
if (mDbHelper != null) {
mDbHelper.close();
}
}


public long createOrderDetail() {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_STATUS, "A");
initialValues.put(KEY_COMPANY, "1");
initialValues.put(KEY_ORDER, "123");
initialValues.put(KEY_SEQ, "1");
initialValues.put(KEY_ITEM,"ABC");
initialValues.put(KEY_DESCRIPTION, "Item ABC description");
initialValues.put(KEY_QUANTITY, "100");
initialValues.put(KEY_PRICE, "99.99");
return mDb.insert(SQLITE_TABLE, null, initialValues);
}

public boolean deleteOrderDetail(long rowId) {

return mDb.delete(SQLITE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}

public ArrayList getOrderDetails(String company, String orderNumber) throws SQLException {


ArrayList orderDetailList = new ArrayList();
Cursor mCursor =


mDb.query(true, SQLITE_TABLE, new String[] {
KEY_ROWID,
KEY_COMPANY,
KEY_ORDER,
KEY_SEQ,
KEY_ITEM,
KEY_DESCRIPTION,
KEY_QUANTITY,
KEY_PRICE,},
KEY_COMPANY + "=?" + " and " +
KEY_ORDER + "=?",
new String[] {company,orderNumber},
null, null, KEY_ITEM , null);


if (mCursor.moveToFirst()) {
do {
OrderDetail orderDetail = new OrderDetail();
orderDetail.setItem(mCursor.getString(mCursor.getColumnIndexOrThrow(KEY_ITEM)));
orderDetail.setDescription(mCursor.getString(mCursor.getColumnIndexOrThrow(KEY_DESCRIPTION)));
orderDetail.setQuantity(mCursor.getString(mCursor.getColumnIndexOrThrow(KEY_QUANTITY)));
orderDetail.setPrice(mCursor.getString(mCursor.getColumnIndexOrThrow(KEY_PRICE)));
orderDetailList.add(orderDetail);
} while (mCursor.moveToNext());
}
if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
return orderDetailList;


}


public boolean deleteAllOrderDetails() {

int doneDelete = 0;
doneDelete = mDb.delete(SQLITE_TABLE, null , null);
Log.w(TAG, Integer.toString(doneDelete));
return doneDelete > 0;

}

}

 

Copyright @ 2013 Android Developers Tipss.