/* * Created by Angel Leon (@gubatron), Alden Torres (aldenml) * Copyright (c) 2011-2014, FrostWire(R). All rights reserved. * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.bt.download.android.gui.views.preference; import java.io.File; import java.util.ArrayList; import java.util.List; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnMultiChoiceClickListener; import android.os.Bundle; import android.os.Environment; import android.preference.DialogPreference; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ImageView; import android.widget.ListView; import android.widget.RadioButton; import android.widget.TextView; import com.bt.download.android.R; import com.bt.download.android.core.ConfigurationManager; import com.bt.download.android.core.SystemPaths; import com.bt.download.android.gui.util.UIUtils; import com.bt.download.android.gui.views.AbstractAdapter; import com.bt.download.android.gui.views.AbstractAdapter.OnItemClickAdapter; import com.bt.download.android.util.SystemUtils; import com.frostwire.bittorrent.BTEngine; import com.frostwire.uxstats.UXAction; import com.frostwire.uxstats.UXStats; /** * @author gubatron * @author aldenml * */ public class StoragePreference extends DialogPreference { private AlertDialog confirmDlg; private String selectedPath; public StoragePreference(Context context, AttributeSet attrs) { super(context, attrs); setDialogLayoutResource(R.layout.dialog_preference_storage); setPositiveButtonText(null); } public StoragePreference(Context context) { this(context, null); } @Override public void showDialog(Bundle state) { super.showDialog(state); } @Override protected void onBindDialogView(View view) { super.onBindDialogView(view); ListView list = (ListView) view.findViewById(R.id.dialog_preference_storage_list); list.setAdapter(new StoragesAdapter(getContext())); list.setOnItemClickListener(new OnItemClickAdapter<StorageMount>() { @Override public void onItemClick(AdapterView<?> parent, View view, AbstractAdapter<StorageMount> adapter, int position, long id) { selectedPath = adapter.getItem(position).path; //if you select the one that was there before dismiss the dialog. if (ConfigurationManager.instance().getStoragePath().equals(selectedPath)) { dismissPreferenceDialog(); } else { //if you select the SD Card option, show the confirmation dialog, with ok button disabled. //will be enabled after user clicks on checkbox. confirmDlg = createConfirmDialog(getContext()); confirmDlg.show(); confirmDlg.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false); } } }); TextView warningText = (TextView) view.findViewById(R.id.dialog_preference_storage_warning); warningText.setVisibility(list.getCount() == 1 ? View.GONE : View.VISIBLE); } @Override public void onActivityDestroy() { dismissConfirmDialog(); super.onActivityDestroy(); } @Override public void onClick(DialogInterface dialog, int which) { if (dialog != null && dialog.equals(confirmDlg)) { if (which == Dialog.BUTTON_POSITIVE && selectedPath != null) { ConfigurationManager.instance().setStoragePath(selectedPath); BTEngine.ctx.dataDir = new File(selectedPath).getAbsoluteFile(); BTEngine.ctx.torrentsDir = SystemPaths.getTorrents(); dismissPreferenceDialog(); uxLogSelection(); } } else { super.onClick(dialog, which); } } private void uxLogSelection() { try { File file = new File(selectedPath); boolean isInternalMemory = SystemUtils.isPrimaryExternalPath(file); UXStats.instance().log(isInternalMemory ? UXAction.SETTINGS_SET_STORAGE_INTERNAL_MEMORY : UXAction.SETTINGS_SET_STORAGE_SD_CARD); } catch (Throwable t) { //we tried. } } private AlertDialog createConfirmDialog(Context context) { OnMultiChoiceClickListener checkListener = new OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { if (confirmDlg != null && confirmDlg.isShowing()) { confirmDlg.getButton(Dialog.BUTTON_POSITIVE).setEnabled(isChecked); } } }; return new AlertDialog.Builder(context). setMultiChoiceItems(new String[] { context.getString(R.string.storage_setting_confirm_dialog_text) }, new boolean[] { false }, checkListener). setTitle(R.string.storage_setting_confirm_dialog_title). setPositiveButton(android.R.string.ok, this). setNegativeButton(android.R.string.cancel, this). create(); } private void dismissConfirmDialog() { if (confirmDlg != null && confirmDlg.isShowing()) { confirmDlg.dismiss(); } } private void dismissPreferenceDialog() { if (getDialog() != null) { getDialog().dismiss(); } } private static final class StorageMount { public StorageMount(String label, String description, String path, boolean primary) { this.label = label; this.description = description; this.path = path; this.primary = primary; } public final String label; public final String description; public final String path; public final boolean primary; } private final class StoragesAdapter extends AbstractAdapter<StorageMount> { public StoragesAdapter(Context context) { super(context, R.layout.view_preference_storage_list_item); addItems(context); } @Override protected void setupView(View view, ViewGroup parent, StorageMount item) { ImageView icon = findView(view, R.id.view_preference_storage_list_item_icon); TextView label = findView(view, R.id.view_preference_storage_list_item_label); TextView description = findView(view, R.id.view_preference_storage_list_item_description); RadioButton radio = findView(view, R.id.view_preference_storage_list_item_radio); icon.setImageResource(item.primary ? R.drawable.internal_memory_notification_dark_bg : R.drawable.sd_card_notification_dark_bg); label.setText(item.label); description.setText(item.description); radio.setChecked(ConfigurationManager.instance().getStoragePath().equals(item.path)); } private void addItems(Context context) { StorageMount primary = getPrimaryExternal(context); if (primary != null) { add(primary); } for (StorageMount mount : getSecondayExternals(context)) { add(mount); } } private StorageMount getPrimaryExternal(Context context) { StorageMount mount = null; if (SystemUtils.isPrimaryExternalStorageMounted()) { File dir = Environment.getExternalStorageDirectory(); String label = context.getString(R.string.device_storage); String description = UIUtils.getBytesInHuman(SystemUtils.getAvailableStorageSize(dir)) + " " + context.getString(R.string.available); String path = dir.getAbsolutePath(); mount = new StorageMount(label, description, path, true); } return mount; } private List<StorageMount> getSecondayExternals(Context context) { List<StorageMount> mounts = new ArrayList<StorageMount>(); // "Returns null if external storage is not currently mounted". File externalFilesDir = context.getExternalFilesDir(null); if (externalFilesDir != null) { String primaryPath = externalFilesDir.getParent(); int i = 0; for (File f : SystemUtils.getExternalFilesDirs(context)) { if (!f.getAbsolutePath().startsWith(primaryPath) && SystemUtils.isSecondaryExternalStorageMounted(f)) { String label = context.getString(R.string.sdcard_storage) + " " + (++i); String description = UIUtils.getBytesInHuman(SystemUtils.getAvailableStorageSize(f)) + " " + context.getString(R.string.available); String path = f.getAbsolutePath(); StorageMount mount = new StorageMount(label, description, path, false); mounts.add(mount); } } } return mounts; } } }