Android Recyclerview for Installed Apps with Checkbox

android recyclerview

One of the most common reasons that you would want to use the android recyclerview is if you want to show a list of some sort. In this example, let’s take a look at how you can use the android recyclerview to show a list of installed apps on your device. Within each item, we will also include a checkbox. Here’s what it will look like:

android recyclerview apps

Layout

Let’s first take care of creating the layout files. Here is my layout file for the main activity (activity_main.xml). I am using a FrameLayout, with the Recyclerview and Floating Action Button. The floating action button is not necessary for this tutorial.

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

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycleView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout_editor_absoluteX="8dp"
        tools:layout_editor_absoluteY="8dp" />


    <android.support.design.widget.FloatingActionButton
        android:id="@+id/sharebutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="16dp"
        android:clickable="true"
        app:elevation="6dp"
        app:fabSize="normal"

        app:srcCompat="@android:drawable/ic_menu_share" />


</FrameLayout>

Next, let’s take care of the layout for each individual item in the list. I am calling this main_line_view.xml. It contains the following contents:

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

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="8dp">

            <ImageView
                android:id="@+id/packageImage"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_marginRight="5dp"
                android:layout_marginTop="6dp"
                android:src="@mipmap/ic_launcher" />

            <TextView
                android:id="@+id/Apk_Name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="4dp"
                android:layout_marginTop="6dp"
                android:layout_toEndOf="@id/packageImage"
                android:layout_toRightOf="@id/packageImage"
                android:textColor="#000" />

            <TextView
                android:id="@+id/Apk_Package_Name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/Apk_Name"
                android:layout_marginLeft="4dp"
                android:layout_toEndOf="@id/packageImage"
                android:layout_toRightOf="@id/packageImage"
                android:textColor="#795548"

                />

            <CheckBox
                android:id="@+id/appSelect"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true" />
        </RelativeLayout>

    </LinearLayout>


</RelativeLayout>

Build Grade

In your build Gradle (of the module: App), make sure that you include the following:

implementation 'com.android.support:recyclerview-v7:26.1.0'
implementation 'com.android.support:design:26.1.0'

Update the version to match the SDK that you are targeting.

Viewing Installed Apps

Now let’s work on getting the list of apps installed on your device. The only important line of code that you will need is the following:

List<ApplicationInfo> packages = mContext.getPackageManager().getInstalledApplications(0);

However, I also want to grab app name and icon. To keep things easy and re-usable, I created a class called AppManager and added the following contents:

public class AppsManager {
    private Context mContext;
    private AppInfo appInfo;
    private ArrayList<AppInfo> myApps;

    public AppsManager(Context c) {
        mContext = c;
        myApps = new ArrayList<AppInfo>();
    }

    public ArrayList<AppInfo> getApps() {
        loadApps();
        return myApps;
    }


    private void loadApps() {

        List<ApplicationInfo> packages = mContext.getPackageManager().getInstalledApplications(0);
        for (ApplicationInfo packageInfo : packages) {
            AppInfo newApp = new AppInfo();
            newApp.setAppName(getApplicationLabelByPackageName(packageInfo.packageName));
            newApp.setAppPackage(packageInfo.packageName);
            newApp.setAppIcon(getAppIconByPackageName(packageInfo.packageName));
            myApps.add(newApp);
        }

        Collections.sort(myApps, new Comparator<AppInfo>() {
            @Override
            public int compare(AppInfo s1, AppInfo s2) {
                return s1.getAppName().compareToIgnoreCase(s2.getAppName());

            }
        });

    }


    // Custom method to get application icon by package name
    private Drawable getAppIconByPackageName(String packageName) {
        Drawable icon;
        try {
            icon = mContext.getPackageManager().getApplicationIcon(packageName);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            // Get a default icon
            icon = ContextCompat.getDrawable(mContext, R.drawable.ic_launcher_background);
        }
        return icon;
    }

    // Custom method to get application label by package name
    private String getApplicationLabelByPackageName(String packageName) {
        PackageManager packageManager = mContext.getPackageManager();
        ApplicationInfo applicationInfo;
        String label = "Unknown";
        try {
            applicationInfo = packageManager.getApplicationInfo(packageName, 0);
            if (applicationInfo != null) {
                label = (String) packageManager.getApplicationLabel(applicationInfo);
            }

        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return label;
    }
}

The first function called loadApps gets the list of installed applications on the device. You will notice that I created my own custom class called AppInfo. This is because I wanted to store particular values and info from each class. Here is what the class AppInfo looks like:

public class AppInfo {
    private String appName;
    private String appPackage;
    private Drawable appIcon;
    private boolean isSelected;

    public String getAppPackage() {
        return appPackage;
    }

    public void setAppPackage(String appPackage) {
        this.appPackage = appPackage;
    }

    public Drawable getAppIcon() {
        return appIcon;
    }

    public void setAppIcon(Drawable appIcon) {
        this.appIcon = appIcon;
    }

    public boolean isSelected() {
        return isSelected;
    }

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

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }
}

So loadApps essentially saves a list of type AppInfo. I also implement a custom sort method that will sort the apps by their app name. You can then grab the list using the getApps method.

View Adapter

Now it’s time to implement a view adapter. If you worked with listviews in the pass, then this will look very familiar. Essentially, a view adapter controls how the recyclerview will show the view. It also maps all of our items from the main_line_view.xml to functions in the adapter. So here’s what the adapter looks like:

public class InstalledAppsAdapter extends RecyclerView.Adapter<InstalledAppsAdapter.ViewHolder> {

    private Context mContext;
    private ArrayList<AppInfo> mDataSet;

    public InstalledAppsAdapter(Context context, ArrayList<AppInfo> list) {
        mContext = context;
        mDataSet = list;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public TextView mTextViewLabel;
        public TextView mTextViewPackage;
        public ImageView mImageViewIcon;
        public CheckBox mAppSelect;
        public RelativeLayout mItem;

        public ViewHolder(View v) {
            super(v);
            // Get the widgets reference from custom layout
            mTextViewLabel = (TextView) v.findViewById(R.id.Apk_Name);
            mTextViewPackage = (TextView) v.findViewById(R.id.Apk_Package_Name);
            mImageViewIcon = (ImageView) v.findViewById(R.id.packageImage);
            mAppSelect = (CheckBox) v.findViewById(R.id.appSelect);
            mItem = (RelativeLayout) v.findViewById(R.id.item);
        }

    }

    @Override
    public InstalledAppsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(mContext).inflate(R.layout.main_line_view, parent, false);
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {

        // Get the current package name
        final String packageName = mDataSet.get(position).getAppPackage();

        // Get the current app icon
        Drawable icon = mDataSet.get(position).getAppIcon();

        // Get the current app label
        String label = mDataSet.get(position).getAppName();

        // Set the current app label
        holder.mTextViewLabel.setText(label);

        // Set the current app package name
        holder.mTextViewPackage.setText(packageName);

        // Set the current app icon
        holder.mImageViewIcon.setImageDrawable(icon);

        holder.mAppSelect.setChecked(mDataSet.get(position).isSelected());

        holder.mItem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDataSet.get(position).setSelected(!mDataSet.get(position).isSelected());
                InstalledAppsAdapter.this.notifyDataSetChanged();
            }
        });


    }

    @Override
    public int getItemCount() {
        // Count the installed apps
        return mDataSet.size();
    }

}

The only thing I want to point out if how I am handling the checkbox click. You will see the I implemented a listener that wraps the entire item. When it’s clicked, I set the selected boolean to the opposite of what it was. Finally, I used the line notifyDataSetChanged so that the recyclerview will refresh the list.

Main Activity

Finally, we can finish it up in our main activity by using the following lines:

public class MainActivity extends AppCompatActivity {

    private RelativeLayout mRelativeLayout;

    private RecyclerView mRecyclerView;
    private RecyclerView.LayoutManager mLayoutManager;
    private RecyclerView.Adapter mAdapter;
    private ArrayList<AppInfo> installedApps;
    private FloatingActionButton shareButton;
    private AppsManager appManager;
    private final String baseURL = "http://192.168.50.48/post.php";

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

        installedApps = new ArrayList<AppInfo>();
        mRecyclerView = (RecyclerView) findViewById(R.id.recycleView);
        shareButton = (FloatingActionButton) findViewById(R.id.sharebutton);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(layoutManager);
        appManager = new AppsManager(this);
        installedApps = appManager.getApps();

        // Initialize a new adapter for RecyclerView
        mAdapter = new InstalledAppsAdapter(
                getApplicationContext(),
                installedApps
        );


        mRecyclerView.setAdapter(mAdapter);
      
    }
}

That’s it! You can now have an android app that will display a list of installed apps using the recyclerview with a checkbox next to each item.