Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Введение
Это комплексное руководство поможет разработчикам интегрировать расширенную поддержку в библиотеку пользовательского интерфейса ACS, используя службы Azure для обработки серверной части. Руководство делится на клиентские и серверные шаги для ясности и простоты реализации.
Предпосылки
- Подписка Azure: Вам нужна активная подписка Azure. Если у вас нет учетной записи, вы можете создать бесплатную учетную запись в бесплатной учетной записи Azure.
- Ресурс Служб коммуникации Azure: Ресурс ACS требуется для использования функций звонков и чатов. Его можно создать на портале Azure.
- Настройка среды разработки: Убедитесь, что среда разработки настроена для одной или нескольких целевых платформ — Android, iOS или Интернета.
- Учетная запись хранения Azure: Для безопасного хранения отзывов пользователей и связанных данных требуется учетная запись хранения Azure.
- Node.js и Express.js: Базовые знания о Node.js и Express.js полезны для настройки серверного приложения для получения и обработки запросов на поддержку.
- Знание API RESTful: Общие сведения о создании и использовании API RESTful в развертывании и настройке клиента и сервера.
- Навыки разработки клиентов: Опыт разработки приложений Android или iOS.
Наличие этих предварительных требований обеспечивает плавное начало интеграции комплексной системы отзывов пользователей с помощью Служб коммуникации Azure и других ресурсов Azure.
Что вы узнаете
В этом руководстве вы получите исчерпывающую информацию об интеграции механизмов обратной связи пользователей в приложениях Служб коммуникации Azure (ACS). Основное внимание уделяется повышению поддержки клиентов через библиотеку пользовательского интерфейса ACS, используя серверные службы Azure для обработки. Следуя этому руководству, разработчики учатся:
- Реализуйте сбор отзывов на стороне клиента: Узнайте, как собирать отзывы пользователей, журналы ошибок и запрашивать поддержку прямо из приложений Android и iOS с помощью UI библиотеки ACS.
- Настройка приложения Server-Side: Пошаговые инструкции по настройке приложения Node.js с помощью Express.js для получения, обработки и хранения запросов на поддержку в хранилище BLOB-объектов Azure. Этот сервер включает обработку multipart/form-data для загрузки файлов и безопасного управления данными пользователей.
- Создайте тикеты в службу поддержки: Узнайте, как генерировать уникальные номера тикетов в службу поддержки, хранить отзывы пользователей наряду с соответствующими данными приложения.
- Используйте хранилище BLOB-объектов Azure: Узнайте, как использовать хранилище BLOB-объектов Azure для хранения отзывов и запросов на поддержку, обеспечивая безопасное и структурированное управление данными, которое поддерживает эффективное извлечение и анализ.
- Повышение надежности приложений и удовлетворенности пользователей: Разработчики могут быстро устранять и устранять проблемы пользователей, реализуя стратегии, описанные в этом руководстве.
Настройка серверной стороны
Настройка приложения Node.js для обработки запросов на поддержку
Цель раздела: Целью является создание приложения Node.js с помощью Express.js, которая служит серверной частью для получения запросов на поддержку от пользователей. Эти запросы могут включать текстовые отзывы, журналы ошибок, снимки экрана и другие важные сведения, которые могут помочь в диагностике и устранении проблем с пользователем. Приложение хранит эти данные в хранилище BLOB-объектов Azure для упорядоченного и безопасного доступа.
Платформа и инструменты
- Express.js: Платформа Node.js для создания веб-приложений и API. Он служит основой для настройки сервера и обработки запросов.
- Formidable: Библиотека для синтаксического анализа данных формы, специально предназначенная для обработки multipart/form-data, который часто используется при загрузке файлов.
- Хранилище Blob Azure: Услуга Microsoft Azure для хранения больших объемов неструктурированных данных.
Шаг 1. Настройка среды
Прежде чем начать, убедитесь, что среда разработки готова к установке Node.js. Для хранения отправленных данных также требуется доступ к учетной записи хранения Azure.
Установка Node.js: Убедитесь, что Node.js установлен в системе. Его можно скачать из Node.js.
Создайте учетную запись хранения BLOB-объектов Azure: Если вы еще не сделали этого, создайте учетную запись хранения Azure на портале Azure. Эта учетная запись используется для хранения данных запроса на поддержку.
Сбор необходимых учетных данных: Убедитесь, что у вас есть строка подключения для учетной записи хранения облачных объектов BLOB Azure.
Шаг 2. Настройка приложения
Инициализация нового проекта Node.js:
Создайте новый каталог для вашего проекта и инициализируйте его с
npm init, чтобы создать файлpackage.json.Установите Express.js, Formidable, SDK для работы с BLOB-объектами хранилища Azure и другие необходимые библиотеки через npm.
npm install express formidable @azure/storage-blob uuid
Реализация сервера:
- Используйте Express.js для настройки базового веб-сервера, который прослушивает запросы POST в определенной конечной точке.
- Используйте Formidable для синтаксического анализа входящих данных формы, обработки содержимого с несколькими частями или данными формы.
- Создайте уникальный номер билета для каждого запроса на поддержку, который можно использовать для упорядочивания данных в хранилище BLOB-объектов Azure и предоставления ссылки для пользователей.
- Храните структурированные данные, такие как сообщения пользователя и метаданные файла журнала, в JSON-файле в хранилище BLOB-объектов. Храните фактические файлы журнала и все снимки экрана или вложения в отдельных blob'ах в одной директории заявки.
- Предоставьте конечную точку для получения сведений о поддержке, которая включает получение и отображение данных из хранилища BLOB-объектов Azure.
Вопросы безопасности:
- Убедитесь, что ваше приложение проверяет входящие данные приложения для защиты от вредоносных данных.
- Используйте переменные среды для безопасного хранения конфиденциальных данных, таких как строка подключения к службе хранилища Azure.
Шаг 3. Запуск и тестирование приложения
Переменные среды:
- Настройте переменные среды для строки подключения к Azure Blob Storage и другой конфиденциальной информации. Например, можно использовать
.envфайл (иdotenvпакет npm для загрузки этих переменных).
- Настройте переменные среды для строки подключения к Azure Blob Storage и другой конфиденциальной информации. Например, можно использовать
Запуск сервера:
- Запустите приложение Node.js, выполнив команду
node <filename>.js, где<filename>находится имя основного файла сервера. - Проверьте сервер с помощью подходящего средства для веб-разработки.
- Запустите приложение Node.js, выполнив команду
Код сервера:
Вот рабочая реализация, с которой можно начать. Этот код является базовой реализацией, адаптированной для демонстрации создания билетов из примеров приложений пользовательского интерфейса ACS.
const express = require('express');
const formidable = require('formidable');
const fs = require('fs').promises
const { BlobServiceClient } = require('@azure/storage-blob');
const { v4: uuidv4 } = require('uuid');
const app = express();
const connectionString = process.env.SupportTicketStorageConnectionString
const port = process.env.PORT || 3000;
const portPostfix = (!process.env.PORT || port === 3000 || port === 80 || port === 443) ? '' : `:${port}`;
app.use(express.json());
app.all('/receiveEvent', async (req, res) => {
try {
const form = new formidable.IncomingForm();
form.parse(req, async (err, fields, files) => {
if (err) {
return res.status(500).send("Error processing request: " + err.message);
}
// Generate a unique ticket number
const ticketNumber = uuidv4();
const blobServiceClient = BlobServiceClient.fromConnectionString(connectionString);
const containerClient = blobServiceClient.getContainerClient('supporttickets');
await containerClient.createIfNotExists();
// Prepare and upload support data
const supportData = {
userMessage: fields.user_message,
uiVersion: fields.ui_version,
sdkVersion: fields.sdk_version,
callHistory: fields.call_history
};
const supportDataBlobClient = containerClient.getBlockBlobClient(`${ticketNumber}/supportdata.json`);
await supportDataBlobClient.upload(JSON.stringify(supportData), Buffer.byteLength(JSON.stringify(supportData)));
// Upload log files
Object.values(files).forEach(async (fileOrFiles) => {
// Check if the fileOrFiles is an array (multiple files) or a single file object
const fileList = Array.isArray(fileOrFiles) ? fileOrFiles : [fileOrFiles];
for (let file of fileList) {
const blobClient = containerClient.getBlockBlobClient(`${ticketNumber}/logs/${file.originalFilename}`);
// Read the file content into a buffer
const fileContent = await fs.readFile(file.filepath);
// Now upload the buffer
await blobClient.uploadData(fileContent); // Upload the buffer instead of the file path
}
});
// Return the ticket URL
const endpointUrl = `${req.protocol}://${req.headers.host}${portPostfix}/ticketDetails?id=${ticketNumber}`;
res.send(endpointUrl);
});
} catch (err) {
res.status(500).send("Error processing request: " + err.message);
}
});
// ticketDetails endpoint to serve details page
app.get('/ticketDetails', async (req, res) => {
const ticketNumber = req.query.id;
if (!ticketNumber) {
return res.status(400).send("Ticket number is required");
}
// Fetch the support data JSON blob to display its contents
try {
const blobServiceClient = BlobServiceClient.fromConnectionString(connectionString);
const containerClient = blobServiceClient.getContainerClient('supporttickets');
const blobClient = containerClient.getBlobClient(`${ticketNumber}/supportdata.json`);
const downloadBlockBlobResponse = await blobClient.download(0);
const downloadedContent = (await streamToBuffer(downloadBlockBlobResponse.readableStreamBody)).toString();
const supportData = JSON.parse(downloadedContent);
// Generate links for log files
let logFileLinks = `<h3>Log Files:</h3>`;
const listBlobs = containerClient.listBlobsFlat({ prefix: `${ticketNumber}/logs/` });
for await (const blob of listBlobs) {
logFileLinks += `<a href="/getLogFile?id=${ticketNumber}&file=${encodeURIComponent(blob.name.split('/')[2])}">${blob.name.split('/')[2]}</a><br>`;
}
// Send a simple HTML page with support data and links to log files
res.send(`
<h1>Ticket Details</h1>
<p><strong>User Message:</strong> ${supportData.userMessage}</p>
<p><strong>UI Version:</strong> ${supportData.uiVersion}</p>
<p><strong>SDK Version:</strong> ${supportData.sdkVersion}</p>
<p><strong>Call History:</strong> </p> <pre>${supportData.callHistory}</pre>
${logFileLinks}
`);
} catch (err) {
res.status(500).send("Error fetching ticket details: " + err.message);
}
});
// getLogFile endpoint to allow downloading of log files
app.get('/getLogFile', async (req, res) => {
const { id: ticketNumber, file } = req.query;
if (!ticketNumber || !file) {
return res.status(400).send("Ticket number and file name are required");
}
try {
const blobServiceClient = BlobServiceClient.fromConnectionString(connectionString);
const containerClient = blobServiceClient.getContainerClient('supporttickets');
const blobClient = containerClient.getBlobClient(`${ticketNumber}/logs/${file}`);
// Stream the blob to the response
const downloadBlockBlobResponse = await blobClient.download(0);
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', `attachment; filename=${file}`);
downloadBlockBlobResponse.readableStreamBody.pipe(res);
} catch (err) {
res.status(500).send("Error downloading file: " + err.message);
}
});
// Helper function to stream blob content to a buffer
async function streamToBuffer(stream) {
const chunks = [];
return new Promise((resolve, reject) => {
stream.on('data', (chunk) => chunks.push(chunk));
stream.on('end', () => resolve(Buffer.concat(chunks)));
stream.on('error', reject);
});
}
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
Настройка на стороне клиента
В этом разделе рассматриваются настройки на стороне клиента и способы достижения следующих целей:
- Зарегистрируйтесь для сообщений о проблемах, сообщённых пользователями.
- Сериализация данных.
- Перенаправите его на сервер.
- Получение ответа.
- Представить ответ пользователю.
Для включения обратной связи пользователей в библиотеке пользовательского интерфейса Служб коммуникации Azure (ACS) разработчикам необходимо предпринять действия. Используя onUserReportedIssueEventHandler интеграцию библиотеки, разработчики могут включить встроенную форму поддержки, позволяя пользователям сообщать о проблемах напрямую. В этом разделе описано, как настроить форму обратной связи на стороне клиента.
Реализация сбора отзывов на стороне клиента в Android
Включение формы поддержки
Регистрация обработчика событий:
- Чтобы активировать форму поддержки в приложении Android, зарегистрируйте
onUserReportedIssueEventHandlerее в соответствующей точке жизненного цикла приложения. Эта регистрация включает не только форму, но и гарантирует, что она становится видимой и доступной для пользователей.
- Чтобы активировать форму поддержки в приложении Android, зарегистрируйте
Видимость форм и доступность:
- Наличие зарегистрированного
onUserReportedIssueEventHandlerнепосредственно влияет на видимость формы поддержки. Без этого обработчика форма остается скрытой от пользовательского интерфейса, делая ее недоступной для сообщения о проблемах.
- Наличие зарегистрированного
Запись и обработка событий поддержки
Генерация событий при отчетах о проблемах:
- Когда пользователи сообщают о проблемах с помощью включенной формы поддержки,
onUserReportedIssueEventHandlerфиксирует сгенерированные события. Эти события инкапсулируют все необходимые сведения, связанные с проблемой, сообщаемой пользователем, например описаниями, журналами ошибок и потенциально снимками экрана.
- Когда пользователи сообщают о проблемах с помощью включенной формы поддержки,
Подготовка данных к отправке:
- Когда пользователь сообщает о проблеме, следующий шаг включает подготовку данных о проблеме для отправки сервера. Эта подготовка включает структурирование захваченных сведений в формат, подходящий для передачи HTTP, в соответствии с ожиданиями сервера.
Отправка данных о проблеме на сервер
Асинхронная передача данных:
- Используйте асинхронные механизмы для передачи подготовленных данных в назначенную конечную точку сервера. Этот подход гарантирует, что приложение остается адаптивным, обеспечивая гладкое взаимодействие с пользователем во время отправки данных в фоновом режиме.
Обработка ответов сервера:
- При отправке данных крайне важно умело обрабатывать ответы сервера. Эта обработка может включать анализ отзывов сервера, чтобы подтвердить успешную передачу данных и, возможно, извлечь ссылку на отправленную проблему (например, номер билета или URL-адрес), которую можно передать пользователю.
Предоставление отзывов пользователей и уведомлений
Немедленная обратная связь пользователей:
- Уведомляйте пользователей о состоянии отправки отчета о проблеме через пользовательский интерфейс приложения. Для успешной отправки рекомендуется указать ссылку на отправленную проблему, которая позволяет пользователям отслеживать ход выполнения отчета.
Стратегия уведомлений для Android O и более поздних версий:
- Для устройств под управлением Android O (уровень API 26) и более новых версий необходимо реализовать канал уведомлений, специфичный для отправки отчетов. Эта настройка необходима для эффективной доставки уведомлений и является обязательным требованием для этих версий Android.
Следуя этим инструкциям, разработчики могут интегрировать надежный механизм обратной связи пользователей в свои приложения Android, используя onUserReportedIssueEventHandler для эффективной отчетности и отслеживания проблем. Этот процесс не только упрощает своевременное решение проблем с пользователем, но и значительно способствует повышению общего взаимодействия с пользователем и удовлетворенности приложением.
Пример кода Android
Фрагмент кода Kotlin демонстрирует процесс интеграции системы для обработки пользовательских проблем в приложении Android с помощью Служб коммуникации Azure. Эта интеграция направлена на упрощение процесса поддержки путем прямого взаимодействия между пользователями и группами поддержки. Ниже приведен обзор описанных действий.
Запись событий: система прослушивает проблемы, сообщаемые пользователем, через библиотеку пользовательского интерфейса ACS. Он использует
onUserReportedIssueEventHandlerдля сбора отзывов из пользовательского интерфейса приложения, включая ошибки и замечания пользователей.Передача данных на сервер: когда сообщается о проблеме, система упаковает соответствующие данные, включая сообщения пользователей, журналы ошибок, версии и диагностические сведения. Затем эти данные отправляются в конечную точку сервера с помощью асинхронного запроса POST, чтобы процесс не препятствовал производительности приложения.
Отзывы пользователей и уведомления. После отправки пользователи сразу же получают сведения о состоянии отчета с помощью уведомлений в приложении. Для успешной отправки уведомление содержит ссылку или упоминание на отправленный билет, позволяя пользователям отслеживать ход решения проблемы.
Эта настройка помогает не только быстро решать проблемы пользователей, но и значительно способствует повышению удовлетворенности пользователей и надежности приложений, предоставляя четкий канал для поддержки и обратной связи.
package com.azure.android.communication.ui.callingcompositedemoapp
import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.net.Uri
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.azure.android.communication.ui.calling.CallCompositeEventHandler
import com.azure.android.communication.ui.calling.models.CallCompositeCallHistoryRecord
import com.azure.android.communication.ui.calling.models.CallCompositeUserReportedIssueEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.asRequestBody
import org.threeten.bp.format.DateTimeFormatter
import java.io.File
import java.io.IOException
/**
* This class is responsible for handling user-reported issues within the Azure Communication Services Calling UI composite.
* It implements the CallCompositeEventHandler interface to listen for CallCompositeUserReportedIssueEvents.
* The class demonstrates how to send diagnostic information to a server endpoint for support purposes and
* how to provide user feedback through notifications.
*/
class UserReportedIssueHandler : CallCompositeEventHandler<CallCompositeUserReportedIssueEvent> {
// Flow to observe user reported issues.
val userIssuesFlow = MutableStateFlow<CallCompositeUserReportedIssueEvent?>(null)
// Reference to the application context, used to display notifications.
lateinit var context: Application
// Lazy initialization of the NotificationManagerCompat for managing notifications.
private val notificationManager by lazy { NotificationManagerCompat.from(context) }
/**
* Handles the event when a user reports an issue.
* - Creates a notification channel for Android O and above.
* - Updates the userIssuesFlow with the new event data.
* - Sends the event data including user message, app and SDK versions, call history, and log files to a server.
*/
override fun handle(eventData: CallCompositeUserReportedIssueEvent?) {
createNotificationChannel()
userIssuesFlow.value = eventData
eventData?.apply {
sendToServer(
userMessage,
debugInfo.versions.azureCallingUILibrary,
debugInfo.versions.azureCallingLibrary,
debugInfo.callHistoryRecords,
debugInfo.logFiles
)
}
}
/**
* Prepares and sends a POST request to a server with the user-reported issue data.
* Constructs a multipart request body containing the user message, app versions, call history, and log files.
*/
private fun sendToServer(
userMessage: String?,
callingUIVersion: String?,
callingSDKVersion: String?,
callHistoryRecords: List<CallCompositeCallHistoryRecord>,
logFiles: List<File>
) {
if (SERVER_URL.isBlank()) { // Check if the server URL is configured.
return
}
showProgressNotification()
CoroutineScope(Dispatchers.IO).launch {
val client = OkHttpClient()
val requestBody = MultipartBody.Builder().setType(MultipartBody.FORM).apply {
userMessage?.let { addFormDataPart("user_message", it) }
callingUIVersion?.let { addFormDataPart("ui_version", it) }
callingSDKVersion?.let { addFormDataPart("sdk_version", it) }
addFormDataPart(
"call_history",
callHistoryRecords.map { "\n\n${it.callStartedOn.format(DateTimeFormatter.BASIC_ISO_DATE)}\n${it.callIds.joinToString("\n")}" }
.joinToString("\n"))
logFiles.filter { it.length() > 0 }.forEach { file ->
val mediaType = "application/octet-stream".toMediaTypeOrNull()
addFormDataPart("log_files", file.name, file.asRequestBody(mediaType))
}
}.build()
val request = Request.Builder()
.url("$SERVER_URL/receiveEvent")
.post(requestBody)
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
CoroutineScope(Dispatchers.Main).launch {
onTicketFailed(e.message ?: "Unknown error")
}
}
override fun onResponse(call: Call, response: Response) {
CoroutineScope(Dispatchers.Main).launch {
if (response.isSuccessful) {
onTicketCreated(response.body?.string() ?: "No URL provided")
} else {
onTicketFailed("Server error: ${response.message}")
}
}
}
})
}
}
/**
* Displays a notification indicating that the issue ticket has been created successfully.
* The notification includes a URL to view the ticket status, provided by the server response.
*/
private fun onTicketCreated(url: String) {
showCompletionNotification(url)
}
/**
* Displays a notification indicating that the submission of the issue ticket failed.
* The notification includes the error reason.
*/
private fun onTicketFailed(error: String) {
showErrorNotification(error)
}
companion object {
// The server URL to which the user-reported issues will be sent. Must be configured.
private const val SERVER_URL = "${INSERT_YOUR_SERVER_ENDPOINT_HERE}"
}
/**
* Creates a notification channel for Android O and above.
* This is necessary to display notifications on these versions of Android.
*/
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "Report Submission"
val descriptionText = "Notifications for report submission status"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel("report_submission_channel", name, importance).apply {
description = descriptionText
}
notificationManager.createNotificationChannel(channel)
}
}
/**
* Shows a notification indicating that the report submission is in progress.
* This uses an indeterminate progress indicator to signify ongoing activity.
*/
private fun showProgressNotification() {
val notification = NotificationCompat.Builder(context, "report_submission_channel")
.setContentTitle("Submitting Report")
.setContentText("Your report is being submitted...")
.setSmallIcon(R.drawable.image_monkey) // Replace with an appropriate icon for your app
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setProgress(0, 0, true) // Indeterminate progress
.build()
notificationManager.notify(1, notification)
}
/**
* Shows a notification indicating that the report has been successfully submitted.
* The notification includes an action to view the report status via a provided URL.
*/
private fun showCompletionNotification(url: String) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
val pendingIntent = PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val notification = NotificationCompat.Builder(context, "report_submission_channel")
.setContentTitle("Report Submitted")
.setContentText("Tap to view")
.setSmallIcon(R.drawable.image_monkey) // Replace with an appropriate icon for your app
.setContentIntent(pendingIntent)
.setAutoCancel(true) // Removes notification after tap
.build()
notificationManager.notify(1, notification)
}
/**
* Shows a notification indicating an error in submitting the report.
* The notification includes the reason for the submission failure.
*/
private fun showErrorNotification(error: String) {
val notification = NotificationCompat.Builder(context, "report_submission_channel")
.setContentTitle("Submission Error")
.setContentText("Error submitting report\nReason: $error")
.setSmallIcon(R.drawable.image_monkey) // Replace with an appropriate icon for your app
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.build()
notificationManager.notify(1, notification)
}
}
После того как у вас есть обработчик для события, его можно зарегистрировать при создании составного элемента вызова.
callComposite.addOnUserReportedEventHandler(userReportedIssueEventHandler)
Общие сведения о поддержке iOS
Чтобы интегрировать сбор отзывов пользователей в приложениях iOS с помощью библиотеки пользовательского интерфейса Служб коммуникации Azure (ACS), разработчикам необходимо выполнить структурированный подход. Этот процесс включает запись отзывов пользователей, включая журналы ошибок и сведения о пользователе. После завершения эти сведения передаются на сервер для обработки. В этом разделе описаны шаги, необходимые для выполнения этой задачи.
В этом примере мы используем библиотеку Alamofire для обработки отправки многокомпонентной формы, включая файлы журналов на сервер.
Реализация формы поддержки
Регистрация обработчика событий. Начните с регистрации обработчика событий, который прослушивает проблемы, сообщаемые пользователем. Этот обработчик имеет решающее значение для записи отзывов непосредственно из интерфейса приложения iOS с помощью возможностей библиотеки пользовательского интерфейса ACS.
Видимость и специальные возможности формы: убедитесь, что форма поддержки легко доступна и видна пользователям в приложении. Активация формы напрямую связана с реализацией обработчика событий, которая активирует его внешний вид в пользовательском интерфейсе, позволяя пользователям сообщать о проблемах.
Сбор и обработка запросов на поддержку
Генерация события при действии пользователя: когда пользователь сообщает о проблеме через форму поддержки, обработчик событий фиксирует это действие. Такие сведения, как описание проблемы, журналы ошибок и все идентификаторы вызовов, должны быть подготовлены для отправки на сервер.
Структурирование данных для отправки: упорядочение захваченных данных в структурированном формате, подходящем для передачи. Подготовьте данные таким образом, чтобы он соответствовал ожидаемому формату конечной точки сервера, которая получает и обрабатывает запрос на поддержку.
Отправка данных на сервер
Асинхронная отправка: используйте асинхронные сетевые вызовы для отправки структурированных данных на сервер. Этот подход гарантирует, что приложение остается адаптивным, обеспечивая простой интерфейс для пользователя во время передачи данных в фоновом режиме.
Обработка ответов сервера: при отправке эффективно обрабатывает ответы сервера. Получение и анализ ответа, чтобы подтвердить успешное получение данных. Извлеките ссылку на запрос в службу поддержки из проанализированного ответа, который можно передать пользователю для последующего выполнения.
Отзывы и уведомления пользователям
Немедленное подтверждение. Немедленно подтвердите отправку запроса на поддержку в приложении, предоставив пользователям подтверждение того, что их отчет был получен.
Стратегия уведомлений. Реализуйте стратегию доставки уведомлений пользователям, особенно на устройствах под управлением версий iOS, поддерживающих определенные платформы уведомлений. Локальные уведомления можно использовать для информирования пользователей о состоянии отчета или предоставлении обновлений по мере устранения проблемы.
Пример кода iOS
Этот пример кода Swift описывает базовую реализацию для записи проблем, сообщаемых пользователем, и отправки их на сервер для обработки. В этом примере показано, как создать обработчик событий поддержки, включая отзывы пользователей и диагностические сведения о приложении и доставку на сервер. Код также включает в себя стратегии обработки ошибок и уведомлений пользователей, чтобы обеспечить гладкое взаимодействие с пользователем.
Следующий пример предназначен для встраивания хука в ваш обработчик событий.
Installation
let onUserReportedIssueHandler: (CallCompositeUserReportedIssue) -> Void = { issue in
// Add a hook to this method, and provide it the Server endpoint + a result callback
sendSupportEventToServer(server: self.issueUrl, event: issue) { success, result in
if success {
// Success: Convey the result link back to the user
} else {
// Error: Let the user know something has happened
}
}
}
Сетевой хук
import Foundation
import UIKit
import Combine
import AzureCommunicationUICalling
import Alamofire
/// Sends a support event to a server with details from a `CallCompositeUserReportedIssue`.
/// - Parameters:
/// - server: The URL of the server where the event will be sent.
/// - event: The `CallCompositeUserReportedIssue` containing details about the issue reported by the user.
/// - callback: A closure that is called when the operation is complete.
/// It provides a `Bool` indicating success or failure, and a `String`
/// containing the server's response or an error message.
func sendSupportEventToServer(server: String,
event: CallCompositeUserReportedIssue,
callback: @escaping (Bool, String) -> Void) {
// Construct the URL for the endpoint.
let url = "\(server)/receiveEvent" // Ensure this is replaced with the actual server URL.
// Extract debugging information from the event.
let debugInfo = event.debugInfo
// Prepare the data to be sent as key-value pairs.
let parameters: [String: String] = [
"user_message": event.userMessage, // User's message about the issue.
"ui_version": debugInfo.versions.callingUIVersion, // Version of the calling UI.
"call_history": debugInfo.callHistoryRecords
.map { $0.callIds.joined(separator: ",") }
.joined(separator: "\n") // Call history, formatted.
]
// Define the headers for the HTTP request.
let headers: HTTPHeaders = [
.contentType("multipart/form-data")
]
// Perform the multipart/form-data upload.
AF.upload(multipartFormData: { multipartFormData in
// Append each parameter as a part of the form data.
for (key, value) in parameters {
if let data = value.data(using: .utf8) {
multipartFormData.append(data, withName: key)
}
}
// Append log files.
debugInfo.logFiles.forEach { fileURL in
do {
let fileData = try Data(contentsOf: fileURL)
multipartFormData.append(fileData,
withName: "log_files",
fileName: fileURL.lastPathComponent,
mimeType: "application/octet-stream")
} catch {
print("Error reading file data: \(error)")
}
}
}, to: url, method: .post, headers: headers).response { response in
// Handle the response from the server.
switch response.result {
case .success(let responseData):
// Attempt to decode the response.
if let data = responseData, let responseString = String(data: data, encoding: .utf8) {
callback(true, responseString) // Success case.
} else {
callback(false, "Failed to decode response.") // Failed to decode.
}
case .failure(let error):
// Handle any errors that occurred during the request.
print("Error sending support event: \(error)")
callback(false, "Error sending support event: \(error.localizedDescription)")
}
}
}
Этот код Swift демонстрирует процесс отправки пользовательских проблем из приложения iOS с помощью Служб коммуникации Azure. Она обрабатывает сбор отзывов пользователей, упаковку диагностических сведений и асинхронную отправку в конечную точку сервера. Кроме того, он предоставляет основу для реализации механизмов обратной связи, обеспечивая информирование пользователей о состоянии своих отчетов и повышение общей надежности приложений и удовлетворенности пользователей.
Conclusion
Интеграция механизмов обратной связи пользователей в приложения с помощью Служб коммуникации Azure (ACS) имеет решающее значение для разработки адаптивных и ориентированных на пользователей приложений. В этом руководстве представлен четкий путь для настройки обработки на стороне сервера с помощью Node.js и отслеживания отзывов на стороне клиента для приложений Android и iOS. Благодаря такой интеграции разработчики могут повысить надежность приложений и удовлетворенность пользователей при использовании облачных служб Azure для эффективного управления данными.
В этом руководстве описаны практические шаги по сбору отзывов пользователей, журналов ошибок и запросов на поддержку непосредственно из приложений. Интеграция событий поддержки обеспечивает безопасный и упорядоченный способ обработки отзывов, позволяя разработчикам быстро устранять и устранять проблемы пользователей, что приводит к улучшению общего взаимодействия с пользователем.
Следуя инструкциям, описанным в этом руководстве, разработчики могут повысить скорость реагирования своих приложений и лучше соответствовать потребностям пользователей. Эти интеграции не только помогают лучше понять отзывы пользователей, но и используют облачные службы для обеспечения плавной и эффективной сбора отзывов и механизма обработки. В конечном счете интеграция механизмов обратной связи пользователей является важной для создания привлекательных и надежных приложений, которые ставят на первое место удовлетворенность пользователей.