Monday, 19 March 2012

The Bugs which i have experienced and analysed


1. created a table without the primary key name as _id
 java.lang.IllegalArgumentException: column '_id' does not exist
        at android.database.AbstractCursor.getColumnIndexOrThrow(Abstr

2. changed to _id but table not replaced
android.database.sqlite.SQLiteException: no such column: _id

3. Used button first and Edittext next
caused by java.lang.classcastexception android.widget.edittext
 <requestFocus />

4. Should not close the database at needed times
java.lang.IllegalStateException: attempt to acquire a reference on a close SQLiteClosable

5. I used two buttons with onclicklistener
E/AndroidRuntime( 8908): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sampleapp.application/com.sampleapp.application.LoginActivity}: java.lang.ClassCastException: android.widget.EditText

6. I tried to display Toast with integer value
android.content.res.Resources$NotFoundException: String resource ID #0x2f
        at android.content.res.Resources.getText(Resources.java:200)
        at android.widget.Toast.makeText(Toast.java:258)

7. Toast is not working, rather this msg displayed in log
I/NotificationService(   51): enqueueToast pkg=com.sampleapp.application callback=android.app.ITransientNotification$Stub$Proxy@44d30338 duration=0

8. java.net.SocketException: Permission denied (maybe missing INTERNET permission)
    add the permission in Android.manifest file "android.permission.INTERNET"

9.  Uncaught handler: thread main exiting due to uncaught exception
 android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.CALL dat=9977666612 }

10. W/PhoneUtils(  120): Exception from phone.dial()
W/PhoneUtils(  120): com.android.internal.telephony.CallStateException: cannot dial in current state

11.  com.android.internal.telephony.CallStateException: cannot dial in current state
                  This error comes while we dial mobile numbers in a sequence.



Saturday, 17 March 2012

More to learn

API Level is an integer value that uniquely identifies the framework API. (version :Android 2.1.x, API Level: 7)


INTENT

Three of the core components of an application — activities, services, and broadcast receivers — are activated through messages, called intents.
Intent i = new Intent(Intent.ACTION_VIEW); 
startActivity(i);

<intent-filter>    -> Specifies the types of intents

UNITS OF MEASUREMENT

px    Pixels - corresponds to actual pixels on the screen.
in    Inches - based on the physical size of the screen.
mm    Millimeters - based on the physical size of the screen.
pt    Points - 1/72 of an inch based on the physical size of the screen.

dp    Density-independent Pixels - an abstract unit that is based on the physical density of the screen.
These units are relative to a 160 dpi screen, so one dp is one pixel on a 160 dpi screen.
The ratio of dp-to-pixel will change with the screen density, but not necessarily in direct proportion.
Note: The compiler accepts both "dip" and "dp", though "dp" is more consistent with "sp".

sp    Scale-independent Pixels - this is like the dp unit, but it is also scaled by the user's font size preference.
It is recommend you use this unit when specifying font sizes, so they will be adjusted for
both the screen density and user's preference.

Toast

  1. A toast notification ia similar to popup
  2. automatically fades in and out, and does not accept interaction events.
  3. A toast can be created and displayed from an Activity or Service
  4. It has three parameters, Ex: Toast toast = Toast.makeText(context, text, duration);
  5. Display it using, "toast.show();"
  6. Constants   LENGTH_LONG , LENGTH_SHORT

ArrayAdapter http://www.vogella.de/articles/AndroidListView/article.html

  1. An adapter which is used to ListView the String must extend BaseAdapter.
  2. Among several standard adapters, important are ArrayAdapter and CursorAdapter. 
  3. ArrayAdapter can handle data based on Arrays or Lists.
  4. SimpleCursorAdapter handle database related data.
  5. Methods:
    public ArrayAdapter (Context context, int resource, int textViewResourceId)
    public ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects)
    public ArrayAdapter (Context context, int resource, int textViewResourceId, List<T> objects)
 
    context        The current context.
    resource        The resource ID for a layout file containing a layout to use when instantiating views.
    textViewResourceId    The id of the TextView within the layout resource to be populated
    objects        The objects to represent in the ListView.
 
  6. Change data in the Adapter using clear(), add(), addAll(),
  7. Filtering lists(ListView) using adapter.getFilter().filter(searchString)


Notifications

Notifications are the messages in the status bar at the top of the screen. They’re handy to do stuff like notifying the user of new, unread e-mail in a background service, even if he’s not currently inside the e-mail application (this is exactly what the GMail app does). The following is the code necessary to display a notification:

Learn : http://android10.org/index.php/articlesuserinterface/257-creating-status-bar-notifications

Best Practices

Best Practices for Web App

1. Redirect mobile devices to a dedicated mobile version of your web site
    you should look for the "mobile" string in the User Agent

2. Use a valid markup DOCTYPE that's appropriate for mobile devices

    XHTML (not allow HTML frames and nested tables)
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">

3. Use viewport meta data to properly resize your web page
    In your document <head>, set the browser's viewport to render your web page
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    Targeting Screens from Web Apps.

4. Avoid multiple file requests
    avoid loading extra files such as stylesheets and script files in the <head>
    optimize the size and speed of your files by compressing them with tools like Minify.

5. Use a vertical linear layout
    Scrolling up and down is easier. (dont use left and right)


Best Practices - Designing for Performance

1. Optimize Judiciously
    the best decisions about data structures and algorithms
    Android-specific micro-optimization

2. Avoid Creating Unnecessary Objects
    memory will be reduced

3. Performance Myths, JIT
    -----

4. Prefer Static Over Virtual
    static method can called without using the object.
    If you don't need to access an object's fields, make your method static

5. Avoid Internal Getters/Setters
    within a class you should always access fields directly
    getter and setter will use objects

6. Use Static Final For Constants
    Memory in the disk retained as in the same place for static.
    Final variable's value will not be changed.
    Final method cant be override.

7. Use Enhanced For Loop Syntax
        for (Foo a : mArray) {
            sum += a.mSplat;
        }

8. Consider Package Instead of Private Access with Private Inner Classes
    ------

9. Use Floating-Point Judiciously
    ----
    should prefer double to float

10. Know And Use The Libraries
    ----

11. Use Native Methods Judiciously
    ----

Best Practices for User Interfaces

Top 10 best practices for developing user interfaces for Android applications

1. UI guidelines - icons, widgets, activities, and menus
    1. Icon Design Guidelines and Android Icon Templates Pack »
    2. Widget Design Guidelines
    3. Activity and Task Design Guidelines
    4. Menu Design Guidelines

2. Understand and design for touch mode
           1. The relationship between touch mode, selection, and focus means you must not rely on selection and/or focus to exist in your application. A very common problem with new Android developers is to rely on ListView.getSelectedItemPosition().
           2. In touch mode, this method will return INVALID_POSITION. You should instead use click listeners or the choice mode.
          3. Focusable in Touch Mode - For receive text input, like EditText or, when filtering is enabled, ListView.
          4. Make sure that buttons and UI widgets are large enough for a touch interface.

3. But, support multiple interaction modes
         -------
4. Use notifications and the window shade
       ------

Wednesday, 14 March 2012

SQLITE in Android

SQLite ( www.sqlite.org )

Learn :  http://www.vogella.de/articles/AndroidSQLite/article.html#sqlite_shell
Download: http://sourceforge.net/projects/sqlitebrowser/

1. SQLite is an Open Source Database which is embedded into Android.
2. SQLite supports standard relational database features like SQL syntax, transactions and prepared statements.
3. In addition it requires only little memory at runtime (approx. 250 KByte).
4. Data types: 
             TEXT (similar to String in Java)
            INTEGER (similar to long in Java)
            REAL (similar to double in Java).
5. SQLite itself does not validate dataType. e.g. you can write an integer into a string column and vice versa.
6. SQLite is available on every Android device. Using an SQLite database in Android does not require any database setup or administration.


SQLiteOpenHelper (class)
    1. Must override to methods:
        1. onCreate() is called by the framework, if the database does not exists.
        2. onUpgrade() is called, if the database version is increased in your application code.
            This method allows you to update the database schema.
    2.  Provide methods: (to read and write in DB )
        1. getReadableDatabase()
        2. getWriteableDatabase()
             These both return a SQLiteDatabase object that represents the database and provides methods for SQLite operations.
    3. The database tables should use the identifier _id for the primary key of the table.
   

SQLiteDatabase (public class)
 1. SQLiteDatabase has methods to create, delete, execute SQL commands, and perform other common database management tasks.
2. Database names must be unique within an application, not across all applications.
3. provides the insert(), update() and delete() methods and also execSQL() for special
4. Queries can be created via the rawQuery() and query() methods or via the SQLiteQueryBuilder class .
5. rawQuery() directly accepts an SQL statement as input.
6. query() provides a structure to do SQL query.

SQLiteQueryBuilder (public class )

     1. For complex queries, like require column aliases, you should use SQLiteQueryBuilder
     2. It provides several convienent methods for building queries.

SQLiteDatabase.CursorFactory (interface)
    1. Used to allow returning sub-classes of Cursor when calling query.
    2. public abstract Cursor newCursor (SQLiteDatabase db, SQLiteCursorDriver masterQuery, String editTable, SQLiteQuery query)
  
SQLiteCursor (class)
    1. A Cursor implementation that exposes results from a query on a SQLiteDatabase.
    2. SQLiteCursor is not internally synchronized so code using a SQLiteCursor from multiple threads should perform its own synchronization when using the SQLiteCursor.

Cursor
A query returns a Cursor object .
A Cursor represents the result of a query and basically points to one row of the query result.

    getCount()                                       --> number of elements in the array
    moveToFirst() and moveToNext()   --> To move between individual data rows
    isAfterLast()                                    --> To check if the end of the query result has been reached.
    get*()                                              --> To access the column data Ex: getLong(columnIndex)
    columnIndex                                    --> Index of the current column
    getColumnIndexOrThrow(String)     --> to get the column index for a column name
   
ListViews, ListActivities and SimpleCursorAdapter
ListViews are Views which allow to display a list of elements.
ListActivities are specialized Activities which make the usage of ListViews easier.
Two arrays have to define column names and IDs of Views.
The SimpleCursorAdapter class will map the columns to the Views based on the Cursor passed to it.

Using SQLite
ContentProvider is typically more resource efficient as you can avoid the creation of model objects.
Loader class is used in Android 3.0, In Android 4.0 we use DAO or ContentProvider.

ContentProvider and sharing data:
Used to share data with other applications you can use a ContentProvider.
It allows applications to access data. In most cases this data is stored in an SQlite database.
Access it using URI
URI is defined as android:authorities attribute in AndroidManifest.xml file.

Own ContentProvider:
1. define a class which extends android.content.ContentProvider
2. define in "AndroidManifest.xml" file with "android:authorities" attribute which allows to identify it
3. implement several methods, e.g. query(), insert(), update(), delete(), getType() and onCreate().
In case you don't support certain methods its good practice to throw an UnsupportedOperationException().
4. Set attribute android:exported=false to use Internally

ListView using StringArray in Android



/***********************AndroidManifest.xml**********************/

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

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

<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".SampleAppActivity"
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=".LoginActivity"
android:label="@string/login_act" >
</activity>
<activity
android:name=".NewListView"
android:label="@string/app_name" >
</activity>
</application>

</manifest>

/**********************SampleAppActivity.java*********************/

package com.sampleapp.application;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class SampleAppActivity extends Activity implements OnClickListener {

Button btn_next;
EditText nw_name;
EditText nw_degn;
EditText nw_cmpyUrl;
EditText nw_mob;
EditText nw_address;
Boolean isAlert = false;
private static final String REGULAR_EXP_NUMBER = "[\\d]+";
private static final String REGULAR_EXP_URL = "http://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
nw_name = (EditText) findViewById(R.id.nw_name);
nw_degn = (EditText) findViewById(R.id.nw_degn);
nw_cmpyUrl = (EditText) findViewById(R.id.nw_cmpy);
nw_mob = (EditText) findViewById(R.id.nw_mob);
nw_address = (EditText) findViewById(R.id.nw_address);

btn_next = (Button) findViewById(R.id.btn_next);
btn_next.setOnClickListener(this);
}

public void onClick(View v) {
String name = (String) nw_name.getText().toString();
String degn = (String) nw_degn.getText().toString();
String cmpy = (String) nw_cmpyUrl.getText().toString();
String mobile = (String) nw_mob.getText().toString();
int mob;
if (!cmpy.matches(REGULAR_EXP_URL)) {
new AlertDialog.Builder(this).setTitle("Error message")
.setMessage("Url incorrect")
.setNeutralButton("Close", null).show();
isAlert = true;
}else
isAlert = false;

if (mobile.equals("") || !mobile.matches(REGULAR_EXP_NUMBER)) {
mob = 0;
} else {
mob = Integer.parseInt(nw_mob.getText().toString());
}

String address = nw_address.getText().toString();
String delimiter = ",";
String[] addArray = address.split(delimiter);

Intent i = new Intent(SampleAppActivity.this, LoginActivity.class);
Bundle b = new Bundle();
b.putString("name", name);
b.putString("degn", degn);
b.putString("cmpy", cmpy);
b.putInt("mob", mob);
b.putStringArray("addArray", addArray);
i.putExtras(b);

if (!isAlert)
startActivity(i);
}
}

/*******************LoginActivity.java*******************/

package com.sampleapp.application;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class LoginActivity extends Activity implements OnClickListener {
TextView nameText;
TextView address;
Button btn_show;

@Override
protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.register);

Bundle b = this.getIntent().getExtras();
String name = b.getString("name");
String degn = b.getString("degn");
String cmpyUrl = b.getString("cmpy");
int mob = b.getInt("mob");
String[] addArray = b.getStringArray("addArray");

String values = "Name: " + name + "\nDesignation: " + degn + "\nCompanyUrl: " + cmpyUrl + "\nContact: " + mob;
nameText = (TextView) findViewById(R.id.r_name);
nameText.setText(values);

address = (TextView) findViewById(R.id.r_address);
String addressInArray = "";
for (int i = 0; i < addArray.length; i++) {
addressInArray = addressInArray + addArray[i];
}
address.setText("\nAddress: "+addressInArray);
btn_show = (Button) findViewById(R.id.btn_show);
btn_show.setOnClickListener(this);
}

@Override
public void onClick(View v) {
Intent i = new Intent(LoginActivity.this, NewListView.class);
startActivityForResult(i, 0);
}
}

/*********************NewListView.java*********************/

package com.sampleapp.application;

import android.app.ListActivity;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class NewListView extends ListActivity implements OnItemClickListener {

@Override
protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
Resources res = getResources();
String[] cities = res.getStringArray(R.array.cities);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, cities);
setListAdapter(adapter);
ListView lv = getListView();
lv.setTextFilterEnabled(true);

lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(),((TextView) view).getText(), Toast.LENGTH_SHORT).show();
}
});
}

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
}
}

/***************************main.xml************************/

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

<TableLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:stretchColumns="1" >

<TableRow>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/name" />

<EditText
android:id="@+id/nw_name"
android:layout_width="120dip"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:hint="Name"
android:text="" />
</TableRow>

<TableRow>
<TextView
android:id="@+id/degn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/designation" />

<EditText
android:id="@+id/nw_degn"
android:layout_width="120dip"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:hint="Designation"
android:text="" />
</TableRow>

<TableRow>
<TextView
android:id="@+id/cmpy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/company" />

<EditText
android:id="@+id/nw_cmpy"
android:layout_width="120dip"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:hint="Company Url"
android:text="" />
</TableRow>

<TableRow>
<TextView
android:id="@+id/mob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mobile" />

<EditText
android:id="@+id/nw_mob"
android:layout_width="120dip"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:hint="Enter number"
android:text="" />
</TableRow>

<TableRow>
<TextView
android:id="@+id/address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/address" />

<EditText
android:id="@+id/nw_address"
android:layout_width="120dip"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:hint="Split with ,"
android:text="" />
</TableRow>

<TableRow>
<Button
android:id="@+id/btn_go"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/go" >
</Button>

<Button
android:id="@+id/btn_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/next" >
</Button>
</TableRow>
</TableLayout>
</LinearLayout>

/**************************register.xml***************************/

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

<TextView
android:id="@+id/r_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />

<TextView
android:id="@+id/r_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />

<Button
android:id="@+id/btn_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/show" >
</Button>

</LinearLayout>

/***********************list_item.xml**********************/

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp" >
</TextView>

/**********************strings.xml*************************/

<?xml version="1.0" encoding="utf-8"?>
<resources>

<string name="hello">hi, AlertActivity!</string>
<string name="app_name">SampleApp</string>
<string name="login_act">LoginAct</string>
<string name="name">Name</string>
<string name="designation">Designation</string>
<string name="company">Company Url</string>
<string name="mobile">Mobile</string>
<string name="address">Address</string>

<string-array name="cities">
<item>Chennai</item>
<item>Trichy</item>
<item>Perambalur</item>
<item>Salem</item>
<item>Karur</item>
<item>Namakkal</item>
<item>Pondy</item>
</string-array>

<string name="go">GO</string>
<string name="next">NEXT</string>
<string name="show">SHOW LISTVIEW</string>

</resources>