Merge pull request #10731 from osmandapp/DataStorageRefactoring
Data storage refactoring
This commit is contained in:
commit
dedea0c45e
17 changed files with 905 additions and 784 deletions
|
@ -9,7 +9,8 @@
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/card_row_min_height">
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="@dimen/card_row_min_height">
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
android:id="@android:id/icon"
|
android:id="@android:id/icon"
|
||||||
|
@ -31,11 +32,15 @@
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:paddingLeft="@dimen/content_padding"
|
android:paddingLeft="@dimen/content_padding"
|
||||||
|
android:paddingStart="@dimen/content_padding"
|
||||||
|
android:paddingRight="0dp"
|
||||||
|
android:paddingEnd="0dp"
|
||||||
|
android:paddingTop="@dimen/content_padding_half"
|
||||||
|
android:paddingBottom="@dimen/content_padding_half"
|
||||||
android:textColor="?android:textColorPrimary"
|
android:textColor="?android:textColorPrimary"
|
||||||
android:textSize="@dimen/default_desc_text_size"
|
android:textSize="@dimen/default_desc_text_size"
|
||||||
osmand:typeface="@string/font_roboto_regular"
|
osmand:typeface="@string/font_roboto_regular"
|
||||||
tools:text="Internal application memory"
|
tools:text="Internal application memory" />
|
||||||
android:paddingStart="@dimen/content_padding" />
|
|
||||||
|
|
||||||
<net.osmand.plus.widgets.TextViewEx
|
<net.osmand.plus.widgets.TextViewEx
|
||||||
android:id="@+id/memory"
|
android:id="@+id/memory"
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<string name="hillshade_slope_contour_lines">Hillshade / Slope / Contour lines</string>
|
||||||
<string name="toast_select_edits_for_upload">Select edits for upload</string>
|
<string name="toast_select_edits_for_upload">Select edits for upload</string>
|
||||||
<string name="uploaded_count">Uploaded %1$d of %2$d</string>
|
<string name="uploaded_count">Uploaded %1$d of %2$d</string>
|
||||||
<string name="uploading_count">Uploading %1$d of %2$d</string>
|
<string name="uploading_count">Uploading %1$d of %2$d</string>
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
android:title="@string/shared_string_maps"/>
|
android:title="@string/shared_string_maps"/>
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="contour_lines_and_hillshade_memory"
|
android:key="terrain_memory_used"
|
||||||
android:layout="@layout/data_storage_memory_used_item"
|
android:layout="@layout/data_storage_memory_used_item"
|
||||||
android:icon="@drawable/ic_map"
|
android:icon="@drawable/ic_map"
|
||||||
android:title="@string/contour_lines_and_hillshade"/>
|
android:title="@string/hillshade_slope_contour_lines"/>
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="tracks_memory_used"
|
android:key="tracks_memory_used"
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
android:layout="@layout/preference_with_descr"
|
android:layout="@layout/preference_with_descr"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/application_dir"
|
android:title="@string/application_dir"
|
||||||
app:fragment="net.osmand.plus.settings.fragments.DataStorageFragment"
|
app:fragment="net.osmand.plus.settings.datastorage.DataStorageFragment"
|
||||||
tools:icon="@drawable/ic_action_folder" />
|
tools:icon="@drawable/ic_action_folder" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
|
|
|
@ -139,7 +139,7 @@ import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
|
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
|
||||||
import net.osmand.plus.settings.fragments.ConfigureProfileFragment;
|
import net.osmand.plus.settings.fragments.ConfigureProfileFragment;
|
||||||
import net.osmand.plus.settings.fragments.DataStorageFragment;
|
import net.osmand.plus.settings.datastorage.DataStorageFragment;
|
||||||
import net.osmand.plus.track.TrackAppearanceFragment;
|
import net.osmand.plus.track.TrackAppearanceFragment;
|
||||||
import net.osmand.plus.track.TrackMenuFragment;
|
import net.osmand.plus.track.TrackMenuFragment;
|
||||||
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
|
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
|
||||||
|
|
|
@ -19,13 +19,13 @@ import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
|
||||||
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
|
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
|
||||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
||||||
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||||
import net.osmand.plus.settings.fragments.DataStorageMenuItem;
|
import net.osmand.plus.settings.datastorage.item.StorageItem;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import static net.osmand.plus.settings.fragments.DataStorageHelper.MANUALLY_SPECIFIED;
|
import static net.osmand.plus.settings.datastorage.DataStorageHelper.MANUALLY_SPECIFIED;
|
||||||
|
|
||||||
public class ChangeDataStorageBottomSheet extends BasePreferenceBottomSheet {
|
public class ChangeDataStorageBottomSheet extends BasePreferenceBottomSheet {
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ public class ChangeDataStorageBottomSheet extends BasePreferenceBottomSheet {
|
||||||
public final static String MOVE_DATA = "move_data";
|
public final static String MOVE_DATA = "move_data";
|
||||||
public final static String CHOSEN_DIRECTORY = "chosen_storage";
|
public final static String CHOSEN_DIRECTORY = "chosen_storage";
|
||||||
|
|
||||||
private DataStorageMenuItem currentDirectory;
|
private StorageItem currentDirectory;
|
||||||
private DataStorageMenuItem newDirectory;
|
private StorageItem newDirectory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createMenuItems(Bundle savedInstanceState) {
|
public void createMenuItems(Bundle savedInstanceState) {
|
||||||
|
@ -126,11 +126,11 @@ public class ChangeDataStorageBottomSheet extends BasePreferenceBottomSheet {
|
||||||
items.add(baseItem);
|
items.add(baseItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentDirectory(DataStorageMenuItem currentDirectory) {
|
public void setCurrentDirectory(StorageItem currentDirectory) {
|
||||||
this.currentDirectory = currentDirectory;
|
this.currentDirectory = currentDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNewDirectory(DataStorageMenuItem newDirectory) {
|
public void setNewDirectory(StorageItem newDirectory) {
|
||||||
this.newDirectory = newDirectory;
|
this.newDirectory = newDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,8 +158,8 @@ public class ChangeDataStorageBottomSheet extends BasePreferenceBottomSheet {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean showInstance(FragmentManager fm, String prefId, DataStorageMenuItem currentDirectory,
|
public static boolean showInstance(FragmentManager fm, String prefId, StorageItem currentDirectory,
|
||||||
DataStorageMenuItem newDirectory, Fragment target, boolean usedOnMap) {
|
StorageItem newDirectory, Fragment target, boolean usedOnMap) {
|
||||||
try {
|
try {
|
||||||
if (fm.findFragmentByTag(TAG) == null) {
|
if (fm.findFragmentByTag(TAG) == null) {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
package net.osmand.plus.settings.fragments;
|
package net.osmand.plus.settings.datastorage;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
@ -26,7 +25,6 @@ import net.osmand.AndroidUtils;
|
||||||
import net.osmand.FileUtils;
|
import net.osmand.FileUtils;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
import net.osmand.plus.ProgressImplementation;
|
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.UiUtilities;
|
import net.osmand.plus.UiUtilities;
|
||||||
import net.osmand.plus.activities.MapActivity;
|
import net.osmand.plus.activities.MapActivity;
|
||||||
|
@ -34,20 +32,21 @@ import net.osmand.plus.activities.OsmandActionBarActivity;
|
||||||
import net.osmand.plus.download.DownloadActivity;
|
import net.osmand.plus.download.DownloadActivity;
|
||||||
import net.osmand.plus.settings.bottomsheets.ChangeDataStorageBottomSheet;
|
import net.osmand.plus.settings.bottomsheets.ChangeDataStorageBottomSheet;
|
||||||
import net.osmand.plus.settings.bottomsheets.SelectFolderBottomSheet;
|
import net.osmand.plus.settings.bottomsheets.SelectFolderBottomSheet;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.plus.settings.datastorage.item.MemoryItem;
|
||||||
|
import net.osmand.plus.settings.datastorage.item.StorageItem;
|
||||||
|
import net.osmand.plus.settings.datastorage.task.MoveFilesTask;
|
||||||
|
import net.osmand.plus.settings.datastorage.task.RefreshUsedMemoryTask;
|
||||||
|
import net.osmand.plus.settings.datastorage.task.ReloadDataTask;
|
||||||
|
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import static net.osmand.plus.settings.fragments.DataStorageHelper.INTERNAL_STORAGE;
|
import static net.osmand.plus.settings.datastorage.DataStorageHelper.INTERNAL_STORAGE;
|
||||||
import static net.osmand.plus.settings.fragments.DataStorageHelper.MANUALLY_SPECIFIED;
|
import static net.osmand.plus.settings.datastorage.DataStorageHelper.MANUALLY_SPECIFIED;
|
||||||
import static net.osmand.plus.settings.fragments.DataStorageHelper.OTHER_MEMORY;
|
import static net.osmand.plus.settings.datastorage.DataStorageHelper.OTHER_MEMORY;
|
||||||
import static net.osmand.plus.settings.fragments.DataStorageHelper.TILES_MEMORY;
|
import static net.osmand.plus.settings.datastorage.DataStorageHelper.TILES_MEMORY;
|
||||||
import static net.osmand.plus.settings.bottomsheets.ChangeDataStorageBottomSheet.CHOSEN_DIRECTORY;
|
import static net.osmand.plus.settings.bottomsheets.ChangeDataStorageBottomSheet.CHOSEN_DIRECTORY;
|
||||||
import static net.osmand.plus.settings.bottomsheets.ChangeDataStorageBottomSheet.MOVE_DATA;
|
import static net.osmand.plus.settings.bottomsheets.ChangeDataStorageBottomSheet.MOVE_DATA;
|
||||||
import static net.osmand.plus.settings.bottomsheets.SelectFolderBottomSheet.NEW_PATH;
|
import static net.osmand.plus.settings.bottomsheets.SelectFolderBottomSheet.NEW_PATH;
|
||||||
|
@ -60,17 +59,17 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
private final static String CHANGE_DIRECTORY_BUTTON = "change_directory";
|
private final static String CHANGE_DIRECTORY_BUTTON = "change_directory";
|
||||||
private final static String OSMAND_USAGE = "osmand_usage";
|
private final static String OSMAND_USAGE = "osmand_usage";
|
||||||
|
|
||||||
private ArrayList<DataStorageMenuItem> menuItems;
|
private ArrayList<StorageItem> storageItems;
|
||||||
private ArrayList<DataStorageMemoryItem> memoryItems;
|
private ArrayList<MemoryItem> memoryItems;
|
||||||
private ArrayList<CheckBoxPreference> dataStorageRadioButtonsGroup;
|
private ArrayList<CheckBoxPreference> dataStorageRadioButtonsGroup;
|
||||||
private Preference changeButton;
|
private Preference changeButton;
|
||||||
private DataStorageMenuItem currentDataStorage;
|
private StorageItem currentDataStorage;
|
||||||
private String tmpManuallySpecifiedPath;
|
private String tmpManuallySpecifiedPath;
|
||||||
private DataStorageHelper dataStorageHelper;
|
private DataStorageHelper dataStorageHelper;
|
||||||
private boolean calculateTilesBtnPressed;
|
private boolean calculateTilesBtnPressed;
|
||||||
|
|
||||||
private DataStorageHelper.RefreshMemoryUsedInfo calculateMemoryTask;
|
private RefreshUsedMemoryTask calculateMemoryTask;
|
||||||
private DataStorageHelper.RefreshMemoryUsedInfo calculateTilesMemoryTask;
|
private RefreshUsedMemoryTask calculateTilesMemoryTask;
|
||||||
|
|
||||||
private OsmandApplication app;
|
private OsmandApplication app;
|
||||||
private OsmandActionBarActivity activity;
|
private OsmandActionBarActivity activity;
|
||||||
|
@ -95,11 +94,11 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
menuItems = dataStorageHelper.getStorageItems();
|
storageItems = dataStorageHelper.getStorageItems();
|
||||||
memoryItems = dataStorageHelper.getMemoryInfoItems();
|
memoryItems = dataStorageHelper.getMemoryInfoItems();
|
||||||
dataStorageRadioButtonsGroup = new ArrayList<>();
|
dataStorageRadioButtonsGroup = new ArrayList<>();
|
||||||
|
|
||||||
for (DataStorageMenuItem item : menuItems) {
|
for (StorageItem item : storageItems) {
|
||||||
CheckBoxPreference preference = new CheckBoxPreference(activity);
|
CheckBoxPreference preference = new CheckBoxPreference(activity);
|
||||||
preference.setKey(item.getKey());
|
preference.setKey(item.getKey());
|
||||||
preference.setTitle(item.getTitle());
|
preference.setTitle(item.getTitle());
|
||||||
|
@ -136,7 +135,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
Bundle resultData = (Bundle) newValue;
|
Bundle resultData = (Bundle) newValue;
|
||||||
if (resultData.containsKey(ChangeDataStorageBottomSheet.TAG)) {
|
if (resultData.containsKey(ChangeDataStorageBottomSheet.TAG)) {
|
||||||
boolean moveMaps = resultData.getBoolean(MOVE_DATA);
|
boolean moveMaps = resultData.getBoolean(MOVE_DATA);
|
||||||
DataStorageMenuItem newDataStorage = resultData.getParcelable(CHOSEN_DIRECTORY);
|
StorageItem newDataStorage = resultData.getParcelable(CHOSEN_DIRECTORY);
|
||||||
if (newDataStorage != null) {
|
if (newDataStorage != null) {
|
||||||
if (tmpManuallySpecifiedPath != null) {
|
if (tmpManuallySpecifiedPath != null) {
|
||||||
String directory = tmpManuallySpecifiedPath;
|
String directory = tmpManuallySpecifiedPath;
|
||||||
|
@ -154,9 +153,9 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
if (pathChanged) {
|
if (pathChanged) {
|
||||||
tmpManuallySpecifiedPath = resultData.getString(NEW_PATH);
|
tmpManuallySpecifiedPath = resultData.getString(NEW_PATH);
|
||||||
if (tmpManuallySpecifiedPath != null) {
|
if (tmpManuallySpecifiedPath != null) {
|
||||||
DataStorageMenuItem manuallySpecified = null;
|
StorageItem manuallySpecified = null;
|
||||||
try {
|
try {
|
||||||
manuallySpecified = (DataStorageMenuItem) dataStorageHelper.getManuallySpecified().clone();
|
manuallySpecified = (StorageItem) dataStorageHelper.getManuallySpecified().clone();
|
||||||
manuallySpecified.setDirectory(tmpManuallySpecifiedPath);
|
manuallySpecified.setDirectory(tmpManuallySpecifiedPath);
|
||||||
} catch (CloneNotSupportedException e) {
|
} catch (CloneNotSupportedException e) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -170,7 +169,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
//show necessary dialog
|
//show necessary dialog
|
||||||
String key = preference.getKey();
|
String key = preference.getKey();
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
DataStorageMenuItem newDataStorage = dataStorageHelper.getStorage(key);
|
StorageItem newDataStorage = dataStorageHelper.getStorage(key);
|
||||||
if (newDataStorage != null) {
|
if (newDataStorage != null) {
|
||||||
if (!currentDataStorage.getKey().equals(newDataStorage.getKey())) {
|
if (!currentDataStorage.getKey().equals(newDataStorage.getKey())) {
|
||||||
if (newDataStorage.getType() == OsmandSettings.EXTERNAL_STORAGE_TYPE_DEFAULT
|
if (newDataStorage.getType() == OsmandSettings.EXTERNAL_STORAGE_TYPE_DEFAULT
|
||||||
|
@ -212,7 +211,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
|
|
||||||
final View itemView = holder.itemView;
|
final View itemView = holder.itemView;
|
||||||
if (preference instanceof CheckBoxPreference) {
|
if (preference instanceof CheckBoxPreference) {
|
||||||
DataStorageMenuItem item = dataStorageHelper.getStorage(key);
|
StorageItem item = dataStorageHelper.getStorage(key);
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
TextView tvTitle = itemView.findViewById(android.R.id.title);
|
TextView tvTitle = itemView.findViewById(android.R.id.title);
|
||||||
TextView tvSummary = itemView.findViewById(R.id.summary);
|
TextView tvSummary = itemView.findViewById(R.id.summary);
|
||||||
|
@ -267,7 +266,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
TextView tvSummary = itemView.findViewById(R.id.summary);
|
TextView tvSummary = itemView.findViewById(R.id.summary);
|
||||||
tvSummary.setText(DataStorageHelper.getFormattedMemoryInfo(totalUsageBytes, memoryUnitsFormats));
|
tvSummary.setText(DataStorageHelper.getFormattedMemoryInfo(totalUsageBytes, memoryUnitsFormats));
|
||||||
} else {
|
} else {
|
||||||
for (DataStorageMemoryItem mi : memoryItems) {
|
for (MemoryItem mi : memoryItems) {
|
||||||
if (key.equals(mi.getKey())) {
|
if (key.equals(mi.getKey())) {
|
||||||
TextView tvMemory = itemView.findViewById(R.id.memory);
|
TextView tvMemory = itemView.findViewById(R.id.memory);
|
||||||
String summary = "";
|
String summary = "";
|
||||||
|
@ -326,7 +325,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showFolderSelectionDialog() {
|
private void showFolderSelectionDialog() {
|
||||||
DataStorageMenuItem manuallySpecified = dataStorageHelper.getManuallySpecified();
|
StorageItem manuallySpecified = dataStorageHelper.getManuallySpecified();
|
||||||
if (manuallySpecified != null) {
|
if (manuallySpecified != null) {
|
||||||
SelectFolderBottomSheet.showInstance(getFragmentManager(), manuallySpecified.getKey(),
|
SelectFolderBottomSheet.showInstance(getFragmentManager(), manuallySpecified.getKey(),
|
||||||
manuallySpecified.getDirectory(), DataStorageFragment.this,
|
manuallySpecified.getDirectory(), DataStorageFragment.this,
|
||||||
|
@ -335,11 +334,11 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void moveData(final DataStorageMenuItem currentStorage, final DataStorageMenuItem newStorage) {
|
private void moveData(final StorageItem currentStorage, final StorageItem newStorage) {
|
||||||
File fromDirectory = new File(currentStorage.getDirectory());
|
File fromDirectory = new File(currentStorage.getDirectory());
|
||||||
File toDirectory = new File(newStorage.getDirectory());
|
File toDirectory = new File(newStorage.getDirectory());
|
||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
MoveFilesToDifferentDirectory task = new MoveFilesToDifferentDirectory(activity, fromDirectory, toDirectory) {
|
MoveFilesTask task = new MoveFilesTask(activity, fromDirectory, toDirectory) {
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -405,7 +404,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void confirm(OsmandApplication app, OsmandActionBarActivity activity, DataStorageMenuItem newStorageDirectory, boolean silentRestart) {
|
private void confirm(OsmandApplication app, OsmandActionBarActivity activity, StorageItem newStorageDirectory, boolean silentRestart) {
|
||||||
String newDirectory = newStorageDirectory.getDirectory();
|
String newDirectory = newStorageDirectory.getDirectory();
|
||||||
int type = newStorageDirectory.getType();
|
int type = newStorageDirectory.getType();
|
||||||
File newDirectoryFile = new File(newDirectory);
|
File newDirectoryFile = new File(newDirectory);
|
||||||
|
@ -454,7 +453,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void reloadData() {
|
protected void reloadData() {
|
||||||
new ReloadData(activity, app).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
|
new ReloadDataTask(activity, app).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -463,204 +462,10 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFinishUpdating(String taskKey) {
|
public void onFinishUpdating(String tag) {
|
||||||
updateAllSettings();
|
updateAllSettings();
|
||||||
if (taskKey != null && taskKey.equals(TILES_MEMORY)) {
|
if (tag != null && tag.equals(TILES_MEMORY)) {
|
||||||
app.getSettings().OSMAND_USAGE_SPACE.set(dataStorageHelper.getTotalUsedBytes());
|
app.getSettings().OSMAND_USAGE_SPACE.set(dataStorageHelper.getTotalUsedBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MoveFilesToDifferentDirectory extends AsyncTask<Void, Void, Boolean> {
|
|
||||||
|
|
||||||
protected WeakReference<OsmandActionBarActivity> activity;
|
|
||||||
private WeakReference<Context> context;
|
|
||||||
private File from;
|
|
||||||
private File to;
|
|
||||||
protected ProgressImplementation progress;
|
|
||||||
private Runnable runOnSuccess;
|
|
||||||
private int movedCount;
|
|
||||||
private long movedSize;
|
|
||||||
private int copiedCount;
|
|
||||||
private long copiedSize;
|
|
||||||
private int failedCount;
|
|
||||||
private long failedSize;
|
|
||||||
private String exceptionMessage;
|
|
||||||
|
|
||||||
public MoveFilesToDifferentDirectory(OsmandActionBarActivity activity, File from, File to) {
|
|
||||||
this.activity = new WeakReference<>(activity);
|
|
||||||
this.context = new WeakReference<>((Context) activity);
|
|
||||||
this.from = from;
|
|
||||||
this.to = to;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRunOnSuccess(Runnable runOnSuccess) {
|
|
||||||
this.runOnSuccess = runOnSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMovedCount() {
|
|
||||||
return movedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCopiedCount() {
|
|
||||||
return copiedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFailedCount() {
|
|
||||||
return failedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getMovedSize() {
|
|
||||||
return movedSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCopiedSize() {
|
|
||||||
return copiedSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getFailedSize() {
|
|
||||||
return failedSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute() {
|
|
||||||
Context ctx = context.get();
|
|
||||||
if (context == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
movedCount = 0;
|
|
||||||
copiedCount = 0;
|
|
||||||
failedCount = 0;
|
|
||||||
progress = ProgressImplementation.createProgressDialog(
|
|
||||||
ctx, ctx.getString(R.string.copying_osmand_files),
|
|
||||||
ctx.getString(R.string.copying_osmand_files_descr, to.getPath()),
|
|
||||||
ProgressDialog.STYLE_HORIZONTAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Boolean result) {
|
|
||||||
Context ctx = context.get();
|
|
||||||
if (ctx == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (result != null) {
|
|
||||||
if (result.booleanValue() && runOnSuccess != null) {
|
|
||||||
runOnSuccess.run();
|
|
||||||
} else if (!result.booleanValue()) {
|
|
||||||
Toast.makeText(ctx, ctx.getString(R.string.shared_string_io_error) + ": " + exceptionMessage, Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (progress.getDialog().isShowing()) {
|
|
||||||
progress.getDialog().dismiss();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
//ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void movingFiles(File f, File t, int depth) throws IOException {
|
|
||||||
Context ctx = context.get();
|
|
||||||
if (ctx == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (depth <= 2) {
|
|
||||||
progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), -1);
|
|
||||||
}
|
|
||||||
if (f.isDirectory()) {
|
|
||||||
t.mkdirs();
|
|
||||||
File[] lf = f.listFiles();
|
|
||||||
if (lf != null) {
|
|
||||||
for (int i = 0; i < lf.length; i++) {
|
|
||||||
if (lf[i] != null) {
|
|
||||||
movingFiles(lf[i], new File(t, lf[i].getName()), depth + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.delete();
|
|
||||||
} else if (f.isFile()) {
|
|
||||||
if (t.exists()) {
|
|
||||||
Algorithms.removeAllFiles(t);
|
|
||||||
}
|
|
||||||
boolean rnm = false;
|
|
||||||
long fileSize = f.length();
|
|
||||||
try {
|
|
||||||
rnm = f.renameTo(t);
|
|
||||||
movedCount++;
|
|
||||||
movedSize += fileSize;
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
}
|
|
||||||
if (!rnm) {
|
|
||||||
FileInputStream fin = new FileInputStream(f);
|
|
||||||
FileOutputStream fout = new FileOutputStream(t);
|
|
||||||
try {
|
|
||||||
progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), (int) (f.length() / 1024));
|
|
||||||
Algorithms.streamCopy(fin, fout, progress, 1024);
|
|
||||||
copiedCount++;
|
|
||||||
copiedSize += fileSize;
|
|
||||||
} catch (IOException e) {
|
|
||||||
failedCount++;
|
|
||||||
failedSize += fileSize;
|
|
||||||
} finally {
|
|
||||||
fin.close();
|
|
||||||
fout.close();
|
|
||||||
}
|
|
||||||
f.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (depth <= 2) {
|
|
||||||
progress.finishTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground(Void... params) {
|
|
||||||
to.mkdirs();
|
|
||||||
try {
|
|
||||||
movingFiles(from, to, 0);
|
|
||||||
} catch (IOException e) {
|
|
||||||
exceptionMessage = e.getMessage();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ReloadData extends AsyncTask<Void, Void, Boolean> {
|
|
||||||
private WeakReference<Context> ctx;
|
|
||||||
protected ProgressImplementation progress;
|
|
||||||
private OsmandApplication app;
|
|
||||||
|
|
||||||
public ReloadData(Context ctx, OsmandApplication app) {
|
|
||||||
this.ctx = new WeakReference<>(ctx);
|
|
||||||
this.app = app;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute() {
|
|
||||||
Context c = ctx.get();
|
|
||||||
if (c == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
progress = ProgressImplementation.createProgressDialog(c, c.getString(R.string.loading_data),
|
|
||||||
c.getString(R.string.loading_data), ProgressDialog.STYLE_HORIZONTAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Boolean result) {
|
|
||||||
try {
|
|
||||||
if (progress.getDialog().isShowing()) {
|
|
||||||
progress.getDialog().dismiss();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
//ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground(Void... params) {
|
|
||||||
app.getResourceManager().reloadIndexes(progress, new ArrayList<String>());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,321 @@
|
||||||
|
package net.osmand.plus.settings.datastorage;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import net.osmand.IndexConstants;
|
||||||
|
import net.osmand.ValueHolder;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.settings.datastorage.item.DirectoryItem;
|
||||||
|
import net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType;
|
||||||
|
import net.osmand.plus.settings.datastorage.item.MemoryItem;
|
||||||
|
import net.osmand.plus.settings.datastorage.item.StorageItem;
|
||||||
|
import net.osmand.plus.settings.datastorage.task.RefreshUsedMemoryTask;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static net.osmand.IndexConstants.AV_INDEX_DIR;
|
||||||
|
import static net.osmand.IndexConstants.BACKUP_INDEX_DIR;
|
||||||
|
import static net.osmand.IndexConstants.GPX_INDEX_DIR;
|
||||||
|
import static net.osmand.IndexConstants.MAPS_PATH;
|
||||||
|
import static net.osmand.IndexConstants.ROADS_INDEX_DIR;
|
||||||
|
import static net.osmand.IndexConstants.SRTM_INDEX_DIR;
|
||||||
|
import static net.osmand.IndexConstants.TILES_INDEX_DIR;
|
||||||
|
import static net.osmand.IndexConstants.WIKIVOYAGE_INDEX_DIR;
|
||||||
|
import static net.osmand.IndexConstants.WIKI_INDEX_DIR;
|
||||||
|
import static net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType.EXTENSIONS;
|
||||||
|
import static net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType.PREFIX;
|
||||||
|
|
||||||
|
public class DataStorageHelper {
|
||||||
|
public final static String INTERNAL_STORAGE = "internal_storage";
|
||||||
|
public final static String EXTERNAL_STORAGE = "external_storage";
|
||||||
|
public final static String SHARED_STORAGE = "shared_storage";
|
||||||
|
public final static String MULTIUSER_STORAGE = "multiuser_storage";
|
||||||
|
public final static String MANUALLY_SPECIFIED = "manually_specified";
|
||||||
|
|
||||||
|
public final static String MAPS_MEMORY = "maps_memory_used";
|
||||||
|
public final static String TERRAIN_MEMORY = "terrain_memory_used";
|
||||||
|
public final static String TRACKS_MEMORY = "tracks_memory_used";
|
||||||
|
public final static String NOTES_MEMORY = "notes_memory_used";
|
||||||
|
public final static String TILES_MEMORY = "tiles_memory_used";
|
||||||
|
public final static String OTHER_MEMORY = "other_memory_used";
|
||||||
|
|
||||||
|
private OsmandApplication app;
|
||||||
|
private ArrayList<StorageItem> storageItems = new ArrayList<>();
|
||||||
|
private StorageItem currentDataStorage;
|
||||||
|
private StorageItem manuallySpecified;
|
||||||
|
|
||||||
|
private ArrayList<MemoryItem> memoryItems = new ArrayList<>();
|
||||||
|
private MemoryItem mapsMemory;
|
||||||
|
private MemoryItem terrainMemory;
|
||||||
|
private MemoryItem tracksMemory;
|
||||||
|
private MemoryItem notesMemory;
|
||||||
|
private MemoryItem tilesMemory;
|
||||||
|
private MemoryItem otherMemory;
|
||||||
|
|
||||||
|
private int currentStorageType;
|
||||||
|
private String currentStoragePath;
|
||||||
|
|
||||||
|
public DataStorageHelper(@NonNull OsmandApplication app) {
|
||||||
|
this.app = app;
|
||||||
|
prepareData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareData() {
|
||||||
|
initStorageItems();
|
||||||
|
initUsedMemoryItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initStorageItems() {
|
||||||
|
OsmandSettings settings = app.getSettings();
|
||||||
|
if (settings.getExternalStorageDirectoryTypeV19() >= 0) {
|
||||||
|
currentStorageType = settings.getExternalStorageDirectoryTypeV19();
|
||||||
|
} else {
|
||||||
|
ValueHolder<Integer> vh = new ValueHolder<Integer>();
|
||||||
|
if (vh.value != null && vh.value >= 0) {
|
||||||
|
currentStorageType = vh.value;
|
||||||
|
} else {
|
||||||
|
currentStorageType = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentStoragePath = settings.getExternalStorageDirectory().getAbsolutePath();
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
|
||||||
|
//internal storage
|
||||||
|
String path = settings.getInternalAppPath().getAbsolutePath();
|
||||||
|
File dir = new File(path);
|
||||||
|
int iconId = R.drawable.ic_action_phone;
|
||||||
|
|
||||||
|
StorageItem internalStorageItem = StorageItem.builder()
|
||||||
|
.setKey(INTERNAL_STORAGE)
|
||||||
|
.setTitle(app.getString(R.string.storage_directory_internal_app))
|
||||||
|
.setDirectory(path)
|
||||||
|
.setDescription(app.getString(R.string.internal_app_storage_description))
|
||||||
|
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_INTERNAL_FILE)
|
||||||
|
.setIconResId(iconId)
|
||||||
|
.createItem();
|
||||||
|
addItem(internalStorageItem);
|
||||||
|
|
||||||
|
//shared storage
|
||||||
|
dir = settings.getDefaultInternalStorage();
|
||||||
|
path = dir.getAbsolutePath();
|
||||||
|
iconId = R.drawable.ic_action_phone;
|
||||||
|
|
||||||
|
StorageItem sharedStorageItem = StorageItem.builder()
|
||||||
|
.setKey(SHARED_STORAGE)
|
||||||
|
.setTitle(app.getString(R.string.storage_directory_shared))
|
||||||
|
.setDirectory(path)
|
||||||
|
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_DEFAULT)
|
||||||
|
.setIconResId(iconId)
|
||||||
|
.createItem();
|
||||||
|
addItem(sharedStorageItem);
|
||||||
|
|
||||||
|
//external storage
|
||||||
|
File[] externals = app.getExternalFilesDirs(null);
|
||||||
|
if (externals != null) {
|
||||||
|
int i = 0;
|
||||||
|
for (File external : externals) {
|
||||||
|
if (external != null) {
|
||||||
|
++i;
|
||||||
|
dir = external;
|
||||||
|
path = dir.getAbsolutePath();
|
||||||
|
iconId = getIconForStorageType(dir);
|
||||||
|
StorageItem externalStorageItem = StorageItem.builder()
|
||||||
|
.setKey(EXTERNAL_STORAGE + i)
|
||||||
|
.setTitle(app.getString(R.string.storage_directory_external) + " " + i)
|
||||||
|
.setDirectory(path)
|
||||||
|
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_EXTERNAL_FILE)
|
||||||
|
.setIconResId(iconId)
|
||||||
|
.createItem();
|
||||||
|
addItem(externalStorageItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//multi user storage
|
||||||
|
File[] obbDirs = app.getObbDirs();
|
||||||
|
if (obbDirs != null) {
|
||||||
|
int i = 0;
|
||||||
|
for (File obb : obbDirs) {
|
||||||
|
if (obb != null) {
|
||||||
|
++i;
|
||||||
|
dir = obb;
|
||||||
|
path = dir.getAbsolutePath();
|
||||||
|
iconId = getIconForStorageType(dir);
|
||||||
|
StorageItem multiuserStorageItem = StorageItem.builder()
|
||||||
|
.setKey(MULTIUSER_STORAGE + i)
|
||||||
|
.setTitle(app.getString(R.string.storage_directory_multiuser) + " " + i)
|
||||||
|
.setDirectory(path)
|
||||||
|
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_OBB)
|
||||||
|
.setIconResId(iconId)
|
||||||
|
.createItem();
|
||||||
|
addItem(multiuserStorageItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//manually specified storage
|
||||||
|
manuallySpecified = StorageItem.builder()
|
||||||
|
.setKey(MANUALLY_SPECIFIED)
|
||||||
|
.setTitle(app.getString(R.string.storage_directory_manual))
|
||||||
|
.setDirectory(currentStoragePath)
|
||||||
|
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_SPECIFIED)
|
||||||
|
.setIconResId(R.drawable.ic_action_folder)
|
||||||
|
.createItem();
|
||||||
|
storageItems.add(manuallySpecified);
|
||||||
|
|
||||||
|
if (currentDataStorage == null) {
|
||||||
|
currentDataStorage = manuallySpecified;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUsedMemoryItems() {
|
||||||
|
mapsMemory = MemoryItem.builder()
|
||||||
|
.setKey(MAPS_MEMORY)
|
||||||
|
.setExtensions(IndexConstants.BINARY_MAP_INDEX_EXT)
|
||||||
|
.setDirectories(
|
||||||
|
createDirectory(MAPS_PATH, false, EXTENSIONS, true),
|
||||||
|
createDirectory(ROADS_INDEX_DIR, true, EXTENSIONS, true),
|
||||||
|
createDirectory(WIKI_INDEX_DIR, true, EXTENSIONS, true),
|
||||||
|
createDirectory(WIKIVOYAGE_INDEX_DIR, true, EXTENSIONS, true),
|
||||||
|
createDirectory(BACKUP_INDEX_DIR, true, EXTENSIONS, true))
|
||||||
|
.createItem();
|
||||||
|
memoryItems.add(mapsMemory);
|
||||||
|
|
||||||
|
terrainMemory = MemoryItem.builder()
|
||||||
|
.setKey(TERRAIN_MEMORY)
|
||||||
|
.setExtensions(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
|
||||||
|
.setDirectories(
|
||||||
|
createDirectory(SRTM_INDEX_DIR, true, EXTENSIONS, true),
|
||||||
|
createDirectory(TILES_INDEX_DIR, false, PREFIX, false))
|
||||||
|
.setPrefixes("Hillshade", "Slope")
|
||||||
|
.createItem();
|
||||||
|
memoryItems.add(terrainMemory);
|
||||||
|
|
||||||
|
tracksMemory = MemoryItem.builder()
|
||||||
|
.setKey(TRACKS_MEMORY)
|
||||||
|
// .setExtensions(IndexConstants.GPX_FILE_EXT, ".gpx.bz2")
|
||||||
|
.setDirectories(
|
||||||
|
createDirectory(GPX_INDEX_DIR, true, EXTENSIONS, true))
|
||||||
|
.createItem();
|
||||||
|
memoryItems.add(tracksMemory);
|
||||||
|
|
||||||
|
notesMemory = MemoryItem.builder()
|
||||||
|
.setKey(NOTES_MEMORY)
|
||||||
|
// .setExtensions("")
|
||||||
|
.setDirectories(
|
||||||
|
createDirectory(AV_INDEX_DIR, true, EXTENSIONS, true))
|
||||||
|
.createItem();
|
||||||
|
memoryItems.add(notesMemory);
|
||||||
|
|
||||||
|
tilesMemory = MemoryItem.builder()
|
||||||
|
.setKey(TILES_MEMORY)
|
||||||
|
// .setExtensions("")
|
||||||
|
.setDirectories(
|
||||||
|
createDirectory(TILES_INDEX_DIR, true, EXTENSIONS, true))
|
||||||
|
.createItem();
|
||||||
|
memoryItems.add(tilesMemory);
|
||||||
|
|
||||||
|
otherMemory = MemoryItem.builder()
|
||||||
|
.setKey(OTHER_MEMORY)
|
||||||
|
.createItem();
|
||||||
|
memoryItems.add(otherMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<StorageItem> getStorageItems() {
|
||||||
|
return storageItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIconForStorageType(File dir) {
|
||||||
|
return R.drawable.ic_action_folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StorageItem getCurrentStorage() {
|
||||||
|
return currentDataStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addItem(StorageItem item) {
|
||||||
|
if (currentStorageType == item.getType() && currentStoragePath.equals(item.getDirectory())) {
|
||||||
|
currentDataStorage = item;
|
||||||
|
}
|
||||||
|
storageItems.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StorageItem getManuallySpecified() {
|
||||||
|
return manuallySpecified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StorageItem getStorage(String key) {
|
||||||
|
if (storageItems != null && key != null) {
|
||||||
|
for (StorageItem storageItem : storageItems) {
|
||||||
|
if (key.equals(storageItem.getKey())) {
|
||||||
|
return storageItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<MemoryItem> getMemoryInfoItems() {
|
||||||
|
return memoryItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefreshUsedMemoryTask calculateMemoryUsedInfo(UpdateMemoryInfoUIAdapter uiAdapter) {
|
||||||
|
File rootDir = new File(currentStoragePath);
|
||||||
|
RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(uiAdapter, otherMemory, rootDir, null, null, OTHER_MEMORY);
|
||||||
|
task.execute(mapsMemory, terrainMemory, tracksMemory, notesMemory);
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefreshUsedMemoryTask calculateTilesMemoryUsed(UpdateMemoryInfoUIAdapter listener) {
|
||||||
|
File rootDir = new File(tilesMemory.getDirectories()[0].getAbsolutePath());
|
||||||
|
RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(listener, otherMemory, rootDir, null, terrainMemory.getPrefixes(), TILES_MEMORY);
|
||||||
|
task.execute(tilesMemory);
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTotalUsedBytes() {
|
||||||
|
long total = 0;
|
||||||
|
if (memoryItems != null && memoryItems.size() > 0) {
|
||||||
|
for (MemoryItem mi : memoryItems) {
|
||||||
|
total += mi.getUsedMemoryBytes();
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DirectoryItem createDirectory(@NonNull String relativePath,
|
||||||
|
boolean processInternalDirectories,
|
||||||
|
CheckingType checkingType,
|
||||||
|
boolean addUnmatchedToOtherMemory) {
|
||||||
|
String path = app.getAppPath(relativePath).getAbsolutePath();
|
||||||
|
return new DirectoryItem(path, processInternalDirectories, checkingType, addUnmatchedToOtherMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFormattedMemoryInfo(long bytes, String[] formatStrings) {
|
||||||
|
int type = 0;
|
||||||
|
double memory = (double) bytes / 1024;
|
||||||
|
while (memory > 1024 && type < formatStrings.length) {
|
||||||
|
++type;
|
||||||
|
memory = memory / 1024;
|
||||||
|
}
|
||||||
|
String formattedUsed = new DecimalFormat("#.##").format(memory);
|
||||||
|
return String.format(formatStrings[type], formattedUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface UpdateMemoryInfoUIAdapter {
|
||||||
|
|
||||||
|
void onMemoryInfoUpdate();
|
||||||
|
|
||||||
|
void onFinishUpdating(String tag);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package net.osmand.plus.settings.datastorage.item;
|
||||||
|
|
||||||
|
public class DirectoryItem {
|
||||||
|
|
||||||
|
private final String absolutePath;
|
||||||
|
private final boolean processInternalDirectories;
|
||||||
|
private final CheckingType checkingType;
|
||||||
|
private final boolean addUnmatchedToOtherMemory;
|
||||||
|
|
||||||
|
public enum CheckingType {
|
||||||
|
EXTENSIONS,
|
||||||
|
PREFIX
|
||||||
|
}
|
||||||
|
|
||||||
|
public DirectoryItem(String absolutePath,
|
||||||
|
boolean processInternalDirectories,
|
||||||
|
CheckingType checkingType,
|
||||||
|
boolean addUnmatchedToOtherMemory) {
|
||||||
|
this.absolutePath = absolutePath;
|
||||||
|
this.processInternalDirectories = processInternalDirectories;
|
||||||
|
this.checkingType = checkingType;
|
||||||
|
this.addUnmatchedToOtherMemory = addUnmatchedToOtherMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAbsolutePath() {
|
||||||
|
return absolutePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldProcessInternalDirectories() {
|
||||||
|
return processInternalDirectories;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckingType getCheckingType() {
|
||||||
|
return checkingType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldAddUnmatchedToOtherMemory() {
|
||||||
|
return addUnmatchedToOtherMemory;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,18 @@
|
||||||
package net.osmand.plus.settings.fragments;
|
package net.osmand.plus.settings.datastorage.item;
|
||||||
|
|
||||||
public class DataStorageMemoryItem {
|
public class MemoryItem {
|
||||||
public final static int EXTENSIONS = 0;
|
|
||||||
public final static int PREFIX = 1;
|
|
||||||
|
|
||||||
private String key;
|
private String key;
|
||||||
private String[] extensions;
|
private final String[] extensions;
|
||||||
private String[] prefixes;
|
private final String[] prefixes;
|
||||||
private Directory[] directories;
|
private final DirectoryItem[] directories;
|
||||||
private long usedMemoryBytes;
|
private long usedMemoryBytes;
|
||||||
|
|
||||||
private DataStorageMemoryItem(String key, String[] extensions, String[] prefixes, long usedMemoryBytes, Directory[] directories) {
|
private MemoryItem(String key,
|
||||||
|
String[] extensions,
|
||||||
|
String[] prefixes,
|
||||||
|
long usedMemoryBytes,
|
||||||
|
DirectoryItem[] directories) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.extensions = extensions;
|
this.extensions = extensions;
|
||||||
this.prefixes = prefixes;
|
this.prefixes = prefixes;
|
||||||
|
@ -42,7 +44,7 @@ public class DataStorageMemoryItem {
|
||||||
return prefixes;
|
return prefixes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Directory[] getDirectories() {
|
public DirectoryItem[] getDirectories() {
|
||||||
return directories;
|
return directories;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +56,7 @@ public class DataStorageMemoryItem {
|
||||||
private String key;
|
private String key;
|
||||||
private String[] extensions;
|
private String[] extensions;
|
||||||
private String[] prefixes;
|
private String[] prefixes;
|
||||||
private Directory[] directories;
|
private DirectoryItem[] directories;
|
||||||
private long usedMemoryBytes;
|
private long usedMemoryBytes;
|
||||||
|
|
||||||
public DataStorageMemoryItemBuilder setKey(String key) {
|
public DataStorageMemoryItemBuilder setKey(String key) {
|
||||||
|
@ -72,7 +74,7 @@ public class DataStorageMemoryItem {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataStorageMemoryItemBuilder setDirectories(Directory ... directories) {
|
public DataStorageMemoryItemBuilder setDirectories(DirectoryItem... directories) {
|
||||||
this.directories = directories;
|
this.directories = directories;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -82,38 +84,8 @@ public class DataStorageMemoryItem {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataStorageMemoryItem createItem() {
|
public MemoryItem createItem() {
|
||||||
return new DataStorageMemoryItem(key, extensions, prefixes, usedMemoryBytes, directories);
|
return new MemoryItem(key, extensions, prefixes, usedMemoryBytes, directories);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Directory {
|
|
||||||
private String absolutePath;
|
|
||||||
private boolean goDeeper;
|
|
||||||
private int checkingType;
|
|
||||||
private boolean skipOther;
|
|
||||||
|
|
||||||
public Directory(String absolutePath, boolean goDeeper, int checkingType, boolean skipOther) {
|
|
||||||
this.absolutePath = absolutePath;
|
|
||||||
this.goDeeper = goDeeper;
|
|
||||||
this.checkingType = checkingType;
|
|
||||||
this.skipOther = skipOther;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAbsolutePath() {
|
|
||||||
return absolutePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGoDeeper() {
|
|
||||||
return goDeeper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCheckingType() {
|
|
||||||
return checkingType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSkipOther() {
|
|
||||||
return skipOther;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package net.osmand.plus.settings.fragments;
|
package net.osmand.plus.settings.datastorage.item;
|
||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import androidx.annotation.IdRes;
|
import androidx.annotation.IdRes;
|
||||||
|
|
||||||
public class DataStorageMenuItem implements Parcelable, Cloneable {
|
public class StorageItem implements Parcelable, Cloneable {
|
||||||
|
|
||||||
private String key;
|
private String key;
|
||||||
private int type;
|
private int type;
|
||||||
|
@ -15,8 +15,12 @@ public class DataStorageMenuItem implements Parcelable, Cloneable {
|
||||||
@IdRes
|
@IdRes
|
||||||
private int iconResId;
|
private int iconResId;
|
||||||
|
|
||||||
private DataStorageMenuItem(String key, int type, String title, String description,
|
private StorageItem(String key,
|
||||||
String directory, int iconResId) {
|
int type,
|
||||||
|
String title,
|
||||||
|
String description,
|
||||||
|
String directory,
|
||||||
|
int iconResId) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
@ -25,7 +29,7 @@ public class DataStorageMenuItem implements Parcelable, Cloneable {
|
||||||
this.iconResId = iconResId;
|
this.iconResId = iconResId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataStorageMenuItem(Parcel in) {
|
private StorageItem(Parcel in) {
|
||||||
key = in.readString();
|
key = in.readString();
|
||||||
type = in.readInt();
|
type = in.readInt();
|
||||||
title = in.readString();
|
title = in.readString();
|
||||||
|
@ -99,16 +103,16 @@ public class DataStorageMenuItem implements Parcelable, Cloneable {
|
||||||
dest.writeString(directory);
|
dest.writeString(directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Parcelable.Creator<DataStorageMenuItem> CREATOR = new Parcelable.Creator<DataStorageMenuItem>() {
|
public static final Parcelable.Creator<StorageItem> CREATOR = new Parcelable.Creator<StorageItem>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataStorageMenuItem createFromParcel(Parcel source) {
|
public StorageItem createFromParcel(Parcel source) {
|
||||||
return new DataStorageMenuItem(source);
|
return new StorageItem(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataStorageMenuItem[] newArray(int size) {
|
public StorageItem[] newArray(int size) {
|
||||||
return new DataStorageMenuItem[size];
|
return new StorageItem[size];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -151,14 +155,14 @@ public class DataStorageMenuItem implements Parcelable, Cloneable {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataStorageMenuItem createItem() {
|
public StorageItem createItem() {
|
||||||
return new DataStorageMenuItem(key, type, title, description, directory, iconResId);
|
return new StorageItem(key, type, title, description, directory, iconResId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object clone() throws CloneNotSupportedException {
|
public Object clone() throws CloneNotSupportedException {
|
||||||
return DataStorageMenuItem.builder()
|
return StorageItem.builder()
|
||||||
.setKey(this.key)
|
.setKey(this.key)
|
||||||
.setTitle(this.title)
|
.setTitle(this.title)
|
||||||
.setDescription(this.description)
|
.setDescription(this.description)
|
|
@ -0,0 +1,173 @@
|
||||||
|
package net.osmand.plus.settings.datastorage.task;
|
||||||
|
|
||||||
|
import android.app.ProgressDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import net.osmand.plus.ProgressImplementation;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.activities.OsmandActionBarActivity;
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
public class MoveFilesTask extends AsyncTask<Void, Void, Boolean> {
|
||||||
|
|
||||||
|
protected WeakReference<OsmandActionBarActivity> activity;
|
||||||
|
private WeakReference<Context> context;
|
||||||
|
private File from;
|
||||||
|
private File to;
|
||||||
|
protected ProgressImplementation progress;
|
||||||
|
private Runnable runOnSuccess;
|
||||||
|
private int movedCount;
|
||||||
|
private long movedSize;
|
||||||
|
private int copiedCount;
|
||||||
|
private long copiedSize;
|
||||||
|
private int failedCount;
|
||||||
|
private long failedSize;
|
||||||
|
private String exceptionMessage;
|
||||||
|
|
||||||
|
public MoveFilesTask(OsmandActionBarActivity activity, File from, File to) {
|
||||||
|
this.activity = new WeakReference<>(activity);
|
||||||
|
this.context = new WeakReference<>((Context) activity);
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRunOnSuccess(Runnable runOnSuccess) {
|
||||||
|
this.runOnSuccess = runOnSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMovedCount() {
|
||||||
|
return movedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCopiedCount() {
|
||||||
|
return copiedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFailedCount() {
|
||||||
|
return failedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMovedSize() {
|
||||||
|
return movedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCopiedSize() {
|
||||||
|
return copiedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getFailedSize() {
|
||||||
|
return failedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
Context ctx = context.get();
|
||||||
|
if (context == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
movedCount = 0;
|
||||||
|
copiedCount = 0;
|
||||||
|
failedCount = 0;
|
||||||
|
progress = ProgressImplementation.createProgressDialog(
|
||||||
|
ctx, ctx.getString(R.string.copying_osmand_files),
|
||||||
|
ctx.getString(R.string.copying_osmand_files_descr, to.getPath()),
|
||||||
|
ProgressDialog.STYLE_HORIZONTAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Boolean result) {
|
||||||
|
Context ctx = context.get();
|
||||||
|
if (ctx == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (result != null) {
|
||||||
|
if (result.booleanValue() && runOnSuccess != null) {
|
||||||
|
runOnSuccess.run();
|
||||||
|
} else if (!result.booleanValue()) {
|
||||||
|
Toast.makeText(ctx, ctx.getString(R.string.shared_string_io_error) + ": " + exceptionMessage, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (progress.getDialog().isShowing()) {
|
||||||
|
progress.getDialog().dismiss();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
//ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void movingFiles(File f, File t, int depth) throws IOException {
|
||||||
|
Context ctx = context.get();
|
||||||
|
if (ctx == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (depth <= 2) {
|
||||||
|
progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), -1);
|
||||||
|
}
|
||||||
|
if (f.isDirectory()) {
|
||||||
|
t.mkdirs();
|
||||||
|
File[] lf = f.listFiles();
|
||||||
|
if (lf != null) {
|
||||||
|
for (int i = 0; i < lf.length; i++) {
|
||||||
|
if (lf[i] != null) {
|
||||||
|
movingFiles(lf[i], new File(t, lf[i].getName()), depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.delete();
|
||||||
|
} else if (f.isFile()) {
|
||||||
|
if (t.exists()) {
|
||||||
|
Algorithms.removeAllFiles(t);
|
||||||
|
}
|
||||||
|
boolean rnm = false;
|
||||||
|
long fileSize = f.length();
|
||||||
|
try {
|
||||||
|
rnm = f.renameTo(t);
|
||||||
|
movedCount++;
|
||||||
|
movedSize += fileSize;
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
}
|
||||||
|
if (!rnm) {
|
||||||
|
FileInputStream fin = new FileInputStream(f);
|
||||||
|
FileOutputStream fout = new FileOutputStream(t);
|
||||||
|
try {
|
||||||
|
progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), (int) (f.length() / 1024));
|
||||||
|
Algorithms.streamCopy(fin, fout, progress, 1024);
|
||||||
|
copiedCount++;
|
||||||
|
copiedSize += fileSize;
|
||||||
|
} catch (IOException e) {
|
||||||
|
failedCount++;
|
||||||
|
failedSize += fileSize;
|
||||||
|
} finally {
|
||||||
|
fin.close();
|
||||||
|
fout.close();
|
||||||
|
}
|
||||||
|
f.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (depth <= 2) {
|
||||||
|
progress.finishTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Boolean doInBackground(Void... params) {
|
||||||
|
to.mkdirs();
|
||||||
|
try {
|
||||||
|
movingFiles(from, to, 0);
|
||||||
|
} catch (IOException e) {
|
||||||
|
exceptionMessage = e.getMessage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,232 @@
|
||||||
|
package net.osmand.plus.settings.datastorage.task;
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import net.osmand.plus.settings.datastorage.DataStorageHelper.UpdateMemoryInfoUIAdapter;
|
||||||
|
import net.osmand.plus.settings.datastorage.item.DirectoryItem;
|
||||||
|
import net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType;
|
||||||
|
import net.osmand.plus.settings.datastorage.item.MemoryItem;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import static net.osmand.plus.settings.datastorage.DataStorageFragment.UI_REFRESH_TIME_MS;
|
||||||
|
import static net.osmand.util.Algorithms.objectEquals;
|
||||||
|
|
||||||
|
public class RefreshUsedMemoryTask extends AsyncTask<MemoryItem, Void, Void> {
|
||||||
|
private final UpdateMemoryInfoUIAdapter uiAdapter;
|
||||||
|
private final File root;
|
||||||
|
private final MemoryItem otherMemoryItem;
|
||||||
|
private final String[] directoriesToSkip;
|
||||||
|
private final String[] filePrefixesToSkip;
|
||||||
|
private final String tag;
|
||||||
|
private long lastRefreshTime;
|
||||||
|
|
||||||
|
public RefreshUsedMemoryTask(UpdateMemoryInfoUIAdapter uiAdapter,
|
||||||
|
MemoryItem otherMemoryItem,
|
||||||
|
File root,
|
||||||
|
String[] directoriesToSkip,
|
||||||
|
String[] filePrefixesToSkip,
|
||||||
|
String tag) {
|
||||||
|
this.uiAdapter = uiAdapter;
|
||||||
|
this.otherMemoryItem = otherMemoryItem;
|
||||||
|
this.root = root;
|
||||||
|
this.directoriesToSkip = directoriesToSkip;
|
||||||
|
this.filePrefixesToSkip = filePrefixesToSkip;
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(MemoryItem... items) {
|
||||||
|
lastRefreshTime = System.currentTimeMillis();
|
||||||
|
if (root.canRead()) {
|
||||||
|
calculateMultiTypes(root, items);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calculateMultiTypes(File rootDir,
|
||||||
|
MemoryItem... items) {
|
||||||
|
File[] subFiles = rootDir.listFiles();
|
||||||
|
if (subFiles != null) {
|
||||||
|
for (File file : subFiles) {
|
||||||
|
if (isCancelled()) break;
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
if (!shouldSkipDirectory(file)) {
|
||||||
|
processDirectory(file, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (file.isFile()) {
|
||||||
|
if (!shouldSkipFile(file)) {
|
||||||
|
processFile(rootDir, file, items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refreshUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldSkipDirectory(@NonNull File dir) {
|
||||||
|
if (directoriesToSkip != null) {
|
||||||
|
for (String dirToSkipPath : directoriesToSkip) {
|
||||||
|
String dirPath = dir.getAbsolutePath();
|
||||||
|
if (objectEquals(dirPath, dirToSkipPath)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldSkipFile(@NonNull File file) {
|
||||||
|
if (filePrefixesToSkip != null) {
|
||||||
|
String fileName = file.getName().toLowerCase();
|
||||||
|
for (String prefixToAvoid : filePrefixesToSkip) {
|
||||||
|
String prefix = prefixToAvoid.toLowerCase();
|
||||||
|
if (fileName.startsWith(prefix)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processDirectory(@NonNull File directory,
|
||||||
|
@NonNull MemoryItem... items) {
|
||||||
|
String directoryPath = directory.getAbsolutePath();
|
||||||
|
for (MemoryItem memoryItem : items) {
|
||||||
|
DirectoryItem[] targetDirectories = memoryItem.getDirectories();
|
||||||
|
if (targetDirectories != null) {
|
||||||
|
for (DirectoryItem dir : targetDirectories) {
|
||||||
|
String allowedDirPath = dir.getAbsolutePath();
|
||||||
|
boolean isPerfectlyMatch = objectEquals(directoryPath, allowedDirPath);
|
||||||
|
boolean isParentDirectory = !isPerfectlyMatch && (directoryPath.startsWith(allowedDirPath));
|
||||||
|
boolean isMatchDirectory = isPerfectlyMatch || isParentDirectory;
|
||||||
|
if (isPerfectlyMatch) {
|
||||||
|
calculateMultiTypes(directory, items);
|
||||||
|
return;
|
||||||
|
} else if (isParentDirectory && dir.shouldProcessInternalDirectories()) {
|
||||||
|
calculateMultiTypes(directory, items);
|
||||||
|
return;
|
||||||
|
} else if (isMatchDirectory && !dir.shouldAddUnmatchedToOtherMemory()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Current directory did not match to any type
|
||||||
|
otherMemoryItem.addBytes(calculateFolderSize(directory));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processFile(@NonNull File rootDir,
|
||||||
|
@NonNull File file,
|
||||||
|
@NonNull MemoryItem... items) {
|
||||||
|
for (MemoryItem item : items) {
|
||||||
|
DirectoryItem[] targetDirectories = item.getDirectories();
|
||||||
|
if (targetDirectories == null) continue;
|
||||||
|
String rootDirPath = rootDir.getAbsolutePath();
|
||||||
|
|
||||||
|
for (DirectoryItem targetDirectory : targetDirectories) {
|
||||||
|
String allowedDirPath = targetDirectory.getAbsolutePath();
|
||||||
|
boolean processInternal = targetDirectory.shouldProcessInternalDirectories();
|
||||||
|
if (objectEquals(rootDirPath, allowedDirPath)
|
||||||
|
|| (rootDirPath.startsWith(allowedDirPath) && processInternal)) {
|
||||||
|
CheckingType checkingType = targetDirectory.getCheckingType();
|
||||||
|
switch (checkingType) {
|
||||||
|
case EXTENSIONS: {
|
||||||
|
if (isSuitableExtension(file, item)) {
|
||||||
|
item.addBytes(file.length());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PREFIX: {
|
||||||
|
if (isSuitablePrefix(file, item)) {
|
||||||
|
item.addBytes(file.length());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!targetDirectory.shouldAddUnmatchedToOtherMemory()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Current file did not match any type
|
||||||
|
otherMemoryItem.addBytes(file.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSuitableExtension(@NonNull File file,
|
||||||
|
@NonNull MemoryItem item) {
|
||||||
|
String[] extensions = item.getExtensions();
|
||||||
|
if (extensions != null) {
|
||||||
|
for (String extension : extensions) {
|
||||||
|
if (file.getAbsolutePath().endsWith(extension)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return extensions == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSuitablePrefix(@NonNull File file,
|
||||||
|
@NonNull MemoryItem item) {
|
||||||
|
String[] prefixes = item.getPrefixes();
|
||||||
|
if (prefixes != null) {
|
||||||
|
for (String prefix : prefixes) {
|
||||||
|
if (file.getName().toLowerCase().startsWith(prefix.toLowerCase())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prefixes == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long calculateFolderSize(@NonNull File dir) {
|
||||||
|
long bytes = 0;
|
||||||
|
if (dir.isDirectory()) {
|
||||||
|
File[] files = dir.listFiles();
|
||||||
|
if (files == null) return 0;
|
||||||
|
|
||||||
|
for (File file : files) {
|
||||||
|
if (isCancelled()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
bytes += calculateFolderSize(file);
|
||||||
|
} else if (file.isFile()) {
|
||||||
|
bytes += file.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onProgressUpdate(Void... values) {
|
||||||
|
super.onProgressUpdate(values);
|
||||||
|
if (uiAdapter != null) {
|
||||||
|
uiAdapter.onMemoryInfoUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid) {
|
||||||
|
super.onPostExecute(aVoid);
|
||||||
|
if (uiAdapter != null) {
|
||||||
|
uiAdapter.onFinishUpdating(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshUI() {
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
if ((currentTime - lastRefreshTime) > UI_REFRESH_TIME_MS) {
|
||||||
|
lastRefreshTime = currentTime;
|
||||||
|
publishProgress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package net.osmand.plus.settings.datastorage.task;
|
||||||
|
|
||||||
|
import android.app.ProgressDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.ProgressImplementation;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class ReloadDataTask extends AsyncTask<Void, Void, Boolean> {
|
||||||
|
private WeakReference<Context> ctx;
|
||||||
|
protected ProgressImplementation progress;
|
||||||
|
private OsmandApplication app;
|
||||||
|
|
||||||
|
public ReloadDataTask(Context ctx, OsmandApplication app) {
|
||||||
|
this.ctx = new WeakReference<>(ctx);
|
||||||
|
this.app = app;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
Context c = ctx.get();
|
||||||
|
if (c == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
progress = ProgressImplementation.createProgressDialog(c, c.getString(R.string.loading_data),
|
||||||
|
c.getString(R.string.loading_data), ProgressDialog.STYLE_HORIZONTAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Boolean result) {
|
||||||
|
try {
|
||||||
|
if (progress.getDialog().isShowing()) {
|
||||||
|
progress.getDialog().dismiss();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
//ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Boolean doInBackground(Void... params) {
|
||||||
|
app.getResourceManager().reloadIndexes(progress, new ArrayList<String>());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,6 +73,7 @@ import net.osmand.plus.settings.bottomsheets.ChangeGeneralProfilesPrefBottomShee
|
||||||
import net.osmand.plus.settings.bottomsheets.EditTextPreferenceBottomSheet;
|
import net.osmand.plus.settings.bottomsheets.EditTextPreferenceBottomSheet;
|
||||||
import net.osmand.plus.settings.bottomsheets.MultiSelectPreferencesBottomSheet;
|
import net.osmand.plus.settings.bottomsheets.MultiSelectPreferencesBottomSheet;
|
||||||
import net.osmand.plus.settings.bottomsheets.SingleSelectPreferenceBottomSheet;
|
import net.osmand.plus.settings.bottomsheets.SingleSelectPreferenceBottomSheet;
|
||||||
|
import net.osmand.plus.settings.datastorage.DataStorageFragment;
|
||||||
import net.osmand.plus.settings.preferences.ListPreferenceEx;
|
import net.osmand.plus.settings.preferences.ListPreferenceEx;
|
||||||
import net.osmand.plus.settings.preferences.MultiSelectBooleanPreference;
|
import net.osmand.plus.settings.preferences.MultiSelectBooleanPreference;
|
||||||
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;
|
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;
|
||||||
|
|
|
@ -1,485 +0,0 @@
|
||||||
package net.osmand.plus.settings.fragments;
|
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import net.osmand.IndexConstants;
|
|
||||||
import net.osmand.ValueHolder;
|
|
||||||
import net.osmand.plus.OsmandApplication;
|
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
|
||||||
import net.osmand.plus.R;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import static net.osmand.plus.settings.fragments.DataStorageFragment.UI_REFRESH_TIME_MS;
|
|
||||||
import static net.osmand.plus.settings.fragments.DataStorageMemoryItem.Directory;
|
|
||||||
import static net.osmand.plus.settings.fragments.DataStorageMemoryItem.EXTENSIONS;
|
|
||||||
import static net.osmand.plus.settings.fragments.DataStorageMemoryItem.PREFIX;
|
|
||||||
|
|
||||||
public class DataStorageHelper {
|
|
||||||
public final static String INTERNAL_STORAGE = "internal_storage";
|
|
||||||
public final static String EXTERNAL_STORAGE = "external_storage";
|
|
||||||
public final static String SHARED_STORAGE = "shared_storage";
|
|
||||||
public final static String MULTIUSER_STORAGE = "multiuser_storage";
|
|
||||||
public final static String MANUALLY_SPECIFIED = "manually_specified";
|
|
||||||
|
|
||||||
public final static String MAPS_MEMORY = "maps_memory_used";
|
|
||||||
public final static String SRTM_AND_HILLSHADE_MEMORY = "contour_lines_and_hillshade_memory";
|
|
||||||
public final static String TRACKS_MEMORY = "tracks_memory_used";
|
|
||||||
public final static String NOTES_MEMORY = "notes_memory_used";
|
|
||||||
public final static String TILES_MEMORY = "tiles_memory_used";
|
|
||||||
public final static String OTHER_MEMORY = "other_memory_used";
|
|
||||||
|
|
||||||
private ArrayList<DataStorageMenuItem> menuItems = new ArrayList<>();
|
|
||||||
private DataStorageMenuItem currentDataStorage;
|
|
||||||
private DataStorageMenuItem manuallySpecified;
|
|
||||||
|
|
||||||
private ArrayList<DataStorageMemoryItem> memoryItems = new ArrayList<>();
|
|
||||||
private DataStorageMemoryItem mapsMemory;
|
|
||||||
private DataStorageMemoryItem srtmAndHillshadeMemory;
|
|
||||||
private DataStorageMemoryItem tracksMemory;
|
|
||||||
private DataStorageMemoryItem notesMemory;
|
|
||||||
private DataStorageMemoryItem tilesMemory;
|
|
||||||
private DataStorageMemoryItem otherMemory;
|
|
||||||
|
|
||||||
private int currentStorageType;
|
|
||||||
private String currentStoragePath;
|
|
||||||
|
|
||||||
public DataStorageHelper(OsmandApplication app) {
|
|
||||||
prepareData(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prepareData(OsmandApplication app) {
|
|
||||||
|
|
||||||
if (app == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OsmandSettings settings = app.getSettings();
|
|
||||||
|
|
||||||
if (settings.getExternalStorageDirectoryTypeV19() >= 0) {
|
|
||||||
currentStorageType = settings.getExternalStorageDirectoryTypeV19();
|
|
||||||
} else {
|
|
||||||
ValueHolder<Integer> vh = new ValueHolder<Integer>();
|
|
||||||
if (vh.value != null && vh.value >= 0) {
|
|
||||||
currentStorageType = vh.value;
|
|
||||||
} else {
|
|
||||||
currentStorageType = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentStoragePath = settings.getExternalStorageDirectory().getAbsolutePath();
|
|
||||||
|
|
||||||
String path;
|
|
||||||
File dir;
|
|
||||||
int iconId;
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
|
||||||
|
|
||||||
//internal storage
|
|
||||||
path = settings.getInternalAppPath().getAbsolutePath();
|
|
||||||
dir = new File(path);
|
|
||||||
iconId = R.drawable.ic_action_phone;
|
|
||||||
|
|
||||||
DataStorageMenuItem internalStorageItem = DataStorageMenuItem.builder()
|
|
||||||
.setKey(INTERNAL_STORAGE)
|
|
||||||
.setTitle(app.getString(R.string.storage_directory_internal_app))
|
|
||||||
.setDirectory(path)
|
|
||||||
.setDescription(app.getString(R.string.internal_app_storage_description))
|
|
||||||
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_INTERNAL_FILE)
|
|
||||||
.setIconResId(iconId)
|
|
||||||
.createItem();
|
|
||||||
addItem(internalStorageItem);
|
|
||||||
|
|
||||||
//shared_storage
|
|
||||||
dir = settings.getDefaultInternalStorage();
|
|
||||||
path = dir.getAbsolutePath();
|
|
||||||
iconId = R.drawable.ic_action_phone;
|
|
||||||
|
|
||||||
DataStorageMenuItem sharedStorageItem = DataStorageMenuItem.builder()
|
|
||||||
.setKey(SHARED_STORAGE)
|
|
||||||
.setTitle(app.getString(R.string.storage_directory_shared))
|
|
||||||
.setDirectory(path)
|
|
||||||
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_DEFAULT)
|
|
||||||
.setIconResId(iconId)
|
|
||||||
.createItem();
|
|
||||||
addItem(sharedStorageItem);
|
|
||||||
|
|
||||||
//external storage
|
|
||||||
File[] externals = app.getExternalFilesDirs(null);
|
|
||||||
if (externals != null) {
|
|
||||||
int i = 0;
|
|
||||||
for (File external : externals) {
|
|
||||||
if (external != null) {
|
|
||||||
++i;
|
|
||||||
dir = external;
|
|
||||||
path = dir.getAbsolutePath();
|
|
||||||
iconId = getIconForStorageType(dir);
|
|
||||||
DataStorageMenuItem externalStorageItem = DataStorageMenuItem.builder()
|
|
||||||
.setKey(EXTERNAL_STORAGE + i)
|
|
||||||
.setTitle(app.getString(R.string.storage_directory_external) + " " + i)
|
|
||||||
.setDirectory(path)
|
|
||||||
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_EXTERNAL_FILE)
|
|
||||||
.setIconResId(iconId)
|
|
||||||
.createItem();
|
|
||||||
addItem(externalStorageItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//multi user storage
|
|
||||||
File[] obbDirs = app.getObbDirs();
|
|
||||||
if (obbDirs != null) {
|
|
||||||
int i = 0;
|
|
||||||
for (File obb : obbDirs) {
|
|
||||||
if (obb != null) {
|
|
||||||
++i;
|
|
||||||
dir = obb;
|
|
||||||
path = dir.getAbsolutePath();
|
|
||||||
iconId = getIconForStorageType(dir);
|
|
||||||
DataStorageMenuItem multiuserStorageItem = DataStorageMenuItem.builder()
|
|
||||||
.setKey(MULTIUSER_STORAGE + i)
|
|
||||||
.setTitle(app.getString(R.string.storage_directory_multiuser) + " " + i)
|
|
||||||
.setDirectory(path)
|
|
||||||
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_OBB)
|
|
||||||
.setIconResId(iconId)
|
|
||||||
.createItem();
|
|
||||||
addItem(multiuserStorageItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//manually specified storage
|
|
||||||
manuallySpecified = DataStorageMenuItem.builder()
|
|
||||||
.setKey(MANUALLY_SPECIFIED)
|
|
||||||
.setTitle(app.getString(R.string.storage_directory_manual))
|
|
||||||
.setDirectory(currentStoragePath)
|
|
||||||
.setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_SPECIFIED)
|
|
||||||
.setIconResId(R.drawable.ic_action_folder)
|
|
||||||
.createItem();
|
|
||||||
menuItems.add(manuallySpecified);
|
|
||||||
|
|
||||||
if (currentDataStorage == null) {
|
|
||||||
currentDataStorage = manuallySpecified;
|
|
||||||
}
|
|
||||||
|
|
||||||
initMemoryUsed(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initMemoryUsed(OsmandApplication app) {
|
|
||||||
mapsMemory = DataStorageMemoryItem.builder()
|
|
||||||
.setKey(MAPS_MEMORY)
|
|
||||||
.setExtensions(IndexConstants.BINARY_MAP_INDEX_EXT)
|
|
||||||
.setDirectories(
|
|
||||||
new Directory(app.getAppPath(IndexConstants.MAPS_PATH).getAbsolutePath(), false, EXTENSIONS, false),
|
|
||||||
new Directory(app.getAppPath(IndexConstants.ROADS_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false),
|
|
||||||
new Directory(app.getAppPath(IndexConstants.WIKI_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false),
|
|
||||||
new Directory(app.getAppPath(IndexConstants.WIKIVOYAGE_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false),
|
|
||||||
new Directory(app.getAppPath(IndexConstants.BACKUP_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false))
|
|
||||||
.createItem();
|
|
||||||
memoryItems.add(mapsMemory);
|
|
||||||
|
|
||||||
srtmAndHillshadeMemory = DataStorageMemoryItem.builder()
|
|
||||||
.setKey(SRTM_AND_HILLSHADE_MEMORY)
|
|
||||||
.setExtensions(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
|
|
||||||
.setDirectories(
|
|
||||||
new Directory(app.getAppPath(IndexConstants.SRTM_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false),
|
|
||||||
new Directory(app.getAppPath(IndexConstants.TILES_INDEX_DIR).getAbsolutePath(), false, PREFIX, true))
|
|
||||||
.setPrefixes("Hillshade")
|
|
||||||
.createItem();
|
|
||||||
memoryItems.add(srtmAndHillshadeMemory);
|
|
||||||
|
|
||||||
tracksMemory = DataStorageMemoryItem.builder()
|
|
||||||
.setKey(TRACKS_MEMORY)
|
|
||||||
// .setExtensions(IndexConstants.GPX_FILE_EXT, ".gpx.bz2")
|
|
||||||
.setDirectories(
|
|
||||||
new Directory(app.getAppPath(IndexConstants.GPX_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false))
|
|
||||||
.createItem();
|
|
||||||
memoryItems.add(tracksMemory);
|
|
||||||
|
|
||||||
notesMemory = DataStorageMemoryItem.builder()
|
|
||||||
.setKey(NOTES_MEMORY)
|
|
||||||
// .setExtensions("")
|
|
||||||
.setDirectories(
|
|
||||||
new Directory(app.getAppPath(IndexConstants.AV_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false))
|
|
||||||
.createItem();
|
|
||||||
memoryItems.add(notesMemory);
|
|
||||||
|
|
||||||
tilesMemory = DataStorageMemoryItem.builder()
|
|
||||||
.setKey(TILES_MEMORY)
|
|
||||||
// .setExtensions("")
|
|
||||||
.setDirectories(
|
|
||||||
new Directory(app.getAppPath(IndexConstants.TILES_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false))
|
|
||||||
.createItem();
|
|
||||||
memoryItems.add(tilesMemory);
|
|
||||||
|
|
||||||
otherMemory = DataStorageMemoryItem.builder()
|
|
||||||
.setKey(OTHER_MEMORY)
|
|
||||||
.createItem();
|
|
||||||
memoryItems.add(otherMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<DataStorageMenuItem> getStorageItems() {
|
|
||||||
return menuItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getIconForStorageType(File dir) {
|
|
||||||
return R.drawable.ic_action_folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataStorageMenuItem getCurrentStorage() {
|
|
||||||
return currentDataStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addItem(DataStorageMenuItem item) {
|
|
||||||
if (currentStorageType == item.getType() && currentStoragePath.equals(item.getDirectory())) {
|
|
||||||
currentDataStorage = item;
|
|
||||||
}
|
|
||||||
menuItems.add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataStorageMenuItem getManuallySpecified() {
|
|
||||||
return manuallySpecified;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataStorageMenuItem getStorage(String key) {
|
|
||||||
if (menuItems != null && key != null) {
|
|
||||||
for (DataStorageMenuItem menuItem : menuItems) {
|
|
||||||
if (key.equals(menuItem.getKey())) {
|
|
||||||
return menuItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCurrentType() {
|
|
||||||
return currentStorageType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCurrentPath() {
|
|
||||||
return currentStoragePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<DataStorageMemoryItem> getMemoryInfoItems() {
|
|
||||||
return memoryItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RefreshMemoryUsedInfo calculateMemoryUsedInfo(UpdateMemoryInfoUIAdapter listener) {
|
|
||||||
File rootDir = new File(currentStoragePath);
|
|
||||||
RefreshMemoryUsedInfo task = new RefreshMemoryUsedInfo(listener, otherMemory, rootDir, null, null, OTHER_MEMORY);
|
|
||||||
task.execute(mapsMemory, srtmAndHillshadeMemory, tracksMemory, notesMemory);
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RefreshMemoryUsedInfo calculateTilesMemoryUsed(UpdateMemoryInfoUIAdapter listener) {
|
|
||||||
File rootDir = new File(tilesMemory.getDirectories()[0].getAbsolutePath());
|
|
||||||
RefreshMemoryUsedInfo task = new RefreshMemoryUsedInfo(listener, otherMemory, rootDir, null, srtmAndHillshadeMemory.getPrefixes(), TILES_MEMORY);
|
|
||||||
task.execute(tilesMemory);
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class RefreshMemoryUsedInfo extends AsyncTask<DataStorageMemoryItem, Void, Void> {
|
|
||||||
private UpdateMemoryInfoUIAdapter listener;
|
|
||||||
private File rootDir;
|
|
||||||
private DataStorageMemoryItem otherMemory;
|
|
||||||
private String[] directoriesToAvoid;
|
|
||||||
private String[] prefixesToAvoid;
|
|
||||||
private String taskKey;
|
|
||||||
private long lastRefreshTime;
|
|
||||||
|
|
||||||
public RefreshMemoryUsedInfo(UpdateMemoryInfoUIAdapter listener, DataStorageMemoryItem otherMemory, File rootDir, String[] directoriesToAvoid, String[] prefixesToAvoid, String taskKey) {
|
|
||||||
this.listener = listener;
|
|
||||||
this.otherMemory = otherMemory;
|
|
||||||
this.rootDir = rootDir;
|
|
||||||
this.directoriesToAvoid = directoriesToAvoid;
|
|
||||||
this.prefixesToAvoid = prefixesToAvoid;
|
|
||||||
this.taskKey = taskKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(DataStorageMemoryItem... items) {
|
|
||||||
lastRefreshTime = System.currentTimeMillis();
|
|
||||||
if (rootDir.canRead()) {
|
|
||||||
calculateMultiTypes(rootDir, items);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateMultiTypes(File rootDir, DataStorageMemoryItem... items) {
|
|
||||||
File[] subFiles = rootDir.listFiles();
|
|
||||||
|
|
||||||
for (File file : subFiles) {
|
|
||||||
if (isCancelled()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
nextFile : {
|
|
||||||
if (file.isDirectory()) {
|
|
||||||
//check current directory should be avoid
|
|
||||||
if (directoriesToAvoid != null) {
|
|
||||||
for (String directoryToAvoid : directoriesToAvoid) {
|
|
||||||
if (file.getAbsolutePath().equals(directoryToAvoid)) {
|
|
||||||
break nextFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//check current directory matched items type
|
|
||||||
for (DataStorageMemoryItem item : items) {
|
|
||||||
Directory[] directories = item.getDirectories();
|
|
||||||
if (directories == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Directory dir : directories) {
|
|
||||||
if (file.getAbsolutePath().equals(dir.getAbsolutePath())
|
|
||||||
|| (file.getAbsolutePath().startsWith(dir.getAbsolutePath()))) {
|
|
||||||
if (dir.isGoDeeper()) {
|
|
||||||
calculateMultiTypes(file, items);
|
|
||||||
break nextFile;
|
|
||||||
} else if (dir.isSkipOther()) {
|
|
||||||
break nextFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//current directory did not match to any type
|
|
||||||
otherMemory.addBytes(getDirectorySize(file));
|
|
||||||
} else if (file.isFile()) {
|
|
||||||
//check current file should be avoid
|
|
||||||
if (prefixesToAvoid != null) {
|
|
||||||
for (String prefixToAvoid : prefixesToAvoid) {
|
|
||||||
if (file.getName().toLowerCase().startsWith(prefixToAvoid.toLowerCase())) {
|
|
||||||
break nextFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//check current file matched items type
|
|
||||||
for (DataStorageMemoryItem item : items) {
|
|
||||||
Directory[] directories = item.getDirectories();
|
|
||||||
if (directories == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Directory dir : directories) {
|
|
||||||
if (rootDir.getAbsolutePath().equals(dir.getAbsolutePath())
|
|
||||||
|| (rootDir.getAbsolutePath().startsWith(dir.getAbsolutePath()) && dir.isGoDeeper())) {
|
|
||||||
int checkingType = dir.getCheckingType();
|
|
||||||
switch (checkingType) {
|
|
||||||
case EXTENSIONS : {
|
|
||||||
String[] extensions = item.getExtensions();
|
|
||||||
if (extensions != null) {
|
|
||||||
for (String extension : extensions) {
|
|
||||||
if (file.getAbsolutePath().endsWith(extension)) {
|
|
||||||
item.addBytes(file.length());
|
|
||||||
break nextFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
item.addBytes(file.length());
|
|
||||||
break nextFile;
|
|
||||||
}
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
case PREFIX : {
|
|
||||||
String[] prefixes = item.getPrefixes();
|
|
||||||
if (prefixes != null) {
|
|
||||||
for (String prefix : prefixes) {
|
|
||||||
if (file.getName().toLowerCase().startsWith(prefix.toLowerCase())) {
|
|
||||||
item.addBytes(file.length());
|
|
||||||
break nextFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
item.addBytes(file.length());
|
|
||||||
break nextFile;
|
|
||||||
}
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dir.isSkipOther()) {
|
|
||||||
break nextFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//current file did not match any type
|
|
||||||
otherMemory.addBytes(file.length());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
refreshUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getDirectorySize(File dir) {
|
|
||||||
long bytes = 0;
|
|
||||||
if (dir.isDirectory()) {
|
|
||||||
File[] files = dir.listFiles();
|
|
||||||
for (File file : files) {
|
|
||||||
if (isCancelled()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (file.isDirectory()) {
|
|
||||||
bytes += getDirectorySize(file);
|
|
||||||
} else if (file.isFile()) {
|
|
||||||
bytes += file.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onProgressUpdate(Void... values) {
|
|
||||||
super.onProgressUpdate(values);
|
|
||||||
if (listener != null) {
|
|
||||||
listener.onMemoryInfoUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Void aVoid) {
|
|
||||||
super.onPostExecute(aVoid);
|
|
||||||
if (listener != null) {
|
|
||||||
listener.onFinishUpdating(taskKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshUI() {
|
|
||||||
long currentTime = System.currentTimeMillis();
|
|
||||||
if ((currentTime - lastRefreshTime) > UI_REFRESH_TIME_MS) {
|
|
||||||
lastRefreshTime = currentTime;
|
|
||||||
publishProgress();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTotalUsedBytes() {
|
|
||||||
long total = 0;
|
|
||||||
if (memoryItems != null && memoryItems.size() > 0) {
|
|
||||||
for (DataStorageMemoryItem mi : memoryItems) {
|
|
||||||
total += mi.getUsedMemoryBytes();
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFormattedMemoryInfo(long bytes, String[] formatStrings) {
|
|
||||||
int type = 0;
|
|
||||||
double memory = (double) bytes / 1024;
|
|
||||||
while (memory > 1024 && type < formatStrings.length) {
|
|
||||||
++type;
|
|
||||||
memory = memory / 1024;
|
|
||||||
}
|
|
||||||
String formattedUsed = new DecimalFormat("#.##").format(memory);
|
|
||||||
return String.format(formatStrings[type], formattedUsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface UpdateMemoryInfoUIAdapter {
|
|
||||||
|
|
||||||
void onMemoryInfoUpdate();
|
|
||||||
|
|
||||||
void onFinishUpdating(String taskKey);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,6 +22,8 @@ import net.osmand.plus.profiles.SelectProfileBottomSheet.DialogMode;
|
||||||
import net.osmand.plus.profiles.SelectProfileBottomSheet.OnSelectProfileCallback;
|
import net.osmand.plus.profiles.SelectProfileBottomSheet.OnSelectProfileCallback;
|
||||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
|
import net.osmand.plus.settings.datastorage.DataStorageHelper;
|
||||||
|
import net.osmand.plus.settings.datastorage.item.StorageItem;
|
||||||
import net.osmand.plus.settings.preferences.ListPreferenceEx;
|
import net.osmand.plus.settings.preferences.ListPreferenceEx;
|
||||||
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;
|
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;
|
||||||
|
|
||||||
|
@ -181,7 +183,7 @@ public class GlobalSettingsFragment extends BaseSettingsFragment
|
||||||
externalStorageDir.setIcon(getActiveIcon(R.drawable.ic_action_folder));
|
externalStorageDir.setIcon(getActiveIcon(R.drawable.ic_action_folder));
|
||||||
|
|
||||||
DataStorageHelper holder = new DataStorageHelper(app);
|
DataStorageHelper holder = new DataStorageHelper(app);
|
||||||
DataStorageMenuItem currentStorage = holder.getCurrentStorage();
|
StorageItem currentStorage = holder.getCurrentStorage();
|
||||||
long totalUsed = app.getSettings().OSMAND_USAGE_SPACE.get();
|
long totalUsed = app.getSettings().OSMAND_USAGE_SPACE.get();
|
||||||
if (totalUsed > 0) {
|
if (totalUsed > 0) {
|
||||||
String[] usedMemoryFormats = new String[] {
|
String[] usedMemoryFormats = new String[] {
|
||||||
|
|
Loading…
Reference in a new issue