Android studio пин код

MVP в Android на примере экрана с пин кодом

Недавно в одном проекте мне понадобилось реализовать классическую схему с пин кодом: при первом запуске приложение просит создать пин код, а при последующих запусках оно просит его ввести и проверяет, что введенный пин правильный. Также есть возможность в настройках сменить пин на новый.

Таким образом, экран пин кода должен поддерживать три режима: создание, проверка и смена пин кода. Реализовав этот экран, я понял, что получился неплохой пример для демонстрации принципов MVP (Model-View-Presenter).

Если вы пока не очень хорошо представляете себе, что такое MVP, то посмотрите сначала этот пост. Он проще и понятнее.

Пример

Напомню, что у экрана с пин кодом может быть три режима.

Соответственно, на экране может быть одно, два или три поля ввода. Каждое поле содержит подпись (label) и имеет ограничение по длине в 4 символа.

При реализации этого экрана я решил использовать одно View и три презентера — отдельный презентер для каждого из трех режимов.

Можно, конечно, было все три режима реализовать в одном презентере, но зачем? Это будет сложно и запутанно. А раз уж я использую MVP, я могу просто разделить логику на три презентера и использовать их для работы с одним экраном.

Пример я оформил отдельным проектом и залил на GitHub. В проекте используются ButterKnife, Dagger 2 и RxJava. Я не буду подробно останавливаться на объяснении принципов их работы. Если вы еще не знакомы с этими инструментами, то я вам рекомендую изучить их. Они сейчас востребованы и активно используются.

Основные компоненты приложения.

Класс по работе с префами. Используется для чтения/записи пин кода.

Здесь описаны Enum для режимов экрана и текстовый ключ, для помещения данных в intent.

Это техническое Activity, без layout. С него стартует приложение.

Из префов читается текущий пин код. Если он задан, то запускается PinCodeActivity в режиме проверки пин кода, иначе — в режиме создания пин кода. И на этом работа Activity завершается.
Если у вас есть Activity с заставкой, можно эту логику поместить в него.

Это основной экран приложения.

Содержит кнопки для сброса и изменения пина.

Рассмотрим классы/интерфейсы, принимающие непосредственное участие в MVP.

Базовые классы и интерфейсы MVP

Интерфейс, который будет реализован всеми View, которые будут работать по MVP. В нашем случае интерфейс пустой.

Интерфейс, который будет реализован всеми презентерами, которые будут работать по MVP. Он содержит несколько методов, которые будут вызываться из View.

attachView(V mvpView) — метод для передачи View презентеру. Т.е. View вызовет его и передаст туда себя.

viewIsReady — сигнал презентеру о том, что View готово к работе. Презентер может начинать, например, загружать данные.

detachView — презентер должен отпустить View. Вызывается, например, при повороте экрана, когда уничтожается старый экземпляр Activity, или при закрытии Activity. Презентер должен обнулить ссылку на Activity.

destroy — сигнал презентеру о том, что View завершает свою работу и будет закрыто. Т.е. Здесь необходимо отписываться от всех моделей, завершать все текущие операции и т.п.

Небольшой базовый класс, который будет наследоваться всеми презентерами. В нем реализованы общие методы по работе с View. В этом примере он достаточно прост. Но обычно здесь располагаются также механизмы для сбора RxJava подписок, которые завершаются в методе destroy.

Переходим к реализации MVP на примере экрана для работы с пин кодами.

Contract

Плюс MVP в том, что вы легко можете заменить View или Presenter, и вся схема продолжит работать. Чтобы иметь возможность легко заменить один класс другим, необходимо использовать интерфейсы. Вы создаете интерфейс для View и интерфейс для Presenter, и далее в работе используете именно их. В этом случае, вы всегда сможете подменить одну реализацию презентера (или экрана) другой без каких-либо последствий.

Читайте также:  Корневая папка sd карты андроид

В этом файле описаны интерфейсы для View и Presenter для экрана, который будет работать с пин кодом.

Полей для ввода пин кода будет всего три, поэтому названия методов содержат порядковые числительные: first, second, third.

В интерфейсе View описаны методы в основном для работы с полями ввода: отображение, получение текста, установка фокуса, очистка. А также методы для показа сообщений пользователю, запуска следующего экрана и закрытия экрана.

В интерфейсе презентера описаны методы, которые будут вызываться, когда соответствующее поле будет полностью заполнено (когда пользователь ввел 4 символа).

Класс PinCodeActivity.java реализует интерфейс PinCodeContract.View, т.к. это Activity играет роль View в MVP схеме.

Рассмотрим некоторые фрагменты кода.

Методы запуска Activity:

Общий метод startActivity создает Intent для запуска PinCodeActivity и помещает в интент параметр — режим запуска. Методы createPinCode, checkPinCode, changePinCode используют метод startActivity и соответствующий режим.

В onCreate вытаскиваем режим PinCodeMode из интента и используем его для создания презентера.

Для создания презентера тут используется даггер. И код, который он выполняет, выглядит так:

В зависимости от режима, мы создаем один из трех презентеров. Это три разных класса, но все они реализуют интерфейс PinCodeContract.Presenter.

А в PinCodeActivity даггер помещает созданный презентер в поле:

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

Далее в onCreate мы даем созданному презентеру View (оно же Activity) и сообщаем, что все готово к работе.

Методом detachView мы просим presenter освободить View. А если Activity закрывается насовсем, то выполняем destroy для презентера и освобождаем компонент даггера.

Далее идет реализация методов интерфейса PinCodeContract.View

Ставим label текст в TextView и показываем его и само поле. Далее с помощью RxJava вешаем обработчика для поля ввода, который будет срабатывать при вводе символов в поле. Добавляем фильтр, чтобы обработчик срабатывал только, когда поле содержит 4 символа (т.е. полностью заполнено). И указываем, что обработчику необходимо будет вызвать метод presenter.onTextFirst().

Тем самым мы сообщим презентеру, что пользователь ввел 4 символа в поле и надо что-то делать дальше.

Методы showSecond и showThird полностью аналогичны.

Методы getTextFirst, getTextSecond и getTextThird просто возвращают содержимое полей ввода.

Методы focusFirst, focusSecond, focusThird ставят фокус в поля ввода.

clearAll очищает все поля ввода.

showMessage показывает Toast.

next запускает MainActivity.

close закрывает Activity.

Presenter

Давайте смотреть код презентеров и там станет понятно, зачем нужны все эти методы в Activity.

Создание пин кода

Обратите внимание, что класс презентера наследует PresenterBase (чтобы иметь базовые методы работы с View) и реализует PinCodeContract.Presenter (чтобы соответствовать требованиям контракта).

Этот презентер используется, когда мы открываем экран в режиме создания пин кода

Нам нужно отобразить два поля из трех. Это мы и делаем в методе viewIsReady. Для доступа к View используем getView из базового класса презентера.

Метод onTextFirst будет вызван из View, когда первое поле будет заполнено. В этом случае мы переводим фокус на второе поле методом focusSecond.

Метод onTextSecond будет вызван из View, когда второе поле будет заполнено. В этом случае мы сверяем значения из первого и второго полей.

Если значения равны, то мы
— сохраняем новый пин
— показываем сообщение, что пин успешно создан
— открываем следующий экран
— закрываем текущий экран

Если же значения не равны
— показываем сообщение о том, что пины не совпадают
— очищаем все поля
— ставим фокус в первое поле

В методе onTextThird ничего не делаем. Он не будет вызван, т.к. мы не отображали третье поле ввода.

Проверка пин кода

Он используется при режиме проверки пин кода

В этом случае нам необходимо показать всего одно поле, что мы и делаем в viewIsReady.

Когда пользователь введет пин код в первое поле, будет вызван метод onTextFirst. В нем проверяем, что введенное значение совпадает с пин кодом который хранится в префах.

Если совпадает, то:
— открываем следующий экран
— закрываем текущий экран

Читайте также:  Какие часы лучше всего для андроид

Иначе:
— показываем сообщение об ошибке
— очищаем все поля

Методы onTextSecond и onTextThird остаются пустыми. Они не будут вызваны из View, т.к. мы не отображали второе и третье поля.

Изменение пин кода

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

Здесь мы отображаем все три поля в методе viewIsReady.

В методах onTextFirst и onTextSecond просто переводим фокус на следующее поле.

В методе onTextThird сначала проверяем, что старый пин введен верно в первое поле. Если пин не совпадает с текущим сохраненным, то
— показываем сообщение об ошибке
— очищаем все поля
— ставим фокус на первое поле
— заканчиваем работу метода

Если же старый пин был указан правильно, то проверяем, что во втором и третьем поле было введено одинаковое значение нового пина.

Если значения совпадают, то
— сохраняем новый пин
— показываем сообщение об успехе
— закрываем экран

Иначе
— показываем сообщение об ошибке
— очищаем все поля
— ставим курсор на первое поле

Если забыть про MVP и поместить всю логику View и трех презентеров в одно Activity, то оно получится достаточно сложным и перегруженным. Вариант с MVP кажется мне более предпочтительным.

Пример был сделан максимально легким и, возможно, не выполняет все необходимые проверки. Основная цель была — показать, как взаимодействуют View и Presenter в MVP.

Также я хотел бы заметить, что в данном примере, при поворотах экрана ваш презентер будет продолжать существовать, и не будет пересоздаваться. Это может быть удобно, когда вы выполняете какие-то долгие операции, например — запросы на сервер. Реализовано это с помощью Dagger 2, но можно и любым другим способом.

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

PFLockScreen Library for Android

I created a PFLockScreen library — Lock screen library you can use in your application. It can be applications that encrypt some sensitive data like notes, pictures, etc or bank applications. For example, medical applications in Japan required additional security level as well.

If you would like to use it but have some issues or ideas fill free to create an issue on GitHub.

How the library works. We have typical UI to input pin code. That also allowed use fingerprint instead of a pin code.

Because AndroidKeystore doesn’t support custom pin for authorization I decided to have to parallel way to unlock app.

How library works inside

Using pin code.

If you don’t know how keysore and fingerprint API in Android works you can read about in my previous article

A user creates pin code. Using keystore and cipher object we encrypt the code. In a key generation, we set required authentication parameter to false. So we won’t need to use a fingerprint to unlock application (because in this case, we need to input pin code and use fingerprint at the same time).

Library encrypts pin code and returns an encrypted string.

For authorization user inputs pin code. The library compares inputted code with the encrypted one and if they match application is unlocked.

To use fingerprint we just will use FingerprintManager without a keystore. Because in our case password and fingerprint methods are separated we don’t actually need to encrypt/decrypt anything. So we just use Fingerprint API to confirm user’s identity. And if it’s confirmed the library returns unlocked state.

So the library can decrypt pin code without user’s fingerprint because we want to have two ways to unlock application

If you don’t need the UI part. You can use only encryption/decryption part of the library.

Читайте также:  Автодозвон для андроид установить

Источник

Tutorial: PIN input view in Android

Today’s post will be about PIN-like view in Android. I’m sure that many Android developers would like to have it by default, me included. And so I wanted to show you how I handled the problem caused by lack of such view. But first, how should it look like? Well, it should like an input field where every character has it’s own box and while typing, characters should automatically populate those boxes. Sounds pretty easy, isn’t it? But later, when you think about all of the aspects, you will realize it’s not that simple at all…

First, I wanted to mention that this particular example is for text passwords (or text pin). The code for just numerical PIN view would be much easier. But it wasn’t the case with the app I was writing and I definitely needed the default keyboard. Because I could change my soft keyboard from text to numerical at any point of typing, I couldn’t have a collection of EditTexts because switching from one to another would have changed a keyboard either to text or numerical and I didn’t want that.

So, I had to think of something more flexible. And what I’ve done is created a collection of EditTexts AND another one which user wouldn’t normally see but which will actually take a focus and basically do the job for us.

OK, lets see some code!

Here’s the main.xml layout:

What you can see here is just a LinearLayout with some text label, five edit texts and one hidden below.
It is not even hidden, just a transparent 1dp width and height EditText. Edit texts for pin have its own style.

styles.xml

We want our characters aligned to center, cursor won’t be visible as we won’t edit one character separately but the whole PIN view at once. Max length each of those PIN inputs should be 1. minEms with value of 2 ensures the width of input won’t shrink or expand depending on character width.

Strings for this example project:

strings.xml

dimens.xml

And AndroidManifest.xml:

This project wasn’t tested on Android 2.x.x, so I just put a min SDK version to 14 (which is Android 4.0). You can try to run it on lower versions.

I have also used Theme.Holo.Light. It could have been any other theme, it’s just that I need EditText focusable and default backgrounds and they were adjusted for the Light theme. Why bother about those backgrounds? Because we will set it programmatically depending on focus and on characters typed in our PIN view. You will see when you will actually run this project 🙂 Just remeber, you need to have some gfx files 😉

OK, so the most interesting part is the code!

Wow, a lot of code you might say! And yet, there’s is just enough for correct functioning 😉

We have init() method in which our edit texts are initialized, then we have onFocusChange() method. If user touches any of our pin edit texts, we should catch the focus of our hidden EditText and show soft keyboard. onKey() method checks if DEL key was pressed, then checks how many characters were typed and based on that sets our edit texts to empty. onTextChanged() method sets correct background based on text length and also sets characters we typed.

The last interesting thing here is MainLayout which is just a LinearLayout with overridden onMeasure() method. Why do you need this? Because when the keyboard is shown, we need to highlight the first PIN box (if it is not empty). This is just for a better UX, nothing more I guess…

And that’s all! A lot of code but the idea is quite clear. We have one EditText, which catches the focus and characters we type, everything else is just a programmatic trick 😉

Источник

Оцените статью