From 10240ef13a7770a5cd43a40e39d2d287a7a18933 Mon Sep 17 00:00:00 2001 From: zsakvo Date: Wed, 20 Feb 2019 22:07:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20epub=20=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 2 + .../zsakvo/yueduhchelper/utils/EpubUtil.java | 459 ++++++++++++++++++ .../yueduhchelper/view/ExportActivity.java | 219 +++++++-- .../yueduhchelper/view/ShowLibsFragment.java | 12 + app/src/main/res/xml/libs.xml | 10 + 5 files changed, 665 insertions(+), 37 deletions(-) create mode 100644 app/src/main/java/cc/zsakvo/yueduhchelper/utils/EpubUtil.java diff --git a/app/build.gradle b/app/build.gradle index 0ec185f..00ad862 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -35,6 +35,8 @@ dependencies { implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' implementation 'io.reactivex.rxjava2:rxjava:2.2.6' implementation 'com.github.bumptech.glide:glide:4.8.0' + implementation 'org.jsoup:jsoup:1.11.3' + implementation 'org.zeroturnaround:zt-zip:1.8' implementation "com.leinardi.android:speed-dial:2.0.0" annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0' testImplementation 'junit:junit:4.12' diff --git a/app/src/main/java/cc/zsakvo/yueduhchelper/utils/EpubUtil.java b/app/src/main/java/cc/zsakvo/yueduhchelper/utils/EpubUtil.java new file mode 100644 index 0000000..6bdda79 --- /dev/null +++ b/app/src/main/java/cc/zsakvo/yueduhchelper/utils/EpubUtil.java @@ -0,0 +1,459 @@ +package cc.zsakvo.yueduhchelper.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; + +import com.bumptech.glide.Glide; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Element; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import cc.zsakvo.yueduhchelper.bean.ExportChapter; + +public class EpubUtil { + private static final String TAG = "EpubUtil"; + public static String BOOKTOC = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "Table Of Contents\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "

目录

\n" + + "
\n" + + "
\n" + + "toreplace0\n" + + "
\n" + + "
\n" + + "\n" + + "\n"; + public static String CHAPTER = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "toreplace0 - 0\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "toreplace1\n" + + "\n" + + ""; + public static String CONTAINER = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + ""; + public static String CONTENT = "\n" + + "\n" + + "\n" + + "easypub-c260e840\n" + + "toreplace0\n" + + "toreplace1\n" + + "2018\n" + + "Created with EasyPub v1.50\n" + + "zh-CN\n" + + "\n" + + "\n" + + "toreplace2\n" + + "toreplace3" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n"; + public static String MIMETYPE = "application/epub+zip"; + public static String STYLE = "@font-face {\n" + + " font-family: \"easypub\";\n" + + " src: url(res:///system/fonts/DroidSansFallback.ttf),\n" + + " url(res:///ebook/fonts/../../system/fonts/DroidSansFallback.ttf);\n" + + "}\n" + + "\n" + + "@page { \n" + + " margin-top: 0px;\n" + + " margin-bottom: 0px;\n" + + "}\n" + + "\n" + + "body { \n" + + " font-family: \"easypub\";\n" + + " padding: 0;\n" + + " margin-left: 0px;\n" + + " margin-right: 0px;\n" + + " orphans: 0;\n" + + " widows: 0;\n" + + "}\n" + + "\n" + + "p { \n" + + " font-family: \"easypub\";\n" + + " font-size: 120%;\n" + + " line-height: 125%;\n" + + " margin-top: 5px;\n" + + " margin-bottom: 0;\n" + + " margin-left: 0;\n" + + " margin-right: 0;\n" + + " orphans: 0;\n" + + " widows: 0;\n" + + "}\n" + + "\n" + + ".a { \n" + + " text-indent: 0em;\n" + + "}\n" + + "\n" + + "div.centeredimage {\n" + + " text-align:center;\n" + + " display:block;\n" + + " margin-top: 0.5em;\n" + + " margin-bottom: 0.5em;\n" + + "}\n" + + "\n" + + "img.attpic {\n" + + " border: 1px solid #000000;\n" + + " max-width: 100%;\n" + + " margin: 0;\n" + + "}\n" + + "\n" + + ".booktitle {\n" + + " margin-top: 30%;\n" + + " margin-bottom: 0;\n" + + " border-style: none solid none none;\n" + + " border-width: 50px;\n" + + " border-color: #4E594D;\n" + + " font-size: 3em;\n" + + " line-height: 120%;\n" + + " text-align: right;\n" + + "}\n" + + "\n" + + ".bookauthor {\n" + + " margin-top: 0;\n" + + " border-style: none solid none none;\n" + + " border-width: 50px;\n" + + " border-color: #4E594D;\n" + + " page-break-after: always;\n" + + " font-size: large;\n" + + " line-height: 120%;\n" + + " text-align: right;\n" + + "}\n" + + "\n" + + ".titletoc, .titlel1top, .titlel1std,.titlel2top, .titlel2std,.titlel3top, .titlel3std,.titlel4std {\n" + + " margin-top: 0;\n" + + " border-style: none double none solid;\n" + + " border-width: 0px 5px 0px 20px;\n" + + " border-color: #586357;\n" + + " background-color: #C1CCC0;\n" + + " padding: 45px 5px 5px 5px;\n" + + " font-size: x-large;\n" + + " line-height: 115%;\n" + + " text-align: justify;\n" + + "}\n" + + "\n" + + ".titlel1single,.titlel2single,.titlel3single {\n" + + " margin-top: 35%;\n" + + " border-style: none solid none none;\n" + + " border-width: 30px;\n" + + " border-color: #4E594D;\n" + + " padding: 30px 5px 5px 5px;\n" + + " font-size: x-large;\n" + + " line-height: 125%;\n" + + " text-align: right;\n" + + "}\n" + + "\n" + + ".toc {\n" + + " margin-left:16%;\n" + + " padding:0px;\n" + + " line-height:130%;\n" + + " text-align: justify;\n" + + "}\n" + + "\n" + + ".toc a { text-decoration: none; color: #000000; }\n" + + "\n" + + ".tocl1 {\n" + + " margin-top:0.5em;\n" + + " margin-left:-30px;\n" + + " border-style: none double double solid;\n" + + " border-width: 0px 5px 2px 20px;\n" + + " border-color: #6B766A;\n" + + " line-height: 135%;\n" + + " font-size: 132%;\n" + + "}\n" + + "\n" + + ".tocl2 {\n" + + " margin-top: 0.5em;\n" + + " margin-left:-20px;\n" + + " border-style: none double none solid;\n" + + " border-width: 0px 2px 0px 10px;\n" + + " border-color: #939E92;\n" + + " line-height: 123%;\n" + + " font-size: 120%;\n" + + "}\n" + + "\n" + + ".tocl3 {\n" + + " margin-top: 0.5em;\n" + + " margin-left:-20px;\n" + + " border-style: none double none solid;\n" + + " border-width: 0px 2px 0px 8px;\n" + + " border-color: #939E92;\n" + + " line-height: 112%;\n" + + " font-size: 109%;\n" + + "}\n" + + "\n" + + ".tocl4 {\n" + + " margin-top: 0.5em;\n" + + " margin-left:-20px;\n" + + " border-style: none double none solid;\n" + + " border-width: 0px 2px 0px 6px;\n" + + " border-color: #939E92;\n" + + " line-height: 115%;\n" + + " font-size: 110%;\n" + + "}\n" + + "\n" + + ".subtoc {\n" + + " margin-left:15%;\n" + + " padding:0px;\n" + + " text-align: justify;\n" + + "}\n" + + "\n" + + ".subtoclist {\n" + + " margin-top: 0.5em;\n" + + " margin-left:-20px;\n" + + " border-style: none double none solid;\n" + + " border-width: 0px 2px 0px 10px;\n" + + " border-color: #939E92;\n" + + " line-height: 123%;\n" + + " font-size: 120%;\n" + + "}\n" + + "\n"; + public static String TOC = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "toreplace0\n" + + "\n" + + "\n" + + "toreplace1\n" + + "\n" + + "\n" + + "toreplace2" + + "\n"; + + public static String COVERHTML = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "Cover\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
\n" + + "
\n" + + "
\n" + + "\"toreplace0\"\n" + + "
\n" + + "
\n" + + "\n" + + ""; + + public static String ELE_DT_A = "
Table
"; + + public static String ELE_MANIFEST = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + ""; + + public static String ELE_SPINE = "\n" + + "\n" + + "\n" + + ""; + + public static String ELE_NAV_MAP = "\n" + + "\n" + + "THETEXT\n" + + "\n" + + "\n"; + + public static String ELE_CHAPTER_BODY = "\n" + + "

\n" + + "

\n" + + ""; + + private String bookName; + private String author; + private String epubCachePath; + private List exportArray; + private Context mContext; + private String coverUrl; + + public EpubUtil(String bookName, String author, String coverUrl, String epubCachePath, List exportArray, Context mContext) { + this.bookName = bookName; + this.author = author; + this.epubCachePath = epubCachePath; + this.exportArray = exportArray; + this.mContext = mContext; + this.coverUrl = coverUrl; + } + + public boolean build() { + if (!new File(epubCachePath + "/META-INF").mkdirs()) return false; + if (!new File(epubCachePath + "/OEBPS").mkdirs()) return false; + if (!writeFile(epubCachePath + "/mimetype", MIMETYPE)) return false; + if (!writeFile(epubCachePath + "/META-INF/container.xml", CONTAINER)) return false; + if (!writeFile(epubCachePath + "/OEBPS/style.css", STYLE)) return false; + if (!generateTocNcx(bookName, author, exportArray, epubCachePath)) return false; + if (!generateContentOpf(bookName, author, epubCachePath, exportArray.size())) return false; + if (!generateBookToc(exportArray, epubCachePath)) return false; + if (!generateCoverHtml(bookName, epubCachePath)) return false; + Drawable drawable = null; + try { + drawable = Glide.with(mContext) + .load(coverUrl) + .submit() + .get(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return saveBitmap(drawableToBitmap2(drawable), epubCachePath + "/OEBPS/cover.jpg"); + } + + private static Bitmap drawableToBitmap2(Drawable drawable) { + BitmapDrawable bd = (BitmapDrawable) drawable; + return bd.getBitmap(); + } + + + private static boolean saveBitmap(Bitmap bitmap, String path) { + + File file = new File(path); + if(file.exists()) { + if(!file.delete()) return false; + } + try { + FileOutputStream fileOutputStream = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.PNG, 100, ((OutputStream)fileOutputStream));//设置PNG的话,透明区域不会变成黑色 + fileOutputStream.close(); + System.out.println("----------save success-------------------"); + return true; + } + catch(Exception v0) { + v0.printStackTrace(); + return false; + } + + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + public static boolean writeFile(String path, String str) { + File file = new File(path); + if (file.exists()) file.delete(); + try { + file.createNewFile(); + BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file)); + bufferedWriter.write(str); + bufferedWriter.flush(); + bufferedWriter.close(); + return true; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + + public static boolean generateTocNcx(String bookName, String bookAuthor, List exportArray, String cachePath) { + String fileText = TOC; + { + StringBuilder d = new StringBuilder(); + String e = ELE_NAV_MAP; + d.append(e.replace("POD", "1").replace("THETEXT", " 封面 ").replace("THEHTML", "cover.html")); + d.append(e.replace("POD", "2").replace("THETEXT", " 目录 ").replace("THEHTML", "book-toc.html")); + int playorder = 3; + int chapter = 0; + for (int i = 0; i < exportArray.size(); i++) { + d.append(e.replace("POD", "" + playorder).replace("THETEXT", exportArray.get(i).getChapterInfo()).replace("THEHTML", "chapter" + chapter + ".html")); + playorder++; + chapter++; + } + fileText = fileText.replace("toreplace0", bookName); + fileText = fileText.replace("toreplace1", bookAuthor); + fileText = fileText.replace("toreplace2", d); + return writeFile(cachePath + "/OEBPS/toc.ncx", fileText); + } + } + + public static boolean generateContentOpf(String bookName, String bookAuthor, String cachePath, int chapterNums) { + String fileText = CONTENT; + Element element_manifest = Jsoup.parse(ELE_MANIFEST).selectFirst("manifest"); + Element element_spine = Jsoup.parse(ELE_SPINE).selectFirst("spine"); + Element d = element_manifest.select("item").get(4).clone(); + Element e = element_spine.select("itemref").get(1).clone(); + int chapter = 0; + for (int i = 0; i < chapterNums; i++) { + d.selectFirst("item").attr("id", "chapter" + chapter); + d.selectFirst("item").attr("href", "chapter" + chapter + ".html"); + e.selectFirst("itemref").attr("idref", "chapter" + chapter); + element_manifest.append(d.toString()); + element_spine.append(e.toString()); + chapter++; + } + fileText = fileText.replace("toreplace0", bookName); + fileText = fileText.replace("toreplace1", bookAuthor); + fileText = fileText.replace("toreplace2", element_manifest.toString()); + fileText = fileText.replace("toreplace3", element_spine.toString()); + return writeFile(cachePath + "/OEBPS/content.opf", fileText); + } + + public static boolean generateBookToc(List exportArray, String cachePath) { + String fileText = BOOKTOC; + StringBuilder tmp = new StringBuilder(); + int chapter = 0; + for (int i = 0; i < exportArray.size(); i++) { + tmp.append(ELE_DT_A.replace("chapter.html", "chapter" + chapter).replace("Table", exportArray.get(i).getChapterInfo())).append("\n"); + chapter++; + } + fileText = fileText.replace("toreplace0", tmp.toString()); + return writeFile(cachePath + "/OEBPS/book-toc.html", fileText); + } + + public static boolean generateCoverHtml(String bookName, String cachePath) { + return writeFile(cachePath + "/OEBPS/cover.html", COVERHTML.replace("toreplace0", bookName)); + } +} diff --git a/app/src/main/java/cc/zsakvo/yueduhchelper/view/ExportActivity.java b/app/src/main/java/cc/zsakvo/yueduhchelper/view/ExportActivity.java index 316695d..e0785db 100644 --- a/app/src/main/java/cc/zsakvo/yueduhchelper/view/ExportActivity.java +++ b/app/src/main/java/cc/zsakvo/yueduhchelper/view/ExportActivity.java @@ -2,11 +2,13 @@ import android.annotation.SuppressLint; import android.content.Context; +import android.content.Intent; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.util.Log; @@ -21,6 +23,9 @@ import com.leinardi.android.speeddial.SpeedDialActionItem; import com.leinardi.android.speeddial.SpeedDialView; +import org.zeroturnaround.zip.NameMapper; +import org.zeroturnaround.zip.ZipUtil; + import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -47,6 +52,7 @@ import cc.zsakvo.yueduhchelper.bean.CacheBooks; import cc.zsakvo.yueduhchelper.bean.ExportChapter; import cc.zsakvo.yueduhchelper.utils.Divider; +import cc.zsakvo.yueduhchelper.utils.EpubUtil; import cc.zsakvo.yueduhchelper.utils.SourceUtil; import io.reactivex.Observable; import io.reactivex.ObservableOnSubscribe; @@ -57,7 +63,7 @@ public class ExportActivity extends BaseActivity { - private static final String TAG = "ExportActivity" + "" ; + private static final String TAG = "ExportActivity" + ""; private Toolbar toolbar; private String bookName; private String author; @@ -122,7 +128,7 @@ public int bindMenu() { } @Override - public void onStart(){ + public void onStart() { super.onStart(); } @@ -145,7 +151,7 @@ public void clickMenu(MenuItem item) { break; case R.id.exchange_source: if (source.length <= 1) { - showSnackBar("只有一个缓存源,无需切换", coord); + showSnackBar("只有一个缓存源,无需切换", speedDialView); } else { AlertDialog.Builder builder = new AlertDialog.Builder(ExportActivity.this); builder.setTitle("切换缓存源"); @@ -195,9 +201,9 @@ public void initView(View view) { RecyclerView mRecyclerView = $(R.id.export_epub_list); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); - mRecyclerView.addItemDecoration(new Divider(this,24)); + mRecyclerView.addItemDecoration(new Divider(this, 24)); - adapter = new ExportBooksAdapter(exportArray,flag); + adapter = new ExportBooksAdapter(exportArray, flag); mRecyclerView.setAdapter(adapter); } @@ -212,11 +218,12 @@ public void doBusiness(Context mContext) { autoDel = getSharedPreferences("settings", MODE_PRIVATE).getBoolean("ad_auto_del", false); String folderPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Documents/YueDuTXT"; outPath = getSharedPreferences("settings", MODE_PRIVATE).getString("outPath", folderPath) + "/"; + CacheBooks cb = (CacheBooks) getIntent().getSerializableExtra("books"); cacheFilePath = cb.getCachePath(); - if (cb.isDetail()){ + if (cb.isDetail()) { epubInfo.setVisibility(View.VISIBLE); - }else { + } else { epubInfo.setVisibility(View.GONE); } bookName = cb.getName(); @@ -224,24 +231,32 @@ public void doBusiness(Context mContext) { intro = cb.getIntro(); coverUrl = cb.getCoverUrl(); tvBookName.setText(bookName); - tvAuthor.setText(String.format(getResources().getString(R.string.epub_author),author)); - tvIntro.setText(String.format(getResources().getString(R.string.epub_intro),intro)); - if (coverUrl==null){ + tvAuthor.setText(String.format(getResources().getString(R.string.epub_author), author)); + tvIntro.setText(String.format(getResources().getString(R.string.epub_intro), intro)); + if (coverUrl == null) { ivCover.setImageBitmap(getNoCover()); - }else { + } else { Glide.with(this) .load(coverUrl) .into(ivCover); } - if (cb.getSourcePath()!=null){ + + if (!new File(outPath).exists()) { + if (!new File(outPath).mkdirs()) { + showSnackBar("环境初始化失败……!", speedDialView); + return; + } + } + + if (cb.getSourcePath() != null) { source = cb.getSourcePath().split(","); sourceList = new String[source.length]; - for (int i=0;i chapters = new ArrayList<>(); for (int i = 0; i < flag.size(); i++) { if (flag.get(i)) { @@ -291,17 +307,144 @@ private void exportTXT(){ } } if (chapters.size() == 0) { - showSnackBar("请至少勾选一章", coord); + showSnackBar("请至少勾选一章", speedDialView); } else { AlertDialog.Builder builder = new AlertDialog.Builder(ExportActivity.this); builder.setCancelable(false); builder.setView(R.layout.loading_dialog); progressDialog = builder.create(); - writeCache(cacheFilePath,chapters); + writeCacheForTXT(cacheFilePath, chapters); } } - private void writeCache(String cacheFilePath, ArrayList list) { + private void exportEpub() { + ArrayList chapters = new ArrayList<>(); + for (int i = 0; i < flag.size(); i++) { + if (flag.get(i)) { + chapters.add(chapterFilePath.get(i)); + } + } + if (chapters.size() == 0) { + showSnackBar("请至少勾选一章", speedDialView); + } else { + AlertDialog.Builder builder = new AlertDialog.Builder(ExportActivity.this); + builder.setCancelable(false); + builder.setView(R.layout.loading_dialog); + progressDialog = builder.create(); + writeCacheForEpub(cacheFilePath, chapters); + } + } + + private void writeCacheForEpub(String cacheFilePath, ArrayList list) { + progress = 0; + progressDialog.show(); + String epubCachePath = outPath + "cache/" + bookName; + + TextView tv_progress = progressDialog.findViewById(R.id.progress_text); + Observable.create((ObservableOnSubscribe) emitter -> { + + try { + deleteDirectory(new File(epubCachePath)); + if (!new EpubUtil(bookName,author,coverUrl,epubCachePath,exportArray,ExportActivity.this).build()) emitter.onError(new Throwable("init failed !")); + int c = 0; + for (String s : list) { + StringBuilder content = new StringBuilder(); + File file = new File(s); + if (!file.isDirectory()) { + if (file.getName().endsWith("nb")) { + try { + InputStream instream = new FileInputStream(file); + InputStreamReader inputreader + = new InputStreamReader(instream, StandardCharsets.UTF_8); + BufferedReader buffreader = new BufferedReader(inputreader); + String line; + while ((line = buffreader.readLine()) != null) { + content.append(line).append("\n"); + } + instream.close(); + String str = content.toString().replace("  ", "

"); + String fileText = EpubUtil.CHAPTER.replace("toreplace0", "chapter" + c); + fileText = fileText.replace("toreplace1", str); + emitter.onNext(fileText); + c++; + } catch (FileNotFoundException e) { + Log.d("ReadCache", "The File doesn't not exist."); + } catch (IOException e) { + Log.d("ReadCache", e.getMessage()); + } + } + } + } + emitter.onComplete(); + + } catch (Exception e) { + e.printStackTrace(); + } + + }).subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer() { + int i = 0; + @Override + public void onSubscribe(Disposable d) { + if (tv_progress != null) tv_progress.setText("正在初始化……"); + Log.d(TAG, "subscribe"); + if (!new File(outPath).exists()) { + if (new File(outPath).mkdirs()) { + Log.d(TAG, "onSubscribe: " + "文件夹创建成功"); + } + } else if (new File(outPath + bookName + ".txt").exists()) { + if (new File(outPath + bookName + ".txt").delete()) { + Log.d(TAG, "已清除原有导出数据"); + } + } + } + + @Override + public void onNext(String string) { + try { + EpubUtil.writeFile(epubCachePath + "/OEBPS/chapter" + i + ".html", string); + i++; + if (tv_progress != null) + tv_progress.setText(String.format(getResources().getString(R.string.exporting), i, list.size())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onError(Throwable e) { + Log.d(TAG, "error"); + progressDialog.cancel(); + showSnackBar("导出失败!", speedDialView); + } + + @Override + public void onComplete() { + Log.d(TAG, "complete"); + ZipUtil.pack(new File(epubCachePath), new File(outPath + bookName + ".epub"), new NameMapper() { + public String map(String name) { + return name; + } + }); + deleteDirectory(new File(epubCachePath)); + if (autoDel) { + deleteDirectory(new File(cacheFilePath)); + } + + final Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + final Uri contentUri = Uri.fromFile(new File(outPath + bookName + ".epub")); + scanIntent.setData(contentUri); + sendBroadcast(scanIntent); + + + progressDialog.cancel(); + showSnackBar("导出成功!", speedDialView); + } + }); + } + + private void writeCacheForTXT(String cacheFilePath, ArrayList list) { progress = 0; progressDialog.show(); @@ -382,7 +525,7 @@ public void onError(Throwable e) { } catch (IOException e1) { e1.printStackTrace(); } - showSnackBar("导出失败!", coord); + showSnackBar("导出失败!", speedDialView); } @Override @@ -398,7 +541,7 @@ public void onComplete() { deleteDirectory(new File(cacheFilePath)); } progressDialog.cancel(); - showSnackBar("导出成功!", coord); + showSnackBar("导出成功!", speedDialView); } }); } @@ -406,32 +549,34 @@ public void onComplete() { @SuppressWarnings("ResultOfMethodCallIgnored") private void deleteDirectory(File file) { File files[] = file.listFiles(); - for (File file1 : files) { - if (file1.isFile()) { - file1.delete(); - } else if (file1.isDirectory()) { - deleteDirectory(file1); + if (files!=null){ + for (File file1 : files) { + if (file1.isFile()) { + file1.delete(); + } else if (file1.isDirectory()) { + deleteDirectory(file1); + } } + file.delete(); } - file.delete(); } @Override public boolean onPrepareOptionsMenu(Menu menu) { - if (exportArray.size()==0) { + if (exportArray.size() == 0) { menu.findItem(R.id.export_check_invert).setVisible(false); menu.findItem(R.id.exchange_source).setVisible(false); - }else { + } else { menu.findItem(R.id.export_check_invert).setVisible(true); menu.findItem(R.id.exchange_source).setVisible(true); } return super.onPrepareOptionsMenu(menu); } - private Bitmap getNoCover(){ + private Bitmap getNoCover() { AssetManager assetManager = getAssets(); try { - InputStream in=assetManager.open("nocover.jpg"); + InputStream in = assetManager.open("nocover.jpg"); return BitmapFactory.decodeStream(in); } catch (Exception e) { e.printStackTrace(); @@ -448,10 +593,10 @@ private void chooseInvert() { private void showChapters() { - if (cacheFiles!=null){ + if (cacheFiles != null) { exportInfo.setText(String.format(getResources().getString(R.string.export_info), chapterNames.size(), SourceUtil.trans(cacheFilePath.split("-")[1]))); for (int i = 0; i < chapterNames.size(); i++) { - exportArray.add(new ExportChapter(chapterNames.get(i),false)); + exportArray.add(new ExportChapter(chapterNames.get(i), false)); flag.add(true); } adapter.notifyDataSetChanged(); @@ -472,20 +617,20 @@ private void scanChapters() { chapterFilePath = new ArrayList<>(); File[] files = new File(cacheFilePath).listFiles(); - LinkedHashMap map = new LinkedHashMap<>(); + LinkedHashMap map = new LinkedHashMap<>(); for (File f : files) { int chapterSN = Integer.parseInt(f.getName().split("-")[0]); String chapterName = f.getName().split("-")[1].replace(".nb", ""); - map.put(chapterSN,chapterName); + map.put(chapterSN, chapterName); } List snList = new ArrayList<>(map.keySet()); Collections.sort(snList); - for (int i=0;i + + + + \ No newline at end of file