The following code sample shows how to attach a SystemDialog to your UI. The
confirmButton
is labeled "Launch
Settings", and when the confirmButton is
tapped, the Settings app is invoked. The displayPermissionError() function displays the SystemDialog when something goes wrong. This
function can be reused for any error that might occur because a permission has
not been granted by the user. When you call the function, you have to supply the
text of the message that asks the user if there is a permission that has not
been granted.
import bb.system 1.2
// ...
// Attach a system dialog that is used to display
// information about missing permissions.
attachedObjects: [
SystemDialog {
id: errorDialog
title: qsTr("Something went wrong.")
confirmButton.label: qsTr("Launch Settings")
onFinished: {
if (value == SystemUiResult.ConfirmButtonSelection) {
// The app settings object can also
// launch the system settings app.
_appSettings.invokeSystemSettings
("settings://permissions");
}
}
}
]
// This function is called when something goes wrong
// because a permission was not granted.
function displayPermissionError(error) {
errorDialog.body = error +
qsTr(" You have to restart the app " +
"after changing permissions.");
errorDialog.show();
}
For example, your app can call displayPermissionError() when your app fails to save a photo. In
the following code sample, the
photoSaveFailed()
signal triggers a
call to the function to display the dialog box:
onPhotoSaveFailed: {
// The photo couldn't be saved.
// It could be that the permission to
// access shared files was not granted.
// Display a dialog box since this is
// the most likely scenario.
displayPermissionError(qsTr("The photo couldn't be saved. "
+ "Make sure that the access_shared permission is set "))
photoTaken = false;
}
To see a sample app that uses these techniques to check for
ungranted permissions, download the Rundgang sample. To
learn more about system dialogs, see
Dialog boxes, prompts, and toasts and
review the
UI
guidelines for dialog boxes and toasts. To learn more about invoking
the Settings app, see
Invoking core applications.
We're currently working on updating this section.
The following code sample illustrates a way to check for
permissions. The code provides an illustration of how to check the error code
when your app doesn't have the proper permissions for the Camera API. The error
codes are different for different APIs.
If your app tries to use the camera but your app didn't request the use_camera permission, an error code is returned
when you call a function from the Camera library. For this reason, you should
always write your application logic to handle situations when the necessary
permissions aren't available.
#include <assert.h>
#include <bps/bps.h>
#include <bps/dialog.h>
#include <bps/event.h>
#include <bps/navigator.h>
#include <bps/screen.h>
#include <screen/screen.h>
#include <camera/camera_api.h>
#define APP_ZORDER (100)
typedef enum { STATE_STARTUP = 0,
STATE_CAMERA_READY,
STATE_VIEWFINDER,
STATE_TAKINGPHOTO,
STATE_NOPERMISSION
} state_t;
static state_t status = STATE_STARTUP;
static dialog_instance_t alert_dialog = NULL;
static bool shutdown = false;
static screen_context_t screen_ctx;
static const char vf_group[] = "viewfinder_window_group";
static camera_handle_t handle = CAMERA_HANDLE_INVALID;
static int main_bps_chid = -1;
char* messageok = "Good! You have the permissions to use the camera.";
char* messagenopermissions = "Oh no! You do not have permission to use the camera. "
"To change the permissions, go to Settings > Security and "
"Privacy > Application Permissions and grant the Camera "
"permission to this app. Close this app and restart it after "
"you have granted the necessary permissions.";
// NOTE: In this code sample, we are purposely ignoring some error return codes
// for the sake of clarity. In production level code, check the return codes for errors
// to help isolate bugs with your app
static void check_permission()
{
camera_error_t err;
unsigned int num;
unsigned int i;
camera_unit_t cams[CAMERA_UNIT_NUM_UNITS];
camera_unit_t unit;
// Select a camera unit
unit = CAMERA_UNIT_REAR;
fprintf(stderr, "selecting camera unit %d\n", unit);
err = camera_open(unit,
CAMERA_MODE_RW | CAMERA_MODE_ROLL,
&handle);
if (err == CAMERA_EOK) {
// Set the message to indicate that you have the required permissions.
// In production code, an error message isn't necessary
status= STATE_CAMERA_READY;
}
if (err == CAMERA_EACCESS){
// Set the state to indicate that the required permissions are not available
fprintf(stderr, "camera_open() - no permission: %d\n", err);
status=STATE_NOPERMISSION;
}
return;
}
// This function is used to show the dialog box with the error messages
static int setAndDisplayDialog()
{
// Set the message to display to determine whether you have permissions
char* displaymessage = "";
if (status == STATE_CAMERA_READY)
displaymessage = messageok;
else if (status == STATE_NOPERMISSION)
displaymessage = messagenopermissions;
else
displaymessage = "Not a permission issue.";
// Create a dialog box to display the error message.
if (dialog_create_alert(&alert_dialog) != BPS_SUCCESS) {
fprintf(stderr, "Failed to create alert dialog.\n");
return -1;
}
if (dialog_set_alert_message_text(alert_dialog, displaymessage) != BPS_SUCCESS) {
fprintf(stderr, "Failed to set alert dialog message text.\n");
dialog_destroy(alert_dialog);
alert_dialog = 0;
}
if (dialog_add_button (alert_dialog, DIALOG_CANCEL_LABEL,
true, NULL, true) != BPS_SUCCESS) {
fprintf(stderr, "Failed to add button to alert dialog.\n");
dialog_destroy(alert_dialog);
alert_dialog = 0;
return -1;
}
if (dialog_show(alert_dialog) != BPS_SUCCESS) {
fprintf(stderr, "Failed to show alert dialog.\n");
dialog_destroy(alert_dialog);
alert_dialog = 0;
}
}
int main(int argc, char **argv) {
const int usage = SCREEN_USAGE_NATIVE;
status = STATE_STARTUP;
screen_window_t screen_win;
screen_buffer_t screen_buf = NULL;
int rect[4] = { 0, 0, 0, 0 };
int i = APP_ZORDER;
// Create an application window that acts as a background
screen_create_context(&screen_ctx, 0);
screen_create_window(&screen_win, screen_ctx);
screen_create_window_group(screen_win, vf_group);
screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage);
screen_create_window_buffers(screen_win, 1);
screen_get_window_property_pv(screen_win,
SCREEN_PROPERTY_RENDER_BUFFERS,
(void **)&screen_buf);
screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, rect+2);
// Fill the window with black
int attribs[] = { SCREEN_BLIT_COLOR, 0x00000000, SCREEN_BLIT_END };
screen_fill(screen_ctx, screen_buf, attribs);
screen_post_window(screen_win, screen_buf, 1, rect, 0);
// Position the window at an arbitrary z-order
screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ZORDER, &i);
// Request that navigator, dialog, and screen events are sent
bps_initialize();
main_bps_chid = bps_channel_get_active();
screen_request_events(screen_ctx);
// Request that events are sent. A value of 0 indicates that
// all events are requested
dialog_request_events(0);
navigator_request_events(0);
// Call the function to check for permissions
check_permission();
setAndDisplayDialog();
while (!shutdown) {
bps_event_t *event = NULL;
// The value of -1 means that the function waits
// for an event before returning
bps_get_event(&event, -1);
// Event loop to receive BPS events. In this scenario,
// receive an event to display the dialog box
if (event) {
if (bps_event_get_domain(event) == dialog_get_domain()) {
int selectedIndex =
dialog_event_get_selected_index(event);
const char* label =
dialog_event_get_selected_label(event);
const char* context =
dialog_event_get_selected_context(event);
// Further handle and process dialog event here.
//...
}
//
// App logic in the event loop
// ...
//
}
//
// App logic in the event loop
// ...
//
}
// Clean up when the app is closed or the main loop exits
screen_stop_events(screen_ctx);
bps_shutdown();
screen_destroy_window(screen_win);
screen_destroy_context(screen_ctx);
return 0;
}