Login Activity in Android Studio – Kotlin & Java – Handy Opinion

Import Material Design Library In Android Studio

In this article, we are going to TextInputLayout from Google Material Design for which we need to import Google Material design library. To import that add the following material design dependency in your app level build.gradle file.

implementation 'com.google.android.material:material:1.1.0'

Login Activity UI XML Design

Add the the following XML code in your Login Activity’s XML File.

Login activity java code (for java project)

If you are developing your Activity in JAVA then add the following code in your LoginActivity.java file.

Login activity kotlin code (for kotlin project)

If you are developing your Activity in Kotlin then add the following code in your LoginActivity.kt file. otherwise for JAVA code please scroll down.

Spinner (выпадающий список)

Для реализации выпадающего списка (например, отфильтруем продукцию по типу) нужно в разметку добавить элемент Spinner

Создать класс ProductType (не data, а обычный) и переопределить в нём метод toString, чтобы в выпадающем списке показывало то что нам нужно

В классе основного окна (в том, где вы будете использовать выпадающий список) создайте список для хранения типов продукции, получите указатель на элемент и назначте ему адаптер:

Вторым параметром передаётся layout файл, в котором должен быть элемент TextView с id=”@android:id/text1″

Добавление альбомной ориентации

В окне разметки (acticity_main.xml) перейдите в режим “design” и кликните кнопку “Orientation…” выбираем “Create Landscape Variation”

Система автоматически создаст Layout с альбомной ориентацией.

Учитывайте, что конструктор общий для всех ориентаций – при обращении к несуществующему объекту произойдет исключение.

Чтобы для разных ориентаций не рисовать одинаковую разметку (допустим список валют выводится в обеих ориентациях) можно вынести повторяющиеся куски разметки в отдельные файлы разметки (layout), а в нужные места вставить ссылку на них с помощью тега include

В паре с include используется тег merge. Если выделяемый кусок разметки содержит несколько отдельных элементов, то по стандартам XML мы должны завернуть их в один родительский. Как раз тег merge и можно использовать в таком случае. Он игнорируется при разборе разметки и ни как на неё не влияет.

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

Запрос auth token

Теперь вы готовы запрашивать токен авторизации. Это многоступенчатый процесс.

Для получения токена авторизации необходимо сначала запросить права на использование ACCOUNT_MANAGER в манифесте. Не забываем про разрешение на интернет.

Похожее:  Интерзет личный кабинет

Имея необходимые полномочия, вы можете вызвать AccountManager.getAuthToken() для получения токена. Большинство методов AccountManager – асинхронные. Вам придётся реализовать её в виде серии обратных вызовов, например:


AccountManager am = AccountManager.get(this);
Bundle options = new Bundle();
 
am.getAuthToken(
    myAccount_,                     // Account retrieved using getAccountsByType()
    "Manage your tasks",            // Auth scope
    options,                        // Authenticator-specific options
    this,                           // Your activity
    new OnTokenAcquired(),          // Callback called when a token is successfully acquired
    new Handler(new OnError()));    // Callback called if an error occurs

В этом примере класс OnTokenAcquired расширяет AccountManagerCallback. AccountManager вызывает run() в OnTokenAcquired с AccountManagerFuture, содержащим Bundle. Если вызов успешен, то токен будет внутри Bundle.

Вы можете получить токен из Bundle:


private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
    @Override
    public void run(AccountManagerFuture<Bundle> result) {
        // Get the result of the operation from the AccountManagerFuture.
        Bundle bundle = result.getResult();
 
        // The token is a named value in the bundle. The name of the value
        // is stored in the constant AccountManager.KEY_AUTHTOKEN.
        token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
        ...
    }
}

Если все пойдёт хорошо, то Bundle будет содержать допустимый токен в ключе KEY_AUTHTOKEN. Но не всегда все идёт так как запланированно.

Ваш первый запрос токена авторизации может завершиться неудачей по нескольким причинам:

  • Ошибка в устройстве или сети вызвала сбой AccountManager.
  • Пользователь решил не предоставлять вашему приложению доступ к аккаунту.
  • Сохраненных полномочий аккаунта не хватает для получения доступа к аккаунту.
  • Кэшированный токен авторизации истек.

Приложения могут обрабатывать первые два случая, показывая сообщение об ошибке пользователю. Если сеть не работает или пользователь решил не предоставлять доступ, то ваше приложение ничего не может с этим поделать. Последние два случая немного сложнее, потому что хорошо оптимизированные приложения должны обрабатывать эти неудачи автоматически.

Третий случай неудачи, имеющий недостаточные полномочия, передается через Bundle, который вы получаете в вашем AccountManagerCallback (OnTokenAcquired из предыдущего примера). Если Bundle включает Intent в ключе KEY_INTENT, то аутентификатор говорит вам, что ему необходимо прямое взаимодействие с пользователем, прежде чем он может дать вам действительный токен.

У аутентификатора может быть много причин для возврата Intent. Это может быть первый вход пользователя в эту учетную запись. Возможно время учетной записи пользователя истекло и требуется повторный вход в систему или сохраненные полномочия неверны.

Может быть аккаунт требует двухфакторной аутентификации либо требуется включение камеры для сканирования сетчатки. В действительности причина не имеет значения. Если вы хотите действительный токен, вы должны обратиться к Intent, чтобы получить его.


private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
    @Override
    public void run(AccountManagerFuture<Bundle> result) {
        ...
        Intent launch = (Intent) result.get(AccountManager.KEY_INTENT);
        if (launch != null) {
            startActivityForResult(launch, 0);
            return;
        }
    }
}

Обратите внимание, что пример использует startActivityForResult(), и вы можете перехватить результат Intent в методе onActivityResult() в вашей активности. Если вы не станете перехватывать результат ответа Intent аутентификатора, невозможно будет определить прошёл ли пользователь проверку подлинности или нет.

Похожее:  Управляющая компания «Наш Дом», Иркутск — адрес и телефон, официальный сайт, отзывы жителей

Если результат RESULT_OK, то аутентификатор обновил сохранённые полномочия, чтобы они были достаточны для доступа который вы запросили, далее вы должны вызвать AccountManager.getAuthToken() снова и запросить новый токен аутентификации.

Последний случай, когда токен истёк, на самом деле не ошибка AccountManager. Единственный способ выяснить действительно ли токен истек – это связаться с сервером, что было бы расточительным и дорогим со стороны AccountManager постоянно выходить в интернет и проверять состояние всех своих токенов.

Первичная настройка приложения

  1. Создаем новый проект и сразу пытаемся его запустить.

    Если при сборке проекта выходит подобная ошибка, то нужно “понизить” версию зависимости, на которую ругается сборщик. Вообще эта ошибка означает, что какой-то пакет (в нашем случае androidx.appcompat:appcompat:1.4.0) требует более новой SDK, чем установлена. Но в AVD пока нет версий новее 30.

    Открываем build.graddle (Module...), находим нужный пакет в зависимостях (секция dependencies) и уменьшаем минорную версию пакета. Например, если была версия 1.4.0, то правим на 1.3.0.

  2. Устанавливаем иконку и название проекта.

Раньше как-то не пришло в голову, но часто графические ресурсы таскают сразу в приложении. По крайней мере в том задании про банк иконки валют и стран прилагались к заданию.

Это значит, что при получении, например, информации о валюте мы должны иконку тащить не из интернета, а из ресурсов.

Простая загрузка ресурса с ИЗВЕСТНЫМ id не сложная:

Но при получении данных из интернета мы имеем НАЗВАНИЕ ресурса (файла), а не его id в приложении. Для поиска id по имени есть отдельный метод:

Подключение к онлайн-сервисам

Пример ниже показывает, как подключиться к серверу Google. Так как Google использует стандарт протокола OAuth2 для проверки подлинности запросов, методы, обсуждаемые здесь широко применимы. Имейте в виду, что каждый сервер отличается. Вам может понадобиться внести небольшие изменения в этот пример для учета вашей конкретной ситуации.

Проект “база”. авторизация на сервере (basic auth, token). post-запросы. api.

Содержание

Регулярные выражения

Возможно будет задание сделать форму регистрации. В этом случае обычно нужно сделать проверку введенных данных. Например, электронной почты

Похожее:  Какие задачи решают IAM системы? / Хабр

Сохранение данных при работе приложения

Специфика жизненного цикла activity такова, что при каждом чихе (смена ориентации, языка и т.п.) окно пересоздаётся То есть все наши данные теряются.

Гугл рекомендует нам пользоваться событиями onSaveInstanceState и onRestoreInstanceState которые вызываются, соответственно, при удалении activity и при восстановлении.

В параметрах этих функций передаётся объект, в который (и из которого) мы можем сохранить нужные нам данные и потом восстановить.

Но хранить в таком объекте можно только скалярные данные (т.е. базовые типы типа “целое”, “строка” и т.п.). Чтобы сохранить более-менее сложный объект, например, массив продукции, нужно использовать сериализацию/десериализацию.

Есть ещё более модная концепция LiveData – но там даже у меня происходит вывих мозга (это самая правильная концепция и если вы не дай бог станете таки андроид-разработчиками, то разобраться в ней надо).

Но ещё есть простой рабоче-крестьянский вариант с глобальными переменными. Само понятие глобальные переменные противоречит одному из основных постулатов ООП – инкапсуляция, поэтому его не рекомендуется использовать в сколько-нибудь серъезных проектах.

  1. Создайте класс MyApp, который наследуется от класа Application и внутри опишите публичные переменные, которые можно будет использовать во всех activity нашего приложения

  2. В манифесте в тег application добавьте атрибут android:name=”.MyApp”, где .MyApp это имя созданного нами ранее класса

  3. В классах, где нам нужны глобальные переменные создаем переменную, которая будет хранить указатель на MyApp

    В конструкторе класса проинициализируйте её

    И дальше в коде можете её использовать

Фильтрация данных

В нормальных АПИ должна быть предусмотрена фильтрация набора данных на сервере, то есть вам придут только те данные, которые нужны. Но на моём сервере АПИ простенькое (зато универсальное), оно просто отдаёт ту таблицу в базе, которую вы запросите (нам это не страшно, так как таблицы у нас коротенькие).

Из-за этого возникает необходимость отфильтровать отображаемые данные.

Делается это элементарно – создаётся ещё один список соотвествующего типа. Причём основной список имеет смысл вынести в класс приложения (MyApp) и заполнять только при первом обращении к нему (size==0).

У нас задача немного осложняется тем, что связь между продуктами и материалами многие-ко-многим и для выковыривания материалов продукта надо считать ещё таблицу связей ProductMaterial.

Имеет смысл и таблицу связей сразу считать в класс приложения (глобальный), а при переходе в продукт составлять локальный список идентификаторов материалов и затем искать по таблице материалов те, которые входят в этот список (<List>.contains)

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector