简体   繁体   中英

How to create a listview with 2 columns showing all installed android apps and the permissions along with it?

I'm pretty newbie to Android development (2 days old).

I intend to create an app that list all the currently installed applications in the device and a column beside each of those results showing the permissions granted. I understand that conventionally a listView has 1 column , how do I make another column ?

I'm open to other ideas as well (like perhaps another intent when i click the installed application name ?)

Below is my code thus far which shows all installed applications :

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextSwitcher;
import android.widget.TextView;

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


public class PopAnalysis extends Activity{
    ListView appList;
    private TextSwitcher mSwitcher;
    TextView myText;
    private ArrayList results = new ArrayList();
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.popupanalysis);
        appList = (ListView)findViewById(R.id.listViewApp);
        PackageManager pm = this.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_MAIN,null);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        ArrayList<ResolveInfo> list = (ArrayList<ResolveInfo>) pm.queryIntentActivities(intent, PackageManager.PERMISSION_GRANTED);
        for (ResolveInfo rInfo : list) {
            results.add(rInfo.activityInfo.applicationInfo.loadLabel(pm).toString());
            System.out.println(rInfo.activityInfo.applicationInfo.loadLabel(pm).toString());
        }
        appList.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, results));
        appList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                int itemposition = position;
                String value = (String) appList.getItemAtPosition(position);

            }
        });
    }
}

Following are my XML codes :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">



     <ListView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/listViewApp"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_marginTop="56dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Large Text"
            android:id="@+id/textViewAnalysis"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true" />
        <TextView
            android:id="@+id/list_item_appname"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:textAppearance="@android:style/TextAppearance.Medium" />

        <TextView
            android:id="@+id/list_item_apppermissions"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </RelativeLayout>

Firstly you need load apps list and permission for every apps. I do it inside Activity.onCreate to simplify example. The better way to do it inside AsyncTask

public class MainActivity extends AppCompatActivity {

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

        final PackageManager packageManager = getPackageManager();

        final List<Pair<String, List<String>>> appsWithPermission = new ArrayList<>();

        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
        for (ResolveInfo info : apps) {
            final ApplicationInfo applicationInfo = info.activityInfo.applicationInfo;
            final String appName = (String) applicationInfo.loadLabel(packageManager);

            final List<String> permissions = new ArrayList<>();

            if (appName != null) {

                try {
                    final PackageInfo packageInfo = packageManager.getPackageInfo(applicationInfo.packageName, PackageManager.GET_PERMISSIONS);
                    final String[] requestedPermissions = packageInfo.requestedPermissions;

                    if (requestedPermissions != null) {
                        permissions.addAll(Arrays.asList(requestedPermissions));
                    }

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

            appsWithPermission.add(new Pair<>(appName, permissions));
        }

        final ListView listView = (ListView) findViewById(R.id.list_view);
        final AppsAdapter appsAdapter = new AppsAdapter(this, appsWithPermission);
        listView.setAdapter(appsAdapter);
    }
}

Secondly you need xml layout list_item.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="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/list_item_appname"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:textAppearance="@android:style/TextAppearance.Medium" />

    <TextView
        android:id="@+id/list_item_apppermissions"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

</LinearLayout>

and finally AppsAdapter.java

public class AppsAdapter extends BaseAdapter {

    private final Context mContext;
    private List<Pair<String, List<String>>> mAppsWithPermission;

    public AppsAdapter(Context context, List<Pair<String, List<String>>> appsWithPermission) {
        mContext = context;
        mAppsWithPermission = appsWithPermission;
    }

    static class ViewHolder {
        public TextView appName;
        public TextView appPermissions;
    }

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

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

    @Override
    public long getItemId(int position) {
        return mAppsWithPermission.get(position).hashCode();
    }

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

        if (convertView == null) {

            convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);
            holder = new ViewHolder();
            holder.appName = (TextView) convertView.findViewById(R.id.list_item_appname);
            holder.appPermissions = (TextView) convertView.findViewById(R.id.list_item_apppermissions);

            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Pair<String, List<String>> item = mAppsWithPermission.get(position);

        holder.appName.setText(item.first);
        holder.appPermissions.setText(item.second.toString());

        return convertView;
    }
}

I see you've already figured out how to get a list of all installed applications and their respective permissions, which is good. In order to make a ListView with multiple columns, though, you'll need to implement a ListViewAdapter.

A really great resource for figuring out how to do this can be found here .

If you're confused about anything on that link, or something doesn't work, let me know.

Code:

PopAnalysis.java

public class PopAnalysis extends Activity {
    public static final String FIRST_COLUMN = "First";
    public static final String SECOND_COLUMN = "Second";

    ListView appList;
    private TextSwitcher mSwitcher;
    TextView myText;
    private ArrayList results = new ArrayList();
    private ArrayList<HashMap<String, String>> list;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.popupanalysis);

        appList = (ListView)findViewById(R.id.listViewApp);
        HashMap<String,String> t1 = new HashMap<String, String>();
        t1.put(FIRST_COLUMN, "App 1");
        t1.put(SECOND_COLUMN, "Permission 1");
        list.add(t1);

        ListViewAdapter adapter = new ListViewAdapter(this, list);
        listView.setAdapter(adapter);
    }
}

ListViewAdapter.java

public class ListViewAdapter extends BaseAdapter {
    public static final String FIRST_COLUMN = "First";
    public static final String SECOND_COLUMN = "Second";

    public ArrayList<HashMap<String, String>> list;
    Activity activity;
    TextView txtFirst;
    TextView txtSecond;


    public ListViewAdapter(Activity activity,ArrayList<HashMap<String, String>> list){
        super();
        this.activity=activity;
        this.list=list;
    }

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

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

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



    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater=activity.getLayoutInflater();

        if(convertView == null){

            convertView=inflater.inflate(R.layout.column_row_layout, null);

            txtFirst=(TextView) convertView.findViewById(R.id.application);
            txtSecond=(TextView) convertView.findViewById(R.id.permissions);

        }

        HashMap<String, String> map=list.get(position);
        txtFirst.setText(map.get(FIRST_COLUMN));
        txtSecond.setText(map.get(SECOND_COLUMN));

        return convertView;
    }
}

column_row_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">
    <TextView android:id="@+id/application"
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:textStyle="bold" />
    <TextView android:id="@+id/permissions"
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="1"/>
</LinearLayout>

In PopAnalysis.java I added only one entry to simply show how it's done. Certainly you shouldn't have any issues implementing the data you want into it.

Instead of 2 column listview , you can also try ExpandableListView. Clicking on the item with expand a detail view just below to it. detail view will contain the permissions of that app.

Expandable Listview Tutorial

BTW, there is no way in SDK's listview to have multiple column. What you can do is to have a pseudo-multicolumn list view like using multiple textview(or other kind of view) in the same row. In that case you will need to make a custom adapter for your list view and a custom row layout file.

If you really want to have something multi-column, then either 3rd party libraries or TableLayout is your only option.

TableLayout tutorial

to make two column listview you have to implement custom listview. please read this link

in program_list.xml instead of imageview take textview it will resolve your problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM