Feedback in iOS and Android Apps
Add thumbs, a marked-up screenshot and screen recordings to a native app, sent to the same inbox as your site.
Add the Swift package or the dev.qaid:feedback library, configure it with your embed key, and call present from a Send feedback button. The person marks up a screenshot or records the screen, and the report lands in your inbox with the app version, device and recent errors.
App reports and site reports share one inbox, one key and one plan.
Install the SDK
| iOS | Android | |
|---|---|---|
| Get it | Swift Package Manager: https://github.com/qaiddev/qaid-native |
implementation("dev.qaid:feedback:0.2.0") |
| Needs | iOS 15 or later | minSdk 26, compileSdk 35 or later |
Both use your project’s embed key, the same one the web embed uses. Find it under the project’s Settings → API Keys. The key only sends feedback, so it is safe inside an app.
Show the sheet
Configure once at launch
On iOS, call
QaidFeedback.configurein your app delegate orAppinit. On Android, call it inApplication.onCreateand pass the application as the first argument.Call present from a button
Put a Send feedback item in a menu or settings screen and call
QaidFeedback.present. Passscreento say where the person was.Send a test report
Run the app, tap the button and send. The report shows in the project’s inbox.
import QaidFeedback
QaidFeedback.configure(QaidConfiguration(
apiKey: "YOUR_EMBED_KEY",
appName: "My App"
))
QaidFeedback.present(screen: "Settings")
QaidFeedback.configure(this, QaidConfig(
apiKey = "YOUR_EMBED_KEY",
appName = "My App",
))
QaidFeedback.present(activity, screen = "Settings")
The project’s Customize page prints both with your key in place. Open the iOS or Android tab under THUMBS CODE.
What the person sees
The SDK takes a screenshot first, so the sheet is never in it. Then the sheet opens with the screenshot, the thumbs and a message box. Mark up opens the same editor as the web embed: boxes, arrows, a pen, and a redact tool to black out anything private.
Record screen closes the sheet and records the app. The person stops the recording, and the sheet comes back with the clip attached.
Recordings need Pro, as on the web. On Free the app says screen recordings aren’t available and offers a screenshot instead.
What reaches your inbox
Open a report and Details lists the app as CinemaCrew 1.4 (812), the device as iPhone16,1 · iOS 18.2, the screen and the locale. Tell it who is signed in and anything else you want beside each report:
QaidFeedback.setUser(id: "u_42", email: "sam@example.com", name: "Sam")
QaidFeedback.setMetadata(key: "plan", value: "pro")
QaidFeedback.log("Sync failed", level: .error)
Console Errors holds recent warnings and errors from the app’s own log plus your log lines. Network Errors holds failed calls you report. Only the method, the address without its query string, and the status are kept.
val client = OkHttpClient.Builder()
.addInterceptor(QaidFeedback.networkInterceptor())
.build()
On iOS, call QaidFeedback.record(request:response:error:) where your requests finish.
Hide private screens
Mark a view as sensitive and it is blacked out in screenshots and covered while recording. Password fields are covered without being marked.
cardNumberField.qaidSensitive = true
Domain Restriction
A project with a Domain Restriction checks app reports too. By default the SDK names the app by its bundle id, and qaid reads the id back to front: com.example.myapp passes a restriction of example.com. If your app’s id doesn’t match your domain, give the SDK an address on the domain instead:
QaidConfiguration(apiKey: "YOUR_EMBED_KEY",
pageUrl: URL(string: "https://example.com/app/ios"),
appName: "My App")
Offline, quests and your own words
A report sent with no connection is saved and sent later. That happens at the next launch, when the app comes back to the front, or when the network returns.
Link quests with quests: QaidQuestLinks(up:, down:, video:) and the quest opens once the report is sent.
Every string on the sheet can be replaced through text, so the sheet can match your app’s language. The full list of options is in the SDK readme.