Статьи

Создание кода для приложения NativeScript в реальном времени: социальный вход и Firebase

NativeScript — это платформа для создания кроссплатформенных собственных мобильных приложений с использованием XML, CSS и JavaScript. В этой серии мы попробуем некоторые интересные вещи, которые вы можете сделать с помощью приложения NativeScript: геолокация и интеграция с Google Maps, база данных SQLite, интеграция с Firebase и push-уведомления. Попутно мы создаем фитнес-приложение с возможностями реального времени, которое будет использовать каждую из этих функций.

Из этого руководства вы узнаете, как добавить логин Facebook в свое приложение NativeScript. Вы также узнаете, как использовать Firebase для хранения данных о прогулках в фитнес-приложении.

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

не вошел

Когда пользователь входит в систему в первый раз, приложение Facebook запрашивает разрешение на доступ к общему профилю и адресу электронной почты:

Разрешения Facebook

Он также запрашивает список друзей в качестве дополнительного разрешения.

После входа пользователя в систему отображается следующий экран:

Социальная вкладка

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

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

1
tns create fitApp —appid «com.yourname.fitApp»

После этого вам также необходимо установить плагины геолокации, Google Maps и SQLite:

1
2
3
tns plugin add nativescript-geolocation
tns plugin add nativescript-google-maps-sdk
tns plugin add nativescript-sqlite

После установки вам необходимо настроить плагин Google Maps. Вы можете прочитать подробные инструкции о том, как это сделать, прочитав раздел Установка плагина Google Maps в этом предыдущем руководстве .

После этого вам также необходимо установить fecha , библиотеку для форматирования дат:

1
npm install —save fecha

Как только все это будет сделано, вы должны быть готовы следовать этому уроку.

Вы можете запустить проект, выполнив tns run android . Но так как это приложение будет использовать функцию геолокации, я рекомендую вам использовать эмулятор GPS для быстрой настройки и изменения вашего местоположения. О том, как это сделать, вы можете прочитать в разделе « Запуск приложения» в предыдущем руководстве .

Первое, что вам нужно сделать при работе с Firebase, это создать приложение Firebase. Вы можете сделать это, перейдя на console.firebase.com и нажав Добавить проект . Введите название проекта и нажмите кнопку « Создать проект» . Убедитесь, что имя проекта совпадает с именем приложения. В этом случае идентификатор приложения — com.yourname.fitApp поэтому имя приложения — fitApp .

создать проект Firebase

Как только приложение будет создано, вы будете перенаправлены на страницу его панели. Оттуда вы можете нажать Добавить Firebase в ваше приложение для Android , ввести идентификатор приложения и нажать кнопку « Зарегистрировать приложение» .

Добавить Firebase в приложение для Android

Затем загрузите файл google-services.json и скопируйте его в каталог app / App_Resources / android . Этот файл содержит все параметры, необходимые приложению для взаимодействия с Firebase.

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

Поскольку мы собираемся использовать логин на Facebook, нам также нужно создать приложение для Facebook. Перейдите на developers.facebook.com и создайте новое приложение Facebook:

Создать приложение Facebook

Как только приложение будет создано, вы будете перенаправлены на панель инструментов приложения. Оттуда, нажмите на + Добавить продукт меню и выберите Facebook Войти .

В разделе Параметры OAuth- клиента включите все, кроме принудительной повторной проверки подлинности OAuth и входа в систему с устройств . Для действительных URI перенаправления OAuth вы можете получить это, вернувшись на панель инструментов Firebase, щелкнув по аутентификации и включив Facebook в качестве метода аутентификации:

Методы аутентификации

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

После этого нажмите « Сохранить» и скопируйте URI перенаправления OAuth в настройки приложения Facebook. Не забудьте сохранить изменения.

Далее вам также необходимо добавить Android в качестве платформы. Вы можете сделать это, перейдя в Основные настройки и нажав Добавить платформу :

Настройки Android

Установите com.yourname.fitApp в качестве значения для имени пакета Google Play и com.tns.NativeScriptActivity для имени класса.

Обратите внимание, что если вы собираетесь позже выпустить приложение в магазин приложений, вам необходимо сгенерировать хеш для файла .apk приложения и добавить его в поле ключевых хешей . Также обратите внимание, что для тестирования вы сможете использовать только учетную запись разработчика Facebook, которую вы использовали для создания приложения. Если вы хотите добавить другие учетные записи Facebook для тестирования, вы можете добавить их в разделе oles .

Чтобы интегрировать Firebase, нам нужно установить плагин Firebase для NativeScript . Это облегчает реализацию входа в Facebook и функцию базы данных в реальном времени в Firebase:

1
tns plugin add nativescript-plugin-firebase

После завершения установки установщик задаст вам несколько вопросов, касающихся функций Firebase, которые вы будете использовать в приложении. Ответьте да для входа в Facebook и нет для остальных.

Вы должны сообщить приложению, с каким приложением Facebook оно будет общаться. Вы можете сделать это, открыв файл app \ App_Resources \ Android \ AndroidManifest.xml и добавив <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/> под <application> :

01
02
03
04
05
06
07
08
09
10
11
12
<application
        android:name=»com.tns.NativeScriptApplication»
        android:allowBackup=»true»
        android:icon=»@drawable/icon»
        android:label=»@string/app_name»
        android:theme=»@style/AppTheme»>
         
        <!— add this: —>
        <meta-data android:name=»com.facebook.sdk.ApplicationId» android:value=»@string/facebook_app_id»/>
 
        <!— other stuff —>
</application>

Затем создайте файл app \ App_Resources \ Android \ values ​​\ facebooklogin.xml и добавьте следующее:

1
2
3
4
<?xml version=’1.0′ encoding=’utf-8′?>
<resources>
     <string name=»facebook_app_id»>YOUR_FACEBOOK_APP_ID</string>
</resources>

Обязательно замените YOUR_FACEBOOK_APP_ID идентификатором приложения Facebook, которое вы создали ранее.

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

Что касается меня, то основной проблемой, с которой я столкнулся, была проблема совместимости с плагином Google Maps . Поскольку этот плагин также использует Сервисы Google Play, возник конфликт с использованием разных версий. Чтобы решить эту проблему, мне пришлось открыть файл app / App_Resources / Android / app.gradle и указать версию Google Play Services:

1
2
3
4
5
6
7
android {
  //default config here
 
  project.ext {
    googlePlayServicesVersion = «11.0.+»
  }
}

На момент написания этого урока он был на 11.0. Но не забудьте проверить, какая версия установлена ​​для вас через Android SDK.

Как только это будет сделано, вы должны удалить платформу Android ( tns platform remove android ) и попытаться снова запустить приложение ( tns run android ).

Если это не работает для вас, и вы по-прежнему получаете ту же ошибку сборки, возможно, вам придется начать все сначала, создав новый проект. Но на этот раз попробуйте установить плагин Firebase перед плагином Google Maps. Затем выполните необходимые изменения конфигурации, прежде чем пытаться запустить приложение.

Теперь мы готовы добавить код. Сначала мы добавим XML, затем JavaScript и, наконец, код CSS.

Мы будем работать в основном в представлении социальных вкладок. Сначала добавьте разметку для отображения информации о текущем вошедшем в систему пользователе, а также кнопку выхода из системы:

1
2
3
4
5
6
<StackLayout width=»140″ class=»profile p-20″ visibility=»{{ is_loggedin ? ‘visible’ : ‘collapsed’ }}»>
    <Image src=»{{ profile_photo }}» stretch=»aspectFit» />
    <Label text=»{{ user_name }}» textWrap=»true» />
    <Button text=»Logout» tap=»{{ logout }}»
    class=»btn-logout» />
</StackLayout>

Ниже приведена разметка для отображения таблицы лидеров. Это перебирает данные friends_data для отображения имени пользователя, расстояния и шагов, сделанных друзьями пользователя и пользователем.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<StackLayout visibility=»{{ is_loggedin && friends_data ? ‘visible’ : ‘collapsed’ }}»>
    <Label text=»Leaderboard» class=»heading» textWrap=»true» />
    <GridLayout columns=»2*,*,*» rows=»auto» class=»item item-header»>
        <Label text=»Name» textWrap=»true» row=»0″ col=»0″/>
        <Label text=»Distance» textWrap=»true» row=»0″ col=»1″ />
        <Label text=»Steps» textWrap=»true» row=»0″ col=»2″ />
    </GridLayout>
    <ListView items=»{{ friends_data }}»>
        <ListView.itemTemplate>
            <GridLayout columns=»2*,*,*» rows=»auto» class=»item item-row»>
                <Label text=»{{ user_name }}» textWrap=»true» row=»0″ col=»0″/>
                <Label text=»{{ distance }}» textWrap=»true» row=»0″ col=»1″ />
                <Label text=»{{ steps }}» textWrap=»true» row=»0″ col=»2″ />
            </GridLayout>
        </ListView.itemTemplate>
    </ListView>
</StackLayout>

Если в данный момент ни один пользователь не вошел в систему, мы показываем кнопку для входа через Facebook:

1
2
3
4
5
<StackLayout class=»p-20″>
    <Button text=»Login with Facebook» tap=»{{ loginFacebook }}»
    class=»btn-facebook»
    visibility=»{{ is_loggedin ? ‘collapsed’ : ‘visible’ }}» />
</StackLayout>

Откройте файл main-view-model.js и добавьте следующий код для импорта библиотеки fecha:

1
2
3
4
5
var fecha = require(‘fecha’);
 
var firebase = require(«nativescript-plugin-firebase»);
var http = require(«http»);
var applicationSettings = require(«application-settings»);

Мы используем nativescript-plugin-firebase для общения с Firebase, http для выполнения HTTP-запросов к API Graph Facebook и application-settings для сохранения данных для входа пользователя.

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

Ниже мы добавляем опцию persist , которая позволяет Firebase сохранять данные локально, чтобы приложение можно было использовать в автономном режиме. Позже мы добавим прослушиватель, когда меняется статус аутентификации (когда пользователь входит в систему или выходит из приложения).

01
02
03
04
05
06
07
08
09
10
11
firebase.init({
    persist: true,
    // add later: code for listening when auth status changes
}).then(
    function(instance){
      console.log(«firebase.init done»);
    },
    function(error){
      console.log(«firebase.init error: » + error);
    }
);

Затем добавьте код, который будет выполняться, когда пользователь нажимает на кнопку для входа в Facebook. При этом используется функция login в login , которая принимает объект, содержащий type и facebookOptions .

type — это метод аутентификации, который будет использоваться для входа в систему. В данном случае это Facebook. facebookOptions — это объект, содержащий массив с именем scope . Элементами этого массива являются разрешения, которые вы хотите, чтобы приложение запрашивало у пользователя.

Как только пользователь вошел в систему и согласился со всеми запрашиваемыми разрешениями, обещание разрешает и выполняет первую функцию, переданную then() . Данные пользователя Facebook передаются в качестве аргумента этой функции, но единственное, что нам нужно, это токен доступа. Мы можем использовать это позже, чтобы отправлять запросы в API Graph Facebook для получения дополнительной информации.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
viewModel.loginFacebook = function() {
     
    firebase.login({
        type: firebase.LoginType.FACEBOOK,
        facebookOptions: {
          scope: [‘public_profile’, ’email’, ‘user_friends’]
        }
    }).then(
        function(fb_result){
 
            var fb_access_token = fb_result.providers[1].token;
             
            // next: add code for checking if user is new or not
 
        },
        function (err) {
            console.log(‘error logging in to facebook: ‘, err);
        }
    );
 
}

Далее мы отправим запрос в базу данных Firebase, чтобы проверить, существует ли пользователь уже или нет. Для этого мы используем метод query() . Это принимает функцию для выполнения, когда ответ возвращается в качестве первого аргумента. Второй аргумент — это путь, по которому выполняется запрос, а третий — сам запрос.

Если пользователь уже существует, query() вернет данные пользователя. Затем мы сохраняем данные локально, используя настройки приложения . Нам понадобится получить доступ к этим данным позже, когда мы будем слушать изменения статуса авторизации и когда мы обновим последний сеанс ходьбы пользователя в Firebase.

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
firebase.query(
    function(firebase_result){
         
        if(!firebase_result.error){
             
            if(firebase_result.value == null){ //user doesn’t exist yet
             
                //next: add code for saving the data for new user
             
            }else{
                // user already exists
                for(var user_key in firebase_result.value){
                    // save user’s data locally
                    applicationSettings.setString(‘user_key’, user_key);
                    applicationSettings.setString(‘user’, JSON.stringify(firebase_result.value));
                    applicationSettings.setString(‘fb_token’, fb_access_token);
                }
            }
        }
 
    },
    ‘/users’,
    {
        singleEvent: true, // for checking if the value exists (return the whole data)
        orderBy: { // the property in each of the objects in which to perform the query
            type: firebase.QueryOrderByType.CHILD,
            value: ‘uid’
        },
        range: { // the comparison operator
            type: firebase.QueryRangeType.EQUAL_TO,
            value: fb_result.uid
        },
        limit: { // limit to only return the first result
            type: firebase.QueryLimitType.FIRST,
            value: 1
        }
    }
);

Теперь давайте добавим код для сохранения данных для нового пользователя. Начните с создания объекта, который содержит пользовательские данные. Затем сделайте запрос к API Graph Facebook, чтобы получить идентификатор Facebook пользователя (который действителен только для этого конкретного приложения).

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

Как только ответ будет возвращен, мы будем использовать метод push() Firebase, чтобы сохранить данные /users пути /users . Это возвращает ключ, который служит идентификатором для этого конкретного пользователя. Мы собираемся использовать его позже, чтобы обновить последнюю сессию пользователя. Вот почему нам также необходимо сохранить его локально вместе с данными пользователя и токеном доступа Facebook.

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
var user_data = {
    ‘uid’: fb_result.uid,
    ‘user_name’: fb_result.name,
    ‘profile_photo’: fb_result.profileImageURL
};
 
http.getJSON(‘https://graph.facebook.com/me?access_token=’ + fb_access_token)
    .then(function(r){
         
        user_data.id = r.id;
         
        // create new user
        firebase.push(
          ‘/users’,
          user_data
        ).then(
          function (result) {
             
            var user = {};
            user[result.key] = user_data;
            // store user’s data locally
            applicationSettings.setString(‘user_key’, result.key);
            applicationSettings.setString(‘user’, JSON.stringify(user));
            applicationSettings.setString(‘fb_token’, fb_access_token);
          }
        );
 
});

Теперь, когда мы добавили код для входа пользователя в систему, следующим шагом будет onAuthStateChanged firebase.init() и добавление onAuthStateChanged . Эта функция будет выполняться каждый раз, когда изменяется статус авторизации (когда пользователь входит в систему или выходит из нее). Если пользователь вошел в систему, мы хотим обновить пользовательский интерфейс, чтобы показать текущего пользователя.

Обратите внимание, что мы оборачиваем его внутри setTimeout() с setTimeout() задержкой, поскольку после входа в систему для доступа к данным пользователя (ключ пользователя Firebase, пользователь Firebase и маркер доступа Facebook) требуется несколько секунд.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
persist: true,
onAuthStateChanged: function (data) {
     
    if(data.loggedIn){ // is a user logged in?
 
        setTimeout(function(){
            // update UI to show the current user
            viewModel.set(‘is_loggedin’, true);
            viewModel.set(‘profile_photo’, data.user.profileImageURL);
            viewModel.set(‘user_name’, data.user.name);
            
            // next: add code for getting friends list
 
        }, 5000);
 
    }
     
}

Далее добавляем код для получения друзей пользователя. API Graph возвращает идентификатор и имя каждого из друзей пользователя, но нам нужны только идентификаторы. Нам также нужно нажать на идентификатор текущего пользователя, так как мы собираемся отобразить его и в списке лидеров.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
var user_key = applicationSettings.getString(‘user_key’);
var user = JSON.parse(applicationSettings.getString(‘user’));
var fb_token = applicationSettings.getString(‘fb_token’);
 
http.getJSON(‘https://graph.facebook.com/me/friends?access_token=’ + fb_token)
    .then(function (r) {
        // extract the ID’s
        var friends_ids = r.data.map(function(obj){
            return obj.id;
        });
        friends_ids.push(user[user_key].id);
 
        // next: add code for listening for changes in the database
 
}, function(e){
    console.log(‘err: ‘, e);
});

Затем добавьте код для прослушивания изменений в базе данных. До сих пор мы не реализовали часть этого приложения в режиме реального времени. Это время, когда мы наконец добавим это.

Для этого мы используем метод addValueEventListener() . Это принимает функцию, которую вы хотите выполнить, когда вносится изменение в путь, указанный вами в качестве второго аргумента. Все значение ( result ) передается в качестве аргумента этой функции.

Там действительно нет функциональности, чтобы указать запрос, чтобы фильтровать результат только по определенным идентификаторам. Таким образом, используя массив идентификаторов друзей ( friends_ids ), мы перебираем result и проверяем, является ли текущий ряд текущим пользователем или одним из его друзей. Только тогда мы нажимаем значение для текущей строки. Оттуда мы просто сортируем и форматируем данные для отображения в пользовательском интерфейсе.

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
firebase.addValueEventListener(function(result){
     
    var friends_data = [];
    for(var row in result.value){
        var friend = result.value[row];
        // check if the current row is the current user or one of their friends
        if(friends_ids.indexOf(friend.id) !== -1){
            friends_data.push(result.value[row]);
        }
    }
    // sort data in descending order of the steps
    var sorted_friends_data = friends_data.sort(function(a, b) {
        return b.steps — a.steps;
    });
    // format the data for displaying
    var formatted_sorted_friends_data = sorted_friends_data.map(function(obj, key){
        var updated_obj = obj;
        updated_obj.distance = commafy(obj.distance) + ‘m’;
        updated_obj.steps = commafy(obj.steps);
        return updated_obj;
    });
    // update the UI
    viewModel.set(‘friends_data’, formatted_sorted_friends_data);
 
}, «/users»);

Когда пользователь перестает отслеживать свое текущее местоположение, мы обновляем distance и steps пользователя в Firebase:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
viewModel.set(‘walks’, walks);
if(walks.length > 0){
    viewModel.set(‘has_walks’, true);
}
 
var user_key = applicationSettings.getString(‘user_key’);
var user = applicationSettings.getString(‘user’);
var user_data = JSON.parse(user);
user_data[user_key].distance = total_distance;
user_data[user_key].steps = total_steps;
 
// update user’s data
firebase.update(
    ‘/users’,
    user_data
);

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

1
2
3
4
5
6
7
8
9
viewModel.logout = function() {
    firebase.logout();
 
    viewModel.set(‘is_loggedin’, false);
    viewModel.set(‘profile_photo’, null);
    viewModel.set(‘user_name’, null);
 
    applicationSettings.clear();
}

Наконец, откройте файл app / app.css и добавьте следующее ниже существующего кода:

01
02
03
04
05
06
07
08
09
10
11
12
13
.btn-facebook {
    background-color: #365899;
    color: #fff;
}
 
.btn-logout {
    background-color: red;
    color: #fff;
}
 
.profile {
    text-align: center;
}

Это оно! Из этого урока вы узнали, как интегрировать логин Facebook и Firebase в приложение NativeScript. Как вы могли заметить в документации к плагину NativeScript Firebase, вы действительно можете сделать намного больше с этим плагином. Фактически, мы будем использовать функцию Cloud Messaging для реализации последней функции для этого приложения: Push-уведомления. Так что следите за обновлениями!

А пока посмотрите другие наши посты о NativeScript и кроссплатформенных мобильных приложениях!

  • ионный
    Начало работы с ионными службами: развертывание
  • NativeScript
    Кодирование приложения NativeScript в реальном времени: геолокация и Google Maps
  • Мобильное приложение
    Создайте приложение погоды с TypeScript и NativeScript
  • React Native
    Практические примеры анимации в React Native