Search code examples
androidlistviewarraylistandroid-checkbox

How to add ListView items where a CheckBox is selected to separate ArrayList?


I am developing an app in which I want to display all the installed applications in a ListView.
I succeeded in doing so. Each item in my ListView contains an application name and a CheckBox. I want that whenever a user presses a Button all the the application names where CheckBox is IsSelected() should be stored in a separate ArrayList.

I have tried so many things, but nothing works.
My code is:

main_activity.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:id="@+id/container"
    android:layout_height="match_parent"
    tools:context="com.example.pc.fkidshell.Teen5Activity">

    <ListView
        android:id="@+id/list"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:layout_weight="1"/>
    <Button
        android:id="@+id/btn_add2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_marginBottom="20dp"
        android:text="Add Selected Apps"
        android:width="170dp"
        android:layout_weight="2"
        android:layout_alignParentBottom="true"
        android:layout_gravity="center_horizontal" />
</FrameLayout>

inflator.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="60dp"
    android:gravity="center"
    android:layout_gravity="center"
    android:orientation="horizontal"
    android:weightSum="2" >
    <TextView
        android:id="@+id/a"
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:textColor="#000"
        android:layout_gravity="center"
        android:gravity="center"
        android:layout_weight="1.7" />

    <CheckBox
        android:id="@+id/b"
        android:layout_width="0dp"
        android:layout_gravity="center"
        android:gravity="center"
        android:layout_weight="0.3"
        android:layout_height="wrap_content" />

</LinearLayout>

Datamodel.java

public class Datamodel {
    public String appname = "";
    private boolean selected;

    public String getAppname() {
        return appname;
    }

    public void setAppname(String appname) {
        this.appname = appname;
    }

    public boolean isSelected() {
        return selected;
    }

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

}

Adapter.java: (in the CheckBox listener I am using "MyApplication.setMyapps(ss);" to assign the application name to my global class (MyApplication) variable ArrayList myapps)

public class Adapter extends BaseAdapter {
    Context _ctx;
    LayoutInflater inflater;
    public ArrayList<Datamodel> data;

    public Adapter(Context c, ArrayList<Datamodel> _arraylist) {
        this._ctx = c;
        this.data = _arraylist;
    }

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

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

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent)
    {
        inflater = (LayoutInflater) _ctx.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View itemView = inflater.inflate(R.layout.inflator, parent, false);
        final CheckBox checks = (CheckBox) itemView.findViewById(R.id.b);
        final TextView _setappname = (TextView) itemView.findViewById(R.id.a);
        checks.setChecked(data.get(position).isSelected());

        Datamodel obj = data.get(position);
        _setappname.setText(obj.getAppname());
        checks.setTag(position);

        checks.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {

            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
            {
                int getPosition = (Integer) buttonView.getTag();
                Datamodel _obj = data.get(getPosition);
                data.get(position).setSelected(isChecked);
                String ss = _obj.getAppname();
                System.out.println("pos is" + getPosition);
                MyApplication.setMyapps(ss);
            }
        });
        return itemView;
    }
}

Mainactivity.java:

public class Teen5Activity extends Activity
{
    private ListView list;
    ArrayList<Datamodel> res;
    Adapter _adapter;

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

        list = (ListView) findViewById(R.id.list);
        List<PackageInfo> _myapps = getPackageManager().getInstalledPackages(0); //all the list of apps pacakage info stores in _myapps
        res = new ArrayList<Datamodel>();   //new arraylist that contains appname and checkboxes status
        for (int i = 0; i < _myapps.size(); i++)
        {
            PackageInfo p = _myapps.get(i);

            Datamodel _model  = new Datamodel();
            _model.setAppname(p.applicationInfo.loadLabel(getPackageManager()).toString());
            res.add(_model);
            System.out.println("ajajajja" + res.size() + res.get(i).getAppname());
        }
        _adapter = new Adapter(getApplicationContext(), res);
        _adapter.notifyDataSetChanged();
        list.setAdapter(_adapter);
        Button addbtn=(Button) findViewById(R.id.btn_add2);
        addbtn.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                if((MyApplication.getMyapps())==null)
                {
                    Toast.makeText(getApplicationContext(), "Nothing to ADD!", Toast.LENGTH_LONG).show();
                }
                else
                {
                    Toast.makeText(getApplicationContext(), "Successfully Added your Apps!", Toast.LENGTH_LONG).show();
                }

            }
        });
    }
}

MyApplication.java:

public class MyApplication extends Application
{
    private static ArrayList<String> myapps=null;
    public static void setMyapps(String logo)
    {
        myapps.add(logo);
    }
    public static ArrayList<String> getMyapps()
    {
        return myapps;
    }

}

Solution

  • Following mistakes I could find in your code:

    1) You need to initialize your MyApplication class's myApps arraylist.If you try to call setMyApps without initializing your arrayList, you will get a null-pointer exception. You need also need a remove method to dynamically update your checked-apps list.

    public class MyApplication extends Application
    {
    private static ArrayList<String> myapps= new ArrayList<String>();//Create an instance of the list, don't keep it as null
    
    public static void setMyapps(String logo)
    {
        myapps.add(logo);
    }
    public static ArrayList<String> getMyapps()
    {
        return myapps;
    }
    public static void removeApp(String appName)
    {
         myapps.remove(appName);
    }
    
    }
    

    2) You need to add it to your list, only if it is checked, not for the false state. So whenever, you access the list, the elements that are present refer to the checked applications.Also, you need to remove the app name from the list in the event of a check and a later uncheck case.

     checks.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
    
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
            {
                int getPosition = (Integer) buttonView.getTag();
                Datamodel _obj = data.get(getPosition);
                data.get(position).setSelected(isChecked);
                String ss = _obj.getAppname();
                System.out.println("pos is" + getPosition);
                if(isChecked) //Only if the app is checked
                    MyApplication.setMyapps(ss);
                else if(MyApplication.getMyApps().contains(ss))
                    MyApplication.removeApp(ss);
            }
        });
    

    3)I am not sure why you are extending the MyApplication class from Application here, if your objective is to store the app names.. a simple string arraylist would have sufficed.

    4) It would be better to track the applications through their package name, instead of app name, as the package name is a more unique property to the app.