mirror of
https://github.com/moparisthebest/keepass2android
synced 2025-02-07 02:10:10 -05:00
updated android-filechooser library (non-public release from HBA)
fixed bug with date parsing in Dropbox added caching of FileEntry in Kp2aFileProvider.java
This commit is contained in:
parent
a44e8a9680
commit
c53bfefee5
@ -5,6 +5,7 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
@ -298,13 +299,22 @@ public class DropboxFileStorage implements JavaFileStorage {
|
||||
}
|
||||
|
||||
private FileEntry convertToFileEntry(com.dropbox.client2.DropboxAPI.Entry e) {
|
||||
//Log.d("JFS","e="+e);
|
||||
FileEntry fileEntry = new FileEntry();
|
||||
fileEntry.canRead = true;
|
||||
fileEntry.canWrite = true;
|
||||
fileEntry.isDirectory = e.isDir;
|
||||
fileEntry.sizeInBytes = e.bytes;
|
||||
fileEntry.path = e.path;
|
||||
fileEntry.lastModifiedTime = com.dropbox.client2.RESTUtility.parseDate(e.modified).getTime();
|
||||
//Log.d("JFS","fileEntry="+fileEntry);
|
||||
Date lastModifiedDate = null;
|
||||
if (e.modified != null)
|
||||
lastModifiedDate = com.dropbox.client2.RESTUtility.parseDate(e.modified);
|
||||
if (lastModifiedDate != null)
|
||||
fileEntry.lastModifiedTime = lastModifiedDate.getTime();
|
||||
else
|
||||
fileEntry.lastModifiedTime = -1;
|
||||
//Log.d("JFS","Ok. Dir="+fileEntry.isDirectory);
|
||||
return fileEntry;
|
||||
}
|
||||
|
||||
@ -324,7 +334,10 @@ public class DropboxFileStorage implements JavaFileStorage {
|
||||
public FileEntry getFileEntry(String filename) throws Exception {
|
||||
try
|
||||
{
|
||||
Log.d("JFS", "Hi!");
|
||||
Log.d("JFS", "mApi = "+mApi);
|
||||
com.dropbox.client2.DropboxAPI.Entry dbEntry = mApi.metadata(filename, 0, null, false, null);
|
||||
Log.d("JFS", "dbEntry = "+dbEntry);
|
||||
|
||||
if (dbEntry.isDeleted)
|
||||
throw new FileNotFoundException(filename+" is deleted!");
|
||||
|
@ -13,7 +13,6 @@ import group.pals.android.lib.ui.filechooser.providers.BaseFileProviderUtils;
|
||||
import group.pals.android.lib.ui.filechooser.providers.basefile.BaseFileContract.BaseFile;
|
||||
import group.pals.android.lib.ui.filechooser.utils.Converter;
|
||||
import group.pals.android.lib.ui.filechooser.utils.DateUtils;
|
||||
import group.pals.android.lib.ui.filechooser.utils.Utils;
|
||||
import group.pals.android.lib.ui.filechooser.utils.ui.ContextMenuUtils;
|
||||
import group.pals.android.lib.ui.filechooser.utils.ui.LoadingDialog;
|
||||
import group.pals.android.lib.ui.filechooser.utils.ui.Ui;
|
||||
@ -510,11 +509,11 @@ public class BaseFileAdapter extends ResourceCursorAdapter {
|
||||
|
||||
@Override
|
||||
public void onClick(final int resId) {
|
||||
new LoadingDialog(v.getContext(),
|
||||
new LoadingDialog<Void, Void, Void>(v.getContext(),
|
||||
R.string.afc_msg_loading, false) {
|
||||
|
||||
@Override
|
||||
protected Object doInBackground(Void... params) {
|
||||
protected Void doInBackground(Void... params) {
|
||||
if (resId == R.string.afc_cmd_advanced_selection_all)
|
||||
asyncSelectAll(-1, true);
|
||||
else if (resId == R.string.afc_cmd_advanced_selection_none)
|
||||
@ -533,7 +532,7 @@ public class BaseFileAdapter extends ResourceCursorAdapter {
|
||||
}// doInBackground()
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Object result) {
|
||||
protected void onPostExecute(Void result) {
|
||||
super.onPostExecute(result);
|
||||
notifyDataSetChanged();
|
||||
}// onPostExecute()
|
||||
@ -544,4 +543,5 @@ public class BaseFileAdapter extends ResourceCursorAdapter {
|
||||
return true;
|
||||
}// onLongClick()
|
||||
};// mCheckboxSelectionOnLongClickListener
|
||||
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ public class FragmentFiles extends Fragment implements
|
||||
private boolean mNewLoader = true;
|
||||
|
||||
/*
|
||||
* Controls.
|
||||
* CONTROLS
|
||||
*/
|
||||
|
||||
private View mBtnGoHome;
|
||||
@ -268,7 +268,7 @@ public class FragmentFiles extends Fragment implements
|
||||
FileChooserActivity.EXTRA_MAX_FILE_COUNT, 1000);
|
||||
mFileAdapter = new BaseFileAdapter(getActivity(), mFilterMode,
|
||||
mIsMultiSelection);
|
||||
mFileAdapter.setBuildOptionsMenuListener(mOnBuildOptionsMenuListener);
|
||||
|
||||
|
||||
/*
|
||||
* History.
|
||||
@ -320,12 +320,16 @@ public class FragmentFiles extends Fragment implements
|
||||
.findViewById(R.id.afc_textview_saveas_filename);
|
||||
mBtnOk = (Button) rootView.findViewById(R.id.afc_button_ok);
|
||||
|
||||
/*
|
||||
* INIT CONTROLS
|
||||
*/
|
||||
|
||||
|
||||
return rootView;
|
||||
}// onCreateView()
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
public void onActivityCreated(final Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
setupHeader();
|
||||
@ -343,7 +347,7 @@ public class FragmentFiles extends Fragment implements
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
if (Utils.doLog())
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(CLASSNAME, "onPrepareOptionsMenu()");
|
||||
|
||||
/*
|
||||
@ -406,13 +410,13 @@ public class FragmentFiles extends Fragment implements
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.afc_menuitem_sort)
|
||||
doResortViewFiles();
|
||||
resortViewFiles();
|
||||
else if (item.getItemId() == R.id.afc_menuitem_new_folder)
|
||||
doCreateNewDir();
|
||||
createNewDir();
|
||||
else if (item.getItemId() == R.id.afc_menuitem_switch_viewmode)
|
||||
doSwitchViewType();
|
||||
switchViewType();
|
||||
else if (item.getItemId() == R.id.afc_menuitem_home)
|
||||
doGoHome();
|
||||
goHome();
|
||||
else
|
||||
return false;
|
||||
|
||||
@ -427,16 +431,16 @@ public class FragmentFiles extends Fragment implements
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
if (Utils.doLog())
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(CLASSNAME, "onStop()");
|
||||
|
||||
super.onStop();
|
||||
HistoryProviderUtils.clearHistory(getActivity());
|
||||
HistoryProviderUtils.doCleanupOutdatedHistoryItems(getActivity());
|
||||
}// onStop()
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (Utils.doLog())
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(CLASSNAME, "onDestroy()");
|
||||
|
||||
super.onDestroy();
|
||||
@ -470,7 +474,7 @@ public class FragmentFiles extends Fragment implements
|
||||
String negativeRegex = getArguments().getString(
|
||||
FileChooserActivity.EXTRA_NEGATIVE_REGEX_FILTER);
|
||||
|
||||
if (Utils.doLog())
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(CLASSNAME, "onCreateLoader() >> path = " + path);
|
||||
|
||||
return new CursorLoader(
|
||||
@ -532,7 +536,6 @@ public class FragmentFiles extends Fragment implements
|
||||
final Uri uriInfo = BaseFileProviderUtils.getUri(data);
|
||||
final Uri selectedFile = (Uri) getArguments().getParcelable(
|
||||
FileChooserActivity.EXTRA_SELECT_FILE);
|
||||
final int colUri = data.getColumnIndex(BaseFile.COLUMN_URI);
|
||||
if (selectedFile != null)
|
||||
getArguments().remove(FileChooserActivity.EXTRA_SELECT_FILE);
|
||||
|
||||
@ -554,76 +557,8 @@ public class FragmentFiles extends Fragment implements
|
||||
: getString(R.string.afc_msg_empty),
|
||||
mFileAdapter.isEmpty());
|
||||
|
||||
if (mNewLoader || selectedFile != null) {
|
||||
/*
|
||||
* Select either the parent path of last path, or the file provided
|
||||
* by key EXTRA_SELECT_FILE. Use a Runnable to make sure this work.
|
||||
* Because if the list view is handling data, this might not work.
|
||||
*/
|
||||
mViewFiles.post(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int shouldBeSelectedIdx = -1;
|
||||
final Uri uri = selectedFile != null ? selectedFile
|
||||
: getLastLocation();
|
||||
if (uri != null
|
||||
&& BaseFileProviderUtils.fileExists(getActivity(),
|
||||
uri)) {
|
||||
final String fileName = BaseFileProviderUtils
|
||||
.getFileName(getActivity(), uri);
|
||||
if (fileName != null) {
|
||||
Uri parentUri = BaseFileProviderUtils
|
||||
.getParentFile(getActivity(), uri);
|
||||
if ((uri == getLastLocation()
|
||||
&& !getCurrentLocation().equals(
|
||||
getLastLocation()) && BaseFileProviderUtils
|
||||
.isAncestorOf(getActivity(),
|
||||
getCurrentLocation(), uri))
|
||||
|| getCurrentLocation().equals(parentUri)) {
|
||||
if (data.moveToFirst()) {
|
||||
while (!data.isLast()) {
|
||||
Uri subUri = Uri.parse(data
|
||||
.getString(colUri));
|
||||
if (uri == getLastLocation()) {
|
||||
if (data.getInt(data
|
||||
.getColumnIndex(BaseFile.COLUMN_TYPE)) == BaseFile.FILE_TYPE_DIRECTORY) {
|
||||
if (subUri.equals(uri)
|
||||
|| BaseFileProviderUtils
|
||||
.isAncestorOf(
|
||||
getActivity(),
|
||||
subUri,
|
||||
uri)) {
|
||||
shouldBeSelectedIdx = Math.max(
|
||||
0,
|
||||
data.getPosition() - 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (uri.equals(subUri)) {
|
||||
shouldBeSelectedIdx = Math.max(
|
||||
0,
|
||||
data.getPosition() - 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data.moveToNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldBeSelectedIdx >= 0
|
||||
&& shouldBeSelectedIdx < mFileAdapter.getCount())
|
||||
mViewFiles.setSelection(shouldBeSelectedIdx);
|
||||
else if (!mFileAdapter.isEmpty())
|
||||
mViewFiles.setSelection(0);
|
||||
}// run()
|
||||
});
|
||||
}
|
||||
if (mNewLoader || selectedFile != null)
|
||||
createFileSelector();
|
||||
|
||||
mNewLoader = false;
|
||||
}// onLoadFinished()
|
||||
@ -693,7 +628,7 @@ public class FragmentFiles extends Fragment implements
|
||||
mViewGoForward.setEnabled(false);
|
||||
mViewGoForward.setOnClickListener(mBtnGoForwardOnClickListener);
|
||||
|
||||
|
||||
|
||||
}// setupHeader()
|
||||
|
||||
/**
|
||||
@ -770,7 +705,9 @@ public class FragmentFiles extends Fragment implements
|
||||
* </ul>
|
||||
*/
|
||||
private void setupFooter() {
|
||||
// by default, view group footer and all its child views are hidden
|
||||
/*
|
||||
* By default, view group footer and all its child views are hidden.
|
||||
*/
|
||||
|
||||
ViewGroup viewGroupFooterContainer = (ViewGroup) getView()
|
||||
.findViewById(R.id.afc_viewgroup_footer_container);
|
||||
@ -851,6 +788,10 @@ public class FragmentFiles extends Fragment implements
|
||||
mFooterView.setVisibility(View.GONE);
|
||||
}// showFooterView()
|
||||
|
||||
/**
|
||||
* This should be called after the owner activity has been created
|
||||
* successfully.
|
||||
*/
|
||||
private void initGestureDetector() {
|
||||
mListviewFilesGestureDetector = new GestureDetector(getActivity(),
|
||||
new GestureDetector.SimpleOnGestureListener() {
|
||||
@ -920,12 +861,12 @@ public class FragmentFiles extends Fragment implements
|
||||
if (BaseFileProviderUtils.isFile(data)) {
|
||||
mTxtSaveas.setText(BaseFileProviderUtils
|
||||
.getFileName(data));
|
||||
doCheckSaveasFilenameAndFinish(BaseFileProviderUtils
|
||||
checkSaveasFilenameAndFinish(BaseFileProviderUtils
|
||||
.getFileName(data));
|
||||
} else
|
||||
return false;
|
||||
} else
|
||||
doFinish(BaseFileProviderUtils.getUri(data));
|
||||
finish(BaseFileProviderUtils.getUri(data));
|
||||
}// double tap to choose files
|
||||
else {
|
||||
// do nothing
|
||||
@ -963,8 +904,8 @@ public class FragmentFiles extends Fragment implements
|
||||
.setAction(MotionEvent.ACTION_CANCEL);
|
||||
mViewFiles.onTouchEvent(cancelEvent);
|
||||
|
||||
doDeleteFile(mViewFiles
|
||||
.getFirstVisiblePosition() + pos);
|
||||
deleteFile(mViewFiles.getFirstVisiblePosition()
|
||||
+ pos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -985,7 +926,7 @@ public class FragmentFiles extends Fragment implements
|
||||
* @param savedInstanceState
|
||||
*/
|
||||
private void loadInitialPath(final Bundle savedInstanceState) {
|
||||
if (Utils.doLog())
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(CLASSNAME, String.format(
|
||||
"loadInitialPath() >> authority=[%s] | mRoot=[%s]",
|
||||
mFileProviderAuthority, mRoot));
|
||||
@ -1046,11 +987,24 @@ public class FragmentFiles extends Fragment implements
|
||||
.getAuthority());
|
||||
|
||||
if (path == null) {
|
||||
doShowCannotConnectToServiceAndFinish();
|
||||
showCannotConnectToServiceAndFinish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!BaseFileProviderUtils.fileCanRead(getActivity(), path)) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(CLASSNAME, "loadInitialPath() >> " + path);
|
||||
|
||||
setCurrentLocation(path);
|
||||
|
||||
if (BaseFileProviderUtils.fileCanRead(getActivity(), path)) {
|
||||
/*
|
||||
* Prepare the loader. Either re-connect with an existing one, or
|
||||
* start a new one.
|
||||
*/
|
||||
Bundle args = new Bundle();
|
||||
args.putParcelable(PATH, path);
|
||||
getLoaderManager().initLoader(mIdLoaderData, args, this);
|
||||
} else {
|
||||
Dlg.toast(
|
||||
getActivity(),
|
||||
getString(R.string.afc_pmsg_cannot_access_dir,
|
||||
@ -1058,19 +1012,6 @@ public class FragmentFiles extends Fragment implements
|
||||
path)), Dlg.LENGTH_SHORT);
|
||||
getActivity().finish();
|
||||
}
|
||||
|
||||
if (Utils.doLog())
|
||||
Log.d(CLASSNAME, "loadInitialPath() >> " + path);
|
||||
|
||||
setCurrentLocation(path);
|
||||
|
||||
/*
|
||||
* Prepare the loader. Either re-connect with an existing one, or start
|
||||
* a new one.
|
||||
*/
|
||||
Bundle b = new Bundle();
|
||||
b.putParcelable(PATH, path);
|
||||
getLoaderManager().initLoader(mIdLoaderData, b, this);
|
||||
}// loadInitialPath()
|
||||
|
||||
/**
|
||||
@ -1100,7 +1041,7 @@ public class FragmentFiles extends Fragment implements
|
||||
/**
|
||||
* As the name means...
|
||||
*/
|
||||
private void doShowCannotConnectToServiceAndFinish() {
|
||||
private void showCannotConnectToServiceAndFinish() {
|
||||
Dlg.showError(getActivity(),
|
||||
R.string.afc_msg_cannot_connect_to_file_provider_service,
|
||||
new DialogInterface.OnCancelListener() {
|
||||
@ -1111,7 +1052,7 @@ public class FragmentFiles extends Fragment implements
|
||||
getActivity().finish();
|
||||
}// onCancel()
|
||||
});
|
||||
}// doShowCannotConnectToServiceAndFinish()
|
||||
}// showCannotConnectToServiceAndFinish()
|
||||
|
||||
/**
|
||||
* Gets last location.
|
||||
@ -1154,9 +1095,10 @@ public class FragmentFiles extends Fragment implements
|
||||
updateDbHistory(location);
|
||||
}// setCurrentLocation()
|
||||
|
||||
private void doGoHome() {
|
||||
private void goHome() {
|
||||
goTo(mRoot);
|
||||
}// doGoHome()
|
||||
}// goHome()
|
||||
|
||||
|
||||
private static final int[] BUTTON_SORT_IDS = {
|
||||
R.id.afc_button_sort_by_name_asc,
|
||||
@ -1169,7 +1111,7 @@ public class FragmentFiles extends Fragment implements
|
||||
* Show a dialog for sorting options and resort file list after user
|
||||
* selected an option.
|
||||
*/
|
||||
private void doResortViewFiles() {
|
||||
private void resortViewFiles() {
|
||||
final Dialog dialog = new Dialog(getActivity(), Ui.resolveAttribute(
|
||||
getActivity(), R.attr.afc_theme_dialog));
|
||||
dialog.setCanceledOnTouchOutside(true);
|
||||
@ -1245,12 +1187,12 @@ public class FragmentFiles extends Fragment implements
|
||||
dialog.setTitle(R.string.afc_title_sort_by);
|
||||
dialog.setContentView(view);
|
||||
dialog.show();
|
||||
}// doResortViewFiles()
|
||||
}// resortViewFiles()
|
||||
|
||||
/**
|
||||
* Switch view type between {@link ViewType#LIST} and {@link ViewType#GRID}
|
||||
*/
|
||||
private void doSwitchViewType() {
|
||||
private void switchViewType() {
|
||||
switch (DisplayPrefs.getViewType(getActivity())) {
|
||||
case GRID:
|
||||
DisplayPrefs.setViewType(getActivity(), ViewType.LIST);
|
||||
@ -1263,12 +1205,12 @@ public class FragmentFiles extends Fragment implements
|
||||
setupViewFiles();
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
goTo(getCurrentLocation());
|
||||
}// doSwitchViewType()
|
||||
}// switchViewType()
|
||||
|
||||
/**
|
||||
* Confirms user to create new directory.
|
||||
*/
|
||||
private void doCreateNewDir() {
|
||||
private void createNewDir() {
|
||||
if (LocalFileContract.getAuthority(getActivity()).equals(
|
||||
mFileProviderAuthority)
|
||||
&& !Utils.hasPermissions(getActivity(),
|
||||
@ -1329,22 +1271,23 @@ public class FragmentFiles extends Fragment implements
|
||||
return;
|
||||
}
|
||||
|
||||
if (getActivity()
|
||||
.getContentResolver()
|
||||
.insert(BaseFile
|
||||
.genContentUriBase(
|
||||
if (BaseFileProviderUtils
|
||||
.insertInBackground(
|
||||
getActivity(),
|
||||
BaseFile.genContentUriBase(
|
||||
getCurrentLocation()
|
||||
.getAuthority())
|
||||
.buildUpon()
|
||||
.appendPath(
|
||||
getCurrentLocation()
|
||||
.getLastPathSegment())
|
||||
.appendQueryParameter(
|
||||
BaseFile.PARAM_NAME, name)
|
||||
.appendQueryParameter(
|
||||
BaseFile.PARAM_FILE_TYPE,
|
||||
Integer.toString(BaseFile.FILE_TYPE_DIRECTORY))
|
||||
.build(), null) != null) {
|
||||
.buildUpon()
|
||||
.appendPath(
|
||||
getCurrentLocation()
|
||||
.getLastPathSegment())
|
||||
.appendQueryParameter(
|
||||
BaseFile.PARAM_NAME,
|
||||
name)
|
||||
.appendQueryParameter(
|
||||
BaseFile.PARAM_FILE_TYPE,
|
||||
Integer.toString(BaseFile.FILE_TYPE_DIRECTORY))
|
||||
.build(), null) != null) {
|
||||
Dlg.toast(getActivity(),
|
||||
getString(R.string.afc_msg_done),
|
||||
Dlg.LENGTH_SHORT);
|
||||
@ -1383,7 +1326,7 @@ public class FragmentFiles extends Fragment implements
|
||||
.trim()));
|
||||
}
|
||||
});
|
||||
}// doCreateNewDir()
|
||||
}// createNewDir()
|
||||
|
||||
/**
|
||||
* Deletes a file.
|
||||
@ -1391,7 +1334,7 @@ public class FragmentFiles extends Fragment implements
|
||||
* @param position
|
||||
* the position of item to be delete.
|
||||
*/
|
||||
private void doDeleteFile(final int position) {
|
||||
private void deleteFile(final int position) {
|
||||
Cursor cursor = (Cursor) mFileAdapter.getItem(position);
|
||||
|
||||
/*
|
||||
@ -1440,13 +1383,15 @@ public class FragmentFiles extends Fragment implements
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
new LoadingDialog(getActivity(), getString(
|
||||
R.string.afc_pmsg_deleting_file,
|
||||
isFile ? getString(R.string.afc_file)
|
||||
: getString(R.string.afc_folder),
|
||||
filename), true) {
|
||||
new LoadingDialog<Void, Void, Void>(
|
||||
getActivity(),
|
||||
getString(
|
||||
R.string.afc_pmsg_deleting_file,
|
||||
isFile ? getString(R.string.afc_file)
|
||||
: getString(R.string.afc_folder),
|
||||
filename), true) {
|
||||
|
||||
final int mTaskId = EnvUtils.genId();
|
||||
final int taskId = EnvUtils.genId();
|
||||
|
||||
private void notifyFileDeleted() {
|
||||
mHistory.removeAll(new HistoryFilter<Uri>() {
|
||||
@ -1472,15 +1417,15 @@ public class FragmentFiles extends Fragment implements
|
||||
}// notifyFileDeleted()
|
||||
|
||||
@Override
|
||||
protected Object doInBackground(Void... arg0) {
|
||||
getActivity()
|
||||
.getContentResolver()
|
||||
.delete(uri
|
||||
.buildUpon()
|
||||
.appendQueryParameter(
|
||||
BaseFile.PARAM_TASK_ID,
|
||||
Integer.toString(mTaskId))
|
||||
.build(), null, null);
|
||||
protected Void doInBackground(Void... params) {
|
||||
BaseFileProviderUtils
|
||||
.deleteInBackground(
|
||||
getActivity(),
|
||||
uri.buildUpon()
|
||||
.appendQueryParameter(
|
||||
BaseFile.PARAM_TASK_ID,
|
||||
Integer.toString(taskId))
|
||||
.build(), null, null);
|
||||
|
||||
return null;
|
||||
}// doInBackground()
|
||||
@ -1490,7 +1435,7 @@ public class FragmentFiles extends Fragment implements
|
||||
if (getCurrentLocation() != null)
|
||||
BaseFileProviderUtils.cancelTask(
|
||||
getActivity(), getCurrentLocation()
|
||||
.getAuthority(), mTaskId);
|
||||
.getAuthority(), taskId);
|
||||
|
||||
if (BaseFileProviderUtils.fileExists(
|
||||
getActivity(), uri)) {
|
||||
@ -1505,7 +1450,7 @@ public class FragmentFiles extends Fragment implements
|
||||
}// onCancelled()
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Object result) {
|
||||
protected void onPostExecute(Void result) {
|
||||
super.onPostExecute(result);
|
||||
|
||||
if (BaseFileProviderUtils.fileExists(
|
||||
@ -1530,7 +1475,7 @@ public class FragmentFiles extends Fragment implements
|
||||
mFileAdapter.markItemAsDeleted(id, false);
|
||||
}// onCancel()
|
||||
});
|
||||
}// doDeleteFile()
|
||||
}// deleteFile()
|
||||
|
||||
/**
|
||||
* As the name means.
|
||||
@ -1538,7 +1483,7 @@ public class FragmentFiles extends Fragment implements
|
||||
* @param filename
|
||||
* @since v1.91
|
||||
*/
|
||||
private void doCheckSaveasFilenameAndFinish(String filename) {
|
||||
private void checkSaveasFilenameAndFinish(String filename) {
|
||||
if (!BaseFileProviderUtils.fileCanWrite(getActivity(),
|
||||
getCurrentLocation())) {
|
||||
Dlg.toast(getActivity(),
|
||||
@ -1553,7 +1498,8 @@ public class FragmentFiles extends Fragment implements
|
||||
return;
|
||||
}
|
||||
|
||||
final Cursor cursor = getActivity().getContentResolver().query(
|
||||
final Cursor cursor = BaseFileProviderUtils.queryInBackground(
|
||||
getActivity(),
|
||||
getCurrentLocation()
|
||||
.buildUpon()
|
||||
.appendQueryParameter(BaseFile.PARAM_APPEND_NAME,
|
||||
@ -1583,7 +1529,7 @@ public class FragmentFiles extends Fragment implements
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
doFinish(uri);
|
||||
finish(uri);
|
||||
}// onClick()
|
||||
});
|
||||
|
||||
@ -1593,7 +1539,7 @@ public class FragmentFiles extends Fragment implements
|
||||
/*
|
||||
* TODO file type unknown?
|
||||
*/
|
||||
doFinish(uri);
|
||||
finish(uri);
|
||||
break;// FILE_TYPE_NOT_EXISTED
|
||||
}
|
||||
}
|
||||
@ -1601,7 +1547,7 @@ public class FragmentFiles extends Fragment implements
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}// doCheckSaveasFilenameAndFinish()
|
||||
}// checkSaveasFilenameAndFinish()
|
||||
|
||||
/**
|
||||
* Goes to a specified location.
|
||||
@ -1616,7 +1562,7 @@ public class FragmentFiles extends Fragment implements
|
||||
dir = BaseFileProviderUtils.getDefaultPath(getActivity(),
|
||||
mFileProviderAuthority);
|
||||
if (dir == null) {
|
||||
doShowCannotConnectToServiceAndFinish();
|
||||
showCannotConnectToServiceAndFinish();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1655,7 +1601,7 @@ public class FragmentFiles extends Fragment implements
|
||||
* Updates or inserts {@code path} into history database.
|
||||
*/
|
||||
private void updateDbHistory(Uri path) {
|
||||
if (Utils.doLog())
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(CLASSNAME, "updateDbHistory() >> path = " + path);
|
||||
|
||||
Calendar cal = Calendar.getInstance();
|
||||
@ -1663,7 +1609,7 @@ public class FragmentFiles extends Fragment implements
|
||||
- (cal.get(Calendar.HOUR_OF_DAY) * 60 * 60 * 1000
|
||||
+ cal.get(Calendar.MINUTE) * 60 * 1000 + cal
|
||||
.get(Calendar.SECOND) * 1000);
|
||||
if (Utils.doLog()) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(CLASSNAME,
|
||||
String.format("beginToday = %s (%s)", DbUtils
|
||||
.formatNumber(beginTodayMillis), new Date(
|
||||
@ -1730,8 +1676,8 @@ public class FragmentFiles extends Fragment implements
|
||||
final int dim = getResources().getDimensionPixelSize(R.dimen.afc_5dp);
|
||||
int count = 0;
|
||||
|
||||
Cursor cursor = getActivity().getContentResolver().query(path, null,
|
||||
null, null, null);
|
||||
Cursor cursor = BaseFileProviderUtils.queryInBackground(getActivity(),
|
||||
path, null, null, null, null);
|
||||
while (cursor != null) {
|
||||
Uri lastUri = null;
|
||||
if (cursor.moveToFirst()) {
|
||||
@ -1771,7 +1717,8 @@ public class FragmentFiles extends Fragment implements
|
||||
/*
|
||||
* Process the parent directory.
|
||||
*/
|
||||
cursor = getActivity().getContentResolver().query(
|
||||
cursor = BaseFileProviderUtils.queryInBackground(
|
||||
getActivity(),
|
||||
BaseFile.genContentUriApi(lastUri.getAuthority())
|
||||
.buildUpon()
|
||||
.appendPath(BaseFile.CMD_GET_PARENT)
|
||||
@ -1809,12 +1756,12 @@ public class FragmentFiles extends Fragment implements
|
||||
* @param files
|
||||
* list of {@link Uri}.
|
||||
*/
|
||||
private void doFinish(Uri... files) {
|
||||
private void finish(Uri... files) {
|
||||
List<Uri> list = new ArrayList<Uri>();
|
||||
for (Uri uri : files)
|
||||
list.add(uri);
|
||||
doFinish((ArrayList<Uri>) list);
|
||||
}// doFinish()
|
||||
finish((ArrayList<Uri>) list);
|
||||
}// finish()
|
||||
|
||||
/**
|
||||
* Finishes this activity.
|
||||
@ -1822,7 +1769,7 @@ public class FragmentFiles extends Fragment implements
|
||||
* @param files
|
||||
* list of {@link Uri}.
|
||||
*/
|
||||
private void doFinish(ArrayList<Uri> files) {
|
||||
private void finish(ArrayList<Uri> files) {
|
||||
if (files == null || files.isEmpty()) {
|
||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
||||
getActivity().finish();
|
||||
@ -1842,7 +1789,7 @@ public class FragmentFiles extends Fragment implements
|
||||
DisplayPrefs.setLastLocation(getActivity(), null);
|
||||
|
||||
getActivity().finish();
|
||||
}// doFinish()
|
||||
}// finish()
|
||||
|
||||
/**
|
||||
* ******************************************************* BUTTON LISTENERS
|
||||
@ -1852,10 +1799,12 @@ public class FragmentFiles extends Fragment implements
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
doGoHome();
|
||||
goHome();
|
||||
}// onClick()
|
||||
};// mBtnGoHomeOnClickListener
|
||||
|
||||
|
||||
|
||||
private final View.OnClickListener mBtnGoBackOnClickListener = new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
@ -1894,7 +1843,7 @@ public class FragmentFiles extends Fragment implements
|
||||
if (BaseFile.FILTER_FILES_ONLY == mFilterMode || mIsSaveDialog)
|
||||
return false;
|
||||
|
||||
doFinish((Uri) v.getTag());
|
||||
finish((Uri) v.getTag());
|
||||
|
||||
return false;
|
||||
}// onLongClick()
|
||||
@ -1922,6 +1871,7 @@ public class FragmentFiles extends Fragment implements
|
||||
}// onClick()
|
||||
};// mBtnGoForwardOnClickListener
|
||||
|
||||
|
||||
private final TextView.OnEditorActionListener mTxtFilenameOnEditorActionListener = new TextView.OnEditorActionListener() {
|
||||
|
||||
@Override
|
||||
@ -1941,7 +1891,7 @@ public class FragmentFiles extends Fragment implements
|
||||
public void onClick(View v) {
|
||||
Ui.showSoftKeyboard(v, false);
|
||||
String filename = mTxtSaveas.getText().toString().trim();
|
||||
doCheckSaveasFilenameAndFinish(filename);
|
||||
checkSaveasFilenameAndFinish(filename);
|
||||
}// onClick()
|
||||
};// mBtnOk_SaveDialog_OnClickListener
|
||||
|
||||
@ -1949,7 +1899,7 @@ public class FragmentFiles extends Fragment implements
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
doFinish(mFileAdapter.getSelectedItems());
|
||||
finish(mFileAdapter.getSelectedItems());
|
||||
}// onClick()
|
||||
};// mBtnOk_OpenDialog_OnClickListener
|
||||
|
||||
@ -1957,7 +1907,7 @@ public class FragmentFiles extends Fragment implements
|
||||
* FRAGMENT LISTENERS
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* LISTVIEW HELPER
|
||||
*/
|
||||
@ -1986,10 +1936,10 @@ public class FragmentFiles extends Fragment implements
|
||||
return;
|
||||
|
||||
if (mIsSaveDialog)
|
||||
doCheckSaveasFilenameAndFinish(BaseFileProviderUtils
|
||||
checkSaveasFilenameAndFinish(BaseFileProviderUtils
|
||||
.getFileName(cursor));
|
||||
else
|
||||
doFinish(BaseFileProviderUtils.getUri(cursor));
|
||||
finish(BaseFileProviderUtils.getUri(cursor));
|
||||
}// single tap to choose files
|
||||
}// onItemClick()
|
||||
};// mViewFilesOnItemClickListener
|
||||
@ -2009,7 +1959,7 @@ public class FragmentFiles extends Fragment implements
|
||||
&& !mIsMultiSelection
|
||||
&& BaseFileProviderUtils.isDirectory(cursor)
|
||||
&& (BaseFile.FILTER_DIRECTORIES_ONLY == mFilterMode || BaseFile.FILTER_FILES_AND_DIRECTORIES == mFilterMode)) {
|
||||
doFinish(BaseFileProviderUtils.getUri(cursor));
|
||||
finish(BaseFileProviderUtils.getUri(cursor));
|
||||
}
|
||||
}// single tap to choose files
|
||||
|
||||
@ -2020,22 +1970,119 @@ public class FragmentFiles extends Fragment implements
|
||||
}// onItemLongClick()
|
||||
};// mViewFilesOnItemLongClickListener
|
||||
|
||||
private final BaseFileAdapter.OnBuildOptionsMenuListener mOnBuildOptionsMenuListener = new BaseFileAdapter.OnBuildOptionsMenuListener() {
|
||||
|
||||
@Override
|
||||
public void onBuildOptionsMenu(View view, Cursor cursor) {
|
||||
if (!BaseFileProviderUtils.fileCanRead(cursor)
|
||||
|| !BaseFileProviderUtils.isDirectory(cursor))
|
||||
return;
|
||||
/**
|
||||
* We use a {@link LoadingDialog} to avoid of
|
||||
* {@code NetworkOnMainThreadException}.
|
||||
*/
|
||||
private LoadingDialog<Void, Void, Integer> mFileSelector;
|
||||
|
||||
final Uri uri = BaseFileProviderUtils.getUri(cursor);
|
||||
final String name = BaseFileProviderUtils.getFileName(cursor);
|
||||
/**
|
||||
* Creates new {@link #mFileSelector} to select appropriate file after
|
||||
* loading a folder's content. It's either the parent path of last path, or
|
||||
* the file provided by key {@link FileChooserActivity#EXTRA_SELECT_FILE}.
|
||||
* Note that this also cancels previous selector if there is such one.
|
||||
*/
|
||||
private void createFileSelector() {
|
||||
if (mFileSelector != null)
|
||||
mFileSelector.cancel(true);
|
||||
|
||||
}// onBuildOptionsMenu()
|
||||
mFileSelector = new LoadingDialog<Void, Void, Integer>(getActivity(),
|
||||
R.string.afc_msg_loading, true) {
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground(Void... params) {
|
||||
final Cursor cursor = mFileAdapter.getCursor();
|
||||
if (cursor == null || cursor.isClosed())
|
||||
return -1;
|
||||
|
||||
final Uri selectedFile = (Uri) getArguments().getParcelable(
|
||||
FileChooserActivity.EXTRA_SELECT_FILE);
|
||||
final int colUri = cursor.getColumnIndex(BaseFile.COLUMN_URI);
|
||||
if (selectedFile != null)
|
||||
getArguments()
|
||||
.remove(FileChooserActivity.EXTRA_SELECT_FILE);
|
||||
|
||||
int shouldBeSelectedIdx = -1;
|
||||
final Uri uri = selectedFile != null ? selectedFile
|
||||
: getLastLocation();
|
||||
if (uri == null
|
||||
|| !BaseFileProviderUtils
|
||||
.fileExists(getActivity(), uri))
|
||||
return -1;
|
||||
|
||||
final String fileName = BaseFileProviderUtils.getFileName(
|
||||
getActivity(), uri);
|
||||
if (fileName == null)
|
||||
return -1;
|
||||
|
||||
Uri parentUri = BaseFileProviderUtils.getParentFile(
|
||||
getActivity(), uri);
|
||||
if ((uri == getLastLocation()
|
||||
&& !getCurrentLocation().equals(getLastLocation()) && BaseFileProviderUtils
|
||||
.isAncestorOf(getActivity(), getCurrentLocation(),
|
||||
uri))
|
||||
|| getCurrentLocation().equals(parentUri)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
while (!cursor.isLast()) {
|
||||
if (isCancelled())
|
||||
return -1;
|
||||
|
||||
Uri subUri = Uri.parse(cursor.getString(colUri));
|
||||
if (uri == getLastLocation()) {
|
||||
if (cursor.getInt(cursor
|
||||
.getColumnIndex(BaseFile.COLUMN_TYPE)) == BaseFile.FILE_TYPE_DIRECTORY) {
|
||||
if (subUri.equals(uri)
|
||||
|| BaseFileProviderUtils
|
||||
.isAncestorOf(
|
||||
getActivity(),
|
||||
subUri, uri)) {
|
||||
shouldBeSelectedIdx = Math.max(0,
|
||||
cursor.getPosition() - 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (uri.equals(subUri)) {
|
||||
shouldBeSelectedIdx = Math.max(0,
|
||||
cursor.getPosition() - 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cursor.moveToNext();
|
||||
}// while
|
||||
}// if
|
||||
}// if
|
||||
|
||||
return shouldBeSelectedIdx;
|
||||
}// doInBackground()
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Integer result) {
|
||||
super.onPostExecute(result);
|
||||
|
||||
if (isCancelled() || mFileAdapter.isEmpty())
|
||||
return;
|
||||
|
||||
/*
|
||||
* Use a Runnable to make sure this works. Because if the list
|
||||
* view is handling data, this might not work.
|
||||
*/
|
||||
mViewFiles.post(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (result >= 0 && result < mFileAdapter.getCount())
|
||||
mViewFiles.setSelection(result);
|
||||
else if (!mFileAdapter.isEmpty())
|
||||
mViewFiles.setSelection(0);
|
||||
}// run()
|
||||
});
|
||||
}// onPostExecute()
|
||||
};
|
||||
|
||||
mFileSelector.execute();
|
||||
}// createFileSelector()
|
||||
|
||||
@Override
|
||||
public void onBuildAdvancedOptionsMenu(View view, Cursor cursor) {
|
||||
// TODO Auto-generated method stub
|
||||
}// onBuildAdvancedOptionsMenu()
|
||||
};// mOnBuildOptionsMenuListener
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
package group.pals.android.lib.ui.filechooser.prefs;
|
||||
|
||||
import group.pals.android.lib.ui.filechooser.utils.Sys;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
@ -14,11 +15,10 @@ import android.os.Build;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceManager;
|
||||
import group.pals.android.lib.ui.filechooser.R;
|
||||
|
||||
/**
|
||||
* Convenient class for working with preferences.
|
||||
*
|
||||
*
|
||||
* @author Hai Bison
|
||||
* @since v4.3 beta
|
||||
*/
|
||||
@ -26,60 +26,58 @@ public class Prefs {
|
||||
|
||||
/**
|
||||
* This unique ID is used for storing preferences.
|
||||
*
|
||||
*
|
||||
* @since v4.9 beta
|
||||
*/
|
||||
public static final String UID = "9795e88b-2ab4-4b81-a548-409091a1e0c6";
|
||||
|
||||
/**
|
||||
* Generates global preference filename of this library.
|
||||
*
|
||||
* @param context the context.
|
||||
*
|
||||
* @return the global preference filename.
|
||||
*/
|
||||
public static final String genPreferenceFilename(Context context) {
|
||||
return String.format("%s_%s", context.getString(R.string.afc_lib_name),
|
||||
UID);
|
||||
public static final String genPreferenceFilename() {
|
||||
return String.format("%s_%s", Sys.LIB_NAME, UID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates global database filename.
|
||||
*
|
||||
* @param context the context.
|
||||
* @param name the database filename.
|
||||
*
|
||||
* @param name
|
||||
* the database filename.
|
||||
* @return the global database filename.
|
||||
*/
|
||||
public static final String genDatabaseFilename(Context context, String name) {
|
||||
return String.format("%s_%s_%s",
|
||||
context.getString(R.string.afc_lib_name), UID, name);
|
||||
public static final String genDatabaseFilename(String name) {
|
||||
return String.format("%s_%s_%s", Sys.LIB_NAME, UID, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets new {@link SharedPreferences}
|
||||
*
|
||||
* @param context the context.
|
||||
*
|
||||
* @param context
|
||||
* the context.
|
||||
* @return {@link SharedPreferences}
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static SharedPreferences p(Context context) {
|
||||
// always use application context
|
||||
return context.getApplicationContext().getSharedPreferences(
|
||||
genPreferenceFilename(context), Context.MODE_MULTI_PROCESS);
|
||||
genPreferenceFilename(), Context.MODE_MULTI_PROCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup {@code pm} to use global unique filename and global access mode.
|
||||
* You must use this method if you let the user change preferences via UI
|
||||
* (such as {@link PreferenceActivity}, {@link PreferenceFragment}...).
|
||||
*
|
||||
* @param context the context.
|
||||
* @param pm {@link PreferenceManager}.
|
||||
*
|
||||
* @param pm
|
||||
* {@link PreferenceManager}.
|
||||
* @since v4.9 beta
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static void setupPreferenceManager(Context context,
|
||||
PreferenceManager pm) {
|
||||
public static void setupPreferenceManager(PreferenceManager pm) {
|
||||
pm.setSharedPreferencesMode(Context.MODE_MULTI_PROCESS);
|
||||
pm.setSharedPreferencesName(genPreferenceFilename(context));
|
||||
pm.setSharedPreferencesName(genPreferenceFilename());
|
||||
}// setupPreferenceManager()
|
||||
|
||||
}
|
||||
|
@ -16,11 +16,14 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Utilities for base file provider.
|
||||
@ -115,11 +118,10 @@ public class BaseFileProviderUtils {
|
||||
String result = getProviderName(providerId);
|
||||
|
||||
if (result == null) {
|
||||
Cursor cursor = context
|
||||
.getContentResolver()
|
||||
.query(BaseFile
|
||||
.genContentUriApi(getProviderAuthority(providerId)),
|
||||
null, null, null, null);
|
||||
Cursor cursor = queryInBackground(
|
||||
context,
|
||||
BaseFile.genContentUriApi(getProviderAuthority(providerId)),
|
||||
null, null, null, null);
|
||||
if (cursor == null)
|
||||
return null;
|
||||
|
||||
@ -165,11 +167,10 @@ public class BaseFileProviderUtils {
|
||||
int attr = MAP_PROVIDER_INFO.get(providerId).getInt(
|
||||
BaseFile.COLUMN_PROVIDER_ICON_ATTR);
|
||||
if (attr == 0) {
|
||||
Cursor cursor = context
|
||||
.getContentResolver()
|
||||
.query(BaseFile
|
||||
.genContentUriApi(getProviderAuthority(providerId)),
|
||||
null, null, null, null);
|
||||
Cursor cursor = queryInBackground(
|
||||
context,
|
||||
BaseFile.genContentUriApi(getProviderAuthority(providerId)),
|
||||
null, null, null, null);
|
||||
if (cursor != null) {
|
||||
try {
|
||||
if (cursor.moveToFirst()) {
|
||||
@ -249,8 +250,8 @@ public class BaseFileProviderUtils {
|
||||
* otherwise.
|
||||
*/
|
||||
public static boolean isDirectory(Context context, Uri uri) {
|
||||
Cursor cursor = context.getContentResolver().query(uri, null, null,
|
||||
null, null);
|
||||
//Log.d("AFC", "isDir? "+uri.toString());
|
||||
Cursor cursor = queryInBackground(context, uri, null, null, null, null);
|
||||
if (cursor == null)
|
||||
return false;
|
||||
|
||||
@ -285,8 +286,8 @@ public class BaseFileProviderUtils {
|
||||
* @return {@code true} if {@code uri} is a file, {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isFile(Context context, Uri uri) {
|
||||
Cursor cursor = context.getContentResolver().query(uri, null, null,
|
||||
null, null);
|
||||
//Log.d("AFC", "isFile? "+uri.toString());
|
||||
Cursor cursor = queryInBackground(context, uri, null, null, null, null);
|
||||
if (cursor == null)
|
||||
return false;
|
||||
|
||||
@ -320,8 +321,8 @@ public class BaseFileProviderUtils {
|
||||
* @return the file name if {@code uri} is a file, {@code null} otherwise.
|
||||
*/
|
||||
public static String getFileName(Context context, Uri uri) {
|
||||
Cursor cursor = context.getContentResolver().query(uri, null, null,
|
||||
null, null);
|
||||
//Log.d("AFC", "getFileName "+uri.toString());
|
||||
Cursor cursor = queryInBackground(context, uri, null, null, null, null);
|
||||
if (cursor == null)
|
||||
return null;
|
||||
|
||||
@ -358,8 +359,8 @@ public class BaseFileProviderUtils {
|
||||
* @return the real URI of {@code uri}.
|
||||
*/
|
||||
public static Uri getRealUri(Context context, Uri uri) {
|
||||
Cursor cursor = context.getContentResolver().query(uri, null, null,
|
||||
null, null);
|
||||
//Log.d("AFC", "getRealUri "+uri.toString());
|
||||
Cursor cursor = queryInBackground(context, uri, null, null, null, null);
|
||||
if (cursor == null)
|
||||
return null;
|
||||
|
||||
@ -399,8 +400,8 @@ public class BaseFileProviderUtils {
|
||||
* {@link #FILE_TYPE_UNKNOWN}, {@link #FILE_TYPE_NOT_EXISTED}.
|
||||
*/
|
||||
public static int getFileType(Context context, Uri uri) {
|
||||
Cursor cursor = context.getContentResolver().query(uri, null, null,
|
||||
null, null);
|
||||
//Log.d("AFC", "filetype? "+uri.toString());
|
||||
Cursor cursor = queryInBackground(context, uri, null, null, null, null);
|
||||
if (cursor == null)
|
||||
return BaseFile.FILE_TYPE_NOT_EXISTED;
|
||||
|
||||
@ -448,8 +449,8 @@ public class BaseFileProviderUtils {
|
||||
* @return {@code true} or {@code false}.
|
||||
*/
|
||||
public static boolean fileExists(Context context, Uri uri) {
|
||||
Cursor cursor = context.getContentResolver().query(uri, null, null,
|
||||
null, null);
|
||||
//Log.d("AFC", "exists? "+uri.toString());
|
||||
Cursor cursor = queryInBackground(context, uri, null, null, null, null);
|
||||
if (cursor == null)
|
||||
return false;
|
||||
|
||||
@ -473,8 +474,8 @@ public class BaseFileProviderUtils {
|
||||
* @return {@code true} or {@code false}.
|
||||
*/
|
||||
public static boolean fileCanRead(Context context, Uri uri) {
|
||||
Cursor cursor = context.getContentResolver().query(uri, null, null,
|
||||
null, null);
|
||||
//Log.d("AFC", "canread? "+uri.toString());
|
||||
Cursor cursor = queryInBackground(context, uri, null, null, null, null);
|
||||
if (cursor == null)
|
||||
return false;
|
||||
|
||||
@ -510,8 +511,8 @@ public class BaseFileProviderUtils {
|
||||
* @return {@code true} or {@code false}.
|
||||
*/
|
||||
public static boolean fileCanWrite(Context context, Uri uri) {
|
||||
Cursor cursor = context.getContentResolver().query(uri, null, null,
|
||||
null, null);
|
||||
//Log.d("AFC", "canWrite? "+uri.toString());
|
||||
Cursor cursor = queryInBackground(context, uri, null, null, null, null);
|
||||
if (cursor == null)
|
||||
return false;
|
||||
|
||||
@ -547,7 +548,8 @@ public class BaseFileProviderUtils {
|
||||
* @return the default path, can be {@code null}.
|
||||
*/
|
||||
public static Uri getDefaultPath(Context context, String authority) {
|
||||
Cursor cursor = context.getContentResolver().query(
|
||||
Cursor cursor = queryInBackground(
|
||||
context,
|
||||
BaseFile.genContentUriApi(authority).buildUpon()
|
||||
.appendPath(BaseFile.CMD_GET_DEFAULT_PATH).build(),
|
||||
null, null, null, null);
|
||||
@ -574,7 +576,8 @@ public class BaseFileProviderUtils {
|
||||
* @return the parent file if it exists, {@code null} otherwise.
|
||||
*/
|
||||
public static Uri getParentFile(Context context, Uri uri) {
|
||||
Cursor cursor = context.getContentResolver().query(
|
||||
Cursor cursor = queryInBackground(
|
||||
context,
|
||||
BaseFile.genContentUriApi(uri.getAuthority())
|
||||
.buildUpon()
|
||||
.appendPath(BaseFile.CMD_GET_PARENT)
|
||||
@ -607,7 +610,8 @@ public class BaseFileProviderUtils {
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isAncestorOf(Context context, Uri uri1, Uri uri2) {
|
||||
return context.getContentResolver().query(
|
||||
return queryInBackground(
|
||||
context,
|
||||
BaseFile.genContentUriApi(uri1.getAuthority())
|
||||
.buildUpon()
|
||||
.appendPath(BaseFile.CMD_IS_ANCESTOR_OF)
|
||||
@ -629,7 +633,8 @@ public class BaseFileProviderUtils {
|
||||
* the task ID.
|
||||
*/
|
||||
public static void cancelTask(Context context, String authority, int taskId) {
|
||||
context.getContentResolver().query(
|
||||
queryInBackground(
|
||||
context,
|
||||
BaseFile.genContentUriApi(authority)
|
||||
.buildUpon()
|
||||
.appendPath(BaseFile.CMD_CANCEL)
|
||||
@ -637,4 +642,186 @@ public class BaseFileProviderUtils {
|
||||
Integer.toString(taskId)).build(), null, null,
|
||||
null, null);
|
||||
}// cancelTask()
|
||||
|
||||
/**
|
||||
* Creates new background thread to delete given URI, waits for the thread
|
||||
* to finish (or be interrupted) and returns the result.
|
||||
*
|
||||
* @param context
|
||||
* the context.
|
||||
* @param uri
|
||||
* the URI to delete, see
|
||||
* {@link ContentResolver#delete(Uri, String, String[])} for more
|
||||
* details.
|
||||
* @param where
|
||||
* the {@code WHERE} clause, see
|
||||
* {@link ContentResolver#delete(Uri, String, String[])} for more
|
||||
* details.
|
||||
* @param selectionArgs
|
||||
* the selection arguments, see
|
||||
* {@link ContentResolver#delete(Uri, String, String[])} for more
|
||||
* details.
|
||||
* @return the value returned from
|
||||
* {@link ContentResolver#delete(Uri, String, String[])} , or
|
||||
* {@code -1} if an error occurred.
|
||||
*/
|
||||
public static int deleteInBackground(final Context context, final Uri uri,
|
||||
final String where, final String[] selectionArgs) {
|
||||
final int[] result = { 0 };
|
||||
|
||||
Thread thread = new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
result[0] = context.getContentResolver().delete(uri, where,
|
||||
selectionArgs);
|
||||
}// run()
|
||||
};
|
||||
thread.start();
|
||||
try {
|
||||
thread.join();
|
||||
return result[0];
|
||||
} catch (InterruptedException e) {
|
||||
return -1;
|
||||
}
|
||||
}// deleteInBackground()
|
||||
|
||||
/**
|
||||
* Creates new background thread to insert values to given URI, waits for
|
||||
* the thread to finish (or be interrupted) and returns the result.
|
||||
*
|
||||
* @param context
|
||||
* the context.
|
||||
* @param uri
|
||||
* the URI to insert values into, see
|
||||
* {@link ContentResolver#insert(Uri, ContentValues)} for more
|
||||
* details.
|
||||
* @param values
|
||||
* the values to insert into, see
|
||||
* {@link ContentResolver#insert(Uri, ContentValues)} for more
|
||||
* details.
|
||||
* @return the URI returned from
|
||||
* {@link ContentResolver#insert(Uri, ContentValues)}, or
|
||||
* {@code null} if an error occurred.
|
||||
*/
|
||||
public static Uri insertInBackground(final Context context, final Uri uri,
|
||||
final ContentValues values) {
|
||||
final Uri[] result = { null };
|
||||
|
||||
Thread thread = new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
result[0] = context.getContentResolver().insert(uri, values);
|
||||
}// run()
|
||||
};
|
||||
thread.start();
|
||||
try {
|
||||
thread.join();
|
||||
return result[0];
|
||||
} catch (InterruptedException e) {
|
||||
return null;
|
||||
}
|
||||
}// insertInBackground()
|
||||
|
||||
/**
|
||||
* Creates new background thread to query given URI, waits for the thread to
|
||||
* finish (or be interrupted) and returns the result.
|
||||
*
|
||||
* @param context
|
||||
* the context.
|
||||
* @param uri
|
||||
* the URI to query, see
|
||||
* {@link ContentResolver#query(Uri, String[], String, String[], String)}
|
||||
* for more details.
|
||||
* @param projection
|
||||
* the projection, see
|
||||
* {@link ContentResolver#query(Uri, String[], String, String[], String)}
|
||||
* for more details.
|
||||
* @param selection
|
||||
* the selection, see
|
||||
* {@link ContentResolver#query(Uri, String[], String, String[], String)}
|
||||
* for more details.
|
||||
* @param selectionArgs
|
||||
* the selection arguments, see
|
||||
* {@link ContentResolver#query(Uri, String[], String, String[], String)}
|
||||
* for more details.
|
||||
* @param sortOrder
|
||||
* the sort order, see
|
||||
* {@link ContentResolver#query(Uri, String[], String, String[], String)}
|
||||
* for more details.
|
||||
* @return the cursor returned from
|
||||
* {@link ContentResolver#query(Uri, String[], String, String[], String)}
|
||||
* , or {@code null} if an error occurred.
|
||||
*/
|
||||
public static Cursor queryInBackground(final Context context,
|
||||
final Uri uri, final String[] projection, final String selection,
|
||||
final String[] selectionArgs, final String sortOrder) {
|
||||
final Cursor[] result = { null };
|
||||
|
||||
Thread thread = new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
result[0] = context.getContentResolver().query(uri, projection,
|
||||
selection, selectionArgs, sortOrder);
|
||||
}// run()
|
||||
};
|
||||
thread.start();
|
||||
try {
|
||||
thread.join();
|
||||
return result[0];
|
||||
} catch (InterruptedException e) {
|
||||
return null;
|
||||
}
|
||||
}// queryInBackground()
|
||||
|
||||
/**
|
||||
* Creates new background thread to update given URI, waits for the thread
|
||||
* to finish (or be interrupted) and returns the result.
|
||||
*
|
||||
* @param context
|
||||
* the context.
|
||||
* @param uri
|
||||
* the URI to update, see
|
||||
* {@link ContentResolver#update(Uri, ContentValues, String, String[])}
|
||||
* for more details.
|
||||
* @param values
|
||||
* the values to update, see
|
||||
* {@link ContentResolver#update(Uri, ContentValues, String, String[])}
|
||||
* for more details.
|
||||
* @param where
|
||||
* the {@code WHERE} clause, see
|
||||
* {@link ContentResolver#update(Uri, ContentValues, String, String[])}
|
||||
* for more details.
|
||||
* @param selectionArgs
|
||||
* the selection arguments, see
|
||||
* {@link ContentResolver#update(Uri, ContentValues, String, String[])}
|
||||
* for more details.
|
||||
* @return the value returned from
|
||||
* {@link ContentResolver#update(Uri, ContentValues, String, String[])}
|
||||
* , or {@code -1} if an error occurred.
|
||||
*/
|
||||
public static int updateInBackground(final Context context, final Uri uri,
|
||||
final ContentValues values, final String where,
|
||||
final String[] selectionArgs) {
|
||||
final int[] result = { 0 };
|
||||
|
||||
Thread thread = new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
result[0] = context.getContentResolver().update(uri, values,
|
||||
where, selectionArgs);
|
||||
}// run()
|
||||
};
|
||||
thread.start();
|
||||
try {
|
||||
thread.join();
|
||||
return result[0];
|
||||
} catch (InterruptedException e) {
|
||||
return -1;
|
||||
}
|
||||
}// updateInBackground()
|
||||
|
||||
}
|
||||
|
@ -7,16 +7,16 @@
|
||||
|
||||
package group.pals.android.lib.ui.filechooser.providers.history;
|
||||
|
||||
import group.pals.android.lib.ui.filechooser.prefs.Prefs;
|
||||
import group.pals.android.lib.ui.filechooser.providers.DbUtils;
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.os.Build;
|
||||
import group.pals.android.lib.ui.filechooser.prefs.Prefs;
|
||||
import group.pals.android.lib.ui.filechooser.providers.DbUtils;
|
||||
|
||||
/**
|
||||
* SQLite helper for history database.
|
||||
*
|
||||
*
|
||||
* @author Hai Bison
|
||||
* @since v5.1 beta
|
||||
*/
|
||||
@ -38,8 +38,8 @@ public class HistoryHelper extends SQLiteOpenHelper {
|
||||
|
||||
public HistoryHelper(Context context) {
|
||||
// always use application context
|
||||
super(context.getApplicationContext(), Prefs.genDatabaseFilename(
|
||||
context, DB_FILENAME), null, DB_VERSION);
|
||||
super(context.getApplicationContext(), Prefs
|
||||
.genDatabaseFilename(DB_FILENAME), null, DB_VERSION);
|
||||
}// HistoryHelper()
|
||||
|
||||
@Override
|
||||
@ -54,4 +54,5 @@ public class HistoryHelper extends SQLiteOpenHelper {
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
// TODO
|
||||
}// onUpgrade()
|
||||
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ package group.pals.android.lib.ui.filechooser.providers.history;
|
||||
import group.pals.android.lib.ui.filechooser.BuildConfig;
|
||||
import group.pals.android.lib.ui.filechooser.R;
|
||||
import group.pals.android.lib.ui.filechooser.providers.DbUtils;
|
||||
import group.pals.android.lib.ui.filechooser.utils.Utils;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ -35,8 +34,8 @@ public class HistoryProviderUtils {
|
||||
* @param context
|
||||
* {@link Context}.
|
||||
*/
|
||||
public static void clearHistory(Context context) {
|
||||
if (Utils.doLog())
|
||||
public static void doCleanupOutdatedHistoryItems(Context context) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(CLASSNAME, "doCleanupCache()");
|
||||
|
||||
try {
|
||||
@ -47,9 +46,9 @@ public class HistoryProviderUtils {
|
||||
final long validityInMillis = new Date().getTime()
|
||||
- 0;
|
||||
|
||||
if (Utils.doLog())
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(CLASSNAME, String.format(
|
||||
"clearHistory() - validity = %,d (%s)",
|
||||
"doCleanupCache() - validity = %,d (%s)",
|
||||
validityInMillis, new Date(validityInMillis)));
|
||||
context.getContentResolver().delete(
|
||||
HistoryContract.genContentUri(context),
|
||||
@ -61,5 +60,6 @@ public class HistoryProviderUtils {
|
||||
* Currently we just ignore it.
|
||||
*/
|
||||
}
|
||||
}// clearHistory()
|
||||
}// doCleanupOutdatedHistoryItems()
|
||||
|
||||
}
|
||||
|
@ -303,7 +303,6 @@ public class LocalFileProvider extends BaseFileProvider {
|
||||
newRow.add(type);
|
||||
newRow.add(file.lastModified());
|
||||
newRow.add(FileUtils.getResIcon(type, file.getName()));
|
||||
|
||||
} else if (BaseFile.CMD_SHUTDOWN.equals(uri.getLastPathSegment())) {
|
||||
/*
|
||||
* TODO Stop all tasks. If the activity call this command in
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
package group.pals.android.lib.ui.filechooser.utils;
|
||||
|
||||
import group.pals.android.lib.ui.filechooser.R;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -15,28 +16,27 @@ import android.view.ContextThemeWrapper;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.widget.TextView;
|
||||
import group.pals.android.lib.ui.filechooser.R;
|
||||
|
||||
/**
|
||||
* Something funny :-)
|
||||
*
|
||||
*
|
||||
* @author Hai Bison
|
||||
*/
|
||||
public class E {
|
||||
|
||||
/**
|
||||
* Shows it!
|
||||
*
|
||||
* @param context {@link Context}
|
||||
*
|
||||
* @param context
|
||||
* {@link Context}
|
||||
*/
|
||||
public static void show(Context context) {
|
||||
String msg = null;
|
||||
try {
|
||||
msg = String.format("Hi :-)\n\n" + "%s %s\n"
|
||||
msg = String.format("Hi :-)\n\n" + "%s v%s\n"
|
||||
+ "…by Hai Bison Apps\n\n" + "http://www.haibison.com\n\n"
|
||||
+ "Hope you enjoy this library.",
|
||||
context.getString(R.string.afc_lib_name),
|
||||
context.getString(R.string.afc_lib_version_name));
|
||||
+ "Hope you enjoy this library.", Sys.LIB_NAME,
|
||||
Sys.LIB_VERSION_NAME);
|
||||
} catch (Exception e) {
|
||||
msg = "Oops… You've found a broken Easter egg, try again later :-(";
|
||||
}
|
||||
@ -70,4 +70,5 @@ public class E {
|
||||
dialog.setContentView(textView);
|
||||
dialog.show();
|
||||
}// show()
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Hai Bison
|
||||
*
|
||||
* See the file LICENSE at the root directory of this project for copying
|
||||
* permission.
|
||||
*/
|
||||
|
||||
package group.pals.android.lib.ui.filechooser.utils;
|
||||
|
||||
/**
|
||||
* System variables.
|
||||
*
|
||||
* @author Hai Bison
|
||||
*
|
||||
*/
|
||||
public class Sys {
|
||||
|
||||
/**
|
||||
* The library name.
|
||||
*/
|
||||
public static final String LIB_NAME = "android-filechooser";
|
||||
|
||||
/**
|
||||
* The library version name.
|
||||
*/
|
||||
public static final String LIB_VERSION_NAME = "5.4.3 beta";
|
||||
|
||||
/**
|
||||
* The library version code.
|
||||
*/
|
||||
public static final int LIB_VERSION_CODE = 54;
|
||||
|
||||
}
|
@ -35,7 +35,7 @@ public class Utils {
|
||||
|
||||
public static boolean doLog()
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
//return BuildConfig.DEBUG; //not working with Mono for Android
|
||||
|
||||
}
|
||||
|
@ -21,7 +21,8 @@ import android.util.Log;
|
||||
* @author Hai Bison
|
||||
* @since v2.1 alpha
|
||||
*/
|
||||
public abstract class LoadingDialog extends AsyncTask<Void, Void, Object> {
|
||||
public abstract class LoadingDialog<Params, Progress, Result> extends
|
||||
AsyncTask<Params, Progress, Result> {
|
||||
|
||||
public static final String CLASSNAME = LoadingDialog.class.getName();
|
||||
|
||||
@ -62,7 +63,7 @@ public abstract class LoadingDialog extends AsyncTask<Void, Void, Object> {
|
||||
}
|
||||
});
|
||||
}
|
||||
}// LoadingDialog
|
||||
}// LoadingDialog()
|
||||
|
||||
/**
|
||||
* Creates new {@link LoadingDialog}
|
||||
@ -76,12 +77,13 @@ public abstract class LoadingDialog extends AsyncTask<Void, Void, Object> {
|
||||
*/
|
||||
public LoadingDialog(Context context, int msgId, boolean cancelable) {
|
||||
this(context, context.getString(msgId), cancelable);
|
||||
}
|
||||
}// LoadingDialog()
|
||||
|
||||
/**
|
||||
* If you override this method, you must call {@code super.onPreExecute()}
|
||||
* at very first of the method.
|
||||
*/
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
|
||||
@ -107,7 +109,8 @@ public abstract class LoadingDialog extends AsyncTask<Void, Void, Object> {
|
||||
* If you override this method, you must call
|
||||
* {@code super.onPostExecute(result)} at the entry point of the method.
|
||||
*/
|
||||
protected void onPostExecute(Object result) {
|
||||
@Override
|
||||
protected void onPostExecute(Result result) {
|
||||
doFinish();
|
||||
}// onPostExecute()
|
||||
|
||||
@ -115,6 +118,7 @@ public abstract class LoadingDialog extends AsyncTask<Void, Void, Object> {
|
||||
* If you override this method, you must call {@code super.onCancelled()} at
|
||||
* the entry point of the method.
|
||||
*/
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
doFinish();
|
||||
super.onCancelled();
|
||||
@ -148,9 +152,10 @@ public abstract class LoadingDialog extends AsyncTask<Void, Void, Object> {
|
||||
*
|
||||
* @param delayTime
|
||||
* the delay time to set
|
||||
* @return {@link LoadingDialog}
|
||||
* @return the instance of this dialog, for chaining multiple calls into a
|
||||
* single statement.
|
||||
*/
|
||||
public LoadingDialog setDelayTime(int delayTime) {
|
||||
public LoadingDialog<Params, Progress, Result> setDelayTime(int delayTime) {
|
||||
mDelayTime = delayTime >= 0 ? delayTime : 0;
|
||||
return this;
|
||||
}// setDelayTime()
|
||||
@ -174,4 +179,5 @@ public abstract class LoadingDialog extends AsyncTask<Void, Void, Object> {
|
||||
protected Throwable getLastException() {
|
||||
return mLastException;
|
||||
}// getLastException()
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,11 @@ import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
@ -50,6 +54,12 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
* Used for debugging or something...
|
||||
*/
|
||||
private static final String CLASSNAME = Kp2aFileProvider.class.getName();
|
||||
|
||||
//cache for FileEntry objects to reduce network traffic
|
||||
private HashMap<String, FileEntry> fileEntryMap = new HashMap<String, FileEntry>();
|
||||
//during write operations it is not desired to put entries to the cache. This set indicates which
|
||||
//files cannot be cached currently:
|
||||
private Set<String> cacheBlockedFiles = new HashSet<String>();
|
||||
|
||||
|
||||
@Override
|
||||
@ -75,12 +85,16 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
Log.d(CLASSNAME, "delete() >> " + uri);
|
||||
|
||||
int count = 0;
|
||||
|
||||
|
||||
|
||||
switch (URI_MATCHER.match(uri)) {
|
||||
case URI_FILE: {
|
||||
boolean isRecursive = ProviderUtils.getBooleanQueryParam(uri,
|
||||
BaseFile.PARAM_RECURSIVE, true);
|
||||
String filename = extractFile(uri);
|
||||
removeFromCache(filename, isRecursive);
|
||||
blockFromCache(filename);
|
||||
if (deletePath(filename, isRecursive))
|
||||
{
|
||||
getContext()
|
||||
@ -96,7 +110,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
.build(), null);
|
||||
count = 1; //success
|
||||
}
|
||||
|
||||
blockFromCache(filename);
|
||||
break;// URI_FILE
|
||||
}
|
||||
|
||||
@ -113,6 +127,10 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
if (Utils.doLog())
|
||||
@ -247,7 +265,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
String fname = getName(parentPath);
|
||||
String fname = getFilenameFromPath(parentPath);
|
||||
|
||||
|
||||
matrixCursor = BaseFileProviderUtils.newBaseFileCursor();
|
||||
@ -291,7 +309,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
return matrixCursor;
|
||||
}// doAnswerApiCommand()
|
||||
|
||||
private String getName(String path) {
|
||||
protected String getFilenameFromPath(String path) {
|
||||
path = removeTrailingSlash(path);
|
||||
int lastSlashPos = path.lastIndexOf("/");
|
||||
//if path is root, return its name. empty is ok
|
||||
@ -365,6 +383,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
break;
|
||||
|
||||
FileEntry f = files.get(i);
|
||||
updateFileEntryCache(f);
|
||||
|
||||
if (Utils.doLog())
|
||||
Log.d(CLASSNAME, "listing " + f.path +" for "+dirName);
|
||||
@ -396,9 +415,9 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
Boolean.toString(hasMoreFiles[0])).build()
|
||||
.toString());
|
||||
newRow.add(dirName);
|
||||
newRow.add(getName(dirName));
|
||||
newRow.add(getFilenameFromPath(dirName));
|
||||
|
||||
Log.d(CLASSNAME, "Returning name " + getName(dirName)+" for " +dirName);
|
||||
Log.d(CLASSNAME, "Returning name " + getFilenameFromPath(dirName)+" for " +dirName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,6 +439,8 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
return matrixCursor;
|
||||
}// doListFiles()
|
||||
|
||||
|
||||
|
||||
private RowBuilder addFileInfo(MatrixCursor matrixCursor, int id,
|
||||
FileEntry f) {
|
||||
int type = !f.isDirectory ? BaseFile.FILE_TYPE_FILE : BaseFile.FILE_TYPE_DIRECTORY;
|
||||
@ -431,7 +452,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
.buildUpon().appendPath(f.path)
|
||||
.build().toString());
|
||||
newRow.add(f.path);
|
||||
newRow.add(getName(f.path));
|
||||
newRow.add(getFilenameFromPath(f.path));
|
||||
newRow.add(f.canRead ? 1 : 0);
|
||||
newRow.add(f.canWrite ? 1 : 0);
|
||||
newRow.add(f.sizeInBytes);
|
||||
@ -440,7 +461,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
newRow.add(f.lastModifiedTime);
|
||||
else
|
||||
newRow.add(null);
|
||||
newRow.add(FileUtils.getResIcon(type, getName(f.path)));
|
||||
newRow.add(FileUtils.getResIcon(type, getFilenameFromPath(f.path)));
|
||||
return newRow;
|
||||
}
|
||||
|
||||
@ -458,9 +479,9 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
|
||||
String filename = extractFile(uri);
|
||||
|
||||
FileEntry f = getFileEntry(filename);
|
||||
FileEntry f = getFileEntryCached(filename);
|
||||
if (f == null)
|
||||
addDeletedFileInfo(matrixCursor, filename);
|
||||
addDeletedFileInfo(matrixCursor, filename);
|
||||
else
|
||||
addFileInfo(matrixCursor, 0, f);
|
||||
|
||||
@ -469,8 +490,60 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
|
||||
|
||||
|
||||
//puts the file entry in the cache for later reuse with retrieveFileInfo
|
||||
private void updateFileEntryCache(FileEntry f) {
|
||||
fileEntryMap.put(f.path, f);
|
||||
}
|
||||
//removes the file entry from the cache (if cached). Should be called whenever the file changes
|
||||
private void removeFromCache(String filename, boolean recursive) {
|
||||
fileEntryMap.remove(filename);
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
Set<String> keys = fileEntryMap.keySet();
|
||||
for (String key: keys)
|
||||
{
|
||||
if (key.startsWith(key))
|
||||
fileEntryMap.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void blockFromCache(String filename) {
|
||||
cacheBlockedFiles.add(filename);
|
||||
}
|
||||
|
||||
private void unblockFromCache(String filename) {
|
||||
cacheBlockedFiles.remove(filename);
|
||||
}
|
||||
|
||||
private void addDeletedFileInfo(MatrixCursor matrixCursor, String filename) {
|
||||
//returns the file entry from the cache if present or queries the concrete provider method to return the file info
|
||||
private FileEntry getFileEntryCached(String filename) {
|
||||
//check if enry is cached:
|
||||
FileEntry cachedEntry = fileEntryMap.get(filename);
|
||||
if (cachedEntry != null)
|
||||
{
|
||||
if (Utils.doLog())
|
||||
Log.d(CLASSNAME, "getFileEntryCached: from cache. " + filename);
|
||||
return cachedEntry;
|
||||
}
|
||||
|
||||
if (Utils.doLog())
|
||||
Log.d(CLASSNAME, "getFileEntryCached: not in cache :-( " + filename);
|
||||
|
||||
|
||||
//it's not -> query the information.
|
||||
FileEntry newEntry = getFileEntry(filename);
|
||||
|
||||
if (!cacheBlockedFiles.contains(filename))
|
||||
updateFileEntryCache(newEntry);
|
||||
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
private void addDeletedFileInfo(MatrixCursor matrixCursor, String filename) {
|
||||
int type = BaseFile.FILE_TYPE_NOT_EXISTED;
|
||||
RowBuilder newRow = matrixCursor.newRow();
|
||||
newRow.add(0);// _ID
|
||||
@ -480,13 +553,13 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
.buildUpon().appendPath(filename)
|
||||
.build().toString());
|
||||
newRow.add(filename);
|
||||
newRow.add(getName(filename));
|
||||
newRow.add(getFilenameFromPath(filename));
|
||||
newRow.add(0);
|
||||
newRow.add(0);
|
||||
newRow.add(0);
|
||||
newRow.add(type);
|
||||
newRow.add(null);
|
||||
newRow.add(FileUtils.getResIcon(type, getName(filename)));
|
||||
newRow.add(FileUtils.getResIcon(type, getFilenameFromPath(filename)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
6237
src/keepass2android/Resources/Resource.designer.cs
generated
6237
src/keepass2android/Resources/Resource.designer.cs
generated
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user