3

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>
misctp asdas
  • 973
  • 4
  • 13
  • 35

4 Answers4

6

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;
    }
}
AndreyICE
  • 3,574
  • 29
  • 27
  • not working. especially the adapter it returned tons of error. please refer to my question and edit your solution again accordingly. Do bear in mind I used "public class PopAnalysis extends Activity{}" and not "public class MainActivity extends AppCompatActivity {". Please re-tailor your solution to my structure please thanks – misctp asdas Mar 17 '16 at 11:58
  • "final ListView listView = (ListView) findViewById(R.id.list_view);" <--- list_view missing in the .xml file? should I be adding a new list_view parameter ? – misctp asdas Mar 17 '16 at 12:25
  • R.id.listViewApp in your xml layout – AndreyICE Mar 17 '16 at 12:38
  • there are some formatting layouts at the moment. if you solved it you will get the bounty ! There were overlapping texts currently. Im not familiar with UI design. Could you propose an edited XML ? I have edited my questions with the xml file – misctp asdas Mar 17 '16 at 12:47
  • Just remove from Activity `RelativeLayout` anything except `ListView`. App names and permissions list are inside other layout witch inflated inside adapter. – AndreyICE Mar 17 '16 at 13:54
1

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.

Shane Duffy
  • 1,117
  • 8
  • 18
  • is there a way you could suggest the answer by posting the recommended solution edits into my question that i posted? – misctp asdas Mar 14 '16 at 07:05
  • Yeah, check my edit. Although I didn't make it list out all apps and their permissions, I added in a single row so that you could see how it was done. It shouldn't be much more code at all to add in what you wanted. – Shane Duffy Mar 14 '16 at 08:07
1

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

Emzor
  • 1,380
  • 17
  • 28
Amit K. Saha
  • 5,871
  • 2
  • 27
  • 35
  • is there a way you could suggest the answer by posting the recommended solution edits into my question that i posted? – misctp asdas Mar 14 '16 at 07:06
0

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.

user3383787
  • 68
  • 1
  • 2
  • 6