Android - Get All Installed Applications in Device

    Usually, your device installed a lot of applications. Is there any way to get all  their name and information? Yes, Android SDK provides the class PackageManager which retrieves various kinds of information related to the application packages that are currently installed on the device. You can get an instance of PackageManager class by calling getPackageManager(). PackageManager provides methods for querying and manipulating installed packages and related permissions, etc.
    In this tutorial, I will make a completed app which will listing all installed apps in Android and provide some extra features: search, directly running,...to make a "shortcut" when launching any app in our own device.
    Project source code now available on Github, you can check it. First, please see this DEMO VIDEO, app run with Genymotion emulator:

Listing all Apps

    Declaring a simple running activity which only include a ListView in layout:
    As note above, we will a PackageManager instance to get all installed app. In programmatically code for activity, this process declaration only 2 lines:
PackageManager packageManager = getPackageManager();
List<Applicationinfo> list = packageManager.getInstalledApplications(PackageManager.GET_META_DATA)
    For app running well, we should do this process in a background thread by an AsyncTask. So, with getInstalledApplications() method was called in doInbackground(), an ApplicationInfo list will be return in onPostExcute(). Full source code for this AsyncTask:
package devexchanges.info.appslist;

import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;

import java.util.ArrayList;
import java.util.List;

public class GetAllAppsTask extends AsyncTask<Void, Void, List<ApplicationInfo>> {

    private MainActivity activity;
    private List<Applicationinfo> apps;
    private PackageManager packageManager;

    public GetAllAppsTask(MainActivity activity, List<Applicationinfo> apps, PackageManager pm) {
        this.activity = activity;
        this.apps = apps;
        this.packageManager = pm;
    }

    @Override
    protected List<Applicationinfo> doInBackground(Void... params) {
        apps = checkForLaunchIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA));
        return apps;
    }

    private List<Applicationinfo> checkForLaunchIntent(List<Applicationinfo> list) {
        ArrayList<Applicationinfo> applist = new ArrayList<>();
        for (ApplicationInfo applicationInfo : list) {
            try {
                if (packageManager.getLaunchIntentForPackage(applicationInfo.packageName) != null) {
                    applist.add(applicationInfo);
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

        return applist;
    }

    @Override
    protected void onPostExecute(List<Applicationinfo> list) {
        super.onPostExecute(list);
        activity.callBackDataFromAsynctask(list);
    }
}
   In onPostExcute() method, I've called back data to main activity and update views. So, this method in activity code is simple like this:
 public void callBackDataFromAsynctask(List<Applicationinfo> list) {
        applicationInfos.clear();

        for (int i = 0; i < list.size(); i++) {
            applicationInfos.add(list.get(i));
        }

        headerText.setText("All Apps (" + applicationInfos.size() + ")");
        adapter.notifyDataSetChanged();
        progressDialog.dismiss(); //dismiss progressing dialog
    }
    In order to our app always update, invoke AsynTask in onStart() method:
 @Override
    protected void onStart() {
        super.onStart();

        //invoke asynctask
        new GetAllAppsTask(this, applicationInfos, packageManager).execute();
    }

Create SearchView to filter List

     After above steps, we have get data and show it to ListView. For more convenient in use, I provide a SearchView on Toolbar to filter apps list.
    First, make a Toolbar layout and include I was included it in activity_main.xml  above:     Create a menu in our activity (in res/menu folder):
    Back to activity code, create menu in onCreateOptionsMenu() and provide OnQueryTextListener for SearchView, when we typing on it, app will filter ListView through call:
//filter adapter and update ListView
adapter.getFilter().filter(s);
    Creating menu search methods:
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        // Inflate menu to add items to action bar if it is present.
        inflater.inflate(R.menu.menu_main, menu);
        // Associate searchable configuration with the SearchView
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
        searchView.setOnQueryTextListener(onQueryTextListener()); // text changed listener
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

        return true;
    }

    private SearchView.OnQueryTextListener onQueryTextListener() {
        return new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String s) {
                //filter adapter and update ListView
                adapter.getFilter().filter(s);

                return false;
            }
        };
    }

Customizing a ListView Adapter

    For scrolling smoother, providing a ViewHolder class and then overriding getView() method:
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        // If holder not exist then locate all view from UI file.
        if (convertView == null) {
            // inflate UI from XML file
            convertView = inflater.inflate(R.layout.item_listview, parent, false);
            // get all UI view
            holder = new ViewHolder(convertView);
            // set tag for holder
            convertView.setTag(holder);
        } else {
            // if holder created, get tag from view
            holder = (ViewHolder) convertView.getTag();
        }

        //setting data to views
        holder.appName.setText(getItem(position).loadLabel(packageManager)); //get app name
        holder.appPackage.setText(getItem(position).packageName); //get app package
        holder.icon.setImageDrawable(getItem(position).loadIcon(packageManager)); //get app icon

        //set on click event for each item view
        convertView.setOnClickListener(onClickListener(position));

        return convertView;
    }

    private class ViewHolder {
        private ImageView icon;
        private TextView appName;
        private TextView appPackage;

        public ViewHolder(View v) {
            icon = (ImageView) v.findViewById(R.id.icon);
            appName = (TextView) v.findViewById(R.id.name);
            appPackage = (TextView) v.findViewById(R.id.app_package);
        }
    }
    When clicking at each item, getting this item (app) packagename through getLaunchIntentForPackage() and lauched it by Intent:
 private View.OnClickListener onClickListener(final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ApplicationInfo app = appsList.get(position);
                try {
                    Intent intent = packageManager.getLaunchIntentForPackage(app.packageName);
                    activity.startActivity(intent);
                    if (null != intent) {
                        activity.startActivity(intent);
                    }
                } catch (ActivityNotFoundException e) {
                    e.printStackTrace();
                }
            }
        };
    }
     Create customize Filter in our adapter to filtering data (ApplicationInfos List). We will override performFiltering() and publishResult() methods:
private class AppsFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();

            if (constraint != null && constraint.length() > 0) {
                ArrayList<Applicationinfo> filterList = new ArrayList<Applicationinfo>();
                for (int i = 0; i < originalList.size(); i++) {
                    if ((originalList.get(i).loadLabel(packageManager).toString().toUpperCase())
                            .contains(constraint.toString().toUpperCase())) {

                        ApplicationInfo applicationInfo = originalList.get(i);
                        filterList.add(applicationInfo);
                    }
                }

                results.count = filterList.size();
                results.values = filterList;

            } else {
                results.count = originalList.size();
                results.values = originalList;
            }
            return results;

        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            appsList = (ArrayList<Applicationinfo>) results.values;
            notifyDataSetChanged();

            if (appsList.size() == originalList.size()) {
                activity.updateUILayout("All apps (" + appsList.size() + ")");
            } else {
                activity.updateUILayout("Filtered apps (" + appsList.size() + ")");
            }
        }
    }

Final code

    Over here, I completed present every step to make this app. Following is full source code for important class and some necessary files.
    Code for main activity:
package devexchanges.info.appslist;

import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ListView listView;
    private TextView headerText;
    private Toolbar toolbar;

    private PackageManager packageManager;
    private ArrayAdapter<Applicationinfo> adapter;
    private ArrayList<Applicationinfo> applicationInfos;
    private ProgressDialog progressDialog;

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

        packageManager = getPackageManager();
        applicationInfos = new ArrayList<>();

        //find View by id
        listView = (ListView) findViewById(R.id.list_view);
        toolbar = (Toolbar) findViewById(R.id.toolbar);

        setSupportActionBar(toolbar);

        //show progress dialog
        progressDialog = ProgressDialog.show(this, "Loading All Apps", "Loading application info...");

        //set list view adapter
        LayoutInflater inflater = getLayoutInflater();
        View header = inflater.inflate(R.layout.layout_lv_header, listView, false);
        headerText = (TextView) header.findViewById(R.id.text_header);
        listView.addHeaderView(header, null, false);

        //initializing and set adapter for listview
        adapter = new ApplicationAdapter(this, R.layout.item_listview, applicationInfos);
        listView.setAdapter(adapter);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        // Inflate menu to add items to action bar if it is present.
        inflater.inflate(R.menu.menu_main, menu);
        // Associate searchable configuration with the SearchView
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
        searchView.setOnQueryTextListener(onQueryTextListener()); // text changed listener
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

        return true;
    }

    private SearchView.OnQueryTextListener onQueryTextListener() {
        return new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String s) {
                //filter adapter and update ListView
                adapter.getFilter().filter(s);

                return false;
            }
        };
    }

    @Override
    protected void onStart() {
        super.onStart();

        //invoke asynctask
        new GetAllAppsTask(this, applicationInfos, packageManager).execute();
    }


    public void callBackDataFromAsynctask(List<Applicationinfo> list) {
        applicationInfos.clear();

        for (int i = 0; i < list.size(); i++) {
            applicationInfos.add(list.get(i));
        }

        headerText.setText("All Apps (" + applicationInfos.size() + ")");
        adapter.notifyDataSetChanged();
        progressDialog.dismiss();
    }

    public void updateUILayout(String content) {
        headerText.setText(content);
    }
}
    ListView adapter class, defining a customize Filter:
package devexchanges.info.appslist;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class ApplicationAdapter extends ArrayAdapter<Applicationinfo> {
    private List<Applicationinfo> appsList;
    private List<Applicationinfo> originalList;
    private MainActivity activity;
    private PackageManager packageManager;
    private AppsFilter filter;

    public ApplicationAdapter(MainActivity activity, int textViewResourceId, List<Applicationinfo> appsList) {
        super(activity, textViewResourceId, appsList);
        this.activity = activity;
        this.appsList = appsList;
        this.originalList = appsList;
        packageManager = activity.getPackageManager();
    }

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

    @Override
    public ApplicationInfo getItem(int position) {
        return appsList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return appsList.indexOf(getItem(position));
    }

    @Override
    public Filter getFilter() {
        if (filter == null) {
            filter = new AppsFilter();
        }
        return filter;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        // If holder not exist then locate all view from UI file.
        if (convertView == null) {
            // inflate UI from XML file
            convertView = inflater.inflate(R.layout.item_listview, parent, false);
            // get all UI view
            holder = new ViewHolder(convertView);
            // set tag for holder
            convertView.setTag(holder);
        } else {
            // if holder created, get tag from view
            holder = (ViewHolder) convertView.getTag();
        }

        //setting data to views
        holder.appName.setText(getItem(position).loadLabel(packageManager)); //get app name
        holder.appPackage.setText(getItem(position).packageName); //get app package
        holder.icon.setImageDrawable(getItem(position).loadIcon(packageManager)); //get app icon

        //set on click event for each item view
        convertView.setOnClickListener(onClickListener(position));

        return convertView;
    }

    private View.OnClickListener onClickListener(final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ApplicationInfo app = appsList.get(position);
                try {
                    Intent intent = packageManager.getLaunchIntentForPackage(app.packageName);
                    activity.startActivity(intent);
                    if (null != intent) {
                        activity.startActivity(intent);
                    }
                } catch (ActivityNotFoundException e) {
                    e.printStackTrace();
                }
            }
        };
    }

    private class ViewHolder {
        private ImageView icon;
        private TextView appName;
        private TextView appPackage;

        public ViewHolder(View v) {
            icon = (ImageView) v.findViewById(R.id.icon);
            appName = (TextView) v.findViewById(R.id.name);
            appPackage = (TextView) v.findViewById(R.id.app_package);
        }
    }

    private class AppsFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();

            if (constraint != null && constraint.length() > 0) {
                ArrayList<Applicationinfo> filterList = new ArrayList<Applicationinfo>();
                for (int i = 0; i < originalList.size(); i++) {
                    if ((originalList.get(i).loadLabel(packageManager).toString().toUpperCase())
                            .contains(constraint.toString().toUpperCase())) {

                        ApplicationInfo applicationInfo = originalList.get(i);
                        filterList.add(applicationInfo);
                    }
                }

                results.count = filterList.size();
                results.values = filterList;

            } else {
                results.count = originalList.size();
                results.values = originalList;
            }
            return results;

        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            appsList = (ArrayList<Applicationinfo>) results.values;
            notifyDataSetChanged();

            if (appsList.size() == originalList.size()) {
                activity.updateUILayout("All apps (" + appsList.size() + ")");
            } else {
                activity.updateUILayout("Filtered apps (" + appsList.size() + ")");
            }
        }
    }
}
    Each ListView item layout:
    Strings resource:     Colors resource:     Styling our app:

Conclusion

    In this tut, I present an "Quick Launch Application" app, create shortcut at device Home screen, we have a simple way to quick launching any app:


You can directly download app apk HERE!
 Update: version 2.0: add feature: swipe to Uninstall an app, fix layout for tablet. Check this direct link for new apk file.



Share


Previous post
« Prev Post
Next post
Next Post »