├── .gitignore ├── README.md ├── app ├── build.gradle └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── github │ │ └── epubparsersampleandroidapplication │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── pg28885-images_new.epub │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── epubparsersampleandroidapplication │ │ │ ├── BookInfo.java │ │ │ ├── BookInfoGridAdapter.java │ │ │ ├── MainActivity.java │ │ │ ├── MenuActivity.java │ │ │ └── PageFragment.java │ └── res │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_menu.xml │ │ ├── book_item.xml │ │ ├── content_menu.xml │ │ └── fragment_display.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── github │ └── epubparsersampleandroidapplication │ └── ExampleUnitTest.java ├── build.gradle └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /.idea 4 | /app/build 5 | /build 6 | /local.properties 7 | /gradle 8 | gradle.properties 9 | gradlew 10 | gradlew.bat 11 | proguard-rules.pro 12 | appengine-web.xml 13 | app/libs/ 14 | projectFilesBackup/ 15 | *.apk -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EpubParser-Sample-Android-Application 2 | 3 | Sample Android Application for EpubParser java library. 4 | 5 | Google Play Link 6 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "25.0.0" 6 | 7 | defaultConfig { 8 | applicationId "com.github.epubparsersampleandroidapplication" 9 | minSdkVersion 9 10 | targetSdkVersion 23 11 | versionCode 4 12 | versionName "1.0.3" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.4.0' 26 | compile 'com.android.support:design:23.4.0' 27 | compile 'com.github.mertakdut:EpubParser:1.0.9' 28 | } 29 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/github/epubparsersampleandroidapplication/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.github.epubparsersampleandroidapplication; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/assets/pg28885-images_new.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mertakdut/EpubParser-Sample-Android-Application/ee41597b64ce69db58b5dd3610cc4688f5c3fd5f/app/src/main/assets/pg28885-images_new.epub -------------------------------------------------------------------------------- /app/src/main/java/com/github/epubparsersampleandroidapplication/BookInfo.java: -------------------------------------------------------------------------------- 1 | package com.github.epubparsersampleandroidapplication; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | /** 6 | * Created by Mert on 08.09.2016. 7 | */ 8 | public class BookInfo { 9 | private String title; 10 | private byte[] coverImage; 11 | private String filePath; 12 | 13 | private boolean isCoverImageNotExists; 14 | private Bitmap coverImageBitmap; 15 | 16 | public String getTitle() { 17 | return title; 18 | } 19 | 20 | public void setTitle(String title) { 21 | this.title = title; 22 | } 23 | 24 | public String getFilePath() { 25 | return filePath; 26 | } 27 | 28 | public void setFilePath(String filePath) { 29 | this.filePath = filePath; 30 | } 31 | 32 | public byte[] getCoverImage() { 33 | return coverImage; 34 | } 35 | 36 | public void setCoverImage(byte[] coverImage) { 37 | this.coverImage = coverImage; 38 | } 39 | 40 | public Bitmap getCoverImageBitmap() { 41 | return coverImageBitmap; 42 | } 43 | 44 | public void setCoverImageBitmap(Bitmap coverImageBitmap) { 45 | this.coverImageBitmap = coverImageBitmap; 46 | } 47 | 48 | public boolean isCoverImageNotExists() { 49 | return isCoverImageNotExists; 50 | } 51 | 52 | public void setCoverImageNotExists(boolean coverImageNotExists) { 53 | isCoverImageNotExists = coverImageNotExists; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/epubparsersampleandroidapplication/BookInfoGridAdapter.java: -------------------------------------------------------------------------------- 1 | package com.github.epubparsersampleandroidapplication; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.BaseAdapter; 10 | import android.widget.ImageView; 11 | import android.widget.TextView; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * Created by Mert on 08.09.2016. 17 | */ 18 | public class BookInfoGridAdapter extends BaseAdapter { 19 | 20 | private Context context; 21 | private List bookInfoList; 22 | 23 | public BookInfoGridAdapter(Context context, List bookInfoList) { 24 | this.context = context; 25 | this.bookInfoList = bookInfoList; 26 | } 27 | 28 | private final class ViewHolder { 29 | public TextView title; 30 | public ImageView coverImage; 31 | } 32 | 33 | @Override 34 | public int getCount() { 35 | return bookInfoList.size(); 36 | } 37 | 38 | @Override 39 | public Object getItem(int i) { 40 | return bookInfoList.get(i); 41 | } 42 | 43 | @Override 44 | public long getItemId(int i) { 45 | return 0; 46 | } 47 | 48 | @Override 49 | public View getView(int position, View convertView, ViewGroup parent) { 50 | ViewHolder viewHolder; 51 | 52 | if (convertView == null) { 53 | LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 54 | convertView = inflater.inflate(R.layout.book_item, parent, false); 55 | 56 | viewHolder = new ViewHolder(); 57 | viewHolder.title = (TextView) convertView.findViewById(R.id.txt_book_title); 58 | viewHolder.coverImage = (ImageView) convertView.findViewById(R.id.img_cover); 59 | 60 | convertView.setTag(viewHolder); 61 | } else { 62 | viewHolder = (ViewHolder) convertView.getTag(); 63 | } 64 | 65 | viewHolder.title.setText(bookInfoList.get(position).getTitle()); 66 | 67 | boolean isCoverImageNotExists = bookInfoList.get(position).isCoverImageNotExists(); 68 | 69 | if (!isCoverImageNotExists) { // Not searched for coverImage for this position yet. It may exist. 70 | Bitmap savedBitmap = bookInfoList.get(position).getCoverImageBitmap(); 71 | 72 | if (savedBitmap != null) { 73 | viewHolder.coverImage.setImageBitmap(savedBitmap); 74 | } else { 75 | byte[] coverImageAsBytes = bookInfoList.get(position).getCoverImage(); 76 | 77 | if (coverImageAsBytes != null) { 78 | Bitmap bitmap = decodeBitmapFromByteArray(coverImageAsBytes, 100, 200); 79 | 80 | bookInfoList.get(position).setCoverImageBitmap(bitmap); 81 | bookInfoList.get(position).setCoverImage(null); 82 | 83 | viewHolder.coverImage.setImageBitmap(bitmap); 84 | } else { // Searched and not found. 85 | bookInfoList.get(position).setCoverImageNotExists(true); 86 | viewHolder.coverImage.setImageResource(android.R.drawable.alert_light_frame); 87 | } 88 | } 89 | } else { // Searched before and not found. 90 | viewHolder.coverImage.setImageResource(android.R.drawable.alert_light_frame); 91 | } 92 | 93 | return convertView; 94 | } 95 | 96 | private Bitmap decodeBitmapFromByteArray(byte[] coverImage, int reqWidth, int reqHeight) { 97 | // First decode with inJustDecodeBounds=true to check dimensions 98 | final BitmapFactory.Options options = new BitmapFactory.Options(); 99 | options.inJustDecodeBounds = true; 100 | BitmapFactory.decodeByteArray(coverImage, 0, coverImage.length, options); 101 | 102 | // Calculate inSampleSize 103 | options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 104 | 105 | // Decode bitmap with inSampleSize set 106 | options.inJustDecodeBounds = false; 107 | return BitmapFactory.decodeByteArray(coverImage, 0, coverImage.length, options); 108 | } 109 | 110 | private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { 111 | // Raw height and width of image 112 | final int height = options.outHeight; 113 | final int width = options.outWidth; 114 | int inSampleSize = 1; 115 | 116 | if (height > reqHeight || width > reqWidth) { 117 | 118 | final int halfHeight = height / 2; 119 | final int halfWidth = width / 2; 120 | 121 | // Calculate the largest inSampleSize value that is a power of 2 and keeps both 122 | // height and width larger than the requested height and width. 123 | while ((halfHeight / inSampleSize) > reqHeight 124 | && (halfWidth / inSampleSize) > reqWidth) { 125 | inSampleSize *= 2; 126 | } 127 | } 128 | 129 | return inSampleSize; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/epubparsersampleandroidapplication/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.epubparsersampleandroidapplication; 2 | 3 | import android.app.SearchManager; 4 | import android.content.Context; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.drawable.BitmapDrawable; 8 | import android.graphics.drawable.Drawable; 9 | import android.os.Bundle; 10 | import android.support.v4.app.Fragment; 11 | import android.support.v4.app.FragmentManager; 12 | import android.support.v4.app.FragmentStatePagerAdapter; 13 | import android.support.v4.view.MenuItemCompat; 14 | import android.support.v4.view.ViewPager; 15 | import android.support.v7.app.AppCompatActivity; 16 | import android.support.v7.widget.SearchView; 17 | import android.support.v7.widget.Toolbar; 18 | import android.text.Html; 19 | import android.text.TextUtils; 20 | import android.util.Base64; 21 | import android.util.DisplayMetrics; 22 | import android.view.Menu; 23 | import android.view.MenuItem; 24 | import android.view.View; 25 | import android.view.ViewGroup; 26 | import android.webkit.WebView; 27 | import android.widget.FrameLayout; 28 | import android.widget.ScrollView; 29 | import android.widget.TextView; 30 | import android.widget.Toast; 31 | 32 | import com.github.mertakdut.BookSection; 33 | import com.github.mertakdut.CssStatus; 34 | import com.github.mertakdut.Reader; 35 | import com.github.mertakdut.exception.OutOfPagesException; 36 | import com.github.mertakdut.exception.ReadingException; 37 | 38 | public class MainActivity extends AppCompatActivity implements PageFragment.OnFragmentReadyListener { 39 | 40 | private Reader reader; 41 | 42 | private ViewPager mViewPager; 43 | 44 | /** 45 | * The {@link android.support.v4.view.PagerAdapter} that will provide 46 | * fragments for each of the sections. We use a 47 | * (FragmentPagerAdapter} derivative, which will keep every 48 | * loaded fragment in memory. If this becomes too memory intensive, it 49 | * may be best to switch to a 50 | * {@link android.support.v4.app.FragmentStatePagerAdapter}. 51 | */ 52 | private SectionsPagerAdapter mSectionsPagerAdapter; 53 | 54 | private int pageCount = Integer.MAX_VALUE; 55 | private int pxScreenWidth; 56 | 57 | private boolean isPickedWebView = false; 58 | 59 | private MenuItem searchMenuItem; 60 | private SearchView searchView; 61 | 62 | private boolean isSkippedToPage = false; 63 | 64 | @Override 65 | protected void onCreate(Bundle savedInstanceState) { 66 | super.onCreate(savedInstanceState); 67 | setContentView(R.layout.activity_main); 68 | 69 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 70 | setSupportActionBar(toolbar); 71 | 72 | pxScreenWidth = getResources().getDisplayMetrics().widthPixels; 73 | 74 | mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); 75 | 76 | mViewPager = (ViewPager) findViewById(R.id.container); 77 | mViewPager.setOffscreenPageLimit(0); 78 | mViewPager.setAdapter(mSectionsPagerAdapter); 79 | 80 | if (getIntent() != null && getIntent().getExtras() != null) { 81 | String filePath = getIntent().getExtras().getString("filePath"); 82 | isPickedWebView = getIntent().getExtras().getBoolean("isWebView"); 83 | 84 | try { 85 | reader = new Reader(); 86 | 87 | // Setting optionals once per file is enough. 88 | reader.setMaxContentPerSection(1250); 89 | reader.setCssStatus(isPickedWebView ? CssStatus.INCLUDE : CssStatus.OMIT); 90 | reader.setIsIncludingTextContent(true); 91 | reader.setIsOmittingTitleTag(true); 92 | 93 | // This method must be called before readSection. 94 | reader.setFullContent(filePath); 95 | 96 | // int lastSavedPage = reader.setFullContentWithProgress(filePath); 97 | if (reader.isSavedProgressFound()) { 98 | int lastSavedPage = reader.loadProgress(); 99 | mViewPager.setCurrentItem(lastSavedPage); 100 | } 101 | 102 | } catch (ReadingException e) { 103 | Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show(); 104 | } 105 | } 106 | } 107 | 108 | @Override 109 | public View onFragmentReady(int position) { 110 | 111 | BookSection bookSection = null; 112 | 113 | try { 114 | bookSection = reader.readSection(position); 115 | } catch (ReadingException e) { 116 | e.printStackTrace(); 117 | Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show(); 118 | } catch (OutOfPagesException e) { 119 | e.printStackTrace(); 120 | this.pageCount = e.getPageCount(); 121 | 122 | if (isSkippedToPage) { 123 | Toast.makeText(MainActivity.this, "Max page number is: " + this.pageCount, Toast.LENGTH_LONG).show(); 124 | } 125 | 126 | mSectionsPagerAdapter.notifyDataSetChanged(); 127 | } 128 | 129 | isSkippedToPage = false; 130 | 131 | if (bookSection != null) { 132 | return setFragmentView(isPickedWebView, bookSection.getSectionContent(), "text/html", "UTF-8"); // reader.isContentStyled 133 | } 134 | 135 | return null; 136 | } 137 | 138 | @Override 139 | public boolean onCreateOptionsMenu(Menu menu) { 140 | getMenuInflater().inflate(R.menu.menu_main, menu); 141 | 142 | SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); 143 | searchMenuItem = menu.findItem(R.id.action_search); 144 | searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem); 145 | searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); 146 | 147 | searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { 148 | @Override 149 | public boolean onQueryTextSubmit(String query) { 150 | 151 | if (query != null && !query.equals("")) { 152 | 153 | if (TextUtils.isDigitsOnly(query)) { 154 | loseFocusOnSearchView(); 155 | 156 | int skippingPage = Integer.valueOf(query); 157 | 158 | if (skippingPage >= 0) { 159 | isSkippedToPage = true; 160 | mViewPager.setCurrentItem(skippingPage); 161 | } else { 162 | Toast.makeText(MainActivity.this, "Page number can't be less than 0", Toast.LENGTH_LONG).show(); 163 | } 164 | 165 | } else { 166 | loseFocusOnSearchView(); 167 | Toast.makeText(MainActivity.this, "Only numbers are allowed", Toast.LENGTH_LONG).show(); 168 | } 169 | 170 | return true; 171 | } 172 | 173 | return false; 174 | } 175 | 176 | @Override 177 | public boolean onQueryTextChange(String newText) { 178 | return false; 179 | } 180 | }); 181 | 182 | return true; 183 | } 184 | 185 | @Override 186 | public void onBackPressed() { 187 | if (!searchView.isIconified()) { 188 | loseFocusOnSearchView(); 189 | } else { 190 | super.onBackPressed(); 191 | } 192 | } 193 | 194 | @Override 195 | protected void onStop() { 196 | super.onStop(); 197 | try { 198 | reader.saveProgress(mViewPager.getCurrentItem()); 199 | Toast.makeText(MainActivity.this, "Saved page: " + mViewPager.getCurrentItem() + "...", Toast.LENGTH_LONG).show(); 200 | } catch (ReadingException e) { 201 | e.printStackTrace(); 202 | Toast.makeText(MainActivity.this, "Progress is not saved: " + e.getMessage(), Toast.LENGTH_LONG).show(); 203 | } catch (OutOfPagesException e) { 204 | e.printStackTrace(); 205 | Toast.makeText(MainActivity.this, "Progress is not saved. Out of Bounds. Page Count: " + e.getPageCount(), Toast.LENGTH_LONG).show(); 206 | } 207 | } 208 | 209 | @Override 210 | public boolean onOptionsItemSelected(MenuItem item) { 211 | 212 | int id = item.getItemId(); 213 | 214 | if (id == R.id.action_search) { 215 | return true; 216 | } 217 | 218 | return super.onOptionsItemSelected(item); 219 | } 220 | 221 | private View setFragmentView(boolean isContentStyled, String data, String mimeType, String encoding) { 222 | 223 | FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 224 | 225 | if (isContentStyled) { 226 | WebView webView = new WebView(MainActivity.this); 227 | webView.loadDataWithBaseURL(null, data, mimeType, encoding, null); 228 | 229 | // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 230 | // webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 231 | // } 232 | 233 | webView.setLayoutParams(layoutParams); 234 | 235 | return webView; 236 | } else { 237 | ScrollView scrollView = new ScrollView(MainActivity.this); 238 | scrollView.setLayoutParams(layoutParams); 239 | 240 | TextView textView = new TextView(MainActivity.this); 241 | textView.setLayoutParams(layoutParams); 242 | 243 | textView.setText(Html.fromHtml(data, new Html.ImageGetter() { 244 | @Override 245 | public Drawable getDrawable(String source) { 246 | String imageAsStr = source.substring(source.indexOf(";base64,") + 8); 247 | byte[] imageAsBytes = Base64.decode(imageAsStr, Base64.DEFAULT); 248 | Bitmap imageAsBitmap = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length); 249 | 250 | int imageWidthStartPx = (pxScreenWidth - imageAsBitmap.getWidth()) / 2; 251 | int imageWidthEndPx = pxScreenWidth - imageWidthStartPx; 252 | 253 | Drawable imageAsDrawable = new BitmapDrawable(getResources(), imageAsBitmap); 254 | imageAsDrawable.setBounds(imageWidthStartPx, 0, imageWidthEndPx, imageAsBitmap.getHeight()); 255 | return imageAsDrawable; 256 | } 257 | }, null)); 258 | 259 | int pxPadding = dpToPx(12); 260 | 261 | textView.setPadding(pxPadding, pxPadding, pxPadding, pxPadding); 262 | 263 | scrollView.addView(textView); 264 | return scrollView; 265 | } 266 | } 267 | 268 | private void loseFocusOnSearchView() { 269 | searchView.setQuery("", false); 270 | searchView.clearFocus(); 271 | searchView.setIconified(true); 272 | MenuItemCompat.collapseActionView(searchMenuItem); 273 | } 274 | 275 | private int dpToPx(int dp) { 276 | DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); 277 | return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT)); 278 | } 279 | 280 | public class SectionsPagerAdapter extends FragmentStatePagerAdapter { 281 | 282 | SectionsPagerAdapter(FragmentManager fm) { 283 | super(fm); 284 | } 285 | 286 | @Override 287 | public int getCount() { 288 | return pageCount; 289 | } 290 | 291 | @Override 292 | public Fragment getItem(int position) { 293 | // getItem is called to instantiate the fragment for the given page. 294 | return PageFragment.newInstance(position); 295 | } 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/epubparsersampleandroidapplication/MenuActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.epubparsersampleandroidapplication; 2 | 3 | import android.content.DialogInterface; 4 | import android.content.Intent; 5 | import android.os.AsyncTask; 6 | import android.os.Bundle; 7 | import android.os.Environment; 8 | import android.support.v7.app.AlertDialog; 9 | import android.support.v7.app.AppCompatActivity; 10 | import android.support.v7.widget.Toolbar; 11 | import android.view.View; 12 | import android.widget.AdapterView; 13 | import android.widget.GridView; 14 | import android.widget.ProgressBar; 15 | import android.widget.Toast; 16 | 17 | import com.github.mertakdut.Reader; 18 | import com.github.mertakdut.exception.ReadingException; 19 | 20 | import java.io.File; 21 | import java.io.FileOutputStream; 22 | import java.io.InputStream; 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | public class MenuActivity extends AppCompatActivity { 27 | 28 | private ProgressBar progressBar; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_menu); 34 | 35 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 36 | setSupportActionBar(toolbar); 37 | 38 | ((GridView) findViewById(R.id.grid_book_info)).setOnItemClickListener(new AdapterView.OnItemClickListener() { 39 | @Override 40 | public void onItemClick(AdapterView adapterView, View view, int i, long l) { 41 | String clickedItemFilePath = ((BookInfo) adapterView.getAdapter().getItem(i)).getFilePath(); 42 | askForWidgetToUse(clickedItemFilePath); 43 | } 44 | }); 45 | 46 | progressBar = (ProgressBar) findViewById(R.id.progressbar); 47 | 48 | new ListBookInfoTask().execute(); 49 | } 50 | 51 | private class ListBookInfoTask extends AsyncTask> { 52 | 53 | private Exception occuredException; 54 | 55 | @Override 56 | protected void onPreExecute() { 57 | super.onPreExecute(); 58 | progressBar.setVisibility(View.VISIBLE); 59 | } 60 | 61 | @Override 62 | protected List doInBackground(Object... params) { 63 | List bookInfoList = searchForPdfFiles(); 64 | 65 | Reader reader = new Reader(); 66 | for (BookInfo bookInfo : bookInfoList) { 67 | try { 68 | reader.setInfoContent(bookInfo.getFilePath()); 69 | 70 | String title = reader.getInfoPackage().getMetadata().getTitle(); 71 | if (title != null && !title.equals("")) { 72 | bookInfo.setTitle(reader.getInfoPackage().getMetadata().getTitle()); 73 | } else { // If title doesn't exist, use fileName instead. 74 | int dotIndex = bookInfo.getTitle().lastIndexOf('.'); 75 | bookInfo.setTitle(bookInfo.getTitle().substring(0, dotIndex)); 76 | } 77 | 78 | bookInfo.setCoverImage(reader.getCoverImage()); 79 | } catch (ReadingException e) { 80 | occuredException = e; 81 | e.printStackTrace(); 82 | } 83 | } 84 | 85 | return bookInfoList; 86 | } 87 | 88 | @Override 89 | protected void onPostExecute(List bookInfoList) { 90 | super.onPostExecute(bookInfoList); 91 | progressBar.setVisibility(View.GONE); 92 | 93 | if (bookInfoList != null) { 94 | BookInfoGridAdapter adapter = new BookInfoGridAdapter(MenuActivity.this, bookInfoList); 95 | ((GridView) findViewById(R.id.grid_book_info)).setAdapter(adapter); 96 | } 97 | 98 | if (occuredException != null) { 99 | Toast.makeText(MenuActivity.this, occuredException.getMessage(), Toast.LENGTH_LONG).show(); 100 | } 101 | } 102 | } 103 | 104 | private List searchForPdfFiles() { 105 | boolean isSDPresent = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); 106 | 107 | List bookInfoList = null; 108 | 109 | if (isSDPresent) { 110 | bookInfoList = new ArrayList<>(); 111 | 112 | List files = getListFiles(new File(Environment.getExternalStorageDirectory().getAbsolutePath())); 113 | 114 | File sampleFile = getFileFromAssets("pg28885-images_new.epub"); 115 | files.add(0, sampleFile); 116 | 117 | for (File file : files) { 118 | BookInfo bookInfo = new BookInfo(); 119 | 120 | bookInfo.setTitle(file.getName()); 121 | bookInfo.setFilePath(file.getPath()); 122 | 123 | bookInfoList.add(bookInfo); 124 | } 125 | } 126 | 127 | return bookInfoList; 128 | } 129 | 130 | public File getFileFromAssets(String fileName) { 131 | 132 | File file = new File(getCacheDir() + "/" + fileName); 133 | 134 | if (!file.exists()) try { 135 | 136 | InputStream is = getAssets().open(fileName); 137 | int size = is.available(); 138 | byte[] buffer = new byte[size]; 139 | is.read(buffer); 140 | is.close(); 141 | 142 | FileOutputStream fos = new FileOutputStream(file); 143 | fos.write(buffer); 144 | fos.close(); 145 | } catch (Exception e) { 146 | throw new RuntimeException(e); 147 | } 148 | 149 | return file; 150 | } 151 | 152 | private List getListFiles(File parentDir) { 153 | ArrayList inFiles = new ArrayList<>(); 154 | File[] files = parentDir.listFiles(); 155 | if (files != null) { 156 | for (File file : files) { 157 | if (file.isDirectory()) { 158 | inFiles.addAll(getListFiles(file)); 159 | } else { 160 | if (file.getName().endsWith(".epub")) { 161 | inFiles.add(file); 162 | } 163 | } 164 | } 165 | } 166 | return inFiles; 167 | } 168 | 169 | private void askForWidgetToUse(final String filePath) { 170 | 171 | final Intent intent = new Intent(MenuActivity.this, MainActivity.class); 172 | intent.putExtra("filePath", filePath); 173 | 174 | new AlertDialog.Builder(MenuActivity.this) 175 | .setTitle("Pick your widget") 176 | .setMessage("Textview or WebView?") 177 | .setPositiveButton("TextView", new DialogInterface.OnClickListener() { 178 | public void onClick(DialogInterface dialog, int which) { 179 | intent.putExtra("isWebView", false); 180 | startActivity(intent); 181 | } 182 | }) 183 | .setNegativeButton("WebView", new DialogInterface.OnClickListener() { 184 | public void onClick(DialogInterface dialog, int which) { 185 | intent.putExtra("isWebView", true); 186 | startActivity(intent); 187 | } 188 | }) 189 | .setIcon(android.R.drawable.ic_dialog_alert) 190 | .show(); 191 | 192 | 193 | } 194 | 195 | } 196 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/epubparsersampleandroidapplication/PageFragment.java: -------------------------------------------------------------------------------- 1 | package com.github.epubparsersampleandroidapplication; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.RelativeLayout; 10 | 11 | /** 12 | * Created by Mert on 08.09.2016. 13 | */ 14 | public class PageFragment extends Fragment { 15 | /** 16 | * The fragment argument representing the section number for this 17 | * fragment. 18 | */ 19 | private static final String ARG_TAB_POSITON = "tab_position"; 20 | 21 | private OnFragmentReadyListener onFragmentReadyListener; 22 | 23 | /** 24 | * Returns a new instance of this fragment for the given section 25 | * number. 26 | */ 27 | public static PageFragment newInstance(int tabPosition) { 28 | PageFragment fragment = new PageFragment(); 29 | Bundle args = new Bundle(); 30 | args.putInt(ARG_TAB_POSITON, tabPosition); 31 | fragment.setArguments(args); 32 | return fragment; 33 | } 34 | 35 | public PageFragment() { 36 | } 37 | 38 | public interface OnFragmentReadyListener { 39 | View onFragmentReady(int position); 40 | } 41 | 42 | @Override 43 | public void onAttach(Context context) { 44 | super.onAttach(context); 45 | onFragmentReadyListener = (OnFragmentReadyListener) context; //Activity version is deprecated. 46 | } 47 | 48 | @Override 49 | public void onDestroy() { 50 | super.onDestroy(); 51 | onFragmentReadyListener = null; 52 | } 53 | 54 | @Override 55 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 56 | View rootView = inflater.inflate(R.layout.fragment_display, container, false); 57 | 58 | RelativeLayout mainLayout = (RelativeLayout) rootView.findViewById(R.id.fragment_main_layout); 59 | 60 | View view = onFragmentReadyListener.onFragmentReady(getArguments().getInt(ARG_TAB_POSITON)); 61 | 62 | if (view != null) { 63 | mainLayout.addView(view); 64 | } 65 | 66 | return rootView; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/book_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 15 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 20 | 21 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_display.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mertakdut/EpubParser-Sample-Android-Application/ee41597b64ce69db58b5dd3610cc4688f5c3fd5f/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mertakdut/EpubParser-Sample-Android-Application/ee41597b64ce69db58b5dd3610cc4688f5c3fd5f/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mertakdut/EpubParser-Sample-Android-Application/ee41597b64ce69db58b5dd3610cc4688f5c3fd5f/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mertakdut/EpubParser-Sample-Android-Application/ee41597b64ce69db58b5dd3610cc4688f5c3fd5f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mertakdut/EpubParser-Sample-Android-Application/ee41597b64ce69db58b5dd3610cc4688f5c3fd5f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | EpubParser Sample Android Application 3 | MenuActivity 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |