diff --git a/README.md b/README.md index f3be5d31a..54cc7f904 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ repositories { } dependencies { - implementation 'com.folioreader:folioreader:0.4.1' + implementation 'com.folioreader:folioreader:0.4.2' } ``` diff --git a/build.gradle b/build.gradle index ce0c90d0b..3e8c21376 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ allprojects { } ext { - LIBRARY_VERSION = '0.4.1' + LIBRARY_VERSION = '0.4.2' R2_STREAMER_VERSION = '0.1.8' VERSION_NAME = "1.0" @@ -39,6 +39,8 @@ ext { ANDROID_COMPILE_SDK_VERSION = 28 ANDROID_TARGET_SDK_VERSION = 28 ANDROID_LIB_VERSION = '28.0.0-rc01' + + CONSTRAINT_LAYOUT_VERSION = "1.1.2" } task clean(type: Delete) { diff --git a/folioreader/build.gradle b/folioreader/build.gradle index 65eedf8e9..7b2ba0736 100644 --- a/folioreader/build.gradle +++ b/folioreader/build.gradle @@ -90,7 +90,7 @@ dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation project(':webViewMarker') - implementation 'com.android.support.constraint:constraint-layout:1.1.2' + implementation "com.android.support.constraint:constraint-layout:$CONSTRAINT_LAYOUT_VERSION" implementation "com.android.support:appcompat-v7:$ANDROID_LIB_VERSION" implementation "com.android.support:recyclerview-v7:$ANDROID_LIB_VERSION" implementation "com.android.support:support-v4:$ANDROID_LIB_VERSION" diff --git a/folioreader/src/main/assets/css/Style.css b/folioreader/src/main/assets/css/Style.css index ba1c71e6d..8500ff7d2 100755 --- a/folioreader/src/main/assets/css/Style.css +++ b/folioreader/src/main/assets/css/Style.css @@ -87,7 +87,7 @@ b, strong, th {font-weight: bolder !important;} /* Forced font overrides */ code, kbd, pre, samp, tt { font-family: monospace, monospace !important; - font-size: 1em; + font-size: 1rem; } button, input, select, textarea { display: inline-block !important; } /*h1, h2, h3, h4, h5, h6 { font-weight: 400!important; }*/ @@ -100,8 +100,8 @@ hr { /* Sub and Super */ -big { font-size: 1.15em !important; } -small, sub, sup { font-size: .65em !important; } +big { font-size: 1.15rem !important; } +small, sub, sup { font-size: .65rem !important; } sub { vertical-align: sub !important; } sup { font-family: monospace !important; @@ -269,27 +269,27 @@ html.textSizeFour { font-size: 19px !important; } html.textSizeFive { font-size: 21px !important; } h1 { - font-size: 2em; + font-size: 2rem; line-height: 1.2; } h2 { - font-size: 1.5em; + font-size: 1.5rem; line-height: 1.2; } h3 { - font-size: 1.17em; + font-size: 1.17rem; line-height: 1.2; } h4 { - font-size: 1em; + font-size: 1rem; line-height: 1.2; } h5 { - font-size: 0.83em; + font-size: 0.83rem; line-height: 1.2; } h6 { - font-size: 0.67em; + font-size: 0.67rem; line-height: 1.2; } body { @@ -298,12 +298,12 @@ body { hyphens: auto !important; } p, span, div { - font-size: 1em; + font-size: 1rem; line-height: 1.5 !important; } @media only screen and (min-device-width: 600px) { div { - font-size: 1em; + font-size: 1rem; line-height: 1.438em !important; } body { diff --git a/folioreader/src/main/java/com/folioreader/FolioReader.java b/folioreader/src/main/java/com/folioreader/FolioReader.java index e44fa2c8d..6f1c123d6 100644 --- a/folioreader/src/main/java/com/folioreader/FolioReader.java +++ b/folioreader/src/main/java/com/folioreader/FolioReader.java @@ -33,10 +33,23 @@ public class FolioReader { private boolean overrideConfig; private OnHighlightListener onHighlightListener; private ReadPositionListener readPositionListener; + private OnClosedListener onClosedListener; private ReadPosition readPosition; public static final String ACTION_SAVE_READ_POSITION = "com.folioreader.action.SAVE_READ_POSITION"; + public static final String ACTION_CLOSE_FOLIOREADER = "com.folioreader.action.CLOSE_FOLIOREADER"; + public static final String ACTION_FOLIOREADER_CLOSED = "com.folioreader.action.FOLIOREADER_CLOSED"; public static final String EXTRA_READ_POSITION = "com.folioreader.extra.READ_POSITION"; + public interface OnClosedListener { + /** + * You may call {@link FolioReader#clear()} in this method, if you wont't require to open + * an epub again from the current activity. + * Or you may call {@link FolioReader#stop()} in this method, if you wont't require to open + * an epub again from your application. + */ + void onFolioReaderClosed(); + } + private BroadcastReceiver highlightReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -55,18 +68,26 @@ public void onReceive(Context context, Intent intent) { ReadPosition readPosition = intent.getParcelableExtra(FolioReader.EXTRA_READ_POSITION); - if (readPositionListener != null ) + if (readPositionListener != null) readPositionListener.saveReadPosition(readPosition); } }; + private BroadcastReceiver closedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (onClosedListener != null) + onClosedListener.onFolioReaderClosed(); + } + }; + public static FolioReader get() { if (singleton == null) { synchronized (FolioReader.class) { if (singleton == null) { if (AppContext.get() == null) { - throw new IllegalArgumentException("-> context == null"); + throw new IllegalStateException("-> context == null"); } singleton = new FolioReader(AppContext.get()); } @@ -81,10 +102,14 @@ private FolioReader() { private FolioReader(Context context) { this.context = context; DbAdapter.initialize(context); - LocalBroadcastManager.getInstance(context).registerReceiver(highlightReceiver, + + LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context); + localBroadcastManager.registerReceiver(highlightReceiver, new IntentFilter(HighlightImpl.BROADCAST_EVENT)); - LocalBroadcastManager.getInstance(context).registerReceiver(readPositionReceiver, + localBroadcastManager.registerReceiver(readPositionReceiver, new IntentFilter(ACTION_SAVE_READ_POSITION)); + localBroadcastManager.registerReceiver(closedReceiver, + new IntentFilter(ACTION_FOLIOREADER_CLOSED)); } public FolioReader openBook(String assetOrSdcardPath) { @@ -160,7 +185,8 @@ private Intent getIntentFromUrl(String assetOrSdcardPath, int rawId) { /** * Pass your configuration and choose to override it every time or just for first execution. - * @param config custom configuration. + * + * @param config custom configuration. * @param overrideConfig true will override the config, false will use either this * config if it is null in application context or will fetch previously * saved one while execution. @@ -181,6 +207,11 @@ public FolioReader setReadPositionListener(ReadPositionListener readPositionList return singleton; } + public FolioReader setOnClosedListener(OnClosedListener onClosedListener) { + this.onClosedListener = onClosedListener; + return singleton; + } + public FolioReader setReadPosition(ReadPosition readPosition) { this.readPosition = readPosition; return singleton; @@ -190,6 +221,18 @@ public void saveReceivedHighLights(List highlights, OnSaveHighlight o new SaveReceivedHighlightTask(onSaveHighlight, highlights).execute(); } + /** + * Closes all the activities related to FolioReader. + * After closing all the activities of FolioReader, callback can be received in + * {@link OnClosedListener#onFolioReaderClosed()} if implemented. + * Developer is still bound to call {@link #clear()} or {@link #stop()} + * for clean up if required. + */ + public void close() { + Intent intent = new Intent(FolioReader.ACTION_CLOSE_FOLIOREADER); + LocalBroadcastManager.getInstance(context).sendBroadcast(intent); + } + /** * Nullifies readPosition and listeners. * This method ideally should be used in onDestroy() of Activity or Fragment. @@ -202,6 +245,7 @@ public static synchronized void clear() { singleton.readPosition = null; singleton.onHighlightListener = null; singleton.readPositionListener = null; + singleton.onClosedListener = null; } } @@ -220,7 +264,9 @@ public static synchronized void stop() { } private void unregisterListeners() { - LocalBroadcastManager.getInstance(context).unregisterReceiver(highlightReceiver); - LocalBroadcastManager.getInstance(context).unregisterReceiver(readPositionReceiver); + LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context); + localBroadcastManager.unregisterReceiver(highlightReceiver); + localBroadcastManager.unregisterReceiver(readPositionReceiver); + localBroadcastManager.unregisterReceiver(closedReceiver); } } diff --git a/folioreader/src/main/java/com/folioreader/ui/folio/activity/FolioActivity.java b/folioreader/src/main/java/com/folioreader/ui/folio/activity/FolioActivity.java index ea84cbd72..fa771639c 100644 --- a/folioreader/src/main/java/com/folioreader/ui/folio/activity/FolioActivity.java +++ b/folioreader/src/main/java/com/folioreader/ui/folio/activity/FolioActivity.java @@ -17,6 +17,7 @@ import android.Manifest; import android.app.Activity; +import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -137,6 +138,8 @@ public enum EpubSourceType { private CharSequence searchQuery; private SearchItem searchItem; private float density; + private Boolean topActivity; + private int taskImportance; private enum RequestCode { CONTENT_HIGHLIGHT(77), @@ -149,11 +152,89 @@ private enum RequestCode { } } + private BroadcastReceiver closeBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Log.v(LOG_TAG, "-> closeBroadcastReceiver -> onReceive -> " + intent.getAction()); + + String action = intent.getAction(); + if (action != null && action.equals(FolioReader.ACTION_CLOSE_FOLIOREADER)) { + + try { + ActivityManager activityManager = (ActivityManager) + context.getSystemService(Context.ACTIVITY_SERVICE); + List tasks = + activityManager.getRunningAppProcesses(); + taskImportance = tasks.get(0).importance; + } catch (Exception e) { + Log.e(LOG_TAG, "-> ", e); + } + + Intent closeIntent = new Intent(getApplicationContext(), FolioActivity.class); + closeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); + closeIntent.setAction(FolioReader.ACTION_CLOSE_FOLIOREADER); + FolioActivity.this.startActivity(closeIntent); + } + } + }; + + @SuppressWarnings("PMD.CollapsibleIfStatements") + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + setIntent(intent); + Log.v(LOG_TAG, "-> onNewIntent"); + + String action = getIntent().getAction(); + if (action != null && action.equals(FolioReader.ACTION_CLOSE_FOLIOREADER)) { + + if (topActivity == null || !topActivity) { + // FolioActivity was already left, so no need to broadcast ReadPosition again. + // Finish activity without going through onPause() and onStop() + finish(); + + // To determine if app in background or foreground + boolean appInBackground = false; + if (Build.VERSION.SDK_INT < 26) { + if (ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND == taskImportance) + appInBackground = true; + } else { + if (ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED == taskImportance) + appInBackground = true; + } + if (appInBackground) + moveTaskToBack(true); + } + } + } + + @Override + protected void onResume() { + super.onResume(); + Log.v(LOG_TAG, "-> onResume"); + topActivity = true; + + String action = getIntent().getAction(); + if (action != null && action.equals(FolioReader.ACTION_CLOSE_FOLIOREADER)) { + // FolioActivity is topActivity, so need to broadcast ReadPosition. + finish(); + } + } + + @Override + protected void onStop() { + super.onStop(); + Log.v(LOG_TAG, "-> onStop"); + topActivity = false; + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); handler = new Handler(); density = getResources().getDisplayMetrics().density; + LocalBroadcastManager.getInstance(this).registerReceiver(closeBroadcastReceiver, + new IntentFilter(FolioReader.ACTION_CLOSE_FOLIOREADER)); // Fix for screen get turned off while reading // TODO: -> Make this configurable @@ -340,7 +421,7 @@ private void initBook(String mEpubFileName, int mEpubRawId, String mEpubFilePath mEpubRawId, mEpubFileName); addEpub(path); - String urlString = Constants.LOCALHOST + bookFileName + "/manifest"; + String urlString = Constants.LOCALHOST + Uri.encode(bookFileName) + "/manifest"; new MainPresenter(this).parseManifest(urlString); } catch (IOException e) { @@ -543,6 +624,9 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RequestCode.SEARCH.value) { Log.v(LOG_TAG, "-> onActivityResult -> " + RequestCode.SEARCH); + if (resultCode == RESULT_CANCELED) + return; + searchAdapterDataBundle = data.getBundleExtra(SearchAdapter.DATA_BUNDLE); searchQuery = data.getCharSequenceExtra(SearchActivity.BUNDLE_SAVE_SEARCH_QUERY); @@ -586,11 +670,16 @@ protected void onDestroy() { if (outState != null) outState.putParcelable(BUNDLE_READ_POSITION_CONFIG_CHANGE, lastReadPosition); - LocalBroadcastManager.getInstance(this).unregisterReceiver(searchReceiver); + LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this); + localBroadcastManager.unregisterReceiver(searchReceiver); + localBroadcastManager.unregisterReceiver(closeBroadcastReceiver); if (mEpubServer != null) { mEpubServer.stop(); } + + if (isFinishing()) + localBroadcastManager.sendBroadcast(new Intent(FolioReader.ACTION_FOLIOREADER_CLOSED)); } @Override diff --git a/folioreader/src/main/java/com/folioreader/ui/folio/activity/SearchActivity.kt b/folioreader/src/main/java/com/folioreader/ui/folio/activity/SearchActivity.kt index 0c6635e4b..73299c9bc 100644 --- a/folioreader/src/main/java/com/folioreader/ui/folio/activity/SearchActivity.kt +++ b/folioreader/src/main/java/com/folioreader/ui/folio/activity/SearchActivity.kt @@ -48,8 +48,8 @@ class SearchActivity : AppCompatActivity(), LoaderManager.LoaderCallbacks, } enum class ResultCode(val value: Int) { - ITEM_SELECTED(1), - BACK_BUTTON_PRESSED(2) + ITEM_SELECTED(2), + BACK_BUTTON_PRESSED(3) } private lateinit var searchUri: Uri diff --git a/folioreader/src/main/java/com/folioreader/ui/folio/fragment/FolioPageFragment.java b/folioreader/src/main/java/com/folioreader/ui/folio/fragment/FolioPageFragment.java index 3068af25e..eccbb46e0 100644 --- a/folioreader/src/main/java/com/folioreader/ui/folio/fragment/FolioPageFragment.java +++ b/folioreader/src/main/java/com/folioreader/ui/folio/fragment/FolioPageFragment.java @@ -204,7 +204,7 @@ public View onCreateView(LayoutInflater inflater, } private String getWebviewUrl() { - return Constants.LOCALHOST + mBookTitle + "/" + spineItem.href; + return Constants.LOCALHOST + Uri.encode(mBookTitle) + "/" + spineItem.href; } /** @@ -1141,7 +1141,8 @@ public void onDestroy() { if (isCurrentFragment()) { if (outState != null) outState.putParcelable(BUNDLE_READ_POSITION_CONFIG_CHANGE, lastReadPosition); - mActivityCallback.storeLastReadPosition(lastReadPosition); + if (getActivity() != null && !getActivity().isFinishing()) + mActivityCallback.storeLastReadPosition(lastReadPosition); } if (mWebview != null) mWebview.destroy(); } diff --git a/folioreader/src/main/java/com/folioreader/ui/tableofcontents/view/TableOfContentFragment.java b/folioreader/src/main/java/com/folioreader/ui/tableofcontents/view/TableOfContentFragment.java index c9a63b5fa..67a513b38 100644 --- a/folioreader/src/main/java/com/folioreader/ui/tableofcontents/view/TableOfContentFragment.java +++ b/folioreader/src/main/java/com/folioreader/ui/tableofcontents/view/TableOfContentFragment.java @@ -2,6 +2,7 @@ import android.app.Activity; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; @@ -72,7 +73,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mTableOfContentsRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view_menu); errorView = (TextView) view.findViewById(R.id.tv_error); - String urlString = Constants.LOCALHOST + mBookTitle + "/manifest"; + String urlString = Constants.LOCALHOST + Uri.encode(mBookTitle) + "/manifest"; configRecyclerViews(); presenter.getTOCContent(urlString); diff --git a/sample/build.gradle b/sample/build.gradle index cad555547..1a6b9f54c 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -61,7 +61,7 @@ repositories { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "com.android.support:appcompat-v7:$ANDROID_LIB_VERSION" - implementation 'com.android.support.constraint:constraint-layout:1.1.2' + implementation "com.android.support.constraint:constraint-layout:$CONSTRAINT_LAYOUT_VERSION" testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' diff --git a/sample/src/main/java/com/folioreader/android/sample/HomeActivity.java b/sample/src/main/java/com/folioreader/android/sample/HomeActivity.java index 05a9fdfc7..0ad457e05 100644 --- a/sample/src/main/java/com/folioreader/android/sample/HomeActivity.java +++ b/sample/src/main/java/com/folioreader/android/sample/HomeActivity.java @@ -42,7 +42,7 @@ import java.util.List; public class HomeActivity extends AppCompatActivity - implements OnHighlightListener, ReadPositionListener { + implements OnHighlightListener, ReadPositionListener, FolioReader.OnClosedListener { private static final String LOG_TAG = HomeActivity.class.getSimpleName(); private FolioReader folioReader; @@ -54,7 +54,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { folioReader = FolioReader.get() .setOnHighlightListener(this) - .setReadPositionListener(this); + .setReadPositionListener(this) + .setOnClosedListener(this); getHighlightsAndSave(); @@ -177,4 +178,9 @@ public void onHighlight(HighLight highlight, HighLight.HighLightAction type) { "highlight id = " + highlight.getUUID() + " type = " + type, Toast.LENGTH_SHORT).show(); } + + @Override + public void onFolioReaderClosed() { + Log.v(LOG_TAG, "-> onFolioReaderClosed"); + } } \ No newline at end of file