miércoles, 26 de septiembre de 2012

Añadir accesos directos

Dependiendo de las funcionalidades que ofrezca nuestra aplicación, nos puede interesar que el usuario pueda añadir accesos directos a ellas. Así pues para llegar a esa opción no será necesario abrir y navegar por la aplicación.
Para crear accesos directos podemos hacerlo de dos formas: Podemos permitir que el usuario tenga la opción de añadirla manualmente (por ejemplo, usando un botón en la app que cree el acceso) o bien, navegando por el sistema (dónde se encuentran el resto de accesos de las otras aplicaciones).

Así pues, en este ejemplo vamos a mostrar com permitir al usuario añadir un acceso directo a partir de la aplicación, ya que, la segunda opción es obvia.

En la aplicación veremos 2 activities, la primera que contendrá el botón que añadirá el acceso a la segunda activity. Sólo ser accesible a partir del acceso directo.

strings.xml

<resources>

    <string name="app_name">BlogShortCut</string>
    <string name="hello_world">Hello world!</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_main">BlogShortCut</string>
    
    <string name="addShortcut">Add shortcut to HomeScreen</string>

    <string name="shortcut">ShortcutExample</string>
    <string name="activityShortcut">I\'m shortCut Activity!</string>

</resources>


AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.blogshortcut"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>


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"
    android:orientation="vertical" >

    <Button
        android:id="@+id/button_add_shortcut"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="50dip"
        android:gravity="center"
        android:text="@string/addShortcut" >
    </Button>

</LinearLayout>

activity_shortcut.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" >

    <TextView
        android:id="@+id/textview_intent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:padding="@dimen/padding_medium"
        android:text="@string/activityShortcut" />

</RelativeLayout>

MainActivity.java
package com.example.blogshortcut;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

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

// allow install shortcuts from homescreen

((Button) findViewById(R.id.button_add_shortcut))
.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
// comprobamos que el dispositivo puede crear el acceso directo
if (getPackageManager()
.queryBroadcastReceivers(
new Intent(
"com.android.launcher.action.INSTALL_SHORTCUT"),
0).size() > 0) {
createShortCut();
} else {
Toast.makeText(MainActivity.this,
"cannot add shortcut", Toast.LENGTH_SHORT)
.show();
}

}
});
}

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

private void createShortCut() {

Intent shortcutIntent = new Intent(this, ShortCutActivity.class);
shortcutIntent.addCategory(Intent.CATEGORY_DEFAULT);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
shortcutIntent.putExtra("myParameter", "Parameter from Intent");
shortcutIntent.putExtra("shortcut", "no");

Intent addIntent = new Intent();
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
addIntent.putExtra("duplicate", false); //evitamos duplicados
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, getResources()
.getString(R.string.activityShortcut));
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
Intent.ShortcutIconResource.fromContext(this,
R.drawable.YOUR_ICON));
addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
sendBroadcast(addIntent);
}
}

ShortCutActivity.java
package com.example.blogshortcut;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.widget.TextView;

public class ShortCutActivity extends Activity {

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

Bundle extras = getIntent().getExtras();
if (extras != null) {
String intentText = extras.getString("myParameter");
if (!"".equals(intentText)) {
((TextView) findViewById(R.id.textview_intent))
.setText(intentText);
}
}
if (extras == null) {
createShortCut();
}

}

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

private void createShortCut() {
Intent shortcutIntent = new Intent(this, ShortCutActivity.class);
shortcutIntent.addCategory(Intent.CATEGORY_DEFAULT);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
shortcutIntent.putExtra("myParameter", "Parameter from Intent");
shortcutIntent.putExtra("shortcut", "no");

Intent addIntent = new Intent();
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
addIntent.putExtra("duplicate", false);
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, getResources()
.getString(R.string.activityShortcut));
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
Intent.ShortcutIconResource.fromContext(this,
R.drawable.ic_shortcut));
addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
sendBroadcast(addIntent);
}
}


A continuación la imagen del shortcut creado:


It works!
Roger Sala,






miércoles, 19 de septiembre de 2012

Crear Widget

Cuando creamos una app nos puede interesar darle al usuario la posibilidad de añadir un widget en el escritorio como, por ejemplo, Twitter o Foursquare.

Para ello podemos usar el siguiente código. En ello podemos ver, cómo:

1.- Se crea la clase Widget que usa AppWidgetProvider.
2.- Se implementa el método onUpdate que se llama al añadir el Widget en el escritorio. El método onReceive para capturar los eventos que se producen (por ejemplo, pulsado de un botón).
3.- Se gestiona el AndroidManifest.xml
4.- Se crea la interfaz gestora del widget (el gestor). widgetproviderinfo.xml
5.- En widgetproviderinfo.xml podemos ver los campos android:minResizeWidth,
    android:minResizeHeight y android:resizeMode que nos permiten cambiar el tamaño de los widgets. 

AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.blogwidgetexample"
    android:installLocation="internalOnly"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <receiver android:name=".BlogWidgetExample" >
            <intent-filter>
             <!-- Se usa para gestionar los eventos de los botones-->
                <action android:name="com.example.blogwidgetexample.ACTION_WIDGET_SHOW" />
                <action android:name="com.example.blogwidgetexample.ACTION_WIDGET_HIDDEN" />
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/widgetproviderinfo" />
        </receiver>
    </application>
</manifest>

Creamos en res/xml
widgetproviderinfo.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/activity_blog_widget_example"
    android:minHeight="130dp"
    android:minWidth="170dp"
    android:minResizeWidth="30dp"
    android:minResizeHeight="30dp"
    android:resizeMode="horizontal|vertical" />

BlogWidgetExample.java
package com.example.blogwidgetexample;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

public class BlogWidgetExample extends AppWidgetProvider {
public static final String WIDGETTAG = "WidgetMood";
// our actions for our buttons
public static String ACTION_WIDGET_HIDDEN = "ActionReceiverHidden";
public static String ACTION_WIDGET_SHOW = "ActionReceiverShow";

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);

RemoteViews remoteViews;

remoteViews = new RemoteViews(context.getPackageName(),
R.layout.activity_blog_widget_example);
remoteViews.setTextViewText(R.id.clicked, "Button not clicked");

// Button hidden
Intent active = new Intent(context, BlogWidgetExample.class);
active.setAction(ACTION_WIDGET_HIDDEN);
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context,
0, active, 0);
remoteViews.setOnClickPendingIntent(R.id.button_hidden,
actionPendingIntent);

// Button show
active = new Intent(context, BlogWidgetExample.class);
active.setAction(ACTION_WIDGET_SHOW);
actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0);
remoteViews.setOnClickPendingIntent(R.id.button_show,
actionPendingIntent);

appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}

@Override
public void onReceive(Context context, Intent intent) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.activity_blog_widget_example);

if (intent.getAction().equals(ACTION_WIDGET_HIDDEN)) {
Log.i("onReceive", ACTION_WIDGET_HIDDEN);
Toast.makeText(context, ACTION_WIDGET_HIDDEN, Toast.LENGTH_SHORT)
.show();
remoteViews.setTextViewText(R.id.clicked, ACTION_WIDGET_HIDDEN);

} else if (intent.getAction().equals(ACTION_WIDGET_SHOW)) {
Log.i("onReceive", ACTION_WIDGET_SHOW);
Toast.makeText(context, ACTION_WIDGET_SHOW, Toast.LENGTH_SHORT)
.show();
remoteViews.setTextViewText(R.id.clicked, ACTION_WIDGET_SHOW);

}
ComponentName cn = new ComponentName(context, BlogWidgetExample.class);
AppWidgetManager.getInstance(context).updateAppWidget(cn, remoteViews);
super.onReceive(context, intent);

}
}

activity_blog_widget_example.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/white" >
    <TextView
        android:id="@+id/clicked"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dip"
        android:padding="@dimen/padding_medium"
        android:text="@string/hello_world"
        android:textColor="@android:color/black"
        tools:context=".BlogWidgetExample" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/clicked" >
        <Button
            android:id="@+id/button_hidden"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hidden"
            android:textColor="@android:color/black" />
        <Button
            android:id="@+id/button_show"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Show"
            android:textColor="@android:color/black" />
    </LinearLayout>
</RelativeLayout>


A continuación podemos ver una imagen de nuestro Widget:




It works!
Roger Sala,

lunes, 17 de septiembre de 2012

Comprobar si aplicación esta Running y en pantalla

Por algun motivo,  cuando creamos una aplicación nos puede interesar saber si la aplicación esta activa en el sistema y en pantalla.  Para ello, podemos usar la siguiente función:


private boolean isOpenApp() {

      ActivityManager am = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
      String packageName = am.getRunningTasks(1).get(0).topActivity.getPackageName();

      if (!packageName.equals(TARGET_APP)) {
            return false;
      } 
      return true;
}

Si se da el caso que queremos activar la aplicación (lanzarla de nuevo en pantalla podemos sustituir el código anterior por el siguiente:

private void openApp() {

      ActivityManager am = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
      String packageName = am.getRunningTasks(1).get(0).topActivity.getPackageName();

      if (!packageName.equals(TARGET_APP)) {
          Intent launchIntent = getPackageManager().getLaunchIntentForPackage(TARGET_APP);
            startActivity(launchIntent);
      } 
}


Espero que les haya servido.

It works!
Roger Sala

Abrir diálogo con los Tonos del teléfono

Si estamos creando una aplicación, por ejemplo, que utiliza sonidos a lo mejor, nos viene bien, usar los que el sistema Android tiene por defecto. Para ello, podemos abrir un cuadro de diálogo mostrando los diferentes tonos que el usuario puede escoger.

A continuación los pasos y el código:

1.- Primero de todo creamos el Intent y luego realizamos la acción de iniciar una Activity esperando el resultado.


private final int TONE_SELECTED = 1;
*********************


Intent intent = new Intent(
RingtoneManager.ACTION_RINGTONE_PICKER);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE,
RingtoneManager.TYPE_NOTIFICATION);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE,
"Selecciona el to d'alarma /*Título del cuadro de diálogo*/");
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI,
(Uri) null);
startActivityForResult(intent, TONE_SELECTED);


2.- En el result nos guardamos la URI (dirección) del tono para futuros usos. En este caso lo guardamos usando SharedPreferences.


public static final String PREFERENCE_TONE_URI = "toneUri";
public static final String PREFERENCE_TONE_NAME = "toneName";
public static final String PREFERENCES_NAME = "PREF_NAME";
*********************


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
         switch (requestCode) {
              case TONE_SELECTED:
                      String toneUri,
                      toneName;
                      try {
                        Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
                        Ringtone ringtone = RingtoneManager.getRingtone(this, uri);

                       if (uri != null) {
                          toneUri = uri.toString();
                          toneName = ringtone.getTitle(this);
                          SharedPreferences preferences = getSharedPreferences(
                          PREFERENCES_NAME, Context.MODE_WORLD_WRITEABLE);
                          SharedPreferences.Editor editor = preferences.edit();
                          editor.putString(PREFERENCE_TONE_URI, toneUri);
                          editor.putString(PREFERENCE_TONE_NAME, toneName);
                         editor.commit();
                        } 
                      } catch (Exception e) {
                         e.printStackTrace();
                         Toast.makeText(this, "No se ha seleccionado ningún tono"Toast.LENGTH_SHORT).show();
                      }
                      break;
                   default:
                      break;
           }
}


Finalmente, una imagen donde se puede apreciar el cuadro de diálogo:




It works!
Roger Sala,





domingo, 2 de septiembre de 2012

ExpandableListView

En Android podemos encontrar listas simples (ListView) o bien listas que permiten expandir su contenido (ExpandableListView).
Una ListView nos permite ver información, normalmente, resumida del contenido de ese elemento el cuál podemos acceder para ver más información. En cambio, las ExpandableListView se usan para agrupar elementos que tienen algo en común. Por ejemplo, podríamos tener una aplicación que tratara sobre vehículos. Entonces podríamos estructurar la vista de manera que cada elemento que se muestre dentro de la lista sean: coches, autobuses, trenes... Al acceder al elemento coche se expandiese una nueva lista dentro de coches con las diferentes marcas a consultar (ídem para autobuses y trenes).

A continuación vamos a ver un ejemplo genérico de como crear nuestra propia ExpandableListView. Para ello vamos a crear:

/*Vista principal que contiene la ExpandableListView que vamos a mostrar*/
activity_expandable.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:orientation="vertical" >
    <ExpandableListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="fill_parent" >
    </ExpandableListView>
</LinearLayout>


/*Vista "customizada" de los elementos que conforman los grupos de la lista*/
group_layout.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" >
    <TextView
        android:id="@+id/tvGroup"
        android:layout_width="wrap_content"
        android:layout_height="40dip"
        android:paddingLeft="5dip"
        android:text="Groups"
        android:gravity="center"
        android:textColor="#000000"
        android:textSize="17sp"
        android:textStyle="bold" >
    </TextView>
</LinearLayout>


/*Vista "customizada" de los elementos que conforman los hijos de la lista*/
child_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/tvChild"
        android:layout_width="fill_parent"
        android:layout_height="45dip"
        android:gravity="center_vertical"
        android:paddingLeft="5dip"
        android:paddingRight="5dip"
        android:text="Children"
        android:textColor="#ffCCCC22"
        android:textSize="17sp"
        android:textStyle="bold" >
    </TextView>
</LinearLayout>


/*Clase que se encargará de gestionar la información que se mostrará en la lista y como se va a mostrar (añadiendo la información en los respectivos TextView, ImageView...)*/
ExpandableListAdapter.java

package com.example.blogexpandablelistview;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;

public class ExpandableListAdapter extends BaseExpandableListAdapter {
@Override
public boolean areAllItemsEnabled() {
return true;
}
private Context context;
private ArrayList<String> groups;
private ArrayList<ArrayList<AbstractGroupItem>> children;

public ExpandableListAdapter(Context context, ArrayList<String> groups,
ArrayList<ArrayList<AbstractGroupItem>> children) {
this.context = context;
this.groups = groups;
this.children = children;
}

//Esta función nos añade la información que queremos mostrar en el adapter
public void addItem(AbstractGroupItem groupItem) {
if (!groups.contains(groupItem.getGroup())) {
groups.add(groupItem.getGroup());
}
int index = groups.indexOf(groupItem.getGroup());
if (children.size() < index + 1) {
children.add(new ArrayList<AbstractGroupItem>());
}
children.get(index).add(groupItem);
}

@Override
public Object getChild(int groupPosition, int childPosition) {
return children.get(groupPosition).get(childPosition);
}

@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}

@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
AbstractGroupItem groupItem = (AbstractGroupItem) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.child_layout, null);
}
TextView tv = (TextView) convertView.findViewById(R.id.tvChild);
tv.setText("   " + groupItem.getName());

tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
return convertView;
}

@Override
public int getChildrenCount(int groupPosition) {
return children.get(groupPosition).size();
}

@Override
public Object getGroup(int groupPosition) {
return groups.get(groupPosition);
}

@Override
public int getGroupCount() {
return groups.size();
}

@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String group = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.group_layout, null);
}
TextView tv = (TextView) convertView.findViewById(R.id.tvGroup);
tv.setText(group);
return convertView;
}

@Override
public boolean hasStableIds() {
return true;
}

@Override
public boolean isChildSelectable(int arg0, int arg1) {
return true;
}
}

/*Clase que se encargará de gestionar la información para rellenar la lista y su adaptador*/
ExpandableListActivity.java
package com.example.blogexpandablelistview;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupClickListener;
import android.widget.Toast;

public class ExpandableListActivity extends Activity {

private ExpandableListAdapter mAdapter;
private final int TOTAL_GROUP_1 = 3;
private final int TOTAL_GROUP_2 = 4;
private final int TOTAL_GROUP_3 = 5;

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

ExpandableListView listView = (ExpandableListView) findViewById(R.id.listView);

listView.setOnChildClickListener(new OnChildClickListener() {

@Override
public boolean onChildClick(ExpandableListView arg0, View arg1,
int arg2, int arg3, long arg4) {
Toast.makeText(getBaseContext(), "Child clicked",
Toast.LENGTH_LONG).show();
return false;
}
});

listView.setOnGroupClickListener(new OnGroupClickListener() {

@Override
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {

Toast.makeText(getBaseContext(), "Group clicked",
Toast.LENGTH_LONG).show();
return false;
}
});

mAdapter = new ExpandableListAdapter(this, new ArrayList<String>(),
new ArrayList<ArrayList<AbstractGroupItem>>());

setupData();

listView.setAdapter(mAdapter);
}

private void setupData() {
AbstractGroupItem groupItem = null;
for (int i = 0; i < TOTAL_GROUP_1; i++) {
groupItem = new GroupItem_1("item child " + i);
mAdapter.addItem(groupItem);
}
for (int i = 0; i < TOTAL_GROUP_2; i++) {
groupItem = new GroupItem_2("item child " + i);
mAdapter.addItem(groupItem);
}
for (int i = 0; i < TOTAL_GROUP_3; i++) {
groupItem = new GroupItem_3("item child " + i);
mAdapter.addItem(groupItem);
}
}
}

A continuación, creamos las distintas clases que conforman el modelo. Como veremos tenemos una clase llamada AbstractGroupItem que nos servirá para tener compartidas las funciones de obtener los grupos y los hijos. Las clases GroupItem_(1,2,3) van a extender de ella para así poder usar esas funciones.

AbstractGroupItem.java
package com.example.blogexpandablelistview;

public class AbstractGroupItem {
private String name;
private String group;

public String getGroup() {
return group;
}

public void setGroup(String group) {
this.group = group;
}

public AbstractGroupItem(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

GroupItem_1.java
package com.example.blogexpandablelistview;
public class GroupItem_1 extends AbstractGroupItem {
    public GroupItem_1(String name) {
        super(name);
        setGroup(GroupItem_1.class.getSimpleName());
    }
}

GroupItem_2.java
package com.example.blogexpandablelistview;
public class GroupItem_2 extends AbstractGroupItem {
    public GroupItem_2(String name) {
        super(name);
        setGroup(GroupItem_2.class.getSimpleName());
    }
}



GroupItem_1.java
package com.example.blogexpandablelistview;
public class GroupItem_3 extends AbstractGroupItem {
    public GroupItem_3(String name) {
        super(name);
        setGroup(GroupItem_3.class.getSimpleName());
    }
}

Finalmente se adjuntan dos imagenes que nos muestran como queda nuestro proyecto:



It works!

Roger Sala,