mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-10 16:02:05 -04:00
Refactoring.
This commit is contained in:
parent
d7c0fbe2c3
commit
8ab2b8ca15
85
src/org/kiwix/kiwixmobile/DataModel.java
Normal file
85
src/org/kiwix/kiwixmobile/DataModel.java
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package org.kiwix.kiwixmobile;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
// This items class stores the Data for the ArrayAdapter.
|
||||||
|
// We Have to implement Parcelable, so we can store ArrayLists with this generic type in the Bundle
|
||||||
|
// of onSaveInstanceState() and retrieve it later on in onRestoreInstanceState()
|
||||||
|
public class DataModel implements Parcelable {
|
||||||
|
|
||||||
|
// Interface that must be implemented and provided as a public CREATOR field.
|
||||||
|
// It generates instances of our Parcelable class from a Parcel.
|
||||||
|
public Creator<DataModel> CREATOR = new Creator<DataModel>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataModel createFromParcel(Parcel source) {
|
||||||
|
return new DataModel(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return super.equals(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return super.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataModel[] newArray(int size) {
|
||||||
|
return new DataModel[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private String mTitle;
|
||||||
|
|
||||||
|
private String mPath;
|
||||||
|
|
||||||
|
public DataModel(String title, String path) {
|
||||||
|
mTitle = title;
|
||||||
|
mPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This constructor will be called when this class is generated by a Parcel.
|
||||||
|
// We have to read the previously written Data in this Parcel.
|
||||||
|
public DataModel(Parcel parcel) {
|
||||||
|
String[] data = new String[2];
|
||||||
|
parcel.readStringArray(data);
|
||||||
|
mTitle = data[0];
|
||||||
|
mTitle = data[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return mTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return mPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
// Write the data to the Parcel, so we can restore this Data later on.
|
||||||
|
// It will be restored by the DataModel(Parcel parcel) constructor.
|
||||||
|
dest.writeArray(new String[]{mTitle, mPath});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override equals(Object) so we can compare objects. Specifically, so List#contains() works.
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
boolean isEqual = false;
|
||||||
|
|
||||||
|
if (object != null && object instanceof DataModel) {
|
||||||
|
isEqual = (this.mPath.equals(((DataModel) object).mPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
return isEqual;
|
||||||
|
}
|
||||||
|
}
|
109
src/org/kiwix/kiwixmobile/FileSearch.java
Normal file
109
src/org/kiwix/kiwixmobile/FileSearch.java
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
package org.kiwix.kiwixmobile;
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.Environment;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FilenameFilter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
public class FileSearch {
|
||||||
|
|
||||||
|
// Array of zim file extensions
|
||||||
|
public static final String[] zimFiles = {"zim", "zimaa"};
|
||||||
|
|
||||||
|
// Scan through the file system and find all the files with .zim and .zimaa extensions
|
||||||
|
public ArrayList<DataModel> findFiles() {
|
||||||
|
String directory = new File(
|
||||||
|
Environment.getExternalStorageDirectory().getAbsolutePath()).toString();
|
||||||
|
final List<String> fileList = new ArrayList<String>();
|
||||||
|
FilenameFilter[] filter = new FilenameFilter[zimFiles.length];
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (final String extension : zimFiles) {
|
||||||
|
filter[i] = new FilenameFilter() {
|
||||||
|
public boolean accept(File dir, String name) {
|
||||||
|
return name.endsWith("." + extension);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
File[] foundFiles = listFilesAsArray(new File(directory), filter, -1);
|
||||||
|
for (File f : foundFiles) {
|
||||||
|
fileList.add(f.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
return createDataForAdapter(fileList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<DataModel> sortDataModel(ArrayList<DataModel> data) {
|
||||||
|
|
||||||
|
// Sorting the data in alphabetical order
|
||||||
|
Collections.sort(data, new Comparator<DataModel>() {
|
||||||
|
@Override
|
||||||
|
public int compare(DataModel a, DataModel b) {
|
||||||
|
return a.getTitle().compareToIgnoreCase(b.getTitle());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through the file system
|
||||||
|
private Collection<File> listFiles(File directory, FilenameFilter[] filter, int recurse) {
|
||||||
|
|
||||||
|
Vector<File> files = new Vector<File>();
|
||||||
|
|
||||||
|
File[] entries = directory.listFiles();
|
||||||
|
|
||||||
|
if (entries != null) {
|
||||||
|
for (File entry : entries) {
|
||||||
|
for (FilenameFilter filefilter : filter) {
|
||||||
|
if (filter == null || filefilter.accept(directory, entry.getName())) {
|
||||||
|
files.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((recurse <= -1) || (recurse > 0 && entry.isDirectory())) {
|
||||||
|
recurse--;
|
||||||
|
files.addAll(listFiles(entry, filter, recurse));
|
||||||
|
recurse++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File[] listFilesAsArray(File directory, FilenameFilter[] filter, int recurse) {
|
||||||
|
Collection<File> files = listFiles(directory, filter, recurse);
|
||||||
|
|
||||||
|
File[] arr = new File[files.size()];
|
||||||
|
return files.toArray(arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an ArrayList with our DataModel
|
||||||
|
private ArrayList<DataModel> createDataForAdapter(List<String> list) {
|
||||||
|
|
||||||
|
ArrayList<DataModel> data = new ArrayList<DataModel>();
|
||||||
|
for (String file : list) {
|
||||||
|
|
||||||
|
data.add(new DataModel(getTitleFromFilePath(file), file));
|
||||||
|
}
|
||||||
|
|
||||||
|
data = sortDataModel(data);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the file path and the extension and return a file name for the given file path
|
||||||
|
private String getTitleFromFilePath(String path) {
|
||||||
|
return new File(path).getName().replaceFirst("[.][^.]+$", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -16,23 +16,23 @@ public class FileWriter {
|
|||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
private ArrayList<ZimFileSelectActivity.DataModel> mDataList;
|
private ArrayList<DataModel> mDataList;
|
||||||
|
|
||||||
public FileWriter(Context context) {
|
public FileWriter(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileWriter(Context context, ArrayList<ZimFileSelectActivity.DataModel> dataList) {
|
public FileWriter(Context context, ArrayList<DataModel> dataList) {
|
||||||
mDataList = dataList;
|
mDataList = dataList;
|
||||||
mContext = context;
|
mContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a CSV list from the file paths
|
// Build a CSV list from the file paths
|
||||||
public void saveArray(ArrayList<ZimFileSelectActivity.DataModel> files) {
|
public void saveArray(ArrayList<DataModel> files) {
|
||||||
|
|
||||||
ArrayList<String> list = new ArrayList<String>();
|
ArrayList<String> list = new ArrayList<String>();
|
||||||
|
|
||||||
for (ZimFileSelectActivity.DataModel file : files) {
|
for (DataModel file : files) {
|
||||||
list.add(file.getPath());
|
list.add(file.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,12 +48,12 @@ public class FileWriter {
|
|||||||
// Add items to the MediaStore list, that are not in the MediaStore database.
|
// Add items to the MediaStore list, that are not in the MediaStore database.
|
||||||
// These will be loaded from a previously saved CSV file.
|
// These will be loaded from a previously saved CSV file.
|
||||||
// We are checking, if these file still exist as well.
|
// We are checking, if these file still exist as well.
|
||||||
public ArrayList<ZimFileSelectActivity.DataModel> getDataModelList() {
|
public ArrayList<DataModel> getDataModelList() {
|
||||||
|
|
||||||
for (String file : readCsv()) {
|
for (String file : readCsv()) {
|
||||||
if (!mDataList.contains(new ZimFileSelectActivity.DataModel(getTitleFromFilePath(file), file))) {
|
if (!mDataList.contains(new DataModel(getTitleFromFilePath(file), file))) {
|
||||||
Log.i("kiwix", "Added file: " + file);
|
Log.i("kiwix", "Added file: " + file);
|
||||||
mDataList.add(new ZimFileSelectActivity.DataModel(getTitleFromFilePath(file), file));
|
mDataList.add(new DataModel(getTitleFromFilePath(file), file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,13 +3,9 @@ package org.kiwix.kiwixmobile;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.media.MediaScannerConnection;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.support.v4.app.LoaderManager;
|
import android.support.v4.app.LoaderManager;
|
||||||
@ -31,22 +27,14 @@ import android.widget.ProgressBar;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FilenameFilter;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
public class ZimFileSelectActivity extends FragmentActivity
|
public class ZimFileSelectActivity extends FragmentActivity
|
||||||
implements LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener {
|
implements LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener {
|
||||||
|
|
||||||
private static final int LOADER_ID = 0x02;
|
private static final int LOADER_ID = 0x02;
|
||||||
|
|
||||||
// Array of zim file extensions
|
|
||||||
private static final String[] zimFiles = {"zim", "zimaa"};
|
|
||||||
|
|
||||||
// Adapter of the Data populated by the MediaStore
|
// Adapter of the Data populated by the MediaStore
|
||||||
private SimpleCursorAdapter mCursorAdapter;
|
private SimpleCursorAdapter mCursorAdapter;
|
||||||
|
|
||||||
@ -61,10 +49,6 @@ public class ZimFileSelectActivity extends FragmentActivity
|
|||||||
|
|
||||||
private TextView mProgressBarMessage;
|
private TextView mProgressBarMessage;
|
||||||
|
|
||||||
private boolean mNeedsUpdate = false;
|
|
||||||
|
|
||||||
private boolean mAdapterRefreshed = false;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@ -72,64 +56,11 @@ public class ZimFileSelectActivity extends FragmentActivity
|
|||||||
|
|
||||||
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
|
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
|
||||||
mProgressBarMessage = (TextView) findViewById(R.id.progressbar_message);
|
mProgressBarMessage = (TextView) findViewById(R.id.progressbar_message);
|
||||||
|
|
||||||
mProgressBar.setVisibility(View.VISIBLE);
|
mProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
mZimFileList = (ListView) findViewById(R.id.zimfilelist);
|
mZimFileList = (ListView) findViewById(R.id.zimfilelist);
|
||||||
mFiles = new ArrayList<DataModel>();
|
mFiles = new ArrayList<DataModel>();
|
||||||
|
|
||||||
selectZimFile();
|
startQuery();
|
||||||
}
|
|
||||||
|
|
||||||
private void finishResult(String path) {
|
|
||||||
// Add new files to MediaStore
|
|
||||||
addDataToMediaStore(mFiles);
|
|
||||||
// Remove the nonexistent files from the MediaStore
|
|
||||||
removeNonExistentFiles(mCursorAdapter.getCursor());
|
|
||||||
if (path != null) {
|
|
||||||
File file = new File(path);
|
|
||||||
Uri uri = Uri.fromFile(file);
|
|
||||||
Log.i("kiwix", "Opening " + uri);
|
|
||||||
setResult(RESULT_OK, new Intent().setData(uri));
|
|
||||||
finish();
|
|
||||||
} else {
|
|
||||||
setResult(RESULT_CANCELED);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void selectZimFile() {
|
|
||||||
|
|
||||||
// Stop endless loops
|
|
||||||
if (mAdapterRefreshed) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
mAdapterRefreshed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines a list of columns to retrieve from the Cursor and load into an output row
|
|
||||||
String[] mZimListColumns = {MediaStore.Files.FileColumns.TITLE, MediaStore.Files.FileColumns.DATA};
|
|
||||||
|
|
||||||
// Defines a list of View IDs that will receive the Cursor columns for each row
|
|
||||||
int[] mZimListItems = {android.R.id.text1, android.R.id.text2};
|
|
||||||
|
|
||||||
mCursorAdapter = new SimpleCursorAdapter(
|
|
||||||
// The Context object
|
|
||||||
ZimFileSelectActivity.this,
|
|
||||||
// A layout in XML for one row in the ListView
|
|
||||||
android.R.layout.simple_list_item_2,
|
|
||||||
// The cursor, swapped later by cursorloader
|
|
||||||
null,
|
|
||||||
// A string array of column names in the cursor
|
|
||||||
mZimListColumns,
|
|
||||||
// An integer array of view IDs in the row layout
|
|
||||||
mZimListItems,
|
|
||||||
// Flags for the Adapter
|
|
||||||
Adapter.NO_SELECTION);
|
|
||||||
|
|
||||||
mZimFileList.setOnItemClickListener(this);
|
|
||||||
|
|
||||||
getSupportLoaderManager().initLoader(LOADER_ID, null, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -150,9 +81,9 @@ public class ZimFileSelectActivity extends FragmentActivity
|
|||||||
String query = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
|
String query = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
|
||||||
+ MediaStore.Files.FileColumns.MEDIA_TYPE_NONE + " AND"
|
+ MediaStore.Files.FileColumns.MEDIA_TYPE_NONE + " AND"
|
||||||
+ " ( LOWER(" +
|
+ " ( LOWER(" +
|
||||||
MediaStore.Images.Media.DATA + ") LIKE '%." + zimFiles[0] + "'"
|
MediaStore.Images.Media.DATA + ") LIKE '%." + FileSearch.zimFiles[0] + "'"
|
||||||
+ " OR LOWER(" +
|
+ " OR LOWER(" +
|
||||||
MediaStore.Images.Media.DATA + ") LIKE '%." + zimFiles[1] + "'"
|
MediaStore.Images.Media.DATA + ") LIKE '%." + FileSearch.zimFiles[1] + "'"
|
||||||
+ " ) ";
|
+ " ) ";
|
||||||
|
|
||||||
String[] selectionArgs = null; // There is no ? in query so null here
|
String[] selectionArgs = null; // There is no ? in query so null here
|
||||||
@ -181,98 +112,6 @@ public class ZimFileSelectActivity extends FragmentActivity
|
|||||||
mCursorAdapter.notifyDataSetChanged();
|
mCursorAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the data of our cursor and wrap it all in our ArrayAdapter.
|
|
||||||
// We are doing this because the CursorAdapter does not allow us do remove rows from its dataset.
|
|
||||||
private RescanDataAdapter buildArrayAdapter(Cursor cursor) {
|
|
||||||
|
|
||||||
ArrayList<DataModel> files = new ArrayList<DataModel>();
|
|
||||||
|
|
||||||
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
|
|
||||||
|
|
||||||
if (new File(cursor.getString(2)).exists()) {
|
|
||||||
files.add(new DataModel(cursor.getString(1), cursor.getString(2)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
files = new FileWriter(ZimFileSelectActivity.this, files).getDataModelList();
|
|
||||||
|
|
||||||
for (int i = 0; i < files.size(); i++) {
|
|
||||||
|
|
||||||
if (!new File(files.get(i).getPath()).exists()) {
|
|
||||||
Log.e("kiwix", "File removed: " + files.get(i).getTitle());
|
|
||||||
files.remove(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
files = sortDataModel(files);
|
|
||||||
mFiles = files;
|
|
||||||
|
|
||||||
return new RescanDataAdapter(ZimFileSelectActivity.this, 0, mFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect to the MediaScannerConnection service and scan all the files, that are returned to us by
|
|
||||||
// our MediaStore query. The file will ideally get removed from the MediaStore,
|
|
||||||
// if the scan resturns null and our CursorAdapter will update.
|
|
||||||
private void removeNonExistentFiles(Cursor cursor) {
|
|
||||||
|
|
||||||
ArrayList<String> files = new ArrayList<String>();
|
|
||||||
|
|
||||||
// Iterate trough the data from our curser and add every file path column to an ArrayList
|
|
||||||
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
|
|
||||||
files.add(cursor.getString(2));
|
|
||||||
}
|
|
||||||
updateMediaStore(files);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new files to the MediaStore
|
|
||||||
private void addDataToMediaStore(ArrayList<DataModel> files) {
|
|
||||||
|
|
||||||
ArrayList<String> paths = new ArrayList<String>();
|
|
||||||
|
|
||||||
for (DataModel file : files) {
|
|
||||||
paths.add(file.getPath());
|
|
||||||
}
|
|
||||||
updateMediaStore(paths);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateMediaStore(ArrayList<String> files) {
|
|
||||||
|
|
||||||
// Abort endless loops. Let this update process only run on rescan.
|
|
||||||
if (!mNeedsUpdate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.i("kiwix", "Updating MediaStore");
|
|
||||||
|
|
||||||
// Scan every file (and delete it from the MediaStore, if it does not exist)
|
|
||||||
MediaScannerConnection.scanFile(
|
|
||||||
ZimFileSelectActivity.this,
|
|
||||||
files.toArray(new String[files.size()]),
|
|
||||||
null,
|
|
||||||
new MediaScannerConnection.OnScanCompletedListener() {
|
|
||||||
@Override
|
|
||||||
public void onScanCompleted(String path, Uri uri) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mNeedsUpdate = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<DataModel> sortDataModel(ArrayList<DataModel> data) {
|
|
||||||
|
|
||||||
// Sorting the data in alphabetical order
|
|
||||||
Collections.sort(data, new Comparator<DataModel>() {
|
|
||||||
@Override
|
|
||||||
public int compare(DataModel a, DataModel b) {
|
|
||||||
return a.getTitle().compareToIgnoreCase(b.getTitle());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoaderReset(Loader<Cursor> cursorLoader) {
|
public void onLoaderReset(Loader<Cursor> cursorLoader) {
|
||||||
mCursorAdapter.swapCursor(null);
|
mCursorAdapter.swapCursor(null);
|
||||||
@ -320,7 +159,6 @@ public class ZimFileSelectActivity extends FragmentActivity
|
|||||||
|
|
||||||
// Make sure, that we set mNeedsUpdate to true and to false, after the MediaStore has been
|
// Make sure, that we set mNeedsUpdate to true and to false, after the MediaStore has been
|
||||||
// updated. Otherwise it will result in a endless loop.
|
// updated. Otherwise it will result in a endless loop.
|
||||||
mNeedsUpdate = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
@ -349,193 +187,75 @@ public class ZimFileSelectActivity extends FragmentActivity
|
|||||||
finishResult(file);
|
finishResult(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This items class stores the Data for the ArrayAdapter.
|
// Query through the MediaStore
|
||||||
// We Have to implement Parcelable, so we can store ArrayLists with this generic type in the Bundle
|
protected void startQuery() {
|
||||||
// of onSaveInstanceState() and retrieve it later on in onRestoreInstanceState()
|
|
||||||
public static class DataModel implements Parcelable {
|
|
||||||
|
|
||||||
// Interface that must be implemented and provided as a public CREATOR field.
|
// Defines a list of columns to retrieve from the Cursor and load into an output row
|
||||||
// It generates instances of our Parcelable class from a Parcel.
|
String[] mZimListColumns = {MediaStore.Files.FileColumns.TITLE, MediaStore.Files.FileColumns.DATA};
|
||||||
public Parcelable.Creator<DataModel> CREATOR = new Parcelable.Creator<DataModel>() {
|
|
||||||
|
|
||||||
@Override
|
// Defines a list of View IDs that will receive the Cursor columns for each row
|
||||||
public DataModel createFromParcel(Parcel source) {
|
int[] mZimListItems = {android.R.id.text1, android.R.id.text2};
|
||||||
return new DataModel(source);
|
|
||||||
|
mCursorAdapter = new SimpleCursorAdapter(
|
||||||
|
// The Context object
|
||||||
|
ZimFileSelectActivity.this,
|
||||||
|
// A layout in XML for one row in the ListView
|
||||||
|
android.R.layout.simple_list_item_2,
|
||||||
|
// The cursor, swapped later by cursorloader
|
||||||
|
null,
|
||||||
|
// A string array of column names in the cursor
|
||||||
|
mZimListColumns,
|
||||||
|
// An integer array of view IDs in the row layout
|
||||||
|
mZimListItems,
|
||||||
|
// Flags for the Adapter
|
||||||
|
Adapter.NO_SELECTION);
|
||||||
|
|
||||||
|
mZimFileList.setOnItemClickListener(this);
|
||||||
|
|
||||||
|
getSupportLoaderManager().initLoader(LOADER_ID, null, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// Get the data of our cursor and wrap it all in our ArrayAdapter.
|
||||||
public boolean equals(Object o) {
|
// We are doing this because the CursorAdapter does not allow us do remove rows from its dataset.
|
||||||
return super.equals(o);
|
private RescanDataAdapter buildArrayAdapter(Cursor cursor) {
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
ArrayList<DataModel> files = new ArrayList<DataModel>();
|
||||||
public int hashCode() {
|
|
||||||
return super.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
|
||||||
public DataModel[] newArray(int size) {
|
|
||||||
return new DataModel[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private String mTitle;
|
if (new File(cursor.getString(2)).exists()) {
|
||||||
|
files.add(new DataModel(cursor.getString(1), cursor.getString(2)));
|
||||||
private String mPath;
|
|
||||||
|
|
||||||
public DataModel(String title, String path) {
|
|
||||||
mTitle = title;
|
|
||||||
mPath = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This constructor will be called when this class is generated by a Parcel.
|
|
||||||
// We have to read the previously written Data in this Parcel.
|
|
||||||
public DataModel(Parcel parcel) {
|
|
||||||
String[] data = new String[2];
|
|
||||||
parcel.readStringArray(data);
|
|
||||||
mTitle = data[0];
|
|
||||||
mTitle = data[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return mTitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPath() {
|
|
||||||
return mPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
// Write the data to the Parcel, so we can restore this Data later on.
|
|
||||||
// It will be restored by the DataModel(Parcel parcel) constructor.
|
|
||||||
dest.writeArray(new String[]{mTitle, mPath});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override equals(Object) so we can compare objects. Specifically, so List#contains() works.
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object object) {
|
|
||||||
boolean isEqual = false;
|
|
||||||
|
|
||||||
if (object != null && object instanceof DataModel) {
|
|
||||||
isEqual = (this.mPath.equals(((DataModel) object).mPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
return isEqual;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This AsyncTask will scan the file system for files with the Extension ".zim" or ".zimaa"
|
files = new FileWriter(ZimFileSelectActivity.this, files).getDataModelList();
|
||||||
private class RescanFileSystem extends AsyncTask<Void, Void, Void> {
|
|
||||||
|
|
||||||
@Override
|
for (int i = 0; i < files.size(); i++) {
|
||||||
protected void onPreExecute() {
|
|
||||||
|
|
||||||
mProgressBarMessage.setVisibility(View.VISIBLE);
|
if (!new File(files.get(i).getPath()).exists()) {
|
||||||
mProgressBar.setVisibility(View.VISIBLE);
|
Log.e("kiwix", "File removed: " + files.get(i).getTitle());
|
||||||
|
files.remove(i);
|
||||||
super.onPreExecute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... params) {
|
|
||||||
|
|
||||||
mFiles = FindFiles();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Void result) {
|
|
||||||
mRescanAdapter = new RescanDataAdapter(ZimFileSelectActivity.this, 0, mFiles);
|
|
||||||
|
|
||||||
mZimFileList.setAdapter(mRescanAdapter);
|
|
||||||
|
|
||||||
mProgressBarMessage.setVisibility(View.GONE);
|
|
||||||
mProgressBar.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
new FileWriter(ZimFileSelectActivity.this).saveArray(mFiles);
|
|
||||||
|
|
||||||
super.onPostExecute(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan through the file system and find all the files with .zim and .zimaa extensions
|
|
||||||
private ArrayList<DataModel> FindFiles() {
|
|
||||||
String directory = new File(
|
|
||||||
Environment.getExternalStorageDirectory().getAbsolutePath()).toString();
|
|
||||||
final List<String> fileList = new ArrayList<String>();
|
|
||||||
FilenameFilter[] filter = new FilenameFilter[zimFiles.length];
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (final String extension : zimFiles) {
|
|
||||||
filter[i] = new FilenameFilter() {
|
|
||||||
public boolean accept(File dir, String name) {
|
|
||||||
return name.endsWith("." + extension);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
File[] foundFiles = listFilesAsArray(new File(directory), filter, -1);
|
|
||||||
for (File f : foundFiles) {
|
|
||||||
fileList.add(f.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
return createDataForAdapter(fileList);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Collection<File> listFiles(File directory, FilenameFilter[] filter,
|
|
||||||
int recurse) {
|
|
||||||
|
|
||||||
Vector<File> files = new Vector<File>();
|
|
||||||
|
|
||||||
File[] entries = directory.listFiles();
|
|
||||||
|
|
||||||
if (entries != null) {
|
|
||||||
for (File entry : entries) {
|
|
||||||
for (FilenameFilter filefilter : filter) {
|
|
||||||
if (filter == null || filefilter.accept(directory, entry.getName())) {
|
|
||||||
files.add(entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((recurse <= -1) || (recurse > 0 && entry.isDirectory())) {
|
|
||||||
recurse--;
|
files = new FileSearch().sortDataModel(files);
|
||||||
files.addAll(listFiles(entry, filter, recurse));
|
mFiles = files;
|
||||||
recurse++;
|
|
||||||
}
|
return new RescanDataAdapter(ZimFileSelectActivity.this, 0, mFiles);
|
||||||
}
|
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public File[] listFilesAsArray(File directory, FilenameFilter[] filter, int recurse) {
|
// Get the selected file and return the result to the Activity, that called this Activity
|
||||||
Collection<File> files = listFiles(directory, filter, recurse);
|
private void finishResult(String path) {
|
||||||
|
|
||||||
File[] arr = new File[files.size()];
|
if (path != null) {
|
||||||
return files.toArray(arr);
|
File file = new File(path);
|
||||||
}
|
Uri uri = Uri.fromFile(file);
|
||||||
|
Log.i("kiwix", "Opening " + uri);
|
||||||
// Create an ArrayList with our DataModel
|
setResult(RESULT_OK, new Intent().setData(uri));
|
||||||
private ArrayList<DataModel> createDataForAdapter(List<String> list) {
|
finish();
|
||||||
|
} else {
|
||||||
ArrayList<DataModel> data = new ArrayList<DataModel>();
|
setResult(RESULT_CANCELED);
|
||||||
for (String file : list) {
|
finish();
|
||||||
|
|
||||||
data.add(new DataModel(getTitleFromFilePath(file), file));
|
|
||||||
}
|
|
||||||
|
|
||||||
data = sortDataModel(data);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the file path and the extension and return a file name for the given file path
|
|
||||||
private String getTitleFromFilePath(String path) {
|
|
||||||
return new File(path).getName().replaceFirst("[.][^.]+$", "");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,4 +296,39 @@ public class ZimFileSelectActivity extends FragmentActivity
|
|||||||
TextView path;
|
TextView path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This AsyncTask will scan the file system for files with the Extension ".zim" or ".zimaa"
|
||||||
|
private class RescanFileSystem extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
|
||||||
|
mProgressBarMessage.setVisibility(View.VISIBLE);
|
||||||
|
mProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
super.onPreExecute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
|
||||||
|
mFiles = new FileSearch().findFiles();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
mRescanAdapter = new RescanDataAdapter(ZimFileSelectActivity.this, 0, mFiles);
|
||||||
|
|
||||||
|
mZimFileList.setAdapter(mRescanAdapter);
|
||||||
|
|
||||||
|
mProgressBarMessage.setVisibility(View.GONE);
|
||||||
|
mProgressBar.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
new FileWriter(ZimFileSelectActivity.this).saveArray(mFiles);
|
||||||
|
|
||||||
|
super.onPostExecute(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user