Текст книги "Разработка Android-приложений в деталях"
Автор книги: Тимур Машнин
Жанр: Компьютеры: прочее, Компьютеры
Возрастные ограничения: +12
сообщить о неприемлемом содержимом
Текущая страница: 9 (всего у книги 20 страниц)
WebView + Pagination
При большом размере HTML-страницы, отображаемой WebView-компонентом появляется проблема постраничного отображения HTML-страницы.
Так как компонент WebView основан на движке WebKit, он поддерживает различные JavaScript-библиотеки, в частности библиотеку JQuery и ее плагины.
Для отображения HTML-страницы в виде электронной книги можно воспользоваться различными JQuery-плагинами, например плагином BookBlock (http://ru.tmsoftstudio.com/file/page/applications/ru/jquery-book-reader.html).
При совместном использовании JavaScript-библиотек и WebView-компонента нужно учитывать, что загрузка и выполнение JavaScript-кода требует дополнительных ресурсов и времени, поэтому Android-приложение может стать менее отзывчивым на действия пользователя.
Для того чтобы WebView-компонент выполнял JavaScript-код, в Android-приложение необходимо добавить следующий код:
WebView myWebView = (WebView) rootView.findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings ();
webSettings.setJavaScriptEnabled (true);
myWebView.loadUrl("file:///android_asset/page.html»);
Для постраничного отображения HTML-страницы скачаем JQuery-плагин BookBlock и применим к HTML-странице следующий шаблон:
<!DOCTYPE html>
<html>
<head>
<meta charset=«UTF-8»>
<title> </title>
<link rel=«stylesheet» type=«text/css» href=«css/bookblock. css» />
<script src=«js/jquery. min. js»> </script>
<script src=«js/pagination. js»> </script>
<script src="js/jquery.bookblock. min. js»> </script>
</head>
<body>
<div class=«container»>
<div class=«main»>
<div class=«bb-custom-wrapper»>
<H1> </H1>
<div id=«bb-bookblock» class=«bb-bookblock»>
<! – Content – >
</div>
<nav>
<div>
<a id=«bb-nav-prev» href=«#» class=«bb-custom-icon bb-custom-icon-arrow-left»> Previous </a>
<a id=«bb-nav-next» href=«#» class=«bb-custom-icon bb-custom-icon-arrow-right»> Next </a>
</div>
<div>
<a id=«bb-nav-first» href=«#» class=«bb-custom-icon bb-custom-icon-first»> First page </a>
<a id=«bb-nav-last» href=«#» class=«bb-custom-icon bb-custom-icon-last»> Last page </a>
</div>
</nav>
</div>
</div>
</div>
</body>
</html>
Отображение электронных книг в формате ePub
Для создания Android EPub приложений существуют как платные, так и бесплатные библиотеки EPub SDK.
В качестве примера рассмотрим использование библиотеки AnFengde EPUB SDK (http://epub.anfengde.com/).
Для интеграции библиотеки с проектом Android-приложения скачаем и распакуем ZIP-архив библиотеки и импортируем проект EPUB_SDK-masterandroidlibEPUB_UI в Workspace-пространство, используя команду File | Import | Existing Android Code Into Workspace среды Eclipse.
В окне Project Explorer среды Eclipse нажмем правой кнопкой мышки на узле Android-приложения и в контекстном меню выберем команду Properties. В разделе Android | Library кнопкой Add добавим проект EPUB_UI и нажмем кнопку OK.
В файл AndroidManifest. xml Android-приложения добавим разрешения и Activity-компонент:
<uses-permission android:name="android.permission.INTERNET»/>
<uses-permission android:name="android.permission. WRITE_EXTERNAL_STORAGE»/>
<uses-permission android:name="android.permission. WRITE_SETTINGS»/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE»/>
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS»/>
<activity android:name="com.google.ads.AdActivity»
android: configChanges=«keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize»/>
</application>
Компоновку activity_main. xml компонента MainActivity определим как:
http://schemas.android.com/apk/res/android"okView xmlns: android="<com.anfengde.epub.ui.Bo
android: id="@+id/bookView»
android: layout_width=«match_parent»
android: layout_height=«fill_parent»>
</com.anfengde.epub.ui.BookView>
В метод onCreate () компонента MainActivity добавим следующий код:
import com.anfengde.epub.core.value.Constants;
import com.anfengde.epub.ui.BookView;
@Override
protected void onCreate (Bundle savedInstanceState) {
super. onCreate (savedInstanceState);
setContentView(R.layout.activity_main);
BookView bookView = (BookView) findViewById(R.id.bookView);
bookView.setPath(Constants.CACHE_PAHT);
bookView.initBook ();
bookView. openShelf ();
}
Теперь при запуске Android-приложения будет загружаться оболочка Book Shelf, отображающая EPub-книги, расположенные в папке assetsbooks приложения.
Для установки значка Android-приложения необходимо изменить файлы ic_launcher.png проекта EPUB_UI.
Для повторной сборки и развертывания Android-приложения нужно очистить папку bin проекта Android-приложения и папку sdcard/epub устройства.
Оболочка Book Shelf формируется кодом файла raw/jindex. js библиотеки EPUB_UI. Для изменения размеров значка книги в оболочке Book Shelf нужно изменить CSS-стили #container #afd_books ul в файле raw/sindex. css библиотеки EPUB_UI.
Отображение PDF
Для отображения в Android-приложении PDF-контента существуют как платные, так и бесплатные библиотеки PDF SDK.
В качестве примера рассмотрим использование библиотеки Android-Pdf-Viewer-Library (https://github.com/jblough/Android-Pdf-Viewer-Library).
Для интеграции библиотеки с проектом Android-приложения скачаем и распакуем ZIP-архив библиотеки и скопируем файл PdfViewer. jar в папку libs проекта.
Создадим Activity-компонент, расширяющий класс net.sf.andpdf. pdfviewer. PdfViewerActivity:
public class PDFActivity extends net.sf.andpdf. pdfviewer. PdfViewerActivity {
public int getPreviousPageImageResource () {return R. drawable. left_arrow;}
public int getNextPageImageResource () {return R. drawable. right_arrow;}
public int getZoomInImageResource () {return R. drawable. zoom_in;}
public int getZoomOutImageResource () {return R. drawable. zoom_out;}
public int getPdfPasswordLayoutResource () {return R.layout. pdf_file_password;}
public int getPdfPageNumberResource () {return R.layout. dialog_pagenumber;}
public int getPdfPasswordEditField () {return R.id.etPassword;}
public int getPdfPasswordOkButton () {return R.id.btOK;}
public int getPdfPasswordExitButton () {return R.id.btExit;}
public int getPdfPageNumberEditField () {return R.id.pagenum_edit;}
}
Скопируем файлы left_arrow.png, right_arrow.png, zoom_in.png, zoom_out.png из папки res/drawable библиотеки в папку res/drawable проекта приложения.
Скопируем файлы dialog_pagenumber. xml, pdf_file_password. xml из папки res/layout библиотеки в папку res/layout проекта приложения.
В файле AndroidManifest. xml проекта приложения добавим разрешение:
<uses-permission android:name="android.permission. WRITE_EXTERNAL_STORAGE» />
Поместим PDF-файл в папку assets проекта приложения.
Изменим код метода onCreate () основного Activity-компонента приложения:
@Override
protected void onCreate (Bundle savedInstanceState) {
super. onCreate (savedInstanceState);
File sdCard = Environment.getExternalStorageDirectory ();
File dir = new File (sdCard.getAbsolutePath () + "/pdf»);
dir.mkdirs ();
File f = new File (dir,«book. pdf»);
if (!f. exists ()) try {
InputStream is = getAssets ().open («book. pdf»);
int size = is. available ();
byte [] buffer = new byte [size];
is.read (buffer);
is.close ();
FileOutputStream fos = new FileOutputStream (f);
fos. write (buffer);
fos.close ();
} catch (Exception e) {throw new RuntimeException (e);}
String path = f.getPath ();
Intent intent = new Intent (this, PDFActivity.class);
intent. putExtra (PDFActivity. EXTRA_PDFFILENAME, path);
startActivity (intent);
}
В методе onCreate () основного Activity-компонента приложения PDF-файл копируется из папки assets в каталог pdf sdcard-карты, после чего вызывается Activity-компонент PDFActivity, обеспечивающий отображение скопированного PDF-файла.
Некоторые рецепты Android
Activity + IntentService + BroadcastReceiver
IntentService не может обрабатывать несколько запросов одновременно, он обрабатывает их последовательно, в порядке очереди.
В Android Studio выберем New | Service | Service (IntentService).
В результате будет создан класс сервиса, код которого модифицируем:
package com. application;
import android.app.IntentService;
import android.content.Intent;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import org. json. JSONObject;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net. URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class WebIntentService extends IntentService {
private static final String EXTRA_PARAM = "com.application.extra.PARAM»;
public static final String RESPONSE_STRING = «WebResponse»;
public static void startAction (Context context, String param) {
Intent intent = new Intent (context, WebIntentService.class);
intent. putExtra (EXTRA_PARAM, param);
context.startService (intent);
}
public WebIntentService () {
super («WebIntentService»);
}
@Override
protected void onHandleIntent (Intent intent) {
if (intent!= null) {
final String param = intent.getStringExtra (EXTRA_PARAM);
handleAction (param);
}
}
private void handleAction (String param) {
ConnectivityManager connMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo ();
if (networkInfo!= null && networkInfo.isConnected () && networkInfo.isAvailable ()) {
InputStream is = null;
URL url = null;
try {
url = new URL (param);
HttpURLConnection conn = (HttpURLConnection) url. openConnection ();
conn.setReadTimeout (10000 /* milliseconds */);
conn.setConnectTimeout (15000 /* milliseconds */);
conn.setRequestMethod («GET»);
conn.setDoInput (true);
conn.connect ();
int response = conn.getResponseCode ();
is = conn.getInputStream ();
// Convert the InputStream into a string
BufferedReader br = null;
StringBuilder sb = new StringBuilder ();
String line;
br = new BufferedReader (new InputStreamReader (is));
while ((line = br.readLine ())!= null) {
sb. append (line);
}
String contentAsString=sb.toString ();
is.close ();
conn. disconnect ();
JSONObject reader = new JSONObject (contentAsString);
JSONObject main = reader.getJSONObject («main»);
String temp = main.getString («temp»);
Calendar c = Calendar.getInstance ();
SimpleDateFormat df = new SimpleDateFormat («yyyy-MM-dd HH: mm: ss»);
String formattedDate = df.format(c.getTime ());
String result=formattedDate + " temp: " +temp;
Intent broadcastIntent = new Intent ();
broadcastIntent.setAction(MainActivity.WebReceiver.PROCESS_RESPONSE);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent. putExtra (RESPONSE_STRING, result);
sendBroadcast (broadcastIntent);
Context context = this;
SharedPreferences sharedPref = context.getSharedPreferences("com.application.PREFERENCE_FILE_KEY",Context.MODE_PRIVATE);
SharedPreferences. Editor editor = sharedPref. edit ();
editor. putString («temp», temp);
editor. putString («date», formattedDate);
editor.commit ();
} catch (Exception e) {
e.printStackTrace ();
}
} else {
Context context = this;
SharedPreferences sharedPref = context.getSharedPreferences("com.application.PREFERENCE_FILE_KEY», Context.MODE_PRIVATE);
String date=sharedPref.getString («date», «unknown date»);
String temp=sharedPref.getString («temp», «unknown temp»);
String result=date + " temp: " +temp;
Intent broadcastIntent = new Intent ();
broadcastIntent.setAction(MainActivity.WebReceiver.PROCESS_RESPONSE);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent. putExtra (RESPONSE_STRING, result);
sendBroadcast (broadcastIntent);
}
}
}
Здесь, при запуске сервиса, проверяется наличие соединения с Интернетом, затем получаются данные в JSON-формате по указанному URL адресу.
Далее необходимые данные извлекаются и отправляются BroadcastReceiver в виде строки.
Извлеченные данные записываются в настройки SharedPreferences.
Если же соединение с Интернетом отсутствует, тогда данные извлекаются из настроек SharedPreferences и отправляются BroadcastReceiver в виде строки.
Для отключения соединения с Интернетом в эмуляторе можно нажать F8.
В MainActivity создадим встроенный класс BroadcastReceiver:
package com. application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android. os. Bundle;
import android.support. v7.app. AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android. widget. TextView;
public class MainActivity extends AppCompatActivity {
private WebReceiver receiver;
@Override
protected void onCreate (Bundle savedInstanceState) {
super. onCreate (savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter(WebReceiver.PROCESS_RESPONSE);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new WebReceiver ();
registerReceiver (receiver, filter);
http://api.openweathermap.org/data/2.5/weather?q=London,uk");is, "WebIntentService.startAction(MainActivity.th
}
@Override
public boolean onCreateOptionsMenu (Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected (MenuItem item) {
int id = item.getItemId ();
if (id == R.id.action_settings) {
return true;
}
return super. onOptionsItemSelected (item);
}
public class WebReceiver extends BroadcastReceiver {
public static final String PROCESS_RESPONSE =«com. WebReceiver»;
public WebReceiver () {}
@Override
public void onReceive (Context context, Intent intent) {
String responseString = intent.getStringExtra(WebIntentService.RESPONSE_STRING);
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText (responseString);
}
}
}
Здесь в методе onCreate содается и регистрируется экземпляр внутреннего класса BroadcastReceiver.
Кроме того, запускается сервис, получающий данные по указанному URL адресу.
BroadcastReceiver получает данные в виде строки и отображает их в TextView.
AndroidManifest. xml будет иметь код:
<?xml version=«1.0» encoding=«utf-8»? >
<manifest xmlns: android="http://schemas.android.com/apk/res/android"
package=«com. application»>
<uses-permission android:name="android.permission.INTERNET» />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE» />
<application
android: allowBackup=«true»
android: icon="@mipmap/ic_launcher»
android: label="@string/app_name»
android: theme="@style/AppTheme»>
<activity
android:name=".MainActivity»
android: label="@string/app_name»>
<intent-filter>
<action android:name="android.intent.action.MAIN» />
<category android:name="android.intent.category.LAUNCHER» />
</intent-filter>
</activity>
<service
android: name=». WebIntentService»
android: exported=«false»>
</service>
</application>
</manifest>
Файл компоновки:
<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» android: paddingLeft="@dimen/activity_horizontal_margin»
android: paddingRight="@dimen/activity_horizontal_margin»
android: paddingTop="@dimen/activity_vertical_margin»
android: paddingBottom="@dimen/activity_vertical_margin» tools:context=".MainActivity»>
<TextView
android: layout_width=«wrap_content»
android: layout_height=«wrap_content»
android: id="@+id/textView»/>
</RelativeLayout>
Для запуска сервиса в отдельном процессе, в тэге <service> файла AndroidManifest. xml атрибут android: process будет иметь значение, начинающееся с двоеточия:
android: process=":new_application_process»
Для ограничения доступа другим приложениям к сервису, в тэге <service> файла AndroidManifest. xml атрибут android: exported будет иметь значение false:
android: exported=«false»
Чтобы предотвратить остановку сервиса системой при нехватке памяти, можно вызвать метод startForeground () в методе обратного вызова onStartCommand ().
Для автоматического запуска сервиса при перезагрузке телефона, можно создать BroadcastReceiver для запуска сервиса:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED» />
<receiver android:name="com.example.StartServiceReceiver»>
<intent-filter>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED»/>
<action android:name="android.intent.action. QUICKBOOT_POWERON» />
</intent-filter>
</intent-filter>
public class StartServiceReceiver extends BroadcastReceiver {
@Override
public void onReceive (Context context, Intent intent)
{
Intent serviceIntent = new Intent (context, StartBootService.class);
context.startService (serviceIntent);
}
}
Activity + IntentService + createPendingResult
Создание объекта PendingIntent методом createPendingResult активности это другой способ получения данных из сервиса для их обработки в методе обратного вызова onActivityResult активности.
Код IntentService при этом будет иметь следующий вид:
package com. application;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import org. json. JSONObject;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net. URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class WebIntentService extends IntentService {
public WebIntentService () {
super («WebIntentService»);
}
@Override
protected void onHandleIntent (Intent intent) {
if (intent!= null) {
final String param = intent.getStringExtra (MainActivity. EXTRA_PARAM);
PendingIntent pi = intent.getParcelableExtra(MainActivity.PARAM_PINTENT);
handleAction (param, pi);
}
}
/**
* Handle action in the provided background thread with the provided
* parameters.
*/
private void handleAction (String param, PendingIntent pi) {
ConnectivityManager connMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo ();
if (networkInfo!= null && networkInfo.isConnected () && networkInfo.isAvailable ()) {
InputStream is = null;
URL url = null;
try {
url = new URL (param);
HttpURLConnection conn = (HttpURLConnection) url. openConnection ();
conn.setReadTimeout (10000 /* milliseconds */);
conn.setConnectTimeout (15000 /* milliseconds */);
conn.setRequestMethod («GET»);
conn.setDoInput (true);
conn.connect ();
int response = conn.getResponseCode ();
is = conn.getInputStream ();
// Convert the InputStream into a string
BufferedReader br = null;
StringBuilder sb = new StringBuilder ();
String line;
br = new BufferedReader (new InputStreamReader (is));
while ((line = br.readLine ())!= null) {
sb. append (line);
}
String contentAsString=sb.toString ();
is.close ();
conn. disconnect ();
JSONObject reader = new JSONObject (contentAsString);
JSONObject main = reader.getJSONObject («main»);
String temp = main.getString («temp»);
Calendar c = Calendar.getInstance ();
SimpleDateFormat df = new SimpleDateFormat («yyyy-MM-dd HH: mm: ss»);
String formattedDate = df.format(c.getTime ());
String result=formattedDate + " temp: " +temp;
Intent intent = new Intent().putExtra(MainActivity.PARAM_RESULT, result);
pi.send(WebIntentService.this,MainActivity.RESULT_CODE, intent);
Context context = this;
SharedPreferences sharedPref = context.getSharedPreferences("com.application.PREFERENCE_FILE_KEY",Context.MODE_PRIVATE);
SharedPreferences. Editor editor = sharedPref. edit ();
editor. putString («temp», temp);
editor. putString («date», formattedDate);
editor.commit ();
} catch (Exception e) {
e.printStackTrace ();
}
} else {
Context context = this;
SharedPreferences sharedPref = context.getSharedPreferences("com.application.PREFERENCE_FILE_KEY», Context.MODE_PRIVATE);
String date=sharedPref.getString («date», «unknown date»);
String temp=sharedPref.getString («temp», «unknown temp»);
String result=date + " temp: " +temp;
Intent intent = new Intent().putExtra(MainActivity.PARAM_RESULT, result);
try {
pi.send(WebIntentService.this,MainActivity.RESULT_CODE, intent);
} catch (PendingIntent.CanceledException e) {
e.printStackTrace ();
}
}
}
}
Здесь, при запуске сервиса, проверяется наличие соединения с Интернетом, затем получаются данные в JSON-формате по указанному URL адресу.
Далее необходимые данные извлекаются и передаются в объект PendingIntent в виде строки.
Объект PendingIntent отправляется обратно в создавшую его активность методом send.
Извлеченные данные записываются в настройки SharedPreferences.
Если же соединение с Интернетом отсутствует, тогда данные извлекаются из настроек SharedPreferences и передаются в объект PendingIntent в виде строки.
Для отключения соединения с Интернетом в эмуляторе можно нажать F8.
Активность, создавшая объект PendingIntent, будет иметь следующий код:
package com. application;
import android.app.PendingIntent;
import android.content.Intent;
import android. os. Bundle;
import android.support. v7.app. AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android. widget. TextView;
public class MainActivity extends AppCompatActivity {
public static final String EXTRA_PARAM = "com.application.extra.PARAM»;
public final static String PARAM_PINTENT = «PendingIntent»;
public final static String PARAM_RESULT = «Result»;
final int REQUEST_CODE = 0;
public final static int RESULT_CODE = 1;
@Override
protected void onCreate (Bundle savedInstanceState) {
super. onCreate (savedInstanceState);
setContentView(R.layout.activity_main);
PendingIntent pi;
pi = createPendingResult (REQUEST_CODE, new Intent (), 0);
Intent intent = new Intent(MainActivity.this, WebIntentService.class);
intent. putExtra (EXTRA_PARAM, "http://api.openweathermap.org/data/2.5/weather?q=London,uk");
intent. putExtra (PARAM_PINTENT, pi);
startService (intent);
}
@Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
// Check which request we’re responding to
if (requestCode == REQUEST_CODE) {
// Make sure the request was successful
if (resultCode == RESULT_CODE) {
String responseString=data.getStringExtra(MainActivity.PARAM_RESULT);
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText (responseString);
}
}
}
@Override
public boolean onCreateOptionsMenu (Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected (MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest. xml.
int id = item.getItemId ();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super. onOptionsItemSelected (item);
}
}
Здесь в методе onCreate создается объект PendingIntent, который передается в объект Intent, с помощью которого запускается сервис.
В методе onActivityResult из возвращаемого объекта PendingIntent извлекаются данные, отображаемые в TextView.
AndroidManifest. xml будет иметь код:
<?xml version=«1.0» encoding=«utf-8»? >
<manifest xmlns: android="http://schemas.android.com/apk/res/android"
package=«com. application»>
<uses-permission android:name="android.permission.INTERNET» />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE» />
<application
android: allowBackup=«true»
android: icon="@mipmap/ic_launcher»
android: label="@string/app_name»
android: theme="@style/AppTheme»>
<activity
android:name=".MainActivity»
android: label="@string/app_name»>
<intent-filter>
<action android:name="android.intent.action.MAIN» />
<category android:name="android.intent.category.LAUNCHER» />
</intent-filter>
</activity>
<service
android: name=». WebIntentService»
android: exported=«false»>
</service>
</application>
</manifest>
Файл компоновки:
<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» android: paddingLeft="@dimen/activity_horizontal_margin»
android: paddingRight="@dimen/activity_horizontal_margin»
android: paddingTop="@dimen/activity_vertical_margin»
android: paddingBottom="@dimen/activity_vertical_margin» tools:context=".MainActivity»>
<TextView
android: layout_width=«wrap_content»
android: layout_height=«wrap_content»
android: id="@+id/textView»/>
</RelativeLayout>
Правообладателям!
Это произведение, предположительно, находится в статусе 'public domain'. Если это не так и размещение материала нарушает чьи-либо права, то сообщите нам об этом.