forked from organicmaps/organicmaps
[android] map storage refactoring
This commit is contained in:
parent
9d69f166d8
commit
0b64872239
10 changed files with 819 additions and 662 deletions
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "../core/jni_helper.hpp"
|
||||
#include "../core/render_context.hpp"
|
||||
#include "../platform/Platform.hpp"
|
||||
|
||||
#include "../../../../../map/framework.hpp"
|
||||
#include "../../../../../map/measurement_utils.hpp"
|
||||
|
@ -39,10 +40,7 @@ android::Framework * g_framework = 0;
|
|||
|
||||
namespace android
|
||||
{
|
||||
void Framework::CallRepaint()
|
||||
{
|
||||
//LOG(LINFO, ("Calling Repaint"));
|
||||
}
|
||||
void Framework::CallRepaint() {}
|
||||
|
||||
Framework::Framework()
|
||||
: m_mask(0),
|
||||
|
@ -54,12 +52,6 @@ namespace android
|
|||
g_framework = this;
|
||||
|
||||
m_videoTimer = new VideoTimer(bind(&Framework::CallRepaint, this));
|
||||
|
||||
/*
|
||||
size_t const measurementsCount = 5;
|
||||
m_sensors[0].SetCount(measurementsCount);
|
||||
m_sensors[1].SetCount(measurementsCount);
|
||||
*/
|
||||
}
|
||||
|
||||
Framework::~Framework()
|
||||
|
@ -89,9 +81,7 @@ namespace android
|
|||
|
||||
void Framework::UpdateCompassSensor(int ind, float * arr)
|
||||
{
|
||||
//LOG ( LINFO, ("Sensors before, C++: ", arr[0], arr[1], arr[2]) );
|
||||
m_sensors[ind].Next(arr);
|
||||
//LOG ( LINFO, ("Sensors after, C++: ", arr[0], arr[1], arr[2]) );
|
||||
}
|
||||
|
||||
void Framework::DeleteRenderPolicy()
|
||||
|
@ -501,7 +491,7 @@ namespace android
|
|||
{
|
||||
ASSERT ( out.empty(), () );
|
||||
|
||||
Platform const & pl = GetPlatform();
|
||||
::Platform const & pl = GetPlatform();
|
||||
|
||||
vector<string> v;
|
||||
m_work.GetLocalMaps(v);
|
||||
|
@ -949,4 +939,57 @@ extern "C"
|
|||
g_framework->Invalidate();
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_maps_Framework_nativeGetBookmarkDir(JNIEnv * env, jclass thiz)
|
||||
{
|
||||
return jni::ToJavaString(env, GetPlatform().SettingsDir().c_str());
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_maps_Framework_nativeGetWritableDir(JNIEnv * env, jclass thiz)
|
||||
{
|
||||
return jni::ToJavaString(env, GetPlatform().WritableDir().c_str());
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_maps_Framework_nativeGetSettingsDir(JNIEnv * env, jclass thiz)
|
||||
{
|
||||
return jni::ToJavaString(env, GetPlatform().SettingsDir().c_str());
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_com_mapswithme_maps_Framework_nativeGetMovablefilesExt(JNIEnv * env, jclass thiz)
|
||||
{
|
||||
jstring fakeString = jni::ToJavaString(env, "");
|
||||
jclass stringClass = env->GetObjectClass(fakeString);
|
||||
|
||||
string exts[] = { DATA_FILE_EXTENSION, FONT_FILE_EXTENSION};
|
||||
jobjectArray resultArray = env->NewObjectArray(ARRAY_SIZE(exts), stringClass, NULL);
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(exts); ++i)
|
||||
env->SetObjectArrayElement(resultArray, i, jni::ToJavaString(env, exts[i]));
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_maps_Framework_nativeGetBookmarksExt(JNIEnv * env, jclass thiz)
|
||||
{
|
||||
return jni::ToJavaString(env, BOOKMARKS_FILE_EXTENSION);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_mapswithme_maps_Framework_nativeSetWritableDir(JNIEnv * env, jclass thiz, jstring _newPath)
|
||||
{
|
||||
string newPath = jni::ToNativeString(env, _newPath);
|
||||
g_framework->RemoveLocalMaps();
|
||||
android::Platform::Instance().SetStoragePath(newPath);
|
||||
g_framework->AddLocalMaps();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_mapswithme_maps_Framework_nativeLoadbookmarks(JNIEnv * env, jclass thiz)
|
||||
{
|
||||
g_framework->NativeFramework()->LoadBookmarks();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,158 +1,19 @@
|
|||
#include "../platform/Platform.hpp"
|
||||
#include "../core/jni_helper.hpp"
|
||||
#include "Framework.hpp"
|
||||
#include "../platform/Platform.hpp"
|
||||
|
||||
#include "../../../../../map/bookmark.hpp"
|
||||
#include "../../../../../base/stl_add.hpp"
|
||||
#include "../../../../../coding/file_name_utils.hpp"
|
||||
#include "../../../../../coding/internal/file_data.hpp"
|
||||
#include "../../../../../std/set.hpp"
|
||||
#include "../../../../../std/string.hpp"
|
||||
#include "../../../../../std/algorithm.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct PathInserter
|
||||
{
|
||||
public:
|
||||
PathInserter(string const & dirPath, set<string> & set)
|
||||
: m_dirPath(dirPath)
|
||||
, m_set(set)
|
||||
{
|
||||
if (m_dirPath[m_dirPath.size() - 1] != '/')
|
||||
m_dirPath = m_dirPath + "/";
|
||||
}
|
||||
|
||||
void operator() (string const & name)
|
||||
{
|
||||
m_set.insert(m_dirPath + name);
|
||||
}
|
||||
|
||||
private:
|
||||
string m_dirPath;
|
||||
set<string> & m_set;
|
||||
};
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_util_StoragePathManager_nativeGetBookmarkDir(JNIEnv * env, jclass thiz)
|
||||
Java_com_mapswithme_util_StoragePathManager_nativeGenerateUniqueBookmarkName(JNIEnv * env, jclass thiz, jstring _baseName)
|
||||
{
|
||||
return jni::ToJavaString(env, GetPlatform().SettingsDir().c_str());
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_util_StoragePathManager_nativeGetWritableDir(JNIEnv * env, jclass thiz)
|
||||
{
|
||||
return jni::ToJavaString(env, GetPlatform().WritableDir().c_str());
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_util_StoragePathManager_nativeGetSettingsDir(JNIEnv * env, jclass thiz)
|
||||
{
|
||||
return jni::ToJavaString(env, GetPlatform().SettingsDir().c_str());
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_mapswithme_util_StoragePathManager_nativeSetStoragePath(JNIEnv * env, jobject thiz,
|
||||
jstring s)
|
||||
{
|
||||
string const from = GetPlatform().WritableDir();
|
||||
string const to = jni::ToNativeString(env, s);
|
||||
|
||||
// Remove all maps from container.
|
||||
g_framework->RemoveLocalMaps();
|
||||
|
||||
// Get files to copy.
|
||||
Platform & pl = GetPlatform();
|
||||
|
||||
// Get regexp like this: (\.mwm$|\.ttf$)
|
||||
string const regexp = "(" "\\"DATA_FILE_EXTENSION"$" "|"
|
||||
"\\"FONT_FILE_EXTENSION"$" ")";
|
||||
Platform::FilesList files;
|
||||
pl.GetFilesByRegExp(from, regexp, files);
|
||||
|
||||
// Copy all needed files.
|
||||
for (size_t i = 0; i < files.size(); ++i)
|
||||
if (!my::CopyFileX(from + files[i], to + files[i]))
|
||||
{
|
||||
// Do the undo - delete all previously copied files.
|
||||
for (size_t j = 0; j <= i; ++j)
|
||||
{
|
||||
string const path = to + files[j];
|
||||
VERIFY ( my::DeleteFileX(path), (path) );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set new storage path.
|
||||
android::Platform::Instance().SetStoragePath(to);
|
||||
|
||||
// Add all maps again.
|
||||
g_framework->AddLocalMaps();
|
||||
|
||||
// Reload bookmarks again
|
||||
g_framework->NativeFramework()->LoadBookmarks();
|
||||
return true;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_mapswithme_util_StoragePathManager_nativeMoveBookmarks(JNIEnv * env, jclass thiz, jobjectArray pathArray, jlong storageAvSize)
|
||||
{
|
||||
set<string> fullBookmarkSet;
|
||||
Platform & pl = GetPlatform();
|
||||
string const settingsDir = pl.SettingsDir();
|
||||
string const writableDir = pl.WritableDir();
|
||||
if (writableDir != settingsDir)
|
||||
{
|
||||
Platform::FilesList list;
|
||||
pl.GetFilesByExt(writableDir, BOOKMARKS_FILE_EXTENSION, list);
|
||||
for_each(list.begin(), list.end(), PathInserter(writableDir, fullBookmarkSet));
|
||||
}
|
||||
|
||||
int const arraySize = env->GetArrayLength(pathArray);
|
||||
for (int i = 0; i < arraySize; ++i)
|
||||
{
|
||||
jstring jPath = (jstring)env->GetObjectArrayElement(pathArray, i);
|
||||
string path = jni::ToNativeString(env, jPath);
|
||||
|
||||
if (path != settingsDir)
|
||||
{
|
||||
Platform::FilesList list;
|
||||
pl.GetFilesByExt(path, BOOKMARKS_FILE_EXTENSION, list);
|
||||
for_each(list.begin(), list.end(), PathInserter(path, fullBookmarkSet));
|
||||
}
|
||||
}
|
||||
|
||||
typedef set<string>::const_iterator fileIt;
|
||||
|
||||
uint64_t fullSize = 0;
|
||||
for (fileIt it = fullBookmarkSet.begin(); it != fullBookmarkSet.end(); ++it)
|
||||
{
|
||||
uint64_t size = 0;
|
||||
my::GetFileSize(*it, size);
|
||||
fullSize += size;
|
||||
}
|
||||
|
||||
if (storageAvSize < fullSize)
|
||||
return false;
|
||||
|
||||
for (fileIt it = fullBookmarkSet.begin(); it != fullBookmarkSet.end(); ++it)
|
||||
{
|
||||
string const oldFilePath = *it;
|
||||
string fileName = oldFilePath;
|
||||
my::GetNameFromFullPath(fileName);
|
||||
my::GetNameWithoutExt(fileName);
|
||||
string const newFilePath = BookmarkCategory::GenerateUniqueFileName(settingsDir, fileName);
|
||||
|
||||
if (my::CopyFileX(oldFilePath, newFilePath))
|
||||
my::DeleteFileX(oldFilePath);
|
||||
}
|
||||
|
||||
g_framework->NativeFramework()->LoadBookmarks();
|
||||
return true;
|
||||
string baseName = jni::ToNativeString(env, _baseName);
|
||||
string bookmarkFileName = BookmarkCategory::GenerateUniqueFileName(GetPlatform().SettingsDir(), baseName);
|
||||
return jni::ToJavaString(env, bookmarkFileName);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
#include "../Framework.hpp"
|
||||
|
||||
#include "../../core/jni_helper.hpp"
|
||||
|
||||
#include "../../platform/Platform.hpp"
|
||||
|
||||
#include "../../../../../../coding/internal/file_data.hpp"
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_maps_settings_StoragePathActivity_nativeGetStoragePath(JNIEnv * env, jobject thiz)
|
||||
{
|
||||
return jni::ToJavaString(env, android::Platform::Instance().GetStoragePathPrefix());
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_mapswithme_maps_settings_SettingsActivity_isDownloadingActive(JNIEnv * env, jobject thiz)
|
||||
{
|
||||
|
|
|
@ -4,31 +4,37 @@
|
|||
<Preference
|
||||
android:key="@string/pref_storage_activity"
|
||||
android:summary="@string/maps_storage_summary"
|
||||
android:title="@string/maps_storage" />
|
||||
android:title="@string/maps_storage"
|
||||
android:order="0"/>
|
||||
|
||||
<ListPreference
|
||||
android:entries="@array/measument_units"
|
||||
android:entryValues="@array/measument_units_values"
|
||||
android:key="@string/pref_munits"
|
||||
android:summary="@string/measurement_units_summary"
|
||||
android:title="@string/measurement_units" />
|
||||
android:title="@string/measurement_units"
|
||||
android:order="1"/>
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="@string/pref_allow_stat"
|
||||
android:summary="@string/allow_statistics_hint"
|
||||
android:title="@string/allow_statistics" />
|
||||
android:title="@string/allow_statistics"
|
||||
android:order="2"/>
|
||||
<CheckBoxPreference
|
||||
android:key="@string/pref_zoom_btns_enabled"
|
||||
android:summary="@string/pref_zoom_summary"
|
||||
android:title="@string/pref_zoom_title" />
|
||||
android:title="@string/pref_zoom_title"
|
||||
android:order="3"/>
|
||||
|
||||
<Preference
|
||||
android:key="@string/pref_yota"
|
||||
android:summary="@string/yopme_pref_summary"
|
||||
android:title="@string/yopme_pref_title" />
|
||||
android:title="@string/yopme_pref_title"
|
||||
android:order="98"/>
|
||||
|
||||
<Preference
|
||||
android:key="@string/pref_about"
|
||||
android:title="@string/about_menu_title" />
|
||||
android:title="@string/about_menu_title"
|
||||
android:order="99"/>
|
||||
|
||||
</PreferenceScreen>
|
|
@ -22,6 +22,41 @@ public class Framework
|
|||
public void onAdditionalLayerActivated(long index);
|
||||
public void onDismiss();
|
||||
}
|
||||
|
||||
static public String GetSettingsDir()
|
||||
{
|
||||
return nativeGetSettingsDir();
|
||||
}
|
||||
|
||||
static public String GetBookmarksDir()
|
||||
{
|
||||
return nativeGetBookmarkDir();
|
||||
}
|
||||
|
||||
static public String GetWritableDir()
|
||||
{
|
||||
return nativeGetWritableDir();
|
||||
}
|
||||
|
||||
static public String GetBookmarkFileExt()
|
||||
{
|
||||
return nativeGetBookmarksExt();
|
||||
}
|
||||
|
||||
static public String[] GetMovableFilesExt()
|
||||
{
|
||||
return nativeGetMovablefilesExt();
|
||||
}
|
||||
|
||||
static public void SetWritableDir(String newPath)
|
||||
{
|
||||
nativeSetWritableDir(newPath);
|
||||
}
|
||||
|
||||
static public void ReloadBookmarks()
|
||||
{
|
||||
nativeLoadbookmarks();
|
||||
}
|
||||
|
||||
// Interface
|
||||
|
||||
|
@ -135,4 +170,12 @@ public class Framework
|
|||
public native static void cleanSearchLayerOnMap();
|
||||
public native static void invalidate();
|
||||
public native static String getPoiTypeNameForLatLon(double lat, double lon);
|
||||
|
||||
private native static String[] nativeGetMovablefilesExt();
|
||||
private native static String nativeGetBookmarksExt();
|
||||
private native static String nativeGetBookmarkDir();
|
||||
private native static String nativeGetSettingsDir();
|
||||
private native static String nativeGetWritableDir();
|
||||
private native static void nativeSetWritableDir(String newPath);
|
||||
private native static void nativeLoadbookmarks();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import android.content.Context;
|
|||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnKeyListener;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Configuration;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
|
@ -118,6 +117,11 @@ public class MWMActivity extends NvEventQueueActivity
|
|||
{
|
||||
return mApplication.getLocationState();
|
||||
}
|
||||
|
||||
private StoragePathManager GetPathManager()
|
||||
{
|
||||
return mApplication.GetPathManager();
|
||||
}
|
||||
|
||||
private void startLocation()
|
||||
{
|
||||
|
@ -337,11 +341,12 @@ public class MWMActivity extends NvEventQueueActivity
|
|||
final String KitKatMigrationCompleted = "KitKatMigrationCompleted";
|
||||
final boolean kmlMoved = MWMApplication.get().nativeGetBoolean(KmlMovedFlag, false);
|
||||
final boolean mapsCpy = MWMApplication.get().nativeGetBoolean(KitKatMigrationCompleted, false);
|
||||
StoragePathManager pathManager = mApplication.GetPathManager();
|
||||
|
||||
if (!kmlMoved)
|
||||
{
|
||||
if (StoragePathManager.MoveBookmarks())
|
||||
MWMApplication.get().nativeSetBoolean(KmlMovedFlag, true);
|
||||
if (pathManager.MoveBookmarks())
|
||||
mApplication.nativeSetBoolean(KmlMovedFlag, true);
|
||||
else
|
||||
{
|
||||
ShowAlertDlg(R.string.bookmark_move_fail);
|
||||
|
@ -356,12 +361,17 @@ public class MWMActivity extends NvEventQueueActivity
|
|||
@Override
|
||||
public void MoveFilesFinished(String newPath)
|
||||
{
|
||||
MWMApplication.get().nativeSetBoolean(KitKatMigrationCompleted, true);
|
||||
mApplication.nativeSetBoolean(KitKatMigrationCompleted, true);
|
||||
ShowAlertDlg(R.string.kitkat_migrate_ok);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void MoveFilesFailed()
|
||||
{
|
||||
ShowAlertDlg(R.string.kitkat_migrate_failed);
|
||||
}
|
||||
};
|
||||
if (StoragePathManager.CheckWritableDir(this, listener) == false)
|
||||
ShowAlertDlg(R.string.kitkat_migrate_failed);
|
||||
pathManager.CheckWritableDir(this, listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1129,19 +1139,7 @@ public class MWMActivity extends NvEventQueueActivity
|
|||
}
|
||||
};
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
|
||||
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
|
||||
filter.addAction(Intent.ACTION_MEDIA_EJECT);
|
||||
filter.addAction(Intent.ACTION_MEDIA_SHARED);
|
||||
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
|
||||
filter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
|
||||
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTABLE);
|
||||
filter.addAction(Intent.ACTION_MEDIA_CHECKING);
|
||||
filter.addAction(Intent.ACTION_MEDIA_NOFS);
|
||||
filter.addDataScheme("file");
|
||||
registerReceiver(m_externalStorageReceiver, filter);
|
||||
|
||||
GetPathManager().StartExtStorageWatching(this, m_externalStorageReceiver);
|
||||
updateExternalStorageState();
|
||||
}
|
||||
|
||||
|
@ -1211,11 +1209,8 @@ public class MWMActivity extends NvEventQueueActivity
|
|||
|
||||
private void stopWatchingExternalStorage()
|
||||
{
|
||||
if (m_externalStorageReceiver != null)
|
||||
{
|
||||
unregisterReceiver(m_externalStorageReceiver);
|
||||
m_externalStorageReceiver = null;
|
||||
}
|
||||
GetPathManager().StopExtStorageWatching();
|
||||
m_externalStorageReceiver = null;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.mapswithme.maps.guides.GuideInfo;
|
|||
import com.mapswithme.maps.guides.GuidesUtils;
|
||||
import com.mapswithme.maps.location.LocationService;
|
||||
import com.mapswithme.util.FbUtil;
|
||||
import com.mapswithme.util.StoragePathManager;
|
||||
import com.mapswithme.util.Utils;
|
||||
import com.mapswithme.util.log.Logger;
|
||||
import com.mapswithme.util.log.SimpleLogger;
|
||||
|
@ -34,7 +35,7 @@ public class MWMApplication extends android.app.Application implements MapStorag
|
|||
|
||||
private static MWMApplication mSelf;
|
||||
|
||||
|
||||
private StoragePathManager m_pathManager = new StoragePathManager();
|
||||
private LocationService m_location = null;
|
||||
private LocationState m_locationState = null;
|
||||
private MapStorage m_storage = null;
|
||||
|
@ -101,6 +102,11 @@ public class MWMApplication extends android.app.Application implements MapStorag
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public StoragePathManager GetPathManager()
|
||||
{
|
||||
return m_pathManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCountryProgress(Index idx, long current, long total)
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
|
|||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
|
@ -16,6 +17,7 @@ import android.preference.Preference;
|
|||
import android.preference.Preference.OnPreferenceChangeListener;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
@ -34,8 +36,8 @@ import com.mapswithme.util.statistics.Statistics;
|
|||
public class SettingsActivity extends PreferenceActivity
|
||||
{
|
||||
private final static String ZOOM_BUTTON_ENABLED = "ZoomButtonsEnabled";
|
||||
|
||||
private native boolean isDownloadingActive();
|
||||
private BroadcastReceiver m_receiver = null;
|
||||
private Preference m_storagePreference = null;
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -44,7 +46,6 @@ public class SettingsActivity extends PreferenceActivity
|
|||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
|
||||
if (Utils.apiEqualOrGreaterThan(11))
|
||||
{
|
||||
// http://stackoverflow.com/questions/6867076/getactionbar-returns-null
|
||||
|
@ -137,8 +138,23 @@ public class SettingsActivity extends PreferenceActivity
|
|||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
m_storagePreference = findPreference(getString(R.string.pref_storage_activity));
|
||||
|
||||
yotaSetup();
|
||||
storagePathSetup();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void storagePathSetup()
|
||||
{
|
||||
PreferenceScreen screen = getPreferenceScreen();
|
||||
if (Yota.isYota())
|
||||
screen.removePreference(m_storagePreference);
|
||||
else if (MWMApplication.get().GetPathManager().HasMoreThanOnceStorage())
|
||||
screen.addPreference(m_storagePreference);
|
||||
else
|
||||
screen.removePreference(m_storagePreference);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -158,9 +174,6 @@ public class SettingsActivity extends PreferenceActivity
|
|||
return true;
|
||||
}
|
||||
});
|
||||
// we dont allow to change maps location
|
||||
getPreferenceScreen()
|
||||
.removePreference(findPreference(getString(R.string.pref_storage_activity)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,6 +192,29 @@ public class SettingsActivity extends PreferenceActivity
|
|||
|
||||
Statistics.INSTANCE.stopActivity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
m_receiver = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
storagePathSetup();
|
||||
}
|
||||
};
|
||||
MWMApplication.get().GetPathManager().StartExtStorageWatching(this, m_receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
MWMApplication.get().GetPathManager().StopExtStorageWatching();
|
||||
m_receiver = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
|
@ -287,4 +323,6 @@ public class SettingsActivity extends PreferenceActivity
|
|||
|
||||
myWebView.loadUrl(url);
|
||||
}
|
||||
|
||||
private native boolean isDownloadingActive();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.widget.CheckedTextView;
|
|||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mapswithme.maps.MWMApplication;
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.base.MapsWithMeBaseListActivity;
|
||||
import com.mapswithme.util.StoragePathManager;
|
||||
|
@ -31,240 +32,9 @@ public class StoragePathActivity extends MapsWithMeBaseListActivity
|
|||
{
|
||||
private static String TAG = "StoragePathActivity";
|
||||
|
||||
/// ListView adapter
|
||||
private static class StoragePathAdapter extends BaseAdapter
|
||||
private StoragePathManager.StoragePathAdapter getAdapter()
|
||||
{
|
||||
private static String TAG = "StoragePathAdapter";
|
||||
|
||||
/// @name Different row types.
|
||||
//@{
|
||||
private static final int TYPE_HEADER = 0;
|
||||
private static final int TYPE_ITEM = 1;
|
||||
private static final int TYPES_COUNT = 2;
|
||||
//@}
|
||||
|
||||
private final LayoutInflater m_inflater;
|
||||
private final Activity m_context;
|
||||
|
||||
private String m_currPath;
|
||||
private final String m_defPath;
|
||||
private long m_sizeNeeded;
|
||||
|
||||
private final int m_listItemHeight;
|
||||
|
||||
public StoragePathAdapter(Activity context, String currPath, String defPath)
|
||||
{
|
||||
m_context = context;
|
||||
m_inflater = m_context.getLayoutInflater();
|
||||
|
||||
m_currPath = currPath;
|
||||
m_defPath = defPath;
|
||||
|
||||
m_listItemHeight = (int)Utils.getAttributeDimension(context, android.R.attr.listPreferredItemHeight);
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
private String getSizeString(long size)
|
||||
{
|
||||
final String arrS[] = { "Kb", "Mb", "Gb" };
|
||||
|
||||
long current = 1024;
|
||||
int i = 0;
|
||||
for (; i < arrS.length; ++i)
|
||||
{
|
||||
final long bound = 1024 * current;
|
||||
if (size < bound)
|
||||
break;
|
||||
else
|
||||
current = bound;
|
||||
}
|
||||
|
||||
// left 1 digit after the comma and add postfix string
|
||||
return String.format("%.1f %s", (double)size / (double)current, arrS[i]);
|
||||
}
|
||||
|
||||
private List<StoragePathManager.StorageItem> m_items = new ArrayList<StoragePathManager.StorageItem>();
|
||||
private int m_current = -1;
|
||||
|
||||
private boolean isAvailable(int index)
|
||||
{
|
||||
assert(index >= 0 && index < m_items.size());
|
||||
return ((m_current != index) && (m_items.get(index).m_size >= m_sizeNeeded));
|
||||
}
|
||||
|
||||
private int findItemByPath(String path)
|
||||
{
|
||||
for (int i = 0; i < m_items.size(); ++i)
|
||||
if (m_items.get(i).m_path.equals(path))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void updateList()
|
||||
{
|
||||
m_sizeNeeded = StoragePathManager.getDirSize(m_currPath);
|
||||
m_items = StoragePathManager.GetStorages(m_context, m_currPath, m_defPath);
|
||||
|
||||
// Find index of the current path.
|
||||
m_current = findItemByPath(m_currPath);
|
||||
assert(m_current != -1);
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private static int HEADERS_COUNT = 1;
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position)
|
||||
{
|
||||
return (position == 0 ? TYPE_HEADER : TYPE_ITEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount()
|
||||
{
|
||||
return TYPES_COUNT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount()
|
||||
{
|
||||
return (m_items != null ? m_items.size() + HEADERS_COUNT : HEADERS_COUNT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoragePathManager.StorageItem getItem(int position)
|
||||
{
|
||||
return (position == 0 ? null : m_items.get(getIndexFromPos(position)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position)
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
// 1. It's a strange thing, but when I tried to use setClickable,
|
||||
// all the views become nonclickable.
|
||||
// 2. I call setMinimumHeight(listPreferredItemHeight)
|
||||
// because standard item's height is unknown.
|
||||
|
||||
switch (getItemViewType(position))
|
||||
{
|
||||
case TYPE_HEADER:
|
||||
{
|
||||
if (convertView == null)
|
||||
{
|
||||
convertView = m_inflater.inflate(android.R.layout.simple_list_item_1, null);
|
||||
convertView.setMinimumHeight(m_listItemHeight);
|
||||
}
|
||||
|
||||
final TextView v = (TextView) convertView;
|
||||
v.setText(m_context.getString(R.string.maps) + ": " + getSizeString(m_sizeNeeded));
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_ITEM:
|
||||
{
|
||||
final int index = getIndexFromPos(position);
|
||||
final StoragePathManager.StorageItem item = m_items.get(index);
|
||||
|
||||
if (convertView == null)
|
||||
{
|
||||
convertView = m_inflater.inflate(android.R.layout.simple_list_item_single_choice, null);
|
||||
convertView.setMinimumHeight(m_listItemHeight);
|
||||
}
|
||||
|
||||
final CheckedTextView v = (CheckedTextView) convertView;
|
||||
v.setText(item.m_path + ": " + getSizeString(item.m_size));
|
||||
v.setChecked(index == m_current);
|
||||
v.setEnabled((index == m_current) || isAvailable(index));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
private int getIndexFromPos(int position)
|
||||
{
|
||||
final int index = position - HEADERS_COUNT;
|
||||
assert(index >= 0 && index < m_items.size());
|
||||
return index;
|
||||
}
|
||||
|
||||
private String getFullPath(int index)
|
||||
{
|
||||
assert(index >= 0 && index < m_items.size());
|
||||
return StoragePathManager.getFullPath(m_items.get(index));
|
||||
}
|
||||
|
||||
private void doUpdateAfterMove(String path)
|
||||
{
|
||||
m_currPath = path;
|
||||
|
||||
updateList();
|
||||
}
|
||||
|
||||
public void onListItemClick(final int position)
|
||||
{
|
||||
final int index = getIndexFromPos(position);
|
||||
if (isAvailable(index))
|
||||
{
|
||||
final String path = getFullPath(index);
|
||||
|
||||
final File f = new File(path);
|
||||
if (!f.exists() && !f.mkdirs())
|
||||
{
|
||||
Log.e(TAG, "Can't create directory: " + path);
|
||||
return;
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(m_context)
|
||||
.setCancelable(false)
|
||||
.setTitle(R.string.move_maps)
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(DialogInterface dlg, int which)
|
||||
{
|
||||
Log.i(TAG, "Transfer data to storage: " + path);
|
||||
|
||||
StoragePathManager.StorageItem oldItem = null;
|
||||
if (m_current != -1)
|
||||
oldItem = m_items.get(m_current);
|
||||
StoragePathManager.SetStoragePath(m_context, new StoragePathManager.SetStoragePathListener()
|
||||
{
|
||||
@Override
|
||||
public void MoveFilesFinished(String newPath)
|
||||
{
|
||||
doUpdateAfterMove(newPath);
|
||||
}
|
||||
}, m_items.get(index), oldItem);
|
||||
|
||||
dlg.dismiss();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(DialogInterface dlg, int which)
|
||||
{
|
||||
dlg.dismiss();
|
||||
}
|
||||
})
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private StoragePathAdapter getAdapter()
|
||||
{
|
||||
return (StoragePathAdapter) getListView().getAdapter();
|
||||
return (StoragePathManager.StoragePathAdapter)getListView().getAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -272,18 +42,7 @@ public class StoragePathActivity extends MapsWithMeBaseListActivity
|
|||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final String currPath = nativeGetStoragePath();
|
||||
final String defPath = Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||
Log.i(TAG, "Current and Default maps pathes: " + currPath + "; " + defPath);
|
||||
|
||||
setListAdapter(new StoragePathAdapter(this, currPath, defPath));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
getAdapter().updateList();
|
||||
setListAdapter(MWMApplication.get().GetPathManager().GetAdapter());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -291,8 +50,20 @@ public class StoragePathActivity extends MapsWithMeBaseListActivity
|
|||
{
|
||||
// Do not process clicks on header items.
|
||||
if (position != 0)
|
||||
getAdapter().onListItemClick(position);
|
||||
getAdapter().onItemClick(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
MWMApplication.get().GetPathManager().StartExtStorageWatching(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
MWMApplication.get().GetPathManager().StopExtStorageWatching();
|
||||
}
|
||||
|
||||
private native String nativeGetStoragePath();
|
||||
}
|
||||
|
|
|
@ -2,41 +2,62 @@ package com.mapswithme.util;
|
|||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.mapswithme.maps.Framework;
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.settings.StoragePathActivity;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Environment;
|
||||
import android.os.StatFs;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.CheckedTextView;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class StoragePathManager
|
||||
{
|
||||
private static String TAG = "StoragePathManager";
|
||||
private static String MWM_DIR_POSTFIX = "/MapsWithMe/";
|
||||
|
||||
public static class StorageItem
|
||||
{
|
||||
public String m_path;
|
||||
public long m_size;
|
||||
public final String m_path;
|
||||
public final long m_size;
|
||||
|
||||
StorageItem(String path, long size)
|
||||
{
|
||||
m_path = path;
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o == this) return true;
|
||||
if (o == null) return false;
|
||||
return m_size == ((StorageItem)o).m_size;
|
||||
StorageItem other = (StorageItem)o;
|
||||
return m_size == other.m_size || m_path.equals(other.m_size);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,21 +67,271 @@ public class StoragePathManager
|
|||
}
|
||||
}
|
||||
|
||||
static public ArrayList<StorageItem> GetStorages(Context context, String currentPath, String defPath)
|
||||
public interface OnStorageItemClickListener
|
||||
{
|
||||
void onItemClick(int position);
|
||||
}
|
||||
|
||||
public interface SetStoragePathListener
|
||||
{
|
||||
void MoveFilesFinished(String newPath);
|
||||
void MoveFilesFailed();
|
||||
}
|
||||
|
||||
public static class StoragePathAdapter extends BaseAdapter
|
||||
implements OnStorageItemClickListener
|
||||
{
|
||||
@Override
|
||||
public int getCount(){ return 0; }
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) { return null; }
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) { return 0; }
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) { return null; }
|
||||
|
||||
@Override
|
||||
public void onItemClick(int position) {}
|
||||
};
|
||||
|
||||
/// ListView adapter
|
||||
private class StoragePathAdapterImpl extends StoragePathAdapter
|
||||
{
|
||||
private static final String TAG = "StoragePathAdapter";
|
||||
|
||||
/// @name Different row types.
|
||||
//@{
|
||||
private static final int TYPE_HEADER = 0;
|
||||
private static final int TYPE_ITEM = 1;
|
||||
private static final int HEADERS_COUNT = 1;
|
||||
private static final int TYPES_COUNT = 2;
|
||||
//@}
|
||||
|
||||
private final LayoutInflater m_inflater;
|
||||
private final Activity m_context;
|
||||
private final int m_listItemHeight;
|
||||
|
||||
private List<StorageItem> m_items = null;
|
||||
private int m_current = -1;
|
||||
private long m_sizeNeeded;
|
||||
|
||||
public StoragePathAdapterImpl(Activity context)
|
||||
{
|
||||
m_context = context;
|
||||
m_inflater = m_context.getLayoutInflater();
|
||||
|
||||
m_listItemHeight = (int)Utils.getAttributeDimension(context, android.R.attr.listPreferredItemHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position)
|
||||
{
|
||||
return (position == 0 ? TYPE_HEADER : TYPE_ITEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount()
|
||||
{
|
||||
return TYPES_COUNT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount()
|
||||
{
|
||||
return (m_items != null ? m_items.size() + HEADERS_COUNT : HEADERS_COUNT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageItem getItem(int position)
|
||||
{
|
||||
return (position == 0 ? null : m_items.get(getIndexFromPos(position)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position)
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
// 1. It's a strange thing, but when I tried to use setClickable,
|
||||
// all the views become nonclickable.
|
||||
// 2. I call setMinimumHeight(listPreferredItemHeight)
|
||||
// because standard item's height is unknown.
|
||||
|
||||
switch (getItemViewType(position))
|
||||
{
|
||||
case TYPE_HEADER:
|
||||
{
|
||||
if (convertView == null)
|
||||
{
|
||||
convertView = m_inflater.inflate(android.R.layout.simple_list_item_1, null);
|
||||
convertView.setMinimumHeight(m_listItemHeight);
|
||||
}
|
||||
|
||||
final TextView v = (TextView) convertView;
|
||||
v.setText(m_context.getString(R.string.maps) + ": " + getSizeString(m_sizeNeeded));
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_ITEM:
|
||||
{
|
||||
final int index = getIndexFromPos(position);
|
||||
final StorageItem item = m_items.get(index);
|
||||
|
||||
if (convertView == null)
|
||||
{
|
||||
convertView = m_inflater.inflate(android.R.layout.simple_list_item_single_choice, null);
|
||||
convertView.setMinimumHeight(m_listItemHeight);
|
||||
}
|
||||
|
||||
final CheckedTextView v = (CheckedTextView) convertView;
|
||||
v.setText(item.m_path + ": " + getSizeString(item.m_size));
|
||||
v.setChecked(index == m_current);
|
||||
v.setEnabled((index == m_current) || isAvailable(index));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(int position)
|
||||
{
|
||||
final int index = getIndexFromPos(position);
|
||||
if (isAvailable(index))
|
||||
onStorageItemClick(index);
|
||||
}
|
||||
|
||||
public void updateList(ArrayList<StorageItem> items, int currentItemIndex, long dirSize)
|
||||
{
|
||||
m_sizeNeeded = dirSize;
|
||||
m_items = items;
|
||||
m_current = currentItemIndex;
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
private String getSizeString(long size)
|
||||
{
|
||||
final String arrS[] = { "Kb", "Mb", "Gb" };
|
||||
|
||||
long current = 1024;
|
||||
int i = 0;
|
||||
for (; i < arrS.length; ++i)
|
||||
{
|
||||
final long bound = 1024 * current;
|
||||
if (size < bound)
|
||||
break;
|
||||
else
|
||||
current = bound;
|
||||
}
|
||||
|
||||
// left 1 digit after the comma and add postfix string
|
||||
return String.format("%.1f %s", (double)size / (double)current, arrS[i]);
|
||||
}
|
||||
|
||||
private boolean isAvailable(int index)
|
||||
{
|
||||
assert(index >= 0 && index < m_items.size());
|
||||
return ((m_current != index) && (m_items.get(index).m_size >= m_sizeNeeded));
|
||||
}
|
||||
|
||||
private int getIndexFromPos(int position)
|
||||
{
|
||||
final int index = position - HEADERS_COUNT;
|
||||
assert(index >= 0 && index < m_items.size());
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
private static String TAG = "StoragePathManager";
|
||||
private static String MWM_DIR_POSTFIX = "/MapsWithMe/";
|
||||
|
||||
private BroadcastReceiver m_externalListener;
|
||||
private BroadcastReceiver m_internalListener;
|
||||
private Activity m_context = null;
|
||||
private ArrayList<StorageItem> m_items = null;
|
||||
private StoragePathAdapterImpl m_adapter = null;
|
||||
private int m_currentItemIndex = -1;
|
||||
|
||||
public void StartExtStorageWatching(Activity context, BroadcastReceiver listener)
|
||||
{
|
||||
m_context = context;
|
||||
m_externalListener = listener;
|
||||
|
||||
m_internalListener = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
if (m_externalListener != null)
|
||||
m_externalListener.onReceive(context, intent);
|
||||
|
||||
UpdateExternalStorages();
|
||||
}
|
||||
};
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
|
||||
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
|
||||
filter.addAction(Intent.ACTION_MEDIA_EJECT);
|
||||
filter.addAction(Intent.ACTION_MEDIA_SHARED);
|
||||
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
|
||||
filter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
|
||||
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTABLE);
|
||||
filter.addAction(Intent.ACTION_MEDIA_CHECKING);
|
||||
filter.addAction(Intent.ACTION_MEDIA_NOFS);
|
||||
filter.addDataScheme("file");
|
||||
|
||||
m_context.registerReceiver(m_internalListener, filter);
|
||||
UpdateExternalStorages();
|
||||
}
|
||||
|
||||
public StoragePathAdapter GetAdapter()
|
||||
{
|
||||
if (m_adapter == null)
|
||||
{
|
||||
m_adapter = new StoragePathAdapterImpl(m_context);
|
||||
UpdateExternalStorages();
|
||||
}
|
||||
|
||||
return m_adapter;
|
||||
}
|
||||
|
||||
public void StopExtStorageWatching()
|
||||
{
|
||||
if (m_internalListener != null)
|
||||
{
|
||||
m_context.unregisterReceiver(m_internalListener);
|
||||
m_internalListener = null;
|
||||
m_externalListener = null;
|
||||
m_adapter = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean HasMoreThanOnceStorage()
|
||||
{
|
||||
return m_items.size() > 1;
|
||||
}
|
||||
|
||||
public void UpdateExternalStorages()
|
||||
{
|
||||
ArrayList<String> pathes = new ArrayList<String>();
|
||||
|
||||
parseMountFile("/etc/vold.conf", VOLD_MODE, pathes);
|
||||
parseMountFile("/etc/vold.fstab", VOLD_MODE, pathes);
|
||||
parseMountFile("/system/etc/vold.fstab", VOLD_MODE, pathes);
|
||||
parseMountFile("/proc/mounts", MOUNTS_MODE, pathes);
|
||||
|
||||
if (Utils.apiEqualOrGreaterThan(android.os.Build.VERSION_CODES.KITKAT))
|
||||
{
|
||||
File[] files = context.getExternalFilesDirs(null);
|
||||
File[] files = m_context.getExternalFilesDirs(null);
|
||||
if (files != null)
|
||||
{
|
||||
File primaryStorageDir = context.getExternalFilesDir(null);
|
||||
File primaryStorageDir = m_context.getExternalFilesDir(null);
|
||||
for(File f : files)
|
||||
{
|
||||
// On kitkat and Greater we ignore private folder on primary storage
|
||||
|
@ -72,31 +343,43 @@ public class StoragePathManager
|
|||
}
|
||||
}
|
||||
|
||||
pathes.add(currentPath);
|
||||
pathes.add(defPath);
|
||||
ParseMountFile("/etc/vold.conf", VOLD_MODE, pathes);
|
||||
ParseMountFile("/etc/vold.fstab", VOLD_MODE, pathes);
|
||||
ParseMountFile("/system/etc/vold.fstab", VOLD_MODE, pathes);
|
||||
ParseMountFile("/proc/mounts", MOUNTS_MODE, pathes);
|
||||
|
||||
ArrayList<StorageItem> items = new ArrayList<StorageItem>();
|
||||
for (String path : pathes)
|
||||
addStorage(path, items);
|
||||
AddStorage(path, items);
|
||||
|
||||
return new ArrayList<StorageItem>(new LinkedHashSet<StorageItem>(items));
|
||||
}
|
||||
|
||||
static public String getFullPath(StorageItem item)
|
||||
{
|
||||
return item.m_path + MWM_DIR_POSTFIX;
|
||||
AddStorage(Environment.getExternalStorageDirectory().getAbsolutePath(), items);
|
||||
|
||||
String writableDir = GetWritableDirRoot();
|
||||
|
||||
StorageItem currentItem = AddStorage(writableDir, items);
|
||||
LinkedHashSet<StorageItem> itemsSet = new LinkedHashSet<StorageItem>(items);
|
||||
if (currentItem != null)
|
||||
itemsSet.remove(currentItem);
|
||||
|
||||
m_items = new ArrayList<StorageItem>(itemsSet);
|
||||
if (currentItem != null)
|
||||
{
|
||||
m_items.add(0, currentItem);
|
||||
m_currentItemIndex = m_items.indexOf(currentItem);
|
||||
}
|
||||
else
|
||||
m_currentItemIndex = -1;
|
||||
if (m_adapter != null)
|
||||
m_adapter.updateList(m_items, m_currentItemIndex, GetMWMDirSize());
|
||||
}
|
||||
|
||||
/// @name Assume that MapsWithMe folder doesn't have inner folders and symbolic links.
|
||||
//@{
|
||||
static public long getDirSize(String basePath)
|
||||
public long GetMWMDirSize()
|
||||
{
|
||||
return getDirSizeImpl(basePath + MWM_DIR_POSTFIX);
|
||||
}
|
||||
|
||||
static private long getDirSizeImpl(String path)
|
||||
{
|
||||
final File dir = new File(path);
|
||||
String writableDir = Framework.GetWritableDir();
|
||||
|
||||
final File dir = new File(writableDir);
|
||||
assert(dir.exists());
|
||||
assert(dir.isDirectory());
|
||||
|
||||
|
@ -106,19 +389,20 @@ public class StoragePathManager
|
|||
assert(f.isFile());
|
||||
size += f.length();
|
||||
}
|
||||
|
||||
return (size + 1024*1024);
|
||||
|
||||
return size;
|
||||
}
|
||||
//@}
|
||||
|
||||
static public boolean MoveBookmarks()
|
||||
public boolean MoveBookmarks()
|
||||
{
|
||||
ArrayList<String> pathes = new ArrayList<String>();
|
||||
if (Utils.apiEqualOrGreaterThan(android.os.Build.VERSION_CODES.KITKAT))
|
||||
{
|
||||
parseMountFile("/etc/vold.conf", VOLD_MODE, pathes);
|
||||
parseMountFile("/etc/vold.fstab", VOLD_MODE, pathes);
|
||||
parseMountFile("/system/etc/vold.fstab", VOLD_MODE, pathes);
|
||||
parseMountFile("/proc/mounts", MOUNTS_MODE, pathes);
|
||||
ParseMountFile("/etc/vold.conf", VOLD_MODE, pathes);
|
||||
ParseMountFile("/etc/vold.fstab", VOLD_MODE, pathes);
|
||||
ParseMountFile("/system/etc/vold.fstab", VOLD_MODE, pathes);
|
||||
ParseMountFile("/proc/mounts", MOUNTS_MODE, pathes);
|
||||
}
|
||||
|
||||
ArrayList<String> approvedPathes = new ArrayList<String>();
|
||||
|
@ -129,69 +413,297 @@ public class StoragePathManager
|
|||
if (f.exists() || f.canRead() || f.isDirectory())
|
||||
approvedPathes.add(mwmPath);
|
||||
}
|
||||
String tmp[] = approvedPathes.toArray(new String[approvedPathes.size()]);
|
||||
return nativeMoveBookmarks(tmp, getFreeBytesAtPath(nativeGetBookmarkDir()));
|
||||
final String settingsDir = Framework.GetSettingsDir();
|
||||
final String writableDir = Framework.GetWritableDir();
|
||||
final String bookmarkDir = Framework.GetBookmarksDir();
|
||||
final String bookmarkFileExt = Framework.GetBookmarkFileExt();
|
||||
|
||||
LinkedHashSet<File> bookmarks = new LinkedHashSet<File>();
|
||||
if (!settingsDir.equals(writableDir))
|
||||
approvedPathes.add(writableDir);
|
||||
|
||||
for (String path : approvedPathes)
|
||||
{
|
||||
if (!path.equals(settingsDir))
|
||||
AccamulateFiles(path, bookmarkFileExt, bookmarks);
|
||||
}
|
||||
|
||||
long bookmarksSize = 0;
|
||||
for (File f : bookmarks)
|
||||
bookmarksSize += f.length();
|
||||
|
||||
if (GetFreeBytesAtPath(bookmarkDir) < bookmarksSize)
|
||||
return false;
|
||||
|
||||
for (File f : bookmarks)
|
||||
{
|
||||
String name = f.getName();
|
||||
name = name.replace(bookmarkFileExt, "");
|
||||
name = nativeGenerateUniqueBookmarkName(name);
|
||||
try
|
||||
{
|
||||
copyFile(f, new File(name));
|
||||
f.delete();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Framework.ReloadBookmarks();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static public boolean CheckWritableDir(Context context, SetStoragePathListener listener)
|
||||
private void AccamulateFiles(final String dirPath, final String filesExtension, Set<File> result)
|
||||
{
|
||||
File f = new File(dirPath);
|
||||
File[] bookmarks = f.listFiles(new FileFilter()
|
||||
{
|
||||
@Override
|
||||
public boolean accept(File pathname)
|
||||
{
|
||||
return pathname.getName().endsWith(filesExtension);
|
||||
}
|
||||
});
|
||||
|
||||
result.addAll(Arrays.asList(bookmarks));
|
||||
}
|
||||
|
||||
private void onStorageItemClick(int index)
|
||||
{
|
||||
final StorageItem oldItem = (m_currentItemIndex != -1) ? m_items.get(m_currentItemIndex) : null;
|
||||
final StorageItem item = m_items.get(index);
|
||||
final String path = GetItemFullPath(item);
|
||||
|
||||
final File f = new File(path);
|
||||
if (!f.exists() && !f.mkdirs())
|
||||
{
|
||||
Log.e(TAG, "Can't create directory: " + path);
|
||||
return;
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(m_context)
|
||||
.setCancelable(false)
|
||||
.setTitle(R.string.move_maps)
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(DialogInterface dlg, int which)
|
||||
{
|
||||
SetStoragePathImpl(m_context, new StoragePathManager.SetStoragePathListener()
|
||||
{
|
||||
@Override
|
||||
public void MoveFilesFinished(String newPath)
|
||||
{
|
||||
UpdateExternalStorages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void MoveFilesFailed()
|
||||
{
|
||||
UpdateExternalStorages();
|
||||
}
|
||||
}, item, oldItem, R.string.wait_several_minutes);
|
||||
|
||||
dlg.dismiss();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(DialogInterface dlg, int which)
|
||||
{
|
||||
dlg.dismiss();
|
||||
}
|
||||
})
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
|
||||
public void CheckWritableDir(Context context, SetStoragePathListener listener)
|
||||
{
|
||||
if (Utils.apiLowerThan(android.os.Build.VERSION_CODES.KITKAT))
|
||||
return true;
|
||||
return;
|
||||
|
||||
final String settingsDir = nativeGetSettingsDir();
|
||||
final String writableDir = nativeGetWritableDir();
|
||||
final String settingsDir = Framework.GetSettingsDir();
|
||||
final String writableDir = Framework.GetWritableDir();
|
||||
|
||||
if (settingsDir.equals(writableDir))
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (isDirWritable(writableDir))
|
||||
return true;
|
||||
if (IsDirWritable(writableDir))
|
||||
return;
|
||||
|
||||
final ArrayList<StorageItem> items = GetStorages(context, writableDir.replace(MWM_DIR_POSTFIX, ""),
|
||||
settingsDir.replace(MWM_DIR_POSTFIX, ""));
|
||||
final long size = getDirSizeImpl(writableDir);
|
||||
for (StorageItem item : items)
|
||||
final long size = GetMWMDirSize();
|
||||
for (StorageItem item : m_items)
|
||||
{
|
||||
if (item.m_size > size)
|
||||
{
|
||||
SetStoragePathImpl(context, listener, item, null, R.string.kitkat_optimization_in_progress);
|
||||
return true;
|
||||
SetStoragePathImpl(context, listener, item, new StorageItem(GetWritableDirRoot(), 0), R.string.kitkat_optimization_in_progress);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
listener.MoveFilesFailed();
|
||||
}
|
||||
|
||||
public interface SetStoragePathListener
|
||||
{
|
||||
void MoveFilesFinished(String newPath);
|
||||
}
|
||||
|
||||
static public void SetStoragePath(Context context, SetStoragePathListener listener, StorageItem newStorage, StorageItem oldStorage)
|
||||
{
|
||||
SetStoragePathImpl(context, listener, newStorage, oldStorage, R.string.wait_several_minutes);
|
||||
}
|
||||
|
||||
static private void SetStoragePathImpl(Context context, SetStoragePathListener listener,
|
||||
StorageItem newStorage, StorageItem oldStorage,
|
||||
int messageId)
|
||||
private void SetStoragePathImpl(Context context, SetStoragePathListener listener,
|
||||
StorageItem newStorage, StorageItem oldStorage, int messageId)
|
||||
{
|
||||
MoveFilesTask task = new MoveFilesTask(context, listener, newStorage, oldStorage, messageId);
|
||||
task.execute("");
|
||||
}
|
||||
|
||||
static private boolean isDirWritable(String path)
|
||||
static private boolean DoMoveMaps(StorageItem newStorage, StorageItem oldStorage)
|
||||
{
|
||||
final File f = new File(path + "/testDir");
|
||||
f.mkdir();
|
||||
// we can't only call canWrite, because on KitKat (Samsung S4) this return true
|
||||
// for sdcard but actually it's read only
|
||||
if (f.exists())
|
||||
String fullOldPath = GetItemFullPath(oldStorage);
|
||||
String fullNewPath = GetItemFullPath(newStorage);
|
||||
File oldDir = new File(fullOldPath);
|
||||
File newDir = new File(fullNewPath);
|
||||
if (!newDir.exists())
|
||||
newDir.mkdir();
|
||||
|
||||
assert(IsDirWritable(fullNewPath));
|
||||
assert(newDir.isDirectory());
|
||||
assert(oldDir.isDirectory());
|
||||
|
||||
final String[] extensions = Framework.GetMovableFilesExt();
|
||||
|
||||
File[] internalFiles = oldDir.listFiles(new FileFilter()
|
||||
{
|
||||
f.delete();
|
||||
return true;
|
||||
|
||||
@Override
|
||||
public boolean accept(File pathname)
|
||||
{
|
||||
for (String postfix : extensions)
|
||||
{
|
||||
if (pathname.getName().endsWith(postfix))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
for (File moveFile : internalFiles)
|
||||
copyFile(moveFile, new File(fullNewPath + moveFile.getName()));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
for (File moveFile : internalFiles)
|
||||
new File(fullNewPath + moveFile.getName()).delete();
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
Framework.SetWritableDir(fullNewPath);
|
||||
|
||||
for (File moveFile : internalFiles)
|
||||
moveFile.delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void copyFile(File source, File dest) throws IOException
|
||||
{
|
||||
FileChannel inputChannel = null;
|
||||
FileChannel outputChannel = null;
|
||||
try
|
||||
{
|
||||
inputChannel = new FileInputStream(source).getChannel();
|
||||
outputChannel = new FileOutputStream(dest).getChannel();
|
||||
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
|
||||
}
|
||||
finally
|
||||
{
|
||||
inputChannel.close();
|
||||
outputChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
private class MoveFilesTask extends AsyncTask<String, Void, Boolean>
|
||||
{
|
||||
private final ProgressDialog m_dlg;
|
||||
private final StorageItem m_newStorage;
|
||||
private final StorageItem m_oldStorage;
|
||||
private final SetStoragePathListener m_listener;
|
||||
|
||||
public MoveFilesTask(Context context, SetStoragePathListener listener,
|
||||
StorageItem newStorage, StorageItem oldStorage, int messageID)
|
||||
{
|
||||
m_newStorage = newStorage;
|
||||
m_oldStorage = oldStorage;
|
||||
m_listener = listener;
|
||||
|
||||
m_dlg = new ProgressDialog(context);
|
||||
m_dlg.setMessage(context.getString(messageID));
|
||||
m_dlg.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||
m_dlg.setIndeterminate(true);
|
||||
m_dlg.setCancelable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute()
|
||||
{
|
||||
m_dlg.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... params)
|
||||
{
|
||||
return DoMoveMaps(m_newStorage, m_oldStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result)
|
||||
{
|
||||
// Using dummy try-catch because of the following:
|
||||
// http://stackoverflow.com/questions/2745061/java-lang-illegalargumentexception-view-not-attached-to-window-manager
|
||||
try
|
||||
{
|
||||
m_dlg.dismiss();
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
if (result)
|
||||
m_listener.MoveFilesFinished(m_newStorage.m_path);
|
||||
else
|
||||
m_listener.MoveFilesFailed();
|
||||
|
||||
UpdateExternalStorages();
|
||||
}
|
||||
}
|
||||
|
||||
static private StorageItem AddStorage(String path, ArrayList<StorageItem> items)
|
||||
{
|
||||
try
|
||||
{
|
||||
final File f = new File(path + "/");
|
||||
if (f.exists() && f.isDirectory() && f.canWrite())
|
||||
{
|
||||
if (!IsDirWritable(path))
|
||||
return null;
|
||||
|
||||
final long size = GetFreeBytesAtPath(path);
|
||||
|
||||
final StorageItem item = new StorageItem(path, size);
|
||||
items.add(item);
|
||||
return item;
|
||||
}
|
||||
else
|
||||
Log.i(TAG, "File error for storage: " + path);
|
||||
}
|
||||
catch (final IllegalArgumentException ex)
|
||||
{
|
||||
// Suppress exceptions for unavailable storages.
|
||||
Log.i(TAG, "StatFs error for storage: " + path);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int VOLD_MODE = 1;
|
||||
|
@ -200,7 +712,7 @@ public class StoragePathManager
|
|||
// http://stackoverflow.com/questions/8151779/find-sd-card-volume-label-on-android
|
||||
// http://stackoverflow.com/questions/5694933/find-an-external-sd-card-location
|
||||
// http://stackoverflow.com/questions/14212969/file-canwrite-returns-false-on-some-devices-although-write-external-storage-pe
|
||||
static private void parseMountFile(String file, int mode, ArrayList<String> pathes)
|
||||
static private void ParseMountFile(String file, int mode, ArrayList<String> pathes)
|
||||
{
|
||||
Log.i(TAG, "Parsing " + file);
|
||||
|
||||
|
@ -257,46 +769,9 @@ public class StoragePathManager
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean addStorage(String path, ArrayList<StorageItem> items)
|
||||
{
|
||||
try
|
||||
{
|
||||
final File f = new File(path + "/");
|
||||
if (f.exists() && f.isDirectory() && f.canWrite())
|
||||
{
|
||||
if (!isDirWritable(path))
|
||||
return false;
|
||||
|
||||
for (StorageItem item : items)
|
||||
{
|
||||
if (item.m_path.equals(path))
|
||||
return true;
|
||||
}
|
||||
|
||||
final long size = getFreeBytesAtPath(path);
|
||||
|
||||
final StorageItem item = new StorageItem();
|
||||
item.m_path = path;
|
||||
item.m_size = size;
|
||||
|
||||
items.add(item);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
Log.i(TAG, "File error for storage: " + path);
|
||||
}
|
||||
catch (final IllegalArgumentException ex)
|
||||
{
|
||||
// Suppress exceptions for unavailable storages.
|
||||
Log.i(TAG, "StatFs error for storage: " + path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@SuppressLint("NewApi")
|
||||
static private long getFreeBytesAtPath(String path)
|
||||
static private long GetFreeBytesAtPath(String path)
|
||||
{
|
||||
final StatFs stat = new StatFs(path);
|
||||
final long size = Utils.apiLowerThan(android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
|
@ -305,105 +780,35 @@ public class StoragePathManager
|
|||
return size;
|
||||
}
|
||||
|
||||
static private boolean doMoveMaps(StorageItem newStorage, StorageItem oldStorage)
|
||||
static private boolean IsDirWritable(String path)
|
||||
{
|
||||
String fullNewPath = getFullPath(newStorage);
|
||||
File f = new File(fullNewPath);
|
||||
if (!f.exists())
|
||||
f.mkdir();
|
||||
|
||||
assert(f.canWrite());
|
||||
assert(f.isDirectory());
|
||||
|
||||
if (StoragePathManager.nativeSetStoragePath(fullNewPath))
|
||||
final File f = new File(path + "/testDir");
|
||||
f.mkdir();
|
||||
// we can't only call canWrite, because on KitKat (Samsung S4) this return true
|
||||
// for sdcard but actually it's read only
|
||||
if (f.exists())
|
||||
{
|
||||
if (oldStorage != null)
|
||||
deleteFiles(new File(getFullPath(oldStorage)));
|
||||
|
||||
f.delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//delete all files (except settings.ini) in directory and bookmarks
|
||||
static private void deleteFiles(File dir)
|
||||
static private String GetItemFullPath(StorageItem item)
|
||||
{
|
||||
assert(dir.exists());
|
||||
assert(dir.isDirectory());
|
||||
|
||||
for (final File file : dir.listFiles())
|
||||
{
|
||||
assert(file.isFile());
|
||||
|
||||
// skip settings.ini - this file should be always in one place
|
||||
if (file.getName().equalsIgnoreCase("settings.ini"))
|
||||
continue;
|
||||
|
||||
// skip bookmarks
|
||||
if (file.getName().endsWith("kml"))
|
||||
continue;
|
||||
|
||||
if (!file.delete())
|
||||
Log.w(TAG, "Can't delete file: " + file.getName());
|
||||
}
|
||||
}
|
||||
//@}
|
||||
|
||||
private static class MoveFilesTask extends AsyncTask<String, Void, Boolean>
|
||||
{
|
||||
private final ProgressDialog m_dlg;
|
||||
private final StorageItem m_newStorage;
|
||||
private final StorageItem m_oldStorage;
|
||||
private final SetStoragePathListener m_listener;
|
||||
|
||||
public MoveFilesTask(Context context, SetStoragePathListener listener,
|
||||
StorageItem newStorage, StorageItem oldStorage, int messageID)
|
||||
{
|
||||
m_newStorage = newStorage;
|
||||
m_oldStorage = oldStorage;
|
||||
m_listener = listener;
|
||||
|
||||
m_dlg = new ProgressDialog(context);
|
||||
m_dlg.setMessage(context.getString(messageID));
|
||||
m_dlg.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||
m_dlg.setIndeterminate(true);
|
||||
m_dlg.setCancelable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute()
|
||||
{
|
||||
m_dlg.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... params)
|
||||
{
|
||||
return doMoveMaps(m_newStorage, m_oldStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result)
|
||||
{
|
||||
// Using dummy try-catch because of the following:
|
||||
// http://stackoverflow.com/questions/2745061/java-lang-illegalargumentexception-view-not-attached-to-window-manager
|
||||
try
|
||||
{
|
||||
m_dlg.dismiss();
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
if (result)
|
||||
m_listener.MoveFilesFinished(m_newStorage.m_path);
|
||||
}
|
||||
return item.m_path + MWM_DIR_POSTFIX;
|
||||
}
|
||||
|
||||
static private native boolean nativeMoveBookmarks(String[] additionalFindPathes, long availableSize);
|
||||
static private native boolean nativeSetStoragePath(String newPath);
|
||||
static private native String nativeGetBookmarkDir();
|
||||
static private native String nativeGetSettingsDir();
|
||||
static private native String nativeGetWritableDir();
|
||||
static private String GetWritableDirRoot()
|
||||
{
|
||||
String writableDir = Framework.GetWritableDir();
|
||||
int index = writableDir.lastIndexOf(MWM_DIR_POSTFIX);
|
||||
if (index != -1)
|
||||
writableDir = writableDir.substring(0, index);
|
||||
|
||||
return writableDir;
|
||||
}
|
||||
|
||||
static private native String nativeGenerateUniqueBookmarkName(String baseName);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue