jahirfiquitiva.iconshowcase.tasks.LoadAppsToRequest.java Source code

Java tutorial

Introduction

Here is the source code for jahirfiquitiva.iconshowcase.tasks.LoadAppsToRequest.java

Source

/*
 * Copyright (c) 2016.  Jahir Fiquitiva
 *
 * Licensed under the CreativeCommons Attribution-ShareAlike
 * 4.0 International License. You may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *    http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Big thanks to the project contributors. Check them in the repository.
 *
 */

/*
 *
 */

package jahirfiquitiva.iconshowcase.tasks;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.support.v4.util.SimpleArrayMap;
import android.util.DisplayMetrics;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import jahirfiquitiva.iconshowcase.R;
import jahirfiquitiva.iconshowcase.fragments.RequestsFragment;
import jahirfiquitiva.iconshowcase.models.AppFilterError;
import jahirfiquitiva.iconshowcase.models.RequestItem;
import jahirfiquitiva.iconshowcase.models.RequestList;
import jahirfiquitiva.iconshowcase.utilities.Utils;

public class LoadAppsToRequest extends AsyncTask<Void, String, ArrayList<RequestItem>> {

    private static PackageManager mPackageManager;
    private static boolean debugging = false;
    private final static ArrayList<String> components = new ArrayList<>();
    private final static ArrayList<RequestItem> appsList = new ArrayList<>();
    private final static ArrayList<AppFilterError> appFilterErrors = new ArrayList<>();
    private final WeakReference<Context> context;
    private final long startTime;
    private static final String TASK = "AppsToRequest";

    @SuppressLint("PrivateResource")
    public LoadAppsToRequest(Context context) {
        startTime = System.currentTimeMillis();
        this.context = new WeakReference<>(context);

        debugging = context.getResources().getBoolean(R.bool.debugging);

        mPackageManager = context.getPackageManager();

        ArrayList<ResolveInfo> rAllActivitiesList = (ArrayList<ResolveInfo>) context.getPackageManager()
                .queryIntentActivities(getAllActivitiesIntent(), 0);

        for (ResolveInfo info : rAllActivitiesList) {

            if (info.activityInfo.packageName.equals(context.getApplicationContext().getPackageName())) {
                continue;
            }

            RequestItem appInfo = new RequestItem(info.loadLabel(mPackageManager).toString(),
                    info.activityInfo.packageName, info.activityInfo.name, getAppIcon(info),
                    getNormalAppIcon(info, mPackageManager));

            appsList.add(appInfo);
        }

    }

    @Override
    protected void onPreExecute() {

    }

    @Override
    protected ArrayList<RequestItem> doInBackground(Void... params) {

        appsList.removeAll(createListFromXML(context.get()));

        Collections.sort(appsList, new Comparator<RequestItem>() {
            @Override
            public int compare(RequestItem a, RequestItem b) {
                return a.getAppName().compareToIgnoreCase(b.getAppName());
            }
        });

        return appsList;
    }

    @Override
    protected void onPostExecute(ArrayList<RequestItem> list) {
        RequestList.setRequestList(list);
        RequestsFragment.setupContent(RequestsFragment.layout, context.get());
        if (list != null) {
            long endTime = System.currentTimeMillis();
            Utils.showLog(context.get(), "Apps to Request Task completed in: "
                    + String.valueOf((endTime - startTime) / 1000) + " secs.");
        }
        if (debugging) {
            if (appFilterErrors != null) {
                showAppFilterErrors(appFilterErrors, context.get());
            }
            if (components != null) {
                showDuplicatedComponentsInLog(components, context.get());
            }
        }
    }

    private static ResolveInfo getResolveInfo(String componentString) {
        Intent intent = new Intent();

        // Example format:
        //intent.setComponent(new ComponentName("com.myapp", "com.myapp.launcher.settings"));

        if (componentString != null) {
            String[] split = null;
            try {
                split = componentString.split("/");
            } catch (ArrayIndexOutOfBoundsException e) {
                //Do nothing
            }
            if (split != null) {
                try {
                    components.add(componentString);
                    intent.setComponent(new ComponentName(split[0], split[1]));
                } catch (ArrayIndexOutOfBoundsException e1) {
                    //Do nothing
                }
            }
            return mPackageManager.resolveActivity(intent, 0);
        } else {
            return null;
        }
    }

    private static String gComponentString(XmlPullParser xmlParser, Context context) {

        boolean halfEmptyPack = false, halfEmptyComp = false;

        try {

            final String initialComponent = xmlParser.getAttributeValue(null, "component").split("/")[1];
            final String finalComponent = initialComponent.substring(0, initialComponent.length() - 1);
            final String initialComponentPackage = xmlParser.getAttributeValue(null, "component").split("/")[0];
            final String finalComponentPackage = initialComponentPackage.substring(14,
                    initialComponentPackage.length());

            if (finalComponentPackage.equals("")) {
                halfEmptyPack = true;
            } else if (finalComponent.equals("")) {
                halfEmptyComp = true;
            }

            final String iconName = getIconName(xmlParser);

            String emptyComponent = finalComponentPackage + finalComponent;
            String completeComponent = finalComponentPackage + "/" + finalComponent;

            boolean error = emptyComponent.equals("") || halfEmptyPack || halfEmptyComp;

            if (debugging) {
                appFilterErrors.add(new AppFilterError(emptyComponent.equals(""), halfEmptyPack, halfEmptyComp,
                        iconName, completeComponent, Utils.getIconResId(context, context.getResources(),
                                context.getPackageName(), iconName, TASK)));
            }

            if (error || iconName.equals("")) {
                return null;
            } else {
                return completeComponent;
            }

        } catch (Exception e) {
            //Do nothing
        }

        return null;

    }

    private static String getIconName(XmlPullParser xmlParser) {
        return xmlParser.getAttributeValue(null, "drawable");
    }

    private Intent getAllActivitiesIntent() {
        Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        return mainIntent;
    }

    @SuppressLint("PrivateResource")
    private ArrayList<RequestItem> createListFromXML(Context context) {

        ArrayList<RequestItem> activitiesToRemove = new ArrayList<>();

        try {

            XmlPullParserFactory xmlFactory = XmlPullParserFactory.newInstance();
            XmlPullParser xmlParser = xmlFactory.newPullParser();
            InputStream inputStream = context.getResources().openRawResource(R.raw.appfilter);
            xmlParser.setInput(inputStream, null);

            int activity = xmlParser.getEventType();

            while (activity != XmlPullParser.END_DOCUMENT) {

                String name = xmlParser.getName();

                switch (activity) {
                case XmlPullParser.START_TAG:
                    break;
                case XmlPullParser.END_TAG:

                    if (name.equals("item")) {

                        ResolveInfo info = getResolveInfo(gComponentString(xmlParser, context));

                        if (info != null) {

                            RequestItem appInfo = new RequestItem(info.loadLabel(mPackageManager).toString(),
                                    info.activityInfo.packageName, info.activityInfo.name, getAppIcon(info),
                                    getNormalAppIcon(info, mPackageManager));

                            activitiesToRemove.add(appInfo);
                        }
                    }

                    break;
                }

                activity = xmlParser.next();
            }

        } catch (IOException | XmlPullParserException e) {
            //Do nothing
        }

        return activitiesToRemove;
    }

    private static void showAppFilterErrors(ArrayList<AppFilterError> errors, Context context) {

        Utils.showAppFilterLog(context, "----- START OF APPFILTER DEBUG -----");

        for (AppFilterError error : errors) {
            String iconName = error.getIconName();
            if (iconName.equals("")) {
                Utils.showAppFilterLog(context,
                        "Found empty drawable for component: \'" + error.getCompleteComponent() + "\'");
            } else {
                if (error.hasEmptyComponent()) {
                    Utils.showAppFilterLog(context, "Found empty ComponentInfo for icon: \'" + iconName + "\'");
                } else if (error.hasHalfEmptyPackage()) {
                    Utils.showAppFilterLog(context, "Found empty component package for icon: \'" + iconName + "\'");
                } else if (error.hasHalfEmptyComponent()) {
                    Utils.showAppFilterLog(context, "Found empty component for icon: \'" + iconName + "\'");
                }
                if (error.getIconID() == 0) {
                    Utils.showAppFilterLog(context, "Icon \'" + iconName
                            + "\' is mentioned in appfilter.xml but could not be found in the app resources.");
                }
            }
        }
    }

    private static void showDuplicatedComponentsInLog(ArrayList<String> components, Context context) {

        String[] componentsArray = new String[components.size()];
        componentsArray = components.toArray(componentsArray);

        SimpleArrayMap<String, Integer> occurrences = new SimpleArrayMap<>();

        int count = 0;

        for (String word : componentsArray) {
            count = occurrences.get(word) == null ? 0 : occurrences.get(word);
            occurrences.put(word, count + 1);
        }

        for (int i = 0; i < occurrences.size(); i++) {
            String word = occurrences.keyAt(i);
            if (count > 0) {
                Utils.showAppFilterLog(context,
                        "Duplicated component: \'" + word + "\' - " + String.valueOf(count) + " times.");
            }
        }

        Utils.showAppFilterLog(context, "----- END OF APPFILTER DEBUG -----");

    }

    public Drawable getAppDefaultActivityIcon() {
        return getAppIcon(Resources.getSystem(), android.R.mipmap.sym_def_app_icon);
    }

    @SuppressWarnings("deprecation")
    public Drawable getAppIcon(Resources resources, int iconId) {
        Drawable d;
        try {
            int iconDpi;

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                iconDpi = DisplayMetrics.DENSITY_XXXHIGH;
            } else {
                iconDpi = DisplayMetrics.DENSITY_XXHIGH;
            }

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                d = resources.getDrawableForDensity(iconId, iconDpi, null);
            } else {
                d = resources.getDrawableForDensity(iconId, iconDpi);
            }

        } catch (Resources.NotFoundException e) {
            try {
                d = ContextCompat.getDrawable(context.get(), R.drawable.ic_na_launcher);
            } catch (Resources.NotFoundException e1) {
                d = null;
            }
        }

        return (d != null) ? d : getAppDefaultActivityIcon();
    }

    public Drawable getAppIcon(ResolveInfo info) {
        return getAppIcon(info.activityInfo);
    }

    public Drawable getAppIcon(ActivityInfo info) {
        Resources resources;
        try {
            resources = context.get().getPackageManager().getResourcesForApplication(info.applicationInfo);
        } catch (PackageManager.NameNotFoundException e) {
            resources = null;
        }
        if (resources != null) {
            int iconId = info.getIconResource();
            if (iconId != 0) {
                return getAppIcon(resources, iconId);
            }
        }
        return getAppDefaultActivityIcon();
    }

    private Drawable getNormalAppIcon(ResolveInfo info, PackageManager pm) {
        if (info != null) {
            return info.loadIcon(pm);
        } else {
            return getAppDefaultActivityIcon();
        }
    }

}