> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# v3-4 Client SDK Reference

> Comprehensive reference of OneSignal's SDK methods

<Warning>
  The methods below require the OneSignal SDK versions 3 & 4.

  It is recommended to upgrade to our latest version 5 SDKs for User Model APIs.

  See [Update to User Model](/docs/en/user-model-migration-guide) for migration steps.
</Warning>

# Initializing OneSignal

These methods serve as a reference and are just a single step in the set up process. Make sure to follow the steps for your particular configuration here:

* [Mobile Push Set Up](/docs/en/mobile-sdk-setup)
* [Web Push Set Up](/docs/en/web-push-setup)

<CodeGroup>
  ```java Java/Kotlin theme={null}
  //See Android SDK Setup for details https://documentation.onesignal.com/docs/en/android-sdk-setup
  OneSignal.initWithContext(this);
  OneSignal.setAppId(ONESIGNAL_APP_ID);
  ```

  ```swift Swift theme={null}
  //See iOS SDK Setup for details https://documentation.onesignal.com/docs/en/ios-sdk-setup
  OneSignal.initWithLaunchOptions(launchOptions)
  OneSignal.setAppId("YOUR_ONESIGNAL_APP_ID")
  ```

  ```objectivec Objective-C (AppDelegate.m) theme={null}
  //See iOS SDK Setup for details https://documentation.onesignal.com/docs/en/ios-sdk-setup
  [OneSignal initWithLaunchOptions:launchOptions];
  [OneSignal setAppId:@"YOUR_ONESIGNAL_APP_ID"];
  ```

  ```csharp Unity(C#) theme={null}
  OneSignal.Default.Initialize("your_app_id");
  ```

  ```javascript React Native theme={null}
  /* This is for Expo Bare Workflows. If using a managed workflow,
  see the Expo set up guide (https://documentation.onesignal.com/docs/en/react-native-expo-sdk-setup)*/

  //Place code in your index.js/main.js
  OneSignal.setAppId("YOUR-ONESIGNAL-APP-ID");
  ```

  ```javascript Flutter theme={null}
  //Remove this method to stop OneSignal Debugging 
  OneSignal.shared.setLogLevel(OSLogLevel.verbose, OSLogLevel.none);

  OneSignal.shared.setAppId("YOUR_ONESIGNAL_APP_ID");

  // The promptForPushNotificationsWithUserResponse function will show the iOS push notification prompt. We recommend removing the following code and instead using an In-App Message to prompt for notification permission
  OneSignal.shared.promptUserForPushNotificationPermission().then((accepted) {
  	print("Accepted permission: $accepted");
  });
  ```

  ```javascript Cordova theme={null}
  window.plugins.OneSignal.setAppId("YOUR_ONESIGNAL_APP_ID");
  ```
</CodeGroup>

<Warning>
  We have a number of SDK's with multiple options for initialization within. If you don't see an init method listed for your particular environment, please follow the links above!
</Warning>

# Debugging

## `setLogLevel` Method

Enable logging to help debug if you run into an issue setting up OneSignal. This selector is static, so you can call it before OneSignal init. For websites see [Debugging with Browser Tools](/docs/en/troubleshooting-web-push).

| Parameters    | Type       | Description                                                             |
| ------------- | ---------- | ----------------------------------------------------------------------- |
| `logLevel`    | LOG\_LEVEL | Sets the logging level to print to the Android LogCat log or Xcode log. |
| `visualLevel` | LOG\_LEVEL | Sets the logging level to show as alert dialogs.                        |

<CodeGroup>
  ```java java theme={null}
  //The following options are available with increasingly more information:
  //NONE, FATAL, ERROR, WARN, INFO, DEBUG, VERBOSE
  OneSignal.setLogLevel(OneSignal.LOG_LEVEL.VERBOSE, OneSignal.LOG_LEVEL.NONE);
  ```

  ```swift Swift theme={null}
  //The following options are available with increasingly more information: 
  //.LL_NONE, .LL_FATAL, .LL_ERROR, .LL_WARN, .LL_INFO, .LL_DEBUG, .LL_VERBOSE.
  OneSignal.setLogLevel(.LL_VERBOSE, visualLevel: .LL_NONE)
  ```

  ```objectivec objectivec theme={null}
  ////The following options are available with increasingly more information: 
  //ONE_S_LL_NONE, ONE_S_LL_FATAL, ONE_S_LL_ERROR, ONE_S_LL_WARN, ONE_S_LL_INFO, ONE_S_LL_DEBUG, ONE_S_LL_VERBOSE.
  [OneSignal setLogLevel:ONE_S_LL_VERBOSE visualLevel:ONE_S_LL_NONE];
  ```

  ```csharp Unity (C#) theme={null}
  //The following options are available with increasingly more information:
  //None, Fatal, Error, Warn, Info, Debug, Verbose
  OneSignal.Default.LogLevel = LogLevel.Info;
  OneSignal.Default.AlertLevel = LogLevel.Error;
  ```

  ```javascript React Native theme={null}
  //The following options are available with increasingly more information: 
  //0 = NONE, 1 = FATAL, 2 = ERROR, 3 = WARN, 4 = INFO, 5 = DEBUG, 6 = VERBOSE
  OneSignal.setLogLevel(6, 0);
  ```

  ```javascript Flutter theme={null}
  //The following options are available with increasingly more information:
  //none, fatal, error, warn, info, debug, verbose
  OneSignal.shared.setLogLevel(OSLogLevel.verbose, OSLogLevel.none);
  ```

  ```javascript Cordova/Ionic theme={null}
  //The following options are available with increasingly more information: 
  //0 = NONE, 1 = FATAL, 2 = ERROR, 3 = WARN, 4 = INFO, 5 = DEBUG, 6 = VERBOSE
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  window.plugins.OneSignal.setLogLevel({logLevel: 6, visualLevel: 0});
  ```

  ```csharp Xamarin theme={null}
  //The following options are available with increasingly more information:
  //NONE, FATAL, ERROR, WARN, INFO, DEBUG, VERBOSE
  // Needs: using Com.OneSignal.Abstractions;
  OneSignal.Default.LogLevel = LogLevel.VERBOSE;
  ```

  ```lua Corona theme={null}
  -- The following options are available with increasingly more information:
  --0 = NONE, 1 = FATAL, 2 = ERROR, 3 = WARN, 4 = INFO, 5 = DEBUG, 6 = VERBOSE
  OneSignal.SetLogLevel(6, 0)
  ```
</CodeGroup>

***

# External User Ids

OneSignal creates and stores device & channel level data under a unique OneSignal Id called the `subscription_id` (formerly called`player_id`). A single user can have multiple `subscription_id` records based on how many devices, email addresses, and phone numbers they use to interact with your app/site.

You can combine `subscription_id` records in OneSignal under a unique User Id called the `external_id`.

See the [External User Ids](/docs/en/users) guide for more details.

If you have a backend server, we strongly recommend using [Identity Verification](/v9.0/docs/identity-verification) with your users. Your backend can generate an ***identifier authentication token*** and send it to your site.

The OneSignal SDK `setExternalUserId` method should be called when the user logs into the app/site and within the callback of the `setEmail` and `setSMSNumber` methods to link the records together.

<CodeGroup>
  ```javascript Web (js) theme={null}
  let externalUserId = "123456789"; // You will supply the external user id to the OneSignal SDK

  OneSignal.push(function() {
    OneSignal.setExternalUserId(externalUserId);
  });
  ```

  ```java java theme={null}
  String externalUserId = "123456789"; // You will supply the external user id to the OneSignal SDK

  // Setting External User Id with Callback Available in SDK Version 4.0.0+
  OneSignal.setExternalUserId(externalUserId, new OneSignal.OSExternalUserIdUpdateCompletionHandler() {
      @Override
      public void onSuccess(JSONObject results) {
          try {
              if (results.has("push") && results.getJSONObject("push").has("success")) {
                  boolean isPushSuccess = results.getJSONObject("push").getBoolean("success");
                  OneSignal.onesignalLog(OneSignal.LOG_LEVEL.VERBOSE, "Set external user id for push status: " + isPushSuccess);
              }
          } catch (JSONException e) {
              e.printStackTrace();
          }

          try {
              if (results.has("email") && results.getJSONObject("email").has("success")) {
                  boolean isEmailSuccess = results.getJSONObject("email").getBoolean("success");
                  OneSignal.onesignalLog(OneSignal.LOG_LEVEL.VERBOSE, "Set external user id for email status: " + isEmailSuccess);
              }
          } catch (JSONException e) {
              e.printStackTrace();
          }
          try {
              if (results.has("sms") && results.getJSONObject("sms").has("success")) {
                  boolean isSmsSuccess = results.getJSONObject("sms").getBoolean("success");
                  OneSignal.onesignalLog(OneSignal.LOG_LEVEL.VERBOSE, "Set external user id for sms status: " + isSmsSuccess);
              }
          } catch (JSONException e) {
              e.printStackTrace();
          }
      }

      @Override
      public void onFailure(OneSignal.ExternalIdError error) {
          // The results will contain channel failure statuses
          // Use this to detect if external_user_id was not set and retry when a better network connection is made
          OneSignal.onesignalLog(OneSignal.LOG_LEVEL.VERBOSE, "Set external user id done with error: " + error.toString());
      }
  });
  ```

  ```swift Swift theme={null}
  let externalUserId = "123456789" // You will supply the external user id to the OneSignal SDK

  // Setting External User Id with Callback Available in SDK Version 3.0.0+
  OneSignal.setExternalUserId(externalUserId, withSuccess: { results in
      // The results will contain push and email success statuses
      print("External user id update complete with results: ", results!.description)
      // Push can be expected in almost every situation with a success status, but
      // as a pre-caution its good to verify it exists
      if let pushResults = results!["push"] {
          print("Set external user id push status: ", pushResults)
      }
      if let emailResults = results!["email"] {
          print("Set external user id email status: ", emailResults)
      }
      if let smsResults = results!["sms"] {
          print("Set external user id sms status: ", smsResults)
      }
  }, withFailure: {error in
      print("Set external user id done with error: " + error.debugDescription)
  })
  ```

  ```objectivec objectivec theme={null}
  NSString* externalUserId = @"123456789"; // You will supply the external user id to the OneSignal SDK

  // Setting External User Id with Callback Available in SDK Version 3.0.0+
  [OneSignal setExternalUserId:externalUserId withSuccess:^(NSDictionary *results) {
      // The results will contain push and email success statuses
      NSLog(@"External user id update complete with results: %@", results.description);
      // Push can be expected in almost every situation with a success status, but
      // as a pre-caution its good to verify it exists
      if (results[@"push"] && results[@"push"][@"success"])
        NSLog(@"Set external user id push status: %@", results[@"push"][@"success"]);
      // Verify the email is set or check that the results have an email success status
      if (results[@"email"] && results[@"email"][@"success"])
        NSLog(@"Set external user id email status: %@", results[@"email"][@"success"]);
      // Verify the number is set or check that the results have an sms success status
      if (results[@"sms"] && results[@"sms"][@"success"])
        NSLog(@"Set external user id sms status: %@", results[@"sms"][@"success"]);
  } withFailure:^(NSError *error) {
        NSLog(@"External user id update failed with error: %@", error);
  }];
  ```

  ```csharp Unity-C# theme={null}
  OneSignal.Default.SetExternalUserId("123456789");
  // or
  var result = await OneSignal.Default.SetExternalUserId("123456789");
  if (result) {
      Debug.Log("success");
  }
  ```

  ```javascript React Native theme={null}
  let externalUserId = '123456789'; // You will supply the external user id to the OneSignal SDK

  // Setting External User Id with Callback Available in SDK Version 3.9.3+
  OneSignal.setExternalUserId(externalUserId, (results) => {
    // The results will contain push and email success statuses
    console.log('Results of setting external user id');
    console.log(results);
    
    // Push can be expected in almost every situation with a success status, but
    // as a pre-caution its good to verify it exists
    if (results.push && results.push.success) {
      console.log('Results of setting external user id push status:');
      console.log(results.push.success);
    }
    
    // Verify the email is set or check that the results have an email success status
    if (results.email && results.email.success) {
      console.log('Results of setting external user id email status:');
      console.log(results.email.success);
    }

    // Verify the number is set or check that the results have an sms success status
    if (results.sms && results.sms.success) {
      console.log('Results of setting external user id sms status:');
      console.log(results.sms.success);
    }
  });
  ```

  ```javascript Flutter theme={null}
  let externalUserId = '123456789'; // You will supply the external user id to the OneSignal SDK

  // Setting External User Id with Callback Available in SDK Version 3.9.3+
  OneSignal.shared.setExternalUserId(externalUserId).then((results) {
    log(results.toString());
  }).catchError((error) {
    log(error.toString());
  });
  ```

  ```javascript Cordova/Ionic theme={null}
  let externalUserId = '123456789'; // You will supply the external user id to the OneSignal SDK

  // Setting External User Id with Callback Available in SDK Version 2.11.2+
  window.plugins.OneSignal.setExternalUserId(externalUserId, (results) => {
    // The results will contain push and email success statuses
    console.log('Results of setting external user id');
    console.log(results);
    
    // Push can be expected in almost every situation with a success status, but
    // as a pre-caution its good to verify it exists
    if (results.push && results.push.success) {
      console.log('Results of setting external user id push status:');
      console.log(results.push.success);
    }
    
    // Verify the email is set or check that the results have an email success status
    if (results.email && results.email.success) {
      console.log('Results of setting external user id email status:');
      console.log(results.email.success);
    }

    // Verify the number is set or check that the results have an sms success status
    if (results.sms && results.sms.success) {
      console.log('Results of setting external user id sms status:');
      console.log(results.sms.success);
    }
  });
  ```

  ```csharp Xamarin theme={null}
  string externalUserId = "123456789"; // You will supply the external user id to the OneSignal SDK

  // Setting External User Id with Callback Available in SDK Version 3.8.0+
  OneSignal.Current.SetExternalUserId(externalId);

  //Callback available in SDK Version 3.8.0+
  private static void OneSignalSetExternalUserId(Dictionary<string, object> results)
  {
    // The results will contain push and email success statuses
    Debug.WriteLine("External user id updated with results: " + Json.Serialize(results));
    // Push can be expected in almost every situation with a success status, but
    // as a pre-caution its good to verify it exists
    if (results.ContainsKey("push"))
    {
      Dictionary<string, object> pushStatusDict = results["push"] as Dictionary<string, object>;
      if (pushStatusDict.ContainsKey("success"))
      {
        Debug.WriteLine("External user id updated for push with results: " + pushStatusDict["success"] as string);
      }
    }
    // Verify the email is set or check that the results have an email success status
    if (results.ContainsKey("email"))
    {
      Dictionary<string, object> emailStatusDict = results["email"] as Dictionary<string, object>;
      if (emailStatusDict.ContainsKey("success"))
      {
        Debug.WriteLine("External user id updated for email with results: " + emailStatusDict["success"] as string);
      }
    }
  }
  ```
</CodeGroup>

If you have a backend server, we strongly recommend using [Identity Verification](/v9.0/docs/identity-verification) with your users. Your backend can generate an ***identifier authentication token*** and send it to your site.

<Warning>
  The OneSignal Android SDKs leverage cacheing on `external_user_id` and [Tags](/docs/en/add-user-data-tags).

  If setting `external_user_id` through the [Edit device](/reference/edit-device) API Endpoint, then use the same endpoint to remove the `external_user_id` upon the user logging out of the app.

  The `removeExternalUserId` method will not work unless the `external_user_id` is set first with the `setExternalUserId` method on Android.

  This is only applicable on the OneSignal Android Mobile App SDKs.
</Warning>

***

# Tags

Tags are custom `key : value` pairs of string or number data you set on users based on events or user data of your choosing. See [Tags Overview](/docs/en/add-user-data-tags) for more details on what tags are used for.

See [Data Tag Implementation](/docs/en/add-user-data-tags) for SDK Method details.

***

# User Data

Methods to get the OneSignal Subscription ID, subscription status, prompt status and push token.

Use `addPermissionObserver` or `addSubscriptionObserver` to react to changes. For example, update your server when the user becomes subscribed or unsubscribed, and to get the OneSignal Subscription Id.

If you need to store the OneSignal Subscription Id within your backend, you can make a REST API call directly from the observer's callback. The OneSignal observer fires only when there is a change (including not firing even if the app has been restarted). This helps ensure you are not making unnecessary network calls to your backend on each app restart if nothing changed.

## Getting User Properties

### Push Notification Properties

<Warning>
  If getDeviceState() is called too early it will be `null` or no available. Use to load your UI to the correct state. Such as showing a toggle button to enable notifications.
</Warning>

<CodeGroup>
  ```java java theme={null}
  // Returns an `OSDeviceState` object with the current immediate device state info
  OSDeviceState device = OneSignal.getDeviceState(); 

  //Get the OneSignal Push Subscription Id
  String userId = device.getUserId();

  //Get device's push token identifier
  String getPushToken = device.getPushToken();

  //Get whether notifications are enabled on the device at the app level
  boolean areNotificationsEnabled = device.areNotificationsEnabled();

  //The device's push subscription status
  boolean isSubscribed = device.isSubscribed();

  //Returns value of pushDisabled method
  boolean isPushDisabled = device.isPushDisabled();
  ```

  ```swift Swift theme={null}
  //Returns an `OSDeviceState` object with the current immediate device state info
  if let deviceState = OneSignal.getDeviceState() {
     //Status of ability to send push notifications to the current device (See status chart below)
     let notificationPermissionStatus = deviceState.notificationPermissionStatus.rawValue
     print("Device's notification permission status: ", notificationPermissionStatus)

     // Get the OneSignal Push Player Id
     let userId = deviceState.userId
     print("OneSignal Push Player ID: ", userId ?? "called too early, not set yet")

     //Get device's push token identifier
     let pushToken = deviceState.pushToken
     print("Device's push token: ", pushToken ?? "called too early or not set yet" )

     // Get whether notifications are enabled on the device at the app level
     let hasNotificationPermission = deviceState.hasNotificationPermission
     print("Has device allowed push permission at some point: ", hasNotificationPermission)

     // The device's push subscription status
     let isSubscribed = deviceState.isSubscribed
     print("Device is subscribed to push notifications: ", isSubscribed)

     // Returns value of pushDisabled method
     let isPushDisabled = deviceState.isPushDisabled
     print("Push notifications are disabled with disablePush method: ", isPushDisabled)
  }
  ```

  ```objectivec Objective-C theme={null}
  // Returns an `OSDeviceState` object with the current immediate device state info
  OSDeviceState *deviceState = [OneSignal getDeviceState];

  //Get the OneSignal Push Player Id
  NSString *userId = deviceState.userId;

  //Get device's push token identifier
  NSString *pushToken = deviceState.pushToken;

  //The device's push subscription status
  BOOL subscribed = deviceState.isSubscribed;
  ```

  ```csharp Unity (C#) theme={null}
  //Status of ability to send push notifications to the current device (See status chart below)
  var currentStatus = OneSignal.Default.NotificationPermission;
  if (currentStatus == NotificationPermission.NotDetermined) {
      // do if user was not prompted
  }

  //The unique OneSignal id of this subscription
  var pushUserId = OneSignal.Default.PushSubscriptionState.userId;
    
  //The device's push subscription status
  var pushState = OneSignal.Default.PushSubscriptionState;
    
  //The unique token provided by the device's operating system used to send push notifications
  var pushToken = OneSignal.Default.PushSubscriptionState.pushToken;
    
  //Returns value of pushDisabled method
  var isPushDisabled = OneSignal.Default.PushSubscriptionState.isPushDisabled;
  ```

  ```javascript React Native theme={null}
  // Returns an `OSDeviceState` object with the current immediate device state info
  const deviceState = await OneSignal.getDeviceState();
  ```

  ```javascript Flutter theme={null}
  // Returns an `OSDeviceState` object with the current immediate device state info
  OneSignal.shared.getDeviceState().then((deviceState) {
       print("OneSignal: device state: ${deviceState.jsonRepresentation()}");
  });

  /The unique OneSignal id of this subscription

  var playerId = deviceState?.userId;

  //Get device's push token identifier

    var pushToken = deviceState?.pushToken;

  //The device's push subscription status

  var pushState = deviceState?.subscribed;
  ```

  ```javascript Cordova theme={null}
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  window.plugins.OneSignal.getDeviceState(function(stateChanges) {
    console.log('OneSignal getDeviceState: ' + JSON.stringify(stateChanges));
  });
  ```
</CodeGroup>

#### Notification Permission Statuses

| Name               | Status                                                                                                                               |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| 0 - Not Determined | The user hasn't yet made a choice about whether the app is allowed to schedule notifications.                                        |
| 1 - Denied         | The application is not authorized to post user notifications.                                                                        |
| 2 - Authorized     | The application is authorized to post user notifications.                                                                            |
| 3 - Provisional    | The application is provisionally authorized to post noninterruptive user notifications.                                              |
| 4 - Ephemeral      | For [App Clips](/docs/en/app-clip-support). The app is authorized to schedule or receive notifications for a limited amount of time. |

### Email User Properties

<CodeGroup>
  ```java java theme={null}
  //The following methods are only available if `SetEmail` was called
  // Returns an `OSDeviceState` object with the current immediate device state info
  OSDeviceState device = OneSignal.getDeviceState(); 

  //Get the OneSignal Email Subscription Id
  String emailUserId = device.getEmailUserId();

  //Get the email address tied to the device
  String emailAddress = device.getEmailAddress();

  //This device's email subscription status
  boolean isEmailSubscribed = device.isEmailSubscribed();
  ```

  ```swift Swift theme={null}
  //The following methods are only available if `SetEmail` was called

  if let deviceState = OneSignal.getDeviceState() {
     //Get the OneSignal Email Player Id
     let emailAddress = deviceState.emailAddress
     print("Email Address tied to this device with setEmail: ", emailAddress ?? "called too early or not set yet" )

     //Get the email address tied to the device
     let emailUserId = deviceState.emailUserId
     print("OneSignal Email player ID: ", emailUserId ?? "called too early or not set yet")

     //This device's email subscription status
     let isEmailSubscribed = deviceState.isEmailSubscribed
     print("is the email address tied to this record subscribed to receive email: ", isEmailSubscribed) 		
  }
  ```

  ```csharp Unity (C#) theme={null}
  //The following methods are only available if `SetEmail` was called

  //Get the OneSignal Email Player Id
  var emailUserId = OneSignal.Default.EmailSubscriptionState.emailUserId

  //Get the email address tied to the device
  var emailAddress = OneSignal.Default.EmailSubscriptionState.emailAddress
    
  //This device's email subscription status
  var isSubscribed = OneSignal.Default.EmailSubscriptionState.isSubscribed
  ```
</CodeGroup>

### SMS User Properties

<CodeGroup>
  ```java java theme={null}
  //The following methods are only available if `SetSMSNumber` was called
  // Returns an `OSDeviceState` object with the current immediate device state info
  OSDeviceState device = OneSignal.getDeviceState(); 

  // Get the SMS Phone Number tied to the device. Only available if OneSignal.setSMSNumber() was called.
  String smsUserId = device.getSMSUserId();

  //Get the phone number tied to the device
  String smsNumber = device.getSMSNumber();

  //This device's SMS subscription status
  boolean isSMSSubscribed = device.isSMSSubscribed();
  ```

  ```swift Swift theme={null}
  //The following methods are only available if `SetSMSNumber` was called

  if let deviceState = OneSignal.getDeviceState() {
  	 //Get the OneSignal SMS Player Id
     let smsUserId = deviceState.smsUserId
     print("OneSignal SMS player ID: ", smsUserId ?? "called too early or not set yet")
    
     //Get the phone number tied to the device
     let smsNumber = deviceState.smsNumber
     print("Phone Number tied to this device with setSMSNumber: ", smsNumber ?? "called too early or not set yet" )
    
     //This device's SMS subscription status
     let isSMSSubscribed = deviceState.isSMSSubscribed
     print("is the phone number tied to this record subscribed to receive sms: ", isSMSSubscribed)
  }
  ```

  ```csharp Unity (C#) theme={null}
  //The following methods are only available if `SetSMSNumber` was called

  //Get the OneSignal SMS Player Id
  string smsUserId = OneSignal.Default.SMSSubscriptionState.smsUserId

  //Get the phone number tied to the device
  string smsNumber = OneSignal.Default.SMSSubscriptionState.smsNumber
    
  //This device's SMS subscription status
  bool isSubscribed = OneSignal.Default.SMSSubscriptionState.isSubscribed
  ```
</CodeGroup>

## User Data Change Events

### Handling Notification Permission Changes

The `onOSPermissionChanged` method will be fired on the passed-in object when a notification permission setting changes.

This includes the following events:

* Notification permission prompt shown (iOS)
* The user accepting or declining the permission prompt (iOS)
* Enabling or disabling notifications for your app in the App Settings and after returning to your app

Instance is given to your `onOSPermissionChanged` method, which provides what the value was (**"from"**) and what the value is now (**"to"**).

Any object implementing the `OSPermissionObserver` and/or the `OSSubscriptionObserver` protocols can be added as an observer. You can call `removePermissionObserver` to remove any existing listeners.

OneSignal uses a weak reference to the observer to prevent leaks.

<CodeGroup>
  ```java java theme={null}
  public class MainActivity extends Activity implements OSPermissionObserver {
    protected void onCreate(Bundle savedInstanceState) {
      OneSignal.addPermissionObserver(this);
    }
    
    public void onOSPermissionChanged(OSPermissionStateChanges stateChanges) {
      if (stateChanges.getFrom().getEnabled() &&
          !stateChanges.getTo().getEnabled()) {
           new AlertDialog.Builder(this)
               .setMessage("Notifications Disabled!")
               .show();
        }
     
        Log.i("Debug", "onOSPermissionChanged: " + stateChanges);
    }
  }

  // Example Logcat entry - User disabling notifications then returning to your app.
  // onOSPermissionChanged{"from":{"enabled":true},"to":{"enabled":false}}
  ```

  ```swift Swift theme={null}
  // AppDelegate.swift
  // Add OSPermissionObserver after UIApplicationDelegate
  class AppDelegate: UIResponder, UIApplicationDelegate, OSPermissionObserver {

     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Add your AppDelegate as an obsserver
        OneSignal.add(self as OSPermissionObserver)
     }

     // Add this new method
     func onOSPermissionChanged(_ stateChanges: OSPermissionStateChanges!) {
        // Example of detecting answering the permission prompt
        if stateChanges.from.status == OSNotificationPermission.notDetermined {
           if stateChanges.to.status == OSNotificationPermission.authorized {
              print("Thanks for accepting notifications!")
           } else if stateChanges.to.status == OSNotificationPermission.denied {
              print("Notifications not accepted. You can turn them on later under your iOS settings.")
           }
        }
        // prints out all properties
        print("PermissionStateChanges: \n\(stateChanges)")
     }

     // Output:
     /*
     Thanks for accepting notifications!
     PermissionStateChanges:
     Optional(<OSSubscriptionStateChanges:
     from: <OSPermissionState: hasPrompted: 0, status: NotDetermined>,
     to:   <OSPermissionState: hasPrompted: 1, status: Authorized>
     >
     */
  }
  ```

  ```objectivec objectivec theme={null}
  // AppDelegate.h
  // Add OSPermissionObserver after UIApplicationDelegate
  @interface AppDelegate : UIResponder <UIApplicationDelegate, OSPermissionObserver>
  @end

  // AppDelegate.m
  @implementation AppDelegate
    
  - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Add your AppDelegate as an obsserver
    [OneSignal addPermissionObserver:self];
  }

  // Add this new method
  - (void)onOSPermissionChanged:(OSPermissionStateChanges*)stateChanges {
    
      // Example of detecting anwsering the permission prompt
      if (stateChanges.from.status == OSNotificationPermissionNotDetermined) {
        if (stateChanges.to.status == OSNotificationPermissionAuthorized)
           NSLog(@"Thanks for accepting notifications!");
        else if (stateChanges.to.status == OSNotificationPermissionDenied)
           NSLog(@"Notifications not accepted. You can turn them on later under your iOS settings.");
      }
      
     // prints out all properties 
     NSLog(@"PermissionStateChanges:\n%@", stateChanges);
  }

  // Output:
  /*
  Thanks for accepting notifications!
  PermissionStateChanges:
  <OSSubscriptionStateChanges:
  from: <OSPermissionState: hasPrompted: 1, status: NotDetermined>,
  to:   <OSPermissionState: hasPrompted: 1, status: Authorized>
  >
  */

  @end
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Default.NotificationPermissionChanged += (current, previous) => {
      if (current != NotificationPermission.NotDetermined) {
          // do if user was prompted
      }
  };
  ```

  ```javascript React Native theme={null}
  OneSignal.addPermissionObserver(event => {
      console.log("OneSignal: permission changed:", event);
  });
  ```

  ```javascript Flutter theme={null}
  OneSignal.shared.setPermissionObserver((OSPermissionStateChanges changes) {
  	// will be called whenever the permission changes
    
    if (changes.to.status == OSNotificationPermission.authorized) {
      //tells you that the user has fully authorized push permissions
    }
  });
  ```

  ```javascript Cordova/Ionic theme={null}
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  window.plugins.OneSignal.addPermissionObserver(function(state) {
    console.log("Notification permission state changed: " + state.hasPrompted);
    console.log("Notification permission status: " + state.status);
  });
  ```

  ```csharp Xamarin theme={null}
  //Currently not available, use the idsAvailableCallback and check if a pushtoken is provided to make sure the user is subscribed
  ```
</CodeGroup>

## Handling Subscription State Changes

* **Web Push** see [`subscriptionChange` Event](/v9.0/docs/web-push-sdk#subscriptionchange-event).
* **Email**: see [`addEmailSubscriptionObserver` Method](/v9.0/docs/email-sdk-methods#email-subscription-observer).
* **SMS**: see [`addSMSSubscriptionObserver` Method](/v9.0/docs/sms-sdk-methods#sms-subscription-observer).

The `onOSSubscriptionChanged` method will be fired on the passed-in object when a notification subscription property changes.

This includes the following events:

* Getting a push token from Google or Apple
* Getting a subscription/user id from OneSignal
* `OneSignal.disablePush` is called
* User disables or enables notifications

The instance is given to your `onOSSubscriptionChanged` method which provides what the value was (**"from"**) and what the value is now (**"to"**).

Any object implementing the `OSPermissionObserver` and/or the `OSSubscriptionObserver` protocols can be added as an observer. You can call `removePermissionObserver` to remove any existing listeners.

OneSignal uses a weak reference to the observer to prevent leaks.

<CodeGroup>
  ```java java theme={null}
  public class MainActivity extends Activity implements OSSubscriptionObserver {
    protected void onCreate(Bundle savedInstanceState) {
      OneSignal.addSubscriptionObserver(this);
    }
    
    public void onOSSubscriptionChanged(OSSubscriptionStateChanges stateChanges) {
      if (!stateChanges.getFrom().getSubscribed() &&
          stateChanges.getTo().getSubscribed()) {
           new AlertDialog.Builder(this)
               .setMessage("You've successfully subscribed to push notifications!")
               .show();
          // get subscription ID
          stateChanges.getTo().getUserId();
        }
     
        Log.i("Debug", "onOSSubscriptionChanged: " + stateChanges);
    }
  }

  /*
  Example Logcat entry - User disabling notifications then returning to your app.
  onOSSubscriptionChanged:
  {"from":{"pushToken":"APA91bG9cmZ262s5gJhr8jvbg1q7aiviEC6lcOCgAQliEzHKO3eOdX5cm7IQqMSWfy8Od7Ol3jSjFfvCfeO2UYUpanJCURJ8RdhgEuV8grYxOCwPNJr5GoqcWTQOaL9u-qE2PQcFlv4K","userSubscriptionSetting":true,"subscribed":false},
   "to":  {"userId":"22712a53-9b5c-4eab-a828-f18f81167fef","pushToken":"APA91bG9cmZ262s5gJhr8jvbg1q7aiviEC6lcOCgAQliEzHKO3eOdX5cm7IQqMSWfy8Od7Ol3jSjFfvCfeO2UYUpanJCURJ8RdhgEuV8grYxOCwPNJr5GoqcWTQOaL9u-qE2PQcFlv4K","userSubscriptionSetting":true,"subscribed":true}}
  ```

  ```swift Swift theme={null}
  // AppDelegate.swift
  // Add OSSubscriptionObserver after UIApplicationDelegate
  class AppDelegate: UIResponder, UIApplicationDelegate, OSSubscriptionObserver {

     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Add your AppDelegate as an obsserver
        OneSignal.add(self as OSSubscriptionObserver)
     }

     // Add this new method
     func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges!) {
        if !stateChanges.from.subscribed && stateChanges.to.subscribed {
           print("Subscribed for OneSignal push notifications!")
           // get player ID
           stateChanges.to.userId
        }
        print("SubscriptionStateChange: \n\(stateChanges)")
     }

     // Output:
     /*
     Subscribed for OneSignal push notifications!
     PermissionStateChanges:
     Optional(<OSSubscriptionStateChanges:
     from: <OSSubscriptionState: userId: (null), pushToken: 0000000000000000000000000000000000000000000000000000000000000000 userSubscriptionSetting: 1, subscribed: 0>,
     to:   <OSSubscriptionState: userId: 11111111-222-333-444-555555555555, pushToken: 0000000000000000000000000000000000000000000000000000000000000000, userSubscriptionSetting: 1, subscribed: 1>
     >
     */
  }
  ```

  ```objectivec objectivec theme={null}
  // AppDelegate.h
  // Add OSSubscriptionObserver after UIApplicationDelegate
  @interface AppDelegate : UIResponder <UIApplicationDelegate, OSSubscriptionObserver>
  @end

  // AppDelegate.m
  @implementation AppDelegate
    
  - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Add your AppDelegate as an obsserver
    [OneSignal addSubscriptionObserver:self];
  }

  // Add this new method
  - (void)onOSSubscriptionChanged:(OSSubscriptionStateChanges*)stateChanges {
    
      // Example of detecting subscribing to OneSignal
      if (!stateChanges.from.subscribed && stateChanges.to.subscribed) {
        NSLog(@"Subscribed for OneSignal push notifications!");
        // get player ID
        stateChanges.to.userId;
      }
      
     // prints out all properties
     NSLog(@"SubscriptionStateChanges:\n%@", stateChanges);
  }

  // Output:
  /*
  Subscribed for OneSignal push notifications!
  PermissionStateChanges:
  <OSSubscriptionStateChanges:
  from: <OSSubscriptionState: userId: (null), pushToken: 0000000000000000000000000000000000000000000000000000000000000000 userSubscriptionSetting: 1, subscribed: 0>,
  to:   <OSSubscriptionState: userId: 11111111-222-333-444-555555555555, pushToken: 0000000000000000000000000000000000000000000000000000000000000000, userSubscriptionSetting: 1, subscribed: 1>
  >
  */

  @end
  ```

  ```csharp Unity (C#) theme={null}
  //Push State Changes
  OneSignal.Default.PushSubscriptionStateChanged += (current, previous) => {
      var pushToken   = current.pushToken;
      var pushEnabled = !current.isPushDisabled;
  };

  //Email State changes
  OneSignal.Default.EmailSubscriptionStateChanged += (current, previous) => {
      var emailSubscribed = current.isSubscribed;
  };

  //SMS State Changes
  OneSignal.Default.SMSSubscriptionStateChanged += (current, previous) => {
      var smsSubscribed = current.isSubscribed;
  };
  ```

  ```javascript React Native theme={null}
  OneSignal.addSubscriptionObserver(event => {
    console.log("OneSignal: subscription changed event:", event);
    console.log("OneSignal: subscription changed from userId:", event.from.userId);
    console.log("OneSignal: subscription changed to userId:", event.to.userId);
    console.log("OneSignal: subscription changed from pushToken:", event.from.pushToken);
    console.log("OneSignal: subscription changed to pushToken:", event.to.pushToken);
    console.log("OneSignal: subscription changed from isPushDisabled:", event.from.isPushDisabled);
    console.log("OneSignal: subscription changed to isPushDisabled:", event.to.isPushDisabled);
    console.log("OneSignal: subscription changed from isSubscribed:", event.from.isSubscribed);
    console.log("OneSignal: subscription changed to isSubscribed:", event.to.isSubscribed);
  });
  ```

  ```javascript Flutter theme={null}
  OneSignal.shared.setSubscriptionObserver((OSSubscriptionStateChanges changes) {
    //will be called whenever the OS subscription changes
  });
  ```

  ```javascript Cordova/Ionic theme={null}
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  window.plugins.OneSignal.addSubscriptionObserver(function (state) {
    if (!state.from.subscribed && state.to.subscribed) {
      console.log("Subscribed for OneSignal push notifications!")
      // get player ID
      state.to.userId
    }
    console.log("Push Subscription state changed: " + JSON.stringify(state));
  });
  ```
</CodeGroup>

## `setLanguage` Method

Language is detected and set automatically through the OneSignal SDK based on the device settings. This method allows you to change that language by passing in the 2-character, lowercase language code. See [Supported Languages](/docs/en/multi-language-messaging#supported-languages).

<CodeGroup>
  ```java java theme={null}
  //Requires SDK 3.16.0+
  OneSignal.setLanguage("es");
  ```

  ```swift Swift theme={null}
  //Requires SDK 3.6.0+
  OneSignal.setLanguage("es")
  ```

  ```objectivec objectivec theme={null}
  //Requires SDK 3.6.0+
  [OneSignal setLanguage:@"es"];
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Default.SetLanguage("es");
  ```

  ```javascript React Native (js) theme={null}
  //Requires SDK 4.2.0+
  OneSignal.setLanguage("es");
  ```

  ```javascript Flutter theme={null}
  //Requires SDK 3.2.0+
  OneSignal.setLanguage("es");
  ```
</CodeGroup>

***

# Privacy

## `setRequiresUserPrivacyConsent` Method

For GDPR users, your application should call this method before initialization of the SDK.

If you pass in `true`, your application will need to call `provideUserConsent(true)` before the OneSignal SDK gets fully initialized. Until this happens, you can continue to call methods (such as `sendTags()`), but nothing will happen.

<CodeGroup>
  ```java java theme={null}
  OneSignal.setRequiresUserPrivacyConsent(true);
  ```

  ```swift Swift theme={null}
  //to require the user's consent before the SDK initializes
  OneSignal.setRequiresUserPrivacyConsent(true);
  ```

  ```objectivec objectivec theme={null}
  //to require the user's consent before the SDK initializes
  [OneSignal setRequiresUserPrivacyConsent:true];
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Default.RequiresPrivacyConsent = true; // before init
  ```

  ```javascript Reactive Native theme={null}
  // Will delay initialization of the SDK until the user provides consent
  OneSignal.setRequiresUserPrivacyConsent(true);
  ```

  ```javascript Flutter theme={null}
  await OneSignal.shared.setRequiresUserPrivacyConsent(true);
  ```

  ```javascript Cordova/Ionic theme={null}
  //will delay initialization of the SDK until the user provides consent
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  window.plugins.OneSignal.setRequiresUserPrivacyConsent(true);
  ```

  ```csharp Xamarin theme={null}
  //will delay initialization of the SDK
  //make sure to call before init()
  OneSignal.SetRequiresUserPrivacyConsent(true);
  ```
</CodeGroup>

## Consent Granted

If your application is set to require the user's privacy consent, you can provide this consent using this method. Until you call `provideUserConsent(true)`, the SDK will not fully initialize, and will not send any data to OneSignal.

<CodeGroup>
  ```java java theme={null}
  public void onUserTappedProvidePrivacyConsent(View v) {
    //will initialize the OneSignal SDK and enable push notifications
    OneSignal.provideUserConsent(true);
  }
  ```

  ```swift Swift theme={null}
  @IBAction func userTappedProvideConsentButton(_ sender : UIButton) {
    //this will complete the initialization of the SDK
  	OneSignal.consentGranted(true); 
  }
  ```

  ```objectivec objectivec theme={null}
  - (IBAction)setEmailButtonPressed:(UIButton *)sender {
    //this will complete the initialization of the SDK
    [OneSignal consentGranted:true];
  }
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Default.PrivacyConsent = true;

  if (OneSignal.Default.PrivacyConsent) {
      // user provided consent
  }
  ```

  ```javascript React Native theme={null}
  function userTappedProvideConsentButton() {
    // Will initialize the SDK and register for push notifications
    OneSignal.provideUserConsent(true);
  }
  ```

  ```javascript Flutter theme={null}
  // the SDK will now initialize
  await OneSignal.shared.consentGranted(true);
  ```

  ```javascript Cordova/Ionic theme={null}
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  window.plugins.OneSignal.userProvidedPrivacyConsent((providedConsent) => {
    //if providedConsent == true, it means the SDK has been initialized and can be used
  });
  ```

  ```csharp Xamarin theme={null}
  PrivacyConsentButton.TouchUpInside += delegate
  {
    //the SDK will now be initialized
  	OneSignal.UserDidProvidePrivacyConsent(true);
  };
  ```
</CodeGroup>

***

# Location Data

## `setLocationShared` Method

Disable or enable location collection (defaults to enabled if your app has location permission).

**Note:** This method must be called **before** OneSignal `initWithLaunchOptions` on iOS.

<CodeGroup>
  ```java java theme={null}
  OneSignal.setLocationShared(false);
  ```

  ```swift Swift theme={null}
  OneSignal.setLocationShared(false)
  ```

  ```objectivec objectivec theme={null}
  [OneSignal setLocationShared:false];
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Default.ShareLocation = true;
  ```

  ```javascript React Native theme={null}
  OneSignal.setLocationShared(false);
  ```

  ```javascript Flutter theme={null}
  await OneSignal.shared.setLocationShared(false);
  ```

  ```javascript Cordova/Ionic theme={null}
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  window.plugins.OneSignal.setLocationShared(false)
  ```

  ```csharp Xamarin theme={null}
  OneSignal.SetLocationShared(false);
  ```

  ```javascript Web-JavaScript theme={null}
  //Our Web SDK does not track location, you can setup the browser to track this and tag the user with the latitutde and longitude
  ```
</CodeGroup>

## `isLocationShared` Method

Return a boolean that indicates location shared state (defaults to true if your app has location permission).

<CodeGroup>
  ```java java theme={null}
  boolean locationShared = OneSignal.isLocationShared();
  ```

  ```swift Swift theme={null}
  let locationShared = OneSignal.isLocationShared()
  ```

  ```objectivec objectivec theme={null}
  BOOL locationShared = [OneSignal isLocationShared];
  ```

  ```csharp Unity (C#) theme={null}
  var locationShared = OneSignal.Default.ShareLocation;
  ```

  ```javascript Cordova/Ionic theme={null}
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  window.plugins.OneSignal.isLocationShared(function(shared) {
  });
  ```
</CodeGroup>

## `promptLocation` Method

**Recommended:** use OneSignal's In-App Message Soft-Prompt before displaying the Native Alert. Details: [Location Opt-In Prompt](/docs/en/location-opt-in-prompt).

Prompts the user for location permissions to allow geotagging from the OneSignal dashboard. This lets you send notifications based on the device's location. See [Location-Triggered Notifications](/docs/en/location-triggered-event) for more details.

Make sure you add location permissions in your `AndroidManifest.xml` and/or `info.plist`.

<CodeGroup>
  ```xml AndroidManifest.xml theme={null}
  // Make sure you add one of the following permissions
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
  ```

  ```text info.plist theme={null}
  //These are examples of how you may setup the app. See Apple's Guide on this: https://developer.apple.com/documentation/corelocation/requesting_authorization_for_location_services
  // Example plist image: https://i.imgur.com/OZDQpyQ.png

  <key>NSLocationUsageDescription</key>
    <string>Your message goes here</string>
  <key>NSLocationWhenInUseUsageDescription</key>
  	<string>Your message goes here</string>  
  <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>Your message goes here</string>
  <key>NSLocationAlwaysUsageDescription</key>
  	<string>Your message goes here</string>
  <key>UIBackgroundModes</key>
  	<array>
  		<string>location</string>
  		<string>remote-notification</string>
  	</array>
  ```
</CodeGroup>

On Android, you need to add the location dependency

<CodeGroup>
  ```groovy app/build.gradle theme={null}
  dependencies {
    ...
    implementation 'com.google.android.gms:play-services-location:YOUR_PLAY_SERVICES_VERSION'
  }
  ```
</CodeGroup>

Finally, don't forget to call the prompt location method

<CodeGroup>
  ```java java theme={null}
  OneSignal.promptLocation();
  ```

  ```swift Swift theme={null}
  OneSignal.promptLocation()
  ```

  ```objectivec objectivec theme={null}
  [OneSignal promptLocation];
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Default.PromptLocation();
  ```

  ```javascript React Native theme={null}
  // Calling promptLocation
  OneSignal.promptLocation();
  ```

  ```javascript Flutter theme={null}
  await OneSignal.shared.promptLocationPermission();
  ```

  ```javascript Cordova/Ionic theme={null}
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  window.plugins.OneSignal.promptLocation();
  ```

  ```csharp Xamarin theme={null}
  OneSignal.Current.PromptLocation();
  ```
</CodeGroup>

***

# Push Notifications

## Push Prompting

iOS requires [prompting users for permission](https://developer.apple.com/documentation/usernotifications/asking_permission_to_use_notifications) to show push notifications that make sound and "pop-up" on the screen. iOS also supports [Provisional Push Notifications](/docs/en/ios-provisional-push-notifications) which are delivered directly to the device's notification center.

Android 13+ requires [prompting users for permission](https://developer.android.com/develop/ui/views/notifications/notification-permission) to show push notifications. This is different behavior from previous Android versions. More details in our [Android 13 Push Notification Developer Update Guide](/release-notes/android-13-push-notification-developer-update-guide).

You can display this prompt using the OneSignal SDK in 2 ways:

1. **Recommended:** use OneSignal's In-App Message Soft-Prompt before displaying the Native Alert. Details: [Prompting for Push Permissions Guide](/docs/en/prompt-for-push-permissions).
2. Programmatically Trigger the Native Alert Prompt with the OneSignal SDK `promptForPushNotifications` method.

<CodeGroup>
  ```swift Swift theme={null}
  OneSignal.promptForPushNotifications(userResponse: { accepted in
    print("User accepted notifications: \(accepted)")
  })
  ```

  ```kotlin kotlin theme={null}
  OneSignal.promptForPushNotifications()
  ```

  ```java java theme={null}
  OneSignal.promptForPushNotifications();
  ```

  ```objectivec objectivec theme={null}
  [OneSignal promptForPushNotificationsWithUserResponse:^(BOOL accepted) {
    NSLog(@"User accepted notifications: %d", accepted);
  }];
  ```

  ```csharp Unity(C#) theme={null}
  OneSignal.Default.PromptForPushNotificationsWithUserResponse();
  ```

  ```javascript React Native / Expo theme={null}
  OneSignal.promptForPushNotificationsWithUserResponse(response => {
    console.log("Prompt response:", response);
  });
  ```

  ```javascript Flutter theme={null}
  OneSignal.shared.promptUserForPushNotificationPermission().then((accepted) {
      print("Accepted permission: $accepted");
  });
  ```

  ```javascript Ionic theme={null}
  OneSignal.promptForPushNotificationsWithUserResponse(function(accepted) {
      console.log("User accepted notifications: " + accepted);
  });
  ```

  ```javascript Cordova theme={null}
  window.plugins.OneSignal.promptForPushNotificationsWithUserResponse(function(accepted) {
      console.log("User accepted notifications: " + accepted);
  });
  ```
</CodeGroup>

## Notification Events & Payload

OneSignal Provides methods for handling notifications received and clicked/opened events. Details and discussion on implementation and Notification Payload in [SDK Notification Event Handlers](/v9.0/docs/sdk-notification-event-handlers).

To send notifications to users, we recommend using the [Create notification](/reference/create-message) REST API docs, or Messages Dashboard.

## `postNotification` Method

Recommended for scheduling notifications in the future to the current user.

<Warning>
  You can only use `include_player_ids` as a targeting parameter from your app. Other target options such as `tags` and `included_segments` require your OneSignal App REST API key which can only be used from your server.

  See the [Create notification](/reference/create-message) REST API POST call for a list of all possible options.
</Warning>

| Parameter    | Type                                             | Description                                                                                                        |
| ------------ | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ |
| `parameters` | JSONObject, NSDictionary\*, JSONString, Callback | Contains notification options, see our [Create notification](/reference/create-message) POST call for all options. |

<CodeGroup>
  ```java java theme={null}
  try {
    OneSignal.postNotification(new JSONObject("{'contents': {'en':'Test Message'}, 'include_player_ids': ['" + "userId" + "']}"),
       new OneSignal.PostNotificationResponseHandler() {
         @Override
         public void onSuccess(JSONObject response) {
           Log.i("OneSignalExample", "postNotification Success: " + response.toString());
         }

         @Override
         public void onFailure(JSONObject response) {
           Log.e("OneSignalExample", "postNotification Failure: " + response.toString());
         }
       });
  } catch (JSONException e) {
    e.printStackTrace();
  }
  ```

  ```swift Swift theme={null}
  let content: [String : Any] = [
      //"content_available" : true,
      //"send_after" : "2021-10-20 14:58:49 GMT+3",
      "contents": ["en": "Contents Example"],
      "headings": ["en": "Headings Example"],
      "include_player_ids": [osPlayerId],
      "data" : ["action" : "custom_action"]
  ]

  OneSignal.postNotification(content,onSuccess: {
      osResultSuccessBlock in print(osResultSuccessBlock.debugDescription)
      },
      onFailure: {
        osFailureBlock in print(osFailureBlock.debugDescription)
  })
  ```

  ```objectivec objectivec theme={null}
  [OneSignal postNotification:@{
     @"contents" : @{@"en": @"Test Message"},
     @"include_player_ids": @[@"3009e210-3166-11e5-bc1b-db44eb02b120"]
  }];
  ```

  ```csharp Unity (C#) theme={null}
  var pushUserId = OneSignal.Default.PushSubscriptionState.userId;
  var pushOptions = new Dictionary<string, object> {
      ["contents"]           = new Dictionary<string, string> { ["en"] = "Test Message" },
      ["include_player_ids"] = new List<string> { pushUserId },
      ["send_after"]         = DateTime.Now.ToUniversalTime().AddSeconds(30).ToString("U")
  };

  var result = await OneSignal.Default.PostNotification(pushOptions);
  if (result != null)
      Debug.Log("success");
  else
      Debug.Log("error");
  ```

  ```javascript React Native theme={null}
  const { userId } = await OneSignal.getDeviceState();

  const notificationObj = {
    contents: {en: "Message Body"},
    include_player_ids: [userId]
  };

  const jsonString = JSON.stringify(notificationObj);

  OneSignal.postNotification(jsonString, (success) => {
    console.log("Success:", success);
  }, (error) => {
    console.log("Error:", error );
  });
  ```

  ```javascript Flutter theme={null}
  var status = await OneSignal.shared.getPermissionSubscriptionState();

  var playerId = status.subscriptionStatus.userId;

  await OneSignal.shared.postNotification(OSCreateNotification(
    playerIds: [playerId],
    content: "this is a test from OneSignal's Flutter SDK",
    heading: "Test Notification",
    send_after: DateTime.now().add(Duration(minutes: 30)).toUtc().toIso8601String();,
    buttons: [
      OSActionButton(text: "test1", id: "id1"),
      OSActionButton(text: "test2", id: "id2")
    ]
  ));
  ```

  ```javascript Cordova/Ionic theme={null}
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  window.plugins.OneSignal.getIds(function(ids) {
    var notificationObj = { contents: {en: "message body"},
                            include_player_ids: [ids.userId]};
    window.plugins.OneSignal.postNotification(notificationObj,
      function(successResponse) {
        console.log("Notification Post Success:", successResponse);
      },
      function (failedResponse) {
        console.log("Notification Post Failed: ", failedResponse);
        alert("Notification Post Failed:\n" + JSON.stringify(failedResponse));
      }
    );
  });
  ```

  ```csharp Xamarin theme={null}
  using OneSignalPush.MiniJSON;

  private static string oneSignalDebugMessage;

  void someMethod() {
  // Just an example userId, use your own or get it the devices by calling OneSignal.GetIdsAvailable
  string userId = "b2f7f966-d8cc-11e4-bed1-df8f05be55ba";

  var notification = new Dictionary<string, object>();
  notification["contents"] = new Dictionary<string, string>() { {"en", "Test Message"} };

  notification["include_player_ids"] = new List<string>() { userId };
  // Example of scheduling a notification in the future.
  notification["send_after"] = System.DateTime.Now.ToUniversalTime().AddSeconds(30).ToString("U");

  OneSignal.Current.PostNotification(notification, (responseSuccess) => {
    oneSignalDebugMessage = "Notification posted successful! Delayed by about 30 secounds to give you time to press the home button to see a notification vs an in-app alert.\n" + Json.Serialize(responseSuccess);
  }, (responseFailure) => {
    oneSignalDebugMessage = "Notification failed to post:\n" + Json.Serialize(responseFailure);
  });

  }
  ```

  ```lua Corona theme={null}
  function IdsAvailable(userID, pushToken)
      if (pushToken) then
          local notification = {
              ["contents"] = {["en"] = "test"}
          }
          notification["include_player_ids"] = {userID}
          
          OneSignal.PostNotification(notification,
              function(jsonData)
                  native.showAlert( "DEBUG", "POST OK!!!", { "OK" } )
                  local json = require "json"
                  print(json.encode(jsonData))
              end,
              function(jsonData)
                  native.showAlert( "DEBUG", "POST NOT OK!!!", { "OK" } )
                  local json = require "json"
                  print(json.encode(jsonData))
              end
          )
      end
  end

  OneSignal.IdsAvailableCallback(IdsAvailable)
  ```

  ```javascript Web-JavaScript theme={null}
  OneSignal.sendSelfNotification(
    /* Title (defaults if unset) */
    "OneSignal Web Push Notification",
    /* Message (defaults if unset) */
    "Action buttons increase the ways your users can interact with your notification.", 
     /* URL (defaults if unset) */
    'https://example.com/?_osp=do_not_open',
    /* Icon */
    'https://onesignal.com/images/notification_logo.png',
    {
      /* Additional data hash */
      notificationType: 'news-feature'
    }, 
    [{ /* Buttons */
      /* Choose any unique identifier for your button. The ID of the clicked button is passed to you so you can identify which button is clicked */
      id: 'like-button',
      /* The text the button should display. Supports emojis. */
      text: 'Like',
      /* A valid publicly reachable URL to an icon. Keep this small because it's downloaded on each notification display. */
      icon: 'http://i.imgur.com/N8SN8ZS.png',
      /* The URL to open when this action button is clicked. See the sections below for special URLs that prevent opening any window. */
      url: 'https://example.com/?_osp=do_not_open'
    },
    {
      id: 'read-more-button',
      text: 'Read more',
      icon: 'http://i.imgur.com/MIxJp1L.png',
      url: 'https://example.com/?_osp=do_not_open'
    }]
  );
  ```
</CodeGroup>

## `clearOneSignalNotifications` Method

Android only. iOS provides a standard way to clear notifications by [clearing badge count](/docs/en/badges). There is no specific OneSignal API call for clearing notifications.

<CodeGroup>
  ```java java theme={null}
  OneSignal.clearOneSignalNotifications();
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Default.ClearOneSignalNotifications();
  ```

  ```javascript React Native theme={null}
  OneSignal.clearOneSignalNotifications();
  ```

  ```javascript Flutter theme={null}
  //Currently not available
  ```

  ```javascript Cordova/Ionic theme={null}
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  OneSignal.clearOneSignalNotifications();
  ```

  ```csharp Xamarin theme={null}
  OneSignal.Current.ClearOneSignalNotifications();
  ```

  ```lua Corona theme={null}
  OneSignal.ClearAllNotifications()
  ```

  ```javascript Web-JavaScript theme={null}
  //Not available
  ```
</CodeGroup>

## `disablePush` Method

The user must first subscribe through the native prompt or app settings. It does not officially subscribe or unsubscribe them from the app settings, it unsubscribes them from receiving push from OneSignal. You can only call this method with true to opt out users from receiving notifications through OneSignal. You can pass false later to opt users back into notifications.

<CodeGroup>
  ```java java theme={null}
  // Android SDK version 4.x.x
  OneSignal.disablePush(true);

  //Android SDK version 3.x.x
  OneSignal.setSubscription(false);
  ```

  ```swift Swift theme={null}
  // iOS SDK 3.x.x use
  OneSignal.disablePush(true)

  // iOS SDK 2.x.x use
  OneSignal.setSubscription(false)
  ```

  ```objectivec objectivec theme={null}
  // iOS SDK 3.x.x use
  [OneSignal disablePush:true];

  // iOS SDK 2.x.x use
  [OneSignal setSubscription:false];
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Default.PushEnabled = false;
  ```

  ```javascript React Native theme={null}
  // RN SDK 4.x.x use
  OneSignal.disablePush(true);

  // RN SDK 3.x.x use
  OneSignal.setSubscription(false);
  ```

  ```javascript Flutter theme={null}
  // Flutter SDK 3.x.x use
  await OneSignal.shared.disablePush(true);

  // Flutter SDK 2.x.x use
  await OneSignal.shared.setSubscription(false);
  ```

  ```javascript Cordova/Ionic theme={null}
  // Ionic 5 Capacitor may need to use (window as any).plugins.OneSignal
  window.plugins.OneSignal.disablePush(false);
  ```

  ```csharp Xamarin theme={null}
  OneSignal.SetSubscription(false);
  ```

  ```lua Corona theme={null}
  OneSignal.SetSubscription(false)
  ```

  ```javascript Web-JavaScript theme={null}
  OneSignal.setSubscription(false);
  ```
</CodeGroup>

## `EnableVibrate` & `EnableSound` Methods

These methods were designed for Android but stopped working in Android 8+ due to a breaking change. To customize going forward, use [Android Notification Categories (Channels)](/docs/en/android-notification-categories).

## `unsubscribeWhenNotificationsAreDisabled` Method

**Only available on Android Native SDK**. If notifications are disabled for your app, unsubscribe the user from OneSignal.

Use case: if notifications are disabled for your app and you still want background notifications to work, pass in false.

<CodeGroup>
  ```java java theme={null}
  OneSignal.unsubscribeWhenNotificationsAreDisabled(false);
  ```

  ```text Unity(C#) theme={null}
  REMOVED - Stopped working in Android 8+ due to a breaking change. 
  To customize going forward, use Notification Categories (Channels).
  ```
</CodeGroup>

## `setLaunchURLsInApp` Method (iOS)

This method can be used to set if launch URLs should be opened in safari or within the application. Set to `true` to launch all notifications with a URL in the app instead of the default web browser. Make sure to call `setLaunchURLsInApp` before the `setAppId` call.

<CodeGroup>
  ```csharp Unity (C#) theme={null}
  OneSignal.Default.SetLaunchURLsInApp(true); // before Initialize
  ```
</CodeGroup>

| Parameter Type | Description                                                                            |
| -------------- | -------------------------------------------------------------------------------------- |
| `Bool`         | Boolean indicates if launch URLs should be opened in safari or within the application. |

***

# Live Activities

Live Activities are a type of interactive push notification. They were designed by Apple to enable iOS apps to provide real-time updates to their users that are visible from the lock screen and dynamic island.

Live Activity support comes with OneSignal iOS SDK version 3.12.3 or above.

## Permission

Live Activities do not need explicit user approval. A developer may start and update a Live Activity via any method without an explicit prompt (unlike Notification Permission or Location Permission). Live Activities appear with the iOS Provisional Authorization UI.

## Developer Guidelines

As with any iOS development, we recommend Apple’s developer guidelines.

According to Apple’s guidelines, applications should give users the option to opt-in to Live Activities. For example, an app can give a user an option to start a Live Activity through it’s UX, such as as a button or in-app. Live Activities must be started when the application is in the foreground.

## Enter a Live Activity

Entering a Live Activity associates an `activityId` with a live activity temporary push `token` on OneSignal's server. The activityId is then used with the OneSignal REST API to update one or multiple Live Activities at one time.

| Parameter    | Type     | Description                                                                                                                                                                                                                                                                                                   |
| ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `activityId` | `String` | A customer defined identifier that gets assisted with the temporary push token on OneSignal's server. When the customer uses the update endpoint they will send this activityId to specify which push tokens they would like to update. NOTE: `activityId` cannot contain any `/` (forward slash) characters. |
| `token`      | `String` | A Live Activity temporary push token.                                                                                                                                                                                                                                                                         |

`enterliveActivity` usage with context:

<CodeGroup>
  ```swift Swift theme={null}
  // ... your app's code 
  let activity = try Activity<OneSignalWidgetAttributes>.request(
    attributes: attributes,
    contentState: contentState,
    pushType: .token)
  Task {
      for await data in activity.pushTokenUpdates {
          let myToken = data.map {String(format: "%02x", $0)}.joined()
          // ... required code for entering a live activity
          OneSignal.enterLiveActivity("my_activity_id", withToken: myToken)
      }
  }
  ```

  ```javascript React Native theme={null}
  OneSignal.enterLiveActivity("my_activity_id", token, (res: object) => {
      loggingFunction("enterLiveActivity completed with result: ", JSON.stringify(res));
  })
  ```

  ```javascript Flutter theme={null}
  OneSignal.shared.enterLiveActivity("my_activity_id", token).then((v) {
      print("Successfully enter live activity");
  }).catchError((error) {
      print("Failed to enter live activity with error: $error");
  });
  ```

  ```javascript Cordova theme={null}
  window.plugins.OneSignal.enterLiveActivity("my_activity_id", token);
  ```

  ```csharp .Net theme={null}
  var result = OneSignalSDK.DotNet.OneSignal.Default.EnterLiveActivity("my_activity_id", token);
  if(result) {
      Console.WriteLine("Success");
  }
  ```

  ```csharp Xamarin theme={null}
  var result = OneSignalSDK.Xamarin.OneSignal.Default.EnterLiveActivity("my_activity_id", token);
  if(result) {
      Console.WriteLine("Success");
  }
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Default.enterLiveActivity("my_activity_id", token);
  ```
</CodeGroup>

### Exit a Live Activity

Exiting a Live activity deletes the association between a customer defined `activityId` with a Live Activity temporary push `token` on OneSignal's server.

`exitliveActivity` usage

<CodeGroup>
  ```swift Swift theme={null}
  OneSignal.exitLiveActivity("my_activity_id")
  ```

  ```javascript React Native theme={null}
  OneSignal.exitLiveActivity("my_activity_id", (res: object) => {
      loggingFunction("exitLiveActivity completed with result: ", JSON.stringify(res));
  })
  ```

  ```javascript Flutter theme={null}
  OneSignal.shared.exitLiveActivity("your_activity_id").then((v) {
      print("Successfully exit live activity");
  }).catchError((error) {
      print("Failed to exit live activity: $error");
  });
  ```

  ```javascript Cordova theme={null}
  window.plugins.OneSignal.exitLiveActivity("my_activity_id");
  ```

  ```csharp .Net theme={null}
  OneSignalSDK.DotNet.OneSignal.Default.ExitLiveActivity("my_activity_id");
  ```

  ```csharp Xamarin theme={null}
  OneSignalSDK.DotNet.OneSignal.Default.ExitLiveActivity("my_activity_id");
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Default.exitLiveActivity("my_activity_id");
  ```
</CodeGroup>

***

# In-App Messages

In-App Messages do not require any code to get started, but if you would like to setup custom triggers to display the In-App Message under certain conditions and track IAM lifecycle events, we have SDK methods for you!

See our [In-App Message SDK Methods](/v9.0/docs/iam-sdk-methods) for details.

***

# Email

OneSignal's Mobile and Web SDKs provide methods for collecting emails, logging out emails, and tracking email subscription changes.

See the [Email SDK Methods](/v9.0/docs/email-sdk-methods) guide for more details.

If you have a backend server, we strongly recommend using [Identity Verification](/v9.0/docs/identity-verification) with your users. Your backend can generate an ***Email authentication token*** and send it to your app.

***

# SMS

OneSignal's Mobile and Web SDKs provide methods for collecting phone numbers, logging out phone numbers, and tracking sms subscription.

See the [SMS SDK Methods](/v9.0/docs/sms-sdk-methods) guide for more details.

If you have a backend server, we strongly recommend using [Identity Verification](/v9.0/docs/identity-verification) with your users. Your backend can generate an ***SMS authentication token*** and send it to your app.

***
