FolioReader / FolioReader-Android

A Java ePub reader and parser framework for Android.
BSD 3-Clause "New" or "Revised" License
2.24k stars 710 forks source link

crash in Android 11 on progress bar #493

Open akshayjain2910 opened 3 years ago

akshayjain2910 commented 3 years ago

Issue / Feature - issue FolioReader version - 0.5.4 FolioReader Stock / Modified -
Android SDK - Mobile / Tablet / Emulator Info - samsung m31S, one plus IN2011 Crash / Error - Fatal Exception: java.lang.RuntimeException Can't create handler inside thread Thread[Thread-3,5,main] that has not called Looper.prepare()

Steps to reproduce / Describe in detail -

every time i am getting this crash in my android 11 devices and in logcat it points me on progressbar ,I have also set some conditions to not to download the file if its already downloaded but its still downloading it .. sharing the code here

  bookprogress = SharedPrefManager.getInstance(context).getBookProgress(
            SharedPrefManager
                    .getInstance(chaptercontext)
                    .getBookId()
    );
}

public static String getFileExt(String fileName) {
    Log.d("aj", "getFileExt: checked ");
    return fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
}

@NonNull
@Override
public CourseChapterListAdapter.viewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(chaptercontext);
    View view = inflater.inflate(R.layout.chapter_view, null);
    folioReader = FolioReader.get()
            .setOnHighlightListener(this)
            .setReadLocatorListener(this)
            .setOnClosedListener(this);
    return new viewholder(view);

}

@Override
public void onBindViewHolder(@NonNull CourseChapterListAdapter.viewholder holder, int position) {
    CourseChapter chapter_model = chapters.get(position);
    SharedPrefManager.getInstance(chaptercontext).saveCourseTotalCount((chapters.size()));

    FolioReader folioReader = FolioReader.get()
            .setOnHighlightListener(this)
            .setReadLocatorListener(this)
            .setOnClosedListener(this);

    holder.name.setText(chapter_model.getName());
    chaptername = chapter_model.getName();
    int number_string = chapter_model.getNumber();

    if (number_string == 0) {
        Log.d("aj", "onBindViewHolder: if null " + number_string);

        holder.number.setText("");
    } else {
        Log.d("aj", "onBindViewHolder: else " + number_string);
        holder.number.setText(String.valueOf(chapter_model.getNumber()));

    }
    getVoiceCount();

    holder.name.setOnClickListener(v -> {
        if (bookprogress <= position) {
            bookprogress++;
            SharedPrefManager.getInstance(chaptercontext).saveBookProgress(SharedPrefManager.getInstance(chaptercontext).getBookId(), bookprogress);
        }
        Log.d("GetBook", "onBindViewHolder: else " + SharedPrefManager
                .getInstance(chaptercontext)
                .getBookId());

        SharedPrefManager.getInstance(chaptercontext).setChapterId(chapter_model.getId());
        folioReader.setReadLocator(null);
        readBook(chapter_model);
    });
    holder.resumebook.setOnClickListener(v -> {
        getHighlightsAndSave();
        ReadLocator readLocator = getLastReadLocator();
        folioReader.setReadLocator(readLocator);
        readBook(chapter_model);

    });
}

@Override
public int getItemCount() {
    return chapters.size();
}

private ReadLocator getLastReadLocator() {
    try {
        String loc = chaptercontext.getFilesDir().getAbsolutePath() + "/read_locator.json";
        File file = new File(loc);
        String json;
        InputStream is = new FileInputStream(file);
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        json = new String(buffer, StandardCharsets.UTF_8);
        return ReadLocator.fromJson(json);
    } catch (Exception ignored) {
        String jsonString = loadAssetTextAsString("Locators/LastReadLocators/last_read_locator_1.json");
        return ReadLocator.fromJson(jsonString);
    }
}

public void downlodeBook(CourseChapter chapter_model) {
    if (baseurl + chapter_model.getFile() == null) {
        Toast.makeText(chaptercontext, "no book here !", Toast.LENGTH_SHORT).show();

    } else {

        final ProgressDialog progressBarDialog = new ProgressDialog(chaptercontext);
        progressBarDialog.setTitle("Downloading Book ...");

        progressBarDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressBarDialog.setCancelable(false);
        progressBarDialog.setProgress(0);

        new Thread(() -> {
            boolean downloading = true;

            DownloadManager downloadmanager = (DownloadManager) chaptercontext.getSystemService(chaptercontext.DOWNLOAD_SERVICE);
            Uri uri = Uri.parse(baseurl + chapter_model.getFile());

            DownloadManager.Request request = new DownloadManager.Request(uri);
            request.setAllowedNetworkTypes(
                    DownloadManager.Request.NETWORK_WIFI
                            | DownloadManager.Request.NETWORK_MOBILE);
            request.setTitle("My File");
            request.setDescription("Downloading");
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            request.setVisibleInDownloadsUi(true);
            // request.setDestinationUri(Uri.parse();
            request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOCUMENTS, chapter_model.getFile());
            assert downloadmanager != null;
            long DownloadManagerId = downloadmanager.enqueue(request);

            while (downloading) {

                DownloadManager.Query q = new DownloadManager.Query();
                q.setFilterById(DownloadManagerId);
                Cursor cursor = downloadmanager.query(q);
                cursor.moveToFirst();
                int bytes_downloaded = cursor.getInt(cursor
                        .getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));

                final int dl_progress = (int) ((bytes_downloaded * 100L) / bytes_total);

                    progressBarDialog.setProgress(dl_progress);

                if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
                  Log.d("ajn", "true progress Status: " + cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)));
                    downloading = false;
                    progressBarDialog.dismiss();
                    readBook(chapter_model);
                }
              Log.d("ajn", "Progress status: " + cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)));
                cursor.close();
                getHighlightsAndSave();
               Log.d("ajn", "run: " + dl_progress);

                Log.d("ajn", "downloading: " + downloading);
            }
        }).start();

        progressBarDialog.show();
    }
}

public void readBook(CourseChapter chapter_model) {
    Config config = AppUtil.getSavedConfig(chaptercontext);
    if (config == null)
        config = new Config();
    config.setAllowedDirection(Config.AllowedDirection.VERTICAL_AND_HORIZONTAL);

    Uri path_to_fetch = Uri.parse("file:///mnt/sdcard/documents/" + chapter_model.getFile());
    Log.d("aj", "readBooks: " + chapter_model.getFile());
    String paths = path_to_fetch.getPath();

    File f = new File(paths);

    if (f.exists() && !f.isDirectory()) {

        if (getFileExt(f.getName()).equals("epub")) {
            Log.d("aj", "readBook: epub " + f.getName());

            folioReader.setConfig(config, true)
                    .openBook(paths);
            bookprogress++;

            Log.d("bookprogress", "progress " + bookprogress);
        }
    } else {
        Log.d("aj", "readBook: book downloading");
        downlodeBook(chapter_model);
    }
}

@Override
public void saveReadLocator(ReadLocator readLocator) {
    Log.i("Book", "-> saveReadLocator -> " + readLocator.toJson());

    try {
        String json = readLocator.toJson();
        Log.d("JSON", "saveReadLocator: " + json);

        String loc = chaptercontext.getFilesDir().getAbsolutePath();
        File writeLocator = new File(loc, "read_locator.json");
        FileWriter writer = new FileWriter(writeLocator, false);
        writer.write(json);
        writer.flush();
        writer.close();

    } catch (IOException e) {
        e.printStackTrace();
        Log.e("Book", "saveReadLocator: " + e.getMessage(), e);
    }
}

private void getHighlightsAndSave() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            ArrayList<HighLight> highlightList = null;
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                highlightList = objectMapper.readValue(
                        loadAssetTextAsString("highlights/highlights_data.json"),
                        new TypeReference<List<HighlightData>>() {
                        });
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (highlightList == null) {
                folioReader.saveReceivedHighLights(highlightList, new OnSaveHighlight() {
                    @Override
                    public void onFinished() {
                    }
                });
            }
        }
    }).start();
}

private String loadAssetTextAsString(String name) {
    BufferedReader in = null;
    try {
        StringBuilder buf = new StringBuilder();
        InputStream is = chaptercontext.getAssets().open(name);
        in = new BufferedReader(new InputStreamReader(is));

        String str;
        boolean isFirst = true;
        while ((str = in.readLine()) != null) {
            if (isFirst)
                isFirst = false;
            else
                buf.append('\n');
            buf.append(str);
        }
        return buf.toString();
    } catch (IOException e) {
        Log.e("HomeActivity", "Error opening asset " + name);
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                Log.e("HomeActivity", "Error closing asset " + name);
            }
        }
    }
    return null;
}

@Override
public void onHighlight(HighLight highlight, HighLight.HighLightAction type) {
}

@Override
public void onFolioReaderClosed() {

    Log.v("Book", "-> onFolioReaderClosed");
}

public static class viewholder extends RecyclerView.ViewHolder {
    private TextView name;
    private TextView number;
    private Button resumebook;

    public viewholder(@NonNull View itemView) {
        super(itemView);

        name = itemView.findViewById(R.id.chapter_name);
        number = itemView.findViewById(R.id.chapter_number);
        resumebook = itemView.findViewById(R.id.resumebook);

    }
}
sourena21 commented 2 years ago

It happened to me too! can anyone suggest any solution?