Tuesday 5 July 2016

How to share data between apps using Content Provider in Android

On the Android platform, one application cannot directly access (read/write) other application's data. All persistent data of an app is private to that app. Every application has its own id data directory and own protected memory area. This means that an app cannot query or manipulate the data of another app. However, if you want to enable an app to query or manipulate the data of another app, you need to use the concept of content providers.

Content Provider:

Content provider is a set of data wrapped up in a custom API to read and write. It acts as an interface that allows you to store and retrieve data from a data source. And also allows you to share an app’s data with other apps. Content providers decouple the app layer from the data layer by abstracting the underlying data source, thereby making apps data-source independent. They allow full permission control by monitoring which app components or users should have access to the data making data sharing easy. As a result, any app with appropriate permissions can add, remove, update, and retrieve data of another app including the data in some native Android databases.

There are 2 types of Content Providers :

  • Custom content providers: These are created by the developer to suit the requirements of an app.
  • Native content providers: These provide access to built-in databases, such as contact manager, media player, and other native databases. You need to grant the required permissions to your app before using native content providers.
Eg : The WhatsApp app sharing mobile contacts data.
Media store-Allows other applications to access, store media files.



Above diagram shows how content provider works. Application 2 stores its data in its own database and provides a provider. Application 1 communicates with the provider to access Application 2's data.

Content Provider uses a special URI starting with content:// will be assigned to each content providers and that will be recognized across applications.

Creating a Content Provider :

To create a content provider we need to

  1. Create sub class for ContentProvider.
  2. Define content URI
  3. Implement all the unimplemented methods. insert(), update(), query(), delete(), getType().
  4. Declare the content provider in AndroidManifest.xml
Specifying the URI of a Content Provide

Content provider URI consists of four parts.
content://authority/path/id

Each content provider exposes a URI that uniquely identifies the content provider’s data set. If a content provider controls multiple datasets, a separate URI needs to be specified for each dataset. The URI of a content provider begins with the string, content://.

content:// - All the content provider URIs should start with this value

authorityA Java namespace of the content provider implementation. (fully qualified Java package name)

path - A virtual directory within the provider that identifies the kind of data being requested.

Id - Its optional part that specifies the primary key of a record being requested. We can omit this part to request all records.

Registering the provider in AndroidManifest.xml

As with any other major parts of Android application, we have to register the content providers too in the AndroidManifest.xml. <provider> element is used to register the content providers. It should be declared under <application>.

<provider
     android:name=".MyProvider"
     android:authorities="com.example.contentproviderexample.MyProvider"
     android:exported="true"
     android:multiprocess="true" >
</provider>

Here authorities is the URI authority to access the content provider. Typically this will be the fully qualified name of the content provider class.

Creating provider application:

This application will create a content provider and share its data. This uses SQLite database 'sharedDb'. It has a table called 'names'. The table names have two columns id, name.
The URI of this content provider is content://com.example.contentproviderexample.MyProvider/cte
We have layout to insert new records to the database table.


Step 1 : Create a new project by going to File ⇒ New Android Application Project. Fill all the details and name your activity as MainActivity. (eclipse)

Step 2 : Design the activity_main.xml layout for MainActivity under layout folder as shown below for capturing data.


activity_main.xml

<LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:tools = "http://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    tools:context = "${relativePackage}.${activityClass}" >
  

    <TextView
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:text = "Enter Name :"
        android:textAppearance = "?android:attr/textAppearanceSmall"/>



  <EditText
        android:id = "@+id/txtName"
        android:layout_width = "fill_parent"
        android:layout_height = "wrap_content"/>



  <Button
        android:id = "@+id/btnAdd"
        android:layout_width = "fill_parent"
        android:layout_height = "wrap_content"

        android:onClick = "onClickAddName"

        android:text = "Add Name"/>



</LinearLayout >


Step 3 : Creating a Custom Content Provider


To create your own content provider, you need to create a class that extends the abstract ContentProvider class and overrides its methods.

MyProvider.java

public class MyProvider extends  ContentProvider
{

static final String PROVIDER_NAME = "com.example.contentproviderexample.MyProvider";
static final String URL = "content://" PROVIDER_NAME + "/cte";
static final Uri CONTENT_URI = Uri.parse(URL);

static final String id = "id";
static final String name = "name";
static final String uriCode = 1;
static final String UriMatcher  uriMatcher;
private static HashMap<String,String> values;

static
{
  uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  uriMatcher.addURI(PROVIDER_NAME ,"cte", uriCode);
  uriMatcher.addURI(PROVIDER_NAME ,"cte/*", uriCode);
}

private SQLiteDatabase db;
  static final String DATABASE_NAME = "sharedDb";
  static final String TABLE_NAME = "names";
  static final int DATABASE_VERSION = 1;
  static final String CREATE_DB_TABLE = " CREATE TABLE " + TABLE_NAME
      + " (id INTEGER PRIMARY KEY AUTOINCREMENT, "
      + " name TEXT NOT NULL);";

    @Override
    public boolean onCreate()
    {
        Context context = getContext();
        DatabaseHelper dbHelper = new DatabaseHelper(context);
        db = dbHelper.getWritableDatabase();
        if (db != null) {
         return true;
        }
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder)
    {
            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
            qb.setTables(TABLE_NAME);

            switch (uriMatcher.match(uri)) {
               case uriCode:
                qb.setProjectionMap(values);
              break;
            default:
             throw new IllegalArgumentException("Unknown URI " + uri);
            }

            if (sortOrder == null || sortOrder == "") {
             sortOrder = name;
            }
            Cursor c = qb.query(db, projection, selection, selectionArgs, null,
              null, sortOrder);
            c.setNotificationUri(getContext().getContentResolver(), uri);
            return c;
    }

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

    @Override
    public Uri insert(Uri uri, ContentValues values)
    {
        long rowID = db.insert(TABLE_NAME, "", values);

        if (rowID > 0) {
         Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
         getContext().getContentResolver().notifyChange(_uri, null);
         return _uri;
        }
        throw new SQLException("Failed to add a record into " + uri);
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs)
    {
        int count = 0;
        switch (uriMatcher.match(uri)) {
        case uriCode :
         count = db.delete(TABLE_NAME, selection, selectionArgs);
         break;
        default:
         throw new IllegalArgumentException("Unknown URI " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return count;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
    {
        int count = 0;
        switch (uriMatcher.match(uri)) {
          case uriCode :
           count = db.update(TABLE_NAME, values, selection, selectionArgs);
          break;
         default:
           throw new IllegalArgumentException("Unknown URI " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return count;
    }

  private static class DatabaseHelper extends SQLiteOpenHelper
    {
          DatabaseHelper(Context context)
        {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
    
        @Override
        public void onCreate(SQLiteDatabase db)
        {
            db.execSQL(CREATE_DB_TABLE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
        {
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
            onCreate(db);
        }
   }
}

Step 4 : Now open up the MainActivity  from src/package. Add the following code.

Note : onClickAddName() is the onClick attribute declared inside layout.

public void onClickAddName(View view)
{
        ContentValues values = new ContentValues();
        values.put(MyProvider.name, ((EditText) findViewById(R.id.txtName))
          .getText().toString());
        Uri uri = getContentResolver().insert(MyProvider.CONTENT_URI, values);
        ((EditText) findViewById(R.id.txtName)).setText("");
        Toast.makeText(getBaseContext(), "New record inserted", Toast.LENGTH_LONG)
          .show();
}

Creating request application:


This application is very simple, it will use the query() method to access the data stored in the Provider application. This application is having a layout to display the data.


Step 5 : Create a new project by going to File ⇒ New Android Application Project. Name it as 'RequestApp' Fill all the details and name your activity as MainActivity. (eclipse)

Step 6 : Design the activity_main.xml layout for MainActivity under layout folder as shown below for displaying data.

activity_main.xml

<LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:tools = "http://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    tools:context = "${relativePackage}.${activityClass}" >
  

  <Button
        android:id = "@+id/btnRetrieve"
        android:layout_width = "fill_parent"
        android:layout_height = "wrap_content"

        android:onClick = "onClickDisplayNames"

        android:text = "Display Names"/>


<TextView
        android:layout_width = "wrap_content"
        android:id = "@+id/res"
        android:layout_height = "wrap_content"
        android:textAppearance = "?android:attr/textAppearanceMedium"/>



</LinearLayout >

Step 7 : Now open up the MainActivity  from src/package. Add the following code.
We have used CusrsorLoader to load the data.

MainActivity.java

import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.content.CursorLoader;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity implements LoaderManager.LoaderCallbacks<Cursor> 
{
    TextView resultView = null; 
    CursorLoader cursorLoader;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        resultView= (TextView) findViewById(R.id.res);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1)
    {
        cursorLoader = new CursorLoader(this, Uri.parse("content://com.example.contentproviderexample.MyProvider/cte"), null, null, null, null);
        return cursorLoader;
    }

 public void onClickDisplayNames(View view)
    {
        getSupportLoaderManager().initLoader(1, null, this);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor)
    {
        if (cursor != null)
        {
            cursor.moveToFirst();
            StringBuilder res = new StringBuilder();
                  while (!cursor.isAfterLast()) {
                   res.append("\n"+cursor.getString(cursor.getColumnIndex("id"))+ "-"+ cursor.getString(cursor.getColumnIndex("name")));
                      cursor.moveToNext();
                  }
                  resultView.setText(res);
        }
        else
        {
            Toast.makeText(getBaseContext(), "No records", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
     public void onLoaderReset(Loader<Cursor> arg0)
    {     
    }
}

Source code : Click here to download.

Thanks a lot for reading...
Don't forget to share this post if you found it interesting!
If you find something to add to this post? or any other quick thoughts/hints that you think people will find useful? Share it in the comments & feedback's are most welcome.

Wednesday 15 June 2016

How to write App LogCat to SD card in Android

The Android logging system provides a mechanism for collecting and viewing system debug output. Logs from various applications and portions of the system are collected in a series of circular buffers.


Img src

We can test app on Emulator and with the help of Logcat we can easily trace the Error details.
But if we are testing on Real Android Device and that is not connected with system then its hard to know where we are getting exception. So this tutorial aims to resolve this problem.

We all know how to view LogCat message in Eclipse but how to write the LogCat details into a file and save it in SD card?

Using Shell command :


To save LogCat to a text file open up a terminal window and type:
    adb logcat -d > logcat.txt

The above command will create a file named "logcat.txt" in your current directory.  The -d option indicates that you are dumping the current contents and then exiting.

Read the LogCat programmatically :

Permission in Manifest :

  1. <uses-permission android:name = "android.permission.READ_LOGS" />
  2. <uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" />
  3. <uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />



Step 1 : Create a new project by going to File ⇒ New Android Application Project. Fill all the details and name your activity as MainActivity. (eclipse)

Step 2 : Design the activity_main.xml layout for MainActivity under layout folder as shown below

 activity_main.xml
 
    <RelativeLayout
        android:layout_width = "fill_parent"
        android:layout_height = "fill_parent" >

        <Button
            android:id = "@+id/btnWriteLogCat"                  
            android:layout_width = "wrap_content"
            android:layout_height = "wrap_content"
            android:layout_centerHorizontal= "true"
            android:layout_centerVertical= "true"
            android:text = "Write LogCat" />

    </RelativeLayout>

Step 3 : Add the following code in onCreate() method of MainActivity.java under src folder.
MainActivity.java

findViewById(R.id.btnWriteLogCat).setOnClickListener(new OnClickListener()

{

      @Override
      public void onClick(View v)
     {
writeLogCat();
     }
});

protected void writeLogCat()
{
try
{
     Process process = Runtime.getRuntime().exec("logcat -d");
               BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream)));
              StringBuilder log = new StringBuilder();
              String line;
              while((line = bufferedReader.readLine()) != null)
              {
                     log.append(line);
                     log.append("\n");
              }

             //Convert log to string
             final String logString = new String(log.toString());
            
             //Create txt file in SD Card
             File sdCard = Environment.getExternalStorageDirectory();
             File dir = new File(sdCard.getAbsolutePath() +File.separator + "Log File");

             if(!dir.exists())
             {
                  dir.mkdirs();
             }

             File file = new File(dir, "logcat.txt");

             //To write logcat in text file
             FileOutputStream fout = new FileOutputStream(file);
             OutputStreamWriter osw = new OutputStreamWriter(fout);

             //Writing the string to file
             osw.write(logString);
             osw.flush();
             osw.close();
          }
          catch(FileNotFoundException e)
          {
               e.printStackTrace();
          }
          catch(IOException e)
         {  
               e.printStackTrace();
         }
}

You can check the generated file named "logcat.txt" inside Log File Folder under Sd card.



Path : sdcard/Log File/logcat.txt

Source link : GreenMan

As always, Thanks a lot for reading...
Don't forget to share this post if you found it interesting!
If you find something to add to this post? or any other quick thoughts/hints that you think people will find useful? Share it in the comments & feedback's are most welcome. 




Thursday 5 May 2016

How to fix 'Unfortunately App has stopped' errors

There is one problem that plagues Android Developer: the cursed Unfortunately, Android App has stopped error message. It appears when you're in the middle of using an app, and then forces that app to close.
Here's how to handle Unfortunately, app has stopped errors and show users an neat regret message within the app as shown below.


The Cause :
Your application quit because an uncaught RuntimeException was thrown.
The most common of these is the NullPointerException.

Here we are going to see how to catch the uncaught exception and schedule a task (Showing an Activity with regret message instead of App crash dialog).

Step 1 : Create a new project by going to File ⇒ New Android Application Project. Fill all the details and name your activity as MainActivity. (eclipse)

Step 2 : Create a new Activity by going to File ⇒ New ⇒ Other ⇒ Android Activity. Fill all the details and name your activity as RegretActivity.

Step 3 : Design the activity_regret.xml layout for RegretActivity under layout folder as shown below

activity_regret.xml

<RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:tools = "http://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    tools:context = "${relativePackage}.${activityClass}" >
  
        <include
            android:id = "@+id/toolbar"
            layout = "@layout/toolbar" />
    <TextView
        android:id = "@+id/textView1"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_centerHorizontal = "true"
        android:layout_centerVertical = "true"
        android:text = "@string/msg_unexpected_error_occured"
        android:textAppearance = "?android:attr/textAppearanceLarge"
        android:textColor = "#505050"
        android:textStyle = "bold" />

    <TextView
        android:id = "@+id/textView2"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_below = "@+id/textView1"
        android:layout_centerHorizontal = "true"
        android:text = "@string/msg_sorry_for_the_inconvenience"
        android:textAppearance = "?android:attr/textAppearanceMedium" />

    <ImageView
        android:id = "@+id/imageView1"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_above = "@+id/textView1"
        android:layout_centerHorizontal = "true"
        android:contentDescription = "@string/tv_access_denied"
        android:src = "@drawable/ic_warning" />

    <Button
        android:id = "@+id/restart_button"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_below = "@+id/textView2"
        android:layout_centerHorizontal = "true"
        android:layout_marginTop = "@dimen/pad_10dp"
        android:background = "@drawable/blue_button_background"
        android:paddingBottom = "@dimen/pad_5dp"
        android:paddingLeft = "@dimen/pad_10dp"
        android:paddingRight = "@dimen/pad_10dp"
        android:paddingTop = "@dimen/pad_5dp"
        android:text = "@string/restart_app"
        android:textColor = "@color/white"
        android:textSize = "@dimen/txt_15sp"
        android:textStyle = "bold"/>

</RelativeLayout>

Step 4 : Create a new class under src/package. Right Click on src/package (com.example.uncaughtexception) ⇒ New ⇒ Class and name it as UncaughtExceptionHandler.java and fill it with following code.

UncaughtExceptionHandler.java

public class UncaughtExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler
{

    /**
     * activity - Activity
     */

    private final ActionBarActivity activity;

    /**
     * UncaughtExceptionHandler - Constructor
     * @param context
     */

    public UncaughtExceptionHandler(ActionBarActivity context)
    {
        activity = context;
    }
   
    @Override
    public void uncaughtException(Thread thread, Throwable exception)
    {
        exception.printStackTrace();
       
        Intent intent = new Intent(activity, RegretActivity.class);
        activity.startActivity(intent);
        activity.finish();

        System.out.println("Error occurred Activity name : " + activity.getClass().getSimpleName());
        android.os.Process.killProcess(android.os.Process.myPid());
        System.exit(10);
    }
}

Step 5 : Now open up the MainActivity  from src/package. Add the following statement next to the super.onCreate(); inside onCreate method.

Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(this));


The above statement will catch the UncaughtExcption occurred in the activity.

Source code : Click here to download. 

Thanks a lot for reading...
Don't forget to share this post if you found it interesting!
If you find something to add to this post? or any other quick thoughts/hints that you think people will find useful? Share it in the comments & feedback's are most welcome.

Wednesday 30 December 2015

TableLayout like ListView (Multi Column ListView)

Many Android developers mess up in building a Multi column ListView, which looks similar to a table layout in android.
So in this tutorial I am showing you how to create a multi column list view.

Output : 



Step 1 : Create a new project by going to File ⇒ New Android Application Project. Fill all the details and name your activity as MainActivity. (eclipse)

Step 2 : Design the activity_main.xml layout for MainActivity under layout folder as shown below

 activity_main.xml
 
    <LinearLayout
        android:id = "@+id/relativeLayout1"
        android:layout_width = "fill_parent"
        android:layout_height = "wrap_content"
        android:background = "@color/colorCell" >

        <TextView
            android:layout_width = "0dp"
            android:layout_height = "wrap_content"
            android:layout_weight = "1"
            android:gravity = "center"
            android:padding = "5dp"
            android:text = "@string/sNo"
            android:textColor = "#ffffff" />

        <TextView
            android:layout_width = "0dp"
            android:layout_height = "wrap_content"
            android:layout_weight = "2"
            android:gravity = "center"
            android:padding = "5dp"
            android:text = "@string/product"
            android:textColor = "#ffffff"/ >

        <TextView
            android:layout_width = "0dp"
            android:layout_height = "wrap_content"
            android:layout_weight = "1.5"
            android:gravity = "center"
            android:padding = "5dp"
            android:text = "@string/category"
            android:textColor = "#ffffff" />

        <TextView
            android:layout_width = "0dp"
            android:layout_height = "wrap_content"
            android:layout_weight = "1"
            android:gravity = "center"
            android:padding = "5dp"
            android:text = "@string/price"
            android:textColor = "#ffffff" />
    </LinearLayout>

    <ListView
        android:id = "@+id/listview"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:divider = "@null"/>

Step 3 : Create a xml file under drawable-hdpi and name it as cell_shape.xml as shown below.

  cell_shape.xml

 <layer-list xmlns:android = "http://schemas.android.com/apk/res/android">

    <item
        android:left = "-2dp"
        android:top = "-2dp">
        <shape android:shape = "rectangle" >
            <solid android:color = "@android:color/transparent" />

            <stroke
                android:width = "1dp"
                android:color = "@color/colorCell" />
        </shape>
    </item>
</layer-list

Step 4 : Create a new class under src/package. Right Click on src/package (com.example.multicolumnlistview) ⇒ New ⇒ Class and name it as Model.java and fill it with following code.

Model.java

public class Model {

    private String sNo;
    private String product;
    private String category;
    private String price;

    public Model(String sNo, String product, String category, String price) {
        this.sNo = sNo;
        this.product = product;
        this.category = category;
        this.price = price;
    }

    public String getsNo() {
        return sNo;
    }

    public String getProduct() {
        return product;
    }

    public String getCategory() {
        return category;
    }

    public String getPrice() {
        return price;
    }
}

Step 5 : Create a new xml file under res/layout. Right Click on res/layout ⇒ New ⇒ Android XML File and name it as listview_row.xml and fill it with following code. This layout is the custom layout inside list adapter.

listview_row.xml 
 
    <LinearLayout
        android:id = "@+id/relativeLayout1"
        android:layout_width = "fill_parent"
        android:layout_height = "wrap_content"
        android:background = "@color/colorCell" >

        <TextView       
            android:id = "@+id/sNo"      
            android:layout_width = "0dp"
            android:layout_height = "match_parent"
            android:layout_weight = "1"
            android:background = "@drawable/cell_shape"
            android:ellipsize = "end"
            android:padding = "5dp"
            android:text = "@string/sNo"
            android:singleLine = "true" />

        <TextView       
            android:id = "@+id/product"      
            android:layout_width = "0dp"
            android:layout_height = "match_parent"
            android:layout_weight = "2"
            android:background = "@drawable/cell_shape"
            android:ellipsize = "end"
            android:padding = "5dp"
            android:text = "@string/product"
            android:singleLine = "true" />

        <TextView       
            android:id = "@+id/category"      
            android:layout_width = "0dp"
            android:layout_height = "match_parent"
            android:layout_weight = "1.5"
            android:background = "@drawable/cell_shape"
            android:ellipsize = "end"
            android:padding = "5dp"
            android:text = "@string/category"
            android:singleLine = "true" />

         <TextView       
            android:id = "@+id/price"      
            android:layout_width = "0dp"
            android:layout_height = "match_parent"
            android:layout_weight = "1"
            android:background = "@drawable/cell_shape"
            android:ellipsize = "end"
            android:padding = "5dp"
            android:text = "@string/price"
            android:singleLine = "true" />
    </LinearLayout>

 Creating custom adapter for list view : 
Step 6 : Create a new class under src/package. Right Click on src/package (com.example.multicolumnlistview) ⇒ New ⇒ Class and name it as listviewAdapter.java and fill it with following code.


listviewAdapter.java

public class listviewAdapter extends BaseAdapter {

     public ArrayList<Model> productList;
     Activity activity;

    public listviewAdapter(Activity activity, ArrayList<Model> productList) {
        super();
        this.activity = activity;
        this.productList = productList;
    }

    @Override
    public int getCount() {
        return productList.size();
    }

    @Override
    public Object getItem(int position) {
       return productList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    private class ViewHolder {
        TextView mSNo;
        TextView mProduct;
        TextView mCategory;
        TextView mPrice;
    }

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

        ViewHolder holder;
        LayoutInflater inflater = activity.getLayoutInflater();

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.listview_row, null);
            holder = new ViewHolder();
            holder.mSNo = (TextView) convertView.findViewById(R.id.sNo);
            holder.mProduct = (TextView) convertView.findViewById(R.id.product);
            holder.mCategory = (TextView) convertView
                    .findViewById(R.id.category);
            holder.mPrice = (TextView) convertView.findViewById(R.id.price);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Model item = productList.get(position);
        holder.mSNo.setText(item.getsNo().toString());
        holder.mProduct.setText(item.getProduct().toString());
        holder.mCategory.setText(item.getCategory().toString());
        holder.mPrice.setText(item.getPrice().toString());

        return convertView;
    }
}

 Step 7 : Add the following code in MainActivity.

MainActivity.java

    private ArrayList<Model> productList;

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

        productList = new ArrayList<Model>();
        ListView lview = (ListView) findViewById(R.id.listview);
        listviewAdapter adapter = new listviewAdapter(this, productList);
        lview.setAdapter(adapter);

        populateList();

        adapter.notifyDataSetChanged();
       
        lview.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

                String sno = ((TextView)view.findViewById(R.id.sNo)).getText().toString();
                String product = ((TextView)view.findViewById(R.id.product)).getText().toString();
                String category = ((TextView)view.findViewById(R.id.category)).getText().toString();
                String price = ((TextView)view.findViewById(R.id.price)).getText().toString();
               
                Toast.makeText(getApplicationContext(),
                          "S no : " + sno +"\n"
                        +"Product : " + product +"\n"
                        +"Category : " +category +"\n"
                        +"Price : " +price, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void populateList() {

        Model item1, item2, item3, item4, item5;

        item1 = new Model("1", "Apple (Northern Spy)", "Fruits", "₹. 200");
        productList.add(item1);

        item2 = new Model("2", "Orange (Sunkist navel)", "Fruits", "₹. 100");
        productList.add(item2);

        item3 = new Model("3", "Tomato", "Vegetable", "₹. 50");
        productList.add(item3);

        item4 = new Model("4", "Carrot", "Vegetable", "₹. 80");
        productList.add(item4);

        item5 = new Model("5", "Banana (Cavendish)", "Fruits", "₹. 100");
        productList.add(item5);
    }

Checkout the live demo :



Source code : Click here to download. 

Source link

As always, Thanks a lot for reading...

Don't forget to share this post if you found it interesting!
If you find something to add to this post? or any other quick thoughts/hints that you think people will find useful? Share it in the comments & feedback's are most welcome.