package net.micode.fileexplorer; import android.app.Activity; import android.app.Fragment; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; import android.widget.TextView; import net.micode.fileexplorer.FavoriteDatabaseHelper.FavoriteDatabaseListener; import net.micode.fileexplorer.FileCategoryHelper.CategoryInfo; import net.micode.fileexplorer.FileCategoryHelper.FileCategory; import net.micode.fileexplorer.FileExplorerTabActivity.IBackPressedListener; import net.micode.fileexplorer.FileViewInteractionHub.Mode; import net.micode.fileexplorer.Util.SDCardInfo; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Timer; import java.util.TimerTask; public class FileCategoryActivity extends Fragment implements IFileInteractionListener, FavoriteDatabaseListener, IBackPressedListener { public static final String EXT_FILETER_KEY = "ext_filter"; private static final String LOG_TAG = "FileCategoryActivity"; private static HashMap<Integer, FileCategory> button2Category = new HashMap<Integer, FileCategory>(); private HashMap<FileCategory, Integer> categoryIndex = new HashMap<FileCategory, Integer>(); private FileListCursorAdapter mAdapter; private FileViewInteractionHub mFileViewInteractionHub; private FileCategoryHelper mFileCagetoryHelper; private FileIconHelper mFileIconHelper; private CategoryBar mCategoryBar; private ScannerReceiver mScannerReceiver; private FavoriteList mFavoriteList; private ViewPage curViewPage = ViewPage.Invalid; private ViewPage preViewPage = ViewPage.Invalid; private Activity mActivity; private View mRootView; private FileViewActivity mFileViewActivity; private boolean mConfigurationChanged = false; public void setConfigurationChanged(boolean changed) { mConfigurationChanged = changed; } static { button2Category.put(R.id.category_music, FileCategory.Music); button2Category.put(R.id.category_video, FileCategory.Video); button2Category.put(R.id.category_picture, FileCategory.Picture); button2Category.put(R.id.category_theme, FileCategory.Theme); button2Category.put(R.id.category_document, FileCategory.Doc); button2Category.put(R.id.category_zip, FileCategory.Zip); button2Category.put(R.id.category_apk, FileCategory.Apk); button2Category.put(R.id.category_favorite, FileCategory.Favorite); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mActivity = getActivity(); mFileViewActivity = (FileViewActivity) ((FileExplorerTabActivity) mActivity) .getFragment(Util.SDCARD_TAB_INDEX); mRootView = inflater.inflate(R.layout.file_explorer_category, container, false); curViewPage = ViewPage.Invalid; mFileViewInteractionHub = new FileViewInteractionHub(this); mFileViewInteractionHub.setMode(Mode.View); mFileViewInteractionHub.setRootPath("/"); mFileIconHelper = new FileIconHelper(mActivity); mFavoriteList = new FavoriteList(mActivity, (ListView) mRootView.findViewById(R.id.favorite_list), this, mFileIconHelper); mFavoriteList.initList(); mAdapter = new FileListCursorAdapter(mActivity, null, mFileViewInteractionHub, mFileIconHelper); ListView fileListView = (ListView) mRootView.findViewById(R.id.file_path_list); fileListView.setAdapter(mAdapter); setupClick(); setupCategoryInfo(); updateUI(); registerScannerReceiver(); return mRootView; } private void registerScannerReceiver() { mScannerReceiver = new ScannerReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED); intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED); intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); intentFilter.addDataScheme("file"); mActivity.registerReceiver(mScannerReceiver, intentFilter); } private void setupCategoryInfo() { mFileCagetoryHelper = new FileCategoryHelper(mActivity); mCategoryBar = (CategoryBar) mRootView.findViewById(R.id.category_bar); int[] imgs = new int[] { R.drawable.category_bar_music, R.drawable.category_bar_video, R.drawable.category_bar_picture, R.drawable.category_bar_theme, R.drawable.category_bar_document, R.drawable.category_bar_zip, R.drawable.category_bar_apk, R.drawable.category_bar_other }; for (int i = 0; i < imgs.length; i++) { mCategoryBar.addCategory(imgs[i]); } for (int i = 0; i < FileCategoryHelper.sCategories.length; i++) { categoryIndex.put(FileCategoryHelper.sCategories[i], i); } } public void refreshCategoryInfo() { SDCardInfo sdCardInfo = Util.getSDCardInfo(); if (sdCardInfo != null) { mCategoryBar.setFullValue(sdCardInfo.total); setTextView(R.id.sd_card_capacity, getString(R.string.sd_card_size, Util.convertStorage(sdCardInfo.total))); setTextView(R.id.sd_card_available, getString(R.string.sd_card_available, Util.convertStorage(sdCardInfo.free))); } mFileCagetoryHelper.refreshCategoryInfo(); // the other category size should include those files didn't get scanned. long size = 0; for (FileCategory fc : FileCategoryHelper.sCategories) { CategoryInfo categoryInfo = mFileCagetoryHelper.getCategoryInfos().get(fc); setCategoryCount(fc, categoryInfo.count); // other category size should be set separately with calibration if(fc == FileCategory.Other) continue; setCategorySize(fc, categoryInfo.size); setCategoryBarValue(fc, categoryInfo.size); size += categoryInfo.size; } if (sdCardInfo != null) { long otherSize = sdCardInfo.total - sdCardInfo.free - size; setCategorySize(FileCategory.Other, otherSize); setCategoryBarValue(FileCategory.Other, otherSize); } setCategoryCount(FileCategory.Favorite, mFavoriteList.getCount()); if (mCategoryBar.getVisibility() == View.VISIBLE) { mCategoryBar.startAnimation(); } } public enum ViewPage { Home, Favorite, Category, NoSD, Invalid } private void showPage(ViewPage p) { if (curViewPage == p) return; curViewPage = p; showView(R.id.file_path_list, false); showView(R.id.navigation_bar, false); showView(R.id.category_page, false); showView(R.id.operation_bar, false); showView(R.id.sd_not_available_page, false); mFavoriteList.show(false); showEmptyView(false); switch (p) { case Home: showView(R.id.category_page, true); if (mConfigurationChanged) { ((FileExplorerTabActivity) mActivity).reInstantiateCategoryTab(); mConfigurationChanged = false; } break; case Favorite: showView(R.id.navigation_bar, true); mFavoriteList.show(true); showEmptyView(mFavoriteList.getCount() == 0); break; case Category: showView(R.id.navigation_bar, true); showView(R.id.file_path_list, true); showEmptyView(mAdapter.getCount() == 0); break; case NoSD: showView(R.id.sd_not_available_page, true); break; } } private void showEmptyView(boolean show) { View emptyView = mActivity.findViewById(R.id.empty_view); if (emptyView != null) emptyView.setVisibility(show ? View.VISIBLE : View.GONE); } private void showView(int id, boolean show) { View view = mRootView.findViewById(id); if (view != null) { view.setVisibility(show ? View.VISIBLE : View.GONE); } } View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { FileCategory f = button2Category.get(v.getId()); if (f != null) { onCategorySelected(f); if (f != FileCategory.Favorite) { setHasOptionsMenu(true); } } } }; private void setCategoryCount(FileCategory fc, long count) { int id = getCategoryCountId(fc); if (id == 0) return; setTextView(id, "(" + count + ")"); } private void setTextView(int id, String t) { TextView text = (TextView) mRootView.findViewById(id); text.setText(t); } private void onCategorySelected(FileCategory f) { if (mFileCagetoryHelper.getCurCategory() != f) { mFileCagetoryHelper.setCurCategory(f); mFileViewInteractionHub.setCurrentPath(mFileViewInteractionHub.getRootPath() + getString(mFileCagetoryHelper.getCurCategoryNameResId())); mFileViewInteractionHub.refreshFileList(); } if (f == FileCategory.Favorite) { showPage(ViewPage.Favorite); } else { showPage(ViewPage.Category); } } private void setupClick(int id) { View button = mRootView.findViewById(id); button.setOnClickListener(onClickListener); } private void setupClick() { setupClick(R.id.category_music); setupClick(R.id.category_video); setupClick(R.id.category_picture); setupClick(R.id.category_theme); setupClick(R.id.category_document); setupClick(R.id.category_zip); setupClick(R.id.category_apk); setupClick(R.id.category_favorite); } @Override public boolean onBack() { if (isHomePage() || curViewPage == ViewPage.NoSD || mFileViewInteractionHub == null) { return false; } return mFileViewInteractionHub.onBackPressed(); } public boolean isHomePage() { return curViewPage == ViewPage.Home; } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { if (curViewPage != ViewPage.Category && curViewPage != ViewPage.Favorite) { return; } mFileViewInteractionHub.onCreateOptionsMenu(menu); } @Override public void onPrepareOptionsMenu(Menu menu) { if (!isHomePage() && mFileCagetoryHelper.getCurCategory() != FileCategory.Favorite) { mFileViewInteractionHub.onPrepareOptionsMenu(menu); } } public boolean onRefreshFileList(String path, FileSortHelper sort) { FileCategory curCategory = mFileCagetoryHelper.getCurCategory(); if (curCategory == FileCategory.Favorite || curCategory == FileCategory.All) return false; Cursor c = mFileCagetoryHelper.query(curCategory, sort.getSortMethod()); showEmptyView(c == null || c.getCount() == 0); mAdapter.changeCursor(c); return true; } @Override public View getViewById(int id) { return mRootView.findViewById(id); } @Override public Context getContext() { return mActivity; } @Override public void onDataChanged() { runOnUiThread(new Runnable() { @Override public void run() { mAdapter.notifyDataSetChanged(); mFavoriteList.getArrayAdapter().notifyDataSetChanged(); showEmptyView(mAdapter.getCount() == 0); } }); } @Override public void onPick(FileInfo f) { // do nothing } @Override public boolean shouldShowOperationPane() { return true; } @Override public boolean onOperation(int id) { mFileViewInteractionHub.addContextMenuSelectedItem(); switch (id) { case R.id.button_operation_copy: case GlobalConsts.MENU_COPY: copyFileInFileView(mFileViewInteractionHub.getSelectedFileList()); mFileViewInteractionHub.clearSelection(); break; case R.id.button_operation_move: case GlobalConsts.MENU_MOVE: startMoveToFileView(mFileViewInteractionHub.getSelectedFileList()); mFileViewInteractionHub.clearSelection(); break; case GlobalConsts.OPERATION_UP_LEVEL: setHasOptionsMenu(false); showPage(ViewPage.Home); break; default: return false; } return true; } @Override public String getDisplayPath(String path) { return getString(R.string.tab_category) + path; } @Override public String getRealPath(String displayPath) { return ""; } @Override public boolean onNavigation(String path) { showPage(ViewPage.Home); return true; } @Override public boolean shouldHideMenu(int menu) { return (menu == GlobalConsts.MENU_NEW_FOLDER || menu == GlobalConsts.MENU_FAVORITE || menu == GlobalConsts.MENU_PASTE || menu == GlobalConsts.MENU_SHOWHIDE); } @Override public void addSingleFile(FileInfo file) { refreshList(); } @Override public Collection<FileInfo> getAllFiles() { return mAdapter.getAllFiles(); } @Override public FileInfo getItem(int pos) { return mAdapter.getFileItem(pos); } @Override public int getItemCount() { return mAdapter.getCount(); } @Override public void sortCurrentList(FileSortHelper sort) { refreshList(); } private void refreshList() { mFileViewInteractionHub.refreshFileList(); } private void copyFileInFileView(ArrayList<FileInfo> files) { if (files.size() == 0) return; mFileViewActivity.copyFile(files); mActivity.getActionBar().setSelectedNavigationItem(Util.SDCARD_TAB_INDEX); } private void startMoveToFileView(ArrayList<FileInfo> files) { if (files.size() == 0) return; mFileViewActivity.moveToFile(files); mActivity.getActionBar().setSelectedNavigationItem(Util.SDCARD_TAB_INDEX); } @Override public FileIconHelper getFileIconHelper() { return mFileIconHelper; } private static int getCategoryCountId(FileCategory fc) { switch (fc) { case Music: return R.id.category_music_count; case Video: return R.id.category_video_count; case Picture: return R.id.category_picture_count; case Theme: return R.id.category_theme_count; case Doc: return R.id.category_document_count; case Zip: return R.id.category_zip_count; case Apk: return R.id.category_apk_count; case Favorite: return R.id.category_favorite_count; } return 0; } private void setCategorySize(FileCategory fc, long size) { int txtId = 0; int resId = 0; switch (fc) { case Music: txtId = R.id.category_legend_music; resId = R.string.category_music; break; case Video: txtId = R.id.category_legend_video; resId = R.string.category_video; break; case Picture: txtId = R.id.category_legend_picture; resId = R.string.category_picture; break; case Theme: txtId = R.id.category_legend_theme; resId = R.string.category_theme; break; case Doc: txtId = R.id.category_legend_document; resId = R.string.category_document; break; case Zip: txtId = R.id.category_legend_zip; resId = R.string.category_zip; break; case Apk: txtId = R.id.category_legend_apk; resId = R.string.category_apk; break; case Other: txtId = R.id.category_legend_other; resId = R.string.category_other; break; } if (txtId == 0 || resId == 0) return; setTextView(txtId, getString(resId) + ":" + Util.convertStorage(size)); } private void setCategoryBarValue(FileCategory f, long size) { if (mCategoryBar == null) { mCategoryBar = (CategoryBar) mRootView.findViewById(R.id.category_bar); } mCategoryBar.setCategoryValue(categoryIndex.get(f), size); } public void onDestroy() { super.onDestroy(); if (mActivity != null) { mActivity.unregisterReceiver(mScannerReceiver); } } private class ScannerReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.v(LOG_TAG, "received broadcast: " + action.toString()); // handle intents related to external storage if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED) || action.equals(Intent.ACTION_MEDIA_MOUNTED) || action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) { notifyFileChanged(); } } } private void updateUI() { boolean sdCardReady = Util.isSDCardReady(); if (sdCardReady) { if (preViewPage != ViewPage.Invalid) { showPage(preViewPage); preViewPage = ViewPage.Invalid; } else if (curViewPage == ViewPage.Invalid || curViewPage == ViewPage.NoSD) { showPage(ViewPage.Home); } refreshCategoryInfo(); // refresh file list mFileViewInteractionHub.refreshFileList(); // refresh file list view in another tab mFileViewActivity.refresh(); } else { preViewPage = curViewPage; showPage(ViewPage.NoSD); } } // process file changed notification, using a timer to avoid frequent // refreshing due to batch changing on file system synchronized public void notifyFileChanged() { if (timer != null) { timer.cancel(); } timer = new Timer(); timer.schedule(new TimerTask() { public void run() { timer = null; Message message = new Message(); message.what = MSG_FILE_CHANGED_TIMER; handler.sendMessage(message); } }, 1000); } private static final int MSG_FILE_CHANGED_TIMER = 100; private Timer timer; private Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case MSG_FILE_CHANGED_TIMER: updateUI(); break; } super.handleMessage(msg); } }; // update the count of favorite @Override public void onFavoriteDatabaseChanged() { setCategoryCount(FileCategory.Favorite, mFavoriteList.getCount()); } @Override public void runOnUiThread(Runnable r) { mActivity.runOnUiThread(r); } }