
Введение
Недавно мы (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.
- Еще зачастую включается заставка при запуске приложения.
Итог
Собственно, все ключевые особенности разработки под нук я постарался изложить, а так же написать простенькие классы, который упрощали бы разработку.
На всякий случай продублирую ссылку на скелетное приложение.