From 5c7f7588af2e56f37f14d011fd4fd12711baca0d Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Wed, 10 Jun 2015 23:26:31 +0300 Subject: implement directory sync properly using a service move all database-related crap to databasehelper which is now a singleton --- org.fox.ttcomics/src/main/AndroidManifest.xml | 5 +- .../java/org/fox/ttcomics2/ComicListFragment.java | 182 +++-------- .../main/java/org/fox/ttcomics2/ComicPager.java | 2 +- .../java/org/fox/ttcomics2/CommonActivity.java | 254 ++-------------- .../java/org/fox/ttcomics2/DatabaseHelper.java | 338 ++++++++++++++++++++- .../main/java/org/fox/ttcomics2/MainActivity.java | 136 +++------ .../java/org/fox/ttcomics2/PositionGetService.java | 119 ++++++++ .../java/org/fox/ttcomics2/ViewComicActivity.java | 6 +- 8 files changed, 572 insertions(+), 470 deletions(-) create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/PositionGetService.java (limited to 'org.fox.ttcomics') diff --git a/org.fox.ttcomics/src/main/AndroidManifest.xml b/org.fox.ttcomics/src/main/AndroidManifest.xml index 9c7265b..fa2eb12 100755 --- a/org.fox.ttcomics/src/main/AndroidManifest.xml +++ b/org.fox.ttcomics/src/main/AndroidManifest.xml @@ -24,7 +24,6 @@ android:label="@string/title_activity_main" > - @@ -63,6 +62,10 @@ android:excludeFromRecents="true" android:finishOnTaskLaunch="true" /> + + \ No newline at end of file diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicListFragment.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicListFragment.java index ceb0d9b..5d58a5b 100644 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicListFragment.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicListFragment.java @@ -4,9 +4,7 @@ import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; -import android.database.SQLException; import android.graphics.Bitmap; -import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; import android.provider.BaseColumns; @@ -37,16 +35,13 @@ import com.nostra13.universalimageloader.core.process.BitmapProcessor; import com.shamanland.fab.FloatingActionButton; import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; import jp.co.recruit_mp.android.widget.HeaderFooterGridView; public class ComicListFragment extends Fragment implements OnItemClickListener { private final String TAG = this.getClass().getSimpleName(); - private final static int SIZE_DIR = -100; + protected final static int SIZE_DIR = -100; // corresponds to tab indexes private final static int MODE_ALL = 0; @@ -222,7 +217,7 @@ public class ComicListFragment extends Fragment implements OnItemClickListener { } } - File thumbnailFile = new File(m_activity.getCacheFileName(firstChild != null ? firstChild : filePath + "/" + fileBaseName)); + File thumbnailFile = new File(CommonActivity.getCacheFileName(m_activity, firstChild != null ? firstChild : filePath + "/" + fileBaseName)); if (holder.thumbnail != null && thumbnailFile != null && thumbnailFile.exists()) { @@ -354,17 +349,19 @@ public class ComicListFragment extends Fragment implements OnItemClickListener { case R.id.menu_reset_progress: if (fileName != null) { m_activity.resetProgress(fileName); - m_adapter.notifyDataSetChanged(); } return true; case R.id.menu_mark_as_read: if (fileName != null) { - m_activity.setLastPosition(fileName, m_activity.getSize(fileName)-1); - m_adapter.notifyDataSetChanged(); + + m_activity.m_databaseHelper.setLastPosition(fileName, + m_activity.m_databaseHelper.getSize(fileName) - 1); + + updateWithoutRescan(); } - return true; + return true; default: Log.d(TAG, "onContextItemSelected, unhandled id=" + item.getItemId()); return super.onContextItemSelected(item); @@ -372,160 +369,71 @@ public class ComicListFragment extends Fragment implements OnItemClickListener { } private Cursor createCursor() { - String baseDir = m_baseDirectory.length() == 0 ? m_prefs.getString("comics_directory", "") : m_baseDirectory; - String selection; String selectionArgs[]; - + switch (m_mode) { case MODE_READ: selection = "path = ? AND position = size - 1"; - selectionArgs = new String[] { baseDir }; + selectionArgs = new String[] { m_baseDirectory }; break; case MODE_UNFINISHED: selection = "path = ? AND position < size AND position > 0 AND position != size - 1"; - selectionArgs = new String[] { baseDir }; + selectionArgs = new String[] { m_baseDirectory }; break; case MODE_UNREAD: selection = "path = ? AND position = 0 AND size != ?"; - selectionArgs = new String[] { baseDir, String.valueOf(SIZE_DIR) }; + selectionArgs = new String[] { m_baseDirectory, String.valueOf(SIZE_DIR) }; break; default: selection = "path = ?"; - selectionArgs = new String[] { baseDir }; + selectionArgs = new String[] { m_baseDirectory }; } - return m_activity.getReadableDb().query("comics_cache", new String[] { BaseColumns._ID, "filename", "path", "position", "size", - "(SELECT path || '/' || filename FROM comics_cache AS t2 WHERE t2.path = comics_cache.path || '/' || comics_cache.filename AND filename != '' ORDER BY filename LIMIT 1) AS firstchild" }, - selection, selectionArgs, null, null, "size != " + SIZE_DIR + ", filename, size = " + SIZE_DIR + ", filename"); + return m_activity + .m_databaseHelper + .getReadableDatabase() + .query("comics_cache", new String[]{BaseColumns._ID, "filename", "path", "position", "size", + "(SELECT path || '/' || filename FROM comics_cache AS t2 WHERE t2.path = comics_cache.path || '/' " + + "|| comics_cache.filename AND filename != '' ORDER BY filename LIMIT 1) AS firstchild"}, + selection, selectionArgs, null, null, "size != " + SIZE_DIR + ", filename, size = " + SIZE_DIR + ", filename"); } - + @Override public void onAttach(Activity activity) { super.onAttach(activity); - + m_activity = (MainActivity)activity; - + m_prefs = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext()); } - + protected void rescan(final boolean fullRescan) { - AsyncTask rescanTask = new AsyncTask() { + if (m_swipeLayout != null) m_swipeLayout.setRefreshing(true); + + m_activity.m_databaseHelper.rescanDirectory(m_baseDirectory, fullRescan, new DatabaseHelper.DirectoryScanListener() { @Override - protected void onProgressUpdate(Integer... progress) { - if (isAdded()) { - m_activity.setProgress(Math.round(((float)progress[0] / (float)progress[1]) * 10000)); - } - } - - @Override - protected Integer doInBackground(String... params) { - String comicsDir = params[0]; - - File dir = new File(comicsDir); - - int fileIndex = 0; - - if (dir.isDirectory()) { - File archives[] = dir.listFiles(); - - java.util.Arrays.sort(archives); - - for (File archive : archives) { - String filePath = archive.getAbsolutePath(); - - if (archive.isDirectory()) { - m_activity.setSize(filePath, SIZE_DIR); - - } else if (archive.getName().toLowerCase().matches(".*\\.(cbz|zip)") && isAdded() && m_activity != null && - m_activity.getWritableDb() != null && m_activity.getWritableDb().isOpen()) { - try { - int size = m_activity.getSize(filePath); - - if (size == -1 || fullRescan) { - - ComicArchive cba = null; - - if (archive.getName().toLowerCase().matches(".*\\.(cbz|zip)")) { - cba = new CbzComicArchive(filePath); - } - - if (cba != null && cba.getCount() > 0) { - // Get cover - - try { - File thumbnailFile = new File(m_activity.getCacheFileName(filePath)); - - if (m_activity.isStorageWritable() && (!thumbnailFile.exists() || fullRescan)) { - InputStream is = cba.getItem(0); - - if (is != null) { - FileOutputStream fos = new FileOutputStream(thumbnailFile); - - byte[] buffer = new byte[1024]; - int len; - while ((len = is.read(buffer)) != -1) { - fos.write(buffer, 0, len); - } - - fos.close(); - is.close(); - } - } - - } catch (IOException e) { - e.printStackTrace(); - } - - size = cba.getCount(); - - m_activity.setSize(filePath, size); - } - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - ++fileIndex; - - publishProgress(Integer.valueOf(fileIndex), Integer.valueOf(archives.length)); - } - } - - if (isAdded() && m_activity != null) { - m_activity.cleanupCache(false); - m_activity.cleanupSqliteCache(comicsDir); - } - - return fileIndex; //m_files.size(); + public void onProgressUpdate(int progress, int max) { + // } - + @Override - protected void onPostExecute(Integer result) { - if (isAdded() && m_adapter != null) { - m_adapter.changeCursor(createCursor()); - //m_animationAdapter.reset(); - m_adapter.notifyDataSetChanged(); + public void onPostExecute(int result) { + try { + m_activity.cleanupCache(false); - if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false); - } - } - }; - - String comicsDir = m_prefs.getString("comics_directory", null); + if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false); - if (comicsDir != null && m_activity.isStorageAvailable()) { - if (m_swipeLayout != null) m_swipeLayout.setRefreshing(true); + updateWithoutRescan(); - rescanTask.execute(m_baseDirectory.length() > 0 ? m_baseDirectory : comicsDir); - } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); } - + @Override public void onResume() { super.onResume(); @@ -535,10 +443,10 @@ public class ComicListFragment extends Fragment implements OnItemClickListener { } String comicsDir = m_prefs.getString("comics_directory", ""); - - if (m_activity.getCachedItemCount(m_baseDirectory.length() > 0 ? m_baseDirectory : comicsDir) == 0) { - rescan(false); - } else { + + if (m_activity.m_databaseHelper.getCachedItemCount(m_baseDirectory) == 0) { + rescan(false); + } else { updateWithoutRescan(); } diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java index e0e3e68..11f0d33 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java @@ -128,7 +128,7 @@ public class ComicPager extends Fragment { m_archive = new CbzComicArchive(m_fileName); } - final int position = m_activity.getLastPosition(m_fileName); + final int position = m_activity.m_databaseHelper.getLastPosition(m_fileName); m_currentPage = (TextView) view.findViewById(R.id.comics_page); m_totalPages = (TextView) view.findViewById(R.id.comics_total_pages); diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/CommonActivity.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/CommonActivity.java index c268590..cc63307 100644 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/CommonActivity.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/CommonActivity.java @@ -3,15 +3,12 @@ package org.fox.ttcomics2; import android.accounts.Account; import android.accounts.AccountManager; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteStatement; import android.os.Bundle; import android.os.Environment; import android.preference.PreferenceManager; -import android.provider.BaseColumns; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.MenuItem; @@ -39,17 +36,15 @@ public class CommonActivity extends AppCompatActivity { protected SharedPreferences m_prefs; protected SyncClient m_syncClient = new SyncClient(); - private boolean m_storageAvailable; - private boolean m_storageWritable; + protected DatabaseHelper m_databaseHelper; - private SQLiteDatabase m_readableDb; - private SQLiteDatabase m_writableDb; - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (!ImageLoader.getInstance().isInited()) { + m_databaseHelper = DatabaseHelper.getInstance(this); + + if (!ImageLoader.getInstance().isInited()) { DisplayImageOptions options = new DisplayImageOptions.Builder() .cacheInMemory(true) @@ -67,33 +62,19 @@ public class CommonActivity extends AppCompatActivity { m_prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - initDatabase(); initSync(); } @Override public void onResume() { super.onResume(); - - String state = Environment.getExternalStorageState(); - - if (Environment.MEDIA_MOUNTED.equals(state)) { - m_storageAvailable = true; - m_storageWritable = true; - } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { - m_storageAvailable = true; - m_storageWritable = false; - } else { - m_storageAvailable = false; - m_storageWritable = false; - } - + initSync(); } private void initSync() { if (m_prefs.getBoolean("use_position_sync", false)) { - String googleAccount = getGoogleAccount(); + String googleAccount = getGoogleAccount(this); if (googleAccount != null) { m_syncClient.setOwner(googleAccount); @@ -120,167 +101,9 @@ public class CommonActivity extends AppCompatActivity { // } - public Cursor findComicByFileName(String fileName) { - File file = new File(fileName); - - Cursor c = getReadableDb().query("comics_cache", null, - "filename = ? AND path = ?", - new String[]{file.getName(), file.getParentFile().getAbsolutePath()}, null, null, null); - - if (c.moveToFirst()) { - return c; - } else { - c.close(); - - SQLiteStatement stmt = getWritableDb().compileStatement("INSERT INTO comics_cache " + - "(filename, path, position, max_position, size, checksum) VALUES (?, ?, 0, 0, -1, '')"); - stmt.bindString(1, file.getName()); - stmt.bindString(2, file.getParentFile().getAbsolutePath()); - stmt.execute(); - - c = getReadableDb().query("comics_cache", null, - "filename = ? AND path = ?", - new String[] { file.getName(), file.getParentFile().getAbsolutePath() }, null, null, null); - - if (c.moveToFirst()) { - return c; - } else { - c.close(); - } - } - - return null; - } - - public void setSize(String fileName, int size) { - Cursor c = findComicByFileName(fileName); - - if (c != null) { - c.close(); - - File file = new File(fileName); - - SQLiteStatement stmt = getWritableDb().compileStatement("UPDATE comics_cache SET size = ? WHERE filename = ? AND path = ?"); - stmt.bindLong(1, size); - stmt.bindString(2, file.getName()); - stmt.bindString(3, file.getParentFile().getAbsolutePath()); - stmt.execute(); - stmt.close(); - } - } - - public void setLastPosition(String fileName, int position) { - int lastPosition = getLastPosition(fileName); - - Cursor c = findComicByFileName(fileName); - - if (c != null) { - c.close(); - - File file = new File(fileName); - - SQLiteStatement stmt = getWritableDb().compileStatement("UPDATE comics_cache SET position = ?, max_position = ? WHERE filename = ? AND path = ?"); - stmt.bindLong(1, position); - stmt.bindLong(2, Math.max(position, lastPosition)); - stmt.bindString(3, file.getName()); - stmt.bindString(4, file.getParentFile().getAbsolutePath()); - stmt.execute(); - stmt.close(); - } - - } - - public void setLastMaxPosition(String fileName, int position) { - - Cursor c = findComicByFileName(fileName); - - if (c != null) { - c.close(); - - File file = new File(fileName); - - SQLiteStatement stmt = getWritableDb().compileStatement("UPDATE comics_cache SET max_position = ? WHERE filename = ? AND path = ?"); - stmt.bindLong(1, position); - stmt.bindString(2, file.getName()); - stmt.bindString(3, file.getParentFile().getAbsolutePath()); - stmt.execute(); - stmt.close(); - } - } - - public int getLastPosition(String fileName) { - int position = 0; - - File file = new File(fileName); - - Cursor c = getReadableDb().query("comics_cache", new String[]{"position"}, - "filename = ? AND path = ?", - new String[]{file.getName(), file.getParentFile().getAbsolutePath()}, null, null, null); - - if (c.moveToFirst()) { - position = c.getInt(c.getColumnIndex("position")); - } - - c.close(); - - return position; - - } - - public int getCachedItemCount(String baseDir) { - Cursor c = getReadableDb().query("comics_cache", new String[] { "COUNT(*)" }, - "path = ?", - new String[] { baseDir }, null, null, null); - - c.moveToFirst(); - int count = c.getInt(0); - c.close(); - - //Log.d(TAG, "getCachedItemCount:" + baseDir + "=" + count); - - return count; - } - - public int getMaxPosition(String fileName) { - int position = 0; - - File file = new File(fileName); - - Cursor c = getReadableDb().query("comics_cache", new String[] { "max_position" }, - "filename = ? AND path = ?", - new String[] { file.getName(), file.getParentFile().getAbsolutePath() }, null, null, null); - - if (c.moveToFirst()) { - position = c.getInt(c.getColumnIndex("max_position")); - } - - c.close(); - - return position; - } - - public int getSize(String fileName) { - int size = -1; - - File file = new File(fileName); - - Cursor c = getReadableDb().query("comics_cache", new String[] { "size" }, - "filename = ? AND path = ?", - new String[] { file.getName(), file.getParentFile().getAbsolutePath() }, null, null, null); - - if (c.moveToFirst()) { - size = c.getInt(c.getColumnIndex("size")); - } - - c.close(); - - //Log.d(TAG, "getSize:" + fileName + "=" + size); - - return size; - } public void onComicSelected(String fileName, int position) { - setLastPosition(fileName, position); + m_databaseHelper.setLastPosition(fileName, position); } public boolean onOptionsItemSelected(MenuItem item) { @@ -337,16 +160,16 @@ public class CommonActivity extends AppCompatActivity { return null; } - public String getCacheFileName(String fileName) { + public static String getCacheFileName(Context ctx, String fileName) { String hash = md5(fileName); - File file = new File(getExternalCacheDir().getAbsolutePath() + "/" + hash + ".png"); + File file = new File(ctx.getExternalCacheDir().getAbsolutePath() + "/" + hash + ".png"); return file.getAbsolutePath(); } - public String getGoogleAccount() { - AccountManager manager = (AccountManager) getSystemService(ACCOUNT_SERVICE); + public static String getGoogleAccount(Context ctx) { + AccountManager manager = (AccountManager) ctx.getSystemService(ACCOUNT_SERVICE); Account[] list = manager.getAccounts(); for (Account account: list) { @@ -376,7 +199,7 @@ public class CommonActivity extends AppCompatActivity { } public void cleanupCache(boolean deleteAll) { - if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { + if (isStorageWritable()) { File cachePath = getExternalCacheDir(); long now = new Date().getTime(); @@ -391,35 +214,33 @@ public class CommonActivity extends AppCompatActivity { } } - public boolean isStorageAvailable() { - return m_storageAvailable; - } - - public boolean isStorageWritable() { - return m_storageWritable; + public static boolean isStorageAvailable() { + + String state = Environment.getExternalStorageState(); + + return Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state); } - private void initDatabase() { - DatabaseHelper dh = new DatabaseHelper(getApplicationContext()); - - m_writableDb = dh.getWritableDatabase(); - m_readableDb = dh.getReadableDatabase(); + public static boolean isStorageWritable() { + + String state = Environment.getExternalStorageState(); + return Environment.MEDIA_MOUNTED.equals(state); } - public synchronized SQLiteDatabase getReadableDb() { + /*public synchronized SQLiteDatabase getReadableDb() { return m_readableDb; } public synchronized SQLiteDatabase getWritableDb() { return m_writableDb; - } + } */ @Override public void onDestroy() { super.onDestroy(); - m_readableDb.close(); - m_writableDb.close(); +// m_readableDb.close(); +// m_writableDb.close(); } public void selectPreviousComic() { @@ -438,29 +259,6 @@ public class CommonActivity extends AppCompatActivity { } } - public void cleanupSqliteCache(String baseDir) { - Cursor c = getReadableDb().query("comics_cache", null, - null, null, null, null, null); - - if (c.moveToFirst()) { - while (!c.isAfterLast()) { - int id = c.getInt(c.getColumnIndex(BaseColumns._ID)); - String fileName = c.getString(c.getColumnIndex("path")) + "/" + c.getString(c.getColumnIndex("filename")); - - File file = new File(fileName); - - if (!file.exists()) { - SQLiteStatement stmt = getWritableDb().compileStatement("DELETE FROM comics_cache WHERE " + BaseColumns._ID + " = ?"); - stmt.bindLong(1, id); - stmt.execute(); - } - - c.moveToNext(); - } - } - - c.close(); - } public void hideSystemUI(boolean hide) { View decorView = getWindow().getDecorView(); diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/DatabaseHelper.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/DatabaseHelper.java index bf66fec..e1976e3 100644 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/DatabaseHelper.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/DatabaseHelper.java @@ -1,37 +1,58 @@ package org.fox.ttcomics2; -import java.io.File; - import android.content.Context; import android.database.Cursor; +import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteStatement; +import android.os.AsyncTask; import android.provider.BaseColumns; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + public class DatabaseHelper extends SQLiteOpenHelper { public static final String DATABASE_NAME = "ComicsCache.db"; public static final int DATABASE_VERSION = 2; - - public DatabaseHelper(Context context) { + private Context m_context; + private static DatabaseHelper m_instance; + + public static synchronized DatabaseHelper getInstance(Context context) { + + if (m_instance == null) { + m_instance = new DatabaseHelper(context.getApplicationContext()); + } + + return m_instance; + } + + public interface DirectoryScanListener { + void onProgressUpdate(int progress, int max); + void onPostExecute(int result); + } + + private DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); + m_context = context; } - @Override public void onCreate(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS comics_cache;"); db.execSQL("CREATE TABLE IF NOT EXISTS comics_cache (" + - BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + - "filename TEXT, " + - "path TEXT, " + //v2 - "checksum TEXT, " + //v2 - "size INTEGER, " + - "position INTEGER, " + - "max_position INTEGER" + - ");"); + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + + "filename TEXT, " + + "path TEXT, " + //v2 + "checksum TEXT, " + //v2 + "size INTEGER, " + + "position INTEGER, " + + "max_position INTEGER" + + ");"); } @Override @@ -65,4 +86,295 @@ public class DatabaseHelper extends SQLiteOpenHelper { } } + public Cursor findComicByFileName(String fileName) { + File file = new File(fileName); + + if (getWritableDatabase() == null) + return null; + + Cursor c = getWritableDatabase().query("comics_cache", null, + "filename = ? AND path = ?", + new String[]{file.getName(), file.getParentFile().getAbsolutePath()}, null, null, null); + + if (c.moveToFirst()) { + return c; + } else { + c.close(); + + SQLiteStatement stmt = getWritableDatabase().compileStatement("INSERT INTO comics_cache " + + "(filename, path, position, max_position, size, checksum) VALUES (?, ?, 0, 0, -1, '')"); + stmt.bindString(1, file.getName()); + stmt.bindString(2, file.getParentFile().getAbsolutePath()); + stmt.execute(); + + c = getWritableDatabase().query("comics_cache", null, + "filename = ? AND path = ?", + new String[] { file.getName(), file.getParentFile().getAbsolutePath() }, null, null, null); + + if (c.moveToFirst()) { + return c; + } else { + c.close(); + } + } + + return null; + } + + public void setSize(String fileName, int size) { + Cursor c = findComicByFileName(fileName); + + if (c != null) { + c.close(); + + File file = new File(fileName); + + SQLiteStatement stmt = getWritableDatabase().compileStatement("UPDATE comics_cache SET size = ? WHERE filename = ? AND path = ?"); + stmt.bindLong(1, size); + stmt.bindString(2, file.getName()); + stmt.bindString(3, file.getParentFile().getAbsolutePath()); + stmt.execute(); + stmt.close(); + } + } + + public void setLastPosition(String fileName, int position) { + int lastPosition = getLastPosition(fileName); + + Cursor c = findComicByFileName(fileName); + + if (c != null) { + c.close(); + + File file = new File(fileName); + + SQLiteStatement stmt = getWritableDatabase().compileStatement("UPDATE comics_cache SET position = ?, max_position = ? WHERE filename = ? AND path = ?"); + stmt.bindLong(1, position); + stmt.bindLong(2, Math.max(position, lastPosition)); + stmt.bindString(3, file.getName()); + stmt.bindString(4, file.getParentFile().getAbsolutePath()); + stmt.execute(); + stmt.close(); + } + + } + + public void setLastMaxPosition(String fileName, int position) { + + Cursor c = findComicByFileName(fileName); + + if (c != null) { + c.close(); + + File file = new File(fileName); + + SQLiteStatement stmt = getWritableDatabase().compileStatement("UPDATE comics_cache SET max_position = ? WHERE filename = ? AND path = ?"); + stmt.bindLong(1, position); + stmt.bindString(2, file.getName()); + stmt.bindString(3, file.getParentFile().getAbsolutePath()); + stmt.execute(); + stmt.close(); + } + } + + public int getLastPosition(String fileName) { + int position = 0; + + File file = new File(fileName); + + Cursor c = getWritableDatabase().query("comics_cache", new String[]{"position"}, + "filename = ? AND path = ?", + new String[]{file.getName(), file.getParentFile().getAbsolutePath()}, null, null, null); + + if (c.moveToFirst()) { + position = c.getInt(c.getColumnIndex("position")); + } + + c.close(); + + return position; + + } + + public int getCachedItemCount(String baseDir) { + Cursor c = getWritableDatabase().query("comics_cache", new String[] { "COUNT(*)" }, + "path = ?", + new String[] { baseDir }, null, null, null); + + c.moveToFirst(); + int count = c.getInt(0); + c.close(); + + //Log.d(TAG, "getCachedItemCount:" + baseDir + "=" + count); + + return count; + } + + public int getMaxPosition(String fileName) { + int position = 0; + + File file = new File(fileName); + + Cursor c = getWritableDatabase().query("comics_cache", new String[]{"max_position"}, + "filename = ? AND path = ?", + new String[]{file.getName(), file.getParentFile().getAbsolutePath()}, null, null, null); + + if (c.moveToFirst()) { + position = c.getInt(c.getColumnIndex("max_position")); + } + + c.close(); + + return position; + } + + public int getSize(String fileName) { + int size = -1; + + File file = new File(fileName); + + Cursor c = getWritableDatabase().query("comics_cache", new String[] { "size" }, + "filename = ? AND path = ?", + new String[] { file.getName(), file.getParentFile().getAbsolutePath() }, null, null, null); + + if (c.moveToFirst()) { + size = c.getInt(c.getColumnIndex("size")); + } + + c.close(); + + //Log.d(TAG, "getSize:" + fileName + "=" + size); + + return size; + } + + public void cleanupSqliteCache(String baseDir) { + Cursor c = getWritableDatabase().query("comics_cache", null, + null, null, null, null, null); + + if (c.moveToFirst()) { + while (!c.isAfterLast()) { + int id = c.getInt(c.getColumnIndex(BaseColumns._ID)); + String fileName = c.getString(c.getColumnIndex("path")) + "/" + c.getString(c.getColumnIndex("filename")); + + File file = new File(fileName); + + if (!file.exists()) { + SQLiteStatement stmt = getWritableDatabase().compileStatement("DELETE FROM comics_cache WHERE " + BaseColumns._ID + " = ?"); + stmt.bindLong(1, id); + stmt.execute(); + } + + c.moveToNext(); + } + } + + c.close(); + } + + public void rescanDirectory(String comicsDir, final boolean fullRescan, final DirectoryScanListener listener) { + + AsyncTask task = new AsyncTask() { + + @Override + protected void onProgressUpdate(Integer... progress) { + listener.onProgressUpdate(progress[0], progress[1]); + } + + @Override + protected void onPostExecute(Integer result) { + listener.onPostExecute(result); + } + + @Override + protected Integer doInBackground(String... params) { + try { + + String comicsDir = params[0]; + File dir = new File(comicsDir); + + int fileIndex = 0; + + if (dir.isDirectory()) { + File archives[] = dir.listFiles(); + + java.util.Arrays.sort(archives); + + for (File archive : archives) { + String filePath = archive.getAbsolutePath(); + + if (archive.isDirectory()) { + setSize(filePath, ComicListFragment.SIZE_DIR); + + } else if (archive.getName().toLowerCase().matches(".*\\.(cbz|zip)")) { + try { + int size = getSize(filePath); + + if (size == -1 || fullRescan) { + + ComicArchive cba = null; + + if (archive.getName().toLowerCase().matches(".*\\.(cbz|zip)")) { + cba = new CbzComicArchive(filePath); + } + + if (cba != null && cba.getCount() > 0) { + // Get cover + + try { + File thumbnailFile = new File(CommonActivity.getCacheFileName(m_context, filePath)); + + if (CommonActivity.isStorageWritable() && (!thumbnailFile.exists() || fullRescan)) { + InputStream is = cba.getItem(0); + + if (is != null) { + FileOutputStream fos = new FileOutputStream(thumbnailFile); + + byte[] buffer = new byte[1024]; + int len; + while ((len = is.read(buffer)) != -1) { + fos.write(buffer, 0, len); + } + + fos.close(); + is.close(); + } + } + + } catch (IOException e) { + e.printStackTrace(); + } + + size = cba.getCount(); + + setSize(filePath, size); + } + } + } catch (IOException e) { + e.printStackTrace(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + ++fileIndex; + + publishProgress(Integer.valueOf(fileIndex), Integer.valueOf(archives.length)); + } + } + + cleanupSqliteCache(comicsDir); + + return fileIndex; + + } catch (Exception e) { + e.printStackTrace(); + } + + return 0; + } + }; + + task.execute(comicsDir); + } } diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/MainActivity.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/MainActivity.java index 9d986d0..a58259e 100644 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/MainActivity.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/MainActivity.java @@ -5,9 +5,11 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.os.AsyncTask; +import android.content.IntentFilter; import android.os.Bundle; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.ActionBar; @@ -17,8 +19,6 @@ import android.view.Menu; import android.view.MenuItem; import java.io.File; -import java.io.IOException; -import java.net.HttpURLConnection; import it.neokree.materialtabs.MaterialTab; import it.neokree.materialtabs.MaterialTabHost; @@ -32,8 +32,31 @@ public class MainActivity extends CommonActivity implements MaterialTabListener private String m_rootDirectory = ""; private MaterialTabHost tabHost; private boolean m_useSync; + private ProgressDialog m_progressDialog; - @SuppressLint("NewApi") + private BroadcastReceiver m_serviceReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (PositionGetService.INTENT_ACTION_FILE_PROCESSED.equals(intent.getAction())) { + + int count = intent.getExtras().getInt("count"); + int index = intent.getExtras().getInt("index"); + + m_progressDialog.setCancelable(false); + m_progressDialog.setTitle("Synchronizing..."); + m_progressDialog.setMessage("File " + index + " of " + count); + m_progressDialog.show(); + } + + if (PositionGetService.INTENT_ACTION_SCAN_COMPLETE.equals(intent.getAction())) { + m_progressDialog.dismiss(); + updateComicsList(); + } + + } + }; + + @SuppressLint("NewApi") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -45,7 +68,9 @@ public class MainActivity extends CommonActivity implements MaterialTabListener setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); setTitle(R.string.app_name); - tabHost = (MaterialTabHost) this.findViewById(R.id.materialTabHost); + m_progressDialog = new ProgressDialog(this); + + tabHost = (MaterialTabHost) this.findViewById(R.id.materialTabHost); if (savedInstanceState == null) { m_selectedTab = 0; //getIntent().getIntExtra("selectedTab", 0); @@ -130,6 +155,13 @@ public class MainActivity extends CommonActivity implements MaterialTabListener public void onResume() { super.onResume(); + IntentFilter filter = new IntentFilter(); + filter.addAction(PositionGetService.INTENT_ACTION_FILE_PROCESSED); + filter.addAction(PositionGetService.INTENT_ACTION_SCAN_COMPLETE); + filter.addCategory(Intent.CATEGORY_DEFAULT); + + registerReceiver(m_serviceReceiver, filter); + if (!m_rootDirectory.equals(m_prefs.getString("comics_directory", ""))) { Log.d(TAG, "root directory changed, restarting"); @@ -207,85 +239,9 @@ public class MainActivity extends CommonActivity implements MaterialTabListener } private void updateLastRead(String baseDir) { - final ProgressDialog progressDialog = new ProgressDialog(this); - - progressDialog.setIndeterminate(false); - //progressDialog.setCancelable(false); - progressDialog.setMessage("Synchronizing..."); - progressDialog.show(); - - AsyncTask task = new AsyncTask() { - @Override - protected Integer doInBackground(String... params) { - File dir = new File(params[0]); - - if (dir.exists() && dir.isDirectory()) { - int fileCount = dir.listFiles().length; - int fileIndex = 0; - - for (File file : dir.listFiles()) { - ++fileIndex; - - if (file.isFile()) { - //Log.d(TAG, "F=" + file.getName()); - - HttpURLConnection conn = m_syncClient.doSyncHttpRequest("get", sha1(file.getName())); - - try { - if (conn != null && conn.getResponseCode() == HttpURLConnection.HTTP_OK) { - String result = m_syncClient.readHttpResponse(conn); - - if (result != null) { - //Log.d(TAG, "GOT=" + result); - - int position = Integer.valueOf(result); - - if (position > getLastPosition(file.getAbsolutePath())) { - setLastPosition(file.getAbsolutePath(), position); - } - } - - } - } catch (IOException e) { - e.printStackTrace(); - } - - publishProgress(fileIndex, fileCount); - - try { - Thread.sleep(250); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - - return null; - } - - @Override - protected void onProgressUpdate(Integer... progress) { - if (progressDialog != null) { - progressDialog.setProgress(progress[0]); - progressDialog.setMax(progress[1]); - progressDialog.setMessage("File " + progress[0] + " of " + progress[1]); - } - } - - @Override - protected void onPostExecute(Integer result) { - if (progressDialog != null) { - progressDialog.dismiss(); - } - - updateComicsList(); - - } - - }; - - task.execute(baseDir); + Intent serviceIntent = new Intent(MainActivity.this, PositionGetService.class); + serviceIntent.putExtra("baseDir", baseDir); + startService(serviceIntent); } @Override @@ -330,7 +286,7 @@ public class MainActivity extends CommonActivity implements MaterialTabListener if (m_prefs.getBoolean("use_position_sync", false) && m_syncClient.hasOwner()) { toast(R.string.sync_uploading); - m_syncClient.setPosition(sha1(new File(fileName).getName()), getLastPosition(fileName)); + m_syncClient.setPosition(sha1(new File(fileName).getName()), m_databaseHelper.getLastPosition(fileName)); } updateComicsList(); @@ -384,8 +340,8 @@ public class MainActivity extends CommonActivity implements MaterialTabListener public void resetProgress(final String fileName) { if (m_prefs.getBoolean("use_position_sync", false) && m_syncClient.hasOwner()) { - setLastPosition(fileName, 0); - setLastMaxPosition(fileName, 0); + m_databaseHelper.setLastPosition(fileName, 0); + m_databaseHelper.setLastMaxPosition(fileName, 0); updateComicsList(); if (m_prefs.getBoolean("use_position_sync", false) && m_syncClient.hasOwner()) { @@ -415,4 +371,10 @@ public class MainActivity extends CommonActivity implements MaterialTabListener } + @Override + public void onPause() { + super.onPause(); + + unregisterReceiver(m_serviceReceiver); + } } diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/PositionGetService.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/PositionGetService.java new file mode 100644 index 0000000..d94e4ac --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/PositionGetService.java @@ -0,0 +1,119 @@ +package org.fox.ttcomics2; + +import android.app.Service; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Binder; +import android.os.IBinder; +import android.util.Log; + +import java.io.File; +import java.io.IOException; +import java.net.HttpURLConnection; + +public class PositionGetService extends Service { + private final String TAG = this.getClass().getSimpleName(); + + public final static String INTENT_ACTION_FILE_PROCESSED = "org.fox.ttcomics2.intent.action.FileProcessed"; + public final static String INTENT_ACTION_SCAN_COMPLETE = "org.fox.ttcomics2.intent.action.ScanComplete"; + + private DatabaseHelper m_databaseHelper; + private final IBinder m_binder = new LocalBinder(); + + public class LocalBinder extends Binder { + PositionGetService getService() { + return PositionGetService.this; + } + } + + @Override + public void onCreate() { + super.onCreate(); + + m_databaseHelper = DatabaseHelper.getInstance(this); + } + + @Override + public IBinder onBind(Intent intent) { + return m_binder; + } + + @Override + public void onStart(Intent intent, int startId) { + String baseDir = intent.getExtras().getString("baseDir"); + + AsyncTask task = new AsyncTask() { + @Override + protected Integer doInBackground(String... params) { + File rootDir = new File(params[0]); + + if (rootDir.exists() && rootDir.isDirectory()) { + + int index = 0; + int count = rootDir.listFiles().length; + + for (File file : rootDir.listFiles()) { + ++index; + + Log.d(TAG, "file=" + file.getAbsolutePath()); + + SyncClient m_syncClient = new SyncClient(); + + String googleAccount = CommonActivity.getGoogleAccount(getApplicationContext()); + + if (googleAccount != null) { + m_syncClient.setOwner(googleAccount); + } else if (BuildConfig.DEBUG) { + m_syncClient.setOwner("TEST-ACCOUNT"); + } + + HttpURLConnection conn = m_syncClient.doSyncHttpRequest("get", CommonActivity.sha1(file.getName())); + + try { + if (conn != null && conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + String result = m_syncClient.readHttpResponse(conn); + + if (result != null) { + //Log.d(TAG, "GOT=" + result); + + int position = Integer.valueOf(result); + + if (position > 0) { + + if (position > m_databaseHelper.getLastPosition(file.getAbsolutePath())) { + m_databaseHelper.setLastPosition(file.getAbsolutePath(), position); + } + } + + } + + Thread.sleep(250); + } + } catch (IOException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + + Intent broadcast = new Intent(); + broadcast.setAction(INTENT_ACTION_FILE_PROCESSED); + broadcast.putExtra("index", index); + broadcast.putExtra("count", count); + broadcast.addCategory(Intent.CATEGORY_DEFAULT); + sendBroadcast(broadcast); + } + } + + Intent broadcast = new Intent(); + broadcast.setAction(INTENT_ACTION_SCAN_COMPLETE); + broadcast.addCategory(Intent.CATEGORY_DEFAULT); + sendBroadcast(broadcast); + + return null; + } + }; + + task.execute(baseDir); + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ViewComicActivity.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ViewComicActivity.java index 56fd182..61a6f41 100644 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ViewComicActivity.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ViewComicActivity.java @@ -108,7 +108,7 @@ public class ViewComicActivity extends CommonActivity { // upload progress if (m_prefs.getBoolean("use_position_sync", false) && m_syncClient.hasOwner()) { //toast(R.string.sync_uploading); - m_syncClient.setPosition(sha1(new File(m_fileName).getName()), getLastPosition(m_fileName)); + m_syncClient.setPosition(sha1(new File(m_fileName).getName()), m_databaseHelper.getLastPosition(m_fileName)); } } @@ -258,7 +258,7 @@ public class ViewComicActivity extends CommonActivity { cp.setCurrentItem(0); break; case 1: - cp.setCurrentItem(getMaxPosition(m_fileName)); + cp.setCurrentItem(m_databaseHelper.getMaxPosition(m_fileName)); break; case 2: if (true) { @@ -268,7 +268,7 @@ public class ViewComicActivity extends CommonActivity { final NumberPicker picker = (NumberPicker) contentView.findViewById(R.id.number_picker); picker.setMinValue(1); - picker.setMaxValue(getSize(m_fileName)); + picker.setMaxValue(m_databaseHelper.getSize(m_fileName)); picker.setValue(cp.getPosition() + 1); Dialog seekDialog = new Dialog(ViewComicActivity.this); -- cgit v1.2.3