Pull to refresh

Разработка приложений под электронную книгу Barnes&Noble Nook

Reading time9 min
Views3.3K
image

Введение


Недавно мы (mynook.ru, первый пост, второй пост) открыли свой профиль на reformal.ru, где нас начали спрашивать как самому писать приложения под нук, а так же просили выложить исходники FBReader'а.
Все исходники вы теперь можете найти на гуглокоде, а вот насчет первого я постараюсь сейчас рассказать.

Большое спасибо отличному дизайнеру nilov за то что помог мне оформить картинками этот пост, за то, как он хорошо передизайнил иконки и за непосредственно перевод Nook'а.

На кого расчитано


Я предполагаю, что человек, который будет читать дальше знает азы разработки под андроид (если быть точнее, то под 1.5) и соответственно прошу не задавать вопросов про азы андроида и уж тем более не обсуждать то, как купить нук в россии/украине/etc…

Особенности железки


Наиболее точную информацию Вы можете найти на соответствующей странице на nookdevs.org
Ключевой момент для нас — это экран. Он, как известно, в нуке разделен на две части — цветная сенсорная и ч/б E-Ink. Причем по ширине они не совпадают:



С точки зрения самого андроида — это один большой экран, размером 600x944 px, причем изображение для LCD не растягивается, а обрезается. Вот как выглядит все это безобразие с точки зрения системы:



Верстка экрана


Здесь все очень просто. Вам достаточно использовать следующий шаблон, который создает два контейнера для E-Ink'а и для LCD экрана:

<?xml version="1.0" encoding="utf-8"?><br><LinearLayout<br>    xmlns:android="http://schemas.android.com/apk/res/android"<br>    android:layout_width="fill_parent"<br>    android:layout_height="fill_parent"<br>    android:orientation="vertical"><br><br>  <FrameLayout<br>      android:id="@+id/eink"<br>      android:layout_width="600.0px"<br>      android:layout_height="760.0px"<br>      android:background="@android:color/white"/><br><br>  <FrameLayout<br>      android:id="@+id/lcd"<br>      android:layout_width="480.0px"<br>      android:layout_height="144.0px"<br>      android:background="@android:color/black"/><br><br></LinearLayout><br><br>* This source code was highlighted with Source Code Highlighter.


Однако, границы E-Ink экрана находятся почти вплотную к бортику и из-за этого контент, который находится вплотную к границам читать очень неудобно и вообще плохо выглядит, а по-этому я бы посоветовал для Вас использовать вариант сразу с необходимыми отступами от краев (сверху отступ не требуется, т.к. там не граница экрана, а таскбар и выглядит все нормально):

<?xml version="1.0" encoding="utf-8"?><br><LinearLayout<br>  xmlns:android="http://schemas.android.com/apk/res/android"<br>  android:layout_width="fill_parent"<br>  android:layout_height="fill_parent"<br>  android:orientation="vertical"><br><br> <FrameLayout<br>   android:id="@+id/eink"<br>   android:layout_width="584.0px"<br>   android:layout_height="752.0px"<br>   android:layout_marginLeft="8px"<br>   android:layout_marginRight="8px"<br>   android:layout_marginBottom="8px"<br>   android:background="@android:color/white"/><br><br> <FrameLayout<br>   android:id="@+id/lcd"<br>   android:layout_width="480.0px"<br>   android:layout_height="144.0px"<br>   android:background="@android:color/black"/><br><br></LinearLayout><br><br>* This source code was highlighted with Source Code Highlighter.


Далее нам необходимо отключить TitleBar у нашего приложения (узенькая полосочка, которая на обычном андроиде играет роль заголовка для экрана). Это делается через аргумент application/activity в AndroidManifest.xml: android:theme="@android:style/Theme.Light.NoTitleBar"

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

Дополнительное API


Некоторое дополнительное API я запрогал в NookActivity и еще одном классе, которые вы можете получить, загрузив скелетное приложение.

Установка заголовка в таскбаре

Это делается через интент следующим кодом:
  private final static String NOOK_UPDATE_TITLE = "com.bravo.intent.UPDATE_TITLE";<br><br>  protected void nookUpdateTitle(String title) {<br>    try {<br>      Intent intent = new Intent(NOOK_UPDATE_TITLE);<br>      String key = "apptitle";<br>      intent.putExtra(key, title);<br>      sendBroadcast(intent);<br>    } catch (Exception ex) {<br>      ex.printStackTrace();<br>    }<br>  }<br><br>* This source code was highlighted with Source Code Highlighter.


Хардварные кнопки и жесты

Кнопки перелистывания страниц имеют следующие коды:
  public static final int NOOK_KEY_PREV_LEFT = 96;<br>  public static final int NOOK_KEY_PREV_RIGHT = 98;<br><br>  public static final int NOOK_KEY_NEXT_LEFT = 95;<br>  public static final int NOOK_KEY_NEXT_RIGHT = 97;<br><br>* This source code was highlighted with Source Code Highlighter.

Жесты тачскрина имеют следующие коды:
  public static final int NOOK_KEY_SHIFT_UP = 101;<br>  public static final int NOOK_KEY_SHIFT_DOWN = 100;<br><br>* This source code was highlighted with Source Code Highlighter.


Управление появлением заставки


Как оказалось необходимо вручную делать так, что бы заставка сама не включалась.
Для этого у меня написан свой классик, которая управляет появлением заставок, причем этот код требует разрешения «android.permission.WAKE_LOCK»:

public class NookScreensaverLock {<br>  Context context;<br>  long timeOut = 10 * 60000;<br>  PowerManager.WakeLock lock;<br><br>  public NookScreensaverLock(Context context) {<br>    this.context = context;<br><br><br>    PowerManager power = (PowerManager) context.getSystemService(Activity.POWER_SERVICE);<br>    lock = power.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "nookactivity" + hashCode());<br>    lock.setReferenceCounted(false);<br><br>    readSystemValues();<br>  }<br><br>  private void readSystemValues() {<br><br>    try {<br>      String[] values = {<br>          "value"<br>      };<br>      String name = null;<br>      String[] fields = {<br>          "bnScreensaverDelay"<br>      };<br>      for (int i = 0; i < fields.length; i++) {<br>        if (name == null) {<br>          name = "name=?";<br>        } else {<br>          name += " or name=?";<br>        }<br>      }<br>      Cursor c = context.getContentResolver().query(Uri.parse("content://settings/system"), values, name, fields, "name");<br>      if (c != null) {<br>        c.moveToFirst();<br>        long lvalue = c.getLong(0);<br>        if (lvalue > 0) {<br>          timeOut = lvalue;<br>        }<br><br>      }<br>      c.close();<br>      c.deactivate();<br><br>    } catch (Exception ex) {<br>      ex.printStackTrace();<br>    }<br>  }<br><br>  public void release() {<br>    if (lock.isHeld())<br>      lock.release();<br>  }<br><br>  public void acquire(long time) {<br>    lock.acquire(time);<br>  }<br><br>  public void acquire() {<br>    lock.acquire(timeOut);<br>  }<br>}<br><br>* This source code was highlighted with Source Code Highlighter.


readSystemValues() читает системные настройки и получает значение таймаута заставки, которое пользователь проставлял в настройках.

Базовое Activity для нука


Это и есть то, от чего вам необходимо наследовать все свои активити для более удобной работы в нуке, а так же здесь так же вы можете понять как используется NookScreensaverLock.
public abstract class NookActivity extends Activity {<br><br>  public static final int NOOK_KEY_PREV_LEFT = 96;<br>  public static final int NOOK_KEY_PREV_RIGHT = 98;<br><br>  public static final int NOOK_KEY_NEXT_LEFT = 95;<br>  public static final int NOOK_KEY_NEXT_RIGHT = 97;<br><br>  public static final int NOOK_KEY_SHIFT_UP = 101;<br>  public static final int NOOK_KEY_SHIFT_DOWN = 100;<br><br>  private NookScreensaverLock lock;<br><br>  private final static String NOOK_UPDATE_TITLE = "com.bravo.intent.UPDATE_TITLE";<br><br>  protected void nookUpdateTitle(String title) {<br>    try {<br>      Intent intent = new Intent(NOOK_UPDATE_TITLE);<br>      String key = "apptitle";<br>      intent.putExtra(key, title);<br>      sendBroadcast(intent);<br>    } catch (Exception ex) {<br>      ex.printStackTrace();<br>    }<br>  }<br><br>  @Override<br>  protected void onCreate(Bundle savedInstanceState) {<br>    super.onCreate(savedInstanceState);<br>    lock = new NookScreensaverLock(this);<br>    lock.acquire();<br>  }<br><br>  @Override<br>  public void onUserInteraction() {<br>    super.onUserInteraction();<br>    lock.acquire();<br>  }<br><br>  @Override<br>  protected void onResume() {<br>    super.onResume();<br>    lock.acquire();<br>  }<br><br>  @Override<br>  protected void onPause() {<br>    super.onPause();<br>    lock.release();<br>  }<br>}<br><br>* This source code was highlighted with Source Code Highlighter.


Особенности разработки



Рут


Прежде всего Вам необходим рут. Могу посоветовать мою и nilov'а прошивку, которую всегда можно найти на нашем блоге mynook.ru, в ней есть, к примеру, менеджер приложений, который иногда удобен при разработке.

Инструкции: mynook.ru, nookdevs.com

Adb и Дебаг

  • Дебаг работает прекрасно через adb, который прокинут через Wifi, к сожалению, драйвера USB еще нет.
  • Причем приложение будет устанавливаться лишь один раз, при повторной установке будет писаться ошибка несоответствия сертификатов и перед второй загрузкой/обновлением необходимо вручную удалять приложение через adb uninstall.
  • Еще зачастую включается заставка при запуске приложения.

Итог


Собственно, все ключевые особенности разработки под нук я постарался изложить, а так же написать простенькие классы, который упрощали бы разработку.
На всякий случай продублирую ссылку на скелетное приложение.
Tags:
Hubs:
+63
Comments12

Articles