Во второй части этого урока мы рассмотрим процесс входа в Google и получения уникального идентификатора. Мы попытаемся написать общий код, который позже сможем использовать для процесса входа в Facebook. Но сначала давайте рассмотрим, что на самом деле означает «вход в систему»…
Когда вы обрабатываете свой собственный список пользователей и пользователь регистрируется в процессе регистрации, вы обычно можете спросить этого пользователя о чем угодно. Тем не менее, когда пользователь входит в систему через Facebook, Google или любую другую службу, вы получаете доступ к этой службе для получения сведений о пользователе … Это до боли понятно с такими службами, которые по умолчанию не предоставляют даже адрес электронной почты при входе в систему. Иногда он доступен в Facebook, но только для пользователей, которые не хотят его скрывать.
Хуже того, одной из основных причин использования такого сервиса является доступ к контактам … Однако Facebook больше не позволяет разработчикам получать доступ к вашим друзьям на Facebook. Разработчик приложения Facebook может получить доступ только к списку друзей, у которых установлено приложение, и для этого нам нужно будет «пригласить» людей использовать / установить приложение.
Начало работы — Конфигурация
Почти все, что обсуждается в этом блоге, освещено здесь . Тем не менее, это довольно общий пост, поэтому в этом уроке я постараюсь быть более конкретным.
Начните с перехода на консоль разработчика Google: https://console.developers.google.com/
Создайте новое приложение, нажав кнопку «Создать»:
Просто введите название приложения, например, в этом случае его SocialChat и нажмите «Создать»:
Теперь можно выбрать раздел API, где вы должны увидеть страницу нового проекта:
В этом проекте вы должны нажать Google+ API в разделе «Социальные сети»:
В разделе учетных данных создайте новый идентификатор клиента, сначала нам нужно создать его для веб-приложения. Это будет использоваться симулятором, чтобы мы могли отлаживать приложение на рабочем столе. Он также будет использоваться портами для JavaScript, рабочего стола и эффективно для всего, кроме iOS и Android:
Экран концентрации используется, чтобы запрашивать у пользователей разрешения, обычно вы должны правильно его заполнять для приложения «реального мира», но в этом случае мы оставили его в основном пустым для простоты:
Теперь нам нужно добавить привязки нативных приложений для Android / iOS практически так же, как мы делали веб-приложение:
Чтобы создать собственное приложение для Android, убедитесь, что вы правильно настроили хранилище ключей для своего приложения. Если у вас нет сертификата Android, вы можете воспользоваться нашим визуальным мастером или использовать командную строку, указанную в нашем руководстве по подписыванию .
Теперь, когда у вас есть сертификат, вам нужно два значения для вашего приложения, первое — это имя пакета, которое должно совпадать с именем пакета вашего основного класса (с методами start, stop). Он должен быть указан в разделе свойств Codename One. Убедитесь, что вы используете абсолютно уникальное имя и используете свой собственный домен, не используйте префикс com.codename1 или что-нибудь подобное …
Вам также нужно значение SHA1 для вашего сертификата, это объясняется Google здесь: https://developers.google.com/+/mobile/android/getting-started
Эффективно вам нужно запустить эту командную строку:
1
|
$ keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v |
Это запросит пароль, а затем напечатает несколько строк данных, одна из которых должна начинаться с SHA1
то есть значения, которое вам понадобится для приложения Android.
Приложение iOS должно иметь то же имя пакета, что и идентификатор пакета. Ему также нужен идентификатор appstore, который вы можете получить из itunes, он должен отображаться в качестве префикса для профиля обеспечения ваших приложений. Если ваше приложение правильно настроено, например, с помощью мастера сертификатов Codename One, вы должны увидеть его в свойствах проекта в разделе Codename One → iOS.
После того, как все будет завершено, вы должны увидеть нечто похожее на это:
Конфигурация проекта
Теперь нам нужно установить несколько важных советов по сборке в проекте, чтобы он работал правильно. Чтобы установить подсказки для сборки, просто щелкните правой кнопкой мыши проект, выберите свойства проекта и в разделе Codename One выберите вторую вкладку. Добавьте эти записи в таблицу:
1
2
|
android.includeGPlayServices= true ios.gplus.clientId=your ios client ID |
Код
Так что теперь, когда все это на месте, мы бы хотели, чтобы оно работало с нашей сборкой …
Сначала, чтобы сделать код более общим, мы определим этот интерфейс, который мы можем реализовать как для Facebook, так и для Google, таким образом обобщая код входа в систему:
1
2
3
4
5
6
|
static interface UserData { public String getName(); public String getId(); public String getImage(); public void fetchData(String token, Runnable callback); } |
Способ работы этого интерфейса заключается в том, что мы вызываем fetchData после завершения процесса входа в систему, чтобы получить данные из Google / Facebook, а затем предоставить нам имя / идентификатор и изображение. Обратите внимание, что, поскольку Facebook не всегда предоставляет электронную почту, мы не можем надежно использовать ее в качестве уникального идентификатора для пользователя …
Также обратите внимание, что fetchData является асинхронным и будет вызывать обратный вызов после его завершения. Мы могли бы сделать это синхронно и использовать invokeAndBlock
.
Код, который привязывает это к кнопке, выглядит следующим образом:
1
2
3
4
5
6
7
|
loginWithGoogle.addActionListener((e) -> { Login gc = GoogleConnect.getInstance(); gc.setClientId( "1013232201263-lf4aib14r7g6mln58v1e36ibhktd79db.apps.googleusercontent.com" ); gc.setClientSecret( "-------------------" ); doLogin(gc, new GoogleData()); }); |
Обратите внимание, что мы спрятали клиент в GoogleData
и использовали класс GoogleData
который фактически является реализацией интерфейса UserData
. Класс GoogleData
выглядит следующим образом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
static class GoogleData extends ConnectionRequest implements UserData { private Runnable callback; private Map<String, Object> parsedData; @Override public String getName() { return (String) parsedData.get( "displayName" ); } @Override public String getId() { java.util.List<Map<String, String>> emailList = (java.util.List<Map<String, String>>) parsedData.get( "emails" ); return emailList.get( 0 ).get( "value" ).toLowerCase(); } @Override public String getImage() { Map<String, Object> imageMeta = ((Map<String, Object>) parsedData.get( "image" )); return (String)imageMeta.get( "url" ); } @Override public void fetchData(String token, Runnable callback) { this .callback = callback; addRequestHeader( "Authorization" , "Bearer " + token); setPost( false ); NetworkManager.getInstance().addToQueue( this ); } @Override protected void readResponse(InputStream input) throws IOException { JSONParser parser = new JSONParser(); parsedData = parser.parseJSON( new InputStreamReader(input, "UTF-8" )); } @Override protected void postResponse() { callback.run(); } } |
Как правило, в классе не так уж много. fetchData
использует запрос на подключение для подключения к URL-адресу в Google+ API, который возвращает сведения о пользователе, когда токен установлен. Эти детали возвращаются в виде строки JSON, которую мы затем анализируем и устанавливаем для правильных переменных.
Класс JSONParser
возвращает данные JSON в виде дерева списков и карт, через которое мы можем пройти, чтобы извлечь нужные нам данные.
Одно значение, которое может быть непонятным для случайного наблюдателя, — это token
, это строка, содержащая «ключ» к учетной записи пользователя. Facebook / Google и т. Д. Хранят пароли своих пользователей в своей базе данных (фактически, даже если они не знают паролей), поэтому, чтобы доказать, что мы получили разрешение пользователя на доступ к его данным, мы получаем уникальный токен, который выглядит следующим образом: длинная строка тарабарщины, и мы можем использовать это при доступе к их соответствующим API, таким образом проверяя себя. Это очень распространенная практика … Однако токены иногда теряют силу, и поэтому вам может потребоваться «обновить» свой токен, выполнив вход снова, как показано в следующем блоке кода.
Теперь мы можем перейти к фактическому процессу входа в систему, который является общим для входа в Google и Facebook благодаря классу выше и встроенным абстракциям в Codename One:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
private String fullName; private String uniqueId; private String imageURL; void doLogin(Login lg, UserData data) { if (lg.isUserLoggedIn()) { showContactsForm(); return ; } // if the user already logged in previously and we have a token String t = Preferences.get( "token" , (String) null ); if (t != null ) { // we check the expiration of the token which we previously stored as System time long tokenExpires = Preferences.get( "tokenExpires" , ( long )- 1 ); if (tokenExpires < 0 || tokenExpires > System.currentTimeMillis()) { // we are still logged in showContactsForm(); return ; } } lg.setCallback( new LoginCallback() { @Override public void loginFailed(String errorMessage) { Dialog.show( "Error Logging In" , "There was an error logging in: " + errorMessage, "OK" , null ); } @Override public void loginSuccessful() { // when login is successful we fetch the full data data.fetchData(lg.getAccessToken().getToken(), ()-> { // we store the values of result into local variables uniqueId = data.getId(); fullName = data.getName(); imageURL = data.getImage(); // we then store the data into local cached storage so they will be around when we run the app next time Preferences.set( "fullName" , fullName); Preferences.set( "uniqueId" , uniqueId); Preferences.set( "imageURL" , imageURL); Preferences.set( "token" , lg.getAccessToken().getToken()); // token expiration is in seconds from the current time, we convert it to a System.currentTimeMillis value so we can // reference it in the future to check expiration Preferences.set( "tokenExpires" , tokenExpirationInMillis(lg.getAccessToken())); showContactsForm(); }); } }); lg.doLogin(); } |
Теперь это большой блок кода, но на самом деле это не так уж и много. Все, что он делает — это делегирует интерфейс UserData
и проверяет токен. Он также хранит возвращенные данные и показывает следующую форму (которую мы не будем сейчас рассматривать).
Последний фрагмент кода для этого раздела — это небольшой служебный метод, который мы использовали для определения истечения срока действия токена:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
/** * token expiration is in seconds from the current time, we convert it to a System.currentTimeMillis value so we can * reference it in the future to check expiration */ long tokenExpirationInMillis(AccessToken token) { String expires = token.getExpires(); if (expires != null && expires.length() > 0 ) { try { // when it will expire in seconds long l = Long.parseLong(expires) * 1000 ; return System.currentTimeMillis() + l; } catch (NumberFormatException err) { // ignore invalid input } } return - 1 ; } |
Это эффективно позволяет нам определить, истек ли токен в будущем выполнении приложения.
Другие сообщения в этой серии
Это непрерывная серия постов, включающая следующие части:
- Часть 1 — Начальный интерфейс
- Часть 2 — Войти через Google
- Часть 3 — Войти через Facebook (скоро)
Ссылка: | Создание приложения для чата с кодовым названием One Part 2 от нашего партнера JCG Шая Альмога из блога Codename One . |