Gebruikersfeedback verzamelen in de ACS UI-bibliotheek
Inleiding
Deze uitgebreide handleiding is ontworpen om ontwikkelaars te helpen bij het integreren van verbeterde ondersteuning in de ACS UI Library, met behulp van Azure-services voor back-endverwerking. De handleiding is onderverdeeld in stappen aan de clientzijde en aan de serverzijde voor duidelijkheid en gebruiksgemak van de implementatie.
Vereisten
- Azure-abonnement: u hebt een actief Azure-abonnement nodig. Als u nog geen account hebt, kunt u een gratis account maken bij een gratis Azure-account.
- Azure Communication Services-resource: een ACS-resource is vereist voor het gebruik van bel- en chatfuncties. U kunt er een maken in Azure Portal.
- Installatie van ontwikkelomgeving: zorg ervoor dat uw ontwikkelomgeving is ingesteld voor een of meer doelplatforms: Android, iOS of web.
- Azure Storage-account: voor het veilig opslaan van feedback van gebruikers en gerelateerde gegevens is een Azure Storage-account nodig.
- Node.js en Express.js: Basiskennis van Node.js en Express.js is handig voor het instellen van de toepassing aan de serverzijde om ondersteuningsaanvragen te ontvangen en te verwerken.
- Kennis van RESTful-API's: inzicht in het maken en gebruiken van RESTful API's bij de implementatie en configuratie van zowel de client als de server.
- Vaardigheden voor clientontwikkeling: vaardigheid in de ontwikkeling van Android- of iOS-toepassingen.
Als u aan deze vereisten voldoet, zorgt u voor een soepele start van de integratie van een uitgebreid feedbacksysteem voor gebruikers met behulp van Azure Communication Services en andere Azure-resources.
Wat u leert
In deze handleiding krijgt u uitgebreide inzichten in het integreren van mechanismen voor gebruikersfeedback in uw ACS-toepassingen (Azure Communication Services). De focus ligt op het verbeteren van de klantondersteuning via de ACS UI-bibliotheek, met behulp van Azure-back-endservices voor verwerking. Door deze handleiding te volgen, leren ontwikkelaars het volgende:
- Feedback vastleggen aan clientzijde implementeren: informatie over het vastleggen van feedback van gebruikers, foutenlogboeken en ondersteuningsaanvragen rechtstreeks vanuit Android- en iOS-toepassingen met behulp van de ACS UI-bibliotheek.
- Een toepassing aan de serverzijde instellen: stapsgewijze instructies voor het instellen van een Node.js-toepassing met behulp van Express.js voor het ontvangen, verwerken en opslaan van ondersteuningsaanvragen in Azure Blob Storage. Deze server omvat het verwerken van multipart-/form-data voor bestandsuploads en het veilig beheren van gebruikersgegevens.
- Ondersteuningstickets maken: informatie over het genereren van unieke ondersteuningsticketnummers, het opslaan van feedback van gebruikers naast relevante toepassingsgegevens.
- Azure Blob Storage gebruiken: ontdek hoe u Azure Blob Storage gebruikt voor het opslaan van feedback- en ondersteuningsaanvraaggegevens, zodat u veilig en gestructureerd gegevensbeheer kunt garanderen dat ondersteuning biedt voor efficiënt ophalen en analyseren.
- Verbeter de betrouwbaarheid en gebruikerstevredenheid van toepassingen: ontwikkelaars kunnen snel gebruikersproblemen oplossen en oplossen door de strategieën te implementeren die in deze handleiding worden beschreven.
Installatie aan serverzijde
Een Node.js-toepassing instellen voor het afhandelen van ondersteuningsaanvragen
Sectiedoelstelling: Het doel is om een Node.js toepassing te maken met behulp van Express.js die als back-end fungeert voor het ontvangen van ondersteuningsaanvragen van gebruikers. Deze aanvragen kunnen tekstuele feedback, foutenlogboeken, schermopnamen en andere relevante informatie bevatten die kan helpen bij het diagnosticeren en oplossen van gebruikersproblemen. De toepassing slaat deze gegevens op in Azure Blob Storage voor georganiseerde en beveiligde toegang.
Framework & Tools
- Express.js: een Node.js framework voor het bouwen van webtoepassingen en API's. Het fungeert als de basis voor het instellen van onze server en het verwerken van aanvragen.
- Enorm: een bibliotheek voor het parseren van formuliergegevens, met name ontworpen voor het verwerken van multipart-/form-data, die vaak wordt gebruikt voor het uploaden van bestanden.
- Azure Blob Storage: een Microsoft Azure-service voor de opslag van grote hoeveelheden ongestructureerde gegevens.
Stap 1: Omgeving instellen
Voordat u begint, moet u ervoor zorgen dat uw ontwikkelomgeving gereed is met Node.js geïnstalleerd. U hebt ook toegang nodig tot een Azure Storage-account om de ingediende gegevens op te slaan.
Installeer Node.js: zorg ervoor dat Node.js op uw systeem is geïnstalleerd. U kunt het downloaden van Node.js.
Maak een Azure Blob Storage-account: als u dat nog niet hebt gedaan, maakt u een Azure Storage-account via Azure Portal. Dit account wordt gebruikt voor het opslaan van de gegevens van de ondersteuningsaanvraag.
Benodigde referenties verzamelen: zorg ervoor dat u de verbindingsreeks hebt voor uw Azure Blob Storage-account.
Stap 2: Toepassing instellen
Een nieuw Node.js-project initialiseren:
Maak een nieuwe map voor uw project en initialiseer deze om
npm init
eenpackage.json
bestand te maken.Installeer Express.js, Formidabele, de Azure Storage Blob SDK en andere benodigde bibliotheken met behulp van npm.
npm install express formidable @azure/storage-blob uuid
Server-implementatie:
- Gebruik Express.js om een eenvoudige webserver in te stellen die luistert naar POST-aanvragen op een specifiek eindpunt.
- Gebruik Formidabele voor het parseren van binnenkomende formuliergegevens en het verwerken van inhoud met meerdere onderdelen/formuliergegevens.
- Genereer een uniek ticketnummer voor elke ondersteuningsaanvraag, die kan worden gebruikt om gegevens in Azure Blob Storage te ordenen en een verwijzing voor gebruikers op te geven.
- Sla gestructureerde gegevens, zoals gebruikersberichten en metagegevens van logboekbestanden, op in een JSON-bestand in de Blob Storage. Sla werkelijke logboekbestanden en eventuele schermafbeeldingen of bijlagen op in afzonderlijke blobs in de map van hetzelfde ticket.
- Geef een eindpunt op voor het ophalen van ondersteuningsdetails, waarbij gegevens uit Azure Blob Storage moeten worden opgehaald en weergegeven.
Beveiligingsoverwegingen:
- Zorg ervoor dat uw toepassing de binnenkomende gegevens valideert om te beschermen tegen schadelijke nettoladingen.
- Gebruik omgevingsvariabelen om gevoelige informatie, zoals uw Azure Storage-verbindingsreeks, veilig op te slaan.
Stap 3: de toepassing uitvoeren en testen
Omgevingsvariabelen:
- Stel omgevingsvariabelen in voor uw Azure Blob Storage-verbindingsreeks en andere gevoelige informatie. U kunt bijvoorbeeld een
.env
bestand (en het npm-pakket voor hetdotenv
laden van deze variabelen) gebruiken.
- Stel omgevingsvariabelen in voor uw Azure Blob Storage-verbindingsreeks en andere gevoelige informatie. U kunt bijvoorbeeld een
De server uitvoeren:
- Start uw Node.js toepassing door uit te voeren
node <filename>.js
, waar<filename>
is de naam van uw hoofdserverbestand. - Valideer de server met een geschikt hulpprogramma voor webontwikkeling.
- Start uw Node.js toepassing door uit te voeren
Servercode:
Hier ziet u een werkende implementatie om mee te beginnen. Deze code is een eenvoudige implementatie die is afgestemd op het maken van tickets vanuit de ACS UI-voorbeeldtoepassingen.
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}`);
});
Installatie aan clientzijde
In deze sectie wordt de installatie aan de clientzijde beschreven en wordt uitgelegd hoe u de volgende doelstellingen kunt bereiken:
- Registreren voor door de gebruiker gemelde problemen.
- Serialiseer de gegevens.
- Doorsturen naar de server.
- Een antwoord ontvangen.
- Presenteer het antwoord op de gebruiker.
Voor het inschakelen van gebruikersfeedback in de GEBRUIKERSinterfacebibliotheek van Azure Communication Services (ACS) is actie vereist voor het onderdeel van de ontwikkelaars. Door gebruik te maken van de onUserReportedIssueEventHandler
integratie van de bibliotheek, kunnen ontwikkelaars het ingebouwde ondersteuningsformulier inschakelen, zodat gebruikers problemen rechtstreeks kunnen melden. In deze sectie wordt u begeleid bij het instellen van het feedbackformulier aan de clientzijde.
Feedback vastleggen aan clientzijde implementeren in Android
Het ondersteuningsformulier inschakelen
Registratie van gebeurtenis-handler:
- Als u het ondersteuningsformulier in uw Android-toepassing wilt activeren, registreert u het
onUserReportedIssueEventHandler
op een geschikt punt in de levenscyclus van uw toepassing. Deze registratie maakt niet alleen het formulier mogelijk, maar zorgt er ook voor dat het zichtbaar en toegankelijk is voor de gebruikers.
- Als u het ondersteuningsformulier in uw Android-toepassing wilt activeren, registreert u het
Zichtbaarheid en toegankelijkheid van formulieren:
- De aanwezigheid van het geregistreerde formulier
onUserReportedIssueEventHandler
is rechtstreeks van invloed op de zichtbaarheid van het ondersteuningsformulier. Zonder deze handler blijft het formulier verborgen in de gebruikersinterface, waardoor het niet toegankelijk is voor het melden van problemen.
- De aanwezigheid van het geregistreerde formulier
Ondersteuningsevenementen vastleggen en verwerken
Gebeurtenisuitgifte bij rapportage van problemen:
- Wanneer gebruikers problemen melden via het ingeschakelde ondersteuningsformulier, worden de
onUserReportedIssueEventHandler
gegenereerde gebeurtenissen vastgelegd. Met deze gebeurtenissen worden alle benodigde details ingekapseld met betrekking tot het door de gebruiker gerapporteerde probleem, zoals beschrijvingen, foutenlogboeken en mogelijk schermopnamen.
- Wanneer gebruikers problemen melden via het ingeschakelde ondersteuningsformulier, worden de
Gegevensvoorbereiding voor verzending:
- Zodra een gebruiker een probleem meldt, moet u in de volgende stap de gerapporteerde probleemgegevens voorbereiden voor het indienen van de server. Deze voorbereiding omvat het structureren van de vastgelegde informatie in een indeling die geschikt is voor HTTP-overdracht, die aan de serververwachtingen voldoen.
Probleemgegevens verzenden naar de server
Asynchrone gegevensoverdracht:
- Gebruik asynchrone mechanismen om de voorbereide gegevens naar het aangewezen servereindpunt te verzenden. Deze aanpak zorgt ervoor dat de toepassing responsief blijft en een soepele gebruikerservaring biedt terwijl de gegevens op de achtergrond worden verzonden.
Verwerking van serverreacties:
- Bij het verzenden van gegevens is het van cruciaal belang om serverreacties goed af te handelen. Deze verwerking kan betrekking hebben op het parseren van serverfeedback om te bevestigen dat de gegevens zijn verzonden en mogelijk een verwijzing naar het ingediende probleem (zoals een ticketnummer of URL) te extraheren dat naar de gebruiker kan worden gecommuniceerd.
Feedback en meldingen van gebruikers geven
Directe feedback van gebruikers:
- Informeer gebruikers onmiddellijk over de status van het verzenden van hun probleemrapport via de gebruikersinterface van de toepassing. Voor geslaagde inzendingen kunt u overwegen een verwijzing naar het ingediende probleem op te geven waarmee gebruikers de voortgang van hun rapport kunnen bijhouden.
Meldingsstrategie voor Android O en hoger:
- Voor apparaten met Android O (API-niveau 26) en hoger moet u ervoor zorgen dat er een meldingskanaal wordt geïmplementeerd dat specifiek is voor het indienen van rapporten. Deze installatie is essentieel voor het effectief leveren van meldingen en is een vereiste voor deze Android-versies.
Door deze stappen te volgen, kunnen ontwikkelaars een robuust mechanisme voor feedback van gebruikers integreren in hun Android-toepassingen, met behulp van de onUserReportedIssueEventHandler
methode voor efficiënte rapportage en tracering van problemen. Dit proces vergemakkelijkt niet alleen de tijdige oplossing van gebruikersproblemen, maar draagt ook aanzienlijk bij aan het verbeteren van de algehele gebruikerservaring en tevredenheid met de toepassing.
Voorbeeld van Android-code
Het Codefragment Kotlin demonstreert het proces van het integreren van een systeem voor het afhandelen van door de gebruiker gerapporteerde problemen in een Android-toepassing met behulp van Azure Communication Services. Deze integratie is erop gericht het ondersteuningsproces te stroomlijnen door directe communicatie tussen gebruikers en ondersteuningsteams mogelijk te maken. Hier volgt een overzicht van de betrokken stappen:
Gebeurtenisopname: Het systeem luistert naar door de gebruiker gerapporteerde problemen via de ACS UI-bibliotheek. Het maakt gebruik van de
onUserReportedIssueEventHandler
app om feedback van de gebruikersinterface van de toepassing vast te leggen, inclusief fouten en problemen van gebruikers.Gegevensoverdracht naar server: wanneer een probleem wordt gerapporteerd, worden de relevante gegevens in het systeem verpakt, waaronder gebruikersberichten, foutenlogboeken, versies en diagnostische gegevens. Deze gegevens worden vervolgens verzonden naar een servereindpunt met behulp van een asynchrone POST-aanvraag, zodat het proces de prestaties van de app niet belemmert.
Feedback en meldingen van gebruikers: na de inzending worden gebruikers onmiddellijk geïnformeerd over de status van hun rapport via meldingen in de app. Voor geslaagde inzendingen bevat een melding een koppeling of verwijzing naar het ingediende ticket, zodat gebruikers de voortgang van de oplossing kunnen bijhouden.
Deze installatie helpt niet alleen bij het snel oplossen van gebruikersproblemen, maar draagt ook aanzienlijk bij aan het verbeteren van de tevredenheid van gebruikers en app-betrouwbaarheid door een duidelijk kanaal te bieden voor ondersteuning en feedback.
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)
}
}
Zodra u een handler voor uw gebeurtenis hebt, kunt u deze registreren bij het maken van de samengestelde oproep.
callComposite.addOnUserReportedEventHandler(userReportedIssueEventHandler)
Overzicht van iOS-ondersteuning
Ontwikkelaars moeten een gestructureerde benadering volgen om gebruikersfeedbackverzameling in iOS-toepassingen te integreren met behulp van de UI Library van Azure Communication Services (ACS). Dit proces omvat het vastleggen van gebruikersfeedback, inclusief foutenlogboeken en gebruikersgegevens. Zodra deze gegevens zijn voltooid, worden deze gegevens ter verwerking naar een server verzonden. In deze sectie worden de stappen beschreven die nodig zijn om deze taak uit te voeren.
In dit voorbeeld maken we gebruik van de Library Voor Het afhandelen van het verzenden van een formulier met meerdere onderdelen, inclusief logboekbestanden, naar de server.
Het ondersteuningsformulier implementeren
Registratie van gebeurtenis-handler: begin met het registreren van een gebeurtenis-handler die luistert naar door de gebruiker gerapporteerde problemen. Deze handler is van cruciaal belang voor het rechtstreeks vastleggen van feedback vanuit de interface van uw iOS-toepassing, met behulp van de mogelijkheden van de ACS UI-bibliotheek.
Zichtbaarheid en toegankelijkheid van het formulier: zorg ervoor dat het ondersteuningsformulier gemakkelijk toegankelijk en zichtbaar is voor gebruikers in de toepassing. De activering van het formulier is rechtstreeks gekoppeld aan de implementatie van de gebeurtenis-handler, waardoor het uiterlijk in de gebruikersinterface wordt geactiveerd, zodat gebruikers problemen kunnen melden.
Ondersteuningsaanvragen vastleggen en verwerken
Gebeurtenisuitgifte voor gebruikersactie: wanneer een gebruiker een probleem meldt via het ondersteuningsformulier, legt de gebeurtenis-handler deze actie vast. De informatie, zoals de beschrijving van het probleem, de foutenlogboeken en eventuele aanroep-id's, moet worden voorbereid om naar de server te verzenden.
Gegevensstructuur voor verzending: organiseer de vastgelegde informatie in een gestructureerde indeling die geschikt is voor verzending. Bereid de gegevens op een manier voor die overeenkomt met de verwachte indeling van het servereindpunt dat de ondersteuningsaanvraag ontvangt en verwerkt.
Gegevens verzenden naar de server
Asynchrone verzending: gebruik asynchrone netwerkaanroepen om de gestructureerde gegevens naar de server te verzenden. Deze aanpak zorgt ervoor dat de toepassing responsief blijft en een naadloze ervaring biedt voor de gebruiker terwijl de gegevens op de achtergrond worden verzonden.
Serverreacties verwerken: bij verzending verwerken serverreacties efficiënt. Het antwoord ontvangen en parseren om te bevestigen dat de gegevens zijn ontvangen en geparseerd. Pak de koppeling naar het ondersteuningsticket uit het geparseerde antwoord, dat kan worden teruggestuurd naar de gebruiker voor opvolging.
Feedback en meldingen voor gebruikers
Onmiddellijke bevestiging: bevestig onmiddellijk het indienen van een ondersteuningsaanvraag in de toepassing, zodat gebruikers bevestiging krijgen dat hun rapport is ontvangen.
Meldingsstrategie: implementeer een strategie voor het leveren van meldingen aan gebruikers, met name op apparaten met iOS-versies die specifieke meldingsframeworks ondersteunen. U kunt lokale meldingen gebruiken om gebruikers te informeren over de status van hun rapport of om updates op te geven wanneer hun probleem wordt opgelost.
Voorbeeld van iOS-code
In dit Swift-codevoorbeeld wordt een eenvoudige implementatie beschreven voor het vastleggen van door de gebruiker gerapporteerde problemen en het verzenden ervan naar een server voor verwerking. In dit voorbeeld ziet u hoe u een handler voor ondersteuningsevenementen maakt, inclusief diagnostische gegevens van gebruikers en toepassingsdiagnosegegevens en levering aan de server. De code bevat ook foutafhandeling en strategieën voor gebruikersmeldingen om een soepele gebruikerservaring te garanderen.
Het volgende voorbeeld is ontworpen om een hook te zijn die moet worden geïnstalleerd in uw Event Handler.
Installatie
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
}
}
}
Netwerkhook
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)")
}
}
}
Deze Swift-code demonstreert het proces van het verzenden van door de gebruiker gerapporteerde problemen vanuit een iOS-toepassing met behulp van Azure Communication Services. Het verwerkt het verzamelen van gebruikersfeedback, het verpakken van diagnostische gegevens en asynchrone verzending naar een servereindpunt. Daarnaast biedt het de basis voor het implementeren van feedbackmechanismen, zodat gebruikers op de hoogte worden gesteld van de status van hun rapporten en het verbeteren van de algehele betrouwbaarheid van toepassingen en de tevredenheid van gebruikers.
Conclusie
Het integreren van feedbackmechanismen voor gebruikers in toepassingen met behulp van Azure Communication Services (ACS) is van cruciaal belang voor het ontwikkelen van responsieve en gebruikersgerichte apps. Deze handleiding biedt een duidelijk pad voor het instellen van zowel verwerking aan de serverzijde als Node.js het vastleggen van feedback aan de clientzijde voor Android- en iOS-toepassingen. Dankzij deze integratie kunnen ontwikkelaars de betrouwbaarheid van toepassingen en de tevredenheid van gebruikers verbeteren terwijl ze gebruikmaken van de cloudservices van Azure voor efficiënt gegevensbeheer.
De handleiding bevat praktische stappen voor het vastleggen van feedback van gebruikers, foutenlogboeken en ondersteuningsaanvragen rechtstreeks vanuit toepassingen. Integratie van ondersteuningsgebeurtenissen zorgt voor een veilige en georganiseerde manier om feedback te verwerken, zodat ontwikkelaars snel gebruikersproblemen kunnen oplossen en oplossen, wat leidt tot een verbeterde algehele gebruikerservaring.
Door de instructies in deze handleiding te volgen, kunnen ontwikkelaars de reactiesnelheid van hun toepassingen verbeteren en beter voldoen aan de behoeften van de gebruiker. Deze integraties helpen niet alleen om gebruikersfeedback effectiever te begrijpen, maar ook om cloudservices te gebruiken om een soepel en effectief mechanisme voor het verzamelen en verwerken van feedback te garanderen. Uiteindelijk is het integreren van mechanismen voor gebruikersfeedback essentieel voor het maken van aantrekkelijke en betrouwbare toepassingen die prioriteit geven aan de tevredenheid van gebruikers.