org.cyanogenmod.theme.chooser.ChooserBrowseFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.cyanogenmod.theme.chooser.ChooserBrowseFragment.java

Source

/*
 * Copyright (C) 2014 The CyanogenMod Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */
package org.cyanogenmod.theme.chooser;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.os.Build;
import android.view.Gravity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.content.res.ThemeConfig;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.ThemesContract;
import android.provider.ThemesContract.ThemesColumns;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.webkit.URLUtil;
import android.webkit.WebView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import org.cyanogenmod.theme.chooser.WallpaperAndIconPreviewFragment.IconInfo;
import org.cyanogenmod.theme.util.BootAnimationHelper;
import org.cyanogenmod.theme.util.IconPreviewHelper;
import org.cyanogenmod.theme.util.ThemedTypefaceHelper;
import org.cyanogenmod.theme.util.Utils;

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

import static android.content.pm.ThemeUtils.SYSTEM_TARGET_API;

public class ChooserBrowseFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
    public static final String TAG = ChooserBrowseFragment.class.getCanonicalName();
    public static final String DEFAULT = ThemeConfig.SYSTEM_DEFAULT;

    private static final String THEME_STORE_PACKAGE_NAME = "com.cyngn.theme.store";
    private static final String GET_THEMES_URL = "http://wiki.cyanogenmod.org/w/Get_Themes?action=render";
    private static final String THEME_STORE_ACTIVITY = "com.cyngn.theme.store.StoreActivity";

    public ListView mListView;
    public LocalPagerAdapter mAdapter;
    public ArrayList<String> mComponentFilters;

    private Point mMaxImageSize = new Point(); //Size of preview image in listview

    public static ChooserBrowseFragment newInstance(ArrayList<String> componentFilters) {
        ChooserBrowseFragment fragment = new ChooserBrowseFragment();
        Bundle args = new Bundle();
        args.putStringArrayList(ChooserActivity.EXTRA_COMPONENT_FILTER, componentFilters);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_chooser_browse, container, false);
        ArrayList<String> filters = getArguments().getStringArrayList(ChooserActivity.EXTRA_COMPONENT_FILTER);
        mComponentFilters = (filters != null) ? filters : new ArrayList<String>(0);
        // If we are filtering by "styles" add status bar and navigation bar to the list
        if (mComponentFilters.contains(ThemesColumns.MODIFIES_OVERLAYS)) {
            mComponentFilters.add(ThemesColumns.MODIFIES_STATUS_BAR);
            mComponentFilters.add(ThemesColumns.MODIFIES_NAVIGATION_BAR);
        }
        mListView = (ListView) v.findViewById(R.id.list);
        mAdapter = new LocalPagerAdapter(getActivity(), null, mComponentFilters);
        mListView.setAdapter(mAdapter);
        mListView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String pkgName = (String) mAdapter.getItem(position);
                ChooserDetailFragment fragment = ChooserDetailFragment.newInstance(pkgName, mComponentFilters);
                FragmentTransaction transaction = getFragmentManager().beginTransaction();
                transaction.replace(R.id.content, fragment, ChooserDetailFragment.class.toString());
                transaction.addToBackStack(null);
                transaction.commit();
            }
        });
        getLoaderManager().initLoader(0, null, this);

        Display display = getActivity().getWindowManager().getDefaultDisplay();
        display.getSize(mMaxImageSize);
        mMaxImageSize.y = (int) getActivity().getResources().getDimension(R.dimen.item_browse_height);

        return v;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.chooser_menu, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.get_more_themes:
            if (isThemeStoreInstalled()) {
                try {
                    launchThemeStore();
                } catch (ActivityNotFoundException e) {
                    launchGetThemesWebView();
                }
            } else {
                launchGetThemesWebView();
            }
            return true;
        }

        return false;
    }

    private boolean isThemeStoreInstalled() {
        PackageManager pm = getActivity().getPackageManager();
        try {
            pm.getPackageInfo(THEME_STORE_PACKAGE_NAME, PackageManager.GET_ACTIVITIES);
            return true;
        } catch (NameNotFoundException e) {
            return false;
        }
    }

    private void launchThemeStore() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(THEME_STORE_PACKAGE_NAME, THEME_STORE_ACTIVITY));
        getActivity().startActivity(intent);
    }

    private void launchGetThemesWebView() {
        Context context = getActivity();
        if (context == null)
            return;

        final WebView webView = new WebView(context);
        String html = createGetThemesHtml(context);
        webView.loadData(html.toString(), "text/html; charset=UTF-8", null);

        // Setup the dialog
        AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
        alert.setView(webView);
        Dialog dialog = alert.create();
        dialog.show();
    }

    private String createGetThemesHtml(Context context) {
        // Setup the webview with progress bar
        StringBuffer sb = new StringBuffer();
        sb.append("<html><body>");
        sb.append(getActivity().getString(R.string.get_more_description));
        sb.append("<ul>");

        String[] entryNames = context.getResources().getStringArray(R.array.get_more_entry_names);
        String[] entryUrls = context.getResources().getStringArray(R.array.get_more_entry_urls);
        for (int i = 0; i < entryNames.length; i++) {
            String name = entryNames[i];
            String url = entryUrls[i];
            appendLink(sb, name, url);
        }

        sb.append("</ul>");
        sb.append("</body></html>");
        return sb.toString();
    }

    private void appendLink(StringBuffer sb, String name, String url) {
        sb.append("<li>");
        sb.append("<a href=\"");
        sb.append(url);
        sb.append("\">");
        sb.append(name);
        sb.append("</a>");
        sb.append("</li>");
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        // Swap the new cursor in. (The framework will take care of closing the
        // old cursor once we return.)
        mAdapter.swapCursor(data);
        mAdapter.notifyDataSetChanged();
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mAdapter.swapCursor(null);
        mAdapter.notifyDataSetChanged();
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        String selection;
        String selectionArgs[] = null;
        if (mComponentFilters.isEmpty()) {
            selection = ThemesColumns.PRESENT_AS_THEME + "=?";
            selectionArgs = new String[] { "1" };
        } else {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < mComponentFilters.size(); i++) {
                sb.append(mComponentFilters.get(i));
                sb.append("=1");
                if (i != mComponentFilters.size() - 1) {
                    sb.append(" OR ");
                }
            }
            selection = sb.toString();
        }

        // sort in ascending order but make sure the "default" theme is always first
        String sortOrder = "(" + ThemesColumns.IS_DEFAULT_THEME + "=1) DESC, " + ThemesColumns.TITLE + " ASC";

        return new CursorLoader(getActivity(), ThemesColumns.CONTENT_URI, null, selection, selectionArgs,
                sortOrder);
    }

    public class LocalPagerAdapter extends CursorAdapter {
        List<String> mFilters;
        Context mContext;
        HashMap<String, ThemedTypefaceHelper> mTypefaceHelpers = new HashMap<String, ThemedTypefaceHelper>();

        public LocalPagerAdapter(Context context, Cursor c, List<String> filters) {
            super(context, c, 0);
            mFilters = filters;
            mContext = context;
        }

        @Override
        public Object getItem(int position) {
            mCursor.moveToPosition(position);
            int pkgIdx = mCursor.getColumnIndex(ThemesColumns.PKG_NAME);
            String pkgName = (String) mCursor.getString(pkgIdx);
            return pkgName;
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            int titleIdx = mCursor.getColumnIndex(ThemesColumns.TITLE);
            int authorIdx = mCursor.getColumnIndex(ThemesColumns.AUTHOR);
            int hsIdx = mCursor.getColumnIndex(ThemesColumns.HOMESCREEN_URI);
            int wpIdx = mCursor.getColumnIndex(ThemesColumns.WALLPAPER_URI);
            int styleIdx = mCursor.getColumnIndex(ThemesColumns.STYLE_URI);
            int pkgIdx = mCursor.getColumnIndex(ThemesColumns.PKG_NAME);
            int defaultIndex = mCursor.getColumnIndex(ThemesColumns.IS_DEFAULT_THEME);
            int targetApiIdx = mCursor.getColumnIndex(ThemesColumns.TARGET_API);

            String pkgName = mCursor.getString(pkgIdx);
            String title = DEFAULT.equals(pkgName) ? mContext.getString(R.string.system_theme_name)
                    : mCursor.getString(titleIdx);
            String author = mCursor.getString(authorIdx);
            String hsImagePath = DEFAULT.equals(pkgName) ? mCursor.getString(hsIdx) : mCursor.getString(wpIdx);
            String styleImagePath = mCursor.getString(styleIdx);
            boolean isDefaultTheme = mCursor.getInt(defaultIndex) == 1;

            ThemeItemHolder item = (ThemeItemHolder) view.getTag();
            item.title.setText(title + (isDefaultTheme ? " " + getString(R.string.default_tag) : ""));
            item.author.setText(author);

            int targetApi = mCursor.getInt(targetApiIdx);
            item.designedFor.setVisibility(
                    (targetApi == SYSTEM_TARGET_API || targetApi > Build.VERSION_CODES.KITKAT) ? View.GONE
                            : View.VISIBLE);

            if (mFilters.isEmpty()) {
                bindDefaultView(item, pkgName, hsImagePath);
            } else if (mFilters.contains(ThemesColumns.MODIFIES_BOOT_ANIM)) {
                bindBootAnimView(item, context, pkgName);
            } else if (mFilters.contains(ThemesColumns.MODIFIES_LAUNCHER)) {
                bindWallpaperView(item, pkgName, hsImagePath);
            } else if (mFilters.contains(ThemesColumns.MODIFIES_FONTS)) {
                bindFontView(view, context, pkgName);
            } else if (mFilters.contains(ThemesColumns.MODIFIES_OVERLAYS)) {
                bindOverlayView(item, pkgName, styleImagePath);
            } else if (mFilters.contains(ThemesColumns.MODIFIES_ICONS)) {
                bindDefaultView(item, pkgName, hsImagePath);
                bindIconView(view, context, pkgName);
            } else {
                bindDefaultView(item, pkgName, hsImagePath);
            }
        }

        private void bindDefaultView(ThemeItemHolder item, String pkgName, String hsImagePath) {
            //Do not load wallpaper if we preview icons
            if (mFilters.contains(ThemesColumns.MODIFIES_ICONS))
                return;

            item.thumbnail.setTag(pkgName);
            item.thumbnail.setImageDrawable(null);

            LoadImage loadImageTask = new LoadImage(item.thumbnail, pkgName, null);
            loadImageTask.execute();
        }

        private void bindOverlayView(ThemeItemHolder item, String pkgName, String styleImgPath) {
            item.thumbnail.setTag(pkgName);
            item.thumbnail.setImageDrawable(null);

            if (item.thumbnail.getTag() != null) {
                LoadImage loadImageTask = new LoadImage(item.thumbnail, pkgName, styleImgPath);
                loadImageTask.execute();
            }
        }

        private void bindBootAnimView(ThemeItemHolder item, Context context, String pkgName) {
            (new BootAnimationHelper.LoadBootAnimationImage(item.thumbnail, context, pkgName)).execute();
        }

        private void bindWallpaperView(ThemeItemHolder item, String pkgName, String hsImagePath) {

            item.thumbnail.setTag(pkgName);
            item.thumbnail.setImageDrawable(null);

            if (item.thumbnail.getTag() != null) {
                LoadImage loadImageTask = new LoadImage(item.thumbnail, pkgName, null);
                loadImageTask.execute();
            }
        }

        public void bindFontView(View view, Context context, String pkgName) {
            FontItemHolder item = (FontItemHolder) view.getTag();
            ThemedTypefaceHelper helper;
            if (!mTypefaceHelpers.containsKey(pkgName)) {
                helper = new ThemedTypefaceHelper();
                helper.load(mContext, pkgName);
                mTypefaceHelpers.put(pkgName, helper);
            } else {
                helper = mTypefaceHelpers.get(pkgName);
            }
            Typeface typefaceNormal = helper.getTypeface(Typeface.NORMAL);
            Typeface typefaceBold = helper.getTypeface(Typeface.BOLD);
            item.textView.setTypeface(typefaceNormal);
            item.textViewBold.setTypeface(typefaceBold);
        }

        public void bindIconView(View view, Context context, String pkgName) {
            ThemeItemHolder holder = (ThemeItemHolder) view.getTag();
            LoadIconsTask loadImageTask = new LoadIconsTask(context, pkgName, holder.mIconHolders);
            loadImageTask.execute();
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            if (mComponentFilters.isEmpty()) {
                return newDefaultView(context, cursor, parent);
            } else if (mComponentFilters.contains(ThemesColumns.MODIFIES_FONTS)) {
                return newFontView(context, cursor, parent);
            } else if (mComponentFilters.contains(ThemesColumns.MODIFIES_ICONS)) {
                return newDefaultView(context, cursor, parent);
            }
            return newDefaultView(context, cursor, parent);
        }

        private View newDefaultView(Context context, Cursor cursor, ViewGroup parent) {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            View row = inflater.inflate(R.layout.item_store_browse, parent, false);
            ThemeItemHolder item = new ThemeItemHolder();
            item.thumbnail = (ImageView) row.findViewById(R.id.image);
            item.title = (TextView) row.findViewById(R.id.title);
            item.author = (TextView) row.findViewById(R.id.author);
            item.designedFor = (TextView) row.findViewById(R.id.designed_for);
            item.mIconHolders = (ViewGroup) row.findViewById(R.id.icon_container);
            row.setTag(item);
            return row;
        }

        private View newFontView(Context context, Cursor cursor, ViewGroup parent) {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            View row = inflater.inflate(R.layout.item_chooser_browse_font, parent, false);
            FontItemHolder item = new FontItemHolder();
            item.textView = (TextView) row.findViewById(R.id.text1);
            item.textViewBold = (TextView) row.findViewById(R.id.text2);
            item.title = (TextView) row.findViewById(R.id.title);
            item.author = (TextView) row.findViewById(R.id.author);
            item.designedFor = (TextView) row.findViewById(R.id.designed_for);
            row.setTag(item);
            return row;
        }
    }

    public static class ThemeItemHolder {
        ImageView thumbnail;
        TextView title;
        TextView author;
        TextView designedFor;
        ViewGroup mIconHolders;
    }

    public static class FontItemHolder extends ThemeItemHolder {
        TextView textView;
        TextView textViewBold;
    }

    public class LoadImage extends AsyncTask<Object, Void, Bitmap> {
        private ImageView imv;
        private String path;
        private String pkgName;

        public LoadImage(ImageView imv, String pkgName, String path) {
            this.imv = imv;
            this.path = path;
            this.pkgName = pkgName;
        }

        @Override
        protected Bitmap doInBackground(Object... params) {
            Bitmap bitmap = null;
            Context context = getActivity();
            if (context == null) {
                Log.d(TAG, "Activity was detached, skipping loadImage");
                return null;
            }

            if (DEFAULT.equals(pkgName)) {
                Resources res = context.getResources();
                AssetManager assets = new AssetManager();
                assets.addAssetPath(WallpaperAndIconPreviewFragment.FRAMEWORK_RES);
                Resources frameworkRes = new Resources(assets, res.getDisplayMetrics(), res.getConfiguration());
                bitmap = Utils.decodeResource(frameworkRes, com.android.internal.R.drawable.default_wallpaper,
                        mMaxImageSize.x, mMaxImageSize.y);
            } else {
                if (URLUtil.isAssetUrl(path)) {
                    Context ctx = context;
                    try {
                        ctx = context.createPackageContext(pkgName, 0);
                    } catch (PackageManager.NameNotFoundException e) {

                    }
                    bitmap = Utils.getBitmapFromAsset(ctx, path, mMaxImageSize.x, mMaxImageSize.y);
                } else if (path != null) {
                    bitmap = Utils.decodeFile(path, mMaxImageSize.x, mMaxImageSize.y);
                } else {
                    bitmap = Utils.getPreviewBitmap(context, pkgName,
                            ThemesContract.PreviewColumns.WALLPAPER_PREVIEW);
                }
            }
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            if (!imv.getTag().toString().equals(pkgName)) {
                return;
            }

            if (result != null && imv != null) {
                imv.setVisibility(View.VISIBLE);
                imv.setImageBitmap(result);
            }
        }
    }

    public static class LoadIconsTask extends AsyncTask<Void, Void, List<IconInfo>> {
        private String mPkgName;
        private Context mContext;
        private ViewGroup mIconViewGroup;

        public LoadIconsTask(Context context, String pkgName, ViewGroup iconViewGroup) {
            mPkgName = pkgName;
            mContext = context.getApplicationContext();
            mIconViewGroup = iconViewGroup;
            mIconViewGroup.setTag(pkgName);
        }

        @Override
        protected List<IconInfo> doInBackground(Void... arg0) {
            List<IconInfo> icons = new ArrayList<IconInfo>();
            IconPreviewHelper helper = new IconPreviewHelper(mContext, mPkgName);

            for (ComponentName component : WallpaperAndIconPreviewFragment.getIconComponents(mContext)) {
                Drawable icon = helper.getIcon(component);
                IconInfo info = new IconInfo(null, icon);
                icons.add(info);
            }

            return icons;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mIconViewGroup.removeAllViews();
        }

        @Override
        protected void onPostExecute(List<IconInfo> icons) {
            if (!mIconViewGroup.getTag().toString().equals(mPkgName) || icons == null) {
                return;
            }

            for (IconInfo info : icons) {
                LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(0, LayoutParams.WRAP_CONTENT, 1f);
                lparams.weight = 1f / icons.size();

                // Sizes of composed icons differ in size from other icons when using
                // ImageView.  Using a TextView like in WallpaperAndIconPreviewFragment
                // displays the icons as the correct size.
                TextView tv = new TextView(mContext);
                tv.setGravity(Gravity.CENTER_HORIZONTAL);
                tv.setLayoutParams(lparams);
                tv.setCompoundDrawables(null, info.icon, null, null);
                mIconViewGroup.addView(tv);
            }
        }
    }
}