Как стать автором
Обновить

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

Время на прочтение9 мин
Количество просмотров3.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.
  • Еще зачастую включается заставка при запуске приложения.

Итог


Собственно, все ключевые особенности разработки под нук я постарался изложить, а так же написать простенькие классы, который упрощали бы разработку.
На всякий случай продублирую ссылку на скелетное приложение.
Теги:
Хабы:
Всего голосов 73: ↑68 и ↓5+63
Комментарии12

Публикации