Как написать читалку для андроид

Post Views: 27 149

В настоящее время наиболее популярными и удобными способами чтения являются электронные книги. Их можно взять с собой куда угодно, они экономят бумагу, отображение текста в них можно настраивать так, как удобно читателю. По этим причинам появилось множество форматов электронных книг, основные из которых это EPUB, FB2 и MOBI. Всем известные DOC и TXT тоже являются форматами электронных книг, однако их возможности по сравнению с вышеуказанными весьма ограничены. У каждого из форматов есть свои преимущества, однако наиболее часто используемыми являются EPUB и FB2, причём второй популярен только у нас в России.

Одной из особенностей этих форматов является то, что для них нужна специальная программа, которая может работать с конкретным форматом. Поэтому в App Store или Google Play можно найти большое количество разнообразных читалок под все известные форматы. В этой статье мы попробуем написать свою собственную читалку электронных книг. Для этой цели мы воспользуемся специальной SDK от разработчиков FBReader, который доступен по следующей ссылке.

В сентябре этого года FBReader выпустили свой собственный SDK для Android, позволяющий создавать свои собственные читалки на его основе. FBReader SDK обладает большим функционалом, который включает в себя следующие возможности:

  • Открытие любых файлов электронных книг (ePub, fb2, mobi, и так далее)
  • Чтение метаданных из файла книги
  • Особенности движка FBReader
  • Возможность менять стиль текста книги

Кроме того, библиотека предоставляет и различные дополнительные возможности для реализации в приложениях, такие как:

  • Выделение текста
  • Закладки
  • Поиск по тексту
  • Оглавление
  • Дополнительная навигация по тексту
  • Поддержка сносок и гиперссылок
  • Настройка яркости

Отдельно стоит отметить, что, хоть FBReader SDK и можно скачать с сайта бесплатно, после встраивания в приложение она будет работать в демо-режиме, который имеет полный функционал, но показывает только несколько первых страниц книги. Для того, чтобы получить полную версию библиотеки, нужно купить её на сайте разработчика и, следуя инструкциям, получить специальный ключ SDK, который затем добавляется в приложение.

В этой статье мы рассмотрим, как на основе FBReader SDK создать свою собственную читалку электронных книг и посмотрим её возможности.

Начнём с добавления SDK в свой проект. Для этого создадим новый проект с пустой активностью. В качестве минимального API укажем API 16.

В файле build.gradle модуля проекта добавим в блок allprojects ссылку для скачивания нужных нам библиотек.

allprojects {
    repositories {
        ...
        maven {
            url "https://sdk.fbreader.org/maven"
        }
    }
}

Затем в файле build.gradle модуля приложения добавим зависимости с библиотеками в блок dependencies.

dependencies {
    ...
    implementation 'com.googlecode.json-simple:json-simple:1.1'
    implementation 'org.fbreader:book:1.0.0-rc01'
    implementation 'org.fbreader:config_client:1.0.0-rc01'
    implementation 'org.fbreader:config_provider:1.0.0-rc01'
    implementation 'org.fbreader:filesystem:1.0.0-rc01'
    implementation 'org.fbreader:fontentry:1.0.0-rc01'
    implementation 'org.fbreader:format_interface:1.0.0-rc01'
    implementation 'org.fbreader:image:1.0.0-rc01'
    implementation 'org.fbreader:intent:1.0.0-rc01'
    implementation 'org.fbreader:language:1.0.0-rc01'
    implementation 'org.fbreader:loader:1.0.0-rc01'
    implementation 'org.fbreader:options:1.0.0-rc01'
    implementation 'org.fbreader:text_client:1.0.0-rc01'
    implementation 'org.fbreader:text_provider:1.0.0-rc01'
    implementation 'org.fbreader:text_util:1.0.0-rc01'
    implementation 'org.fbreader:text_view:1.0.0-rc01'
    implementation 'org.fbreader:toc:1.0.0-rc01'
    implementation 'org.fbreader:util:1.0.0-rc01'
    implementation 'org.fbreader:view:1.0.0-rc01'
    implementation 'org.fbreader:vimgadgets:1.0.0-rc01'
    implementation 'org.fbreader:zip-amse:1.0.0-rc01'
}

Как вы можете заметить, здесь также присутствует библиотека «com.googlecode.json-simple:json-simple:1.1». Она пригодится чуть позже для работы с JSON-файлами.

Библиотек, входящих в FBReader SDK довольно много, однако они разделены так, чтобы можно было подключать только те, которые нужны для конкретного случая.

В этом же файле в блок android добавим следующие строки, которые должны обеспечить успешную сборку проекта.

android {
  ...

  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

На сайте SDK разработчики также предоставляют исходный код различных компонентов, которые упрощают реализацию интерфейса. Скачаем его и добавим в проект. Для этого перенесём оттуда папку fbreader в папку своего проекта. После этого в файле settings.gradle пропишем эту папку и пути до нужных модулей.

include 'fbreader_extras'
project(':fbreader_extras').projectDir = new File('fbreader/extras')
include 'fbreader_styles'
project(':fbreader_styles').projectDir = new File('fbreader/styles')
include 'fbreader_text_extras'
project(':fbreader_text_extras').projectDir = new File('fbreader/text_extras')

Теперь добавим зависимости с ними в файле build.gradle модуля приложения.

dependencies {
  ...
  implementation project(':fbreader_extras')
  implementation project(':fbreader_styles')
  implementation project(':fbreader_text_extras')
}

Когда IDE пересоберёт проект, мы увидим добавленные модули в списке слева.

На этом подключение SDK завершено и можно приступать к непосредственно созданию приложения. В конце статьи у нас должна получиться простая читалка с двумя активностями, одна из которых будет отображать список электронных книг на устройстве, а вторая открывать выбранный файл.

Начнём с разметки. Для MainActivity добавим на экран компонент RecyclerView, который будет содержать собственно список файлов. Для этого добавим в файл layout/activity_main.xml следующий код.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:paddingRight="12dp"
    android:paddingLeft="12dp"
    >

  <androidx.recyclerview.widget.RecyclerView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_marginTop="6dp"
      android:id="@+id/rv_files"
      />

</RelativeLayout>

Теперь инициализируем этот объект в коде активности. Откроем файл MainActivity.java и добавим следующий код.

public class MainActivity extends AppCompatActivity {
  private RecyclerView rvFiles;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    rvFiles = findViewById(R.id.rv_files);
    rvFiles.setLayoutManager(new LinearLayoutManager(this));
  }
}

Для того, чтобы работать с файлами, хранящимися на устройстве, нам потребуется запрашивать специальное разрешение. Добавим в манифест приложения AndroidManifest.xml следующие разрешения.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ru.androidtools.multireader">

  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

  <application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:supportsRtl="true"
      android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LAUNCHER"/>
      </intent-filter>
    </activity>
  </application>

</manifest>

Начиная с API 23 это разрешение необходимо запрашивать у пользователя в рантайме. Для этого при запуске приложения будем проверять версию Android на устройстве и при необходимости отправлять пользователю запрос на получение разрешения.

public class MainActivity extends AppCompatActivity {
  ...
  private static final int REQUEST_PERMISSION = 101;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    rvFiles = findViewById(R.id.rv_files);
    rvFiles.setLayoutManager(new LinearLayoutManager(this));

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      checkPermission();
    } else {
      generateList();
    }
  }

  @TargetApi(Build.VERSION_CODES.M) private void checkPermission() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
        == PackageManager.PERMISSION_GRANTED) {
      generateList();
    } else {
      ActivityCompat.requestPermissions(this,
          new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, REQUEST_PERMISSION);
    }
  }
}

Получить результат запроса можно, переопределив метод активности onRequestPermissionResult(). Если разрешение приложению было предоставлено, продолжаем дальнейшую работу.

@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
    @NonNull int[] grantResults) {
  switch (requestCode) {
    case REQUEST_PERMISSION: {
      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        generateList();
      }
      break;
    }
  }
}

В методе generateList() мы будем искать нужные файлы на устройстве и отображать их в списке приложения. Для этого создадим AsyncTask, который будет выполнять всю работу в отдельном потоке и возвращать готовый список с найденными файлами. Добавим следующий код в MainActivity.

private void generateList() {
  List<StorageBean> storageBeans = StorageUtils.getStorageData(this); // получение списка смонтированных карт памяти на устройстве
  List<String> paths = new ArrayList<>();
  if (storageBeans != null) {
    for (StorageBean storageBean : storageBeans) {
      paths.add(storageBean.getPath());
    }
  } else {
    String path = Environment.getExternalStorageDirectory().getAbsolutePath();
    paths.add(path);
  }
  ListFilesTask listFilesTask = new ListFilesTask(paths);
  listFilesTask.setListener(new ListFilesTask.ListFilesListener() {
    @Override public void onTaskCompleted(List<File> files) {
    }
  });
  listFilesTask.execute();
}

static class ListFilesTask extends AsyncTask<Void, Void, List<File>> {
  public interface ListFilesListener {
    void onTaskCompleted(List<File> files);
  }

  private ListFilesListener listener;
  private List<String> startPaths;
  private List<File> files;
  private boolean completed;

  public ListFilesTask(List<String> startPaths) {
    this.startPaths = new ArrayList<>(startPaths);
    this.files = new ArrayList<>();
    this.completed = false;
  }

  public void setListener(ListFilesListener listener) {
    this.listener = listener;
    if (completed && listener != null && files != null) {
      listener.onTaskCompleted(files);
    }
  }

  @Override protected List<File> doInBackground(Void... voids) {
    List<File> fileList = new ArrayList<>();
    for (String s : startPaths) {
      searchFiles(fileList, new File(s));
    }
    return fileList;
  }

  @Override protected void onPostExecute(List<File> files) {
    completed = true;
    if (listener != null) {
      listener.onTaskCompleted(files);
    } else {
      this.files = new ArrayList<>(files);
    }
  }

  private void searchFiles(List<File> list, File dir) {
    String epubPattern = ".epub";
    String fb2Pattern = ".fb2";

    File[] listFiles = dir.listFiles();
    if (listFiles != null) {
      for (File listFile : listFiles) {
        if (listFile.isDirectory()) {
          searchFiles(list, listFile);
        } else {
          if (listFile.getName().endsWith(epubPattern) || listFile.getName()
              .endsWith(fb2Pattern)) {
            list.add(listFile);
          }
        }
      }
    }
  }
}

Полученный результат нужно отобразить. Для этого нам понадобится адаптер для RecyclerView и модель, в которой будут храниться данные элементов списка. Создадим простой класс BookFile, в котором мы будем хранить имя файла и путь до него на устройстве.

public class BookFile {
  private String filename, path;

  public BookFile(String filename, String path) {
    this.filename = filename;
    this.path = path;
  }

  public String getFilename() {
    return filename;
  }

  public String getPath() {
    return path;
  }

  @Override public int hashCode() {
    return filename.hashCode() + path.hashCode();
  }

  @Override public boolean equals(Object obj) {
    if (obj instanceof BookFile) {
      BookFile bookFile = (BookFile) obj;
      return this.filename.equals(bookFile.getFilename()) && this.path.equals(bookFile.getPath());
    }
    return false;
  }
}

Теперь нам нужен адаптер, в который мы будем загружать список. Добавим разметку для элемента списка, для этого создадим файл layout/file_list_item.xml и добавим в него следующий код.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="2dp"
    android:layout_marginTop="2dp"
    android:orientation="vertical"
    android:paddingBottom="6dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="6dp"
    >

  <TextView
      android:id="@+id/tv_filename"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="filename"
      android:textSize="16sp"
      />

  <TextView
      android:id="@+id/tv_path"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="2dp"
      android:text="path"
      android:textSize="14sp"
      />

</LinearLayout>

Теперь создадим класс BooksAdapter, который будет наследовать от RecyclerView.Adapter<>. В нём нам нужно инициализировать элементы списка, загружая в них пути и имена файлов электронных книг. Таким образом, код адаптера будет выглядеть следующим образом.

public class BooksAdapter extends RecyclerView.Adapter<BooksAdapter.BookHolder> {
  public interface BookListener {
    void onBookOpen(BookFile bookFile);
  }

  private BookListener listener;
  private List<BookFile> books;

  public BooksAdapter(List<BookFile> books, BookListener listener) {
    this.books = new ArrayList<>(books);
    this.listener = listener;
  }

  @NonNull @Override public BookHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view =
        LayoutInflater.from(parent.getContext()).inflate(R.layout.file_list_item, parent, false);
    return new BookHolder(view);
  }

  @Override public void onBindViewHolder(@NonNull BookHolder holder, int position) {
    BookFile bookFile = books.get(position);
    holder.bind(bookFile);
  }

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

  class BookHolder extends RecyclerView.ViewHolder {
    private LinearLayout itemLayout;
    private TextView tvPath, tvName;

    public BookHolder(@NonNull View itemView) {
      super(itemView);
      itemLayout = itemView.findViewById(R.id.item_layout);
      tvName = itemView.findViewById(R.id.tv_filename);
      tvPath = itemView.findViewById(R.id.tv_path);
    }

    public void bind(BookFile bookFile) {
      tvPath.setText(bookFile.getPath());
      tvName.setText(bookFile.getFilename());
      itemLayout.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View view) {
          listener.onBookOpen(bookFile);
        }
      });
    }
  }
}

Кроме того, между активностью и адаптером пробрасывается интерфейс, с помощью которого мы будем передавать в активность файл, который пользователь хочет открыть.

Вернёмся в главную активность. В методе generateList() мы запускаем AsyncTask и привязываем к нему слушатель, который должен вызывать метод onTaskCompleted() при завершении работы. В этом методе нам нужно составить список, отсортировать его по имени и передать в адаптер. Добавим сюда следующий код:

listFilesTask.setListener(new ListFilesTask.ListFilesListener() {
  @Override public void onTaskCompleted(List<File> files) {
    if (!isFinishing()) {
      List<BookFile> bookFiles = new ArrayList<>();
      for (File f : files) {
        BookFile bookFile = new BookFile(f.getName(), f.getAbsolutePath());
        if (!bookFiles.contains(bookFile)) bookFiles.add(bookFile);
      }
      Collections.sort(bookFiles, new Comparator<BookFile>() {
        @Override public int compare(BookFile bookFile, BookFile t1) {
          return bookFile.getFilename().compareToIgnoreCase(t1.getFilename());
        }
      });
      rvFiles.setAdapter(new BooksAdapter(bookFiles, new BooksAdapter.BookListener() {
        @Override public void onBookOpen(BookFile bookFile) {

        }
      }));
    }
  }
});

Теперь, запустив приложение, мы можем увидеть список файлов электронных книг, которые есть на устройстве.

Однако нам нужно этот файл открыть и прочитать, в этом нам и поможет FBReader SDK. Создадим новую активность, назовём её ReaderActivity. Теперь из скачанного исходного кода нам понадобится несколько классов. Откроем в папке с исходным кодом samples/extensions/src/main и скопируем себе в проект целиком папку res, за исключением res/layout/main.xml, и из java/org/fbreader/sample/extensions скопируем все классы, кроме MainActivity.java. Эти классы содержат готовые компоненты, которые помогут нам в создании читалки, при желании их можно модифицировать в соответствии с потребностями.

Теперь откроем layout/reader_activity.xml и добавим в него следующий код разметки.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/widget_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

  <ru.androidtools.multireader.TextWidgetExt
      android:id="@+id/text_widget"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:focusable="true"
      android:scrollbars="vertical"
      android:scrollbarAlwaysDrawVerticalTrack="true"
      android:fadeScrollbars="false"
      />

  <TextView
      android:id="@+id/error_message"
      android:textAppearance="?android:attr/textAppearanceLarge"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
      android:text="The app couldn't open the book"
      android:visibility="gone"
      />

</RelativeLayout>

TextWidgetExt является обёрткой класса библиотеки TextWidget, этот класс является основным и именно он отображает содержимое книги.

Инициализируем теперь эти объекты в коде активности ReaderActivity.java.

public class ReaderActivity extends AppCompatActivity {
  private TextWidgetExt widget;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_reader);

    widget = findViewById(R.id.text_widget);
    View errorView = findViewById(R.id.error_message);
    widget.setVisibility(View.VISIBLE);
    errorView.setVisibility(View.GONE);
  }
}

Мы должны получить от главной активности путь до файла, который пользователь хочет открыть. Для этого мы будем передавать интент из одной активности в другую, содержащий нужный путь. Вернёмся в MainActivity.java и добавим код создания интента в метод onBookOpen() интерфейса адаптера.

rvFiles.setAdapter(new BooksAdapter(bookFiles, new BooksAdapter.BookListener() {
  @Override public void onBookOpen(BookFile bookFile) {
    Intent intent = new Intent(MainActivity.this, ReaderActivity.class);
    intent.putExtra(ReaderActivity.EXTRA_PATH, bookFile.getPath());
    startActivity(intent);
  }
}));

После этого отправленный интент нам нужен получить в ReaderActivity.java при старте активности. Добавим в onCreate() запись пути файла.

...
public final static String EXTRA_PATH = "EXTRA_PATH";
private String filepath;

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_reader);

  widget = findViewById(R.id.text_widget);
  View errorView = findViewById(R.id.error_message);
  widget.setVisibility(View.VISIBLE);
  errorView.setVisibility(View.GONE);

  filepath = getIntent().getStringExtra(EXTRA_PATH);
  }
}

Полученный путь мы передаём в метод setBook() у объекта TextWidgetExt. После этого он должен нам вернуть объект Book, который можно получить с помощью метода TextWidgetExt controller(). Если объект не будет равен null, значит загрузка содержимого прошла успешно и можно показать книгу пользователю.

...
private TextWidgetExt widget;

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_reader);

  ...

  try {
    widget.setBook(BookLoader.fromFile(filepath, this, 1L));
    Book book = widget.controller().book;
    if (book != null) {
      widget.invalidate();
      widget.post(new Runnable() {
        @Override public void run() {
          widget.gotoPage(0);
          setTitle(book.getTitle());
        }
      });
    } else {
      errorView.setVisibility(View.VISIBLE);
    }
  } catch (BookException e) {
    e.printStackTrace();
    errorView.setVisibility(View.VISIBLE);
  }
}

Теперь, если запустить приложение, мы уже можем видеть содержимое книги, пролистывать его и работать с ним.

Однако это не весь функционал, на который способна данная SDK. Ранее мы добавляли файлы ресурсов: различные разметки, иконки и меню. Добавим меню в наше приложение, для этого в ReaderActivity.java переопределим метод onCreateOptionsMenu() и добавим в него следующий код.

@Override
public boolean onCreateOptionsMenu(final Menu menu) {
  getMenuInflater().inflate(R.menu.app, menu);
  return true;
}

Также переопределим методы onPrepareOptionsMenu() и onOptionsItemSelected() для работы с этим меню.

@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
  SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
  searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
    @Override
    public boolean onQueryTextChange(String query) {
      return true;
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
      widget.searchInText(query);
      menu.findItem(R.id.menu_search).collapseActionView();
      return true;
    }
  });

  menu.findItem(R.id.menu_table_of_contents).setEnabled(TableOfContentsUtil.isAvailable(widget));
  String name = widget.colorProfile().name;
  menu.findItem(R.id.menu_color_profile_light).setChecked("defaultLight".equals(name));
  menu.findItem(R.id.menu_color_profile_dark).setChecked("defaultDark".equals(name));
  menu.findItem(R.id.menu_color_profile_dark_with_bg).setChecked("darkWithBg".equals(name));
  menu.findItem(R.id.menu_color_profile_pink).setChecked("pink".equals(name));
  return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
  BaseStyle baseStyle = widget.baseStyle();

  switch (item.getItemId()) {
    case R.id.menu_table_of_contents: {
      final Intent intent = TableOfContentsUtil.intent(widget);
      if (intent != null) {
        startActivityForResult(intent, REQUEST_TABLE_OF_CONTENT);
      }
      break;
    }
    case R.id.menu_zoom_in:
      baseStyle.fontSize.setValue(baseStyle.fontSize.getValue() + 2);
      break;
    case R.id.menu_zoom_out:
      baseStyle.fontSize.setValue(baseStyle.fontSize.getValue() - 2);
      break;
    case R.id.menu_color_profile_light:
      widget.setColorProfileName("defaultLight");
      break;
    case R.id.menu_color_profile_dark:
      widget.setColorProfileName("defaultDark");
      break;
    case R.id.menu_color_profile_dark_with_bg:
      widget.setColorProfileName("darkWithBg");
      break;
    case R.id.menu_color_profile_pink:
      widget.setColorProfileName("pink");
      break;
  }
  widget.clearTextCaches();
  widget.invalidate();
  return true;
}

Таким образом мы добавим в читалку меню, позволяющее нам:

  • Менять размер текста
  • Менять стиль текста
  • Искать по тексту
  • Открывать оглавление

По поводу оглавления стоит сказать отдельно. В коде, взятом из библиотеки, оглавление представлено в виде отдельной активности, мы её скопировали ранее, но не добавили в манифест. Поэтому откроем файл манифеста AndroidManifest.xml и зарегистрируем в нём новую активность.

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
  ...
  <activity android:name=".TableOfContentsActivity"/>
</application>

Теперь при открытии оглавления через меню у нас будет запускаться новая активность, содержащая в себе оглавление открытой книги. Стоит отметить, что не все книги содержат такое оглавление, поэтому в таких случаях кнопка меню будет неактивна.

При выборе главы обратно в ReaderActivity будет возвращаться номер страницы, на которую нужно перейти. Чтобы получить этот результат, в ReaderActivity.java мы переопределим метод onActivityResult(), в который добавим следующий код.

public class ReaderActivity extends AppCompatActivity {
  private final int REQUEST_TABLE_OF_CONTENT = 1;

  ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
      case REQUEST_TABLE_OF_CONTENT:
        if (resultCode == RESULT_OK) {
          int ref = data.getIntExtra(String.valueOf(TableOfContentsUtil.Key.reference), -1);
          if (widget != null && ref != -1) {
            widget.jumpTo(new FixedPosition(ref, 0, 0));
          }
        }
      default:
        super.onActivityResult(requestCode, resultCode, data);
    }
  }

Как можно увидеть, библиотека предоставляет разработчикам весь свой функционал, единственным ограничением бесплатной версии здесь является то, что она открывает только первые несколько страниц книги, о чём говорится при открытии книги.

Если вы купили ключ SDK и хотите добавить его в своё приложение, вам понадобится в файле build.gradle модуля приложения добавить в блоке buildTypes следующий код.

buildTypes {
  ...

  all {
  resValue 'string', 'fbreader_sdk_key', 'put your fbreader sdk key here'
  }
}

Не смотря на то, что движок FBReader достаточно мощный, а также учитывая графические ресурсы, добавляемые вместе с библиотекой, итоговый APK получился небольшого размера, что говорит о хорошей оптимизации библиотеки.

Итак, с помощью FBReader SDK и небольшого количества кода мы смогли создать простую читалку для электронных книг. Можно уже оставить как есть, либо продолжить модифицировать, изменяя интерфейс и дизайн так, как нужно разработчику. Пока что SDK есть только на Android, но разработчики планируют к концу года выпустить версию и для iOS.

Осенью 2016 года хороший друг нашей студии Аскар Жумагалиев, рассказал во время обеда о том, как он начал изучать казахский язык при помощи книг на казахском языке. Он также поделился мнением, что ему было бы удобнее читать их в приложении на своем телефоне, и при нажатии на неизвестное слово на казахском, видеть его перевод на русский язык, тем самым расширяя свой словарный запас. Так обед плавно превратился в обсуждение идеи и дальнейшую четырехмесячную разработку мобильного приложения-читалки книг, со встроенной библиотекой и словарем языковых пар казахский-русский.

По ходу обсуждений миссией приложения мы выбрали следующее: сделать казахскую литературу доступной даже для тех, кто только изучает казахский язык или знает его на бытовом уровне. Бонусом к этому, была возможность изучать казахский язык при помощи книг.

Когда мы делали приложение, мы как-то и не задумались о том, что нам потребуются авторские права на использование книг в своем мобильном приложении. Чуть позже на финишной прямой мы все таки смогли получить разрешение на использование книг от Нұрбека Матжани, президента Фонда WikiBilim любезно предоставившего нам как права на использование книг, так и словарь казахского языка хорошего качества.

В целом, мы видели потребность в казахских книгах в виде мобильного приложения. В том же Google Play мы нашли приложение со сборником стихов Мұқағали Мақатаева (казахский писатель). Там было больше полумиллиона скачиваний. Дизайн был ужасным, навигация не совсем удобной, но люди все равно продолжали скачивать приложение и оставлять хорошие отзывы. Поэтому во время обсуждения дизайна мы решили не заморачиваться а сделать так, как нам понравится. Итог вы сможете видеть на скриншотах ниже.

b_58db5efd87222.jpgПервым прототипом приложения была читалка написанная на React Native, выпущенная для платформ Android и iOS и с одной книгой: роман-эпопея Путь Абая, под авторством Мұхтара Ауезова. Тут стоит особо отметить о том, как мы потеряли два месяца работая над тупиковым путем, выбрав писать на React Native, взамен нативной разработке на Swift/Objective-C и Java. Как оказалось некоторые вещи, которые нам нужны в приложении не было возможно реализовать при помощи React Native. Потому что, пока нужных библиотек для корректной работы с форматом электронных книг Epub в React Native нет.

Поэтому через два месяца разработки нам пришлось свернуть проект на React Native и начать нативную разработку на обе платформы.

Еще одной ошибкой было то, что Apple не сразу пропустил наше приложение. Так как мы его позиционировали как читалка для книг, они не хотели его пропускать в AppStore только с одной книгой, настоятельно советовали отправить книгу в сервис чтения книг iBooks, что нас никак не устраивало. Поэтому мы в срочном порядке добавили в iOS версию еще пару книг и утолили жажду ревьюеров Apple.

К концу разработки мы начали думать о названии приложения. И почему-то нам оно легко далось. Есть замечательное стихотворение казахского писателя Міржақыпа Дулатова — «Оян, қазақ». Слово «Оян» с казахского переводится как «Проснись». Вот так мы и решили назвать наше приложение Оян, написав его на латинице — Oyan.

После нескольких версий приложения мы решили пора рассказать о себе миру! И написали один пост на фейсбуке. Который разлетелся по всему казахстанскому сегменту интернета. Ну и не для кого секрет, что социальные проекты люди любят больше и шейря больше. Мы получили большой охват в СМИ и смогли выйти на пару дней в ТОП бесплатных приложений на AppStore и Google Play. Также слово Oyan было в топе поисковых запросов AppStore.

b_58e222985f318.jpg

В данный момент в приложении вы найдете порядка 170 книг знаменитых казахских авторов. Но самое главное — наведя на любое слово, вы сможете увидеть его перевод, определение, а также объяснения сложных фраз, добавленные другими пользователями.

Особо стоит отметить о переводах добавленных пользователями. Этот канал очень активно нами используется для наполнения нашего словаря и без поддержки волонтеров этого не получилось бы.

Выводы которые наша студия сделала это основное: не начинать работу на React Native пока досконально не изучишь все моменты, которые необходимы для твоего мобильного приложения. Присмотритесь, возможно то что вам нужно реализовать невозможно сделать на React Native.

Ссылка для скачивания: в App Store & Play Market.

P.S. Наша команда этим летом проведет летнюю школу программирования в городе Астана, Казахстан. Мы научим вас программировать и создать за 12 недель приложение с 10 000 пользователями! Если вы хотите туда попасть, добро пожаловать на сайт программы: N17R.com

Introduction

An electronic book, also known as an eBook, is a book made available in digital form, consisting of text, images, or both, readable on the flat-panel display of computers or other electronic devices that features a controllable viewing screen, including desktop computers, laptops, tablets, and smartphones.

Features of eBooks

  1. Intuitive List of Chapters
  2. Reader-Friendly Interface
  3. Multiple Platform Support
  4. Support Different Formats
  5. Reading Tools

What makes them better than printed books?

eBooks Are More Portable Than Print

Printed books, especially hardbound editions, can be very heavy, while most modern eReader devices are lightweight. It’s much easier to carry an eReader containing an entire library of titles than to bring even a few physical books.

eBooks Take Up Much Less Space

Avid readers tend to collect a lot of books, which can take up too much space and make your home feel cluttered. However, even the largest collection of eBooks won’t take up much physical space in your home.

There Are No Late Fees for Library eBooks

If you borrow a physical book from the library and forget to return it, you will be charged a late fee. Many libraries also now offer eBook loans in addition to their print book offerings. You don’t have to return them by any due date instead, their licenses will simply expire on your device

Now we will learn how to program in Android studio using a java programming language step by step.

Step 1

First, we will create an Android Studio project named as per your choice. and go to Empty Activity, Android Studio will create MainActivity.java and activity_main.xml.

Step 2

Before starting we have to add the dependency that is used for open Pdf files in our build.gradle code file of the application. Here is our build.gradle file.

  1. apply plugin: ‘com.android.application’      
  2.       
  3. android {      
  4.     compileSdkVersion 29      
  5.     buildToolsVersion «29.0.2»      
  6.     defaultConfig {      
  7.         applicationId «com.example.book»      
  8.         minSdkVersion 24      
  9.         targetSdkVersion 29      
  10.         versionCode 1      
  11.         versionName «1.0»      
  12.         testInstrumentationRunner «androidx.test.runner.AndroidJUnitRunner»      
  13.     }      
  14.     buildTypes {      
  15.         release {      
  16.             minifyEnabled false      
  17.             proguardFiles getDefaultProguardFile(‘proguard-android-optimize.txt’), ‘proguard-rules.pro’      
  18.         }      
  19.     }      
  20. }      
  21.       
  22. dependencies {      
  23.     implementation fileTree(dir: ‘libs’, include: [‘*.jar’])      
  24.     implementation ‘androidx.appcompat:appcompat:1.2.0’      
  25.     implementation ‘androidx.constraintlayout:constraintlayout:2.0.4’      
  26.         
  27.     testImplementation ‘junit:junit:4.12’      
  28.     androidTestImplementation ‘androidx.test.ext:junit:1.1.2’      
  29.     androidTestImplementation ‘androidx.test.espresso:espresso-core:3.3.0’      
  30.     implementation ‘com.github.barteksc:android-pdf-viewer:2.8.2’      
  31.       
  32. }     

Here we Implement two methods: com.github.barteksc:android-pdf-viewer:2.8.2'
We add the material dependency in build.gradle file. the Android application which is used for material design,
After adding the dependency in our project sync the project.

Step 3

After the successful sync of the project. go to splash screen activity   

Activity-Splash-Screen.xml

The first screen visible to the user when the application’s launched.  We use Splash screens to display some animations and application logos, while some data for the next screens are fetched

  1. <RelativeLayout      
  2.          android:layout_width=«match_parent»      
  3.          android:layout_height=«match_parent»>      
  4.        
  5.          <ImageView      
  6.              android:id=«@+id/img»      
  7.              android:layout_width=«329dp»      
  8.              android:layout_height=«409dp»      
  9.              android:layout_marginLeft=«40dp»      
  10.              android:layout_marginTop=«20dp»      
  11.              android:src=«@drawable/logo» />      
  12.        
  13.         <TextView      
  14.              android:id=«@+id/tv3»      
  15.              android:layout_width=«wrap_content»      
  16.              android:layout_height=«wrap_content»      
  17.              android:layout_marginLeft=«70sp»      
  18.              android:layout_marginTop=«568sp»      
  19.              android:fontFamily=«cursive»      
  20.              android:text=«Powered by Yatish Chhonkar»      
  21.              android:textColor=«@color/colorwhite»      
  22.              android:textSize=«25sp» />      
  23.        
  24.      </RelativeLayout>      

After completing the XML part be jumped into  implementation in java.

Step 4 — Main Activity java

Here we implement java code with XML which is a simple constant screen for a fixed amount of time that is used to display the book content, logo, name.

  1. public class Splash_screen extends AppCompatActivity {    
  2.     
  3.     TextView slogan ,txt;    
  4.         
  5.     Animation topanim,bottomanim;    
  6.     
  7.     @Override    
  8.     protected void onCreate(Bundle savedInstanceState) {    
  9.         super.onCreate(savedInstanceState);    
  10.     
  11.        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);    
  12.     
  13.         setContentView(R.layout.activity_splash_screen);    
  14.     
  15.         slogan=(TextView)findViewById(R.id.tv2);    
  16.         txt=(TextView)findViewById(R.id.tv3);    
  17.     
  18.                          
  19.     
  20.         topanim = AnimationUtils.loadAnimation(this,R.anim.top_animation);    
  21.         bottomanim = AnimationUtils.loadAnimation(this,R.anim.bottom_animation);    
  22.     
  23.           
  24.     
  25.         slogan.setAnimation(bottomanim);    
  26.         txt.setAnimation(bottomanim);    
  27.     
  28.           
  29.     
  30.     new Handler().postDelayed(new Runnable() {    
  31.         @Override    
  32.         public void run() {    
  33.     
  34.             Intent intent = new Intent(Splash_screen.this,MainActivity.class);    
  35.             startActivity(intent);    
  36.             finish();    
  37.     
  38.         }    
  39.     },6000);    
  40.     
  41.     }    
  42. }   

Step 5 

While complying with the part of the splash screen we move to the next remaining part to open pdf content file.   

PdfOpner.xml

Create another empty activity to open Pdf file

 

  1. <?xml version=«1.0» encoding=«utf-8»?>    
  2.  <androidx.constraintlayout.widget.ConstraintLayout xmlns:android=«http://schemas.android.com/apk/res/android»    
  3.      xmlns:app=«http://schemas.android.com/apk/res-auto»    
  4.      xmlns:tools=«http://schemas.android.com/tools»    
  5.      android:layout_width=«match_parent»    
  6.      android:layout_height=«match_parent»    
  7.      tools:context=«.pdfOpener»>    
  8.      
  9.      <com.github.barteksc.pdfviewer.PDFView    
  10.          android:layout_width=«match_parent»    
  11.          android:layout_height=«match_parent»    
  12.          android:id=«@+id/pdfViewer»>    
  13.      
  14.      </com.github.barteksc.pdfviewer.PDFView>    
  15.      
  16.  </androidx.constraintlayout.widget.ConstraintLayout>   

Here we use a library for it too.. github.com/barteksc/AndroidPdfViewer in our project too

Step 6

While completing the part of the pdf opener file .xml we move to the next remaining part to pdf opener file .java class, 

PdfOpenerFile.java

 

  1. public class pdfOpener extends AppCompatActivity {    
  2.     
  3.     PDFView myPDFViewer;    
  4.     
  5.     @Override    
  6.  protected void onCreate(Bundle savedInstanceState) {    
  7.         super.onCreate(savedInstanceState);    
  8.         setContentView(R.layout.activity_pdf_opener);    
  9.     
  10.         myPDFViewer = (PDFView) findViewById(R.id.pdfViewer);    
  11.     
  12.         String getItam =getIntent().getStringExtra(«PdfFieName»);    
  13.     
  14.         if(getItam.equals(«संख्या पद्धति»)){    
  15.             myPDFViewer.fromAsset(«संख्या पद्धति.pdf»).load();    
  16.         }    
  17.     
  18.         if(getItam.equals(«सरलीकरण»)){    
  19.             myPDFViewer.fromAsset(«सरलीकरण.pdf»).load();    
  20.         }    
  21.     
  22.         if(getItam.equals(«LCM तथा HCF»)){    
  23.             myPDFViewer.fromAsset(«LCM तथा HCF.pdf»).load();    
  24.         }    
  25.     
  26.         if(getItam.equals(«वर्गमूल तथा घनमूल»)){    
  27.             myPDFViewer.fromAsset(«वर्गमूल तथा घनमूल.pdf»).load();    
  28.         }    
  29.     
  30.         if(getItam.equals(«घातांक एवं करणी»)){    
  31.             myPDFViewer.fromAsset(«घातांक एवं करणी.pdf»).load();    
  32.         }    
  33.     
  34.         if(getItam.equals(«औसत»)){    
  35.             myPDFViewer.fromAsset(«औसत.pdf»).load();    
  36.         }    
  37.     
  38.         if(getItam.equals(«प्रतिशत»)){    
  39.             myPDFViewer.fromAsset(«प्रतिशत.pdf»).load();    
  40.         }    
  41.     
  42.         if(getItam.equals(«लाभ और हानि»)){    
  43.             myPDFViewer.fromAsset(«लाभ और हानि.pdf»).load();    
  44.         }    
  45.     
  46.         if(getItam.equals(«आयु पर आधरित प्रश्न»)){    
  47.             myPDFViewer.fromAsset(«आयु पर आधरित प्रश्न.pdf»).load();    
  48.         }    
  49.     
  50.         if(getItam.equals(«अनुपात एवं समानुपात»)){    
  51.             myPDFViewer.fromAsset(«अनुपात एवं समानुपात.pdf»).load();    
  52.         }    
  53.     
  54.         if(getItam.equals(«साझा»)){    
  55.             myPDFViewer.fromAsset(«साझा.pdf»).load();    
  56.         }    
  57.     
  58.         if(getItam.equals(«मिश्रण»)){    
  59.             myPDFViewer.fromAsset(«मिश्रण.pdf»).load();    
  60.         }    
  61.     
  62.         if(getItam.equals(«मिश्र समानुपात»)){    
  63.             myPDFViewer.fromAsset(«मिश्र समानुपात.pdf»).load();    
  64.         }    
  65.     
  66.         if(getItam.equals(«साधारण ब्याज»)){    
  67.             myPDFViewer.fromAsset(«साधारण ब्याज.pdf»).load();    
  68.         }    
  69.     
  70.         if(getItam.equals(«चक्रवृध्दि ब्याज»)){    
  71.             myPDFViewer.fromAsset(«चक्रवृध्दि ब्याज.pdf»).load();    
  72.         }    
  73.     
  74.     
  75.         if(getItam.equals(«कार्य तथा समय»)){    
  76.             myPDFViewer.fromAsset(«कार्य तथा समय.pdf»).load();    
  77.         }    
  78.     
  79.         if(getItam.equals(«नल एवमं हौज़»)){    
  80.             myPDFViewer.fromAsset(«नल एवमं हौज़.pdf»).load();    
  81.         }    
  82.     
  83.         if(getItam.equals(«रेलगाडी»)){    
  84.             myPDFViewer.fromAsset(«रेलगाडी.pdf»).load();    
  85.         }    
  86.     
  87.         if(getItam.equals(«नाव तथा धारा»)) {    
  88.             myPDFViewer.fromAsset(«नाव तथा धारा.pdf»).load();    
  89.         }    
  90.     
  91.             if(getItam.equals(«क्षेत्रफल एवमं आयतन»)) {    
  92.                 myPDFViewer.fromAsset(«क्षेत्रफल एवमं आयतन.pdf»).load();    
  93.     
  94.             }    
  95.     }    
  96. }   

We can use a custom PDF Viewer.

In your Gradle file compile this: 'com.github.barteksc:android-pdf-viewer:2.0.3'

Step 7 — Activity-Main-.XML

While complying with the part of the pdf opener class .java we move to the next remaining part to Main Activity .xml, 

  

Here we add a list view in XML with match parent height and width and assign id as a listview. 

  1. <RelativeLayout      
  2.       
  3.  xmlns:android=«http://schemas.android.com/apk/res/android»      
  4.  xmlns:app=«http://schemas.android.com/apk/res-auto»      
  5.  xmlns:tools=«http://schemas.android.com/tools»      
  6.  android:layout_width=«match_parent»      
  7.  android:layout_height=«match_parent»      
  8.  tools:context=«.MainActivity»>      
  9.       
  10. <ListView      
  11.     android:layout_width=«match_parent»      
  12.     android:layout_height=«match_parent»      
  13.     android:id=«@+id/lstview»      
  14.     android:padding=«15dp»/>      
  15. </RelativeLayout>     

Step 8

Here we set data into list view  which we create in XML  

Main Activity-.java 

  1. public class MainActivity extends AppCompatActivity {  
  2.   
  3.     ListView lsview;  
  4.   
  5.     @Override  
  6.     protected void onCreate(Bundle savedInstanceState) {  
  7.         super.onCreate(savedInstanceState);  
  8.         setContentView(R.layout.activity_main);  
  9.   
  10.         lsview = (ListView) findViewById(R.id.lstview);  
  11.   
  12.         String[] chapter = {  
  13.             «संख्या पद्धति»,  
  14.             «सरलीकरण»,  
  15.             «LCM तथा HCF»,  
  16.             «वर्गमूल तथा घनमूल»,  
  17.             «घातांक एवं करणी»,  
  18.             «औसत»,  
  19.             «प्रतिशत»,  
  20.             «लाभ और हानि»,  
  21.             «आयु पर आधरित प्रश्न»,  
  22.             «अनुपात एवं समानुपात»,  
  23.             «साझा»,  
  24.             «मिश्रण»,  
  25.             «मिश्र समानुपात»,  
  26.             «साधारण ब्याज»,  
  27.             «चक्रवृध्दि ब्याज»,  
  28.             «कार्य तथा समय»,  
  29.             «नल एवमं हौज़»,  
  30.             «रेलगाडी»,  
  31.             «नाव तथा धारा»,  
  32.             «क्षेत्रफल एवमं आयतन»  
  33.         };  
  34.   
  35.         ArrayAdapter < String > adapter = new ArrayAdapter < String > (this, android.R.layout.simple_list_item_1, chapter) {  
  36.   
  37.             @NonNull  
  38.             @Override  
  39.             public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {  
  40.   
  41.                 View view = super.getView(position, convertView, parent);  
  42.   
  43.                 TextView mytxt = (TextView) view.findViewById(android.R.id.text1);  
  44.                 return view;  
  45.             }  
  46.         };  
  47.   
  48.         lsview.setAdapter(adapter);  
  49.   
  50.   
  51.         lsview.setOnItemClickListener(new AdapterView.OnItemClickListener() {  
  52.             @Override  
  53.             public void onItemClick(AdapterView < ? > parent, View view, int position, long id) {  
  54.   
  55.                 String iteam = lsview.getItemAtPosition(position).toString();  
  56.   
  57.                 Intent start = new Intent(getApplicationContext(), pdfOpener.class);  
  58.                 start.putExtra(«PdfFieName», iteam);  
  59.                 startActivity(start);  
  60.   
  61.             }  
  62.         });  
  63.     }  

Here we use listview, array adapter, and set adapter into list view once we click the listview, the intent will take us to Pdfopner class activity. 

 

After complying with the code it will look like as shown in the picture. It’s ready to use.

 

Explanation

In the MainActivity.java file, we used List view and pdf open file by the line «findViewById(R.id.ls view)» we connect together and set the click listener name as per pdf file which saves in Array Adapter. Once we click the list view it fires in the intent and jumps into a pdf file.   

Benefits of eBooks  

  1. eBooks save space
  2. eBooks save money
  3. eBooks help the environment
  4. An eBook is portable and convenient 
  5. Instantly download 

You can have a look at the output below

Conclusion 

You can easily turn your eBook into a revenue-generating machine on any platform screen. The key being – effective use of the eBook features to stand out in the digital world. An eBook is a way of reaching your readers in a digital world.

Introduction

An electronic book, also known as an eBook, is a book made available in digital form, consisting of text, images, or both, readable on the flat-panel display of computers or other electronic devices that features a controllable viewing screen, including desktop computers, laptops, tablets, and smartphones.

Features of eBooks

  1. Intuitive List of Chapters
  2. Reader-Friendly Interface
  3. Multiple Platform Support
  4. Support Different Formats
  5. Reading Tools

What makes them better than printed books?

eBooks Are More Portable Than Print

Printed books, especially hardbound editions, can be very heavy, while most modern eReader devices are lightweight. It’s much easier to carry an eReader containing an entire library of titles than to bring even a few physical books.

eBooks Take Up Much Less Space

Avid readers tend to collect a lot of books, which can take up too much space and make your home feel cluttered. However, even the largest collection of eBooks won’t take up much physical space in your home.

There Are No Late Fees for Library eBooks

If you borrow a physical book from the library and forget to return it, you will be charged a late fee. Many libraries also now offer eBook loans in addition to their print book offerings. You don’t have to return them by any due date instead, their licenses will simply expire on your device

Now we will learn how to program in Android studio using a java programming language step by step.

Step 1

First, we will create an Android Studio project named as per your choice. and go to Empty Activity, Android Studio will create MainActivity.java and activity_main.xml.

Step 2

Before starting we have to add the dependency that is used for open Pdf files in our build.gradle code file of the application. Here is our build.gradle file.

  1. apply plugin: ‘com.android.application’      
  2.       
  3. android {      
  4.     compileSdkVersion 29      
  5.     buildToolsVersion «29.0.2»      
  6.     defaultConfig {      
  7.         applicationId «com.example.book»      
  8.         minSdkVersion 24      
  9.         targetSdkVersion 29      
  10.         versionCode 1      
  11.         versionName «1.0»      
  12.         testInstrumentationRunner «androidx.test.runner.AndroidJUnitRunner»      
  13.     }      
  14.     buildTypes {      
  15.         release {      
  16.             minifyEnabled false      
  17.             proguardFiles getDefaultProguardFile(‘proguard-android-optimize.txt’), ‘proguard-rules.pro’      
  18.         }      
  19.     }      
  20. }      
  21.       
  22. dependencies {      
  23.     implementation fileTree(dir: ‘libs’, include: [‘*.jar’])      
  24.     implementation ‘androidx.appcompat:appcompat:1.2.0’      
  25.     implementation ‘androidx.constraintlayout:constraintlayout:2.0.4’      
  26.         
  27.     testImplementation ‘junit:junit:4.12’      
  28.     androidTestImplementation ‘androidx.test.ext:junit:1.1.2’      
  29.     androidTestImplementation ‘androidx.test.espresso:espresso-core:3.3.0’      
  30.     implementation ‘com.github.barteksc:android-pdf-viewer:2.8.2’      
  31.       
  32. }     

Here we Implement two methods: com.github.barteksc:android-pdf-viewer:2.8.2'
We add the material dependency in build.gradle file. the Android application which is used for material design,
After adding the dependency in our project sync the project.

Step 3

After the successful sync of the project. go to splash screen activity   

Activity-Splash-Screen.xml

The first screen visible to the user when the application’s launched.  We use Splash screens to display some animations and application logos, while some data for the next screens are fetched

  1. <RelativeLayout      
  2.          android:layout_width=«match_parent»      
  3.          android:layout_height=«match_parent»>      
  4.        
  5.          <ImageView      
  6.              android:id=«@+id/img»      
  7.              android:layout_width=«329dp»      
  8.              android:layout_height=«409dp»      
  9.              android:layout_marginLeft=«40dp»      
  10.              android:layout_marginTop=«20dp»      
  11.              android:src=«@drawable/logo» />      
  12.        
  13.         <TextView      
  14.              android:id=«@+id/tv3»      
  15.              android:layout_width=«wrap_content»      
  16.              android:layout_height=«wrap_content»      
  17.              android:layout_marginLeft=«70sp»      
  18.              android:layout_marginTop=«568sp»      
  19.              android:fontFamily=«cursive»      
  20.              android:text=«Powered by Yatish Chhonkar»      
  21.              android:textColor=«@color/colorwhite»      
  22.              android:textSize=«25sp» />      
  23.        
  24.      </RelativeLayout>      

After completing the XML part be jumped into  implementation in java.

Step 4 — Main Activity java

Here we implement java code with XML which is a simple constant screen for a fixed amount of time that is used to display the book content, logo, name.

  1. public class Splash_screen extends AppCompatActivity {    
  2.     
  3.     TextView slogan ,txt;    
  4.         
  5.     Animation topanim,bottomanim;    
  6.     
  7.     @Override    
  8.     protected void onCreate(Bundle savedInstanceState) {    
  9.         super.onCreate(savedInstanceState);    
  10.     
  11.        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);    
  12.     
  13.         setContentView(R.layout.activity_splash_screen);    
  14.     
  15.         slogan=(TextView)findViewById(R.id.tv2);    
  16.         txt=(TextView)findViewById(R.id.tv3);    
  17.     
  18.                          
  19.     
  20.         topanim = AnimationUtils.loadAnimation(this,R.anim.top_animation);    
  21.         bottomanim = AnimationUtils.loadAnimation(this,R.anim.bottom_animation);    
  22.     
  23.           
  24.     
  25.         slogan.setAnimation(bottomanim);    
  26.         txt.setAnimation(bottomanim);    
  27.     
  28.           
  29.     
  30.     new Handler().postDelayed(new Runnable() {    
  31.         @Override    
  32.         public void run() {    
  33.     
  34.             Intent intent = new Intent(Splash_screen.this,MainActivity.class);    
  35.             startActivity(intent);    
  36.             finish();    
  37.     
  38.         }    
  39.     },6000);    
  40.     
  41.     }    
  42. }   

Step 5 

While complying with the part of the splash screen we move to the next remaining part to open pdf content file.   

PdfOpner.xml

Create another empty activity to open Pdf file

 

  1. <?xml version=«1.0» encoding=«utf-8»?>    
  2.  <androidx.constraintlayout.widget.ConstraintLayout xmlns:android=«http://schemas.android.com/apk/res/android»    
  3.      xmlns:app=«http://schemas.android.com/apk/res-auto»    
  4.      xmlns:tools=«http://schemas.android.com/tools»    
  5.      android:layout_width=«match_parent»    
  6.      android:layout_height=«match_parent»    
  7.      tools:context=«.pdfOpener»>    
  8.      
  9.      <com.github.barteksc.pdfviewer.PDFView    
  10.          android:layout_width=«match_parent»    
  11.          android:layout_height=«match_parent»    
  12.          android:id=«@+id/pdfViewer»>    
  13.      
  14.      </com.github.barteksc.pdfviewer.PDFView>    
  15.      
  16.  </androidx.constraintlayout.widget.ConstraintLayout>   

Here we use a library for it too.. github.com/barteksc/AndroidPdfViewer in our project too

Step 6

While completing the part of the pdf opener file .xml we move to the next remaining part to pdf opener file .java class, 

PdfOpenerFile.java

 

  1. public class pdfOpener extends AppCompatActivity {    
  2.     
  3.     PDFView myPDFViewer;    
  4.     
  5.     @Override    
  6.  protected void onCreate(Bundle savedInstanceState) {    
  7.         super.onCreate(savedInstanceState);    
  8.         setContentView(R.layout.activity_pdf_opener);    
  9.     
  10.         myPDFViewer = (PDFView) findViewById(R.id.pdfViewer);    
  11.     
  12.         String getItam =getIntent().getStringExtra(«PdfFieName»);    
  13.     
  14.         if(getItam.equals(«संख्या पद्धति»)){    
  15.             myPDFViewer.fromAsset(«संख्या पद्धति.pdf»).load();    
  16.         }    
  17.     
  18.         if(getItam.equals(«सरलीकरण»)){    
  19.             myPDFViewer.fromAsset(«सरलीकरण.pdf»).load();    
  20.         }    
  21.     
  22.         if(getItam.equals(«LCM तथा HCF»)){    
  23.             myPDFViewer.fromAsset(«LCM तथा HCF.pdf»).load();    
  24.         }    
  25.     
  26.         if(getItam.equals(«वर्गमूल तथा घनमूल»)){    
  27.             myPDFViewer.fromAsset(«वर्गमूल तथा घनमूल.pdf»).load();    
  28.         }    
  29.     
  30.         if(getItam.equals(«घातांक एवं करणी»)){    
  31.             myPDFViewer.fromAsset(«घातांक एवं करणी.pdf»).load();    
  32.         }    
  33.     
  34.         if(getItam.equals(«औसत»)){    
  35.             myPDFViewer.fromAsset(«औसत.pdf»).load();    
  36.         }    
  37.     
  38.         if(getItam.equals(«प्रतिशत»)){    
  39.             myPDFViewer.fromAsset(«प्रतिशत.pdf»).load();    
  40.         }    
  41.     
  42.         if(getItam.equals(«लाभ और हानि»)){    
  43.             myPDFViewer.fromAsset(«लाभ और हानि.pdf»).load();    
  44.         }    
  45.     
  46.         if(getItam.equals(«आयु पर आधरित प्रश्न»)){    
  47.             myPDFViewer.fromAsset(«आयु पर आधरित प्रश्न.pdf»).load();    
  48.         }    
  49.     
  50.         if(getItam.equals(«अनुपात एवं समानुपात»)){    
  51.             myPDFViewer.fromAsset(«अनुपात एवं समानुपात.pdf»).load();    
  52.         }    
  53.     
  54.         if(getItam.equals(«साझा»)){    
  55.             myPDFViewer.fromAsset(«साझा.pdf»).load();    
  56.         }    
  57.     
  58.         if(getItam.equals(«मिश्रण»)){    
  59.             myPDFViewer.fromAsset(«मिश्रण.pdf»).load();    
  60.         }    
  61.     
  62.         if(getItam.equals(«मिश्र समानुपात»)){    
  63.             myPDFViewer.fromAsset(«मिश्र समानुपात.pdf»).load();    
  64.         }    
  65.     
  66.         if(getItam.equals(«साधारण ब्याज»)){    
  67.             myPDFViewer.fromAsset(«साधारण ब्याज.pdf»).load();    
  68.         }    
  69.     
  70.         if(getItam.equals(«चक्रवृध्दि ब्याज»)){    
  71.             myPDFViewer.fromAsset(«चक्रवृध्दि ब्याज.pdf»).load();    
  72.         }    
  73.     
  74.     
  75.         if(getItam.equals(«कार्य तथा समय»)){    
  76.             myPDFViewer.fromAsset(«कार्य तथा समय.pdf»).load();    
  77.         }    
  78.     
  79.         if(getItam.equals(«नल एवमं हौज़»)){    
  80.             myPDFViewer.fromAsset(«नल एवमं हौज़.pdf»).load();    
  81.         }    
  82.     
  83.         if(getItam.equals(«रेलगाडी»)){    
  84.             myPDFViewer.fromAsset(«रेलगाडी.pdf»).load();    
  85.         }    
  86.     
  87.         if(getItam.equals(«नाव तथा धारा»)) {    
  88.             myPDFViewer.fromAsset(«नाव तथा धारा.pdf»).load();    
  89.         }    
  90.     
  91.             if(getItam.equals(«क्षेत्रफल एवमं आयतन»)) {    
  92.                 myPDFViewer.fromAsset(«क्षेत्रफल एवमं आयतन.pdf»).load();    
  93.     
  94.             }    
  95.     }    
  96. }   

We can use a custom PDF Viewer.

In your Gradle file compile this: 'com.github.barteksc:android-pdf-viewer:2.0.3'

Step 7 — Activity-Main-.XML

While complying with the part of the pdf opener class .java we move to the next remaining part to Main Activity .xml, 

  

Here we add a list view in XML with match parent height and width and assign id as a listview. 

  1. <RelativeLayout      
  2.       
  3.  xmlns:android=«http://schemas.android.com/apk/res/android»      
  4.  xmlns:app=«http://schemas.android.com/apk/res-auto»      
  5.  xmlns:tools=«http://schemas.android.com/tools»      
  6.  android:layout_width=«match_parent»      
  7.  android:layout_height=«match_parent»      
  8.  tools:context=«.MainActivity»>      
  9.       
  10. <ListView      
  11.     android:layout_width=«match_parent»      
  12.     android:layout_height=«match_parent»      
  13.     android:id=«@+id/lstview»      
  14.     android:padding=«15dp»/>      
  15. </RelativeLayout>     

Step 8

Here we set data into list view  which we create in XML  

Main Activity-.java 

  1. public class MainActivity extends AppCompatActivity {  
  2.   
  3.     ListView lsview;  
  4.   
  5.     @Override  
  6.     protected void onCreate(Bundle savedInstanceState) {  
  7.         super.onCreate(savedInstanceState);  
  8.         setContentView(R.layout.activity_main);  
  9.   
  10.         lsview = (ListView) findViewById(R.id.lstview);  
  11.   
  12.         String[] chapter = {  
  13.             «संख्या पद्धति»,  
  14.             «सरलीकरण»,  
  15.             «LCM तथा HCF»,  
  16.             «वर्गमूल तथा घनमूल»,  
  17.             «घातांक एवं करणी»,  
  18.             «औसत»,  
  19.             «प्रतिशत»,  
  20.             «लाभ और हानि»,  
  21.             «आयु पर आधरित प्रश्न»,  
  22.             «अनुपात एवं समानुपात»,  
  23.             «साझा»,  
  24.             «मिश्रण»,  
  25.             «मिश्र समानुपात»,  
  26.             «साधारण ब्याज»,  
  27.             «चक्रवृध्दि ब्याज»,  
  28.             «कार्य तथा समय»,  
  29.             «नल एवमं हौज़»,  
  30.             «रेलगाडी»,  
  31.             «नाव तथा धारा»,  
  32.             «क्षेत्रफल एवमं आयतन»  
  33.         };  
  34.   
  35.         ArrayAdapter < String > adapter = new ArrayAdapter < String > (this, android.R.layout.simple_list_item_1, chapter) {  
  36.   
  37.             @NonNull  
  38.             @Override  
  39.             public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {  
  40.   
  41.                 View view = super.getView(position, convertView, parent);  
  42.   
  43.                 TextView mytxt = (TextView) view.findViewById(android.R.id.text1);  
  44.                 return view;  
  45.             }  
  46.         };  
  47.   
  48.         lsview.setAdapter(adapter);  
  49.   
  50.   
  51.         lsview.setOnItemClickListener(new AdapterView.OnItemClickListener() {  
  52.             @Override  
  53.             public void onItemClick(AdapterView < ? > parent, View view, int position, long id) {  
  54.   
  55.                 String iteam = lsview.getItemAtPosition(position).toString();  
  56.   
  57.                 Intent start = new Intent(getApplicationContext(), pdfOpener.class);  
  58.                 start.putExtra(«PdfFieName», iteam);  
  59.                 startActivity(start);  
  60.   
  61.             }  
  62.         });  
  63.     }  

Here we use listview, array adapter, and set adapter into list view once we click the listview, the intent will take us to Pdfopner class activity. 

 

After complying with the code it will look like as shown in the picture. It’s ready to use.

 

Explanation

In the MainActivity.java file, we used List view and pdf open file by the line «findViewById(R.id.ls view)» we connect together and set the click listener name as per pdf file which saves in Array Adapter. Once we click the list view it fires in the intent and jumps into a pdf file.   

Benefits of eBooks  

  1. eBooks save space
  2. eBooks save money
  3. eBooks help the environment
  4. An eBook is portable and convenient 
  5. Instantly download 

You can have a look at the output below

Conclusion 

You can easily turn your eBook into a revenue-generating machine on any platform screen. The key being – effective use of the eBook features to stand out in the digital world. An eBook is a way of reaching your readers in a digital world.

1 / 1 / 1

Регистрация: 03.06.2010

Сообщений: 91

1

20.05.2012, 11:44. Показов 8620. Ответов 4


Доброе время суток гиганты научной мысли!! =)
Мне нужно сделать читалку под андроид. Язык — желательно Java. Формат, который читалка должна уметь открывать — *.docbook.

Если есть где-нибудь исходники я был очень признателен. Но за счастье будет если вы хотя бы посоветуете в какую сторону рыть. Может есть какие-нибудь готовые библиотеки? Или примеры? Пробовал разобраться в FBReader’е но пока безрезультатно.

Извините если вопрос затертый. Не могу найти ничего путевого.

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



31 / 31 / 0

Регистрация: 05.11.2011

Сообщений: 178

21.05.2012, 02:36

2

Копаем в сторону парсеров… А остальное уже будет просто.



0



1 / 1 / 1

Регистрация: 03.06.2010

Сообщений: 91

21.05.2012, 02:46

 [ТС]

3

этого я и боялся =). Не сочтите за наглость, а проще никак нельзя реализовать?



0



31 / 31 / 0

Регистрация: 05.11.2011

Сообщений: 178

21.05.2012, 02:58

4

нет, полюбому придется писать свой парсер под конкретный тип файла))

все остальное по сравнению с этим — цветочки. ну может, вы и найдете необходимый парсер на просторах сети. но почти с нулевой вероятностью — нормальный.



0



Да да, вы не ослышались и все это возможно сделать при помощи простой как нокия 3310 программы Android App Book Maker! Как же долго я ее искал..

Android App Book Maker — Приложение позволит в наименьшие сроки делать полноценные книги — приложения для нашего Андроида. Создавать книгу имея это приложение под рукой — дело 3 минут! Можно добавить изображение, импортировать текстовый файл, настроить шрифт и анимации в нашей программе. Поддерживаются все оперативные системы Windows для установок.
Книги, деланные данным приложением, работают на любых Анлроид устройствах.

Краткое описание:
Программа предназначенная для легкого создания книг для вашего Андроид.

Описание:
Программа позволяет в кратчайшие сроки сделать полноценную книгу-приложение для вашего Андроидфона. Создать книгу имея эту программу под рукой — дело двух минут!
Возможно добавлять изображения, импортировать текстовые файлы, настраивать шрифт и анимацию в вашем приложении…. Одним словом кул 😀
Поддерживает все семейства ос windows для установки.

Возможности:
-Простой интерфейс
-Возможность импорта текстовых файлов
-Вставка картинок
-Оформление книги своей иконкой и обложкой
-Подпись файла прямо из программы

Она выложена на 4pda уже с кряком.

P.S : В архиве с прогой и лекарством в качестве бонуса добавил иконки в виде книжек.
P.P.S : В маркете — 60 процентов книжек платных и бесплатных сделаны этой самой программой.

Скачать Android App Book Maker с кряком можно здесь.

В чем соль:

А соль в том что теперь вы можете выпускать свои собственные книги-приложения и распространять их через Google Play и самое приятно что для этого вам не нужно разбираться в программировании, ведь с такой красотой не надо ничего знать!..

menu_Help wps-wpimage

Как написать программу для телефона для чтения книг

С появлением мобильных телефонов книги приобрели удобный электронный формат, который позволяет читать их с экрана аппарата. Карманная книга не только скрашивает свободное время полезным чтением, но и может помочь в нужную минуту.

Как написать программу для телефона для чтения книг

Вам понадобится

  • — поддержка java; — программа для чтения книг.

Инструкция

Некоторые современные телефоны поддерживают текстовые форматы TXT, PDF и другие. Но если ваш аппарат не умеет читать текстовые файлы, вы можете установить в него программу для чтения книг. Существуют как универсальные утилиты, так и написанные специально для вашей модели.

Для начала попробуйте установить в телефон программу, которая поддерживает распознавание форматов TXT, FB2 и тому подобные. Например, утилита Foliant подходит для большинства современных моделей телефонов, работает на тачфоне, распознает архивы. С ее помощью можно найти нужные книги в интернете. Скачайте программу и установите ее на телефон. Скопируйте в память книгу, которую вы хотите почитать, в формате TXT или FB2. Откройте файл с помощью программы Foliant и наслаждайтесь чтением.

Если по каким-то причинам универсальная программа для чтения книг в вашем телефоне не работает, вы можете воспользоваться утилитами для создания JAVA-книг. Скачайте и установите на компьютере программу BookReader. Запустите ее. Утилита позволяет выбирать нужные параметры будущей книги: шрифт, размер букв, язык, разбиение на абзацы и многое другое. Затем укажите из списка нужную вам книгу и создайте JAR-файл. Перенесите полученный файл в телефон и запустите как обычное JAVA-приложение. Перед вами откроется созданная книга.

Если вам неудобно каждый раз создавать JAVA-книгу для телефона, вы можете написать программу для вашей модели, которая будет поддерживать текстовые форматы. Скачайте и установите на компьютер утилиту ReadManiac. Запустите ее и настройте нужные вам параметры: включите языки, шрифты, возможность чтения из архива и другие. Укажите модель вашего телефона или близкую к ней, если ее нет в списке. Создайте программу с расширением JAR и скопируйте ее в память сотового. Запустите утилиту в телефоне и выберите в меню нужную вам книгу или архив с книгой из памяти. С помощью такой программы вы можете легко менять настройки чтения.

Видео по теме

Обратите внимание

Подбирайте формат книг, распознаваемый установленной программой.

Полезный совет

Не делайте слишком мелкий шрифт в телефонной книге. Не читайте книги с экрана телефона дольше 30 минут, а также находясь в движении. Это портит зрение.

Источники:

  • Сайт разработчика программы BookReader
  • Сайт разработчика программы ReadManiac

Войти на сайт

или

Забыли пароль?
Еще не зарегистрированы?

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Понравилась статья? Поделить с друзьями:
  • Как написать читай
  • Как написать читабельный пост
  • Как написать число сто пятью единицами
  • Как написать число со степенью на компьютере
  • Как написать число словами python