Advertisement
  1. Code
  2. Mobile Web Apps

Использование jQuery Mobile для создания нативного новостного приложения на Android: часть 3

Scroll to top
Read Time: 10 min
This post is part of a series called Use jQuery Mobile to Build a Native Android News Reader App.
Use jQuery Mobile to Build a Native Android News Reader App: Part 2

() translation by (you can also view the original English article)

В 1 части этой серии уроков мы представили наше приложение, описали макет страницы и обсудили, как создавать страницы в приложении с помощью jQuery Mobile. Во 2 части мы завершили внедрение нашего веб-приложения. В этой заключительной части мы перенесем веб-приложение в нативное приложение для Android.


Перенос в нативное приложение для Android

Веб-приложение, завершенное во 2 части будет преобразовано в нативное приложение для Android. Обсуждение ниже относится к ОС Android версии 2.2 и 2.3.

Приложение Android будет использовать файл index.html в качестве компонента пользовательского интерфейса. Мы создадим класс android.app.Activity для определения точки интеграции между index.html и приложением. Также мы создадим класс android.webkit.WebViewClient, чтобы убедиться, что страница «Новость» отображается в исходном экземпляре android.webkit.WebView, где запущено приложение «Новости».

Изменения в index.html

Обновим переменную NEWS_URI следующим образом:

1
var NEWS_URI = 'https://rss.news.yahoo.com/rss/';

Нам не нужен файл bridge.php для Android, чтобы перенаправлять AJAX-запросы на сервер Yahoo! News. Это связано с тем, что здесь не применяется ограничение на источник запроса. Когда он реализован как часть приложения, файл index.html не загружается с веб-сервера. Таким образом, он может выполнять вызовы AJAX для удаленных URL-адресов.

Кроме того, мы добавляем следующую функцию:

1
var EMPTY = '';
2
...
3
function changeLocation(varURI){
4
  showProgress();  
5
  $.get(EMPTY,function(data){
6
    window.location = varURI;
7
  });	
8
}

Функция changeLocation() выполняется из файла android.webkit.WebViewClient, который будет отображаться мгновенно. Цель этой функции - показать страницу прогресса во время перехода с страницы новостей на страницу новости.

  • Первый шаг в changeLocation() - отображение страницы прогресса.
  • Помните, что функция jQuery get() является специальной функцией jQuery ajax(). Мы вызываем функцию get(), передавая ему пустой URL-адрес и обработчик обратного вызова, который устанавливает переменную window.location как входящий аргумент. Аргумент ввода - это URL-адрес в атрибуте <a href='...'>, заключенный в тег a для новостного элемента, описаного в части 2 «Переход на страницу новости». Когда URL загружается, страница прогресса заменяется содержимым этого URL-адреса.
  • Как мы указывали ниже, функция changeLocation() не является важной частью переноса веб-приложения. Это необходимо только для отображения страницы прогресса при переходе со страницы новостей на страницу новости в приложении.
  • Страница перехода не требуется в веб-приложении при переходе со страницы списка новостей на страницу новости. Это связано с тем, что во время перехода сам веб-браузер отображает индикатор прогресса для пользователя. Например, в Android, как в нативном, так и в Dolphin-браузерах отображается вращающееся колесо и индикатор выполнения на панели навигации. В iOS браузер Safari отображает аналогичный индикатор прогресса.

Класс Activity

Начало нашего класса Activity, названная NewsActivity, показана ниже:

1
package com.news;
2
3
import android.app.Activity;
4
import android.webkit.WebView;
5
import android.os.Bundle;
6
...
7
public class NewsActivity extends Activity {
8
	WebView mWebView;
9
10
  public void onCreate(Bundle savedInstanceState) {
11
    super.onCreate(savedInstanceState);
12
    setContentView(R.layout.main);
13
14
    mWebView = (WebView) findViewById(R.id.webview);
15
    mWebView.setWebViewClient(new NewsClient());
16
    mWebView.getSettings().setJavaScriptEnabled(true);
17
    mWebView.getSettings().setDomStorageEnabled(true);
18
    mWebView.loadUrl("android_asset/www/index.html");
19
  }
20
  ...
21
}
  • В методе onCreate() мы сначала вызываем реализацию по умолчанию из суперкласса, а затем вызываем setContentView() для загрузки файла макета для этого действия. Входящим аргументом для setContentView() будет R.layout.main, который ссылается на файл main.xml в папке res/layout.
  • Мы получаем обращение к WebView через findViewById(R.id.webview). Мы устанавливаем пользовательский WebViewClient в WebView с именем NewsClient (который будет рассмотрен в ближайшее время). Затем мы настраиваем WebView, чтобы разрешить выполнение JavaScript и API хранилища DOM (последний необходим для использования HTML5 localStorage).
  • Наконец, мы просим WebView загрузить страницу index.html с кодом пользовательского интерфейса.

На странице новости нажатие кнопки Назад на устройстве вернет пользователя на страницу Категории. Чтобы убедиться в этом, нам сначала нужно обработать событие onKeyDown в нашем NewsActivity. Это действие показано ниже:

1
 public class NewsActivity extends Activity {
2
	WebView mWebView;
3
4
  public void onCreate(Bundle savedInstanceState) {
5
    ...
6
  }
7
  
8
  public boolean onKeyDown(int keyCode, KeyEvent event) {
9
    if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
10
      mWebView.goBack();            
11
      return true;
12
    }
13
    return super.onKeyDown(keyCode, event);
14
  }  
15
  ...
16
}

Если событие клавиши соответствует кнопке Назад на и WebView содержит некоторую историю, чтобы вернуться к ней, мы попросим WebView вернуться на один шаг в своей истории На странице Новости это будет соответствовать файлу index.html. Когда история возвращается на один шаг назад, страница Категорий будет отображаться в соответствии с шагами, описанными в части 2 «Запуск приложения».

Наконец, давайте посмотрим на пользовательский WebViewClient, который реализован как внутренний класс NewsActivity.

1
 public class NewsActivity extends Activity {
2
	WebView mWebView;
3
4
  public void onCreate(Bundle savedInstanceState) {
5
    ...
6
	mWebView.setWebViewClient(new NewsClient());
7
	...
8
  }
9
  
10
  public boolean onKeyDown(int keyCode, KeyEvent event) {
11
    ...
12
  }  
13
  
14
  private class NewsClient extends WebViewClient {
15
16
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
17
      view.loadUrl("javascript:changeLocation('" + url + "')");
18
      return true;
19
    }
20
  }
21
...
22
}

Единственной операцией, которую мы переопределяем из родительского класса, является shouldOverrideUrlLoading(), где мы программируем WebView на вызов функции JavaScript changeLocation() в index.html.

  • Если мы не определим пользовательский WebViewClient, страница новостей будет отображаться в отдельном приложении браузера вне нашего приложения. Поэтому определение WebViewClient имеет важное значение для отображения страницы новости как части приложения (т.е. в том же WebView, на котором размещается файл index.html).
  • Мы можем написать функцию shouldOverrideUrlLoading() более простым способом:
    1
    public boolean shouldOverrideUrlLoading(WebView view, String url)
    
    2
    {
    
    3
        view.loadUrl(url);
    
    4
        return true;
    
    5
    }
    

    Этого было бы достаточно, чтобы отобразить страницу новостей в том же WebView, на котором размещается index.html. Однако переход с страницы новостей на страницу Сведения о новостях не включает показ страницы прогресса

Изучив класс Activity, рассмотрим другие компоненты нашего приложения.

AndroidManifest.xml

1
<?xml version="1.0" encoding="utf-8"?>
2
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
  package="com.news" android:versionCode="1" android:versionName="1.0">
4
    <application android:icon="@drawable/icon" android:label="@string/app_name">
5
      <activity android:name=".NewsActivity" android:configChanges="orientation|keyboardHidden"
6
        android:label="@string/app_name">
7
          <intent-filter>
8
            <action android:name="android.intent.action.MAIN" />
9
            <category android:name="android.intent.category.LAUNCHER" />
10
          </intent-filter>
11
      </activity>
12
    </application>
13
    <uses-permission android:name="android.permission.INTERNET" />
14
</manifest>

Чтобы понять как работает файл AndroidManifest.xml обратитесь к официальной документации. В этом файле есть два отдельных объекта, достойных внимания.

  • Как описано в документации android.app.Activity, по умолчанию изменение конфигурации, включая изменение ориентации устройства или доступность клавиатуры, приводит к закрытию текущей активности. Чтобы предотвратить поведение по умолчанию, мы настраиваем наше приложение, указывая изменения конфигурации, которые будут обрабатываться самим приложением. Это определяется в атрибуте configChanges, где orientation устройства соответствует её изменению, а keyboardHidden соответствует изменению статуса клавиатуры (например, пользователь открыл клавиатуру устройства). Мы настраиваем приложение таким образом, чтобы при возникновении любого из этих событий текущая активность не была закрыта.
  • Элемент <uses-permission android:name="android.permission.INTERNET" /> позволяет приложению получать доступ к Интернету.

strings.xml

1
<?xml version="1.0" encoding="utf-8"?>
2
<resources>
3
  <string name="app_name">News</string>
4
</resources>

Этот файл определяет константу с именем app_name, которая используется для идентификации приложения Новости. Значение этого атрибута отображается в разных местах нашего Android-устройства, как видно ниже. Слева направо: под значком запуска приложения, панель заголовка, «Настройки» - «Управление приложениями».

Application nameApplication nameApplication name

Рисунок 11. Как отображается имя приложения в Android.

Интеграция HTML-интерфейса с помощью android.app.Activity

Мы реализуем пользовательский интерфейс в нашем Android-приложении, используя файл index.html и библиотеки JavaScript и css. Точка интеграции между index.html и пользовательским классом android.app.Activity представляет собой следующую строку:

1
  mWebView.loadUrl("android_asset/www/index.html");

Кроме того, обратите внимание на «Класс активности»,  в котором мы подключаем JavaScript и DOMStorage в объекте android.webkit.WebView так как в index.html необходимо запустить JavaScript и получить доступ к HTML5 localStorage.

1
  mWebView.getSettings().setJavaScriptEnabled(true);
2
  mWebView.getSettings().setDomStorageEnabled(true);

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

1
<uses-permission android:name="android.permission.INTERNET" />

Скриншоты приложения Android

на Рисунках 1 - 4 в первой части этой серии скриншоты приложения для Android.


Иконка приложения

Чтобы создать иконку для приложения Новости, мы следуем рекомендациям для дизайна приложений Android. В этом ресурсе доступны различные шаблоны в формате Adobe PSD. Мы загрузили icon_templates-v2.0.zip и извлекли файл Launcher-icon-template.psd. В этом файле мы выбрали два шаблона для создания иконки приложения:

icon 1icon 2

Мы разместили эти шаблоны в двух отдельных слоях в Adobe Photoshop и добавили графический текст News на дополнительный слой вверху, чтобы сделать иконку. В соответствии с руководством мы создали три версии иконки для экранов с низким, средним и высоким разрешением с размерами 36 x 36, 48 x 48 и 72 x 72 пикселей соответственно. Каждый из этих значков называется icon.png, и они помещаются в папки проектов Android в соответствии со следующей таблицей:

Имя папки Название файла Размер в пикселях
res\drawable-ldpi icon.png 36 x 36
res\drawable-mdpi icon.png 48 x 48
res\drawable-hdpi icon.png 72 x 72

В примере указана иконка размером 36 х 36:

icon ldpi


Нативная среда разработки приложений для Android

В этом уроке мы подготовили необходимые файлы проекта для импорта приложения для Android-новостей в среду разработки Eclipse. Требованиями проекта являются:

Проект был успешно протестирован как для платформы Android 2.2 API 8 уровня так и для API 2.3 уровня 9.

Импорт проекта

Перед импортом проекта в среду Eclipse убедитесь, что плагин Eclipse ADT указывает на правильное расположение Android SDK в вашей локальной системе. Чтобы проверить это, в меню Eclipse перейдите в Окно -> Настройки -> Android. Окно SDK Location должно указывать на местоположение Android SDK. После правильной настройки вы должны увидеть что-то похожее на то что есть на изображении ниже:

PreferencesPreferencesPreferences

Рисунок 12. Настройки Eclipse.

Файлы проекта располагаются в архиве с именем news.zip. Чтобы импортировать проект в меню Eclipse, перейдите в меню File -> Import, а затем в мастере импорта файлов выберите General -> Existing Projects into Workspace (см. Ниже).

ImportImportImport

Рисунок 13. Импорт проекта.

На следующей странице мастера нажмите Select archive file и найдите, где находится news.zip в вашей файловой системе. Окно Projects будет автоматически заполнено, если проект News уже выбран. Как показано ниже. Нажмите кнопку Finish, чтобы завершить импорт.

Project File SelectionProject File SelectionProject File Selection

Рисунок 14. Выбор файла проекта.

Eclipse автоматически создаст приложение после импорта. Теперь вы должны увидеть проект Новости в проводнике проекта, как показано ниже:

Project ExplorerProject ExplorerProject Explorer

Рисунок 15. Проводник проекта.

Для создания / отладки вашего проекта вы можете выбрать платформу Android OS 2.3 и 2.2 в качестве сборки. Для этого выберите проект News в проводнике проекта и в контекстном меню выберите Properties. В левой части списка свойств выберите Android в качестве свойства. Доступные цели сборки отображаются справа, как показано ниже:

Android Build TargetAndroid Build TargetAndroid Build Target

Рисунок 16. Сборка Android.

Список файлов

Список файлов в проекте приведен ниже.

Project ContentsProject ContentsProject Contents

Рисунок 17. Содержание проекта.

Мы уже обсуждали некоторые из этих файлов. Ниже приведен краткий обзор:

  • Папка src содержит исходный код для класса NewsActivity.
  • Папка gen содержит файлы, автоматически созданные Eclipse ADT.
  • В папке assets\www и ее подпапках содержатся все файлы, необходимые для UI, включая index.html; assets\www\css-js содержит файлы css и JavaScript, используемые index.html. В частности:
    • jquery-1.4.4.min.js, jquery.mobile-1.0a2.min.js, jquery.mobile-1.0a2.min.css - это библиотеки фреймворка jQuery Mobile.
    • jquery.ba-dotimeout.js являются библиотеками jQuery-dotimeout-plugin.
    • jquery.dst.js является библиотекой плагина DST.js.
    • assets\www\css-js\images\icons-18-white.png является файлами изображения, на которые ссылается jQuery Mobile.
  • assets\www\img\wait.gif - это иконка, используемая на странице прогресса.
  • Папки res\drawable* сохраняют иконки приложения, которые описаны в разделе «Иконка приложения» в этом руководстве.
  • Файл res\layout\main.xml является файлом макета Android XML. Поскольку пользовательский интерфейс в нашем приложении определен в файле index.html с использованием фреймворка jQuery Mobile, этот файл понятен и не нуждается в дальнейших комментариях.
  • Мы уже рассмотрели папки res\values\strings.xml и файл AndroidManifest.xml.
  • Файл default.properties определяет объект сборки и является частью архива news.zip. Он будет перезаписан Eclipse ADT в зависимости от выбора объекта сборки.

Вывод

Помимо разработки кросс-платформенных мобильных веб-приложений, платформа jQuery Mobile может использоваться для реализации нативных приложений для Android. В этой серии уроков мы разработали веб-приложение используя jQuery Mobile, а затем перенесли его в нативное приложение Android с небольшими изменениями. Основная идея состоит в том, чтобы использовать объект android.webkit.WebView в качестве контейнера для запуска html-файла веб-приложения и содержащегося в нем jQuery Mobile JavaScript-кода. Некоторые заключительные замечания приводятся ниже.

  • При сборке нативного приложения для Android страница html, работающая в android.webkit.WebView, не подвергается ограничениям одного и того же источника запроса при выполнении AJAX.
  • Плагин jquery-dotimeout и плагин DST.js, хотя и первоначально разработанный для рамки jQuery, хорошо работает в jQuery Mobile. Существует огромное количество плагинов, написанных для jQuery, и, хотя необходимо рассматривать каждый случай отдельно, они могут быть легко доступны в jQuery Mobile. Это огромное преимущество для этого фреймворка!
  • Мы протестировали веб-приложение на Android OS 2.2 и iPod Touch iOS 4.1 и 4.2. Нативное приложение для Android было протестировано с помощью эмуляторов Android OS 2.2 и 2.3 и телефона Android OS 2.2. Во всех случаях внешний вид и функциональные атрибуты очень похожи.
  • На платформе Android существуют известные приёмы для создания вызовов JavaScript-to-Java и Java-to-JavaScript. Фактически, мы продемонстрировали, как вызвать функцию jQuery Mobile JavaScript из кода Java в нашем приложении. Можно было бы разработать плагины jQuery Mobile для доступа к собственным API-интерфейсам Android. Это говорит о возможностях платформы jQuery Mobile для разработки нативных приложений для Android.
Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.