Слайд 1Разработка мобильных приложений
Чиркунов Кирилл Лекция 4 cyril.chirkunov@computer.org vk.com/chirkunov
Новосибирский национальный исследовательский государственный университет (НГУ)
Слайд 2На прошлой лекции Лекция 4, слайд 1
Новосибирский государственный университет, 2012
Views (GroupView, TextView, Spinner, EditView and etc.) AbsoluteLayout, FrameLayout, LinearLayout, TableLayout, RelativeLayout Оптимизация разметки Drawables & Menus
Слайд 3Сегодня
Intents & Receivers Broadcast messaging Data Adapters Preferences & Settings & Files
Лекция 4, слайд 2
Слайд 4Намерения (Intents) Лекция 4, слайд 3
Применяются для: объявления о запуске Activity или Service, чтобы выполнить какие-либо действия на основе некоторых данных передачи уведомлений о том, что произошло событие явного запуска определенного Service или Activity
Слайд 5Код результата закрытия Activity
Лекция 4, слайд 4
Вызов из родительской активности: startActivityForResult(Intent i, int call_Identificator) Выставление результата в дочерней активности: setResult(int result, Intent i) Коды возврата: Activity.RESULT_OK Activity.RESULT_CANCELED (по умолчанию) Другие, более специализированные: RESULT_FIRST_USER RESULT_COMMON_ERROR и др.
Слайд 6Лекция 4, слайд 5
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch(requestCode) { case (SHOW_SUB_ACTIVITY_ONE) : { if (resultCode == Activity.RESULT_OK) { Uri horse = data.getData(); boolean inputCorrect = data.getBooleanExtra(IS_INPUT_CORRECT, false); String selectedPistol = data.getStringExtra(SELECTED_PISTOL); } break; } case (SHOW_SUB_ACTIVITY_TWO) : { if (resultCode == Activity.RESULT_OK) { // TODO: Handle OK click. } break; } } }
Слайд 7Лекция 4, слайд 6
Стандартные действия (часть)
Слайд 8Лекция 4, слайд 7
Стандартные категории (не все)
Слайд 9Данные намерения Лекция 4, слайд 8
Слайд 10Утверждение намерений
Лекция 4, слайд 9
Слайд 11Делегирование намерений
Лекция 4, слайд 10
Intent intent = getIntent(); … //some code startNextMatchingActivity(intent);
Слайд 12Выбор контакта из списка (демо)
Лекция 4, слайд 11
Слайд 13Расширяемость меню
Лекция 4, слайд 12
public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); Intent intent = new Intent(); intent.setData(MoonBaseProvider.CONTENT_URI); intent.addCategory(Intent.CATEGORY_SELECTED_ALTERNATIVE); int menuGroup = 0; int menuItemId = 0; int menuItemOrder = Menu.NONE; ComponentName caller = getComponentName(); Intent[] specificIntents = null; // The menu items created from the previous Intents // will populate this array. MenuItem[] outSpecificItems = null; // Set any optional flags. int flags = Menu.FLAG_APPEND_TO_GROUP; // Populate the menu menu.addIntentOptions(menuGroup, menuItemId,menuItemOrder,caller, specificIntents, intent, flags, outSpecificItems); return true; }
Слайд 14Linkify Лекция 4, слайд 13
TextView textView = (TextView) findViewById (R.id.myTextView); Linkify.addLinks (textView, Linkify.WEB_URLS|Linkify.EMAIL_ADDRESSES);
Определение через код:
Определение через xml-файл:
Определение через регулярные выражения:
int flags = Pattern.CASE_INSENSITIVE; Pattern p = Pattern.compile("\\bquake[0-9]*\\b", flags); Linkify.addLinks(myTextView, p, "content://com.paad.earthquake/earthquakes/");
Слайд 15Linkify MatchModifier & TransformFilter
Лекция 4, слайд 14
class MyMatchFilter implements MatchFilter { public boolean acceptMatch(CharSequence s, int start, int end) { return (start == 0 || s.charAt(start-1) != '!'); } }
class MyTransformFilter implements TransformFilter { public String transformUrl(Matcher match, String url) { return url.toLowerCase(); } }
Linkify.addLinks(myTextView, pattern, prefixWith, new MyMatchFilter(), new MyTransformFilter());
Слайд 16Регистрация широковещательного приемника
Лекция 4, слайд 16
Через manifest.xml: Через код: IntentFilter filter = new IntentFilter(NEW_LIFEFORM_DETECTED); LifeformDetectedBroadcastReceiver r = new LifeformDetectedBroadcastReceiver(); registerReceiver(r, filter); … unregisterReceiver(receiver);
Слайд 17Оповещение о событиях
Лекция 4, слайд 15
Intent intent = new Intent(NEW_LIFEFORM_DETECTED); intent.putExtra("lifeformName", lifeformType); intent.putExtra("longitude", currentLongitude); intent.putExtra("latitude", currentLatitude); sendBroadcast(intent);
public class LifeformDetectedBroadcastReceiver extends BroadcastReceiver { public static final String BURN = "com.paad.alien.action.BURN_IT_WITH_FIRE"; @Override public void onReceive(Context context, Intent intent) { // Get the lifeform details from the intent. Uri data = intent.getData(); String type = intent.getStringExtra("type"); double lat = intent.getDoubleExtra("latitude", 0); double lng = intent.getDoubleExtra("longitude", 0); Location loc = new Location("gps"); loc.setLatitude(lat); loc.setLongitude(lng); if (type.equals("alien")) { Intent startIntent = new Intent(BURN, data); startIntent.putExtra("latitude", lat); startIntent.putExtra("longitude", lng); context.startActivity(startIntent); } } }
Слайд 18Продвинутое оповещение
Упорядоченное оповещение: sendOrderedBroadcast(intent, null) sendOrderedBroadcast(intent, null, myBroadcastReceiver, null, Activity.RESULT_OK, null, null); «Липкие» трансляции (требуется полномочие BROADCAST_STICKY) sendStickyBroadcast removeStickyBroadcast
Лекция 4, слайд 17
Слайд 19Ожидающие намерения (Pending Intents)
Лекция 4, слайд 18
// Start an Activity Intent startActivityIntent = new Intent(this, MyOtherActivity.class); PendingIntent.getActivity(this, 0, startActivityIntent, 0); // Broadcast an Intent Intent broadcastIntent = new Intent(NEW_LIFEFORM_DETECTED); PendingIntent.getBroadcast(this, 0, broadcastIntent, 0);
Слайд 20Адаптеры
Интерфейс Adapter Наследники: ArrayAdapter SimpleCursorAdapter BaseAdapter, CursorAdapter, HeaderViewListAdapter, ListAdapter, ResourceCursorAdapter, SimpleAdapter, SpinnerAdapter, WrapperListAdapter Пользовательские адаптеры поддерживающие привязку к представлениям, наследникам абстрактного класса AdapterView
Лекция 4, слайд 19
Слайд 21Адаптеры (пример)
public class MyArrayAdapter extends ArrayAdapter { int resource; public ToDoItemAdapter(Context context, int resource, List items) { super(context, resource, items); resource = _resource; } @Override public View getView(int position, View convertView, ViewGroup parent) { LinearLayout newView; MyClass classInstance = getItem(position); // TODO Retrieve values to display from the // classInstance variable. // Inflate a new view if this is not an update. if (convertView == null) { newView = new LinearLayout(getContext()); String inflater = Context.LAYOUT_INFLATER_SERVICE; LayoutInflater vi = (LayoutInflater)getContext().getSystemService(inflater); vi.inflate(resource, newView, true); } else { newView = (LinearLayout)convertView; } // TODO Retrieve the Views to populate // TODO Populate the Views with object property values. return todoView; } }
Лекция 4, слайд 20
Слайд 22Использование адаптеров
Лекция 4, слайд 21
ArrayList myStringArray = new ArrayList(); ArrayAdapter myAdapterInstance; int layoutID = android.R.layout.simple_list_item_1; myAdapterInstance = new ArrayAdapter(this, layoutID , myStringArray); myListView.setAdapter(myAdapterInstance); String uriString = "content://contacts/people/"; Cursor myCursor = managedQuery(Uri.parse(uriString), null, null, null); String[] fromColumns = new String[] {People.NUMBER, People.NAME}; int[] toLayoutIDs = new int[] { R.id.nameTextView, R.id.numberTextView}; SimpleCursorAdapter myAdapter; myAdapter = new SimpleCursorAdapter(this, R.layout.simplecursorlayout, myCursor, fromColumns, toLayoutIDs); myListView.setAdapter(myAdapter);
Слайд 23Лекция 4, слайд 22
String uriString = "content://contacts/people/"; Cursor myCursor = managedQuery(Uri.parse(uriString), null, null, null); String[] fromColumns = new String[] {People.NUMBER, People.NAME}; int[] toLayoutIDs = new int[] { R.id.nameTextView, R.id.numberTextView}; SimpleCursorAdapter myAdapter; myAdapter = new SimpleCursorAdapter(this, R.layout.simplecursorlayout, myCursor, fromColumns, toLayoutIDs); myListView.setAdapter(myAdapter);
Слайд 24Internet resources Лекция 4, слайд 23
String myFeed = getString(R.string.my_feed); try { URL url = new URL(myFeed); URLConnection connection = url.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection)connection; int responseCode = httpConnection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { InputStream in = httpConnection.getInputStream(); [ ... Process the input stream as required ... ] } } catch (MalformedURLException e) { } catch (IOException e) { }
Слайд 25Лекция 4, слайд 24 Диалоговые окна
Класс Dialog и его производные Специальные диалоговые окна: AlertDialog CharacterPickerDialog DatePickerDialog TimePickerDialog ProgressDialog Activity в модальном режиме
Слайд 26Управление диалогами
Лекция 4, слайд 25
static final private int TIME_DIALOG = 1; @Override public Dialog onCreateDialog(int id) { switch(id) { case (TIME_DIALOG) : AlertDialog.Builder timeDialog = new AlertDialog.Builder(this); timeDialog.setTitle("The Current Time Is..."); timeDialog.setMessage("Now"); return timeDialog.create(); } return null; } @Override public void onPrepareDialog(int id, Dialog dialog) { switch(id) { case (TIME_DIALOG) : SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); Date currentTime = new Date(java.lang.System.currentTimeMillis()); String dateString = sdf.format(currentTime); AlertDialog timeDialog = (AlertDialog)dialog; timeDialog.setMessage(dateString); break; } }
Слайд 27Просмотр данных о землетрясениях (демо)
Лекция 4, слайд 26
Слайд 28Работа с файлами Лекция 4, слайд 27
String FILE_NAME = "tempfile.tmp"; // Create a new output file stream that’s private to this application. FileOutputStream fos = openFileOutput(FILE_NAME, Context.MODE_PRIVATE); // Create a new file input stream. FileInputStream fis = openFileInput(FILE_NAME);
Типы режимов доступа к файлам MODE_APPEND MODE_PRIVATE MODE_WORLD_READABLE MODE_WORLD_WRITEABLE
Resources myResources = getResources(); InputStream myFile = myResources.openRawResource(R.raw.myfileName)
Доступ к файлам из ресурсов:
Другие операции: deleteFile, fileList (также см. java.io.File)
Слайд 29Настройки Лекция 4, слайд 28
Общие (SharedPreferences) Состояние приложения/активности (Bundle)
Поддерживаемые типы: boolean string float long integer
Слайд 30Общие настройки Лекция 4, слайд 29
// Get the stored preferences int mode = Activity.MODE_PRIVATE; final String MY_PREFS = "MY_PREFS"; SharedPreferences mySharedPreferences = getSharedPreferences(MY_PREFS, mode); // Retrieve the saved values. boolean isTrue = mySharedPreferences.getBoolean("isTrue", false); float lastFloat = mySharedPreferences.getFloat("lastFloat", 0f); int wholeNumber = mySharedPreferences.getInt("wholeNumber", 1); long aNumber = mySharedPreferences.getLong("aNumber", 0); String stringPreference = mySharedPreferences.getString("textEntryValue", ""); ... SharedPreferences.Editor editor = mySharedPreferences.edit(); // Store new primitive types in the shared preferences object. editor.putBoolean("isTrue", true); editor.putFloat("lastFloat", 1f); editor.putInt("wholeNumber", 2); editor.putLong("aNumber", 3l); editor.putString("textEntryValue", "Not Empty"); // Commit the changes. editor.commit();
Слайд 31PreferenceScreen Лекция 4, слайд 30
Слайд 32Работа с PreferenceActivity
Лекция 4, слайд 31
public class MySettings extends PreferenceActivity { SharedPreferences prefs; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); prefs = this.getSharedPreferences("MySettings", Activity.MODE_PRIVATE); }
...
Intent i = new intent(this, MySettings.class); startActivityForResult(i, SHOW_PREFERENCES);
Слайд 33Работа с общими настройками
Лекция 4, слайд 32
Context context = getApplicationContext(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); // TODO: use get methods
public class MyActivity extends Activity implements OnSharedPreferenceChangeListener { @Override public void onCreate(Bundle SavedInstanceState) { // Register this OnSharedPreferenceChangeListener Context context = getApplicationContext(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); prefs.registerOnSharedPreferenceChangeListener(this); } public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { // TODO Check the shared preference and key parameters and change UI or // behavior as appropriate. } }
Слайд 34Пример PreferenceActivity Лекция 4, слайд 33
Слайд 35На следующей лекции
Лекция 4, слайд 34
SQLite и источники данных Геокодирование & Карты Геолокационные сервисы
Слайд 36Задание «Записная книжка»
Лекция 4, слайд 35
Разработать приложение с графическим пользовательским интерфейсом, поддерживающее cоздание, редактирование, удаление, поиск заметок. Два варианта хранения заметок: А) в базе SQLite; Б) с использованием файловой системы.
Срок выполнения: 2 недели
Слайд 37Лекция 4, слайд 36