package com.sparseboolean.ifexplorer; import gem.com.slidinglayer.SlidingLayer; import gem.kevin.innov.FilePathUrlManager; import gem.kevin.util.DataUtil; import gem.kevin.util.StorageUtil; import gem.kevin.widget.DropableListView; import java.io.File; import java.util.HashSet; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.RelativeLayout.LayoutParams; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.Toast; import com.sparseboolean.ifexplorer.IfAppController.FileDataListAdapter; import com.sparseboolean.ifexplorer.ui.DeviceDataAdapter; import com.sparseboolean.ifexplorer.ui.FilePathNavigator; import com.sparseboolean.ifexplorer.ui.TaskGroupListWidget; import com.sparseboolean.ifexplorer.ui.FilePathNavigator.NavigationCallback; import com.sparseboolean.ifexplorer.R; public class IfFileChooser extends Activity implements OnItemClickListener, NavigationCallback, IfAppController.DeviceDataListener, IfAppController.UiCallback { private static final String TAG = "IfExplorer-IfFileChooser"; private static final boolean KLOG = true; private static final String KEY_SAVE_LOCATION = "location"; private String mInitLocation; private FilePathUrlManager mFileManager; private IfAppController mAppController; private FileDataListAdapter mFileDataListAdapter; private DropableListView mFileListView; private ImageView mCollectionSwitchButton; private SlidingLayer mSlidingLayer; // Task groups private HashSet<TaskGroupListWidget> mMiniPanelWidgets = new HashSet<TaskGroupListWidget>(); // Devices private TaskGroupListWidget mInternalStorageMiniWidget; private TaskGroupListWidget mSdcardMiniWidget; private TaskGroupListWidget mUsb1StorageMiniWidget; private TaskGroupListWidget mUsb2StorageMiniWidget; private TaskGroupListWidget mUsb3StorageMiniWidget; private TaskGroupListWidget mUsb4StorageMiniWidget; private TaskGroupListWidget mStorageA_MiniWidget; private TaskGroupListWidget mStorageB_MiniWidget; private TaskGroupListWidget mStorageC_MiniWidget; private TaskGroupListWidget mStorageD_MiniWidget; private static final int kTagTaskGroupBase = 0; private AbsListView mCurrentShowList; private FilePathNavigator mPathNavigator; private Button mCancelButton; /* Storage monitoring */ private IntentFilter mStorageIntentFilter; private BroadcastReceiver mStorageBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); String path = intent.getData().getPath(); Log.i(TAG, "ACTION: " + action + " happened on path: " + path); if (mAppController != null) { if (mFileManager.getCurrentUrl().contains(path)) { Log.i(TAG, "CONTAINS"); if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED) || action.equals(Intent.ACTION_MEDIA_BAD_REMOVAL)) { // Update to a null directory at once. // It's a tricky to make IF release possible possessive // file descriptors // so it won't get killed by ActivityManager mAppController.updateDirectory(null); mAppController.updateDirectory(mFileManager .getNextUrlContent(StorageUtil.getHomeDir(), true, false)); } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) { mAppController.updateDirectory(mFileManager .refreshUrlContent()); } } if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) { mAppController.updateStorageDevice(path, Environment.MEDIA_MOUNTED, true); } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) { mAppController.updateStorageDevice(path, Environment.MEDIA_UNMOUNTED, true); // URL starts with this path now become invalid mFileManager.removeInvalidUrls(path); } else if (action.equals(Intent.ACTION_MEDIA_BAD_REMOVAL)) { mAppController.updateStorageDevice(path, Environment.MEDIA_BAD_REMOVAL, true); mFileManager.removeInvalidUrls(path); } else { return; } } } }; public void handleFileItemClick(ArrayAdapter<FileItem> fileDataAdapter, View view, int position, long id) { final String path = fileDataAdapter.getItem(position).getPath(); File file = new File(path); String item_ext = null; try { item_ext = path.substring(path.lastIndexOf("."), path.length()); } catch (IndexOutOfBoundsException e) { item_ext = ""; } if (!item_ext.equals("")) { item_ext = DataUtil.getFileExtensionWithoutDot(item_ext); } if (file.isDirectory()) { if (file.canRead()) { mAppController.stopThumbnailThread(); mAppController.updateDirectory(mFileManager.getNextUrlContent( path, true, false)); // When entering a folder, always focus on // the first item mCurrentShowList.setSelection(0); } else { Toast.makeText(this, R.string.read_fail_permission, Toast.LENGTH_SHORT).show(); } } else { onFileSelected(file); } } @Override public void navigateToPath(String path) { mAppController.updateDirectory(mFileManager.getNextUrlContent(path, true, false)); } @Override public void onConfigurationChanged(Configuration newConfig) { Log.i(TAG, "onConfigurationChanged" + newConfig.keyboard); if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) { Log.i(TAG, "hard keyboard presented."); } else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) { Log.i(TAG, "hard keyboard quits."); } super.onConfigurationChanged(newConfig); } @Override public void onItemClick(AdapterView<?> adapterView, View itemView, int pos, long id) { if (adapterView.getAdapter() instanceof DeviceDataAdapter) { DeviceItem deviceItem = (DeviceItem) adapterView .getItemAtPosition(pos); String path = deviceItem.getPath(); mAppController.updateDirectory(mFileManager.getNextUrlContent(path, true, false)); closeSlidingLayer(false); } else if (adapterView.getAdapter() instanceof FileDataListAdapter) { handleFileItemClick(mFileDataListAdapter, itemView, pos, id); } } @Override public void onStorageDeviceItemChanged() { // do nothing } @Override public void onUrlContentUpdated(String newUrl, int contentSize, boolean fromHistory) { if (mPathNavigator != null) { mPathNavigator.updatePathNodes(mFileManager.getCurrentUrl()); mPathNavigator.switchToNavigateMode(); } } private void closeSlidingLayer(boolean smooth) { if (mSlidingLayer != null && mSlidingLayer.isOpened()) { mSlidingLayer.closeLayer(smooth); if (mCollectionSwitchButton != null) { mCollectionSwitchButton .setImageResource(R.drawable.collection_expand); } } mCurrentShowList.setVisibility(View.VISIBLE); } private void onFileSelected(File file) { if (file != null) { if (file.canRead()) { Uri uri = Uri.fromFile(file); setResult(RESULT_OK, new Intent().setData(Uri.parse(uri.toString()))); finish(); } else { String errMessage = getResources().getString( R.string.no_permission_read_file, file.getName()); Toast.makeText(this, errMessage, Toast.LENGTH_SHORT).show(); } } } private void openSlidingLayer(boolean smooth) { if (mSlidingLayer != null && !mSlidingLayer.isOpened()) { mSlidingLayer.openLayer(smooth); mCollectionSwitchButton .setImageResource(R.drawable.collection_collapse); mCurrentShowList.setVisibility(View.GONE); } } private void setupAddressBar() { mPathNavigator = (FilePathNavigator) findViewById(R.id.filePath_navigator); mPathNavigator.setNavigationCallback(this); mPathNavigator.setPathButtonOnDropDelegate(mAppController); mPathNavigator.setPathButtonOpenDelegate(mAppController); mPathNavigator.showInSimpleMode(true); mCollectionSwitchButton = (ImageView) mPathNavigator .findViewById(R.id.collection_panel_switch); mCollectionSwitchButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mSlidingLayer != null && mSlidingLayer.isOpened()) { closeSlidingLayer(true); } else if (mSlidingLayer != null && !mSlidingLayer.isOpened()) { openSlidingLayer(true); } } }); } private void setupFileList() { mFileDataListAdapter = mAppController.getFileDataListAdapter(); mFileListView = (DropableListView) findViewById(R.id.file_listview); mFileListView.setAdapter(mFileDataListAdapter); mFileListView.setOnItemClickListener(this); // default mCurrentShowList = mFileListView; mFileListView.setVisibility(View.VISIBLE); mAppController.updateDirectory(mFileManager.refreshUrlContent()); } private void initSlidingLayerState() { mSlidingLayer.setStickTo(SlidingLayer.STICK_TO_TOP); LayoutParams rlp = (LayoutParams) mSlidingLayer.getLayoutParams(); rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP); mSlidingLayer.setLayoutParams(rlp); mSlidingLayer.setShadowWidth(0); mSlidingLayer.setShadowDrawable(null); mSlidingLayer.setSlidingEnabled(false); mSlidingLayer.setOpenOnTapEnabled(false); mSlidingLayer.setCloseOnTapEnabled(false); } protected void intializeMiniWidgets() { /* Storage devices */ // internal SD card mInternalStorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.internal_collection); mInternalStorageMiniWidget.setGroupTag(kTagTaskGroupBase + 2); mInternalStorageMiniWidget.setDefaultGroupLabel(getResources() .getString(R.string.internal_storage)); mInternalStorageMiniWidget.setEjectable(false); AbsListView intSdcardList = mInternalStorageMiniWidget .activateListMode(); intSdcardList.setOnItemClickListener(this); intSdcardList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.Internal)); mMiniPanelWidgets.add(mInternalStorageMiniWidget); // external SD card mSdcardMiniWidget = (TaskGroupListWidget) findViewById(R.id.sdcard_collection); mSdcardMiniWidget.setGroupTag(kTagTaskGroupBase + 3); mSdcardMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.sdcard_storage)); mSdcardMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView extSdcardList = mSdcardMiniWidget.activateListMode(); extSdcardList.setOnItemClickListener(this); extSdcardList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.SDSlot)); mMiniPanelWidgets.add(mSdcardMiniWidget); // USB 1 storage mUsb1StorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.usb1_disk_collection); mUsb1StorageMiniWidget.setGroupTag(kTagTaskGroupBase + 4); mUsb1StorageMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb1_storage)); mUsb1StorageMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usb1storageList = mUsb1StorageMiniWidget.activateListMode(); usb1storageList.setOnItemClickListener(this); usb1storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBPort1)); mMiniPanelWidgets.add(mUsb1StorageMiniWidget); // USB 2 storage mUsb2StorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.usb2_disk_collection); mUsb2StorageMiniWidget.setGroupTag(kTagTaskGroupBase + 5); mUsb2StorageMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb2_storage)); mUsb2StorageMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usb2storageList = mUsb2StorageMiniWidget.activateListMode(); usb2storageList.setOnItemClickListener(this); usb2storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBPort2)); mMiniPanelWidgets.add(mUsb2StorageMiniWidget); // USB 3 storage mUsb3StorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.usb3_disk_collection); mUsb3StorageMiniWidget.setGroupTag(kTagTaskGroupBase + 6); mUsb3StorageMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb3_storage)); mUsb3StorageMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usb3storageList = mUsb3StorageMiniWidget.activateListMode(); usb3storageList.setOnItemClickListener(this); usb3storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBPort3)); mMiniPanelWidgets.add(mUsb3StorageMiniWidget); // USB 4 storage mUsb4StorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.usb4_disk_collection); mUsb4StorageMiniWidget.setGroupTag(kTagTaskGroupBase + 7); mUsb4StorageMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb4_storage)); mUsb4StorageMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usb4storageList = mUsb4StorageMiniWidget.activateListMode(); usb4storageList.setOnItemClickListener(this); usb4storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBPort4)); mMiniPanelWidgets.add(mUsb4StorageMiniWidget); // USB Storage A mStorageA_MiniWidget = (TaskGroupListWidget) findViewById(R.id.usb_a_collection); mStorageA_MiniWidget.setGroupTag(kTagTaskGroupBase + 8); mStorageA_MiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb_storage_a)); mStorageA_MiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usba_storageList = mStorageA_MiniWidget.activateListMode(); usba_storageList.setOnItemClickListener(this); DeviceDataAdapter usba_adapter = mAppController .getDeviceDataAdapter(StorageUtil.USBSDA); usba_storageList.setAdapter(usba_adapter); mMiniPanelWidgets.add(mStorageA_MiniWidget); // USB Storage B mStorageB_MiniWidget = (TaskGroupListWidget) findViewById(R.id.usb_b_collection); mStorageB_MiniWidget.setGroupTag(kTagTaskGroupBase + 9); mStorageB_MiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb_storage_b)); mStorageB_MiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usbb_storageList = mStorageB_MiniWidget.activateListMode(); usbb_storageList.setOnItemClickListener(this); usbb_storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBSDB)); mMiniPanelWidgets.add(mStorageB_MiniWidget); // USB Storage C mStorageC_MiniWidget = (TaskGroupListWidget) findViewById(R.id.usb_c_collection); mStorageC_MiniWidget.setGroupTag(kTagTaskGroupBase + 10); mStorageC_MiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb_storage_c)); mStorageC_MiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usbc_storageList = mStorageC_MiniWidget.activateListMode(); usbc_storageList.setOnItemClickListener(this); usbc_storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBSDC)); mMiniPanelWidgets.add(mStorageC_MiniWidget); // USB Storage D mStorageD_MiniWidget = (TaskGroupListWidget) findViewById(R.id.usb_d_collection); mStorageD_MiniWidget.setGroupTag(kTagTaskGroupBase + 11); mStorageD_MiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb_storage_d)); mStorageD_MiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usbd_storageList = mStorageD_MiniWidget.activateListMode(); usbd_storageList.setOnItemClickListener(this); usbd_storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBSDD)); mMiniPanelWidgets.add(mStorageD_MiniWidget); } protected void refreshTaskGroups() { for (TaskGroupListWidget taskGroup : mMiniPanelWidgets) { AbsListView taskList = taskGroup.activateListMode(); if (taskList.getCount() == 0) { taskGroup.hideHeader(); } else { if (taskList.getAdapter() instanceof DeviceDataAdapter) { DeviceItem firstItem = (DeviceItem) taskList .getItemAtPosition(0); if (firstItem != null) { String deviceName = firstItem.getContainerDeviceName(); if (deviceName != null) { taskGroup.setLabel(deviceName); } else { taskGroup .setLabel(taskGroup.getDefaultGroupLabel()); } } } taskGroup.showHeader(); } } } protected void initializeSlidingLayer() { // Reset at first mSlidingLayer = null; if (mCollectionSwitchButton != null) { mCollectionSwitchButton.setVisibility(View.GONE); } mSlidingLayer = (SlidingLayer) findViewById(R.id.sliding_panel); if (mSlidingLayer != null) { // Using sliding layer means display space is limited, FilePathNavigator.MAX_BUTTON_NUM = 2; initSlidingLayerState(); if (mCollectionSwitchButton != null) { mCollectionSwitchButton.setVisibility(View.VISIBLE); } } else { FilePathNavigator.MAX_BUTTON_NUM = 5; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ifexplorer_file_chooser); restoreSavedInfo(savedInstanceState); // file manager mFileManager = FilePathUrlManager.getLocalFileManager(mInitLocation); // event handler mAppController = new IfAppController(this, mFileManager); mAppController.setUiCallback(this); // storage monitoring mStorageIntentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); mStorageIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mStorageIntentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); mStorageIntentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); mStorageIntentFilter.addAction(Intent.ACTION_MEDIA_REMOVED); mStorageIntentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL); mStorageIntentFilter.addAction(Intent.ACTION_MEDIA_SHARED); mStorageIntentFilter.addDataScheme("file"); mStorageIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); registerReceiver(mStorageBroadcastReceiver, mStorageIntentFilter); // initialize mini widget intializeMiniWidgets(); // initialize storage device and do pre scan mAppController.intializeStorageDevicesAsync(); // initialize default favorites mAppController.initializeDefaultFavorites(); // refresh collection view refreshTaskGroups(); setupAddressBar(); setupFileList(); // initialize sliding layer initializeSlidingLayer(); mCancelButton = (Button) findViewById(R.id.cancelButton); mCancelButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { IfFileChooser.this.finish(); } }); // update current directory mAppController.updateDirectory(mFileManager.refreshUrlContent()); } @Override protected void onDestroy() { mAppController.cancelAllBackgroundWork(); unregisterReceiver(mStorageBroadcastReceiver); super.onDestroy(); } @Override protected void onSaveInstanceState(Bundle outState) { outState.putString(KEY_SAVE_LOCATION, mFileManager.getCurrentUrl()); super.onSaveInstanceState(outState); } protected void restoreSavedInfo(Bundle savedInfo) { if (savedInfo != null) { mInitLocation = savedInfo.getString(KEY_SAVE_LOCATION); super.onRestoreInstanceState(savedInfo); } else { mInitLocation = StorageUtil.getHomeDir(); } File initDir = new File(mInitLocation); if (!initDir.exists() || !initDir.isDirectory()) { // Due to backward compatibility, this // path works in all kinds of android devices. mInitLocation = "/sdcard"; } } }