org.jak_linux.dns66.main.WhitelistFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.jak_linux.dns66.main.WhitelistFragment.java

Source

/* Copyright (C) 2016 Julian Andres Klode <jak@jak-linux.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 */
package org.jak_linux.dns66.main;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.TextView;

import org.jak_linux.dns66.BuildConfig;
import org.jak_linux.dns66.FileHelper;
import org.jak_linux.dns66.MainActivity;
import org.jak_linux.dns66.R;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Activity showing a list of apps that are whitelisted by the VPN.
 *
 * @author Braden Farmer
 */
public class WhitelistFragment extends Fragment {

    private static final String TAG = "Whitelist";
    private AppListGenerator appListGenerator;
    private ListView appList;
    private SwipeRefreshLayout swipeRefresh;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        View rootView = inflater.inflate(R.layout.activity_whitelist, container, false);

        appList = (ListView) rootView.findViewById(R.id.list);

        swipeRefresh = (SwipeRefreshLayout) rootView.findViewById(R.id.swiperefresh);
        swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                appListGenerator = new AppListGenerator();
                appListGenerator.execute();
            }
        });
        swipeRefresh.setRefreshing(true);

        Switch switchShowSystemApps = (Switch) rootView.findViewById(R.id.switch_show_system_apps);

        switchShowSystemApps.setChecked(MainActivity.config.whitelist.showSystemApps);
        switchShowSystemApps.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                MainActivity.config.whitelist.showSystemApps = isChecked;
                FileHelper.writeSettings(getContext(), MainActivity.config);
                appListGenerator = new AppListGenerator();
                appListGenerator.execute();
            }
        });

        appListGenerator = new AppListGenerator();
        appListGenerator.execute();

        return rootView;
    }

    private class AppListAdapter extends ArrayAdapter<ListEntry> {
        AppListAdapter(Context context, int layout, List<ListEntry> list) {
            super(context, layout, list);
        }

        @Override
        public View getView(int position, View convertView, final ViewGroup parent) {
            // Check if an existing view is being reused, otherwise inflate the view
            if (convertView == null)
                convertView = LayoutInflater.from(getContext()).inflate(R.layout.whitelist_row, parent, false);

            final ListEntry entry = getItem(position);

            final ImageView iconView = (ImageView) convertView.findViewById(R.id.app_icon);

            AsyncTask<ListEntry, Void, Drawable> task = (AsyncTask<ListEntry, Void, Drawable>) convertView.getTag();
            if (task != null)
                task.cancel(true);

            task = null;
            final Drawable icon = entry.getIcon();
            if (icon != null) {
                iconView.setImageDrawable(icon);
                iconView.setVisibility(View.VISIBLE);
                convertView.setTag(null);
            } else {
                iconView.setVisibility(View.INVISIBLE);

                task = new AsyncTask<ListEntry, Void, Drawable>() {
                    @Override
                    protected Drawable doInBackground(ListEntry... entries) {
                        return entries[0].loadIcon(getContext().getPackageManager());
                    }

                    @Override
                    protected void onPostExecute(Drawable drawable) {
                        if (!isCancelled()) {
                            iconView.setImageDrawable(drawable);
                            iconView.setVisibility(View.VISIBLE);
                        }
                        super.onPostExecute(drawable);
                    }
                };
                convertView.setTag(task);

                task.execute(entry);
            }

            TextView textView = (TextView) convertView.findViewById(R.id.name);
            textView.setText(entry.getLabel());

            TextView details = (TextView) convertView.findViewById(R.id.details);
            details.setText(entry.getPackageName());

            final Switch checkBox = (Switch) convertView.findViewById(R.id.checkbox);

            checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
                    /* No change, do nothing */
                    if (checked == MainActivity.config.whitelist.items.contains(entry.getPackageName()))
                        return;
                    if (checked) {
                        MainActivity.config.whitelist.items.add(entry.getPackageName());
                    } else {
                        MainActivity.config.whitelist.items.remove(entry.getPackageName());
                    }
                    FileHelper.writeSettings(getActivity(), MainActivity.config);
                }
            });

            View layout = convertView.findViewById(R.id.entry);
            layout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    checkBox.setChecked(!checkBox.isChecked());
                }
            });

            checkBox.setChecked(MainActivity.config.whitelist.items.contains(entry.getPackageName()));

            return convertView;
        }
    }

    private final class AppListGenerator extends AsyncTask<Void, Void, AppListAdapter> {
        private PackageManager pm;

        @Override
        protected AppListAdapter doInBackground(Void... params) {
            pm = getContext().getPackageManager();

            List<ApplicationInfo> info = pm.getInstalledApplications(0);

            Collections.sort(info, new ApplicationInfo.DisplayNameComparator(pm));

            final List<ListEntry> entries = new ArrayList<>();
            for (ApplicationInfo appInfo : info) {
                if (!appInfo.packageName.equals(BuildConfig.APPLICATION_ID)
                        && (MainActivity.config.whitelist.showSystemApps
                                || (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0))
                    entries.add(new ListEntry(appInfo, appInfo.packageName, appInfo.loadLabel(pm).toString()));
            }

            return new AppListAdapter(getContext(), R.layout.whitelist_row, entries);
        }

        @Override
        protected void onPostExecute(AppListAdapter adapter) {
            appList.setAdapter(adapter);
            swipeRefresh.setRefreshing(false);
        }
    }

    private class ListEntry {
        private ApplicationInfo appInfo;
        private String packageName;
        private String label;
        private WeakReference<Drawable> weakIcon;

        private ListEntry(ApplicationInfo appInfo, String packageName, String label) {
            this.appInfo = appInfo;
            this.packageName = packageName;
            this.label = label;
        }

        private String getPackageName() {
            return packageName;
        }

        private String getLabel() {
            return label;
        }

        private ApplicationInfo getAppInfo() {
            return appInfo;
        }

        private Drawable getIcon() {
            return weakIcon != null ? weakIcon.get() : null;
        }

        private Drawable loadIcon(PackageManager pm) {
            Drawable icon = weakIcon != null ? weakIcon.get() : null;
            if (icon == null) {
                icon = appInfo.loadIcon(pm);
                weakIcon = new WeakReference<>(icon);
            }
            return icon;
        }
    }
}