<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://nielsentest.mywikis.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Admin2</id>
	<title>Engineering Client Portal - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://nielsentest.mywikis.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Admin2"/>
	<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/wiki/Special:Contributions/Admin2"/>
	<updated>2026-04-03T17:27:34Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.5</generator>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=DCR_Podcasts_in_Digital&amp;diff=3110</id>
		<title>DCR Podcasts in Digital</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=DCR_Podcasts_in_Digital&amp;diff=3110"/>
		<updated>2019-01-11T16:28:25Z</updated>

		<summary type="html">&lt;p&gt;Admin2: UTC -&amp;gt; UNIX&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Audio}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Podcasts]]&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Steps ==&lt;br /&gt;
'''This document assumes you have implemented Digital Audio with Live AM/FM stream measurement''' with a &amp;quot;radio&amp;quot; content type.    It outlines the new parameters you will use to implement podcast measurement. &lt;br /&gt;
&lt;br /&gt;
#Contact your Nielsen Account Representative to discuss the way you would like your podcasts reported (Classified)&lt;br /&gt;
#Your TAM will provide new appIds for the applications that will offer podcasts&lt;br /&gt;
#Update the parameters you use to call the SDK play and playheadPosition. Reference the appropriate [[DCR Podcasts in Digital#Changes_for_Podcast_Measurement|Changes for Podcast Measurement]]  below&lt;br /&gt;
#Obtain Nielsen Podcast certification once your changes are complete and tested &lt;br /&gt;
#Complete a Production License with your Nielsen Account Representative&lt;br /&gt;
=== Library ===&lt;br /&gt;
Use the same SDK library as Digital Audio, live AM/FM stream measurement.&lt;br /&gt;
&lt;br /&gt;
== Changes for Podcast Measurement ==&lt;br /&gt;
=== Initializing the SDK ===&lt;br /&gt;
Update your appid to the new ID provided by your TAM for podcast measurement. &lt;br /&gt;
When you initialize the SDK, use 'dcr' in the sfcode instead of 'drm'. &lt;br /&gt;
&lt;br /&gt;
=== play ===&lt;br /&gt;
Call [[play]] when the user taps the '''Play''' button to start the content.. The channelName parameter is not required.&lt;br /&gt;
&lt;br /&gt;
'''play Example'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
   &amp;quot;channelName&amp;quot;: &amp;quot;KABC-FM Morning Show&amp;quot;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
Use [[loadMetadata]] to pass information about your podcast to the SDK. The parameters must be passed as a JSON object.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;    – (void) loadMetadata :(id)metadata;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Refer to [[loadMetadata]] for the list of parameters to be passed in the JSON object.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The [[loadMetadata]] call after the first [[play]] call '''must have ‘content’ (&amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;).''' &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''loadMetadata Example'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
  &amp;quot;assetid&amp;quot;: &amp;quot;KABC:345-67483&amp;quot;,&lt;br /&gt;
  &amp;quot;program&amp;quot;: &amp;quot;KABC Morning Show&amp;quot;,&lt;br /&gt;
  &amp;quot;title&amp;quot;: &amp;quot;20171125: HR1&amp;quot;,&lt;br /&gt;
  &amp;quot;length&amp;quot;: &amp;quot;3600&amp;quot;,&lt;br /&gt;
  &amp;quot;segB&amp;quot;: &amp;quot;KABC-FM&amp;quot;,                        // station call letters and band are optional here                   &lt;br /&gt;
  &amp;quot;isfullepisode&amp;quot;: &amp;quot;y&amp;quot;,&lt;br /&gt;
  &amp;quot;airdate&amp;quot;: &amp;quot;20171125 06:00:00&amp;quot;,&lt;br /&gt;
  &amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
  &amp;quot;pipmode&amp;quot;:&amp;quot;false&amp;quot; &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition for &amp;quot;content&amp;quot; ===&lt;br /&gt;
You will continue to use [[playheadPosition]] to pass the position of the playhead while the content is being played; however, you will pass the relative position from the beginning of the file.  '''This is different than live stream measurement, which uses the current Unix timestamp (seconds since Jan-1-1970 UTC).'''&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required? (Y/N) !! Example&lt;br /&gt;
|-&lt;br /&gt;
| On-Demand Audio || Position taken from beginning of the content in seconds. || Client-defined || Yes || Current player position from beginning of the content.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
''' playheadPosition Syntax Example for iOS'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;    CMTime curTime=[player currentTime];&lt;br /&gt;
    long pos=CMTimeGetSeconds(curTime);&lt;br /&gt;
    [nAppApiObject playheadPosition:pos];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Usage Sequence and API'''&lt;br /&gt;
The sample API sequence can be used as a reference to identify the specific events that need to be called during content and ad playback.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Action !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;[nielsenMeter play: channelName];&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of program being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Listening || &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;[nielsenMeter end];&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
- Continue to call [[playheadPosition]] every two seconds until the user pauses, stops, or loses audio. &lt;br /&gt;
&lt;br /&gt;
- Call a new ''loadMetadata'' when the user selects a different program.&lt;br /&gt;
 &lt;br /&gt;
'''With Preroll, Midroll, Postroll Ads'''&lt;br /&gt;
'''Please note:''' The below examples include ad pod information.  These ads are not ads served as part of the originator's programming (studio-recorded ads). These ads are hosted independently from the podcast content file. &lt;br /&gt;
&lt;br /&gt;
When applicable, Playhead should be passed for the entire duration of ad pod, if the ad pod details are passed as part of [[loadMetadata]].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Action !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;[nielsenMeter play: channelName];&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel/video name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Preroll || &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: prerollMetadataObject];&amp;lt;/code&amp;gt; || // prerollMetadataObject contains the JSON metadata for the preroll ad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // position is position of the playhead while the preroll ad is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter stop];&amp;lt;/code&amp;gt; || // Call stop after preroll occurs&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Listening || &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // position is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter stop];&amp;lt;/code&amp;gt; || // Call stop after the content is paused (ad starts)&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Midroll || &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: midrollMetadataObject];&amp;lt;/code&amp;gt; || // midrollMetadataObject contains the JSON metadata for the midroll ad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // position is position of the playhead while the midroll ad is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter stop];&amp;lt;/code&amp;gt; || // Call stop after midroll occurs&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Content (End of stream) || &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // position is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter end];&amp;lt;/code&amp;gt; || // Called at the end of content&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Postroll || &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: postrollMetadataObject];&amp;lt;/code&amp;gt; || // postrollMetadataObject contains the JSON metadata for the postroll ad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // position is position of the playhead while the postroll ad is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter stop];&amp;lt;/code&amp;gt; || // Call stop after postroll occurs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Each Ad playhead should reset or begin from 0 at ad start. When content has resumed following an ad break, playhead position must continue from where previous content segment was left off.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Measurement Opt-Out Implementation ==&lt;br /&gt;
No changes are necessary because Opt-out implementation for podcasts is the same as live AM/FM stream measurement.&lt;br /&gt;
&lt;br /&gt;
== Technical Guides ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; | Type&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | OS&lt;br /&gt;
! style=&amp;quot;width: 50%;&amp;quot; | DCR Implementation Guide&lt;br /&gt;
!| SDK Documentation&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;7&amp;quot; | {{SmallIcon|SDKIcon.png|alt=SDK}}&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | {{OSIcon|VideoIcon.png|alt=Video}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png|alt=iOS}}&lt;br /&gt;
| '''[[DCR Video iOS SDK]]'''&lt;br /&gt;
| [[iOS SDK API Reference]]&lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|AndroidIcon.png|alt=Android}}&lt;br /&gt;
| '''[[DCR Video Android SDK]]'''&lt;br /&gt;
| [[Android SDK API Reference]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 42%;&amp;quot; | Technical Guides&lt;br /&gt;
!&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;7&amp;quot; | {{SmallIcon|DigitalIcon.png}}&lt;br /&gt;
| '''[[Digital Measurement Onboarding]]'''&lt;br /&gt;
| '''[[Digital Measurement Metadata]]'''&lt;br /&gt;
|-&lt;br /&gt;
| '''[[Digital Measurement Testing]]'''&lt;br /&gt;
| '''[[Digital Measurement Interruption Scenarios]]'''&lt;br /&gt;
|-&lt;br /&gt;
| '''[[Digital Measurement FAQ]]'''&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| '''[[Digital Pre-Certification Checklist App SDK]]'''&lt;br /&gt;
| '''[[Digital Pre-Certification Checklist Browser SDK]]'''&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Digital_Measurement_Metadata&amp;diff=3001</id>
		<title>Digital Measurement Metadata</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Digital_Measurement_Metadata&amp;diff=3001"/>
		<updated>2018-10-23T18:40:29Z</updated>

		<summary type="html">&lt;p&gt;Admin2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR &amp;amp; DTVR}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting. There are reserved Nielsen keys for collecting the required metadata.&lt;br /&gt;
&lt;br /&gt;
=== Reserved Keys ===&lt;br /&gt;
Content and Ad Metadata can be passed through key-values using the Nielsen reserved keys. The last column in the table below indicates metadata parameters that will be displayed in reporting.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key&lt;br /&gt;
! Description&lt;br /&gt;
! style=&amp;quot;width: 14%;&amp;quot; | Values&lt;br /&gt;
! style=&amp;quot;width: 12%;&amp;quot; | Required for Audio/Video?&lt;br /&gt;
! style=&amp;quot;width: 12%;&amp;quot; | Required for Static (page)?&lt;br /&gt;
! Reported for&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || custom || Optional || Optional || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| subbrand || VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || custom || Optional || Optional || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*audio / video – &amp;quot;content&amp;quot;&lt;br /&gt;
*page – &amp;quot;static&amp;quot;&lt;br /&gt;
*ad – &amp;quot;preroll&amp;quot;, &amp;quot;midroll&amp;quot; or &amp;quot;postroll&amp;quot;&lt;br /&gt;
|| &amp;quot;content&amp;quot;, &amp;quot;static&amp;quot; || Mandatory || Mandatory || &lt;br /&gt;
|-&lt;br /&gt;
| assetid || ID assigned to content. '''Must be unique and consistent''' across all content at the episode level, as well as across platforms (e.g. iOS and Android use the same ID). || custom&amp;lt;br&amp;gt;(no [[Special Characters]]) || Mandatory || Not Required || &lt;br /&gt;
|-&lt;br /&gt;
| section || Section of site || custom || Not Required || Mandatory || &lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
*&amp;quot;y&amp;quot; or &amp;quot;lf&amp;quot; - full episode&lt;br /&gt;
*&amp;quot;n&amp;quot; or &amp;quot;sf&amp;quot; - short form&lt;br /&gt;
|| Mandatory || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name || custom || Mandatory || Not Required || Audio / Video Measurement&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title || custom || Mandatory || Not Required || Audio / Video Measurement&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. 0 may be used for Live content if the exact content length is not known.  || custom || Mandatory || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| segA || Segment A (this is not available for audio / video Measurement reporting as the episode title is reported) || custom || Not Required || Not Required || Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| segB || Segment B || custom || Not Required || Not Required || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| segC || Segment C || custom || Not Required || Not Required || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| crossId1 || Standard episode ID. Gracenote/TMS ID should be used when available. Must be unique per episode. || custom || Optional || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| crossId2 || Content originator (required only for distributors) || custom || Optional || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (Eastern Time for US) || YYYYMMDD HH24:MI:SS || Mandatory || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| pipmode ||&lt;br /&gt;
Current state of picture-in-picture (PIP) mode on device.&lt;br /&gt;
*&amp;quot;true&amp;quot; if audio / video measurement is displayed in PIP mode&lt;br /&gt;
*&amp;quot;false&amp;quot; if audio / video measurement is displayed in regular mode&lt;br /&gt;
|| &amp;quot;true&amp;quot;, &amp;quot;false&amp;quot; || Optional || Not Required || Audio / Video Measurement&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;quot;1&amp;quot; - Linear&lt;br /&gt;
&amp;quot;2&amp;quot; - Dynamic&lt;br /&gt;
|| Mandatory for DCR || Not Required || DCR &lt;br /&gt;
|-&lt;br /&gt;
| adModel ||&lt;br /&gt;
Type of ad model:&lt;br /&gt;
#Linear - matches TV ad load&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;quot;1&amp;quot; - Linear&lt;br /&gt;
&amp;quot;2&amp;quot; - Dynamic&lt;br /&gt;
|| Mandatory for DTVR || Not Required || DTVR&lt;br /&gt;
|-&lt;br /&gt;
| progen || Genre (required only for non-TV originated content). See [[DCR OTT Genre List]] for acceptable values. || e.g. DD for Daytime Drama || Required for non-TV content || Not Required&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''clientid &amp;amp; subbrand (vcid)'''&lt;br /&gt;
By default, clientid and subbrand are setup in Nielsen backend configuration to capture brand and sub-brand information. The fields get populated from backend for a registered client appid. But if an app contains multiple brands and sub-brands and client is willing to give credit to another brand or sub-brand then :&lt;br /&gt;
*Client app developer can override the clientid and subbrand (brand and sub-brand info.) in [[loadMetadata]] call to get a proper measurement for a desired brand and sub-brand.&lt;br /&gt;
**If no clientid and subbrand are specified in CMS of a content and an ad, default values reported in the Configuration will be reported.&lt;br /&gt;
**If clientid and subbrand are specified in CMS of the content or ad, the most recent clientid and subbrand will be reported in subsequent pings. To report with a different clientid and subbrand, include the new values for the keys in their subsequent [[loadMetadata]] call.&lt;br /&gt;
'''Picture-in-picture (PIP) mode'''&lt;br /&gt;
Once the app detects PIP mode, call [[loadMetadata]] with the same set of assetids, values and with one additional parameter &amp;quot;pipmode&amp;quot;: &amp;quot;true&amp;quot;. Once PIP mode is disabled in the device, call [[loadMetadata]] again with &amp;quot;pipmode&amp;quot;:&amp;quot;false&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Custom Variables Extension ====&lt;br /&gt;
Contact Nielsen Technical Account Manager (TAM) to configure any custom variables, as needed for implementing the application.&lt;br /&gt;
&lt;br /&gt;
See [[Custom Variables Extension]] for more information.&lt;br /&gt;
&lt;br /&gt;
==== Advertisement Metadata ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required for Audio / Video? !! Required for Static (page)&lt;br /&gt;
|-&lt;br /&gt;
| type || Type of ad || &amp;quot;preroll&amp;quot;&lt;br /&gt;
&amp;quot;midroll&amp;quot;&lt;br /&gt;
&amp;quot;postroll&amp;quot; &lt;br /&gt;
|| Mandatory || Not Required&lt;br /&gt;
|-&lt;br /&gt;
| assetid || An ID assigned to the advertisement. Can be an internal ID, an ID provided by the ad server, or a randomly generated ID. Must be unique across all ads || custom || Mandatory || Not Required&lt;br /&gt;
|-&lt;br /&gt;
| title || Title of the advertisement || &amp;quot;MyAdName&amp;quot; || Mandatory || Not Required&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Passing Metadata ===&lt;br /&gt;
The required metadata can be passed as key values through the loadMetadata method. The sample code below shows a metadata objects for various assets.&lt;br /&gt;
'''Audio / Video Measurement Asset'''&lt;br /&gt;
Type should be &amp;quot;content&amp;quot;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
       &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
       &amp;quot;assetName&amp;quot;: &amp;quot;myassetName&amp;quot;,&lt;br /&gt;
       &amp;quot;length&amp;quot;: &amp;quot;300.0&amp;quot;,&lt;br /&gt;
       &amp;quot;title&amp;quot;: &amp;quot;myTitle&amp;quot;,&lt;br /&gt;
       &amp;quot;program&amp;quot;: &amp;quot;myProgram&amp;quot;,&lt;br /&gt;
       &amp;quot;censuscategory&amp;quot;: &amp;quot;myCensusCategory&amp;quot;,&lt;br /&gt;
       &amp;quot;assetid&amp;quot;: &amp;quot;myAssetId&amp;quot;,&lt;br /&gt;
       &amp;quot;channelName&amp;quot;: &amp;quot;myChannel&amp;quot;,&lt;br /&gt;
       &amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
       &amp;quot;segB&amp;quot;: &amp;quot;segmentB&amp;quot;,&lt;br /&gt;
       &amp;quot;segC&amp;quot;: &amp;quot;segmentC&amp;quot;,&lt;br /&gt;
       &amp;quot;isfullepisode&amp;quot;:&amp;quot;y&amp;quot;,&lt;br /&gt;
       &amp;quot;crossId1&amp;quot;: &amp;quot;Reference11&amp;quot;,&lt;br /&gt;
       &amp;quot;crossId2&amp;quot;: &amp;quot;Reference22&amp;quot;,&lt;br /&gt;
       &amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Static (Page) Measurement Asset'''&lt;br /&gt;
Type should be &amp;quot;static&amp;quot;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
       &amp;quot;type&amp;quot;: &amp;quot;static&amp;quot;,&lt;br /&gt;
       &amp;quot;assetid&amp;quot;: &amp;quot;static123&amp;quot;,&lt;br /&gt;
       &amp;quot;assetName&amp;quot;: &amp;quot;Page-Asset&amp;quot;,&lt;br /&gt;
       &amp;quot;section&amp;quot;: &amp;quot;siteSection&amp;quot;,&lt;br /&gt;
       &amp;quot;segA&amp;quot;: &amp;quot;segmentA&amp;quot;,&lt;br /&gt;
       &amp;quot;segB&amp;quot;: &amp;quot;segmentB&amp;quot;,&lt;br /&gt;
       &amp;quot;segC&amp;quot;: &amp;quot;segmentC&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''For any of the ad types'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;midroll&amp;quot;,&lt;br /&gt;
        &amp;quot;length&amp;quot;: &amp;quot;30.0&amp;quot;,&lt;br /&gt;
        &amp;quot;assetid&amp;quot;: &amp;quot;myMidrollAssetId&amp;quot;,&lt;br /&gt;
        &amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
        &amp;quot;tv&amp;quot;: &amp;quot;true&amp;quot;,&lt;br /&gt;
        &amp;quot;dataSrc&amp;quot;: &amp;quot;cms&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': In case the individual ad details are not available, send ad pod (presence) details through the &amp;lt;code&amp;gt;loadMetadata&amp;lt;/code&amp;gt; and playhead position through &amp;lt;code&amp;gt;setPlayheadPosition&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''loadMetadata'''&lt;br /&gt;
The object can then be passed when calling [[loadMetadata]].&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;    loadMetadata(jsonMetadataObject);&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Digital_Measurement_Metadata&amp;diff=3000</id>
		<title>Digital Measurement Metadata</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Digital_Measurement_Metadata&amp;diff=3000"/>
		<updated>2018-10-23T18:39:18Z</updated>

		<summary type="html">&lt;p&gt;Admin2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR &amp;amp; DTVR}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting. There are reserved Nielsen keys for collecting the required metadata.&lt;br /&gt;
&lt;br /&gt;
=== Reserved Keys ===&lt;br /&gt;
Content and Ad Metadata can be passed through key-values using the Nielsen reserved keys. The last column in the table below indicates metadata parameters that will be displayed in reporting.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key&lt;br /&gt;
! Description&lt;br /&gt;
! style=&amp;quot;width: 14%;&amp;quot; | Values&lt;br /&gt;
! style=&amp;quot;width: 12%;&amp;quot; | Required for Audio/Video?&lt;br /&gt;
! style=&amp;quot;width: 12%;&amp;quot; | Required for Static (page)?&lt;br /&gt;
! Reported for&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || custom || Optional || Optional || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| subbrand || VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || custom || Optional || Optional || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*audio / video – &amp;quot;content&amp;quot;&lt;br /&gt;
*page – &amp;quot;static&amp;quot;&lt;br /&gt;
*ad – &amp;quot;preroll&amp;quot;, &amp;quot;midroll&amp;quot; or &amp;quot;postroll&amp;quot;&lt;br /&gt;
|| &amp;quot;content&amp;quot;, &amp;quot;static&amp;quot; || Mandatory || Mandatory || &lt;br /&gt;
|-&lt;br /&gt;
| assetid || ID assigned to content. '''Must be unique and consistent''' across all content at the episode level, across platforms. || custom&amp;lt;br&amp;gt;(no [[Special Characters]]) || Mandatory || Not Required || &lt;br /&gt;
|-&lt;br /&gt;
| section || Section of site || custom || Not Required || Mandatory || &lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
*&amp;quot;y&amp;quot; or &amp;quot;lf&amp;quot; - full episode&lt;br /&gt;
*&amp;quot;n&amp;quot; or &amp;quot;sf&amp;quot; - short form&lt;br /&gt;
|| Mandatory || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name || custom || Mandatory || Not Required || Audio / Video Measurement&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title || custom || Mandatory || Not Required || Audio / Video Measurement&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. 0 may be used for Live content if the exact content length is not known.  || custom || Mandatory || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| segA || Segment A (this is not available for audio / video Measurement reporting as the episode title is reported) || custom || Not Required || Not Required || Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| segB || Segment B || custom || Not Required || Not Required || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| segC || Segment C || custom || Not Required || Not Required || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| crossId1 || Standard episode ID. Gracenote/TMS ID should be used when available. Must be unique per episode. || custom || Optional || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| crossId2 || Content originator (required only for distributors) || custom || Optional || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (Eastern Time for US) || YYYYMMDD HH24:MI:SS || Mandatory || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| pipmode ||&lt;br /&gt;
Current state of picture-in-picture (PIP) mode on device.&lt;br /&gt;
*&amp;quot;true&amp;quot; if audio / video measurement is displayed in PIP mode&lt;br /&gt;
*&amp;quot;false&amp;quot; if audio / video measurement is displayed in regular mode&lt;br /&gt;
|| &amp;quot;true&amp;quot;, &amp;quot;false&amp;quot; || Optional || Not Required || Audio / Video Measurement&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;quot;1&amp;quot; - Linear&lt;br /&gt;
&amp;quot;2&amp;quot; - Dynamic&lt;br /&gt;
|| Mandatory for DCR || Not Required || DCR &lt;br /&gt;
|-&lt;br /&gt;
| adModel ||&lt;br /&gt;
Type of ad model:&lt;br /&gt;
#Linear - matches TV ad load&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;quot;1&amp;quot; - Linear&lt;br /&gt;
&amp;quot;2&amp;quot; - Dynamic&lt;br /&gt;
|| Mandatory for DTVR || Not Required || DTVR&lt;br /&gt;
|-&lt;br /&gt;
| progen || Genre (required only for non-TV originated content). See [[DCR OTT Genre List]] for acceptable values. || e.g. DD for Daytime Drama || Required for non-TV content || Not Required&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''clientid &amp;amp; subbrand (vcid)'''&lt;br /&gt;
By default, clientid and subbrand are setup in Nielsen backend configuration to capture brand and sub-brand information. The fields get populated from backend for a registered client appid. But if an app contains multiple brands and sub-brands and client is willing to give credit to another brand or sub-brand then :&lt;br /&gt;
*Client app developer can override the clientid and subbrand (brand and sub-brand info.) in [[loadMetadata]] call to get a proper measurement for a desired brand and sub-brand.&lt;br /&gt;
**If no clientid and subbrand are specified in CMS of a content and an ad, default values reported in the Configuration will be reported.&lt;br /&gt;
**If clientid and subbrand are specified in CMS of the content or ad, the most recent clientid and subbrand will be reported in subsequent pings. To report with a different clientid and subbrand, include the new values for the keys in their subsequent [[loadMetadata]] call.&lt;br /&gt;
'''Picture-in-picture (PIP) mode'''&lt;br /&gt;
Once the app detects PIP mode, call [[loadMetadata]] with the same set of assetids, values and with one additional parameter &amp;quot;pipmode&amp;quot;: &amp;quot;true&amp;quot;. Once PIP mode is disabled in the device, call [[loadMetadata]] again with &amp;quot;pipmode&amp;quot;:&amp;quot;false&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Custom Variables Extension ====&lt;br /&gt;
Contact Nielsen Technical Account Manager (TAM) to configure any custom variables, as needed for implementing the application.&lt;br /&gt;
&lt;br /&gt;
See [[Custom Variables Extension]] for more information.&lt;br /&gt;
&lt;br /&gt;
==== Advertisement Metadata ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required for Audio / Video? !! Required for Static (page)&lt;br /&gt;
|-&lt;br /&gt;
| type || Type of ad || &amp;quot;preroll&amp;quot;&lt;br /&gt;
&amp;quot;midroll&amp;quot;&lt;br /&gt;
&amp;quot;postroll&amp;quot; &lt;br /&gt;
|| Mandatory || Not Required&lt;br /&gt;
|-&lt;br /&gt;
| assetid || An ID assigned to the advertisement. Can be an internal ID, an ID provided by the ad server, or a randomly generated ID. Must be unique across all ads || custom || Mandatory || Not Required&lt;br /&gt;
|-&lt;br /&gt;
| title || Title of the advertisement || &amp;quot;MyAdName&amp;quot; || Mandatory || Not Required&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Passing Metadata ===&lt;br /&gt;
The required metadata can be passed as key values through the loadMetadata method. The sample code below shows a metadata objects for various assets.&lt;br /&gt;
'''Audio / Video Measurement Asset'''&lt;br /&gt;
Type should be &amp;quot;content&amp;quot;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
       &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
       &amp;quot;assetName&amp;quot;: &amp;quot;myassetName&amp;quot;,&lt;br /&gt;
       &amp;quot;length&amp;quot;: &amp;quot;300.0&amp;quot;,&lt;br /&gt;
       &amp;quot;title&amp;quot;: &amp;quot;myTitle&amp;quot;,&lt;br /&gt;
       &amp;quot;program&amp;quot;: &amp;quot;myProgram&amp;quot;,&lt;br /&gt;
       &amp;quot;censuscategory&amp;quot;: &amp;quot;myCensusCategory&amp;quot;,&lt;br /&gt;
       &amp;quot;assetid&amp;quot;: &amp;quot;myAssetId&amp;quot;,&lt;br /&gt;
       &amp;quot;channelName&amp;quot;: &amp;quot;myChannel&amp;quot;,&lt;br /&gt;
       &amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
       &amp;quot;segB&amp;quot;: &amp;quot;segmentB&amp;quot;,&lt;br /&gt;
       &amp;quot;segC&amp;quot;: &amp;quot;segmentC&amp;quot;,&lt;br /&gt;
       &amp;quot;isfullepisode&amp;quot;:&amp;quot;y&amp;quot;,&lt;br /&gt;
       &amp;quot;crossId1&amp;quot;: &amp;quot;Reference11&amp;quot;,&lt;br /&gt;
       &amp;quot;crossId2&amp;quot;: &amp;quot;Reference22&amp;quot;,&lt;br /&gt;
       &amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Static (Page) Measurement Asset'''&lt;br /&gt;
Type should be &amp;quot;static&amp;quot;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
       &amp;quot;type&amp;quot;: &amp;quot;static&amp;quot;,&lt;br /&gt;
       &amp;quot;assetid&amp;quot;: &amp;quot;static123&amp;quot;,&lt;br /&gt;
       &amp;quot;assetName&amp;quot;: &amp;quot;Page-Asset&amp;quot;,&lt;br /&gt;
       &amp;quot;section&amp;quot;: &amp;quot;siteSection&amp;quot;,&lt;br /&gt;
       &amp;quot;segA&amp;quot;: &amp;quot;segmentA&amp;quot;,&lt;br /&gt;
       &amp;quot;segB&amp;quot;: &amp;quot;segmentB&amp;quot;,&lt;br /&gt;
       &amp;quot;segC&amp;quot;: &amp;quot;segmentC&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''For any of the ad types'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;midroll&amp;quot;,&lt;br /&gt;
        &amp;quot;length&amp;quot;: &amp;quot;30.0&amp;quot;,&lt;br /&gt;
        &amp;quot;assetid&amp;quot;: &amp;quot;myMidrollAssetId&amp;quot;,&lt;br /&gt;
        &amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
        &amp;quot;tv&amp;quot;: &amp;quot;true&amp;quot;,&lt;br /&gt;
        &amp;quot;dataSrc&amp;quot;: &amp;quot;cms&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': In case the individual ad details are not available, send ad pod (presence) details through the &amp;lt;code&amp;gt;loadMetadata&amp;lt;/code&amp;gt; and playhead position through &amp;lt;code&amp;gt;setPlayheadPosition&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''loadMetadata'''&lt;br /&gt;
The object can then be passed when calling [[loadMetadata]].&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;    loadMetadata(jsonMetadataObject);&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=DCR_Static_Google_AMP_Cloud_API&amp;diff=2621</id>
		<title>DCR Static Google AMP Cloud API</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=DCR_Static_Google_AMP_Cloud_API&amp;diff=2621"/>
		<updated>2018-03-20T22:45:04Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Metadata Keys */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR &amp;amp; DTVR}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show you how to enable Digital Content Ratings (DCR) Static measurement on Google AMP.&lt;br /&gt;
&lt;br /&gt;
== Import AMP Analytics Javascript Library ==&lt;br /&gt;
If you have not already, you will need to import the AMP JS library in the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; of your webpage in order to make an AMP page:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script async src=&amp;quot;https://cdn.ampproject.org/v0.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Next, please ensure that the following line is included in the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; of the webpage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script async custom-element=&amp;quot;amp-analytics&amp;quot; src=&amp;quot;https://cdn.ampproject.org/v0/amp-analytics-0.1.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': AMP pages require all traffic to be using HTTPS, including the webpage itself&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Specify the Analytics Provider ==&lt;br /&gt;
DCR measurement can be added to your AMP pages through the AMP-Analytics element:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;amp-analytics type=&amp;quot;nielsen&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Add Nielsen DCR Tags here --&amp;gt;&lt;br /&gt;
&amp;lt;/amp-analytics&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information on the Analytics type, you can refer to the [https://www.ampproject.org/docs/guides/analytics/analytics-vendors Analytics vendors] section of Google's AMP Developer Documentation.&lt;br /&gt;
&lt;br /&gt;
== Configure Metadata ==&lt;br /&gt;
You will need to match the metadata fields on your AMP page with those of your non-AMP page.&lt;br /&gt;
&lt;br /&gt;
=== Metadata Keys ===&lt;br /&gt;
The Nielsen reserved keys are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Example Value !! Required&lt;br /&gt;
|-&lt;br /&gt;
| apid || unique ID assigned by Nielsen || &amp;lt;code&amp;gt;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| apv || current version of the Nielsen implementation || &amp;lt;code&amp;gt;1.0&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| apn || name of the website || &amp;lt;code&amp;gt;My AMP Website&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| section || section of the site to be measured || &amp;lt;code&amp;gt;Entertainment&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| segA || custom segment to be used to break out reporting || &amp;lt;code&amp;gt;Music&amp;lt;/code&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
| segB || custom segment to be used to break out reporting || &amp;lt;code&amp;gt;News&amp;lt;/code&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
| segC || Reserved custom segment for Google AMP || &amp;lt;code&amp;gt;Google AMP&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The values passed through the Nielsen keys will determine the breakouts you will see in reporting. If you decide not to use custom segments A and B, then you do not need to pass a value in these keys. It is suggested you use the same segments used in non-AMP pages.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': The value for the 'apid' you pass for AMP measurement should not include the 'P' prefix that is otherwise present on other SDK-related implementations&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Metadata for Reporting ===&lt;br /&gt;
You can reference the table to determine how the metadata you pass is used to define your reporting structure:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Reporting Level !! Key !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Brand/Sub-brand || apid || brand and sub-brand are determined by assigned App ID passed during initialization&lt;br /&gt;
|-&lt;br /&gt;
| Section || section || section or category for the AMP page&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment A || segA || available segment for custom reporting. Custom segments will roll into the sub-brand&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment B || segB || available segment for custom reporting. Custom segments will roll into the sub-brand&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment C || segC || Custom segment C is reserved for reporting ‘Google AMP’. The Google AMP custom segment will be available under sub-brand and will include the total metrics for all your AMP pages&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you would like your AMP pages to report into the same reporting structure as your website, we recommend passing the same dynamic metadata in Section, Custom Segment A, and Custom Segment B as you are on your website. This way your AMP pageviews contribute to those aggregations.&lt;br /&gt;
&lt;br /&gt;
=== Aggregation Limits ===&lt;br /&gt;
There are limits on the number of unique values that can be aggregated on in reporting. The specific limitations by key are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Aggregation Limit&lt;br /&gt;
|-&lt;br /&gt;
| section || maximum of 25 unique values (section &amp;lt;= 25)&lt;br /&gt;
|-&lt;br /&gt;
| segA || total sum of segA, segB, and segC must be a maximum of 24 unique values (segA + segB + segC &amp;lt;= 24)&lt;br /&gt;
|-&lt;br /&gt;
| segB || total sum of segA, segB, and segC must be a maximum of 24 unique values (segA + segB + segC &amp;lt;= 24)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Example Implementation ==&lt;br /&gt;
The below is an example implementation of Nielsen measurement on an AMP page:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;amp-analytics type=&amp;quot;nielsen&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;application/json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;vars&amp;quot;: {&lt;br /&gt;
        &amp;quot;apid&amp;quot;: &amp;quot;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
        &amp;quot;apv&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
        &amp;quot;apn&amp;quot;: &amp;quot;My AMP Website&amp;quot;,&lt;br /&gt;
        &amp;quot;section&amp;quot;: &amp;quot;Entertainment&amp;quot;,&lt;br /&gt;
        &amp;quot;segA&amp;quot;: &amp;quot;Music&amp;quot;,&lt;br /&gt;
        &amp;quot;segB&amp;quot;: &amp;quot;News&amp;quot;,&lt;br /&gt;
        &amp;quot;segC&amp;quot;: &amp;quot;Google AMP&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/amp-analytics&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can find more information about dynamic variables on [https://github.com/ampproject/amphtml/blob/master/spec/amp-var-substitutions.md#page-and-content Google's AMP documentation].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': append &amp;lt;code&amp;gt;#development=1&amp;lt;/code&amp;gt; at the end of your URL to see AMP debug logs in the console. This can be helpful when troubleshooting&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Privacy Policy ==&lt;br /&gt;
Nielsen uses cookies for browser measurement. In order to comply with our privacy restrictions, we ask that you make a link to our Digital Privacy Policy available on your site. You can find our privacy policy here: &lt;br /&gt;
http://priv-policy.imrworldwide.com/priv/browser/us/en/optout.html&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=DCR_%26_DTVR&amp;diff=2430</id>
		<title>DCR &amp; DTVR</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=DCR_%26_DTVR&amp;diff=2430"/>
		<updated>2018-01-29T14:13:15Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Plugins */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
{{CategoryIcon|DCR.png|Digital Content Ratings (DCR) &amp;amp; Digital in TV Ratings (DTVR)}}&lt;br /&gt;
&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 42%;&amp;quot; | General Reference&lt;br /&gt;
!&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;7&amp;quot; | {{SmallIcon|DigitalIcon.png}}&lt;br /&gt;
| '''[[Digital Measurement Onboarding]]'''&lt;br /&gt;
| '''[[Digital Measurement Metadata]]'''&lt;br /&gt;
|-&lt;br /&gt;
| '''[[Digital Measurement Testing]]'''&lt;br /&gt;
| '''[[Digital Measurement Interruption Scenarios]]'''&lt;br /&gt;
|-&lt;br /&gt;
| '''[[Digital Measurement FAQ]]'''&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| '''[[Digital Pre-Certification Checklist App SDK]]'''&lt;br /&gt;
| '''[[Digital Pre-Certification Checklist Browser SDK]]'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== SDK - Video ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; | Type&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | OS&lt;br /&gt;
! style=&amp;quot;width: 30%;&amp;quot; | DCR Implementation Guide&lt;br /&gt;
! style=&amp;quot;width: 25%;&amp;quot; | DTVR Implementation Guide&lt;br /&gt;
!| SDK Documentation&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;7&amp;quot; | {{SmallIcon|SDKIcon.png|alt=SDK}}&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | {{OSIcon|VideoIcon.png|alt=Video}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png|alt=iOS}}&lt;br /&gt;
| '''[[DCR Video iOS SDK]]'''&lt;br /&gt;
| '''[[DTVR iOS SDK]]'''&lt;br /&gt;
| [[iOS SDK API Reference]]&lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|AndroidIcon.png|alt=Android}}&lt;br /&gt;
| '''[[DCR Video Android SDK]]'''&lt;br /&gt;
| '''[[DTVR Android SDK]]'''&lt;br /&gt;
| [[Android SDK API Reference]]&lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|BrowserIcon.png|alt=Browser}}&lt;br /&gt;
| '''[[DCR Video Browser SDK]]'''&lt;br /&gt;
| '''[[DTVR Browser SDK]]'''&lt;br /&gt;
| [[Browser SDK API Reference]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== SDK - Static ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; | Type&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | OS&lt;br /&gt;
! style=&amp;quot;width: 55%;&amp;quot; | DCR Implementation Guide&lt;br /&gt;
!| SDK Documentation&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;6&amp;quot; | {{SmallIcon|SDKIcon.png|alt=SDK}}&lt;br /&gt;
| rowspan=&amp;quot;7&amp;quot; | {{OSIcon|StaticIcon.png|alt=Static Content}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png|alt=iOS}}&lt;br /&gt;
| '''[[DCR Static iOS SDK]]'''&lt;br /&gt;
| [[iOS SDK API Reference]]&lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|AndroidIcon.png|alt=Android}}&lt;br /&gt;
| '''[[DCR Static Android SDK]]'''&lt;br /&gt;
| [[Android SDK API Reference]]&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | {{OSIcon|BrowserIcon.png|alt=Browser}}&lt;br /&gt;
| '''[[DCR Static Browser SDK]]'''&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | [[Browser SDK API Reference]]&lt;br /&gt;
|-&lt;br /&gt;
| '''[[DCR Static Lite Browser SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
|  {{OSIcon|GoogleTagManagerIcon.png|alt=Google Tag Manager}}&lt;br /&gt;
| '''[[DCR Static Google Tag Manager]]'''&lt;br /&gt;
|-&lt;br /&gt;
|  {{OSIcon|FacebookIcon.png|alt=Facebook Instant Articles}}&lt;br /&gt;
| '''[[DCR Static Facebook Instant Articles Browser SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|  {{OSIcon|AMPIcon.png|alt=Google AMP}}&lt;br /&gt;
| '''[[DCR Static Google AMP Cloud API]]'''&lt;br /&gt;
| N/A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Cloud API ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; | Type&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | OS&lt;br /&gt;
!| DCR Implementation Guide&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | {{SmallIcon|CloudAPIIcon.png|alt=Cloud API}} &lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; |&lt;br /&gt;
{{OSIcon|VideoIcon.png|alt=Video}}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{OSIcon|StaticIcon.png|alt=Static Content}}&lt;br /&gt;
| {{OSIcon|APIIcon.png|alt=Cloud API}}&lt;br /&gt;
| '''[[DCR Video &amp;amp; Static Cloud API ]]''' &lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|APIIcon.png|alt=Cloud API}}&lt;br /&gt;
| '''[[DCR Video &amp;amp; Static Mobile Cloud API ]]'''&lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|RokuIcon.png|alt=Roku}}&lt;br /&gt;
| '''[[DCR Video &amp;amp; Static Roku Cloud API]]'''&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=International&amp;diff=2429</id>
		<title>International</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=International&amp;diff=2429"/>
		<updated>2018-01-29T14:12:33Z</updated>

		<summary type="html">&lt;p&gt;Admin2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
{{CategoryIcon|International.png|International}}&lt;br /&gt;
&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Please contact your Nielsen representative for documentation if the guides for your country aren't listed.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | Downloads&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width: 90px;&amp;quot; |{{SmallIcon|DownloadIcon.png|alt=Cloud API}} &lt;br /&gt;
|style=&amp;quot;width: 90px;&amp;quot; | {{SmallIcon|SDKIcon.png}}&lt;br /&gt;
| '''[[Digital Downloads|SDK Downloads]]'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; | Germany&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | &lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | OS&lt;br /&gt;
!| Guide&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;6&amp;quot; | {{SmallIcon|DEFlagIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;6&amp;quot; | {{SmallIcon|SDKIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | {{OSIcon|VideoIcon.png}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png}}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{OSIcon|AndroidIcon.png}}&lt;br /&gt;
| '''[[DCR Germany Video App SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|BrowserIcon.png}}&lt;br /&gt;
| '''[[DCR Germany Video Browser SDK]]'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; | Italy&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | &lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | OS&lt;br /&gt;
!| Guide&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;7&amp;quot; | {{SmallIcon|ITFlagIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;7&amp;quot; | {{SmallIcon|SDKIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | {{OSIcon|VideoIcon.png}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png}}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{OSIcon|AndroidIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Video App SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | {{OSIcon|BrowserIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Video Browser SDK (6.0.0)]]'''&lt;br /&gt;
|-&lt;br /&gt;
| '''[[DCR Italy Video Browser SDK (6.0.1)]] Object Video only'''&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;5&amp;quot; | {{OSIcon|StaticIcon.png}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png}}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{OSIcon|AndroidIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Static App SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|BrowserIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Static Browser SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
|  {{OSIcon|FacebookIcon.png|alt=Facebook Instant Articles}}&lt;br /&gt;
| '''[[DCR Italy Static Facebook Instant Articles Browser SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
|  {{OSIcon|AMPIcon.png|alt=Google AMP}}&lt;br /&gt;
| '''[[DCR Italy Static Google AMP Cloud API]]'''&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=DCR_Italy_Static_Google_AMP_Cloud_API&amp;diff=2397</id>
		<title>DCR Italy Static Google AMP Cloud API</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=DCR_Italy_Static_Google_AMP_Cloud_API&amp;diff=2397"/>
		<updated>2018-01-25T17:55:34Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Metadata Keys */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR &amp;amp; DTVR}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show you how to enable Digital Content Ratings (DCR) Static measurement on Google AMP.&lt;br /&gt;
&lt;br /&gt;
== Import AMP Analytics Javascript Library ==&lt;br /&gt;
If you have not already, you will need to import the AMP JS library in the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; of your webpage in order to make an AMP page:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script async src=&amp;quot;https://cdn.ampproject.org/v0.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Next, please ensure that the following line is included in the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; of the webpage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script async custom-element=&amp;quot;amp-analytics&amp;quot; src=&amp;quot;https://cdn.ampproject.org/v0/amp-analytics-0.1.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': AMP pages require all traffic to be using HTTPS, including the webpage itself&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Specify the Analytics Provider ==&lt;br /&gt;
DCR measurement can be added to your AMP pages through the AMP-Analytics element:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;amp-analytics type=&amp;quot;nielsen&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Add Nielsen DCR Tags here --&amp;gt;&lt;br /&gt;
&amp;lt;/amp-analytics&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information on the Analytics type, you can refer to the [https://www.ampproject.org/docs/guides/analytics/analytics-vendors Analytics vendors] section of Google's AMP Developer Documentation.&lt;br /&gt;
&lt;br /&gt;
== Configure Metadata ==&lt;br /&gt;
You will need to match the metadata fields on your AMP page with those of your non-AMP page.&lt;br /&gt;
&lt;br /&gt;
=== Metadata Keys ===&lt;br /&gt;
The Nielsen reserved keys are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Example Value !! Required&lt;br /&gt;
|-&lt;br /&gt;
| apid || unique ID assigned by Nielsen || &amp;lt;code&amp;gt;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| prefix || URL prefix to allow EU data collection || &amp;lt;code&amp;gt;eu-&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| apv || current version of the Nielsen implementation || &amp;lt;code&amp;gt;1.0&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| apn || name of the website || &amp;lt;code&amp;gt;My AMP Website&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| section || section of the site to be measured || &amp;lt;code&amp;gt;Entertainment&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| segA || custom segment to be used to break out reporting || &amp;lt;code&amp;gt;Music&amp;lt;/code&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
| segB || custom segment to be used to break out reporting || &amp;lt;code&amp;gt;News&amp;lt;/code&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
| segC || Reserved custom segment for Google AMP || &amp;lt;code&amp;gt;Google AMP&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The values passed through the Nielsen keys will determine the breakouts you will see in reporting. If you decide not to use custom segments A and B, then you do not need to pass a value in these keys. It is suggested you use the same segments used in non-AMP pages.&lt;br /&gt;
&lt;br /&gt;
=== Metadata for Reporting ===&lt;br /&gt;
You can reference the table to determine how the metadata you pass is used to define your reporting structure:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Reporting Level !! Key !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Brand/Sub-brand || apid || brand and sub-brand are determined by assigned App ID passed during initialization&lt;br /&gt;
|-&lt;br /&gt;
| Section || section || section or category for the AMP page&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment A || segA || available segment for custom reporting. Custom segments will roll into the sub-brand&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment B || segB || available segment for custom reporting. Custom segments will roll into the sub-brand&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment C || segC || Custom segment C is reserved for reporting ‘Google AMP’. The Google AMP custom segment will be available under sub-brand and will include the total metrics for all your AMP pages&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you would like your AMP pages to report into the same reporting structure as your website, we recommend passing the same dynamic metadata in Section, Custom Segment A, and Custom Segment B as you are on your website. This way your AMP pageviews contribute to those aggregations.&lt;br /&gt;
&lt;br /&gt;
=== Aggregation Limits ===&lt;br /&gt;
There are limits on the number of unique values that can be aggregated on in reporting. The specific limitations by key are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Aggregation Limit&lt;br /&gt;
|-&lt;br /&gt;
| section || maximum of 25 unique values (section &amp;lt;= 25)&lt;br /&gt;
|-&lt;br /&gt;
| segA || total sum of segA, segB, and segC must be a maximum of 24 unique values (segA + segB + segC &amp;lt;= 24)&lt;br /&gt;
|-&lt;br /&gt;
| segB || total sum of segA, segB, and segC must be a maximum of 24 unique values (segA + segB + segC &amp;lt;= 24)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Example Implementation ==&lt;br /&gt;
The below is an example implementation of Nielsen measurement on an AMP page:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;amp-analytics type=&amp;quot;nielsen&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;application/json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;vars&amp;quot;: {&lt;br /&gt;
        &amp;quot;apid&amp;quot;: &amp;quot;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
        &amp;quot;prefix&amp;quot;: &amp;quot;eu-&amp;quot;,&lt;br /&gt;
        &amp;quot;apv&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
        &amp;quot;apn&amp;quot;: &amp;quot;My AMP Website&amp;quot;,&lt;br /&gt;
        &amp;quot;section&amp;quot;: &amp;quot;Entertainment&amp;quot;,&lt;br /&gt;
        &amp;quot;segA&amp;quot;: &amp;quot;Music&amp;quot;,&lt;br /&gt;
        &amp;quot;segB&amp;quot;: &amp;quot;News&amp;quot;,&lt;br /&gt;
        &amp;quot;segC&amp;quot;: &amp;quot;Google AMP&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/amp-analytics&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can find more information about dynamic variables on [https://github.com/ampproject/amphtml/blob/master/spec/amp-var-substitutions.md#page-and-content Google's AMP documentation].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': append &amp;lt;code&amp;gt;#development=1&amp;lt;/code&amp;gt; at the end of your URL to see AMP debug logs in the console. This can be helpful when troubleshooting&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Privacy Policy ==&lt;br /&gt;
Nielsen uses cookies for browser measurement. In order to comply with our privacy restrictions, we ask that you make a link to our Digital Privacy Policy available on your site. You can find our privacy policy here: &lt;br /&gt;
http://www.nielsen.com/digitalprivacy#choice&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=DCR_Italy_Static_Google_AMP_Cloud_API&amp;diff=2375</id>
		<title>DCR Italy Static Google AMP Cloud API</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=DCR_Italy_Static_Google_AMP_Cloud_API&amp;diff=2375"/>
		<updated>2018-01-24T16:50:52Z</updated>

		<summary type="html">&lt;p&gt;Admin2: Created page with &amp;quot;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR &amp;amp; DTVR}}  {{CurrentBreadcrumb}} Category:Digital  This guide will show you how to enable Digital Content Ratings (D...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR &amp;amp; DTVR}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show you how to enable Digital Content Ratings (DCR) Static measurement on Google AMP.&lt;br /&gt;
&lt;br /&gt;
== Import AMP Analytics Javascript Library ==&lt;br /&gt;
If you have not already, you will need to import the AMP JS library in the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; of your webpage in order to make an AMP page:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script async src=&amp;quot;https://cdn.ampproject.org/v0.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Next, please ensure that the following line is included in the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; of the webpage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script async custom-element=&amp;quot;amp-analytics&amp;quot; src=&amp;quot;https://cdn.ampproject.org/v0/amp-analytics-0.1.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': AMP pages require all traffic to be using HTTPS, including the webpage itself&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Specify the Analytics Provider ==&lt;br /&gt;
DCR measurement can be added to your AMP pages through the AMP-Analytics element:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;amp-analytics type=&amp;quot;nielsen&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Add Nielsen DCR Tags here --&amp;gt;&lt;br /&gt;
&amp;lt;/amp-analytics&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information on the Analytics type, you can refer to the [https://www.ampproject.org/docs/guides/analytics/analytics-vendors Analytics vendors] section of Google's AMP Developer Documentation.&lt;br /&gt;
&lt;br /&gt;
== Configure Metadata ==&lt;br /&gt;
You will need to match the metadata fields on your AMP page with those of your non-AMP page.&lt;br /&gt;
&lt;br /&gt;
=== Metadata Keys ===&lt;br /&gt;
The Nielsen reserved keys are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Example Value !! Required&lt;br /&gt;
|-&lt;br /&gt;
| apid || unique ID assigned by Nielsen || &amp;lt;code&amp;gt;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| apv || current version of the Nielsen implementation || &amp;lt;code&amp;gt;1.0&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| apn || name of the website || &amp;lt;code&amp;gt;My AMP Website&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| section || section of the site to be measured || &amp;lt;code&amp;gt;Entertainment&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| segA || custom segment to be used to break out reporting || &amp;lt;code&amp;gt;Music&amp;lt;/code&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
| segB || custom segment to be used to break out reporting || &amp;lt;code&amp;gt;News&amp;lt;/code&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
| segC || Reserved custom segment for Google AMP || &amp;lt;code&amp;gt;Google AMP&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The values passed through the Nielsen keys will determine the breakouts you will see in reporting. If you decide not to use custom segments A and B, then you do not need to pass a value in these keys. It is suggested you use the same segments used in non-AMP pages.&lt;br /&gt;
&lt;br /&gt;
=== Metadata for Reporting ===&lt;br /&gt;
You can reference the table to determine how the metadata you pass is used to define your reporting structure:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Reporting Level !! Key !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Brand/Sub-brand || apid || brand and sub-brand are determined by assigned App ID passed during initialization&lt;br /&gt;
|-&lt;br /&gt;
| Section || section || section or category for the AMP page&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment A || segA || available segment for custom reporting. Custom segments will roll into the sub-brand&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment B || segB || available segment for custom reporting. Custom segments will roll into the sub-brand&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment C || segC || Custom segment C is reserved for reporting ‘Google AMP’. The Google AMP custom segment will be available under sub-brand and will include the total metrics for all your AMP pages&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you would like your AMP pages to report into the same reporting structure as your website, we recommend passing the same dynamic metadata in Section, Custom Segment A, and Custom Segment B as you are on your website. This way your AMP pageviews contribute to those aggregations.&lt;br /&gt;
&lt;br /&gt;
=== Aggregation Limits ===&lt;br /&gt;
There are limits on the number of unique values that can be aggregated on in reporting. The specific limitations by key are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Aggregation Limit&lt;br /&gt;
|-&lt;br /&gt;
| section || maximum of 25 unique values (section &amp;lt;= 25)&lt;br /&gt;
|-&lt;br /&gt;
| segA || total sum of segA, segB, and segC must be a maximum of 24 unique values (segA + segB + segC &amp;lt;= 24)&lt;br /&gt;
|-&lt;br /&gt;
| segB || total sum of segA, segB, and segC must be a maximum of 24 unique values (segA + segB + segC &amp;lt;= 24)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Example Implementation ==&lt;br /&gt;
The below is an example implementation of Nielsen measurement on an AMP page:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;amp-analytics type=&amp;quot;nielsen&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;application/json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;vars&amp;quot;: {&lt;br /&gt;
        &amp;quot;apid&amp;quot;: &amp;quot;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
        &amp;quot;prefix&amp;quot;: &amp;quot;eu-&amp;quot;,&lt;br /&gt;
        &amp;quot;apv&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
        &amp;quot;apn&amp;quot;: &amp;quot;My AMP Website&amp;quot;,&lt;br /&gt;
        &amp;quot;section&amp;quot;: &amp;quot;Entertainment&amp;quot;,&lt;br /&gt;
        &amp;quot;segA&amp;quot;: &amp;quot;Music&amp;quot;,&lt;br /&gt;
        &amp;quot;segB&amp;quot;: &amp;quot;News&amp;quot;,&lt;br /&gt;
        &amp;quot;segC&amp;quot;: &amp;quot;Google AMP&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/amp-analytics&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can find more information about dynamic variables on [https://github.com/ampproject/amphtml/blob/master/spec/amp-var-substitutions.md#page-and-content Google's AMP documentation].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': append &amp;lt;code&amp;gt;#development=1&amp;lt;/code&amp;gt; at the end of your URL to see AMP debug logs in the console. This can be helpful when troubleshooting&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Privacy Policy ==&lt;br /&gt;
Nielsen uses cookies for browser measurement. In order to comply with our privacy restrictions, we ask that you make a link to our Digital Privacy Policy available on your site. You can find our privacy policy here: &lt;br /&gt;
http://www.nielsen.com/digitalprivacy#choice&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Brightcove_Plugin_Browser&amp;diff=1887</id>
		<title>Brightcove Plugin Browser</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Brightcove_Plugin_Browser&amp;diff=1887"/>
		<updated>2017-11-02T18:27:02Z</updated>

		<summary type="html">&lt;p&gt;Admin2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR &amp;amp; DTVR}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
The Nielsen Browser SDK (Software Development Kit) is the Nielsen framework for measuring media consumption in browser environments.&lt;br /&gt;
&lt;br /&gt;
{{PluginInfobox&lt;br /&gt;
|pluginImage=BrightcoveIcon&lt;br /&gt;
|osImage=BrowserIcon&lt;br /&gt;
|playerVersion=5.18.0 - 5.22.0&lt;br /&gt;
|SDKVersion=5.1.1&lt;br /&gt;
|supportedAdFrameworks=&lt;br /&gt;
}}.&lt;br /&gt;
&lt;br /&gt;
This SDK has the following features:&lt;br /&gt;
* '''Multiple product support''': built-in capabilities to support Digital Content Ratings(DCR), VideoCensus(VC), Digital Program Ratings(DPR) and IAG.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''':  The Brightcove Plugin 5.1.0.9 is compatible with the Brightcove V5 player version 5.17 and 5.22.2. Brightcove V5 player 5.18 through 5.22.0 should not be used with the version 5.1.0.9 of the plugin.&lt;br /&gt;
&lt;br /&gt;
All of the player issues that would have impacted measurement have been fixed in 5.22.2. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
=== What You Will Need? ===&lt;br /&gt;
* '''Nielsen App ID (apid)''': a Unique ID that Nielsen assigns to the site / player. The 'apid' will be provided by your Technical Account Manager.&lt;br /&gt;
* '''BrightCove Plugin''': Plugin URLs are provided in the below [[#URL|section]].&lt;br /&gt;
* '''Test Environment Validation''': before you move into production, Nielsen must validate the SDK integration in a test environment.&lt;br /&gt;
&lt;br /&gt;
=== Initial Configuration ===&lt;br /&gt;
Before integrating the plugin, configure the metadata, obtain Nielsen APID's, and review the Nielsen plugin URLs for Brightcove.&lt;br /&gt;
&lt;br /&gt;
=== Obtain the Nielsen Application ID (apid) ===&lt;br /&gt;
The Nielsen apid is required to enable SDK functionality. Your Technical Account Manager will provide two apids for each player configuration&lt;br /&gt;
* Test apid: use this apid during development and testing&lt;br /&gt;
* Production apid: use this apid in your production environment after Nielsen has tested and qualified the player.&lt;br /&gt;
&lt;br /&gt;
=== Brightcove Plugin URL's ===&lt;br /&gt;
* BC Perform Player (JS)&lt;br /&gt;
** http://cdn-gl.imrworldwide.com/novms/bc/3/ggng510.js&lt;br /&gt;
** https://cdn-gl.imrworldwide.com/novms/bc/3/ggng510.js&lt;br /&gt;
&lt;br /&gt;
=== Global Parameters ===&lt;br /&gt;
To initialize the Nielsen Browser SDK, pass four global parameters when adding the BC Perform plugin.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site. There are two IDs provided || &amp;lt;code&amp;gt;'XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&amp;lt;/code&amp;gt;&lt;br /&gt;
* Test: begins with 'T' and is used for testing&lt;br /&gt;
* Production: begins with 'P' and is used in live environment when testing and certification is completed.&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Location of collection environment. During testing, all traffic should be directed to 'dcr-cert'. || testing: &amp;lt;code&amp;gt;'dcr-cert'&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
production: &amp;lt;code&amp;gt;'dcr'&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| nsdkv || 	Nielsen SDK Version || &amp;lt;code&amp;gt;'511'&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| apn || User-defined string value for describing the player / site. || custom&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The below parameter is optional but recommended when testing implementation.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Nielsen SDK console logging that should be used while testing. Make sure to disable before moving the implementation to production. || &amp;lt;code&amp;gt;'INFO'&amp;lt;/code&amp;gt; – API calls&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'WARNING'&amp;lt;/code&amp;gt; – System level logs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'ERROR'&amp;lt;/code&amp;gt; – Error logs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'DEBUG'&amp;lt;/code&amp;gt; – Full logs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Configure Metadata ===&lt;br /&gt;
There are two types of metadata&lt;br /&gt;
* '''DCR Content Metadata''': identify content&lt;br /&gt;
* '''DCR Ad Metadata''': identify ad&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys.&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting. There are reserved Nielsen keys for collecting the required metadata.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Type !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || Type of asset || &amp;lt;code&amp;gt;'content'&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to asset || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program || Program Name || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || The original airdate for linear TV || &amp;lt;code&amp;gt;'20161013 20:00:00'&amp;lt;/code&amp;gt; || date || No&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds || &amp;lt;code&amp;gt;3600&amp;lt;/code&amp;gt; (86400 for lives tream)|| integer || Yes&lt;br /&gt;
|-&lt;br /&gt;
| segB || Custom Reporting Segment || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || No&lt;br /&gt;
|-&lt;br /&gt;
| segC || Custom Reporting Segment || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || No&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full Episode Flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;'y'&amp;lt;/code&amp;gt; - Full Episode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'n'&amp;lt;/code&amp;gt; - Non Full Episode &lt;br /&gt;
|| boolean || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || Distinguishes Dynamic vs Linear Ad Insertion ||&lt;br /&gt;
&amp;lt;code&amp;gt;'1'&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'2'&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| integer || Yes&lt;br /&gt;
|-&lt;br /&gt;
| crossId1 || Standard Episode ID || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| crossId2 || Content Originator ID || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || No&lt;br /&gt;
|-&lt;br /&gt;
| mediaURL || URL location of the content being streamed || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| hasAds || Distinguishes when content includes Ads ||&lt;br /&gt;
&amp;lt;code&amp;gt;'0'&amp;lt;/code&amp;gt; - No Ads&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'1'&amp;lt;/code&amp;gt; - Includes Ads&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'2'&amp;lt;/code&amp;gt; - Unknown&lt;br /&gt;
|| integer || Yes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Type !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || Type of ad ||&lt;br /&gt;
&amp;lt;code&amp;gt;'preroll'&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'midroll'&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'postroll'&amp;lt;/code&amp;gt;&lt;br /&gt;
|| string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''':There is a URL character limit of 2000 characters imposed due to browser limitations. Exceeding this value can impair data delivery on particular browsers.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
In order to integrate the Nielsen plugin, follow the steps for setting up these players in the Brightcove user interface as they appear below by each player type.&lt;br /&gt;
&lt;br /&gt;
=== Brightcove Player Setup ===&lt;br /&gt;
The new Brightcove Perform player allows two interchangeable ways to add the plugin: on the web site, so the player will come already configured, and programmatically on the client side.&lt;br /&gt;
&lt;br /&gt;
These options, as well as the whole process of adding a plugin is common to the player and described here http://support.brightcove.com/en/perform/docs/configuring-player-plugins&lt;br /&gt;
&lt;br /&gt;
==== For Nielsen SDK plugin, the integrator would need ====&lt;br /&gt;
* A list of initialization parameters (Application ID, App Name, sfcode, and nsdkv). Refer to [[#Global Parameters|Global Parameters]] section above.&lt;br /&gt;
* A link (URL) to SDK plugin (ggng510.js) for Brightcove&lt;br /&gt;
* A list of metadata fields with their names (Nielsen Key Mapping) to pass to the plugin. For more information, refer to [[#Configure Metadata|Configure Metadata]] section.&lt;br /&gt;
* Access to the Brightcove VideoCloud Perform Portal https://studio.brightcove.com/products/videocloud/home&lt;br /&gt;
&lt;br /&gt;
==== To add Nielsen SDK plugin using UI do the following ====&lt;br /&gt;
Open Brightcove VideoCloud portal, open players list and open (or create) a player the plugin should be added to.&lt;br /&gt;
Scroll down to the 'Plugins' section in player configuration&lt;br /&gt;
&lt;br /&gt;
[[File:Plugins-BC.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
* Click &amp;quot;Edit&amp;quot; and enter the URL to plugin JS file. Click &amp;quot;+&amp;quot; to add the row.&lt;br /&gt;
&lt;br /&gt;
[[File:js-BC.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
* Then click &amp;quot;Name, Options (JSON)&amp;quot; row and enter &amp;quot;NielsenBC&amp;quot; for the plugin name and required initialization parameters provided by your Nielsen Technical Account Manager, as below:&lt;br /&gt;
&lt;br /&gt;
[[File:Js-BC2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Example Code:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;nol_sdkDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;,&lt;br /&gt;
  &amp;quot;sfcode&amp;quot;: &amp;quot;dcr-cert&amp;quot;,&lt;br /&gt;
  &amp;quot;apn&amp;quot;: &amp;quot;Test_player_name&amp;quot;,&lt;br /&gt;
  &amp;quot;nsdkv&amp;quot;: &amp;quot;511&amp;quot;,&lt;br /&gt;
  &amp;quot;apid&amp;quot;: &amp;quot;T4BFBFAC9-XXXX-XXXX-XXXX-22B092CBCC2B&amp;quot;,&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Adding &amp;lt;code&amp;gt;&amp;quot;nol_sdkDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&amp;lt;/code&amp;gt; will allow SDK events in the console.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': &amp;lt;code&amp;gt;&amp;quot;nol_sdkDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&amp;lt;/code&amp;gt; must be removed when moving a player live to production to disable the debug logging.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Pass Content &amp;amp; Ad Metadata to The Brightcove Video Player ====&lt;br /&gt;
Pass the required content, and ad metadata to the Brightcove video player so that the Nielsen Plug-In is able to pick it up in order to populate the DCR crediting tags. The Nielsen Plug-In is preconfigured to automatically obtain metadata from Custom Fields. These can be set through the Brightcove User Interface (under ADMIN) or programmatically.&lt;br /&gt;
&lt;br /&gt;
Information on creating Custom Metadatafields can be found on the [https://support.brightcove.com/en/video-cloud/docs/creating-custom-metadata-fields|Brightcove Support site].&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If you are using the Brightcove player with the PERFORM service, you will need to populate the media info. Please contact Brightcove support for details on this process.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Video-Fields.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information on how to pass the required metadata to the Brightcove [https://www.brightcove.com/en/online-video-platform VideoCloud] player, please reach out to your Brightcove Account Manager for further assistance.&lt;br /&gt;
&lt;br /&gt;
==== To add Nielsen SDK programmatically ====&lt;br /&gt;
* Include plugin source&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script src=&amp;quot;//cdn-gl.imrworldwide.com/novms/bc/3/ggng510.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Bind plugin to the player with inititalization parameters&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;videojs(&amp;quot;myPlayerID&amp;quot;).NielsenBC(&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;apid&amp;quot;: &amp;quot;PXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
    &amp;quot;apn&amp;quot;: &amp;quot;Your_player_name&amp;quot;,&lt;br /&gt;
    &amp;quot;sfcode&amp;quot;: &amp;quot;dcr-cert&amp;quot;,&lt;br /&gt;
    &amp;quot;nsdkv&amp;quot;: &amp;quot;511&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* For CMS data binding, the following rules apply&lt;br /&gt;
* The plugin automatically captures the following video data&lt;br /&gt;
* * Data from video duration is automatically capture by the plugin&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nielsenData.length = videoInfo.duration;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* * Field &amp;quot;type&amp;quot; is set to &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* If video data contains custom fields, all those fields are copied over to Nielsen data: &amp;lt;code&amp;gt;nielsenData[i] = videoInfo.custom_fields[i]&amp;lt;/code&amp;gt; (with 'i' iterated over all custom field names), which may override some of the default values or standard field values&lt;br /&gt;
* '''The plugin does not automatically assign a value to assetid'''. To pass programmatically, use the custom fields object. (See code example below)&lt;br /&gt;
* Parameter videoInfo.id must be a unique string to allow the plugin detecting the content change.&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
* If some CMS metadata values should be set for all videos played, those values can be passed as &amp;quot;defaults&amp;quot; field on the player level (in the player configuration), like this&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;apid&amp;quot;: &amp;quot;PXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;apn&amp;quot;: &amp;quot;Your_player_name&amp;quot;,&lt;br /&gt;
  &amp;quot;sfcode&amp;quot;: &amp;quot;dcr&amp;quot;,&lt;br /&gt;
  &amp;quot;nsdkv&amp;quot;: &amp;quot;511&amp;quot;,&lt;br /&gt;
  &amp;quot;defaults&amp;quot;: { &amp;quot;customValue&amp;quot;: &amp;quot;true&amp;quot; }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* CMS metadata values can also be set at the asset level&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;sources&amp;quot; :&lt;br /&gt;
    [ {&lt;br /&gt;
      &amp;quot;src&amp;quot; : &amp;quot;http://solutions.brightcove.com/../videos/Sea_SeaHorse.mp4&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot; : &amp;quot;video/mp4&amp;quot;&lt;br /&gt;
    } ],&lt;br /&gt;
    &amp;quot;custom_fields&amp;quot;:&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;assetid&amp;quot;: &amp;quot;6475587654&amp;quot;,&lt;br /&gt;
        &amp;quot;mediaURL&amp;quot;: &amp;quot;http://solutions.brightcove.com/bcls/../videos/Sea_Anemone.mp4&amp;quot;,&lt;br /&gt;
        &amp;quot;dataSrc&amp;quot;: &amp;quot;cms&amp;quot;,&lt;br /&gt;
        &amp;quot;hasAds&amp;quot;: &amp;quot;1&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Sea Anemone&amp;quot;,&lt;br /&gt;
      &amp;quot;thumbnail&amp;quot;: &amp;quot;http://solutions.brightcove.com/bcls/assets/images/Sea_Anemone_poster.png&amp;quot;,&lt;br /&gt;
      &amp;quot;id&amp;quot;: &amp;quot;5195888503001&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Support ===&lt;br /&gt;
The plugin will also extract information about the number and length of advertisements played with the video.&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation ==&lt;br /&gt;
The site must provide a means for the user to opt out of, or opt back into Nielsen Measurement. A user can opt out if preferring to not participate in any Nielsen online measurement research. To implement the Opt-Out option, include the following in the privacy policy page:&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings)&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at http://www.nielsen.com/digitalprivacy&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click choices to read more detailed information about the measurement software and their options. The users can click a link to retrieve an Opt-Out cookie if they do not want to participate in Nielsen online measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen properties may feature Nielsen proprietary measurement software, which will allow the users to contribute to market research, such as Nielsen TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
=== Opt-In ===&lt;br /&gt;
Once users have opted out, they can choose to opt back into Nielsen Measurement at anytime by selecting the Opt-In link on the Nielsen Digital Privacy Policy page. When a user selects the link, their Opt-Out cookie will be deleted and they will be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
After the integration is certified, there is one update to be made to the existing code to ensure that the player will be measured properly:&lt;br /&gt;
*'''App ID''': Change the apid to the production ID starting with the letter 'P':&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;'PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* '''Collection Environment''': Change the value for &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; from &amp;lt;code&amp;gt;dcr-cert&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;dcr&amp;lt;/code&amp;gt; to point traffic to the Nielsen production collection environment. Do not use &amp;lt;code&amp;gt;dcr-cert&amp;lt;/code&amp;gt; for production traffic&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure that the &amp;lt;code&amp;gt;nol_sdkDebug&amp;lt;/code&amp;gt; parameter is not used.&amp;lt;/blockquote&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Brightcove_Plugin_Browser&amp;diff=1786</id>
		<title>Brightcove Plugin Browser</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Brightcove_Plugin_Browser&amp;diff=1786"/>
		<updated>2017-10-18T21:29:22Z</updated>

		<summary type="html">&lt;p&gt;Admin2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR &amp;amp; DTVR}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
The Nielsen Browser SDK (Software Development Kit) is the Nielsen framework for measuring media consumption in browser environments.&lt;br /&gt;
&lt;br /&gt;
{{PluginInfobox&lt;br /&gt;
|pluginImage=BrightcoveIcon&lt;br /&gt;
|osImage=BrowserIcon&lt;br /&gt;
|playerVersion=5.18.0 - 5.22.0&lt;br /&gt;
|SDKVersion=5.1.1&lt;br /&gt;
|supportedAdFrameworks=&lt;br /&gt;
}}.&lt;br /&gt;
&lt;br /&gt;
This SDK has the following features:&lt;br /&gt;
* '''Multiple product support''': built-in capabilities to support Digital Content Ratings(DCR), VideoCensus(VC), Digital Program Ratings(DPR) and IAG.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''':  The Brightcove Plugin 5.1.0.9 is compatible with the Brightcove V5 player version 5.17 and 5.22.2. &lt;br /&gt;
&lt;br /&gt;
All of the player issues that would have impacted measurement have been fixed in 5.22.2.&lt;br /&gt;
&lt;br /&gt;
Brightcove V5 player 5.18 through 5.22.0 should not be used with the plugin.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
=== What You Will Need? ===&lt;br /&gt;
* '''Nielsen App ID (apid)''': a Unique ID that Nielsen assigns to the site / player. The 'apid' will be provided by your Technical Account Manager.&lt;br /&gt;
* '''BrightCove Plugin''': Plugin URLs are provided in the below [[#URL|section]].&lt;br /&gt;
* '''Test Environment Validation''': before you move into production, Nielsen must validate the SDK integration in a test environment.&lt;br /&gt;
&lt;br /&gt;
=== Initial Configuration ===&lt;br /&gt;
Before integrating the plugin, configure the metadata, obtain Nielsen APID's, and review the Nielsen plugin URLs for Brightcove.&lt;br /&gt;
&lt;br /&gt;
=== Obtain the Nielsen Application ID (apid) ===&lt;br /&gt;
The Nielsen apid is required to enable SDK functionality. Your Technical Account Manager will provide two apids for each player configuration&lt;br /&gt;
* Test apid: use this apid during development and testing&lt;br /&gt;
* Production apid: use this apid in your production environment after Nielsen has tested and qualified the player.&lt;br /&gt;
&lt;br /&gt;
=== Brightcove Plugin URL's ===&lt;br /&gt;
* BC Perform Player (JS)&lt;br /&gt;
** http://cdn-gl.imrworldwide.com/novms/bc/3/ggng510.js&lt;br /&gt;
** https://cdn-gl.imrworldwide.com/novms/bc/3/ggng510.js&lt;br /&gt;
&lt;br /&gt;
=== Global Parameters ===&lt;br /&gt;
To initialize the Nielsen Browser SDK, pass four global parameters when adding the BC Perform plugin.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site. There are two IDs provided || &amp;lt;code&amp;gt;'XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&amp;lt;/code&amp;gt;&lt;br /&gt;
* Test: begins with 'T' and is used for testing&lt;br /&gt;
* Production: begins with 'P' and is used in live environment when testing and certification is completed.&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Location of collection environment. During testing, all traffic should be directed to 'dcr-cert'. || testing: &amp;lt;code&amp;gt;'dcr-cert'&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
production: &amp;lt;code&amp;gt;'dcr'&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| nsdkv || 	Nielsen SDK Version || &amp;lt;code&amp;gt;'511'&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| apn || User-defined string value for describing the player / site. || custom&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The below parameter is optional but recommended when testing implementation.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Nielsen SDK console logging that should be used while testing. Make sure to disable before moving the implementation to production. || &amp;lt;code&amp;gt;'INFO'&amp;lt;/code&amp;gt; – API calls&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'WARNING'&amp;lt;/code&amp;gt; – System level logs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'ERROR'&amp;lt;/code&amp;gt; – Error logs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'DEBUG'&amp;lt;/code&amp;gt; – Full logs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Configure Metadata ===&lt;br /&gt;
There are two types of metadata&lt;br /&gt;
* '''DCR Content Metadata''': identify content&lt;br /&gt;
* '''DCR Ad Metadata''': identify ad&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys.&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting. There are reserved Nielsen keys for collecting the required metadata.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Type !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || Type of asset || &amp;lt;code&amp;gt;'content'&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to asset || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program || Program Name || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || The original airdate for linear TV || &amp;lt;code&amp;gt;'20161013 20:00:00'&amp;lt;/code&amp;gt; || date || No&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds || &amp;lt;code&amp;gt;3600&amp;lt;/code&amp;gt; (86400 for lives tream)|| integer || Yes&lt;br /&gt;
|-&lt;br /&gt;
| segB || Custom Reporting Segment || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || No&lt;br /&gt;
|-&lt;br /&gt;
| segC || Custom Reporting Segment || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || No&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full Episode Flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;'y'&amp;lt;/code&amp;gt; - Full Episode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'n'&amp;lt;/code&amp;gt; - Non Full Episode &lt;br /&gt;
|| boolean || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || Distinguishes Dynamic vs Linear Ad Insertion ||&lt;br /&gt;
&amp;lt;code&amp;gt;'1'&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'2'&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| integer || Yes&lt;br /&gt;
|-&lt;br /&gt;
| crossId1 || Standard Episode ID || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| crossId2 || Content Originator ID || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || No&lt;br /&gt;
|-&lt;br /&gt;
| mediaURL || URL location of the content being streamed || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| hasAds || Distinguishes when content includes Ads ||&lt;br /&gt;
&amp;lt;code&amp;gt;'0'&amp;lt;/code&amp;gt; - No Ads&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'1'&amp;lt;/code&amp;gt; - Includes Ads&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'2'&amp;lt;/code&amp;gt; - Unknown&lt;br /&gt;
|| integer || Yes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Type !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || Type of ad ||&lt;br /&gt;
&amp;lt;code&amp;gt;'preroll'&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'midroll'&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'postroll'&amp;lt;/code&amp;gt;&lt;br /&gt;
|| string || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || string || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''':There is a URL character limit of 2000 characters imposed due to browser limitations. Exceeding this value can impair data delivery on particular browsers.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
In order to integrate the Nielsen plugin, follow the steps for setting up these players in the Brightcove user interface as they appear below by each player type.&lt;br /&gt;
&lt;br /&gt;
=== Brightcove Player Setup ===&lt;br /&gt;
The new Brightcove Perform player allows two interchangeable ways to add the plugin: on the web site, so the player will come already configured, and programmatically on the client side.&lt;br /&gt;
&lt;br /&gt;
These options, as well as the whole process of adding a plugin is common to the player and described here http://support.brightcove.com/en/perform/docs/configuring-player-plugins&lt;br /&gt;
&lt;br /&gt;
==== For Nielsen SDK plugin, the integrator would need ====&lt;br /&gt;
* A list of initialization parameters (Application ID, App Name, sfcode, and nsdkv). Refer to [[#Global Parameters|Global Parameters]] section above.&lt;br /&gt;
* A link (URL) to SDK plugin (ggng510.js) for Brightcove&lt;br /&gt;
* A list of metadata fields with their names (Nielsen Key Mapping) to pass to the plugin. For more information, refer to [[#Configure Metadata|Configure Metadata]] section.&lt;br /&gt;
* Access to the Brightcove VideoCloud Perform Portal https://studio.brightcove.com/products/videocloud/home&lt;br /&gt;
&lt;br /&gt;
==== To add Nielsen SDK plugin using UI do the following ====&lt;br /&gt;
Open Brightcove VideoCloud portal, open players list and open (or create) a player the plugin should be added to.&lt;br /&gt;
Scroll down to the 'Plugins' section in player configuration&lt;br /&gt;
&lt;br /&gt;
[[File:Plugins-BC.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
* Click &amp;quot;Edit&amp;quot; and enter the URL to plugin JS file. Click &amp;quot;+&amp;quot; to add the row.&lt;br /&gt;
&lt;br /&gt;
[[File:js-BC.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
* Then click &amp;quot;Name, Options (JSON)&amp;quot; row and enter &amp;quot;NielsenBC&amp;quot; for the plugin name and required initialization parameters provided by your Nielsen Technical Account Manager, as below:&lt;br /&gt;
&lt;br /&gt;
[[File:Js-BC2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Example Code:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;nol_sdkDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;,&lt;br /&gt;
  &amp;quot;sfcode&amp;quot;: &amp;quot;dcr-cert&amp;quot;,&lt;br /&gt;
  &amp;quot;apn&amp;quot;: &amp;quot;Test_player_name&amp;quot;,&lt;br /&gt;
  &amp;quot;nsdkv&amp;quot;: &amp;quot;511&amp;quot;,&lt;br /&gt;
  &amp;quot;apid&amp;quot;: &amp;quot;T4BFBFAC9-XXXX-XXXX-XXXX-22B092CBCC2B&amp;quot;,&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Adding &amp;lt;code&amp;gt;&amp;quot;nol_sdkDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&amp;lt;/code&amp;gt; will allow SDK events in the console.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': &amp;lt;code&amp;gt;&amp;quot;nol_sdkDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&amp;lt;/code&amp;gt; must be removed when moving a player live to production to disable the debug logging.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Pass Content &amp;amp; Ad Metadata to The Brightcove Video Player ====&lt;br /&gt;
Pass the required content, and ad metadata to the Brightcove video player so that the Nielsen Plug-In is able to pick it up in order to populate the DCR crediting tags. The Nielsen Plug-In is preconfigured to automatically obtain metadata from Custom Fields. These can be set through the Brightcove User Interface (under ADMIN) or programmatically.&lt;br /&gt;
&lt;br /&gt;
Information on creating Custom Metadatafields can be found on the [https://support.brightcove.com/en/video-cloud/docs/creating-custom-metadata-fields|Brightcove Support site].&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If you are using the Brightcove player with the PERFORM service, you will need to populate the media info. Please contact Brightcove support for details on this process.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Video-Fields.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information on how to pass the required metadata to the Brightcove [https://www.brightcove.com/en/online-video-platform VideoCloud] player, please reach out to your Brightcove Account Manager for further assistance.&lt;br /&gt;
&lt;br /&gt;
==== To add Nielsen SDK programmatically ====&lt;br /&gt;
* Include plugin source&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script src=&amp;quot;//cdn-gl.imrworldwide.com/novms/bc/3/ggng510.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Bind plugin to the player with inititalization parameters&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;videojs(&amp;quot;myPlayerID&amp;quot;).NielsenBC(&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;apid&amp;quot;: &amp;quot;PXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
    &amp;quot;apn&amp;quot;: &amp;quot;Your_player_name&amp;quot;,&lt;br /&gt;
    &amp;quot;sfcode&amp;quot;: &amp;quot;dcr-cert&amp;quot;,&lt;br /&gt;
    &amp;quot;nsdkv&amp;quot;: &amp;quot;511&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* For CMS data binding, the following rules apply&lt;br /&gt;
* The plugin automatically captures the following video data&lt;br /&gt;
* * Data from video duration is automatically capture by the plugin&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nielsenData.length = videoInfo.duration;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* * Field &amp;quot;type&amp;quot; is set to &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* If video data contains custom fields, all those fields are copied over to Nielsen data: &amp;lt;code&amp;gt;nielsenData[i] = videoInfo.custom_fields[i]&amp;lt;/code&amp;gt; (with 'i' iterated over all custom field names), which may override some of the default values or standard field values&lt;br /&gt;
* '''The plugin does not automatically assign a value to assetid'''. To pass programmatically, use the custom fields object. (See code example below)&lt;br /&gt;
* Parameter videoInfo.id must be a unique string to allow the plugin detecting the content change.&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
* If some CMS metadata values should be set for all videos played, those values can be passed as &amp;quot;defaults&amp;quot; field on the player level (in the player configuration), like this&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;apid&amp;quot;: &amp;quot;PXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;apn&amp;quot;: &amp;quot;Your_player_name&amp;quot;,&lt;br /&gt;
  &amp;quot;sfcode&amp;quot;: &amp;quot;dcr&amp;quot;,&lt;br /&gt;
  &amp;quot;nsdkv&amp;quot;: &amp;quot;511&amp;quot;,&lt;br /&gt;
  &amp;quot;defaults&amp;quot;: { &amp;quot;customValue&amp;quot;: &amp;quot;true&amp;quot; }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* CMS metadata values can also be set at the asset level&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;sources&amp;quot; :&lt;br /&gt;
    [ {&lt;br /&gt;
      &amp;quot;src&amp;quot; : &amp;quot;http://solutions.brightcove.com/../videos/Sea_SeaHorse.mp4&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot; : &amp;quot;video/mp4&amp;quot;&lt;br /&gt;
    } ],&lt;br /&gt;
    &amp;quot;custom_fields&amp;quot;:&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;assetid&amp;quot;: &amp;quot;6475587654&amp;quot;,&lt;br /&gt;
        &amp;quot;mediaURL&amp;quot;: &amp;quot;http://solutions.brightcove.com/bcls/../videos/Sea_Anemone.mp4&amp;quot;,&lt;br /&gt;
        &amp;quot;dataSrc&amp;quot;: &amp;quot;cms&amp;quot;,&lt;br /&gt;
        &amp;quot;hasAds&amp;quot;: &amp;quot;1&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Sea Anemone&amp;quot;,&lt;br /&gt;
      &amp;quot;thumbnail&amp;quot;: &amp;quot;http://solutions.brightcove.com/bcls/assets/images/Sea_Anemone_poster.png&amp;quot;,&lt;br /&gt;
      &amp;quot;id&amp;quot;: &amp;quot;5195888503001&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Support ===&lt;br /&gt;
The plugin will also extract information about the number and length of advertisements played with the video.&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation ==&lt;br /&gt;
The site must provide a means for the user to opt out of, or opt back into Nielsen Measurement. A user can opt out if preferring to not participate in any Nielsen online measurement research. To implement the Opt-Out option, include the following in the privacy policy page:&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings)&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at http://www.nielsen.com/digitalprivacy&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click choices to read more detailed information about the measurement software and their options. The users can click a link to retrieve an Opt-Out cookie if they do not want to participate in Nielsen online measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen properties may feature Nielsen proprietary measurement software, which will allow the users to contribute to market research, such as Nielsen TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
=== Opt-In ===&lt;br /&gt;
Once users have opted out, they can choose to opt back into Nielsen Measurement at anytime by selecting the Opt-In link on the Nielsen Digital Privacy Policy page. When a user selects the link, their Opt-Out cookie will be deleted and they will be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
After the integration is certified, there is one update to be made to the existing code to ensure that the player will be measured properly:&lt;br /&gt;
*'''App ID''': Change the apid to the production ID starting with the letter 'P':&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;'PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* '''Collection Environment''': Change the value for &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; from &amp;lt;code&amp;gt;dcr-cert&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;dcr&amp;lt;/code&amp;gt; to point traffic to the Nielsen production collection environment. Do not use &amp;lt;code&amp;gt;dcr-cert&amp;lt;/code&amp;gt; for production traffic&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure that the &amp;lt;code&amp;gt;nol_sdkDebug&amp;lt;/code&amp;gt; parameter is not used.&amp;lt;/blockquote&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=DTVR_Android_SDK&amp;diff=1534</id>
		<title>DTVR Android SDK</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=DTVR_Android_SDK&amp;diff=1534"/>
		<updated>2017-09-22T20:27:34Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Configure API calls - loadMetadata */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR &amp;amp; DTVR}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK''' and '''Sample Player''': A part of the downloaded package&lt;br /&gt;
If you do not have any of these pre-requisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] for more information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
== Import Library ==&lt;br /&gt;
Refer to [[Android SDK API Reference#Setting Up Development Environment|Android SDK API Reference - Setting Up Development Environment]] for information on importing libraries.&lt;br /&gt;
* The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Note: The latest version of App SDK contains only appsdk.jar file and does not feature any native shared libraries like libAppSdk.so.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Initialize SDK ==&lt;br /&gt;
Initialize App SDK as soon as the application is launched. Refer to [[Android SDK API Reference#Initialization|Android SDK API Reference - Initialization]] for details on initializing an AppSDK object and the parameters required.&lt;br /&gt;
&lt;br /&gt;
== Configure and fire API calls ==&lt;br /&gt;
=== Configure API calls - play ===&lt;br /&gt;
Call [[play()]] when starting or resuming a streaming session to pass the channel descriptor information through &amp;lt;code&amp;gt;channelName&amp;lt;/code&amp;gt; parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
* &amp;lt;code&amp;gt;channelName&amp;lt;/code&amp;gt; is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.)&lt;br /&gt;
Call [[play()]] with &amp;lt;code&amp;gt;channelName&amp;lt;/code&amp;gt; JSON as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
      &amp;quot;channelName&amp;quot;: &amp;quot;TheMovieTitle&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configure API calls - loadMetadata ===&lt;br /&gt;
Load the CMS metadata by calling [[loadMetadata|loadMetadata()]] on the SDK object.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;    loadMetadata(JSONObject jsonMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Refer to [[Digital Measurement Metadata]] for the list of parameters to be passed in the JSON object.&lt;br /&gt;
Call [[loadMetadata()]] for the content after the first [[play()]] call. Call [[loadMetadata()]] with JSON metadata for the active content as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
      &amp;quot;adModel&amp;quot;: &amp;quot;1&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configure API calls - sendID3 ===&lt;br /&gt;
[[sendID3()]] API is a receiver for HLS timed metadata events (ID3 tags) provided through the notification system. This API filters out Nielsen-specific ID3 tags from the system and buffers the data for transfer to Nielsen’s collection facility. Call [[sendID3()]] whenever new Nielsen ID3 metadata is available for processing during session playback.&lt;br /&gt;
==== Sample ID3 tags ====&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refer to [[Android SDK API Reference#Retrieving ID3 Tags|Android SDK API Reference - Retrieving ID3 Tags]] section to know more details.&lt;br /&gt;
&lt;br /&gt;
===Configure API calls - stop ===&lt;br /&gt;
Call [[stop()]] only when the stream playback is stopped by a user. Common events are; network loss, power / standby, incoming call, alarm, etc. Call [[stop()]] only when buffering continues for 30 seconds (not when it starts). Call [[play()]] when resuming a stream (previously stopped) or starting playback of a new stream.&lt;br /&gt;
&lt;br /&gt;
===Configure API calls - end ===&lt;br /&gt;
Call [[end()]] only at the end of playback. Not mandatory if stream is live/does not end.&lt;br /&gt;
&lt;br /&gt;
==API Call sequence==&lt;br /&gt;
===Use Case 1: Content has no Advertisements===&lt;br /&gt;
Call [[play()]] with &amp;lt;code&amp;gt;channelName&amp;lt;/code&amp;gt; JSON as below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
        &amp;quot;channelName&amp;quot;: &amp;quot;TheMovieTitle&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Use Case 2: Content has linear (non-DAI) Advertisements===&lt;br /&gt;
Call [[play()]] (for the first ad) with &amp;lt;code&amp;gt;channelName&amp;lt;/code&amp;gt; JSON as below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
        &amp;quot;channelName&amp;quot;: &amp;quot;TheMovieTitle&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Call [[loadMetadata()]] with JSON metadata for the active content as below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
        &amp;quot;adModel&amp;quot;: &amp;quot;1&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Call [[sendID3()]] with ID3 payload&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
    sendID3(payload)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Handling Foreground and Background states of App==&lt;br /&gt;
&lt;br /&gt;
There are two ways of handling the foreground and background states of the client application.&lt;br /&gt;
*Let App SDK handle the app states information (foreground / background) and use it, as necessary.&lt;br /&gt;
*Capture app states through the application and trigger the corresponding API ([[appInForeground()]] or [[appInBackground()]]) upon every change of state. This allows Nielsen App SDK to know the app state.&lt;br /&gt;
&lt;br /&gt;
=== New devices (Android 4.0 and later versions) ===&lt;br /&gt;
&lt;br /&gt;
'''Add ''application'' tag to Manifest XML file'''&lt;br /&gt;
When a client’s app supports only new devices (Android 4.0 and above) and the client has not implemented a custom Application class for some other purpose,&lt;br /&gt;
* Add the following entry (application tag) into the Manifest XML file to use SDK’s state detection feature.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;   &amp;lt;application android:name=&amp;quot;com.nielsen.app.sdk.AppSdkApplication&amp;quot;&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This is the custom Application class where the whole background detection implementation is done. No new permissions are required to change the properties in Manifest XML file.&lt;br /&gt;
&lt;br /&gt;
=== Older devices (Android 4.0 or earlier version) ===&lt;br /&gt;
&lt;br /&gt;
Identify the change of state through the application and call the respective API ([[appInForeground()]] or [[appInBackground()]]) upon every change of state (foreground / background). The SDK will use this information to pass the app launch times, etc. to Collection facility.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
AppLaunchMeasurementManager.appInForeground(getApplicationContext());&lt;br /&gt;
AppLaunchMeasurementManager.appInBackground(getApplicationContext());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interruptions during playback ==&lt;br /&gt;
As part of integrating Nielsen App SDK with the player application, the Audio / Video app developer needs to handle the following possible interruption scenarios:&lt;br /&gt;
* Pause / Play&lt;br /&gt;
* Network Loss (Wi-Fi / Airplane / Cellular)&lt;br /&gt;
* Call Interrupt (SIM or Third party Skype / Hangout call)&lt;br /&gt;
* Alarm Interrupt&lt;br /&gt;
* Content Buffering&lt;br /&gt;
* Device Lock / Unlock (Video players only, not for Audio players)&lt;br /&gt;
* App going in the Background/Foreground (Video players only, not for Audio players)&lt;br /&gt;
* Channel / Station Change Scenario&lt;br /&gt;
* Unplugging of headphone&lt;br /&gt;
In case of encountering one of the above interruptions, the player application needs to&lt;br /&gt;
* Call [[stop()]] immediately (except when content is buffering) and withhold sending playhead position.&lt;br /&gt;
* Start sending pings – [[loadMetadata()]] and [[sendID3()]] for the new viewing session, once the playback resumes.&lt;br /&gt;
Please see the [[Digital Measurement FAQ]] for more details&lt;br /&gt;
&lt;br /&gt;
== Nielsen Measurement Opt-Out Implementation ==&lt;br /&gt;
As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. Our digital measurement products are not used to identify the consumer in any way, but they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.&lt;br /&gt;
* When the app user wants to opt in or opt out of Nielsen measurement, a new dynamic page (with content string obtained from [[userOptOutURLString()]]) should be displayed.&lt;br /&gt;
** Use [[getOptOutStatus()]] to retrieve the device’s Opt-Out status.&lt;br /&gt;
* This Opt-out page should be displayed in a webview (within the app) and not in any external browser.&lt;br /&gt;
* Capture the user’s selection in this page and pass it to the SDK through [[userOptOut()]] for Nielsen to save the user’s preference.&lt;br /&gt;
* For more details, refer to [[Android SDK API Reference#Android Opt-Out Implementation|Android SDK API Reference - Android Opt-Out Implementation]] and Nielsen Digital Privacy.&lt;br /&gt;
&lt;br /&gt;
== Testing an Implementation - App ==&lt;br /&gt;
See [[Digital Measurement Testing]].&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=DTVR_iOS_SDK&amp;diff=1533</id>
		<title>DTVR iOS SDK</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=DTVR_iOS_SDK&amp;diff=1533"/>
		<updated>2017-09-22T20:27:05Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Configure API calls - loadMetadata */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR &amp;amp; DTVR}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK''' and '''Sample Player''': A part of the downloaded package&lt;br /&gt;
If you do not have any of these pre-requisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] for more information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
== Import Library ==&lt;br /&gt;
Refer to [[iOS SDK API Reference#Importing Frameworks|Importing Frameworks]] for information on importing libraries.&lt;br /&gt;
* The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues.&lt;br /&gt;
&lt;br /&gt;
== Initialize SDK ==&lt;br /&gt;
Initialize App SDK as soon as the application is launched. Refer to [[iOS SDK API Reference#Initialization|Initialization]] for details on initializing an AppSDK object and the parameters required.&lt;br /&gt;
&lt;br /&gt;
== Configure and fire API calls ==&lt;br /&gt;
=== Configure API calls - play ===&lt;br /&gt;
Use [[play]] to pass the channel descriptor information through channelName parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
* &amp;lt;code&amp;gt;channelName&amp;lt;/code&amp;gt; is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.)&lt;br /&gt;
Call [[play]] with &amp;lt;code&amp;gt;channelName&amp;lt;/code&amp;gt; JSON as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
      &amp;quot;channelName&amp;quot;: &amp;quot;TheMovieTitle&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configure API calls - loadMetadata ===&lt;br /&gt;
Use [[loadMetadata]] to pass ‘content’ and ‘ad’ [[Digital Measurement Metadata]]. The CMS data must be passed as a JSON object.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;    – (void) loadMetadata :(id)metadata;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Refer to [[loadMetadata]] for the list of parameters to be passed in the JSON object.&lt;br /&gt;
Call [[loadMetadata]] after the first play call. Call [[loadMetadata]] with JSON metadata for the active content as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
      &amp;quot;adModel&amp;quot;: &amp;quot;1&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configure API calls - sendID3 ===&lt;br /&gt;
[[sendID3]] API is a receiver for HLS timed metadata events (ID3 tags) provided through iOS’s NSNotificationCenter notification system. This API filters out Nielsen-specific ID3 tags from the system and buffers the data for transfer to Nielsen’s collection facility.&lt;br /&gt;
==== Sample ID3 tags ====&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
Refer to [[iOS SDK API Reference#Retrieving ID3 Tags|Retrieving ID3 Tags]] section to know more details.&lt;br /&gt;
&lt;br /&gt;
===Configure API calls - stop ===&lt;br /&gt;
Call [[stop]] in case of interruptions during playback like flight mode, Wi-Fi toggle, etc. Call [[play]] when resuming the stream / starting the new stream.&lt;br /&gt;
&lt;br /&gt;
===Configure API calls - end ===&lt;br /&gt;
Call [[end]] only at the end of playback.&lt;br /&gt;
&lt;br /&gt;
== Interruptions during playback ==&lt;br /&gt;
As part of integrating Nielsen App SDK with the player application, the Audio / Video app developer needs to handle the following possible interruption scenarios:&lt;br /&gt;
* Pause / Play&lt;br /&gt;
* Network Loss (Wi-Fi / Airplane / Cellular)&lt;br /&gt;
* Call Interrupt (SIM or Third party Skype / Hangout call)&lt;br /&gt;
* Alarm Interrupt&lt;br /&gt;
* Content Buffering&lt;br /&gt;
* Device Lock / Unlock (Video players only, not for Audio players)&lt;br /&gt;
* App going in the Background/Foreground (Video players only, not for Audio players)&lt;br /&gt;
* Channel / Station Change Scenario&lt;br /&gt;
* Unplugging of headphone&lt;br /&gt;
In case of encountering one of the above interruptions, the player application needs to&lt;br /&gt;
* Call [[stop]] immediately (except when content is buffering) and withhold sending playhead position.&lt;br /&gt;
* Start sending pings – [[loadMetadata]] and [[sendID3]] for the new viewing session, once the playback resumes.&lt;br /&gt;
Please see the [[Digital Measurement FAQ]] for more details&lt;br /&gt;
&lt;br /&gt;
== Nielsen Measurement Opt-Out Implementation ==&lt;br /&gt;
As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. Our digital measurement products are not used to identify the consumer in any way, but they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.&lt;br /&gt;
* When the app user wants to opt in or opt out of Nielsen measurement, a new dynamic page (with content string obtained from [[optOutURL]]) should be displayed.&lt;br /&gt;
* Use [[optOutStatus]] to retrieve the device’s Opt-Out status.&lt;br /&gt;
* This Opt-out page should be displayed in a webview (within the app) and not in any external browser.&lt;br /&gt;
* Capture the user’s selection in this page and pass it to the SDK through [[userOptOut]] for Nielsen to save the user’s preference.&lt;br /&gt;
&amp;lt;!-- * For more details, refer to [[iOS SDK API Reference#iOS Opt-Out Implementation|iOS SDK API Reference - iOS Opt-Out Implementation]] and Nielsen Digital Privacy. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing an Implementation - App ==&lt;br /&gt;
See [[Digital Measurement Testing]].&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Digital_Measurement_Metadata&amp;diff=1474</id>
		<title>Digital Measurement Metadata</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Digital_Measurement_Metadata&amp;diff=1474"/>
		<updated>2017-09-19T19:49:20Z</updated>

		<summary type="html">&lt;p&gt;Admin2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR &amp;amp; DTVR}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting. There are reserved Nielsen keys for collecting the required metadata.&lt;br /&gt;
&lt;br /&gt;
=== Reserved Keys ===&lt;br /&gt;
Content and Ad Metadata can be passed through key-values using the Nielsen reserved keys. The last column in the table below indicates metadata parameters that will be displayed in reporting.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required for Audio/Video? !! Required for Static (page)? !! Reported for&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || custom || Optional || Optional || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || custom || Optional || Optional || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*audio / video – &amp;quot;content&amp;quot;&lt;br /&gt;
*page – &amp;quot;static&amp;quot;&lt;br /&gt;
*ad – &amp;quot;preroll&amp;quot;, &amp;quot;midroll&amp;quot; or &amp;quot;postroll&amp;quot;&lt;br /&gt;
|| &amp;quot;content&amp;quot;, &amp;quot;static&amp;quot; || Mandatory || Mandatory || &lt;br /&gt;
|-&lt;br /&gt;
| assetid || ID assigned to content. Must be unique across all content at the episode level. || custom || Mandatory || Not Required || &lt;br /&gt;
|-&lt;br /&gt;
| section || Section of site || custom || Not Required || Mandatory || &lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
*&amp;quot;y&amp;quot; or &amp;quot;lf&amp;quot; - full episode&lt;br /&gt;
*&amp;quot;n&amp;quot; or &amp;quot;sf&amp;quot; - short form&lt;br /&gt;
|| Mandatory || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name || custom || Mandatory || Not Required || Audio / Video Measurement&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title || custom || Mandatory || Not Required || Audio / Video Measurement&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || custom || Mandatory || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| segA || Segment A (this is not available for audio / video Measurement reporting as the episode title is reported) || custom || Not Required || Not Required || Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| segB || Segment B || custom || Not Required || Not Required || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| segC || Segment C || custom || Not Required || Not Required || Audio / Video and Static Measurement&lt;br /&gt;
|-&lt;br /&gt;
| crossId1 || Standard episode ID || custom || Optional || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| crossId2 || Content originator (required only for distributors) || custom || Optional || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (Eastern Time for US) || YYYYMMDD HH24:MI:SS || Mandatory || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| pipmode ||&lt;br /&gt;
Current state of picture-in-picture (PIP) mode on device.&lt;br /&gt;
*&amp;quot;true&amp;quot; if audio / video measurement is displayed in PIP mode&lt;br /&gt;
*&amp;quot;false&amp;quot; if audio / video measurement is displayed in regular mode&lt;br /&gt;
|| &amp;quot;true&amp;quot;, &amp;quot;false&amp;quot; || Mandatory || Not Required || Audio / Video Measurement&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;quot;1&amp;quot; - Linear&lt;br /&gt;
&amp;quot;2&amp;quot; - Dynamic&lt;br /&gt;
|| Mandatory || Not Required ||&lt;br /&gt;
|-&lt;br /&gt;
| progen || Genre (required only for OTT) || e.g. DD for Daytime Drama || Optional || Not Required&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''clientid &amp;amp; subbrand (vcid)'''&lt;br /&gt;
By default, clientid and subbrand are setup in Nielsen backend configuration to capture brand and sub-brand information. The fields get populated from backend for a registered client appid. But if an app contains multiple brands and sub-brands and client is willing to give credit to another brand or sub-brand then :&lt;br /&gt;
*Client app developer can override the clientid and subbrand (brand and sub-brand info.) in [[loadMetadata]] call to get a proper measurement for a desired brand and sub-brand.&lt;br /&gt;
**If no clientid and subbrand are specified in CMS of a content and an ad, default values reported in the Configuration will be reported.&lt;br /&gt;
**If clientid and subbrand are specified in CMS of the content or ad, the most recent clientid and subbrand will be reported in subsequent pings. To report with a different clientid and subbrand, include the new values for the keys in their subsequent [[loadMetadata]] call.&lt;br /&gt;
'''Picture-in-picture (PIP) mode'''&lt;br /&gt;
Once the app detects PIP mode, call [[loadMetadata]] with the same set of assetids, values and with one additional parameter &amp;quot;pipmode&amp;quot;: &amp;quot;true&amp;quot;. Once PIP mode is disabled in the device, call [[loadMetadata]] again with &amp;quot;pipmode&amp;quot;:&amp;quot;false&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Custom Variables Extension ====&lt;br /&gt;
Contact Nielsen Technical Account Manager (TAM) to configure any custom variables, as needed for implementing the application.&lt;br /&gt;
&lt;br /&gt;
See [[Custom Variables Extension]] for more information.&lt;br /&gt;
&lt;br /&gt;
==== Advertisement Metadata ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required for Audio / Video? !! Required for Static (page)&lt;br /&gt;
|-&lt;br /&gt;
| type || Type of ad || &amp;quot;preroll&amp;quot;&lt;br /&gt;
&amp;quot;midroll&amp;quot;&lt;br /&gt;
&amp;quot;postroll&amp;quot; &lt;br /&gt;
|| Mandatory || Not Required&lt;br /&gt;
|-&lt;br /&gt;
| assetid || An ID assigned to the advertisement. Can be an internal ID, an ID provided by the ad server, or a randomly generated ID. Must be unique across all ads || custom || Mandatory || Not Required&lt;br /&gt;
|-&lt;br /&gt;
| title || Title of the advertisement || &amp;quot;MyAdName&amp;quot; || Mandatory || Not Required&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Passing Metadata ===&lt;br /&gt;
The required metadata can be passed as key values through the loadMetadata method. The sample code below shows a metadata objects for various assets.&lt;br /&gt;
'''Audio / Video Measurement Asset'''&lt;br /&gt;
Type should be &amp;quot;content&amp;quot;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
       &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
       &amp;quot;assetName&amp;quot;: &amp;quot;myassetName&amp;quot;,&lt;br /&gt;
       &amp;quot;length&amp;quot;: &amp;quot;300&amp;quot;,&lt;br /&gt;
       &amp;quot;title&amp;quot;: &amp;quot;myTitle&amp;quot;,&lt;br /&gt;
       &amp;quot;program&amp;quot;: &amp;quot;myProgram&amp;quot;,&lt;br /&gt;
       &amp;quot;censuscategory&amp;quot;: &amp;quot;myCensusCategory&amp;quot;,&lt;br /&gt;
       &amp;quot;assetid&amp;quot;: &amp;quot;myAssetId&amp;quot;,&lt;br /&gt;
       &amp;quot;channelName&amp;quot;: &amp;quot;myChannel&amp;quot;,&lt;br /&gt;
       &amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
       &amp;quot;segB&amp;quot;: &amp;quot;segmentB&amp;quot;,&lt;br /&gt;
       &amp;quot;segC&amp;quot;: &amp;quot;segmentC&amp;quot;,&lt;br /&gt;
       &amp;quot;isfullepisode&amp;quot;:&amp;quot;y&amp;quot;,&lt;br /&gt;
       &amp;quot;crossId1&amp;quot;: &amp;quot;Reference11&amp;quot;,&lt;br /&gt;
       &amp;quot;crossId2&amp;quot;: &amp;quot;Reference22&amp;quot;,&lt;br /&gt;
       &amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Static (Page) Measurement Asset'''&lt;br /&gt;
Type should be &amp;quot;static&amp;quot;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
       &amp;quot;type&amp;quot;: &amp;quot;static&amp;quot;,&lt;br /&gt;
       &amp;quot;assetid&amp;quot;: &amp;quot;static123&amp;quot;,&lt;br /&gt;
       &amp;quot;assetName&amp;quot;: &amp;quot;Page-Asset&amp;quot;,&lt;br /&gt;
       &amp;quot;section&amp;quot;: &amp;quot;siteSection&amp;quot;,&lt;br /&gt;
       &amp;quot;segA&amp;quot;: &amp;quot;segmentA&amp;quot;,&lt;br /&gt;
       &amp;quot;segB&amp;quot;: &amp;quot;segmentB&amp;quot;,&lt;br /&gt;
       &amp;quot;segC&amp;quot;: &amp;quot;segmentC&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''For any of the ad types'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;midroll&amp;quot;,&lt;br /&gt;
        &amp;quot;length&amp;quot;: &amp;quot;30&amp;quot;,&lt;br /&gt;
        &amp;quot;assetid&amp;quot;: &amp;quot;myMidrollAssetId&amp;quot;,&lt;br /&gt;
        &amp;quot;adModel&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
        &amp;quot;tv&amp;quot;: &amp;quot;true&amp;quot;,&lt;br /&gt;
        &amp;quot;dataSrc&amp;quot;: &amp;quot;cms&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': In case the individual ad details are not available, send ad pod (presence) details through the &amp;lt;code&amp;gt;loadMetadata&amp;lt;/code&amp;gt; and playhead position through &amp;lt;code&amp;gt;setPlayheadPosition&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''loadMetadata'''&lt;br /&gt;
The object can then be passed when calling [[loadMetadata]].&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;    loadMetadata(jsonMetadataObject);&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Digital_Pre-Certification_Checklist_App_SDK&amp;diff=1429</id>
		<title>Digital Pre-Certification Checklist App SDK</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Digital_Pre-Certification_Checklist_App_SDK&amp;diff=1429"/>
		<updated>2017-09-12T20:38:43Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* loadMetadata() - Content */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Pre-certification Checklist - VOD with Ads ==&lt;br /&gt;
Before starting the certification process, please verify the following steps have been completed.&lt;br /&gt;
* Your Client Service representative should have already discussed a reporting hierarchy with you -- along with a Parent, Brand, and Sub-brand/Channel&lt;br /&gt;
* Your Technical Account Manager should have:&lt;br /&gt;
** provided you with an AppID&lt;br /&gt;
** informed you of our Opt-Out requirement for your App/Play Store description&lt;br /&gt;
** informed you of our Opt-Out requirement for a WebView inside your apps&lt;br /&gt;
* Retrieving AppSDK logs&lt;br /&gt;
** ‘nol_devDebug’ : ‘DEBUG’ should be present in initialization call (see below)&lt;br /&gt;
** Android: use adb logcat (note: requires Android Studio)&lt;br /&gt;
** iOS: idevicesyslog (note: requires XCode)&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The first step in the Certification process is to ensure that the Nielsen SDK is initializing at app startup, and that the global metadata values are present.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Value&lt;br /&gt;
|-&lt;br /&gt;
| appid || &amp;lt;code&amp;gt;PXXXXX-XXXXXX-XXXXX-XXXXX&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| appname || &amp;lt;code&amp;gt;example app name&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| appversion || &amp;lt;code&amp;gt;2.0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || &amp;lt;code&amp;gt;debug&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''iOS Example'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{ // AppID is Nielsen-supplied&lt;br /&gt;
	 @&amp;quot;appid&amp;quot;: @&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
 	 @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
 	 @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
 	 @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot; // required for testing only&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Android Example'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appversion&amp;quot;,&amp;quot;2.0&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug”, &amp;quot;DEBUG&amp;quot;); // required for testing only&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Cases ==&lt;br /&gt;
The following lists the test cases along with the Expected results:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Param !! Expected Result !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| SDK Initialized || &amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt; || Correct app id || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt; || Player name || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; || Correct build || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;'DEBUG&amp;lt;/code&amp;gt; || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== play() ===&lt;br /&gt;
* The &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt; call is required only once per viewing session (until app is killed)&lt;br /&gt;
* Called just before playback commences for first piece of content&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Param !! Expected Result !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| Play || &amp;lt;code&amp;gt;channelname&amp;lt;/code&amp;gt; || Name of Channel || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata() - Content ===&lt;br /&gt;
* Called at beginning of content, or when resuming content from interruption&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test !! Param !! Example Value !! Accepted Values !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| loadMetadata || &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;assetid&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;unique_id_500291&amp;quot;&amp;lt;/code&amp;gt; || (unique per asset) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;length&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;600&amp;quot;&amp;lt;/code&amp;gt; || length in seconds (int or float) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Episode Title&amp;quot;&amp;lt;/code&amp;gt; || (any non-empty value) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;program&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Show Name&amp;quot;&amp;lt;/code&amp;gt; || (any non-empty value) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;segB&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Primetime&amp;quot;&amp;lt;/code&amp;gt; || (any value), used for optional breakdown || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;segC&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Comedy&amp;quot;&amp;lt;/code&amp;gt; || (any value), used for optional breakdown || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;crossId1&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;EP018S9S290015&amp;quot;&amp;lt;/code&amp;gt; || Gracenote ID || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;crossId2&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;ABC&amp;quot;&amp;lt;/code&amp;gt; || Network Name || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;isfullepisode&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; || (&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;) (&amp;lt;code&amp;gt;&amp;quot;Y&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;N&amp;quot;&amp;lt;/code&amp;gt;) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;airdate&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;20160206 23:00:00&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;YYYYMMDD[space]HH:MM:SS&amp;quot;&amp;lt;/code&amp;gt; -- note: HH=24 hour time || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;adloadtype&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; for linear ads, &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; for DAI || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;hasAds&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; for no ads, &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; for has ads || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata() - ad ===&lt;br /&gt;
* Called at beginning of ad, or when resuming ad from interruption&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test !! Param !! Example Value !! Accepted Values !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| loadMetadata || &amp;lt;code&amp;gt;assetid&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;ad_2201343201&amp;quot;&amp;lt;/code&amp;gt; || (any non-empty value) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || Example&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== setPlayheadPosition() - Preroll ad ===&lt;br /&gt;
* Track current position of playhead&lt;br /&gt;
* Starts at 0 at the beginning of ad&lt;br /&gt;
* Updated at least once per second&lt;br /&gt;
* Separate playhead position for ads and content, should accurately reflect current position in either ads or content&lt;br /&gt;
* Final playhead position for content must equal the length specified in loadMetadata(), followed by end() call&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setPlayehadPosition&amp;lt;/code&amp;gt; || Called every second || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt; || Called at the end of Ad || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata() - Content ===&lt;br /&gt;
* Test is to validate Content metadata is the same as original metadata passed during initial loadMetadata call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test !! Param !! Example Value !! Accepted Values !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| loadMetadata || &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;assetid&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;unique_id_500291&amp;quot;&amp;lt;/code&amp;gt; || (unique per asset) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;length&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;600&amp;quot;&amp;lt;/code&amp;gt; || length in seconds (int or float) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Episode Title&amp;quot;&amp;lt;/code&amp;gt; || (any non-empty value) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;program&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Show Name&amp;quot;&amp;lt;/code&amp;gt; || (any non-empty value) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;segB&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Primetime&amp;quot;&amp;lt;/code&amp;gt; || (any value), used for optional breakdown || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;segC&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Comedy&amp;quot;&amp;lt;/code&amp;gt; || (any value), used for optional breakdown || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;crossId1&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;EP018S9S290015&amp;quot;&amp;lt;/code&amp;gt; || Gracenote ID || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;crossId2&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;ABC&amp;quot;&amp;lt;/code&amp;gt; || Network Name || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;isfullepisode&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; || (&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;) (&amp;lt;code&amp;gt;&amp;quot;Y&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;N&amp;quot;&amp;lt;/code&amp;gt;) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;airdate&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;20160206 23:00:00&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;YYYYMMDD[space]HH:MM:SS&amp;quot;&amp;lt;/code&amp;gt; -- note: HH=24 hour time || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;adloadtype&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; for linear ads, &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; for DAI || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;hasAds&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; for no ads, &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; for has ads || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== setPlayheadPosition() - Content ===&lt;br /&gt;
* Track current position of playhead&lt;br /&gt;
* Starts at 0 at the beginning of content&lt;br /&gt;
* Updated at least once per second&lt;br /&gt;
* Separate playhead position for ads and content, should accurately reflect current position in either ads or content&lt;br /&gt;
* Final playhead position for content must equal the length specified in loadMetadata(), followed by end() call&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setPlayehadPosition&amp;lt;/code&amp;gt; || Called every second || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt; || Called at the end of Content || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== stop() ===&lt;br /&gt;
* Indicates one of the following:&lt;br /&gt;
* Playback of content or ad was interrupted&lt;br /&gt;
* Reached end of ad (no parameters or metadata)&lt;br /&gt;
&lt;br /&gt;
=== end() ===&lt;br /&gt;
* Reached the end of content (no parameters or metadata)&lt;br /&gt;
&lt;br /&gt;
== Interruptions ==&lt;br /&gt;
* All interruptions to playback of content or ads should trigger a call to stop(). Once the interruption is over, loadMetadata() with the same metadata should be called, followed by playheadPosition resuming from where it left off.&lt;br /&gt;
&lt;br /&gt;
* Interruptions include:&lt;br /&gt;
** user-induced pause&lt;br /&gt;
** screen turned off&lt;br /&gt;
** app sent to background&lt;br /&gt;
** headphones removed (note, if app simply switches audio output from headphones to speaker without pausing, there is no need to call stop())&lt;br /&gt;
** alarm/call interruption&lt;br /&gt;
** internet connection lost (n.b. cached playback plays as normal until it expires)&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| user-induced pause || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| screen turned off || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| app sent to background || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| headphones removed || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| alarm/call interruption || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| internet connection lost || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| content paused || &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; is not passed || &lt;br /&gt;
|-&lt;br /&gt;
| resume content || &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; is called for content || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;loadMetadataM&amp;lt;/code&amp;gt; is the same as original || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; continues from resumed position || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Expected SDK behavior for all interruptions:'''&lt;br /&gt;
# interruption triggers stop() call&lt;br /&gt;
# when content resumes, loadMetadata() is called with the same metadata that was playing previously (ad or content)&lt;br /&gt;
# playheadPosition() resumes from the same position before the interruption&lt;br /&gt;
&lt;br /&gt;
'''Example session:'''&lt;br /&gt;
* 5 minutes of content played, call interruption, content resumes until end of 15 min video&lt;br /&gt;
&lt;br /&gt;
== Scrubbing ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| Scrub Backward || new playhead position is accurate || &lt;br /&gt;
|-&lt;br /&gt;
|  || new playhead continues from new position || &lt;br /&gt;
|-&lt;br /&gt;
| Scrub Forward || new playhead position is accurate || &lt;br /&gt;
|-&lt;br /&gt;
|  || new playhead continues from new position || &lt;br /&gt;
|-&lt;br /&gt;
| Scrub to end || final playhead position is passed || &lt;br /&gt;
|-&lt;br /&gt;
|  || end event called at completion of content playback || &lt;br /&gt;
|-&lt;br /&gt;
| Scrub past midroll || Playhead for content stops || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Midroll &amp;amp; Postroll Ads ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; || Called for each Ad || &lt;br /&gt;
|-&lt;br /&gt;
|  || Required Metadata is accurate || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || Passed every second || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt; || called for each ad || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt; || correct sequence for each ad || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
Users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in 'WebView' / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;optOutView&amp;lt;/code&amp;gt; || User can Opt-Out || &lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Digital_Pre-Certification_Checklist_App_SDK&amp;diff=1428</id>
		<title>Digital Pre-Certification Checklist App SDK</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Digital_Pre-Certification_Checklist_App_SDK&amp;diff=1428"/>
		<updated>2017-09-12T17:47:07Z</updated>

		<summary type="html">&lt;p&gt;Admin2: Does not need to be fired before every playhead position update, this will cause the SDK to not credit any seconds of viewing.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Pre-certification Checklist - VOD with Ads ==&lt;br /&gt;
Before starting the certification process, please verify the following steps have been completed.&lt;br /&gt;
* Your Client Service representative should have already discussed a reporting hierarchy with you -- along with a Parent, Brand, and Sub-brand/Channel&lt;br /&gt;
* Your Technical Account Manager should have:&lt;br /&gt;
** provided you with an AppID&lt;br /&gt;
** informed you of our Opt-Out requirement for your App/Play Store description&lt;br /&gt;
** informed you of our Opt-Out requirement for a WebView inside your apps&lt;br /&gt;
* Retrieving AppSDK logs&lt;br /&gt;
** ‘nol_devDebug’ : ‘DEBUG’ should be present in initialization call (see below)&lt;br /&gt;
** Android: use adb logcat (note: requires Android Studio)&lt;br /&gt;
** iOS: idevicesyslog (note: requires XCode)&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The first step in the Certification process is to ensure that the Nielsen SDK is initializing at app startup, and that the global metadata values are present.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Value&lt;br /&gt;
|-&lt;br /&gt;
| appid || &amp;lt;code&amp;gt;PXXXXX-XXXXXX-XXXXX-XXXXX&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| appname || &amp;lt;code&amp;gt;example app name&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| appversion || &amp;lt;code&amp;gt;2.0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || &amp;lt;code&amp;gt;debug&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''iOS Example'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{ // AppID is Nielsen-supplied&lt;br /&gt;
	 @&amp;quot;appid&amp;quot;: @&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
 	 @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
 	 @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
 	 @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot; // required for testing only&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Android Example'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appversion&amp;quot;,&amp;quot;2.0&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug”, &amp;quot;DEBUG&amp;quot;); // required for testing only&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Cases ==&lt;br /&gt;
The following lists the test cases along with the Expected results:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Param !! Expected Result !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| SDK Initialized || &amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt; || Correct app id || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt; || Player name || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; || Correct build || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;'DEBUG&amp;lt;/code&amp;gt; || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== play() ===&lt;br /&gt;
* The &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt; call is required only once per viewing session (until app is killed)&lt;br /&gt;
* Called just before playback commences for first piece of content&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Param !! Expected Result !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| Play || &amp;lt;code&amp;gt;channelname&amp;lt;/code&amp;gt; || Name of Channel || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata() - Content ===&lt;br /&gt;
* Called at beginning of content, or when resuming content from interruption&lt;br /&gt;
* Fires before any playheadPosition update&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test !! Param !! Example Value !! Accepted Values !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| loadMetadata || &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;assetid&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;unique_id_500291&amp;quot;&amp;lt;/code&amp;gt; || (unique per asset) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;length&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;600&amp;quot;&amp;lt;/code&amp;gt; || length in seconds (int or float) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Episode Title&amp;quot;&amp;lt;/code&amp;gt; || (any non-empty value) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;program&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Show Name&amp;quot;&amp;lt;/code&amp;gt; || (any non-empty value) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;segB&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Primetime&amp;quot;&amp;lt;/code&amp;gt; || (any value), used for optional breakdown || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;segC&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Comedy&amp;quot;&amp;lt;/code&amp;gt; || (any value), used for optional breakdown || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;crossId1&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;EP018S9S290015&amp;quot;&amp;lt;/code&amp;gt; || Gracenote ID || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;crossId2&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;ABC&amp;quot;&amp;lt;/code&amp;gt; || Network Name || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;isfullepisode&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; || (&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;) (&amp;lt;code&amp;gt;&amp;quot;Y&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;N&amp;quot;&amp;lt;/code&amp;gt;) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;airdate&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;20160206 23:00:00&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;YYYYMMDD[space]HH:MM:SS&amp;quot;&amp;lt;/code&amp;gt; -- note: HH=24 hour time || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;adloadtype&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; for linear ads, &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; for DAI || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;hasAds&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; for no ads, &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; for has ads || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata() - ad ===&lt;br /&gt;
* Called at beginning of ad, or when resuming ad from interruption&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test !! Param !! Example Value !! Accepted Values !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| loadMetadata || &amp;lt;code&amp;gt;assetid&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;ad_2201343201&amp;quot;&amp;lt;/code&amp;gt; || (any non-empty value) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || Example&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== setPlayheadPosition() - Preroll ad ===&lt;br /&gt;
* Track current position of playhead&lt;br /&gt;
* Starts at 0 at the beginning of ad&lt;br /&gt;
* Updated at least once per second&lt;br /&gt;
* Separate playhead position for ads and content, should accurately reflect current position in either ads or content&lt;br /&gt;
* Final playhead position for content must equal the length specified in loadMetadata(), followed by end() call&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setPlayehadPosition&amp;lt;/code&amp;gt; || Called every second || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt; || Called at the end of Ad || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata() - Content ===&lt;br /&gt;
* Test is to validate Content metadata is the same as original metadata passed during initial loadMetadata call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test !! Param !! Example Value !! Accepted Values !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| loadMetadata || &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;assetid&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;unique_id_500291&amp;quot;&amp;lt;/code&amp;gt; || (unique per asset) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;length&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;600&amp;quot;&amp;lt;/code&amp;gt; || length in seconds (int or float) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Episode Title&amp;quot;&amp;lt;/code&amp;gt; || (any non-empty value) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;program&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Show Name&amp;quot;&amp;lt;/code&amp;gt; || (any non-empty value) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;segB&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Primetime&amp;quot;&amp;lt;/code&amp;gt; || (any value), used for optional breakdown || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;segC&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Comedy&amp;quot;&amp;lt;/code&amp;gt; || (any value), used for optional breakdown || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;crossId1&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;EP018S9S290015&amp;quot;&amp;lt;/code&amp;gt; || Gracenote ID || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;crossId2&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;ABC&amp;quot;&amp;lt;/code&amp;gt; || Network Name || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;isfullepisode&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; || (&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;) (&amp;lt;code&amp;gt;&amp;quot;Y&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;N&amp;quot;&amp;lt;/code&amp;gt;) || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;airdate&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;20160206 23:00:00&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;YYYYMMDD[space]HH:MM:SS&amp;quot;&amp;lt;/code&amp;gt; -- note: HH=24 hour time || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;adloadtype&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; for linear ads, &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; for DAI || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;hasAds&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; for no ads, &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; for has ads || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== setPlayheadPosition() - Content ===&lt;br /&gt;
* Track current position of playhead&lt;br /&gt;
* Starts at 0 at the beginning of content&lt;br /&gt;
* Updated at least once per second&lt;br /&gt;
* Separate playhead position for ads and content, should accurately reflect current position in either ads or content&lt;br /&gt;
* Final playhead position for content must equal the length specified in loadMetadata(), followed by end() call&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setPlayehadPosition&amp;lt;/code&amp;gt; || Called every second || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt; || Called at the end of Content || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== stop() ===&lt;br /&gt;
* Indicates one of the following:&lt;br /&gt;
* Playback of content or ad was interrupted&lt;br /&gt;
* Reached end of ad (no parameters or metadata)&lt;br /&gt;
&lt;br /&gt;
=== end() ===&lt;br /&gt;
* Reached the end of content (no parameters or metadata)&lt;br /&gt;
&lt;br /&gt;
== Interruptions ==&lt;br /&gt;
* All interruptions to playback of content or ads should trigger a call to stop(). Once the interruption is over, loadMetadata() with the same metadata should be called, followed by playheadPosition resuming from where it left off.&lt;br /&gt;
&lt;br /&gt;
* Interruptions include:&lt;br /&gt;
** user-induced pause&lt;br /&gt;
** screen turned off&lt;br /&gt;
** app sent to background&lt;br /&gt;
** headphones removed (note, if app simply switches audio output from headphones to speaker without pausing, there is no need to call stop())&lt;br /&gt;
** alarm/call interruption&lt;br /&gt;
** internet connection lost (n.b. cached playback plays as normal until it expires)&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| user-induced pause || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| screen turned off || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| app sent to background || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| headphones removed || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| alarm/call interruption || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| internet connection lost || &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| content paused || &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; is not passed || &lt;br /&gt;
|-&lt;br /&gt;
| resume content || &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; is called for content || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;loadMetadataM&amp;lt;/code&amp;gt; is the same as original || &lt;br /&gt;
|-&lt;br /&gt;
|  || &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; continues from resumed position || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Expected SDK behavior for all interruptions:'''&lt;br /&gt;
# interruption triggers stop() call&lt;br /&gt;
# when content resumes, loadMetadata() is called with the same metadata that was playing previously (ad or content)&lt;br /&gt;
# playheadPosition() resumes from the same position before the interruption&lt;br /&gt;
&lt;br /&gt;
'''Example session:'''&lt;br /&gt;
* 5 minutes of content played, call interruption, content resumes until end of 15 min video&lt;br /&gt;
&lt;br /&gt;
== Scrubbing ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| Scrub Backward || new playhead position is accurate || &lt;br /&gt;
|-&lt;br /&gt;
|  || new playhead continues from new position || &lt;br /&gt;
|-&lt;br /&gt;
| Scrub Forward || new playhead position is accurate || &lt;br /&gt;
|-&lt;br /&gt;
|  || new playhead continues from new position || &lt;br /&gt;
|-&lt;br /&gt;
| Scrub to end || final playhead position is passed || &lt;br /&gt;
|-&lt;br /&gt;
|  || end event called at completion of content playback || &lt;br /&gt;
|-&lt;br /&gt;
| Scrub past midroll || Playhead for content stops || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Midroll &amp;amp; Postroll Ads ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt; || Called for each Ad || &lt;br /&gt;
|-&lt;br /&gt;
|  || Required Metadata is accurate || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt; || Passed every second || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt; || called for each ad || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;loadMetadata()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;playheadPosition&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;stop()&amp;lt;/code&amp;gt; || correct sequence for each ad || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
Users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in 'WebView' / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Test Case !! Test Condition !! Pass/Fail&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;optOutView&amp;lt;/code&amp;gt; || User can Opt-Out || &lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=DAR_Android_SDK&amp;diff=1363</id>
		<title>DAR Android SDK</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=DAR_Android_SDK&amp;diff=1363"/>
		<updated>2017-08-29T19:28:19Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* SDK Integration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK''' and '''Sample Player''': A part of the downloaded package&lt;br /&gt;
If you do not have any of these pre-requisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] for more information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
== Import Library ==&lt;br /&gt;
Refer to [[Android SDK API Reference#Importing Frameworks|Android SDK API Reference - Importing Frameworks]] for information on importing libraries.&lt;br /&gt;
* The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The latest version of App SDK contains only appsdk.jar file and does not feature any native shared libraries like libAppSdk.so.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Initialize SDK ==&lt;br /&gt;
Initialize App SDK as soon as the application is launched. Refer to [[Android SDK API Reference#Initialization|Android SDK API Reference - Initialization]] for details on initializing an AppSDK object and the parameters required.&lt;br /&gt;
&lt;br /&gt;
== Configure API calls ==&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
DAR tags are used to track commercial delivery for campaign ratings. DAR tags are received during the streaming session from the Content Management System (CMS) identifying that the video contains ad content. This information should be passed as a JSON object via the [[loadMetadata()]] method with DAR contents.&lt;br /&gt;
&lt;br /&gt;
=== DAR Tags ===&lt;br /&gt;
Nielsen DAR tag may come in different forms from ad service via VAST XML or ad service integrated player framework library. The CMS data must be passed as a JSON object.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
    loadMetadata(JSONObject jsonMetadata);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refer to [[Digital Measurement Metadata]] section for the parameters to be passed in the JSON object.&lt;br /&gt;
&lt;br /&gt;
The DAR tags received from your CMS system should be transformed into a JSON string and passed in via the [[loadMetadata()]] method.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable Name !! Variable Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| type || Type identifies the tag content type. For DAR, the data type should be always set to &amp;quot;ad&amp;quot;. || ad&lt;br /&gt;
|-&lt;br /&gt;
| ocrtag || The complete tag/URL is supplied by your Technical Account Manager. This should include the complete URL including the http portion. The ocrtag should be properly URI encoded. || &amp;lt;nowiki&amp;gt;http://secure-uat-cert.imrworldwide.com&amp;lt;/nowiki&amp;gt;&amp;lt;wbr /&amp;gt;/cgi-bin&amp;lt;wbr /&amp;gt;/m?ci= ENTXX5&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;ep=1&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st= image&amp;lt;wbr /&amp;gt;&amp;amp;ca=XX1717&amp;lt;wbr /&amp;gt;&amp;amp;cr=crvXX35&amp;lt;wbr /&amp;gt;&amp;amp;pc=plc1234&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Integration ===&lt;br /&gt;
After getting the string from an ad service, to integrate Nielsen SDK for DAR tag, the app should first identify a Nielsen beacon in the use cases below&lt;br /&gt;
* If the input string is CDATA string, get the value of the CDATA as a new input string.&lt;br /&gt;
* If the input string (or new input string) starts with http and the hostname ends with “imrworldwide.com”, the input string is a Nielsen beacon (case 1 and case 3).&lt;br /&gt;
* If the input string (or new input string) starts with http and the CR field exists&lt;br /&gt;
** Get the value of the CR field.&lt;br /&gt;
** If the CR value starts with http and the hostname of the CR value ends with “imrworldwide.com”, the CR value is a Nielsen beacon (case 2 and case 4).&lt;br /&gt;
** If the Nielsen beacon exists, remove the value of the CR field from the input string and process the updated string for the non-DAR beacon.&lt;br /&gt;
* If the Nielsen beacon exists&lt;br /&gt;
** URL decode the Nielsen beacon.&lt;br /&gt;
** If the c13 field exists in the Nielsen beacon, remove the c13 from the Nielsen beacon.&lt;br /&gt;
** Create JSON with the Nielsen beacon&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;ad&amp;quot;,&lt;br /&gt;
        &amp;quot;ocrtag&amp;quot;: &amp;quot;&amp;lt;Nielsen beacon&amp;gt;&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* '''EXAMPLE''': Sample JSON string with the DAR string (decoded http string without the c13)&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;ad&amp;quot;,&lt;br /&gt;
        &amp;quot;ocrtag&amp;quot;: &amp;quot;http://secure-gl.imrworldwide.com/cgi-bin/m?ci=ent30986&amp;amp;am=22&amp;amp;ep=1&amp;amp;at=view&amp;amp;rt=banner&amp;amp;st=image&amp;amp;ca=cmp97144&amp;amp;cr=1186239&amp;amp;pc=3739659&amp;amp;r=2011370876&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
** Send the JSON to the Nielsen SDK using loadMetadata.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Measurement Opt-Out Implementation ==&lt;br /&gt;
As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. Our digital measurement products are not used to identify the consumer in any way, but they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.&lt;br /&gt;
* When the app user wants to opt in or opt out of Nielsen measurement, a new dynamic page (with content string obtained from [[userOptOutURLString()]]) should be displayed.&lt;br /&gt;
** Use [[getOptOutStatus()]] to retrieve the device’s Opt-Out status.&lt;br /&gt;
* This Opt-out page should be displayed in a webview (within the app) and not in any external browser.&lt;br /&gt;
* Capture the user’s selection in this page and pass it to the SDK through [[userOptOut()]] for Nielsen to save the user’s preference.&lt;br /&gt;
* For more details, refer to [[Android SDK API Reference#Android Opt-Out Implementation|Android SDK API Reference - Android Opt-Out Implementation]] and Nielsen Digital Privacy.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The SDK will continue measurement even after the user has opted out from Nielsen measurement.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-Certification Checklists ===&lt;br /&gt;
After the application is ready to be sent for Nielsen Certification, please go through the Pre-Certification Checklist and ensure the app behaves as expected, before submitting to Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Testing an Implementation - App ===&lt;br /&gt;
See [[Digital Measurement Testing]].&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=DAR_Android_SDK&amp;diff=1361</id>
		<title>DAR Android SDK</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=DAR_Android_SDK&amp;diff=1361"/>
		<updated>2017-08-29T19:19:34Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* SDK Integration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK''' and '''Sample Player''': A part of the downloaded package&lt;br /&gt;
If you do not have any of these pre-requisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] for more information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
== Import Library ==&lt;br /&gt;
Refer to [[Android SDK API Reference#Importing Frameworks|Android SDK API Reference - Importing Frameworks]] for information on importing libraries.&lt;br /&gt;
* The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The latest version of App SDK contains only appsdk.jar file and does not feature any native shared libraries like libAppSdk.so.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Initialize SDK ==&lt;br /&gt;
Initialize App SDK as soon as the application is launched. Refer to [[Android SDK API Reference#Initialization|Android SDK API Reference - Initialization]] for details on initializing an AppSDK object and the parameters required.&lt;br /&gt;
&lt;br /&gt;
== Configure API calls ==&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
DAR tags are used to track commercial delivery for campaign ratings. DAR tags are received during the streaming session from the Content Management System (CMS) identifying that the video contains ad content. This information should be passed as a JSON object via the [[loadMetadata()]] method with DAR contents.&lt;br /&gt;
&lt;br /&gt;
=== DAR Tags ===&lt;br /&gt;
Nielsen DAR tag may come in different forms from ad service via VAST XML or ad service integrated player framework library. The CMS data must be passed as a JSON object.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
    loadMetadata(JSONObject jsonMetadata);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refer to [[Digital Measurement Metadata]] section for the parameters to be passed in the JSON object.&lt;br /&gt;
&lt;br /&gt;
The DAR tags received from your CMS system should be transformed into a JSON string and passed in via the [[loadMetadata()]] method.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable Name !! Variable Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| type || Type identifies the tag content type. For DAR, the data type should be always set to &amp;quot;ad&amp;quot;. || ad&lt;br /&gt;
|-&lt;br /&gt;
| ocrtag || The complete tag/URL is supplied by your Technical Account Manager. This should include the complete URL including the http portion. The ocrtag should be properly URI encoded. || &amp;lt;nowiki&amp;gt;http://secure-uat-cert.imrworldwide.com&amp;lt;/nowiki&amp;gt;&amp;lt;wbr /&amp;gt;/cgi-bin&amp;lt;wbr /&amp;gt;/m?ci= ENTXX5&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;ep=1&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st= image&amp;lt;wbr /&amp;gt;&amp;amp;ca=XX1717&amp;lt;wbr /&amp;gt;&amp;amp;cr=crvXX35&amp;lt;wbr /&amp;gt;&amp;amp;pc=plc1234&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Integration ===&lt;br /&gt;
After getting the string from an ad service, to integrate Nielsen SDK for DAR tag, the app should first identify a Nielsen beacon in the use cases below&lt;br /&gt;
* If the input string is CDATA string, get the value of the CDATA as a new input string.&lt;br /&gt;
* If the input string (or new input string) starts with http and the hostname ends with “imrworldwide.com”, the input string is a Nielsen beacon (case 1 and case 3).&lt;br /&gt;
* If the input string (or new input string) starts with http and the CR field exists&lt;br /&gt;
** Get the value of the CR field.&lt;br /&gt;
** If the CR value starts with http and the hostname of the CR value ends with “imrworldwide.com”, the CR value is a Nielsen beacon (case 2 and case 4).&lt;br /&gt;
** If the Nielsen beacon exists, remove the value of the CR field from the input string and process the updated string for the non-DAR beacon.&lt;br /&gt;
* If the Nielsen beacon exists&lt;br /&gt;
** URL decode the Nielsen beacon.&lt;br /&gt;
** If the c13 field exists in the Nielsen beacon, remove the c13 from the Nielsen beacon.&lt;br /&gt;
** Create JSON with the Nielsen beacon&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;ad&amp;quot;,&lt;br /&gt;
        &amp;quot;ocrtag&amp;quot;: &amp;quot;&amp;lt;Nielsen beacon&amp;gt;&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* '''EXAMPLE''': Sample JSON string with the DAR string (decoded http string without the c13)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;ad&amp;quot;,&lt;br /&gt;
        &amp;quot;ocrtag&amp;quot;: &amp;quot;http://secure-gl.imrworldwide.com/cgi-bin/m?ci=ent30986&amp;amp;am=22&amp;amp;ep=1&amp;amp;at=view&amp;amp;rt=banner&amp;amp;st=image&amp;amp;ca=cmp97144&amp;amp;cr=1186239&amp;amp;pc=3739659&amp;amp;r=2011370876&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
** Send the JSON to the Nielsen SDK using loadMetadata.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Measurement Opt-Out Implementation ==&lt;br /&gt;
As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. Our digital measurement products are not used to identify the consumer in any way, but they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.&lt;br /&gt;
* When the app user wants to opt in or opt out of Nielsen measurement, a new dynamic page (with content string obtained from [[userOptOutURLString()]]) should be displayed.&lt;br /&gt;
** Use [[getOptOutStatus()]] to retrieve the device’s Opt-Out status.&lt;br /&gt;
* This Opt-out page should be displayed in a webview (within the app) and not in any external browser.&lt;br /&gt;
* Capture the user’s selection in this page and pass it to the SDK through [[userOptOut()]] for Nielsen to save the user’s preference.&lt;br /&gt;
* For more details, refer to [[Android SDK API Reference#Android Opt-Out Implementation|Android SDK API Reference - Android Opt-Out Implementation]] and Nielsen Digital Privacy.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The SDK will continue measurement even after the user has opted out from Nielsen measurement.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-Certification Checklists ===&lt;br /&gt;
After the application is ready to be sent for Nielsen Certification, please go through the Pre-Certification Checklist and ensure the app behaves as expected, before submitting to Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Testing an Implementation - App ===&lt;br /&gt;
See [[Digital Measurement Testing]].&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=DAR_Android_SDK&amp;diff=1360</id>
		<title>DAR Android SDK</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=DAR_Android_SDK&amp;diff=1360"/>
		<updated>2017-08-29T19:19:22Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* SDK Integration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK''' and '''Sample Player''': A part of the downloaded package&lt;br /&gt;
If you do not have any of these pre-requisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] for more information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
== Import Library ==&lt;br /&gt;
Refer to [[Android SDK API Reference#Importing Frameworks|Android SDK API Reference - Importing Frameworks]] for information on importing libraries.&lt;br /&gt;
* The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The latest version of App SDK contains only appsdk.jar file and does not feature any native shared libraries like libAppSdk.so.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Initialize SDK ==&lt;br /&gt;
Initialize App SDK as soon as the application is launched. Refer to [[Android SDK API Reference#Initialization|Android SDK API Reference - Initialization]] for details on initializing an AppSDK object and the parameters required.&lt;br /&gt;
&lt;br /&gt;
== Configure API calls ==&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
DAR tags are used to track commercial delivery for campaign ratings. DAR tags are received during the streaming session from the Content Management System (CMS) identifying that the video contains ad content. This information should be passed as a JSON object via the [[loadMetadata()]] method with DAR contents.&lt;br /&gt;
&lt;br /&gt;
=== DAR Tags ===&lt;br /&gt;
Nielsen DAR tag may come in different forms from ad service via VAST XML or ad service integrated player framework library. The CMS data must be passed as a JSON object.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
    loadMetadata(JSONObject jsonMetadata);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refer to [[Digital Measurement Metadata]] section for the parameters to be passed in the JSON object.&lt;br /&gt;
&lt;br /&gt;
The DAR tags received from your CMS system should be transformed into a JSON string and passed in via the [[loadMetadata()]] method.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable Name !! Variable Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| type || Type identifies the tag content type. For DAR, the data type should be always set to &amp;quot;ad&amp;quot;. || ad&lt;br /&gt;
|-&lt;br /&gt;
| ocrtag || The complete tag/URL is supplied by your Technical Account Manager. This should include the complete URL including the http portion. The ocrtag should be properly URI encoded. || &amp;lt;nowiki&amp;gt;http://secure-uat-cert.imrworldwide.com&amp;lt;/nowiki&amp;gt;&amp;lt;wbr /&amp;gt;/cgi-bin&amp;lt;wbr /&amp;gt;/m?ci= ENTXX5&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;ep=1&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st= image&amp;lt;wbr /&amp;gt;&amp;amp;ca=XX1717&amp;lt;wbr /&amp;gt;&amp;amp;cr=crvXX35&amp;lt;wbr /&amp;gt;&amp;amp;pc=plc1234&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Integration ===&lt;br /&gt;
After getting the string from an ad service, to integrate Nielsen SDK for DAR tag, the app should first identify a Nielsen beacon in the use cases below&lt;br /&gt;
* If the input string is CDATA string, get the value of the CDATA as a new input string.&lt;br /&gt;
* If the input string (or new input string) starts with http and the hostname ends with “imrworldwide.com”, the input string is a Nielsen beacon (case 1 and case 3).&lt;br /&gt;
* If the input string (or new input string) starts with http and the CR field exists&lt;br /&gt;
** Get the value of the CR field.&lt;br /&gt;
** If the CR value starts with http and the hostname of the CR value ends with “imrworldwide.com”, the CR value is a Nielsen beacon (case 2 and case 4).&lt;br /&gt;
** If the Nielsen beacon exists, remove the value of the CR field from the input string and process the updated string for the non-DAR beacon.&lt;br /&gt;
* If the Nielsen beacon exists&lt;br /&gt;
** URL decode the Nielsen beacon.&lt;br /&gt;
** If the c13 field exists in the Nielsen beacon, remove the c13 from the Nielsen beacon.&lt;br /&gt;
** Create JSON with the Nielsen beacon&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;ad&amp;quot;,&lt;br /&gt;
        &amp;quot;ocrtag&amp;quot;: &amp;quot;&amp;lt;Nielsen beacon&amp;gt;&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* '''EXAMPLE''': Sample JSON string with the DAR string (decoded http string without the c13)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;ad&amp;quot;,&lt;br /&gt;
        &amp;quot;ocrtag&amp;quot;: &amp;quot;http://secure-gl.imrworldwide.com/cgi-bin/m?ci=ent30986&amp;amp;am=22&amp;amp;ep=1&amp;amp;at=view&amp;amp;rt=banner&amp;amp;st=image&amp;amp;ca=cmp97144&amp;amp;cr=1186239&amp;amp;pc=3739659&amp;amp;r=2011370876&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Send the JSON to the Nielsen SDK using loadMetadata.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Measurement Opt-Out Implementation ==&lt;br /&gt;
As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. Our digital measurement products are not used to identify the consumer in any way, but they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.&lt;br /&gt;
* When the app user wants to opt in or opt out of Nielsen measurement, a new dynamic page (with content string obtained from [[userOptOutURLString()]]) should be displayed.&lt;br /&gt;
** Use [[getOptOutStatus()]] to retrieve the device’s Opt-Out status.&lt;br /&gt;
* This Opt-out page should be displayed in a webview (within the app) and not in any external browser.&lt;br /&gt;
* Capture the user’s selection in this page and pass it to the SDK through [[userOptOut()]] for Nielsen to save the user’s preference.&lt;br /&gt;
* For more details, refer to [[Android SDK API Reference#Android Opt-Out Implementation|Android SDK API Reference - Android Opt-Out Implementation]] and Nielsen Digital Privacy.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The SDK will continue measurement even after the user has opted out from Nielsen measurement.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-Certification Checklists ===&lt;br /&gt;
After the application is ready to be sent for Nielsen Certification, please go through the Pre-Certification Checklist and ensure the app behaves as expected, before submitting to Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Testing an Implementation - App ===&lt;br /&gt;
See [[Digital Measurement Testing]].&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=DAR_iOS_SDK&amp;diff=1359</id>
		<title>DAR iOS SDK</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=DAR_iOS_SDK&amp;diff=1359"/>
		<updated>2017-08-29T19:18:57Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* SDK Integration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK''' and '''Sample Player''': A part of the downloaded package&lt;br /&gt;
If you do not have any of these pre-requisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] for more information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
== Import Library ==&lt;br /&gt;
Refer to [[iOS SDK API Reference#Importing Frameworks|iOS SDK API Reference - Importing Frameworks]] for information on importing libraries.&lt;br /&gt;
* The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues.&lt;br /&gt;
&lt;br /&gt;
== Initialize SDK ==&lt;br /&gt;
Initialize App SDK as soon as the application is launched. Refer to [[iOS SDK API Reference#Initialization|iOS SDK API Reference - Initialization]] for details on initializing an AppSDK object and the parameters required.&lt;br /&gt;
&lt;br /&gt;
== Configure API calls ==&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
DAR tags are used to track commercial delivery for campaign ratings. DAR tags are received during the streaming session from the Content Management System (CMS) identifying that the video contains ad content. This information should be passed as a JSON object via the [[loadMetadata]] method with DAR contents.&lt;br /&gt;
&lt;br /&gt;
=== DAR Tags ===&lt;br /&gt;
Nielsen DAR tag may come in different forms from ad service via VAST XML or ad service integrated player framework library&lt;br /&gt;
&lt;br /&gt;
The CMS data must be passed as a JSON object.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)loadMetadata:(id)metadata;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refer to [[Digital Measurement Metadata]] section for the list of parameters to be passed in the JSON object.&lt;br /&gt;
&lt;br /&gt;
[[loadMetadata]] call after the first play call must have ‘content’ details (&amp;lt;code&amp;gt;&amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;). This call should occur before any preroll ad starts playing.&lt;br /&gt;
&lt;br /&gt;
=== API Call sequence ===&lt;br /&gt;
Call [[loadMetadata]] with JSON metadata for content as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
    NSDictionary* metaDatainformation =&lt;br /&gt;
    @{&lt;br /&gt;
        @&amp;quot;type&amp;quot; : @&amp;quot;ad&amp;quot;,&lt;br /&gt;
        @&amp;quot;ocrtag&amp;quot; : @&amp;quot;URL received from Ad server&amp;quot;&lt;br /&gt;
    };&lt;br /&gt;
    NSData* jsonDARInfo = [NSJSONSerialization dataWithJSONObject:metaDatainformation options:0 error:nil];&lt;br /&gt;
    NSString* darInfo = [[NSString alloc] initWithBytes:[jsonDARInfo bytes]&lt;br /&gt;
    length:[jsonDARInfo length]&lt;br /&gt;
    encoding:NSUTF8StringEncoding];&lt;br /&gt;
    [NID3Meter loadMetadata:darInfo];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The DAR tags received from your CMS system should be transformed into a JSON string and passed in via the [[loadMetadata]] method.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable Name !! Variable Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| type || Type identifies the tag content type. For DAR, the data type should be always set to &amp;quot;ad&amp;quot;. || ad&lt;br /&gt;
|-&lt;br /&gt;
| ocrtag || The complete tag/URL is supplied by your Technical Account Manager. This should include the complete URL including the http portion. The ocrtag should be properly URI encoded. || &amp;lt;nowiki&amp;gt;http://secure-uat-cert.imrworldwide.com&amp;lt;/nowiki&amp;gt;&amp;lt;wbr /&amp;gt;/cgi-bin&amp;lt;wbr /&amp;gt;/m?ci&amp;lt;wbr /&amp;gt;= ENTXX5&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;ep=1&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st= image&amp;lt;wbr /&amp;gt;&amp;amp;ca=XX1717&amp;lt;wbr /&amp;gt;&amp;amp;cr=crvXX35&amp;lt;wbr /&amp;gt;&amp;amp;pc=plc1234&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Integration ===&lt;br /&gt;
After getting the string from an ad service, to integrate Nielsen SDK for DAR tag, the app should first identify a Nielsen beacon in the use cases below&lt;br /&gt;
* If the input string is CDATA string, get the value of the CDATA as a new input string.&lt;br /&gt;
* If the input string (or new input string) starts with http and the hostname ends with “imrworldwide.com”, the input string is a Nielsen beacon (case 1 and case 3).&lt;br /&gt;
* If the input string (or new input string) starts with http and the CR field exists&lt;br /&gt;
** Get the value of the CR field.&lt;br /&gt;
** If the CR value starts with http and the hostname of the CR value ends with “imrworldwide.com”, the CR value is a Nielsen beacon (case 2 and case 4).&lt;br /&gt;
** If the Nielsen beacon exists, remove the value of the CR field from the input string and process the updated string for the non-DAR beacon.&lt;br /&gt;
* If the Nielsen beacon exists&lt;br /&gt;
** URL decode the Nielsen beacon.&lt;br /&gt;
** If the c13 field exists in the Nielsen beacon, remove the c13 from the Nielsen beacon.&lt;br /&gt;
** Create JSON with the Nielsen beacon&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;ad&amp;quot;,&lt;br /&gt;
        &amp;quot;ocrtag&amp;quot;: &amp;quot;&amp;lt;Nielsen beacon&amp;gt;&amp;quot;&lt;br /&gt;
    }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* '''EXAMPLE''': Sample JSON string with the DAR string (decoded http string without the c13)&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;ad&amp;quot;,&lt;br /&gt;
        &amp;quot;ocrtag&amp;quot;: &amp;quot;http://secure-gl.imrworldwide.com/cgi-bin/m?ci=ent30986&amp;amp;am=22&amp;amp;ep=1&amp;amp;at=view&amp;amp;rt=banner&amp;amp;st=image&amp;amp;ca=cmp97144&amp;amp;cr=1186239&amp;amp;pc=3739659&amp;amp;r=2011370876&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
** Send the JSON to the Nielsen SDK using loadMetadata.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Measurement Opt-Out Implementation ==&lt;br /&gt;
As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. Our digital measurement products are not used to identify the consumer in any way, but they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.&lt;br /&gt;
* When the app user wants to opt in or opt out of Nielsen measurement, a new dynamic page (with content string obtained from [[optOutURL]]) should be displayed.&lt;br /&gt;
** Use [[optOutStatus]] to retrieve the device’s Opt-Out status.&lt;br /&gt;
* This Opt-out page should be displayed in a webview (within the app) and not in any external browser.&lt;br /&gt;
* Capture the user’s selection in this page and pass it to the SDK through [[userOptOut]] for Nielsen to save the user’s preference.&lt;br /&gt;
* For more details, refer to [[iOS SDK API Reference#iOS Opt-Out Implementation|iOS SDK API Reference - iOS Opt-Out Implementation]] and Nielsen Digital Privacy.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Note: The SDK will continue measurement even after the user has opted out from Nielsen measurement.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-Certification Checklists ===&lt;br /&gt;
After the application is ready to be sent for Nielsen Certification, please go through the Pre-Certification Checklist and ensure the app behaves as expected, before submitting to Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Testing an Implementation - App ===&lt;br /&gt;
See [[Digital Measurement Testing ]].&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Mobile_DAR_Attributes_Requirements&amp;diff=1358</id>
		<title>Mobile DAR Attributes Requirements</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Mobile_DAR_Attributes_Requirements&amp;diff=1358"/>
		<updated>2017-08-29T19:16:26Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Appendix A: Example Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Currently, Nielsen’s DAR tags are well supported online via '''browser'''-based viewing on PCs, MACs, and tablets/smartphones. However, when ads are served to tablets/smartphones via native '''app-store applications''', additional attributes are needed in order for Nielsen clients to employ Nielsen’s mobile DAR (mDAR) measurement product.&lt;br /&gt;
&lt;br /&gt;
One way Nielsen clients can accomplish this is by the use of Nielsen’s native iOS/Android App SDK. Nielsen’s App SDK automatically adds these additional mobile attributes to mDAR measurement pings that are sent to Nielsen’s collection system. However, there is a significant portion of the mobile application universe where it is either not feasible, or desirable to integrate Nielsen’s native App SDK into 3rd party applications.&lt;br /&gt;
&lt;br /&gt;
This document describes additional attributes that must be added to DAR pings to create mDAR-compliant tags by way of a server-side macro replacement. This method is often referred to as Nielsen’s “non-SDK” DAR solution. Nielsen envisions that these attributes be added by ad networks when they respond to ad requests from client mobile devices.&lt;br /&gt;
&lt;br /&gt;
To support the insertion of the Advertising ID, it is assumed that you have published a specification that app publishers follow to pass the appropriate Advertising ID (for example, IDFA) in the Ad request URL. Typically, your Ad server will expand a macro that grabs that ID seen in the Ad request URL and pass it via the DAR pixel outlined below. See [[#Appendix A: Example Implementation]].&lt;br /&gt;
&lt;br /&gt;
Finally, once you have completed your integration, you will be required to submit to a short certification. See [[#Appendix B: Implementation, Testing &amp;amp; Certification]]. Certification also grants inclusion to the approved publisher and platform vendor list.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Additional DAR Tag Parameters for Mobile !! Description !! Mandatory?&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c7 || OS Grouping ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c8  || Device Grouping || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c9 || Advertising ID || &amp;lt;center&amp;gt;✔&amp;lt;/center&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c10 || Platform || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c12 || App Version ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c13 || AppID (Nielsen assigned App ID) || &amp;lt;center&amp;gt;✔&amp;lt;/center&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c14 || OS Version ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;uoo || Opt-out indicator || When applicable&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Clients are encouragesd to make an effort to always fill-in optional parameters.&lt;br /&gt;
&lt;br /&gt;
'''Note''': Do not URL encode the values.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C7 - OS Grouping (Optional) ==&lt;br /&gt;
Valid device OS Grouping data values are the following literal values:&lt;br /&gt;
* osgrp,IOS&lt;br /&gt;
* osgrp,DROID&lt;br /&gt;
* osgrp,ANDROID&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If one of the above values cannot be specific, then the parameter should not be included int he call.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C8 - Device Grouping ==&lt;br /&gt;
Valid literal values for phone, tablet, portable media player (iPod) and unknown are as follows:&lt;br /&gt;
* devgrp,PHN&lt;br /&gt;
* devgrp,TAB&lt;br /&gt;
* devgrp,PMP&lt;br /&gt;
* devgrp,UNWN&lt;br /&gt;
* devgrp,DSK&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If one of the above values cannot be specific, then the parameter should not be included in the call or should be left empty&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C9 - Advertising ID ==&lt;br /&gt;
This is the advertiser ID for the client’s mobile device. IDFA for iOS, Google Advertising ID for Android:&lt;br /&gt;
* devid,&amp;lt;IDFA&amp;gt;&lt;br /&gt;
* devid,&amp;lt;IFA&amp;gt;&lt;br /&gt;
* devid,&amp;lt;Google Advertising ID&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For Android devices, the Google Advertiser ID should be used as the default and the Android ID as the second option.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': If C9 is &amp;lt;empty&amp;gt;, upon receiving the ping, the Nielsen collection server will attempt a 302 redirect to the data provider per the regular DAR pixel for browsers.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As of August 1, 2014, Google is enforcing use of the Advertising ID for advertising and user analytics (http://play.google.com/about/developer-content-policy.html).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'' &amp;quot;Beginning August 1st 2014, all updates and new apps uploaded to the Play Store must use the advertising ID (when available on a device) in lieu of any other device identifiers for any advertising purposes.&amp;quot;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is preferred that the IDFA or Google Advertising ID be sent as is from the mobile device (“cleartext”). However, if mandated, we will support SHA256 hashed values with no-salt. Passing a hashed value (and/or salting) using any other standard will result in a failed match by the data provider upon receiving the ping. In turn, this results in impressions surfacing in the DAR unmeasurable audience totals. Please contact Nielsen if you anticipate a large percentage of hashed values coming in from your publisher clients.&lt;br /&gt;
&lt;br /&gt;
=== Privacy, Ad Tracking, and Ad Targeting ===&lt;br /&gt;
In newer iterations of the iOS and Android device operating systems, a facility exists allowing users to “opt-out” of “Ad Tracking”. It is Nielsen’s interpretation that this setting is primarily designed to allow users to specify opt-out of Ad Targeting rather than Ad Measurement. DAR&lt;br /&gt;
does not provide Ad Targeting data.&lt;br /&gt;
&lt;br /&gt;
However, it is also Nielsen’s position that the publisher or Ad network should provide a mechanism to also allow a user to opt-out of Ad Measurement. The Nielsen SDK will honor the Nielsen Ad Measurement opt-out settings configurable @ http://www.nielsen.com/us/en/campaigns/privacy-policy-opt-out.html.&lt;br /&gt;
&lt;br /&gt;
However if the integration approach described in this document is being used instead of the Nielsen SDK then '''YOU''' as the publisher or Ad network must provide a capability to opt-out of Ad Measurement as the configuration on www.nielsen.com will not be detectable. You may&lt;br /&gt;
elect to interpret the iOS / Android “Ad Tracking” setting for the purpose of limit Ad measurement or provide a separate discreet mechanism to allow a user to opt-out of Ad measurement.&lt;br /&gt;
&lt;br /&gt;
Please see '''&amp;amp;uoo''' later in this document for implementation details of the optout indicator.&lt;br /&gt;
&lt;br /&gt;
For additional clarification on privacy policy, please contact your Nielsen representative.&lt;br /&gt;
&lt;br /&gt;
== C10 - Platform ==&lt;br /&gt;
To determine this value, Nielsen suggests that the ad network leverage user agent information to determine if the client device is either a mobile or desktop device.&lt;br /&gt;
&lt;br /&gt;
Valid literal values for mobile and desktop data values are as follows:&lt;br /&gt;
* plt,MBL&lt;br /&gt;
* plt,DSK&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If one of the above values cannot be specific, then the parameter should not be included in the call or&lt;br /&gt;
should be left empty.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C12 - App Version (Optional) ==&lt;br /&gt;
This is the version of the ad network system software or SDK that is implemented in this extension. Although this field is not required, this feature can be useful for troubleshooting purposes following deployment.&lt;br /&gt;
* apv,&amp;lt;N.N&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C13 - AppID ==&lt;br /&gt;
This Nielsen provided ID is unique to the ad network and is required for certification.&lt;br /&gt;
* asid,&amp;lt;NNNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN&amp;gt;&lt;br /&gt;
An App ID will be provided for testing. A separate App ID will be provided for production use. Please request from your Nielsen representative.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If you are a publisher leveraging the non-SDK solution, you will be provided with a unique App ID for each combination of app and device OS type.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C14 - OS Version (Optional) ==&lt;br /&gt;
Operating system version&lt;br /&gt;
* osver,&amp;lt;OS Version&amp;gt;&lt;br /&gt;
Example: for iOS -&amp;gt; 7.0.4&lt;br /&gt;
&lt;br /&gt;
== UOO - Opt Out (Optional) ==&lt;br /&gt;
Opt-out parameter&lt;br /&gt;
* &amp;lt;Boolean state&amp;gt;&lt;br /&gt;
&amp;lt;Boolean state&amp;gt; is a Boolean representation of whether the user is opting out or not.&lt;br /&gt;
&lt;br /&gt;
The absence of uoo in the tag is interpreted as an implicit opt-in. i.e. not opting out.&lt;br /&gt;
&lt;br /&gt;
The following pairings of opt-out are supported. Important: you must choose one set of paired values only and inform your Nielsen representative.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Opt-out !! Opt-in&lt;br /&gt;
|-&lt;br /&gt;
| uoo=true || uoo=false&lt;br /&gt;
|-&lt;br /&gt;
| uoo=1 || uoo=0&lt;br /&gt;
|-&lt;br /&gt;
| uoo=yes || uoo=no&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''':  if your Ad server is not capable os supporting the discrete &amp;amp;uoo parameter then you can set the c9 value to &amp;lt;code&amp;gt;devid,optout&amp;lt;/code&amp;gt; (for example &amp;lt;code&amp;gt;…&amp;amp;c8=PHN&amp;amp;c9=devid,optout&amp;amp;c10=MBL…&amp;lt;/code&amp;gt;)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples of DAR and mDAR Tags ==&lt;br /&gt;
For each of the tag examples detailed below, we can support both unsecure (http) and secure (https) flavors.&lt;br /&gt;
&lt;br /&gt;
'''Important note''': the values in the following tags are for illustrative purposes only. Please contact your Nielsen representative for specific parameter values for your use of DAR.&lt;br /&gt;
&lt;br /&gt;
'''Test and Certification'''&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://secure-cert.imrworldwide.com&amp;lt;/nowiki&amp;gt;/cgi-bin/m?ci=nlsnci535&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st=image&amp;lt;wbr /&amp;gt;&amp;amp;ca=nlsn12452&amp;lt;wbr /&amp;gt;&amp;amp;cr=crtve&amp;lt;wbr /&amp;gt;&amp;amp;pc=%3cclientname%3e_plc0001&amp;lt;wbr /&amp;gt;&amp;amp;ce=%3cclientname%3e&amp;lt;wbr /&amp;gt;&amp;amp;c7=osgrp&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Production'''&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://secure-gl.imrworldwide.com&amp;lt;/nowiki&amp;gt;/cgibin/m?ci=nlsnci535&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st=image&amp;lt;wbr /&amp;gt;&amp;amp;ca=nlsn12452&amp;lt;wbr /&amp;gt;&amp;amp;cr=crtve&amp;lt;wbr /&amp;gt;&amp;amp;pc=&amp;lt;clientname&amp;gt;_plc0001&amp;lt;wbr /&amp;gt;&amp;amp;ce=&amp;lt;clientname&amp;gt;&amp;lt;wbr /&amp;gt;&amp;amp;c7=osgrp,IOS&amp;lt;wbr /&amp;gt;&amp;amp;c8=devgrp,TAB&amp;lt;wbr /&amp;gt;&amp;amp;c9=devid,XXXX-XX-XXXXX-XXXX&amp;lt;wbr /&amp;gt;&amp;amp;c10=plt,MBL &amp;lt;wbr /&amp;gt;&amp;amp;c12=apv,AppVersion&amp;lt;wbr /&amp;gt;&amp;amp;c13=asid,NIELSEN-PROVIDEDID&amp;lt;wbr /&amp;gt;&amp;amp;c14=osver,7.0.4&amp;lt;wbr /&amp;gt;&amp;amp;uoo=1&amp;lt;wbr /&amp;gt;&amp;amp;r=[timestamp]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Standard DAR tag (for information and completeness)'''&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://secure-gl.imrworldwide.com&amp;lt;/nowiki&amp;gt;/cgi-bin/m?ci=nlsnci535&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st=image&amp;lt;wbr /&amp;gt;&amp;amp;ca=nlsn12452&amp;lt;wbr /&amp;gt;&amp;amp;cr=crtve&amp;lt;wbr /&amp;gt;&amp;amp;pc=%3cclientname%3e_plc0001&amp;lt;wbr /&amp;gt;&amp;amp;ce=%3cclientname%3e&amp;lt;wbr /&amp;gt;&amp;amp;uoo=1&amp;lt;wbr /&amp;gt;&amp;amp;r=%5btimestamp&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Appendix A: Example Implementation ==&lt;br /&gt;
In the below examples, you will see the overall DAR flow (Figure 1) and a detailed illustrative Ad Request / Response model (Figure 2).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Figure 1 – End to End Data Flow'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:mDAR_Dataflow.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Nielsen certified publishers and platforms will append the new parameters (below) with the appropriate URL safe values passed to Nielsen’s current DAR tag. The current DAR tag should be acquired using the existing processes for each campaign/placement. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;lt;code&amp;gt;'''&amp;amp;c7'''=osgrp,IOS'''&amp;amp;c8'''=devgrp,PHN'''&amp;amp;c9'''=devid,XXXX-XX-XXXXXXXXX'''&amp;amp;c10'''=plt,MBL'''&amp;amp;c12'''=apv,AppVersion'''&amp;amp;c13'''=asid,XXXX-XX-XXXX-XXXX&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Figure 2 – Illustrative Ad Request / Ad Response'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ad_response.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
The above is an example of how an Ad server is supporting the build of mobile DAR tags for its publisher clients. Step 2 in Figure 1 is a summary of steps 1 and 2 in Figure 2 above. Steps 3 and 4 in Figure 1 is a summary of steps 3 through 9 in Figure 2 above.&lt;br /&gt;
&lt;br /&gt;
== Appendix B: Implementation, Testing &amp;amp; Certification ==&lt;br /&gt;
Once you have integrated the ping per the above specs, Nielsen requires you to pass through a one-time certification before traffic can be accepted into the production environment.&lt;br /&gt;
&lt;br /&gt;
The overall process is:&lt;br /&gt;
# Valid DAR contract or NDA is in place.&lt;br /&gt;
# Kick-off meeting with Nielsen onboarding team.&lt;br /&gt;
# Confirm meet minimums testing requriements:&lt;br /&gt;
## Host Ad/Tag for in-app delivery&lt;br /&gt;
## Can pass opt-out back to Nielsen&lt;br /&gt;
## Can pass Device ID in cleartext or SHA-256&lt;br /&gt;
# Nielsen provides the mDAR testing form that includes the test App ID and the test tag&lt;br /&gt;
# Implement the specification and provide Nielsen the completed testing form.&lt;br /&gt;
# Identify the live campaigns for intial testing and run the test tag; suggest 5,000-10,000 impressions.&lt;br /&gt;
# Nielsen validates the data received from the test and confirms the initial test successful and provides the production App ID.&lt;br /&gt;
## Goal is to test that all minimum requirements in step 3 are confirmed passed to Nielsen with no issues.&lt;br /&gt;
# Ensure contracts are in place for external test campaign with Nielsen Client Service team.&lt;br /&gt;
# Identify another live campaigns for production testing with production tag and app ID.&lt;br /&gt;
# Nielsen validates the data received from the final test and confirms certification for any DAR countries tested.&lt;br /&gt;
## Goal to test in full DAR E2E environment, receive matches from data provider for demographics and correct identification of mobile impressions.&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Mobile_DAR_Attributes_Requirements&amp;diff=1357</id>
		<title>Mobile DAR Attributes Requirements</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Mobile_DAR_Attributes_Requirements&amp;diff=1357"/>
		<updated>2017-08-29T19:15:37Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Currently, Nielsen’s DAR tags are well supported online via '''browser'''-based viewing on PCs, MACs, and tablets/smartphones. However, when ads are served to tablets/smartphones via native '''app-store applications''', additional attributes are needed in order for Nielsen clients to employ Nielsen’s mobile DAR (mDAR) measurement product.&lt;br /&gt;
&lt;br /&gt;
One way Nielsen clients can accomplish this is by the use of Nielsen’s native iOS/Android App SDK. Nielsen’s App SDK automatically adds these additional mobile attributes to mDAR measurement pings that are sent to Nielsen’s collection system. However, there is a significant portion of the mobile application universe where it is either not feasible, or desirable to integrate Nielsen’s native App SDK into 3rd party applications.&lt;br /&gt;
&lt;br /&gt;
This document describes additional attributes that must be added to DAR pings to create mDAR-compliant tags by way of a server-side macro replacement. This method is often referred to as Nielsen’s “non-SDK” DAR solution. Nielsen envisions that these attributes be added by ad networks when they respond to ad requests from client mobile devices.&lt;br /&gt;
&lt;br /&gt;
To support the insertion of the Advertising ID, it is assumed that you have published a specification that app publishers follow to pass the appropriate Advertising ID (for example, IDFA) in the Ad request URL. Typically, your Ad server will expand a macro that grabs that ID seen in the Ad request URL and pass it via the DAR pixel outlined below. See [[#Appendix A: Example Implementation]].&lt;br /&gt;
&lt;br /&gt;
Finally, once you have completed your integration, you will be required to submit to a short certification. See [[#Appendix B: Implementation, Testing &amp;amp; Certification]]. Certification also grants inclusion to the approved publisher and platform vendor list.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Additional DAR Tag Parameters for Mobile !! Description !! Mandatory?&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c7 || OS Grouping ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c8  || Device Grouping || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c9 || Advertising ID || &amp;lt;center&amp;gt;✔&amp;lt;/center&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c10 || Platform || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c12 || App Version ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c13 || AppID (Nielsen assigned App ID) || &amp;lt;center&amp;gt;✔&amp;lt;/center&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c14 || OS Version ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;uoo || Opt-out indicator || When applicable&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Clients are encouragesd to make an effort to always fill-in optional parameters.&lt;br /&gt;
&lt;br /&gt;
'''Note''': Do not URL encode the values.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C7 - OS Grouping (Optional) ==&lt;br /&gt;
Valid device OS Grouping data values are the following literal values:&lt;br /&gt;
* osgrp,IOS&lt;br /&gt;
* osgrp,DROID&lt;br /&gt;
* osgrp,ANDROID&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If one of the above values cannot be specific, then the parameter should not be included int he call.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C8 - Device Grouping ==&lt;br /&gt;
Valid literal values for phone, tablet, portable media player (iPod) and unknown are as follows:&lt;br /&gt;
* devgrp,PHN&lt;br /&gt;
* devgrp,TAB&lt;br /&gt;
* devgrp,PMP&lt;br /&gt;
* devgrp,UNWN&lt;br /&gt;
* devgrp,DSK&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If one of the above values cannot be specific, then the parameter should not be included in the call or should be left empty&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C9 - Advertising ID ==&lt;br /&gt;
This is the advertiser ID for the client’s mobile device. IDFA for iOS, Google Advertising ID for Android:&lt;br /&gt;
* devid,&amp;lt;IDFA&amp;gt;&lt;br /&gt;
* devid,&amp;lt;IFA&amp;gt;&lt;br /&gt;
* devid,&amp;lt;Google Advertising ID&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For Android devices, the Google Advertiser ID should be used as the default and the Android ID as the second option.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': If C9 is &amp;lt;empty&amp;gt;, upon receiving the ping, the Nielsen collection server will attempt a 302 redirect to the data provider per the regular DAR pixel for browsers.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As of August 1, 2014, Google is enforcing use of the Advertising ID for advertising and user analytics (http://play.google.com/about/developer-content-policy.html).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'' &amp;quot;Beginning August 1st 2014, all updates and new apps uploaded to the Play Store must use the advertising ID (when available on a device) in lieu of any other device identifiers for any advertising purposes.&amp;quot;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is preferred that the IDFA or Google Advertising ID be sent as is from the mobile device (“cleartext”). However, if mandated, we will support SHA256 hashed values with no-salt. Passing a hashed value (and/or salting) using any other standard will result in a failed match by the data provider upon receiving the ping. In turn, this results in impressions surfacing in the DAR unmeasurable audience totals. Please contact Nielsen if you anticipate a large percentage of hashed values coming in from your publisher clients.&lt;br /&gt;
&lt;br /&gt;
=== Privacy, Ad Tracking, and Ad Targeting ===&lt;br /&gt;
In newer iterations of the iOS and Android device operating systems, a facility exists allowing users to “opt-out” of “Ad Tracking”. It is Nielsen’s interpretation that this setting is primarily designed to allow users to specify opt-out of Ad Targeting rather than Ad Measurement. DAR&lt;br /&gt;
does not provide Ad Targeting data.&lt;br /&gt;
&lt;br /&gt;
However, it is also Nielsen’s position that the publisher or Ad network should provide a mechanism to also allow a user to opt-out of Ad Measurement. The Nielsen SDK will honor the Nielsen Ad Measurement opt-out settings configurable @ http://www.nielsen.com/us/en/campaigns/privacy-policy-opt-out.html.&lt;br /&gt;
&lt;br /&gt;
However if the integration approach described in this document is being used instead of the Nielsen SDK then '''YOU''' as the publisher or Ad network must provide a capability to opt-out of Ad Measurement as the configuration on www.nielsen.com will not be detectable. You may&lt;br /&gt;
elect to interpret the iOS / Android “Ad Tracking” setting for the purpose of limit Ad measurement or provide a separate discreet mechanism to allow a user to opt-out of Ad measurement.&lt;br /&gt;
&lt;br /&gt;
Please see '''&amp;amp;uoo''' later in this document for implementation details of the optout indicator.&lt;br /&gt;
&lt;br /&gt;
For additional clarification on privacy policy, please contact your Nielsen representative.&lt;br /&gt;
&lt;br /&gt;
== C10 - Platform ==&lt;br /&gt;
To determine this value, Nielsen suggests that the ad network leverage user agent information to determine if the client device is either a mobile or desktop device.&lt;br /&gt;
&lt;br /&gt;
Valid literal values for mobile and desktop data values are as follows:&lt;br /&gt;
* plt,MBL&lt;br /&gt;
* plt,DSK&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If one of the above values cannot be specific, then the parameter should not be included in the call or&lt;br /&gt;
should be left empty.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C12 - App Version (Optional) ==&lt;br /&gt;
This is the version of the ad network system software or SDK that is implemented in this extension. Although this field is not required, this feature can be useful for troubleshooting purposes following deployment.&lt;br /&gt;
* apv,&amp;lt;N.N&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C13 - AppID ==&lt;br /&gt;
This Nielsen provided ID is unique to the ad network and is required for certification.&lt;br /&gt;
* asid,&amp;lt;NNNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN&amp;gt;&lt;br /&gt;
An App ID will be provided for testing. A separate App ID will be provided for production use. Please request from your Nielsen representative.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If you are a publisher leveraging the non-SDK solution, you will be provided with a unique App ID for each combination of app and device OS type.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C14 - OS Version (Optional) ==&lt;br /&gt;
Operating system version&lt;br /&gt;
* osver,&amp;lt;OS Version&amp;gt;&lt;br /&gt;
Example: for iOS -&amp;gt; 7.0.4&lt;br /&gt;
&lt;br /&gt;
== UOO - Opt Out (Optional) ==&lt;br /&gt;
Opt-out parameter&lt;br /&gt;
* &amp;lt;Boolean state&amp;gt;&lt;br /&gt;
&amp;lt;Boolean state&amp;gt; is a Boolean representation of whether the user is opting out or not.&lt;br /&gt;
&lt;br /&gt;
The absence of uoo in the tag is interpreted as an implicit opt-in. i.e. not opting out.&lt;br /&gt;
&lt;br /&gt;
The following pairings of opt-out are supported. Important: you must choose one set of paired values only and inform your Nielsen representative.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Opt-out !! Opt-in&lt;br /&gt;
|-&lt;br /&gt;
| uoo=true || uoo=false&lt;br /&gt;
|-&lt;br /&gt;
| uoo=1 || uoo=0&lt;br /&gt;
|-&lt;br /&gt;
| uoo=yes || uoo=no&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''':  if your Ad server is not capable os supporting the discrete &amp;amp;uoo parameter then you can set the c9 value to &amp;lt;code&amp;gt;devid,optout&amp;lt;/code&amp;gt; (for example &amp;lt;code&amp;gt;…&amp;amp;c8=PHN&amp;amp;c9=devid,optout&amp;amp;c10=MBL…&amp;lt;/code&amp;gt;)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples of DAR and mDAR Tags ==&lt;br /&gt;
For each of the tag examples detailed below, we can support both unsecure (http) and secure (https) flavors.&lt;br /&gt;
&lt;br /&gt;
'''Important note''': the values in the following tags are for illustrative purposes only. Please contact your Nielsen representative for specific parameter values for your use of DAR.&lt;br /&gt;
&lt;br /&gt;
'''Test and Certification'''&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://secure-cert.imrworldwide.com&amp;lt;/nowiki&amp;gt;/cgi-bin/m?ci=nlsnci535&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st=image&amp;lt;wbr /&amp;gt;&amp;amp;ca=nlsn12452&amp;lt;wbr /&amp;gt;&amp;amp;cr=crtve&amp;lt;wbr /&amp;gt;&amp;amp;pc=%3cclientname%3e_plc0001&amp;lt;wbr /&amp;gt;&amp;amp;ce=%3cclientname%3e&amp;lt;wbr /&amp;gt;&amp;amp;c7=osgrp&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Production'''&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://secure-gl.imrworldwide.com&amp;lt;/nowiki&amp;gt;/cgibin/m?ci=nlsnci535&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st=image&amp;lt;wbr /&amp;gt;&amp;amp;ca=nlsn12452&amp;lt;wbr /&amp;gt;&amp;amp;cr=crtve&amp;lt;wbr /&amp;gt;&amp;amp;pc=&amp;lt;clientname&amp;gt;_plc0001&amp;lt;wbr /&amp;gt;&amp;amp;ce=&amp;lt;clientname&amp;gt;&amp;lt;wbr /&amp;gt;&amp;amp;c7=osgrp,IOS&amp;lt;wbr /&amp;gt;&amp;amp;c8=devgrp,TAB&amp;lt;wbr /&amp;gt;&amp;amp;c9=devid,XXXX-XX-XXXXX-XXXX&amp;lt;wbr /&amp;gt;&amp;amp;c10=plt,MBL &amp;lt;wbr /&amp;gt;&amp;amp;c12=apv,AppVersion&amp;lt;wbr /&amp;gt;&amp;amp;c13=asid,NIELSEN-PROVIDEDID&amp;lt;wbr /&amp;gt;&amp;amp;c14=osver,7.0.4&amp;lt;wbr /&amp;gt;&amp;amp;uoo=1&amp;lt;wbr /&amp;gt;&amp;amp;r=[timestamp]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Standard DAR tag (for information and completeness)'''&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://secure-gl.imrworldwide.com&amp;lt;/nowiki&amp;gt;/cgi-bin/m?ci=nlsnci535&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st=image&amp;lt;wbr /&amp;gt;&amp;amp;ca=nlsn12452&amp;lt;wbr /&amp;gt;&amp;amp;cr=crtve&amp;lt;wbr /&amp;gt;&amp;amp;pc=%3cclientname%3e_plc0001&amp;lt;wbr /&amp;gt;&amp;amp;ce=%3cclientname%3e&amp;lt;wbr /&amp;gt;&amp;amp;uoo=1&amp;lt;wbr /&amp;gt;&amp;amp;r=%5btimestamp&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Appendix A: Example Implementation ==&lt;br /&gt;
In the below examples, you will see the overall DAR flow (Figure 1) and a detailed illustrative Ad Request / Response model (Figure 2).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Figure 1 – End to End Data Flow'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:mDAR_Dataflow.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Nielsen certified publishers and platforms will append the new parameters (below) with the appropriate URL safe values passed to Nielsen’s current DAR tag. The current DAR tag should be acquired using the existing processes for each campaign/placement. &lt;br /&gt;
&amp;lt;code&amp;gt;'''&amp;amp;c7'''=osgrp,IOS'''&amp;amp;c8'''=devgrp,PHN'''&amp;amp;c9'''=devid,XXXX-XX-XXXXXXXXX'''&amp;amp;c10'''=plt,MBL'''&amp;amp;c12'''=apv,AppVersion'''&amp;amp;c13'''=asid,XXXX-XX-XXXX-XXXX&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Figure 2 – Illustrative Ad Request / Ad Response'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ad_response.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
The above is an example of how an Ad server is supporting the build of mobile DAR tags for its publisher clients. Step 2 in Figure 1 is a summary of steps 1 and 2 in Figure 2 above. Steps 3 and 4 in Figure 1 is a summary of steps 3 through 9 in Figure 2 above.&lt;br /&gt;
&lt;br /&gt;
== Appendix B: Implementation, Testing &amp;amp; Certification ==&lt;br /&gt;
Once you have integrated the ping per the above specs, Nielsen requires you to pass through a one-time certification before traffic can be accepted into the production environment.&lt;br /&gt;
&lt;br /&gt;
The overall process is:&lt;br /&gt;
# Valid DAR contract or NDA is in place.&lt;br /&gt;
# Kick-off meeting with Nielsen onboarding team.&lt;br /&gt;
# Confirm meet minimums testing requriements:&lt;br /&gt;
## Host Ad/Tag for in-app delivery&lt;br /&gt;
## Can pass opt-out back to Nielsen&lt;br /&gt;
## Can pass Device ID in cleartext or SHA-256&lt;br /&gt;
# Nielsen provides the mDAR testing form that includes the test App ID and the test tag&lt;br /&gt;
# Implement the specification and provide Nielsen the completed testing form.&lt;br /&gt;
# Identify the live campaigns for intial testing and run the test tag; suggest 5,000-10,000 impressions.&lt;br /&gt;
# Nielsen validates the data received from the test and confirms the initial test successful and provides the production App ID.&lt;br /&gt;
## Goal is to test that all minimum requirements in step 3 are confirmed passed to Nielsen with no issues.&lt;br /&gt;
# Ensure contracts are in place for external test campaign with Nielsen Client Service team.&lt;br /&gt;
# Identify another live campaigns for production testing with production tag and app ID.&lt;br /&gt;
# Nielsen validates the data received from the final test and confirms certification for any DAR countries tested.&lt;br /&gt;
## Goal to test in full DAR E2E environment, receive matches from data provider for demographics and correct identification of mobile impressions.&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Mobile_DAR_Attributes_Requirements&amp;diff=1356</id>
		<title>Mobile DAR Attributes Requirements</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Mobile_DAR_Attributes_Requirements&amp;diff=1356"/>
		<updated>2017-08-29T19:13:45Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Currently, Nielsen’s DAR tags are well supported online via '''browser'''-based viewing on PCs, MACs, and tablets/smartphones. However, when ads are served to tablets/smartphones via native '''app-store applications''', additional attributes are needed in order for Nielsen clients to employ Nielsen’s mobile DAR (mDAR) measurement product.&lt;br /&gt;
&lt;br /&gt;
One way Nielsen clients can accomplish this is by the use of Nielsen’s native iOS/Android App SDK. Nielsen’s App SDK automatically adds these additional mobile attributes to mDAR measurement pings that are sent to Nielsen’s collection system. However, there is a significant portion of the mobile application universe where it is either not feasible, or desirable to integrate Nielsen’s native App SDK into 3rd party applications.&lt;br /&gt;
&lt;br /&gt;
This document describes additional attributes that must be added to DAR pings to create mDAR-compliant tags by way of a server-side macro replacement. This method is often referred to as Nielsen’s “non-SDK” DAR solution. Nielsen envisions that these attributes be added by ad networks when they respond to ad requests from client mobile devices.&lt;br /&gt;
&lt;br /&gt;
To support the insertion of the Advertising ID, it is assumed that you have published a specification that app publishers follow to pass the appropriate Advertising ID (for example, IDFA) in the Ad request URL. Typically, your Ad server will expand a macro that grabs that ID seen in the Ad request URL and pass it via the DAR pixel outlined below. See [[#Appendix A: Example Implementation]].&lt;br /&gt;
&lt;br /&gt;
Finally, once you have completed your integration, you will be required to submit to a short certification. See [[#Appendix B: Implementation, Testing &amp;amp; Certification]]. Certification also grants inclusion to the approved publisher and platform vendor list.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Additional DAR Tag Parameters for Mobile !! Description !! Mandatory?&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c7 || OS Grouping ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c8  || Device Grouping || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c9 || Advertising ID || ✔&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c10 || Platform || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c12 || App Version ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c13 || AppID (Nielsen assigned App ID) || ✔&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;c14 || OS Version ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;uoo || Opt-out indicator || When applicable&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Clients are encouragesd to make an effort to always fill-in optional parameters.&lt;br /&gt;
&lt;br /&gt;
'''Note''': Do not URL encode the values.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C7 - OS Grouping (Optional) ==&lt;br /&gt;
Valid device OS Grouping data values are the following literal values:&lt;br /&gt;
* osgrp,IOS&lt;br /&gt;
* osgrp,DROID&lt;br /&gt;
* osgrp,ANDROID&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If one of the above values cannot be specific, then the parameter should not be included int he call.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C8 - Device Grouping ==&lt;br /&gt;
Valid literal values for phone, tablet, portable media player (iPod) and unknown are as follows:&lt;br /&gt;
* devgrp,PHN&lt;br /&gt;
* devgrp,TAB&lt;br /&gt;
* devgrp,PMP&lt;br /&gt;
* devgrp,UNWN&lt;br /&gt;
* devgrp,DSK&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If one of the above values cannot be specific, then the parameter should not be included in the call or should be left empty&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C9 - Advertising ID ==&lt;br /&gt;
This is the advertiser ID for the client’s mobile device. IDFA for iOS, Google Advertising ID for Android:&lt;br /&gt;
* devid,&amp;lt;IDFA&amp;gt;&lt;br /&gt;
* devid,&amp;lt;IFA&amp;gt;&lt;br /&gt;
* devid,&amp;lt;Google Advertising ID&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For Android devices, the Google Advertiser ID should be used as the default and the Android ID as the second option.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': If C9 is &amp;lt;empty&amp;gt;, upon receiving the ping, the Nielsen collection server will attempt a 302 redirect to the data provider per the regular DAR pixel for browsers.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As of August 1, 2014, Google is enforcing use of the Advertising ID for advertising and user analytics (http://play.google.com/about/developer-content-policy.html).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'' &amp;quot;Beginning August 1st 2014, all updates and new apps uploaded to the Play Store must use the advertising ID (when available on a device) in lieu of any other device identifiers for any advertising purposes.&amp;quot;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is preferred that the IDFA or Google Advertising ID be sent as is from the mobile device (“cleartext”). However, if mandated, we will support SHA256 hashed values with no-salt. Passing a hashed value (and/or salting) using any other standard will result in a failed match by the data provider upon receiving the ping. In turn, this results in impressions surfacing in the DAR unmeasurable audience totals. Please contact Nielsen if you anticipate a large percentage of hashed values coming in from your publisher clients.&lt;br /&gt;
&lt;br /&gt;
=== Privacy, Ad Tracking, and Ad Targeting ===&lt;br /&gt;
In newer iterations of the iOS and Android device operating systems, a facility exists allowing users to “opt-out” of “Ad Tracking”. It is Nielsen’s interpretation that this setting is primarily designed to allow users to specify opt-out of Ad Targeting rather than Ad Measurement. DAR&lt;br /&gt;
does not provide Ad Targeting data.&lt;br /&gt;
&lt;br /&gt;
However, it is also Nielsen’s position that the publisher or Ad network should provide a mechanism to also allow a user to opt-out of Ad Measurement. The Nielsen SDK will honor the Nielsen Ad Measurement opt-out settings configurable @ http://www.nielsen.com/us/en/campaigns/privacy-policy-opt-out.html.&lt;br /&gt;
&lt;br /&gt;
However if the integration approach described in this document is being used instead of the Nielsen SDK then '''YOU''' as the publisher or Ad network must provide a capability to opt-out of Ad Measurement as the configuration on www.nielsen.com will not be detectable. You may&lt;br /&gt;
elect to interpret the iOS / Android “Ad Tracking” setting for the purpose of limit Ad measurement or provide a separate discreet mechanism to allow a user to opt-out of Ad measurement.&lt;br /&gt;
&lt;br /&gt;
Please see '''&amp;amp;uoo''' later in this document for implementation details of the optout indicator.&lt;br /&gt;
&lt;br /&gt;
For additional clarification on privacy policy, please contact your Nielsen representative.&lt;br /&gt;
&lt;br /&gt;
== C10 - Platform ==&lt;br /&gt;
To determine this value, Nielsen suggests that the ad network leverage user agent information to determine if the client device is either a mobile or desktop device.&lt;br /&gt;
&lt;br /&gt;
Valid literal values for mobile and desktop data values are as follows:&lt;br /&gt;
* plt,MBL&lt;br /&gt;
* plt,DSK&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If one of the above values cannot be specific, then the parameter should not be included in the call or&lt;br /&gt;
should be left empty.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C12 - App Version (Optional) ==&lt;br /&gt;
This is the version of the ad network system software or SDK that is implemented in this extension. Although this field is not required, this feature can be useful for troubleshooting purposes following deployment.&lt;br /&gt;
* apv,&amp;lt;N.N&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C13 - AppID ==&lt;br /&gt;
This Nielsen provided ID is unique to the ad network and is required for certification.&lt;br /&gt;
* asid,&amp;lt;NNNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN&amp;gt;&lt;br /&gt;
An App ID will be provided for testing. A separate App ID will be provided for production use. Please request from your Nielsen representative.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If you are a publisher leveraging the non-SDK solution, you will be provided with a unique App ID for each combination of app and device OS type.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== C14 - OS Version (Optional) ==&lt;br /&gt;
Operating system version&lt;br /&gt;
* osver,&amp;lt;OS Version&amp;gt;&lt;br /&gt;
Example: for iOS -&amp;gt; 7.0.4&lt;br /&gt;
&lt;br /&gt;
== UOO - Opt Out (Optional) ==&lt;br /&gt;
Opt-out parameter&lt;br /&gt;
* &amp;lt;Boolean state&amp;gt;&lt;br /&gt;
&amp;lt;Boolean state&amp;gt; is a Boolean representation of whether the user is opting out or not.&lt;br /&gt;
&lt;br /&gt;
The absence of uoo in the tag is interpreted as an implicit opt-in. i.e. not opting out.&lt;br /&gt;
&lt;br /&gt;
The following pairings of opt-out are supported. Important: you must choose one set of paired values only and inform your Nielsen representative.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Opt-out !! Opt-in&lt;br /&gt;
|-&lt;br /&gt;
| uoo=true || uoo=false&lt;br /&gt;
|-&lt;br /&gt;
| uoo=1 || uoo=0&lt;br /&gt;
|-&lt;br /&gt;
| uoo=yes || uoo=no&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''':  if your Ad server is not capable os supporting the discrete &amp;amp;uoo parameter then you can set the c9 value to &amp;lt;code&amp;gt;devid,optout&amp;lt;/code&amp;gt; (for example &amp;lt;code&amp;gt;…&amp;amp;c8=PHN&amp;amp;c9=devid,optout&amp;amp;c10=MBL…&amp;lt;/code&amp;gt;)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples of DAR and mDAR Tags ==&lt;br /&gt;
For each of the tag examples detailed below, we can support both unsecure (http) and secure (https) flavors.&lt;br /&gt;
&lt;br /&gt;
'''Important note''': the values in the following tags are for illustrative purposes only. Please contact your Nielsen representative for specific parameter values for your use of DAR.&lt;br /&gt;
&lt;br /&gt;
'''Test and Certification'''&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://secure-cert.imrworldwide.com&amp;lt;/nowiki&amp;gt;/cgi-bin/m?ci=nlsnci535&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st=image&amp;lt;wbr /&amp;gt;&amp;amp;ca=nlsn12452&amp;lt;wbr /&amp;gt;&amp;amp;cr=crtve&amp;lt;wbr /&amp;gt;&amp;amp;pc=%3cclientname%3e_plc0001&amp;lt;wbr /&amp;gt;&amp;amp;ce=%3cclientname%3e&amp;lt;wbr /&amp;gt;&amp;amp;c7=osgrp&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Production'''&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://secure-gl.imrworldwide.com&amp;lt;/nowiki&amp;gt;/cgibin/m?ci=nlsnci535&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st=image&amp;lt;wbr /&amp;gt;&amp;amp;ca=nlsn12452&amp;lt;wbr /&amp;gt;&amp;amp;cr=crtve&amp;lt;wbr /&amp;gt;&amp;amp;pc=&amp;lt;clientname&amp;gt;_plc0001&amp;lt;wbr /&amp;gt;&amp;amp;ce=&amp;lt;clientname&amp;gt;&amp;lt;wbr /&amp;gt;&amp;amp;c7=osgrp,IOS&amp;lt;wbr /&amp;gt;&amp;amp;c8=devgrp,TAB&amp;lt;wbr /&amp;gt;&amp;amp;c9=devid,XXXX-XX-XXXXX-XXXX&amp;lt;wbr /&amp;gt;&amp;amp;c10=plt,MBL &amp;lt;wbr /&amp;gt;&amp;amp;c12=apv,AppVersion&amp;lt;wbr /&amp;gt;&amp;amp;c13=asid,NIELSEN-PROVIDEDID&amp;lt;wbr /&amp;gt;&amp;amp;c14=osver,7.0.4&amp;lt;wbr /&amp;gt;&amp;amp;uoo=1&amp;lt;wbr /&amp;gt;&amp;amp;r=[timestamp]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Standard DAR tag (for information and completeness)'''&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://secure-gl.imrworldwide.com&amp;lt;/nowiki&amp;gt;/cgi-bin/m?ci=nlsnci535&amp;lt;wbr /&amp;gt;&amp;amp;am=3&amp;lt;wbr /&amp;gt;&amp;amp;at=view&amp;lt;wbr /&amp;gt;&amp;amp;rt=banner&amp;lt;wbr /&amp;gt;&amp;amp;st=image&amp;lt;wbr /&amp;gt;&amp;amp;ca=nlsn12452&amp;lt;wbr /&amp;gt;&amp;amp;cr=crtve&amp;lt;wbr /&amp;gt;&amp;amp;pc=%3cclientname%3e_plc0001&amp;lt;wbr /&amp;gt;&amp;amp;ce=%3cclientname%3e&amp;lt;wbr /&amp;gt;&amp;amp;uoo=1&amp;lt;wbr /&amp;gt;&amp;amp;r=%5btimestamp&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Appendix A: Example Implementation ==&lt;br /&gt;
In the below examples, you will see the overall DAR flow (Figure 1) and a detailed illustrative Ad Request / Response model (Figure 2).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Figure 1 – End to End Data Flow'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:mDAR_Dataflow.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Nielsen certified publishers and platforms will append the new parameters (below) with the appropriate URL safe values passed to Nielsen’s current DAR tag. The current DAR tag should be acquired using the existing processes for each campaign/placement. &lt;br /&gt;
&amp;lt;code&amp;gt;'''&amp;amp;c7'''=osgrp,IOS'''&amp;amp;c8'''=devgrp,PHN'''&amp;amp;c9'''=devid,XXXX-XX-XXXXXXXXX'''&amp;amp;c10'''=plt,MBL'''&amp;amp;c12'''=apv,AppVersion'''&amp;amp;c13'''=asid,XXXX-XX-XXXX-XXXX&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Figure 2 – Illustrative Ad Request / Ad Response'''&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ad_response.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
The above is an example of how an Ad server is supporting the build of mobile DAR tags for its publisher clients. Step 2 in Figure 1 is a summary of steps 1 and 2 in Figure 2 above. Steps 3 and 4 in Figure 1 is a summary of steps 3 through 9 in Figure 2 above.&lt;br /&gt;
&lt;br /&gt;
== Appendix B: Implementation, Testing &amp;amp; Certification ==&lt;br /&gt;
Once you have integrated the ping per the above specs, Nielsen requires you to pass through a one-time certification before traffic can be accepted into the production environment.&lt;br /&gt;
&lt;br /&gt;
The overall process is:&lt;br /&gt;
# Valid DAR contract or NDA is in place.&lt;br /&gt;
# Kick-off meeting with Nielsen onboarding team.&lt;br /&gt;
# Confirm meet minimums testing requriements:&lt;br /&gt;
## Host Ad/Tag for in-app delivery&lt;br /&gt;
## Can pass opt-out back to Nielsen&lt;br /&gt;
## Can pass Device ID in cleartext or SHA-256&lt;br /&gt;
# Nielsen provides the mDAR testing form that includes the test App ID and the test tag&lt;br /&gt;
# Implement the specification and provide Nielsen the completed testing form.&lt;br /&gt;
# Identify the live campaigns for intial testing and run the test tag; suggest 5,000-10,000 impressions.&lt;br /&gt;
# Nielsen validates the data received from the test and confirms the initial test successful and provides the production App ID.&lt;br /&gt;
## Goal is to test that all minimum requirements in step 3 are confirmed passed to Nielsen with no issues.&lt;br /&gt;
# Ensure contracts are in place for external test campaign with Nielsen Client Service team.&lt;br /&gt;
# Identify another live campaigns for production testing with production tag and app ID.&lt;br /&gt;
# Nielsen validates the data received from the final test and confirms certification for any DAR countries tested.&lt;br /&gt;
## Goal to test in full DAR E2E environment, receive matches from data provider for demographics and correct identification of mobile impressions.&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1072</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1072"/>
		<updated>2017-07-12T21:16:31Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* AppApiErrorCode */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== AppApiErrorCode ==&lt;br /&gt;
iOS contains two types of error codes, 1-15 and 1001-1009.&lt;br /&gt;
&lt;br /&gt;
For, 1-15, an enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;typedef NS_ENUM(unsigned int, LogCode) {&lt;br /&gt;
    LogCodeFailedParseStartInfo, // 1.&lt;br /&gt;
    LogCodeFailedParseMetadata, // 2.&lt;br /&gt;
    LogCodeFailedProcessID3, // 3.&lt;br /&gt;
    LogCodeFailedReceiveConfig, // 4.&lt;br /&gt;
    LogCodeFailedParseConfig, // 5.&lt;br /&gt;
    LogCodeFailedStartProcessor, // 6.&lt;br /&gt;
    LogCodeFailedCreateUrl, // 7.&lt;br /&gt;
    LogCodeFailedCreateRequest, // 8.&lt;br /&gt;
    LogCodeFailedSendHttpRequest, // 9.&lt;br /&gt;
    LogCodeFailedSendPing, // 10.&lt;br /&gt;
    LogCodeFailedSendTSV, // 11.&lt;br /&gt;
    LogCodeFailedSendStationRequest, // 12.&lt;br /&gt;
    LogCodeFailedAccessDatabase, // 13.&lt;br /&gt;
    LogCodeException, // 14.&lt;br /&gt;
    LogCodeInvalidPlayheadPosition, // 15.&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For, 1001-1009, an enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error Code !! Error Name !! Error Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || LogCodeFailedParseStartInfo || Failed to parse the play() JSON string&lt;br /&gt;
|-&lt;br /&gt;
| 2 || LogCodeFailedParseMetadata || Failed to parse the loadMetadata() JSON string&lt;br /&gt;
|-&lt;br /&gt;
| 3 || LogCodeFailedProcessID3 || Failed to process ID3 data on a data processor&lt;br /&gt;
|-&lt;br /&gt;
| 4 || LogCodeFailedReceiveConfig || Failed to receive configuration file from Census&lt;br /&gt;
|-&lt;br /&gt;
| 5 || LogCodeFailedParseConfig || Failed to parse the config file JSON string&lt;br /&gt;
|-&lt;br /&gt;
| 6 || LogCodeFailedStartProcessor || Failed to create SDK processor&lt;br /&gt;
|-&lt;br /&gt;
| 7 || LogCodeFailedCreateUrl || Failed to generate URL due to missing mandatory parameter&lt;br /&gt;
|-&lt;br /&gt;
| 8 || LogCodeFailedCreateRequest || Failed to create request in HTTP client&lt;br /&gt;
|-&lt;br /&gt;
| 9 || LogCodeFailedSendHttpRequest || Failed sending HTTP or HTTPS request&lt;br /&gt;
|-&lt;br /&gt;
| 10 || LogCodeFailedSendPing || Failed to send ping&lt;br /&gt;
|-&lt;br /&gt;
| 11 || LogCodeFailedSendTSV || Failed to send TSV request&lt;br /&gt;
|-&lt;br /&gt;
| 12 || LogCodeFailedSendStationRequest || Failed to send StationId request&lt;br /&gt;
|-&lt;br /&gt;
| 13 || LogCodeFailedAccessDatabase || Failed to read/write from/to database table&lt;br /&gt;
|-&lt;br /&gt;
| 14 || LogCodeException || Any exception handled by SDK code&lt;br /&gt;
|-&lt;br /&gt;
| 15 || LogCodeInvalidPlayheadPosition || Invalid playhead position&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error Code !! Error Name !! Error Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1071</id>
		<title>Android SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1071"/>
		<updated>2017-07-12T20:54:43Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* App SDK Error Codes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*Create and initialize an instance object of &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class.&lt;br /&gt;
*The player application can use this object to collect HLS timed metadata through a [[sendID3()]] call.&lt;br /&gt;
The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package. It inherits from the closeable interface and exposes the public APIs the client’s app will use. Below is the declaration of the &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class: &amp;lt;code&amp;gt;public class AppSdk implements Closeable&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Up Development Environment ==&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Setting up in Eclipse IDE ===&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-properties-drm.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
&lt;br /&gt;
'''Library''':&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
'''Classes/package''':&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
 &lt;br /&gt;
=== Setting up in Android Studio IDE ===&lt;br /&gt;
Launch '''Android Studio''' and select '''Import project (Eclipse ADT)'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-setup-launch.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Browse for project destination directory and click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-import-project.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Go to '''File &amp;gt; Project Structure &amp;gt; App &amp;gt; Dependencies'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-pro-structure.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Click '''+''' to add library dependency.&lt;br /&gt;
&lt;br /&gt;
Select '''play-services''' and click '''OK'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-choose-library.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information, refer to https://developer.android.com/google/play-services/setup.html&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Android Application Life Cycle with respect to Nielsen App SDK ===&lt;br /&gt;
[[File:andr-init-img1.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 1: App SDK initialization ===&lt;br /&gt;
==== For API version 4.0.0 and above ====&lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject config = null;&lt;br /&gt;
 &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;uat-cert&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;INFO&amp;quot;) // only for debug builds&lt;br /&gt;
          .put(&amp;quot;custom_key1&amp;quot;, &amp;quot;custom_value1&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;custom_key2&amp;quot;, &amp;quot;custom_value2&amp;quot;);&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
==== Android Application Life Cycle with respect to Nielsen App SDK ====&lt;br /&gt;
[[File:andr-radioandvideo-app.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 2: App SDK libraries inclusion in project ===&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&lt;br /&gt;
*Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Nielsen App SDK Streaming Sessions ===&lt;br /&gt;
After ensuring that the SDK object has been initialized, link the streaming session APIs. The next steps are:&lt;br /&gt;
*Call [[play()]] when starting or resuming a streaming session. Use the channelName parameter to pass channel descriptor information. The channel name field is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.) which must be inserted on a JSON string.&lt;br /&gt;
*Load the CMS metadata by calling the [[loadMetadata()]] on the SDK object.&lt;br /&gt;
*Call [[stop()]] when ending or pausing a viewing session.&lt;br /&gt;
*During session playback, call the SDK [[setPlayheadPosition()]] and / or [[sendID3()]]&lt;br /&gt;
**Call [[setPlayheadPosition()]] every one second until the stream is stopped or paused. Normally this happens on Digital Audio measurements.&lt;br /&gt;
**Call [[sendID3()]] if the client relies on the Nielsen ID3 tags for its measurements; this call should happen whenever a new Nielsen ID3 metadata is available for processing. Normally this happens on DTVR and ID3 measurements.&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
*The client’s app must clearly identify the mode of operation (live vs. VOD) and stick to the type of playhead coordinates until the playback is completed. The client must reliably provide the appropriated playhead position value depending on the type of content streamed.&lt;br /&gt;
*If streaming live video content, the client must pass the current UTC time in seconds as playhead position.&lt;br /&gt;
*If streaming VOD (video on demand), the client must stream the offset from the beginning of the file as playhead position.&lt;br /&gt;
*For all Digital Audio listening, the client must pass the current UTC time in seconds as playhead position, regardless of station type.&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extracting ID3 tags from Android Players ===&lt;br /&gt;
==== ID3 Support Matrix ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Player Name !! Minimum supported version !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Android Native Media Player || Android 6 || Android 6 Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags, generates TimedMetaData.&lt;br /&gt;
|-&lt;br /&gt;
| Google ExoPlayer || Android 4.1 ||&lt;br /&gt;
|-&lt;br /&gt;
| Brightcove Player || Android 4.1 || Support for Android versions 2.3.3 and 4.0 is now deprecated. Learn more about why Brightcove is removing support for these versions as of January 1, 2016 in this [https://support.brightcove.com/en/perform/docs/announcement-brightcove-sdk-android-version-support|announcement]&lt;br /&gt;
|-&lt;br /&gt;
| Adobe PrimeTime Player || Android 4.2 ||&lt;br /&gt;
|-&lt;br /&gt;
| VisualOn Player || Android 2.3 || Android 5 is the latest supported version&lt;br /&gt;
|-&lt;br /&gt;
| NexStream Player || Android 1.6 || Supported till Android 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Android Native Media Player ====&lt;br /&gt;
As the Android Media Player versions (prior to Android 6 / Android API 23) do not support ID3, Nielsen has created a library that becomes an extension to the media player, thus MPX. This library extracts the ID3 tags and sends them to the app. For more information on how to use the MPX component, refer to the Nielsen-supplied sample application.&lt;br /&gt;
&lt;br /&gt;
Starting from '''Android 6 (Android API 23)''', Android Native Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags generate TimedMetadata. Once the HLS video starts, call onTimedMetaDataAvailable() as and when the player observes a TimedMetadata (ID3 tag).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;@Override&lt;br /&gt;
   public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data)&lt;br /&gt;
     {&lt;br /&gt;
       byte[] iD3PayloadArray = data.getMetaData();&lt;br /&gt;
       String iD3Payload = new String(iD3PayloadArray, StandardCharsets.UTF_8);&lt;br /&gt;
       if (null != iD3Payload &amp;amp;&amp;amp; iD3Payload.contains(&amp;quot;www.nielsen.com&amp;quot;))&lt;br /&gt;
         {&lt;br /&gt;
           int index = iD3Payload.indexOf(&amp;quot;www.nielsen.com&amp;quot;);&lt;br /&gt;
           String id3String = iD3Payload.substring(index, (index + 249));&lt;br /&gt;
           Log.d(TAG, &amp;quot;TimedMetaData ID3 Tag:&amp;quot; + id3String);&lt;br /&gt;
           appProcessID3tag(id3String);&lt;br /&gt;
         }&lt;br /&gt;
     }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ExoPlayer ====&lt;br /&gt;
he SDK is designed around an event-driven architecture where components emit events to allow other components to listen and respond to state changes.&lt;br /&gt;
&lt;br /&gt;
'''Player SDK Classes used:'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;com.google.android.exoplayer.demo.player.DemoPlayer&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since Nielsen App SDK is interested in extracting the Timed Metadata (ID3 Tags) in HLS and VOD on the EXO Player, trace the ID3_TAG emitted during video content played using EXOPlayer component as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;DemoPlayer implements ExoPlayer.Listener&lt;br /&gt;
—————————————————–&lt;br /&gt;
/**&lt;br /&gt;
* A listener for receiving ID3 metadata parsed from the media stream.&lt;br /&gt;
*/&lt;br /&gt;
public interface Id3MetadataListener&lt;br /&gt;
{&lt;br /&gt;
  void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata);&lt;br /&gt;
}&lt;br /&gt;
——————————————————-&lt;br /&gt;
MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String,&lt;br /&gt;
Object&amp;gt;&amp;gt; getId3MetadataRenderer()&lt;br /&gt;
  {&lt;br /&gt;
    return new MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;()&lt;br /&gt;
      {&lt;br /&gt;
        @Override&lt;br /&gt;
        public void onMetadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
          {&lt;br /&gt;
            if (id3MetadataListener != null)&lt;br /&gt;
              {&lt;br /&gt;
                id3MetadataListener.onId3Metadata(metadata);&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      };&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also in ''Player.java'' class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;Player implements DemoPlayer.Id3MetadataListener&lt;br /&gt;
—————————————————–&lt;br /&gt;
@SuppressWarnings(&amp;quot;rawtypes&amp;quot;)&lt;br /&gt;
@Override&lt;br /&gt;
public void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
{&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
      for (Object o : metadata.entrySet())&lt;br /&gt;
        {&lt;br /&gt;
          Map.Entry pairs = (Map.Entry) o;&lt;br /&gt;
          if (metadata.containsKey(TxxxMetadata.TYPE))&lt;br /&gt;
            {&lt;br /&gt;
              TxxxMetadata txxxMetadata = (TxxxMetadata) metadata&lt;br /&gt;
              .get(TxxxMetadata.TYPE);&lt;br /&gt;
            }&lt;br /&gt;
          else&lt;br /&gt;
            {&lt;br /&gt;
              String aStr = new String((byte[]) pairs.getValue());&lt;br /&gt;
              MainActivity.mAppSdk.sendID3(aStr);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  catch (Exception e)&lt;br /&gt;
    {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      Log.d(TAG, &amp;quot;onId3Metadata(): No Id3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-exo-retrievingID3tags.png|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Brightcove Player ====&lt;br /&gt;
While the Brightcove player plays the content, EventListener triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;SeamlessVideoDisplayComponent.ID3_TAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;brightcoveVideoView.getEventEmitter().on(SeamlessVideoDisplayComponent.ID3_TAG, new EventListener()&lt;br /&gt;
  {&lt;br /&gt;
    public void processEvent(Event event)&lt;br /&gt;
      {&lt;br /&gt;
        NlsId3Tag nlsID3 = new NlsId3Tag(event.properties.get(SeamlessVideoDisplayComponent.ID3_DATA).toString());&lt;br /&gt;
        Log.w(&amp;quot;ID3&amp;quot;, nlsID3.NlsPayload);&lt;br /&gt;
        // Sent ID3 Tags to App&lt;br /&gt;
        appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      }&lt;br /&gt;
      });&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Adobe PrimeTime Player ====&lt;br /&gt;
While the Adobe PrimeTime player plays the content, MediaPlayer.PlaybackEventListener triggers a callback when an ID3 packet is received (onTimedMetadata). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetadata(TimedMetadata id3Metadata)&lt;br /&gt;
{&lt;br /&gt;
  NlsId3Tag nlsID3 = new NlsId3Tag(id3Metadata.getMetadata().toString());&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;ID3 Timed Data –&amp;gt; &amp;quot; + nlsID3.NlsPayload);&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;PayLoad Size –&amp;gt; &amp;quot; + nlsID3.NlsPayload.length());&lt;br /&gt;
  appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== VisualOn Player ====&lt;br /&gt;
While the VisualOn player plays the content, &amp;lt;code&amp;gt;VOCommonPlayerListener&amp;lt;/code&amp;gt; triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;case VO_OSMP_SRC_CB_CUSTOMER_TAG:&lt;br /&gt;
{&lt;br /&gt;
  VO_OSMP_SRC_CUSTOMERTAGID tag = VO_OSMP_SRC_CUSTOMERTAGID.valueOf(nParam1);&lt;br /&gt;
  switch (tag)&lt;br /&gt;
    {&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG:&lt;br /&gt;
      // do something with this tag&lt;br /&gt;
      int time = nParam2;&lt;br /&gt;
      byte[] b = (byte[]) obj;&lt;br /&gt;
      String s = new String(b);&lt;br /&gt;
      NlsId3Tag nlsID3 = new NlsId3Tag(b);&lt;br /&gt;
      // Sent ID3 Tags to App&lt;br /&gt;
      appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      if (appid3If != null)&lt;br /&gt;
      appid3If.onId3(nlsID3.NlsPayload);&lt;br /&gt;
      break;&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_MAX:&lt;br /&gt;
      // ignore this type of tag&lt;br /&gt;
      break;&lt;br /&gt;
      default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
      break;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== NextStream Player ====&lt;br /&gt;
ID3 tags will be received in the NexStream Player through &amp;lt;code&amp;gt;onTimedMetaRenderRender(NexPlayer mp,NexID3TagInformation metadata)&amp;lt;/code&amp;gt; callback API. A sample implementation for the callback is shown below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetaRenderRender(NexPlayer mp, NexID3TagInformation m)&lt;br /&gt;
  {&lt;br /&gt;
    text = m.getPrivateFrame();&lt;br /&gt;
    if (text != null)&lt;br /&gt;
      {&lt;br /&gt;
        data = text.getTextData();&lt;br /&gt;
        if (data != null)&lt;br /&gt;
          {&lt;br /&gt;
            // make sure to identify the beginning  of  the&lt;br /&gt;
            // Nielsen ID3 tag payload by searching for the&lt;br /&gt;
            // &amp;quot;www.nielsen.com&amp;quot; string on the ID3 tag and&lt;br /&gt;
            // passing to the App SDK all information that&lt;br /&gt;
            // follows. It should be:&lt;br /&gt;
            // nlsPayload = &amp;quot;www.nielsen.com&amp;quot; + dataFollowing&lt;br /&gt;
            nlsPayload = getDataAfterWwwNielsenCom(data);&lt;br /&gt;
            if (nlsPayload!= NULL)&lt;br /&gt;
            mAppSdk.sendID3(nlsPayload);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[sendID3()]] sends the extracted Nielsen ID3 payload to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
== Android SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[AppSDK()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadmetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3()]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[setPlayheadPosition()]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOutURLString()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getOptOutStatus()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi()]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getAppDisable()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query if the SDK is disabled or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastEvent()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last status&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastError()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last error&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[isValid()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to check if the SDK was successfully instantiated or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getMeterVersion()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getNielsenId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getDeviceId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current device id.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInBackground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app going to background.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInForeground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app coming to foreground&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[setDebug()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-andr.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''5.1.1.18 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14, skip ahead to: [[#Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14|Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18, Opt-Out related behavior has been changed in the following ways:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Version 5.1.1.18 or above, refer to documentation above ([[#Opt-out Android SDK Version 5.1.1.18 or above|Opt-out Android SDK Version 5.1.1.18 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**Capture user’s selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Opt Out of Ads for Personalization for the latest versions of the SDK (5.1.1.18 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Opt Out of Ads for Personalization&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in Google Play Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample Google Play Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2000 || EVENT_INITIATE || App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || EVENT_STARTUP || App SDK has started up. It will happen only after App SDK has received a valid config file. This is the location in the code to acquire the value of [[userOptOutURLString()]].&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || EVENT_SHUTDOWN || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
Constants with predefined error codes which the AppSdk object can generate.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error Code !! Error Name !! Description !! Behavior&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || ERROR_FAILED_CREATE_URL_STRING || Failed generating ping string due to error on parsing || Include last error message from URL parser&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || ERROR_FAILED_RECEIVE_CONFIG || Failed to receive configuration file from Census || On 5th time, it will log event and keep requesting config 10 min apart&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || ERROR_FAILED_PARSING_CONFIG || Failed parsing the config file JSON string || Include json error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || ERROR_FAILED_PARSING_PLAY || Failed parsing the play() JSON string || Include JSON error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || ERROR_FAILED_PARSING_METADATA || Failed parsing the play() JSON string || Include JSON error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || ERROR_FAILED_GENERATING_PING || Failed creating ping before adding it to the UPLOAD table) || Include ping nol_url index, cadence to identify ping&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || ERROR_FAILED_PROCESSOR_START || Failed starting data processor thread. Normally, that means a product || Include processor that failed to start&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || ERROR_FAILED_PROCESS_ID3 || Failed processing data on a data processor. Normally, that means the input to a product || Include processor and data that failed to process (ID3 tag on a MTVR impression, for example)&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || ERROR_FAILED_HTTP_SEND || Failed sending HTTP or HTTPS requests || Include HTTP error number&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || ERROR_FAILED_SENDING_PING || Failed sending pings (on ANDROID, the ping on the UPLOAD table) || Include ping up to 80 char from the end&lt;br /&gt;
|-&lt;br /&gt;
| 1011 || ERROR_FAILED_SENDING_TSV || Failed sending TSV requests || Include TSV request message&lt;br /&gt;
|-&lt;br /&gt;
| 1012 || ERROR_FAILED_SENDING_STATION_ID || Failed sending Station ID requests || Include Station ID request message&lt;br /&gt;
|-&lt;br /&gt;
| 1013 || ERROR_FAILED_ACCESSING_DB || Failed read/write from/to database table || Include SQL statement and data and SQLite error number/message&lt;br /&gt;
|-&lt;br /&gt;
| 1014 || ERROR_CHANGED_DEVICE_ID || Device ID changed ||&lt;br /&gt;
|-&lt;br /&gt;
| 1015 || ERROR_CHANGED_NUID || NUID changed ||&lt;br /&gt;
|-&lt;br /&gt;
| 1016 || ERROR_SDK_NOT_INITIALIZED || App SDK initialization failed ||&lt;br /&gt;
|-&lt;br /&gt;
| 1017 || ERROR_FAILED_SDK_SUSPEND || App SDK failed to suspend activities ||&lt;br /&gt;
|-&lt;br /&gt;
| 1018 || ERROR_INVALID_PARAMETERS || App SDK invalid parameters ||&lt;br /&gt;
|-&lt;br /&gt;
| 1019 || ERROR_INVALID_STATE || App SDK called in incorrect state ||&lt;br /&gt;
|-&lt;br /&gt;
| 1020 || ERROR_FAILED_PROCESS_PLAYHEAD || App SDK failed processing playhead position ||&lt;br /&gt;
|-&lt;br /&gt;
| 1021 || ERROR_FAILED_PROCESS_METADATA || App SDK failed processing not-null, syntax valid JSON metadada ||&lt;br /&gt;
|-&lt;br /&gt;
| 1022 || ERROR_FAILED_PROCESS_STOP || App SDK failed processing stop ||&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1070</id>
		<title>Android SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1070"/>
		<updated>2017-07-12T20:06:23Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* App SDK Event Codes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*Create and initialize an instance object of &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class.&lt;br /&gt;
*The player application can use this object to collect HLS timed metadata through a [[sendID3()]] call.&lt;br /&gt;
The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package. It inherits from the closeable interface and exposes the public APIs the client’s app will use. Below is the declaration of the &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class: &amp;lt;code&amp;gt;public class AppSdk implements Closeable&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Up Development Environment ==&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Setting up in Eclipse IDE ===&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-properties-drm.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
&lt;br /&gt;
'''Library''':&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
'''Classes/package''':&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
 &lt;br /&gt;
=== Setting up in Android Studio IDE ===&lt;br /&gt;
Launch '''Android Studio''' and select '''Import project (Eclipse ADT)'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-setup-launch.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Browse for project destination directory and click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-import-project.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Go to '''File &amp;gt; Project Structure &amp;gt; App &amp;gt; Dependencies'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-pro-structure.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Click '''+''' to add library dependency.&lt;br /&gt;
&lt;br /&gt;
Select '''play-services''' and click '''OK'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-choose-library.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information, refer to https://developer.android.com/google/play-services/setup.html&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Android Application Life Cycle with respect to Nielsen App SDK ===&lt;br /&gt;
[[File:andr-init-img1.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 1: App SDK initialization ===&lt;br /&gt;
==== For API version 4.0.0 and above ====&lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject config = null;&lt;br /&gt;
 &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;uat-cert&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;INFO&amp;quot;) // only for debug builds&lt;br /&gt;
          .put(&amp;quot;custom_key1&amp;quot;, &amp;quot;custom_value1&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;custom_key2&amp;quot;, &amp;quot;custom_value2&amp;quot;);&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
==== Android Application Life Cycle with respect to Nielsen App SDK ====&lt;br /&gt;
[[File:andr-radioandvideo-app.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 2: App SDK libraries inclusion in project ===&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&lt;br /&gt;
*Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Nielsen App SDK Streaming Sessions ===&lt;br /&gt;
After ensuring that the SDK object has been initialized, link the streaming session APIs. The next steps are:&lt;br /&gt;
*Call [[play()]] when starting or resuming a streaming session. Use the channelName parameter to pass channel descriptor information. The channel name field is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.) which must be inserted on a JSON string.&lt;br /&gt;
*Load the CMS metadata by calling the [[loadMetadata()]] on the SDK object.&lt;br /&gt;
*Call [[stop()]] when ending or pausing a viewing session.&lt;br /&gt;
*During session playback, call the SDK [[setPlayheadPosition()]] and / or [[sendID3()]]&lt;br /&gt;
**Call [[setPlayheadPosition()]] every one second until the stream is stopped or paused. Normally this happens on Digital Audio measurements.&lt;br /&gt;
**Call [[sendID3()]] if the client relies on the Nielsen ID3 tags for its measurements; this call should happen whenever a new Nielsen ID3 metadata is available for processing. Normally this happens on DTVR and ID3 measurements.&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
*The client’s app must clearly identify the mode of operation (live vs. VOD) and stick to the type of playhead coordinates until the playback is completed. The client must reliably provide the appropriated playhead position value depending on the type of content streamed.&lt;br /&gt;
*If streaming live video content, the client must pass the current UTC time in seconds as playhead position.&lt;br /&gt;
*If streaming VOD (video on demand), the client must stream the offset from the beginning of the file as playhead position.&lt;br /&gt;
*For all Digital Audio listening, the client must pass the current UTC time in seconds as playhead position, regardless of station type.&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extracting ID3 tags from Android Players ===&lt;br /&gt;
==== ID3 Support Matrix ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Player Name !! Minimum supported version !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Android Native Media Player || Android 6 || Android 6 Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags, generates TimedMetaData.&lt;br /&gt;
|-&lt;br /&gt;
| Google ExoPlayer || Android 4.1 ||&lt;br /&gt;
|-&lt;br /&gt;
| Brightcove Player || Android 4.1 || Support for Android versions 2.3.3 and 4.0 is now deprecated. Learn more about why Brightcove is removing support for these versions as of January 1, 2016 in this [https://support.brightcove.com/en/perform/docs/announcement-brightcove-sdk-android-version-support|announcement]&lt;br /&gt;
|-&lt;br /&gt;
| Adobe PrimeTime Player || Android 4.2 ||&lt;br /&gt;
|-&lt;br /&gt;
| VisualOn Player || Android 2.3 || Android 5 is the latest supported version&lt;br /&gt;
|-&lt;br /&gt;
| NexStream Player || Android 1.6 || Supported till Android 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Android Native Media Player ====&lt;br /&gt;
As the Android Media Player versions (prior to Android 6 / Android API 23) do not support ID3, Nielsen has created a library that becomes an extension to the media player, thus MPX. This library extracts the ID3 tags and sends them to the app. For more information on how to use the MPX component, refer to the Nielsen-supplied sample application.&lt;br /&gt;
&lt;br /&gt;
Starting from '''Android 6 (Android API 23)''', Android Native Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags generate TimedMetadata. Once the HLS video starts, call onTimedMetaDataAvailable() as and when the player observes a TimedMetadata (ID3 tag).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;@Override&lt;br /&gt;
   public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data)&lt;br /&gt;
     {&lt;br /&gt;
       byte[] iD3PayloadArray = data.getMetaData();&lt;br /&gt;
       String iD3Payload = new String(iD3PayloadArray, StandardCharsets.UTF_8);&lt;br /&gt;
       if (null != iD3Payload &amp;amp;&amp;amp; iD3Payload.contains(&amp;quot;www.nielsen.com&amp;quot;))&lt;br /&gt;
         {&lt;br /&gt;
           int index = iD3Payload.indexOf(&amp;quot;www.nielsen.com&amp;quot;);&lt;br /&gt;
           String id3String = iD3Payload.substring(index, (index + 249));&lt;br /&gt;
           Log.d(TAG, &amp;quot;TimedMetaData ID3 Tag:&amp;quot; + id3String);&lt;br /&gt;
           appProcessID3tag(id3String);&lt;br /&gt;
         }&lt;br /&gt;
     }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ExoPlayer ====&lt;br /&gt;
he SDK is designed around an event-driven architecture where components emit events to allow other components to listen and respond to state changes.&lt;br /&gt;
&lt;br /&gt;
'''Player SDK Classes used:'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;com.google.android.exoplayer.demo.player.DemoPlayer&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since Nielsen App SDK is interested in extracting the Timed Metadata (ID3 Tags) in HLS and VOD on the EXO Player, trace the ID3_TAG emitted during video content played using EXOPlayer component as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;DemoPlayer implements ExoPlayer.Listener&lt;br /&gt;
—————————————————–&lt;br /&gt;
/**&lt;br /&gt;
* A listener for receiving ID3 metadata parsed from the media stream.&lt;br /&gt;
*/&lt;br /&gt;
public interface Id3MetadataListener&lt;br /&gt;
{&lt;br /&gt;
  void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata);&lt;br /&gt;
}&lt;br /&gt;
——————————————————-&lt;br /&gt;
MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String,&lt;br /&gt;
Object&amp;gt;&amp;gt; getId3MetadataRenderer()&lt;br /&gt;
  {&lt;br /&gt;
    return new MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;()&lt;br /&gt;
      {&lt;br /&gt;
        @Override&lt;br /&gt;
        public void onMetadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
          {&lt;br /&gt;
            if (id3MetadataListener != null)&lt;br /&gt;
              {&lt;br /&gt;
                id3MetadataListener.onId3Metadata(metadata);&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      };&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also in ''Player.java'' class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;Player implements DemoPlayer.Id3MetadataListener&lt;br /&gt;
—————————————————–&lt;br /&gt;
@SuppressWarnings(&amp;quot;rawtypes&amp;quot;)&lt;br /&gt;
@Override&lt;br /&gt;
public void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
{&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
      for (Object o : metadata.entrySet())&lt;br /&gt;
        {&lt;br /&gt;
          Map.Entry pairs = (Map.Entry) o;&lt;br /&gt;
          if (metadata.containsKey(TxxxMetadata.TYPE))&lt;br /&gt;
            {&lt;br /&gt;
              TxxxMetadata txxxMetadata = (TxxxMetadata) metadata&lt;br /&gt;
              .get(TxxxMetadata.TYPE);&lt;br /&gt;
            }&lt;br /&gt;
          else&lt;br /&gt;
            {&lt;br /&gt;
              String aStr = new String((byte[]) pairs.getValue());&lt;br /&gt;
              MainActivity.mAppSdk.sendID3(aStr);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  catch (Exception e)&lt;br /&gt;
    {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      Log.d(TAG, &amp;quot;onId3Metadata(): No Id3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-exo-retrievingID3tags.png|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Brightcove Player ====&lt;br /&gt;
While the Brightcove player plays the content, EventListener triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;SeamlessVideoDisplayComponent.ID3_TAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;brightcoveVideoView.getEventEmitter().on(SeamlessVideoDisplayComponent.ID3_TAG, new EventListener()&lt;br /&gt;
  {&lt;br /&gt;
    public void processEvent(Event event)&lt;br /&gt;
      {&lt;br /&gt;
        NlsId3Tag nlsID3 = new NlsId3Tag(event.properties.get(SeamlessVideoDisplayComponent.ID3_DATA).toString());&lt;br /&gt;
        Log.w(&amp;quot;ID3&amp;quot;, nlsID3.NlsPayload);&lt;br /&gt;
        // Sent ID3 Tags to App&lt;br /&gt;
        appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      }&lt;br /&gt;
      });&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Adobe PrimeTime Player ====&lt;br /&gt;
While the Adobe PrimeTime player plays the content, MediaPlayer.PlaybackEventListener triggers a callback when an ID3 packet is received (onTimedMetadata). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetadata(TimedMetadata id3Metadata)&lt;br /&gt;
{&lt;br /&gt;
  NlsId3Tag nlsID3 = new NlsId3Tag(id3Metadata.getMetadata().toString());&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;ID3 Timed Data –&amp;gt; &amp;quot; + nlsID3.NlsPayload);&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;PayLoad Size –&amp;gt; &amp;quot; + nlsID3.NlsPayload.length());&lt;br /&gt;
  appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== VisualOn Player ====&lt;br /&gt;
While the VisualOn player plays the content, &amp;lt;code&amp;gt;VOCommonPlayerListener&amp;lt;/code&amp;gt; triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;case VO_OSMP_SRC_CB_CUSTOMER_TAG:&lt;br /&gt;
{&lt;br /&gt;
  VO_OSMP_SRC_CUSTOMERTAGID tag = VO_OSMP_SRC_CUSTOMERTAGID.valueOf(nParam1);&lt;br /&gt;
  switch (tag)&lt;br /&gt;
    {&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG:&lt;br /&gt;
      // do something with this tag&lt;br /&gt;
      int time = nParam2;&lt;br /&gt;
      byte[] b = (byte[]) obj;&lt;br /&gt;
      String s = new String(b);&lt;br /&gt;
      NlsId3Tag nlsID3 = new NlsId3Tag(b);&lt;br /&gt;
      // Sent ID3 Tags to App&lt;br /&gt;
      appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      if (appid3If != null)&lt;br /&gt;
      appid3If.onId3(nlsID3.NlsPayload);&lt;br /&gt;
      break;&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_MAX:&lt;br /&gt;
      // ignore this type of tag&lt;br /&gt;
      break;&lt;br /&gt;
      default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
      break;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== NextStream Player ====&lt;br /&gt;
ID3 tags will be received in the NexStream Player through &amp;lt;code&amp;gt;onTimedMetaRenderRender(NexPlayer mp,NexID3TagInformation metadata)&amp;lt;/code&amp;gt; callback API. A sample implementation for the callback is shown below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetaRenderRender(NexPlayer mp, NexID3TagInformation m)&lt;br /&gt;
  {&lt;br /&gt;
    text = m.getPrivateFrame();&lt;br /&gt;
    if (text != null)&lt;br /&gt;
      {&lt;br /&gt;
        data = text.getTextData();&lt;br /&gt;
        if (data != null)&lt;br /&gt;
          {&lt;br /&gt;
            // make sure to identify the beginning  of  the&lt;br /&gt;
            // Nielsen ID3 tag payload by searching for the&lt;br /&gt;
            // &amp;quot;www.nielsen.com&amp;quot; string on the ID3 tag and&lt;br /&gt;
            // passing to the App SDK all information that&lt;br /&gt;
            // follows. It should be:&lt;br /&gt;
            // nlsPayload = &amp;quot;www.nielsen.com&amp;quot; + dataFollowing&lt;br /&gt;
            nlsPayload = getDataAfterWwwNielsenCom(data);&lt;br /&gt;
            if (nlsPayload!= NULL)&lt;br /&gt;
            mAppSdk.sendID3(nlsPayload);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[sendID3()]] sends the extracted Nielsen ID3 payload to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
== Android SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[AppSDK()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadmetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3()]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[setPlayheadPosition()]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOutURLString()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getOptOutStatus()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi()]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getAppDisable()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query if the SDK is disabled or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastEvent()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last status&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastError()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last error&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[isValid()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to check if the SDK was successfully instantiated or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getMeterVersion()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getNielsenId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getDeviceId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current device id.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInBackground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app going to background.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInForeground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app coming to foreground&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[setDebug()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-andr.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''5.1.1.18 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14, skip ahead to: [[#Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14|Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18, Opt-Out related behavior has been changed in the following ways:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Version 5.1.1.18 or above, refer to documentation above ([[#Opt-out Android SDK Version 5.1.1.18 or above|Opt-out Android SDK Version 5.1.1.18 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**Capture user’s selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Opt Out of Ads for Personalization for the latest versions of the SDK (5.1.1.18 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Opt Out of Ads for Personalization&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in Google Play Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample Google Play Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2000 || EVENT_INITIATE || App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || EVENT_STARTUP || App SDK has started up. It will happen only after App SDK has received a valid config file. This is the location in the code to acquire the value of [[userOptOutURLString()]].&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || EVENT_SHUTDOWN || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
Constants with predefined error codes which the AppSdk object can generate.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Description !! Behavior&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || ERROR_FAILED_CREATE_URL_STRING || Failed generating ping string due to error on parsing || Include last error message from URL parser&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || ERROR_FAILED_RECEIVE_CONFIG || Failed to receive configuration file from Census || On 5th time, it will log event and keep requesting config 10 min apart&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || ERROR_FAILED_PARSING_CONFIG || Failed parsing the config file JSON string || Include json error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || ERROR_FAILED_PARSING_PLAY || Failed parsing the play() JSON string || Include JSON error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || ERROR_FAILED_PARSING_METADATA || Failed parsing the play() JSON string || Include JSON error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || ERROR_FAILED_GENERATING_PING || Failed creating ping before adding it to the UPLOAD table) || Include ping nol_url index, cadence to identify ping&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || ERROR_FAILED_PROCESSOR_START || Failed starting data processor thread. Normally, that means a product || Include processor that failed to start&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || ERROR_FAILED_PROCESS_ID3 || Failed processing data on a data processor. Normally, that means the input to a product || Include processor and data that failed to process (ID3 tag on a MTVR impression, for example)&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || ERROR_FAILED_HTTP_SEND || Failed sending HTTP or HTTPS requests || Include HTTP error number&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || ERROR_FAILED_SENDING_PING || Failed sending pings (on ANDROID, the ping on the UPLOAD table) || Include ping up to 80 char from the end&lt;br /&gt;
|-&lt;br /&gt;
| 1011 || ERROR_FAILED_SENDING_TSV || Failed sending TSV requests || Include TSV request message&lt;br /&gt;
|-&lt;br /&gt;
| 1012 || ERROR_FAILED_SENDING_STATION_ID || Failed sending Station ID requests || Include Station ID request message&lt;br /&gt;
|-&lt;br /&gt;
| 1013 || ERROR_FAILED_ACCESSING_DB || Failed read/write from/to database table || Include SQL statement and data and SQLite error number/message&lt;br /&gt;
|-&lt;br /&gt;
| 1014 || ERROR_CHANGED_DEVICE_ID || Device ID changed ||&lt;br /&gt;
|-&lt;br /&gt;
| 1015 || ERROR_CHANGED_NUID || NUID changed ||&lt;br /&gt;
|-&lt;br /&gt;
| 1016 || ERROR_SDK_NOT_INITIALIZED || App SDK initialization failed ||&lt;br /&gt;
|-&lt;br /&gt;
| 1017 || ERROR_FAILED_SDK_SUSPEND || App SDK failed to suspend activities ||&lt;br /&gt;
|-&lt;br /&gt;
| 1018 || ERROR_INVALID_PARAMETERS || App SDK invalid parameters ||&lt;br /&gt;
|-&lt;br /&gt;
| 1019 || ERROR_INVALID_STATE || App SDK called in incorrect state ||&lt;br /&gt;
|-&lt;br /&gt;
| 1020 || ERROR_FAILED_PROCESS_PLAYHEAD || App SDK failed processing playhead position ||&lt;br /&gt;
|-&lt;br /&gt;
| 1021 || ERROR_FAILED_PROCESS_METADATA || App SDK failed processing not-null, syntax valid JSON metadada ||&lt;br /&gt;
|-&lt;br /&gt;
| 1022 || ERROR_FAILED_PROCESS_STOP || App SDK failed processing stop ||&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1069</id>
		<title>Android SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1069"/>
		<updated>2017-07-12T20:05:59Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* App SDK Error Codes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*Create and initialize an instance object of &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class.&lt;br /&gt;
*The player application can use this object to collect HLS timed metadata through a [[sendID3()]] call.&lt;br /&gt;
The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package. It inherits from the closeable interface and exposes the public APIs the client’s app will use. Below is the declaration of the &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class: &amp;lt;code&amp;gt;public class AppSdk implements Closeable&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Up Development Environment ==&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Setting up in Eclipse IDE ===&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-properties-drm.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
&lt;br /&gt;
'''Library''':&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
'''Classes/package''':&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
 &lt;br /&gt;
=== Setting up in Android Studio IDE ===&lt;br /&gt;
Launch '''Android Studio''' and select '''Import project (Eclipse ADT)'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-setup-launch.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Browse for project destination directory and click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-import-project.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Go to '''File &amp;gt; Project Structure &amp;gt; App &amp;gt; Dependencies'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-pro-structure.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Click '''+''' to add library dependency.&lt;br /&gt;
&lt;br /&gt;
Select '''play-services''' and click '''OK'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-choose-library.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information, refer to https://developer.android.com/google/play-services/setup.html&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Android Application Life Cycle with respect to Nielsen App SDK ===&lt;br /&gt;
[[File:andr-init-img1.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 1: App SDK initialization ===&lt;br /&gt;
==== For API version 4.0.0 and above ====&lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject config = null;&lt;br /&gt;
 &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;uat-cert&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;INFO&amp;quot;) // only for debug builds&lt;br /&gt;
          .put(&amp;quot;custom_key1&amp;quot;, &amp;quot;custom_value1&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;custom_key2&amp;quot;, &amp;quot;custom_value2&amp;quot;);&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
==== Android Application Life Cycle with respect to Nielsen App SDK ====&lt;br /&gt;
[[File:andr-radioandvideo-app.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 2: App SDK libraries inclusion in project ===&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&lt;br /&gt;
*Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Nielsen App SDK Streaming Sessions ===&lt;br /&gt;
After ensuring that the SDK object has been initialized, link the streaming session APIs. The next steps are:&lt;br /&gt;
*Call [[play()]] when starting or resuming a streaming session. Use the channelName parameter to pass channel descriptor information. The channel name field is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.) which must be inserted on a JSON string.&lt;br /&gt;
*Load the CMS metadata by calling the [[loadMetadata()]] on the SDK object.&lt;br /&gt;
*Call [[stop()]] when ending or pausing a viewing session.&lt;br /&gt;
*During session playback, call the SDK [[setPlayheadPosition()]] and / or [[sendID3()]]&lt;br /&gt;
**Call [[setPlayheadPosition()]] every one second until the stream is stopped or paused. Normally this happens on Digital Audio measurements.&lt;br /&gt;
**Call [[sendID3()]] if the client relies on the Nielsen ID3 tags for its measurements; this call should happen whenever a new Nielsen ID3 metadata is available for processing. Normally this happens on DTVR and ID3 measurements.&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
*The client’s app must clearly identify the mode of operation (live vs. VOD) and stick to the type of playhead coordinates until the playback is completed. The client must reliably provide the appropriated playhead position value depending on the type of content streamed.&lt;br /&gt;
*If streaming live video content, the client must pass the current UTC time in seconds as playhead position.&lt;br /&gt;
*If streaming VOD (video on demand), the client must stream the offset from the beginning of the file as playhead position.&lt;br /&gt;
*For all Digital Audio listening, the client must pass the current UTC time in seconds as playhead position, regardless of station type.&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extracting ID3 tags from Android Players ===&lt;br /&gt;
==== ID3 Support Matrix ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Player Name !! Minimum supported version !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Android Native Media Player || Android 6 || Android 6 Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags, generates TimedMetaData.&lt;br /&gt;
|-&lt;br /&gt;
| Google ExoPlayer || Android 4.1 ||&lt;br /&gt;
|-&lt;br /&gt;
| Brightcove Player || Android 4.1 || Support for Android versions 2.3.3 and 4.0 is now deprecated. Learn more about why Brightcove is removing support for these versions as of January 1, 2016 in this [https://support.brightcove.com/en/perform/docs/announcement-brightcove-sdk-android-version-support|announcement]&lt;br /&gt;
|-&lt;br /&gt;
| Adobe PrimeTime Player || Android 4.2 ||&lt;br /&gt;
|-&lt;br /&gt;
| VisualOn Player || Android 2.3 || Android 5 is the latest supported version&lt;br /&gt;
|-&lt;br /&gt;
| NexStream Player || Android 1.6 || Supported till Android 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Android Native Media Player ====&lt;br /&gt;
As the Android Media Player versions (prior to Android 6 / Android API 23) do not support ID3, Nielsen has created a library that becomes an extension to the media player, thus MPX. This library extracts the ID3 tags and sends them to the app. For more information on how to use the MPX component, refer to the Nielsen-supplied sample application.&lt;br /&gt;
&lt;br /&gt;
Starting from '''Android 6 (Android API 23)''', Android Native Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags generate TimedMetadata. Once the HLS video starts, call onTimedMetaDataAvailable() as and when the player observes a TimedMetadata (ID3 tag).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;@Override&lt;br /&gt;
   public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data)&lt;br /&gt;
     {&lt;br /&gt;
       byte[] iD3PayloadArray = data.getMetaData();&lt;br /&gt;
       String iD3Payload = new String(iD3PayloadArray, StandardCharsets.UTF_8);&lt;br /&gt;
       if (null != iD3Payload &amp;amp;&amp;amp; iD3Payload.contains(&amp;quot;www.nielsen.com&amp;quot;))&lt;br /&gt;
         {&lt;br /&gt;
           int index = iD3Payload.indexOf(&amp;quot;www.nielsen.com&amp;quot;);&lt;br /&gt;
           String id3String = iD3Payload.substring(index, (index + 249));&lt;br /&gt;
           Log.d(TAG, &amp;quot;TimedMetaData ID3 Tag:&amp;quot; + id3String);&lt;br /&gt;
           appProcessID3tag(id3String);&lt;br /&gt;
         }&lt;br /&gt;
     }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ExoPlayer ====&lt;br /&gt;
he SDK is designed around an event-driven architecture where components emit events to allow other components to listen and respond to state changes.&lt;br /&gt;
&lt;br /&gt;
'''Player SDK Classes used:'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;com.google.android.exoplayer.demo.player.DemoPlayer&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since Nielsen App SDK is interested in extracting the Timed Metadata (ID3 Tags) in HLS and VOD on the EXO Player, trace the ID3_TAG emitted during video content played using EXOPlayer component as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;DemoPlayer implements ExoPlayer.Listener&lt;br /&gt;
—————————————————–&lt;br /&gt;
/**&lt;br /&gt;
* A listener for receiving ID3 metadata parsed from the media stream.&lt;br /&gt;
*/&lt;br /&gt;
public interface Id3MetadataListener&lt;br /&gt;
{&lt;br /&gt;
  void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata);&lt;br /&gt;
}&lt;br /&gt;
——————————————————-&lt;br /&gt;
MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String,&lt;br /&gt;
Object&amp;gt;&amp;gt; getId3MetadataRenderer()&lt;br /&gt;
  {&lt;br /&gt;
    return new MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;()&lt;br /&gt;
      {&lt;br /&gt;
        @Override&lt;br /&gt;
        public void onMetadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
          {&lt;br /&gt;
            if (id3MetadataListener != null)&lt;br /&gt;
              {&lt;br /&gt;
                id3MetadataListener.onId3Metadata(metadata);&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      };&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also in ''Player.java'' class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;Player implements DemoPlayer.Id3MetadataListener&lt;br /&gt;
—————————————————–&lt;br /&gt;
@SuppressWarnings(&amp;quot;rawtypes&amp;quot;)&lt;br /&gt;
@Override&lt;br /&gt;
public void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
{&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
      for (Object o : metadata.entrySet())&lt;br /&gt;
        {&lt;br /&gt;
          Map.Entry pairs = (Map.Entry) o;&lt;br /&gt;
          if (metadata.containsKey(TxxxMetadata.TYPE))&lt;br /&gt;
            {&lt;br /&gt;
              TxxxMetadata txxxMetadata = (TxxxMetadata) metadata&lt;br /&gt;
              .get(TxxxMetadata.TYPE);&lt;br /&gt;
            }&lt;br /&gt;
          else&lt;br /&gt;
            {&lt;br /&gt;
              String aStr = new String((byte[]) pairs.getValue());&lt;br /&gt;
              MainActivity.mAppSdk.sendID3(aStr);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  catch (Exception e)&lt;br /&gt;
    {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      Log.d(TAG, &amp;quot;onId3Metadata(): No Id3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-exo-retrievingID3tags.png|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Brightcove Player ====&lt;br /&gt;
While the Brightcove player plays the content, EventListener triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;SeamlessVideoDisplayComponent.ID3_TAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;brightcoveVideoView.getEventEmitter().on(SeamlessVideoDisplayComponent.ID3_TAG, new EventListener()&lt;br /&gt;
  {&lt;br /&gt;
    public void processEvent(Event event)&lt;br /&gt;
      {&lt;br /&gt;
        NlsId3Tag nlsID3 = new NlsId3Tag(event.properties.get(SeamlessVideoDisplayComponent.ID3_DATA).toString());&lt;br /&gt;
        Log.w(&amp;quot;ID3&amp;quot;, nlsID3.NlsPayload);&lt;br /&gt;
        // Sent ID3 Tags to App&lt;br /&gt;
        appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      }&lt;br /&gt;
      });&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Adobe PrimeTime Player ====&lt;br /&gt;
While the Adobe PrimeTime player plays the content, MediaPlayer.PlaybackEventListener triggers a callback when an ID3 packet is received (onTimedMetadata). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetadata(TimedMetadata id3Metadata)&lt;br /&gt;
{&lt;br /&gt;
  NlsId3Tag nlsID3 = new NlsId3Tag(id3Metadata.getMetadata().toString());&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;ID3 Timed Data –&amp;gt; &amp;quot; + nlsID3.NlsPayload);&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;PayLoad Size –&amp;gt; &amp;quot; + nlsID3.NlsPayload.length());&lt;br /&gt;
  appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== VisualOn Player ====&lt;br /&gt;
While the VisualOn player plays the content, &amp;lt;code&amp;gt;VOCommonPlayerListener&amp;lt;/code&amp;gt; triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;case VO_OSMP_SRC_CB_CUSTOMER_TAG:&lt;br /&gt;
{&lt;br /&gt;
  VO_OSMP_SRC_CUSTOMERTAGID tag = VO_OSMP_SRC_CUSTOMERTAGID.valueOf(nParam1);&lt;br /&gt;
  switch (tag)&lt;br /&gt;
    {&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG:&lt;br /&gt;
      // do something with this tag&lt;br /&gt;
      int time = nParam2;&lt;br /&gt;
      byte[] b = (byte[]) obj;&lt;br /&gt;
      String s = new String(b);&lt;br /&gt;
      NlsId3Tag nlsID3 = new NlsId3Tag(b);&lt;br /&gt;
      // Sent ID3 Tags to App&lt;br /&gt;
      appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      if (appid3If != null)&lt;br /&gt;
      appid3If.onId3(nlsID3.NlsPayload);&lt;br /&gt;
      break;&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_MAX:&lt;br /&gt;
      // ignore this type of tag&lt;br /&gt;
      break;&lt;br /&gt;
      default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
      break;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== NextStream Player ====&lt;br /&gt;
ID3 tags will be received in the NexStream Player through &amp;lt;code&amp;gt;onTimedMetaRenderRender(NexPlayer mp,NexID3TagInformation metadata)&amp;lt;/code&amp;gt; callback API. A sample implementation for the callback is shown below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetaRenderRender(NexPlayer mp, NexID3TagInformation m)&lt;br /&gt;
  {&lt;br /&gt;
    text = m.getPrivateFrame();&lt;br /&gt;
    if (text != null)&lt;br /&gt;
      {&lt;br /&gt;
        data = text.getTextData();&lt;br /&gt;
        if (data != null)&lt;br /&gt;
          {&lt;br /&gt;
            // make sure to identify the beginning  of  the&lt;br /&gt;
            // Nielsen ID3 tag payload by searching for the&lt;br /&gt;
            // &amp;quot;www.nielsen.com&amp;quot; string on the ID3 tag and&lt;br /&gt;
            // passing to the App SDK all information that&lt;br /&gt;
            // follows. It should be:&lt;br /&gt;
            // nlsPayload = &amp;quot;www.nielsen.com&amp;quot; + dataFollowing&lt;br /&gt;
            nlsPayload = getDataAfterWwwNielsenCom(data);&lt;br /&gt;
            if (nlsPayload!= NULL)&lt;br /&gt;
            mAppSdk.sendID3(nlsPayload);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[sendID3()]] sends the extracted Nielsen ID3 payload to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
== Android SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[AppSDK()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadmetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3()]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[setPlayheadPosition()]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOutURLString()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getOptOutStatus()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi()]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getAppDisable()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query if the SDK is disabled or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastEvent()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last status&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastError()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last error&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[isValid()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to check if the SDK was successfully instantiated or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getMeterVersion()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getNielsenId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getDeviceId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current device id.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInBackground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app going to background.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInForeground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app coming to foreground&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[setDebug()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-andr.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''5.1.1.18 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14, skip ahead to: [[#Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14|Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18, Opt-Out related behavior has been changed in the following ways:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Version 5.1.1.18 or above, refer to documentation above ([[#Opt-out Android SDK Version 5.1.1.18 or above|Opt-out Android SDK Version 5.1.1.18 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**Capture user’s selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Opt Out of Ads for Personalization for the latest versions of the SDK (5.1.1.18 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Opt Out of Ads for Personalization&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in Google Play Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample Google Play Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
'''App SDK Event Codes '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2000 || EVENT_INITIATE || App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || EVENT_STARTUP || App SDK has started up. It will happen only after App SDK has received a valid config file. This is the location in the code to acquire the value of [[userOptOutURLString()]].&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || EVENT_SHUTDOWN || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
Constants with predefined error codes which the AppSdk object can generate.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Description !! Behavior&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || ERROR_FAILED_CREATE_URL_STRING || Failed generating ping string due to error on parsing || Include last error message from URL parser&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || ERROR_FAILED_RECEIVE_CONFIG || Failed to receive configuration file from Census || On 5th time, it will log event and keep requesting config 10 min apart&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || ERROR_FAILED_PARSING_CONFIG || Failed parsing the config file JSON string || Include json error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || ERROR_FAILED_PARSING_PLAY || Failed parsing the play() JSON string || Include JSON error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || ERROR_FAILED_PARSING_METADATA || Failed parsing the play() JSON string || Include JSON error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || ERROR_FAILED_GENERATING_PING || Failed creating ping before adding it to the UPLOAD table) || Include ping nol_url index, cadence to identify ping&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || ERROR_FAILED_PROCESSOR_START || Failed starting data processor thread. Normally, that means a product || Include processor that failed to start&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || ERROR_FAILED_PROCESS_ID3 || Failed processing data on a data processor. Normally, that means the input to a product || Include processor and data that failed to process (ID3 tag on a MTVR impression, for example)&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || ERROR_FAILED_HTTP_SEND || Failed sending HTTP or HTTPS requests || Include HTTP error number&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || ERROR_FAILED_SENDING_PING || Failed sending pings (on ANDROID, the ping on the UPLOAD table) || Include ping up to 80 char from the end&lt;br /&gt;
|-&lt;br /&gt;
| 1011 || ERROR_FAILED_SENDING_TSV || Failed sending TSV requests || Include TSV request message&lt;br /&gt;
|-&lt;br /&gt;
| 1012 || ERROR_FAILED_SENDING_STATION_ID || Failed sending Station ID requests || Include Station ID request message&lt;br /&gt;
|-&lt;br /&gt;
| 1013 || ERROR_FAILED_ACCESSING_DB || Failed read/write from/to database table || Include SQL statement and data and SQLite error number/message&lt;br /&gt;
|-&lt;br /&gt;
| 1014 || ERROR_CHANGED_DEVICE_ID || Device ID changed ||&lt;br /&gt;
|-&lt;br /&gt;
| 1015 || ERROR_CHANGED_NUID || NUID changed ||&lt;br /&gt;
|-&lt;br /&gt;
| 1016 || ERROR_SDK_NOT_INITIALIZED || App SDK initialization failed ||&lt;br /&gt;
|-&lt;br /&gt;
| 1017 || ERROR_FAILED_SDK_SUSPEND || App SDK failed to suspend activities ||&lt;br /&gt;
|-&lt;br /&gt;
| 1018 || ERROR_INVALID_PARAMETERS || App SDK invalid parameters ||&lt;br /&gt;
|-&lt;br /&gt;
| 1019 || ERROR_INVALID_STATE || App SDK called in incorrect state ||&lt;br /&gt;
|-&lt;br /&gt;
| 1020 || ERROR_FAILED_PROCESS_PLAYHEAD || App SDK failed processing playhead position ||&lt;br /&gt;
|-&lt;br /&gt;
| 1021 || ERROR_FAILED_PROCESS_METADATA || App SDK failed processing not-null, syntax valid JSON metadada ||&lt;br /&gt;
|-&lt;br /&gt;
| 1022 || ERROR_FAILED_PROCESS_STOP || App SDK failed processing stop ||&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1068</id>
		<title>Android SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1068"/>
		<updated>2017-07-12T20:05:16Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Event and Error Handling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*Create and initialize an instance object of &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class.&lt;br /&gt;
*The player application can use this object to collect HLS timed metadata through a [[sendID3()]] call.&lt;br /&gt;
The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package. It inherits from the closeable interface and exposes the public APIs the client’s app will use. Below is the declaration of the &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class: &amp;lt;code&amp;gt;public class AppSdk implements Closeable&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Up Development Environment ==&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Setting up in Eclipse IDE ===&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-properties-drm.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
&lt;br /&gt;
'''Library''':&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
'''Classes/package''':&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
 &lt;br /&gt;
=== Setting up in Android Studio IDE ===&lt;br /&gt;
Launch '''Android Studio''' and select '''Import project (Eclipse ADT)'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-setup-launch.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Browse for project destination directory and click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-import-project.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Go to '''File &amp;gt; Project Structure &amp;gt; App &amp;gt; Dependencies'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-pro-structure.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Click '''+''' to add library dependency.&lt;br /&gt;
&lt;br /&gt;
Select '''play-services''' and click '''OK'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-choose-library.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information, refer to https://developer.android.com/google/play-services/setup.html&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Android Application Life Cycle with respect to Nielsen App SDK ===&lt;br /&gt;
[[File:andr-init-img1.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 1: App SDK initialization ===&lt;br /&gt;
==== For API version 4.0.0 and above ====&lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject config = null;&lt;br /&gt;
 &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;uat-cert&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;INFO&amp;quot;) // only for debug builds&lt;br /&gt;
          .put(&amp;quot;custom_key1&amp;quot;, &amp;quot;custom_value1&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;custom_key2&amp;quot;, &amp;quot;custom_value2&amp;quot;);&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
==== Android Application Life Cycle with respect to Nielsen App SDK ====&lt;br /&gt;
[[File:andr-radioandvideo-app.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 2: App SDK libraries inclusion in project ===&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&lt;br /&gt;
*Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Nielsen App SDK Streaming Sessions ===&lt;br /&gt;
After ensuring that the SDK object has been initialized, link the streaming session APIs. The next steps are:&lt;br /&gt;
*Call [[play()]] when starting or resuming a streaming session. Use the channelName parameter to pass channel descriptor information. The channel name field is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.) which must be inserted on a JSON string.&lt;br /&gt;
*Load the CMS metadata by calling the [[loadMetadata()]] on the SDK object.&lt;br /&gt;
*Call [[stop()]] when ending or pausing a viewing session.&lt;br /&gt;
*During session playback, call the SDK [[setPlayheadPosition()]] and / or [[sendID3()]]&lt;br /&gt;
**Call [[setPlayheadPosition()]] every one second until the stream is stopped or paused. Normally this happens on Digital Audio measurements.&lt;br /&gt;
**Call [[sendID3()]] if the client relies on the Nielsen ID3 tags for its measurements; this call should happen whenever a new Nielsen ID3 metadata is available for processing. Normally this happens on DTVR and ID3 measurements.&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
*The client’s app must clearly identify the mode of operation (live vs. VOD) and stick to the type of playhead coordinates until the playback is completed. The client must reliably provide the appropriated playhead position value depending on the type of content streamed.&lt;br /&gt;
*If streaming live video content, the client must pass the current UTC time in seconds as playhead position.&lt;br /&gt;
*If streaming VOD (video on demand), the client must stream the offset from the beginning of the file as playhead position.&lt;br /&gt;
*For all Digital Audio listening, the client must pass the current UTC time in seconds as playhead position, regardless of station type.&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extracting ID3 tags from Android Players ===&lt;br /&gt;
==== ID3 Support Matrix ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Player Name !! Minimum supported version !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Android Native Media Player || Android 6 || Android 6 Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags, generates TimedMetaData.&lt;br /&gt;
|-&lt;br /&gt;
| Google ExoPlayer || Android 4.1 ||&lt;br /&gt;
|-&lt;br /&gt;
| Brightcove Player || Android 4.1 || Support for Android versions 2.3.3 and 4.0 is now deprecated. Learn more about why Brightcove is removing support for these versions as of January 1, 2016 in this [https://support.brightcove.com/en/perform/docs/announcement-brightcove-sdk-android-version-support|announcement]&lt;br /&gt;
|-&lt;br /&gt;
| Adobe PrimeTime Player || Android 4.2 ||&lt;br /&gt;
|-&lt;br /&gt;
| VisualOn Player || Android 2.3 || Android 5 is the latest supported version&lt;br /&gt;
|-&lt;br /&gt;
| NexStream Player || Android 1.6 || Supported till Android 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Android Native Media Player ====&lt;br /&gt;
As the Android Media Player versions (prior to Android 6 / Android API 23) do not support ID3, Nielsen has created a library that becomes an extension to the media player, thus MPX. This library extracts the ID3 tags and sends them to the app. For more information on how to use the MPX component, refer to the Nielsen-supplied sample application.&lt;br /&gt;
&lt;br /&gt;
Starting from '''Android 6 (Android API 23)''', Android Native Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags generate TimedMetadata. Once the HLS video starts, call onTimedMetaDataAvailable() as and when the player observes a TimedMetadata (ID3 tag).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;@Override&lt;br /&gt;
   public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data)&lt;br /&gt;
     {&lt;br /&gt;
       byte[] iD3PayloadArray = data.getMetaData();&lt;br /&gt;
       String iD3Payload = new String(iD3PayloadArray, StandardCharsets.UTF_8);&lt;br /&gt;
       if (null != iD3Payload &amp;amp;&amp;amp; iD3Payload.contains(&amp;quot;www.nielsen.com&amp;quot;))&lt;br /&gt;
         {&lt;br /&gt;
           int index = iD3Payload.indexOf(&amp;quot;www.nielsen.com&amp;quot;);&lt;br /&gt;
           String id3String = iD3Payload.substring(index, (index + 249));&lt;br /&gt;
           Log.d(TAG, &amp;quot;TimedMetaData ID3 Tag:&amp;quot; + id3String);&lt;br /&gt;
           appProcessID3tag(id3String);&lt;br /&gt;
         }&lt;br /&gt;
     }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ExoPlayer ====&lt;br /&gt;
he SDK is designed around an event-driven architecture where components emit events to allow other components to listen and respond to state changes.&lt;br /&gt;
&lt;br /&gt;
'''Player SDK Classes used:'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;com.google.android.exoplayer.demo.player.DemoPlayer&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since Nielsen App SDK is interested in extracting the Timed Metadata (ID3 Tags) in HLS and VOD on the EXO Player, trace the ID3_TAG emitted during video content played using EXOPlayer component as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;DemoPlayer implements ExoPlayer.Listener&lt;br /&gt;
—————————————————–&lt;br /&gt;
/**&lt;br /&gt;
* A listener for receiving ID3 metadata parsed from the media stream.&lt;br /&gt;
*/&lt;br /&gt;
public interface Id3MetadataListener&lt;br /&gt;
{&lt;br /&gt;
  void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata);&lt;br /&gt;
}&lt;br /&gt;
——————————————————-&lt;br /&gt;
MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String,&lt;br /&gt;
Object&amp;gt;&amp;gt; getId3MetadataRenderer()&lt;br /&gt;
  {&lt;br /&gt;
    return new MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;()&lt;br /&gt;
      {&lt;br /&gt;
        @Override&lt;br /&gt;
        public void onMetadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
          {&lt;br /&gt;
            if (id3MetadataListener != null)&lt;br /&gt;
              {&lt;br /&gt;
                id3MetadataListener.onId3Metadata(metadata);&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      };&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also in ''Player.java'' class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;Player implements DemoPlayer.Id3MetadataListener&lt;br /&gt;
—————————————————–&lt;br /&gt;
@SuppressWarnings(&amp;quot;rawtypes&amp;quot;)&lt;br /&gt;
@Override&lt;br /&gt;
public void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
{&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
      for (Object o : metadata.entrySet())&lt;br /&gt;
        {&lt;br /&gt;
          Map.Entry pairs = (Map.Entry) o;&lt;br /&gt;
          if (metadata.containsKey(TxxxMetadata.TYPE))&lt;br /&gt;
            {&lt;br /&gt;
              TxxxMetadata txxxMetadata = (TxxxMetadata) metadata&lt;br /&gt;
              .get(TxxxMetadata.TYPE);&lt;br /&gt;
            }&lt;br /&gt;
          else&lt;br /&gt;
            {&lt;br /&gt;
              String aStr = new String((byte[]) pairs.getValue());&lt;br /&gt;
              MainActivity.mAppSdk.sendID3(aStr);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  catch (Exception e)&lt;br /&gt;
    {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      Log.d(TAG, &amp;quot;onId3Metadata(): No Id3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-exo-retrievingID3tags.png|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Brightcove Player ====&lt;br /&gt;
While the Brightcove player plays the content, EventListener triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;SeamlessVideoDisplayComponent.ID3_TAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;brightcoveVideoView.getEventEmitter().on(SeamlessVideoDisplayComponent.ID3_TAG, new EventListener()&lt;br /&gt;
  {&lt;br /&gt;
    public void processEvent(Event event)&lt;br /&gt;
      {&lt;br /&gt;
        NlsId3Tag nlsID3 = new NlsId3Tag(event.properties.get(SeamlessVideoDisplayComponent.ID3_DATA).toString());&lt;br /&gt;
        Log.w(&amp;quot;ID3&amp;quot;, nlsID3.NlsPayload);&lt;br /&gt;
        // Sent ID3 Tags to App&lt;br /&gt;
        appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      }&lt;br /&gt;
      });&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Adobe PrimeTime Player ====&lt;br /&gt;
While the Adobe PrimeTime player plays the content, MediaPlayer.PlaybackEventListener triggers a callback when an ID3 packet is received (onTimedMetadata). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetadata(TimedMetadata id3Metadata)&lt;br /&gt;
{&lt;br /&gt;
  NlsId3Tag nlsID3 = new NlsId3Tag(id3Metadata.getMetadata().toString());&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;ID3 Timed Data –&amp;gt; &amp;quot; + nlsID3.NlsPayload);&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;PayLoad Size –&amp;gt; &amp;quot; + nlsID3.NlsPayload.length());&lt;br /&gt;
  appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== VisualOn Player ====&lt;br /&gt;
While the VisualOn player plays the content, &amp;lt;code&amp;gt;VOCommonPlayerListener&amp;lt;/code&amp;gt; triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;case VO_OSMP_SRC_CB_CUSTOMER_TAG:&lt;br /&gt;
{&lt;br /&gt;
  VO_OSMP_SRC_CUSTOMERTAGID tag = VO_OSMP_SRC_CUSTOMERTAGID.valueOf(nParam1);&lt;br /&gt;
  switch (tag)&lt;br /&gt;
    {&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG:&lt;br /&gt;
      // do something with this tag&lt;br /&gt;
      int time = nParam2;&lt;br /&gt;
      byte[] b = (byte[]) obj;&lt;br /&gt;
      String s = new String(b);&lt;br /&gt;
      NlsId3Tag nlsID3 = new NlsId3Tag(b);&lt;br /&gt;
      // Sent ID3 Tags to App&lt;br /&gt;
      appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      if (appid3If != null)&lt;br /&gt;
      appid3If.onId3(nlsID3.NlsPayload);&lt;br /&gt;
      break;&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_MAX:&lt;br /&gt;
      // ignore this type of tag&lt;br /&gt;
      break;&lt;br /&gt;
      default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
      break;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== NextStream Player ====&lt;br /&gt;
ID3 tags will be received in the NexStream Player through &amp;lt;code&amp;gt;onTimedMetaRenderRender(NexPlayer mp,NexID3TagInformation metadata)&amp;lt;/code&amp;gt; callback API. A sample implementation for the callback is shown below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetaRenderRender(NexPlayer mp, NexID3TagInformation m)&lt;br /&gt;
  {&lt;br /&gt;
    text = m.getPrivateFrame();&lt;br /&gt;
    if (text != null)&lt;br /&gt;
      {&lt;br /&gt;
        data = text.getTextData();&lt;br /&gt;
        if (data != null)&lt;br /&gt;
          {&lt;br /&gt;
            // make sure to identify the beginning  of  the&lt;br /&gt;
            // Nielsen ID3 tag payload by searching for the&lt;br /&gt;
            // &amp;quot;www.nielsen.com&amp;quot; string on the ID3 tag and&lt;br /&gt;
            // passing to the App SDK all information that&lt;br /&gt;
            // follows. It should be:&lt;br /&gt;
            // nlsPayload = &amp;quot;www.nielsen.com&amp;quot; + dataFollowing&lt;br /&gt;
            nlsPayload = getDataAfterWwwNielsenCom(data);&lt;br /&gt;
            if (nlsPayload!= NULL)&lt;br /&gt;
            mAppSdk.sendID3(nlsPayload);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[sendID3()]] sends the extracted Nielsen ID3 payload to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
== Android SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[AppSDK()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadmetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3()]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[setPlayheadPosition()]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOutURLString()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getOptOutStatus()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi()]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getAppDisable()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query if the SDK is disabled or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastEvent()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last status&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastError()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last error&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[isValid()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to check if the SDK was successfully instantiated or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getMeterVersion()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getNielsenId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getDeviceId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current device id.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInBackground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app going to background.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInForeground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app coming to foreground&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[setDebug()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-andr.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''5.1.1.18 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14, skip ahead to: [[#Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14|Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18, Opt-Out related behavior has been changed in the following ways:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Version 5.1.1.18 or above, refer to documentation above ([[#Opt-out Android SDK Version 5.1.1.18 or above|Opt-out Android SDK Version 5.1.1.18 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**Capture user’s selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Opt Out of Ads for Personalization for the latest versions of the SDK (5.1.1.18 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Opt Out of Ads for Personalization&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in Google Play Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample Google Play Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
'''App SDK Event Codes '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2000 || EVENT_INITIATE || App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || EVENT_STARTUP || App SDK has started up. It will happen only after App SDK has received a valid config file. This is the location in the code to acquire the value of [[userOptOutURLString()]].&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || EVENT_SHUTDOWN || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
Constants with predefined error codes which the AppSdk object can generate.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Description !! Behavior&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || ERROR_FAILED_CREATE_URL_STRING || Failed generating ping string due to error on parsing || Include last error message from URL parser&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || ERROR_FAILED_RECEIVE_CONFIG || Failed to receive configuration file from Census || On 5th time, it will log event and keep requesting config 10 min apart&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || ERROR_FAILED_PARSING_CONFIG || Failed parsing the config file JSON string || Include json error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || ERROR_FAILED_PARSING_PLAY || Failed parsing the play() JSON string || Include JSON error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || ERROR_FAILED_PARSING_METADATA || Failed parsing the play() JSON string || Include JSON error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || ERROR_FAILED_GENERATING_PING || Failed creating ping before adding it to the UPLOAD table) || Include ping nol_url index, cadence to identify ping&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || ERROR_FAILED_PROCESSOR_START || Failed starting data processor thread. Normally, that means a product || Include processor that failed to start&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || ERROR_FAILED_PROCESS_ID3 || Failed processing data on a data processor. Normally, that means the input to a product || Include processor and data that failed to process (ID3 tag on a MTVR impression, for example)&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || ERROR_FAILED_HTTP_SEND || Failed sending HTTP or HTTPS requests || Include HTTP error number&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || ERROR_FAILED_SENDING_PING || Failed sending pings (on ANDROID, the ping on the UPLOAD table) || Include ping up to 80 char from the end&lt;br /&gt;
|-&lt;br /&gt;
| 1011 || ERROR_FAILED_SENDING_TSV || Failed sending TSV requests || Include TSV request message&lt;br /&gt;
|-&lt;br /&gt;
| 1012 || ERROR_FAILED_SENDING_STATION_ID || Failed sending Station ID requests || Include Station ID request message&lt;br /&gt;
|-&lt;br /&gt;
| 1013 || ERROR_FAILED_ACCESSING_DB || Failed read/write from/to database table || Include SQL statement and data and SQLite error number/message&lt;br /&gt;
|-&lt;br /&gt;
| 1014 || ERROR_CHANGED_DEVICE_ID || Device ID changed&lt;br /&gt;
|-&lt;br /&gt;
| 1015 || ERROR_CHANGED_NUID || NUID changed&lt;br /&gt;
|-&lt;br /&gt;
| 1016 || ERROR_SDK_NOT_INITIALIZED || App SDK initialization failed&lt;br /&gt;
|-&lt;br /&gt;
| 1017 || ERROR_FAILED_SDK_SUSPEND || App SDK failed to suspend activities&lt;br /&gt;
|-&lt;br /&gt;
| 1018 || ERROR_INVALID_PARAMETERS || App SDK invalid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 1019 || ERROR_INVALID_STATE || App SDK called in incorrect state&lt;br /&gt;
|-&lt;br /&gt;
| 1020 || ERROR_FAILED_PROCESS_PLAYHEAD || App SDK failed processing playhead position&lt;br /&gt;
|-&lt;br /&gt;
| 1021 || ERROR_FAILED_PROCESS_METADATA || App SDK failed processing not-null, syntax valid JSON metadada&lt;br /&gt;
|-&lt;br /&gt;
| 1022 || ERROR_FAILED_PROCESS_STOP || App SDK failed processing stop&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1067</id>
		<title>Android SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1067"/>
		<updated>2017-07-12T20:04:56Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* App SDK Error Codes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*Create and initialize an instance object of &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class.&lt;br /&gt;
*The player application can use this object to collect HLS timed metadata through a [[sendID3()]] call.&lt;br /&gt;
The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package. It inherits from the closeable interface and exposes the public APIs the client’s app will use. Below is the declaration of the &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class: &amp;lt;code&amp;gt;public class AppSdk implements Closeable&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Up Development Environment ==&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Setting up in Eclipse IDE ===&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-properties-drm.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
&lt;br /&gt;
'''Library''':&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
'''Classes/package''':&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
 &lt;br /&gt;
=== Setting up in Android Studio IDE ===&lt;br /&gt;
Launch '''Android Studio''' and select '''Import project (Eclipse ADT)'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-setup-launch.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Browse for project destination directory and click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-import-project.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Go to '''File &amp;gt; Project Structure &amp;gt; App &amp;gt; Dependencies'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-pro-structure.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Click '''+''' to add library dependency.&lt;br /&gt;
&lt;br /&gt;
Select '''play-services''' and click '''OK'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-choose-library.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information, refer to https://developer.android.com/google/play-services/setup.html&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Android Application Life Cycle with respect to Nielsen App SDK ===&lt;br /&gt;
[[File:andr-init-img1.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 1: App SDK initialization ===&lt;br /&gt;
==== For API version 4.0.0 and above ====&lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject config = null;&lt;br /&gt;
 &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;uat-cert&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;INFO&amp;quot;) // only for debug builds&lt;br /&gt;
          .put(&amp;quot;custom_key1&amp;quot;, &amp;quot;custom_value1&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;custom_key2&amp;quot;, &amp;quot;custom_value2&amp;quot;);&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
==== Android Application Life Cycle with respect to Nielsen App SDK ====&lt;br /&gt;
[[File:andr-radioandvideo-app.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 2: App SDK libraries inclusion in project ===&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&lt;br /&gt;
*Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Nielsen App SDK Streaming Sessions ===&lt;br /&gt;
After ensuring that the SDK object has been initialized, link the streaming session APIs. The next steps are:&lt;br /&gt;
*Call [[play()]] when starting or resuming a streaming session. Use the channelName parameter to pass channel descriptor information. The channel name field is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.) which must be inserted on a JSON string.&lt;br /&gt;
*Load the CMS metadata by calling the [[loadMetadata()]] on the SDK object.&lt;br /&gt;
*Call [[stop()]] when ending or pausing a viewing session.&lt;br /&gt;
*During session playback, call the SDK [[setPlayheadPosition()]] and / or [[sendID3()]]&lt;br /&gt;
**Call [[setPlayheadPosition()]] every one second until the stream is stopped or paused. Normally this happens on Digital Audio measurements.&lt;br /&gt;
**Call [[sendID3()]] if the client relies on the Nielsen ID3 tags for its measurements; this call should happen whenever a new Nielsen ID3 metadata is available for processing. Normally this happens on DTVR and ID3 measurements.&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
*The client’s app must clearly identify the mode of operation (live vs. VOD) and stick to the type of playhead coordinates until the playback is completed. The client must reliably provide the appropriated playhead position value depending on the type of content streamed.&lt;br /&gt;
*If streaming live video content, the client must pass the current UTC time in seconds as playhead position.&lt;br /&gt;
*If streaming VOD (video on demand), the client must stream the offset from the beginning of the file as playhead position.&lt;br /&gt;
*For all Digital Audio listening, the client must pass the current UTC time in seconds as playhead position, regardless of station type.&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extracting ID3 tags from Android Players ===&lt;br /&gt;
==== ID3 Support Matrix ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Player Name !! Minimum supported version !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Android Native Media Player || Android 6 || Android 6 Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags, generates TimedMetaData.&lt;br /&gt;
|-&lt;br /&gt;
| Google ExoPlayer || Android 4.1 ||&lt;br /&gt;
|-&lt;br /&gt;
| Brightcove Player || Android 4.1 || Support for Android versions 2.3.3 and 4.0 is now deprecated. Learn more about why Brightcove is removing support for these versions as of January 1, 2016 in this [https://support.brightcove.com/en/perform/docs/announcement-brightcove-sdk-android-version-support|announcement]&lt;br /&gt;
|-&lt;br /&gt;
| Adobe PrimeTime Player || Android 4.2 ||&lt;br /&gt;
|-&lt;br /&gt;
| VisualOn Player || Android 2.3 || Android 5 is the latest supported version&lt;br /&gt;
|-&lt;br /&gt;
| NexStream Player || Android 1.6 || Supported till Android 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Android Native Media Player ====&lt;br /&gt;
As the Android Media Player versions (prior to Android 6 / Android API 23) do not support ID3, Nielsen has created a library that becomes an extension to the media player, thus MPX. This library extracts the ID3 tags and sends them to the app. For more information on how to use the MPX component, refer to the Nielsen-supplied sample application.&lt;br /&gt;
&lt;br /&gt;
Starting from '''Android 6 (Android API 23)''', Android Native Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags generate TimedMetadata. Once the HLS video starts, call onTimedMetaDataAvailable() as and when the player observes a TimedMetadata (ID3 tag).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;@Override&lt;br /&gt;
   public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data)&lt;br /&gt;
     {&lt;br /&gt;
       byte[] iD3PayloadArray = data.getMetaData();&lt;br /&gt;
       String iD3Payload = new String(iD3PayloadArray, StandardCharsets.UTF_8);&lt;br /&gt;
       if (null != iD3Payload &amp;amp;&amp;amp; iD3Payload.contains(&amp;quot;www.nielsen.com&amp;quot;))&lt;br /&gt;
         {&lt;br /&gt;
           int index = iD3Payload.indexOf(&amp;quot;www.nielsen.com&amp;quot;);&lt;br /&gt;
           String id3String = iD3Payload.substring(index, (index + 249));&lt;br /&gt;
           Log.d(TAG, &amp;quot;TimedMetaData ID3 Tag:&amp;quot; + id3String);&lt;br /&gt;
           appProcessID3tag(id3String);&lt;br /&gt;
         }&lt;br /&gt;
     }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ExoPlayer ====&lt;br /&gt;
he SDK is designed around an event-driven architecture where components emit events to allow other components to listen and respond to state changes.&lt;br /&gt;
&lt;br /&gt;
'''Player SDK Classes used:'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;com.google.android.exoplayer.demo.player.DemoPlayer&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since Nielsen App SDK is interested in extracting the Timed Metadata (ID3 Tags) in HLS and VOD on the EXO Player, trace the ID3_TAG emitted during video content played using EXOPlayer component as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;DemoPlayer implements ExoPlayer.Listener&lt;br /&gt;
—————————————————–&lt;br /&gt;
/**&lt;br /&gt;
* A listener for receiving ID3 metadata parsed from the media stream.&lt;br /&gt;
*/&lt;br /&gt;
public interface Id3MetadataListener&lt;br /&gt;
{&lt;br /&gt;
  void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata);&lt;br /&gt;
}&lt;br /&gt;
——————————————————-&lt;br /&gt;
MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String,&lt;br /&gt;
Object&amp;gt;&amp;gt; getId3MetadataRenderer()&lt;br /&gt;
  {&lt;br /&gt;
    return new MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;()&lt;br /&gt;
      {&lt;br /&gt;
        @Override&lt;br /&gt;
        public void onMetadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
          {&lt;br /&gt;
            if (id3MetadataListener != null)&lt;br /&gt;
              {&lt;br /&gt;
                id3MetadataListener.onId3Metadata(metadata);&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      };&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also in ''Player.java'' class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;Player implements DemoPlayer.Id3MetadataListener&lt;br /&gt;
—————————————————–&lt;br /&gt;
@SuppressWarnings(&amp;quot;rawtypes&amp;quot;)&lt;br /&gt;
@Override&lt;br /&gt;
public void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
{&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
      for (Object o : metadata.entrySet())&lt;br /&gt;
        {&lt;br /&gt;
          Map.Entry pairs = (Map.Entry) o;&lt;br /&gt;
          if (metadata.containsKey(TxxxMetadata.TYPE))&lt;br /&gt;
            {&lt;br /&gt;
              TxxxMetadata txxxMetadata = (TxxxMetadata) metadata&lt;br /&gt;
              .get(TxxxMetadata.TYPE);&lt;br /&gt;
            }&lt;br /&gt;
          else&lt;br /&gt;
            {&lt;br /&gt;
              String aStr = new String((byte[]) pairs.getValue());&lt;br /&gt;
              MainActivity.mAppSdk.sendID3(aStr);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  catch (Exception e)&lt;br /&gt;
    {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      Log.d(TAG, &amp;quot;onId3Metadata(): No Id3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-exo-retrievingID3tags.png|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Brightcove Player ====&lt;br /&gt;
While the Brightcove player plays the content, EventListener triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;SeamlessVideoDisplayComponent.ID3_TAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;brightcoveVideoView.getEventEmitter().on(SeamlessVideoDisplayComponent.ID3_TAG, new EventListener()&lt;br /&gt;
  {&lt;br /&gt;
    public void processEvent(Event event)&lt;br /&gt;
      {&lt;br /&gt;
        NlsId3Tag nlsID3 = new NlsId3Tag(event.properties.get(SeamlessVideoDisplayComponent.ID3_DATA).toString());&lt;br /&gt;
        Log.w(&amp;quot;ID3&amp;quot;, nlsID3.NlsPayload);&lt;br /&gt;
        // Sent ID3 Tags to App&lt;br /&gt;
        appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      }&lt;br /&gt;
      });&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Adobe PrimeTime Player ====&lt;br /&gt;
While the Adobe PrimeTime player plays the content, MediaPlayer.PlaybackEventListener triggers a callback when an ID3 packet is received (onTimedMetadata). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetadata(TimedMetadata id3Metadata)&lt;br /&gt;
{&lt;br /&gt;
  NlsId3Tag nlsID3 = new NlsId3Tag(id3Metadata.getMetadata().toString());&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;ID3 Timed Data –&amp;gt; &amp;quot; + nlsID3.NlsPayload);&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;PayLoad Size –&amp;gt; &amp;quot; + nlsID3.NlsPayload.length());&lt;br /&gt;
  appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== VisualOn Player ====&lt;br /&gt;
While the VisualOn player plays the content, &amp;lt;code&amp;gt;VOCommonPlayerListener&amp;lt;/code&amp;gt; triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;case VO_OSMP_SRC_CB_CUSTOMER_TAG:&lt;br /&gt;
{&lt;br /&gt;
  VO_OSMP_SRC_CUSTOMERTAGID tag = VO_OSMP_SRC_CUSTOMERTAGID.valueOf(nParam1);&lt;br /&gt;
  switch (tag)&lt;br /&gt;
    {&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG:&lt;br /&gt;
      // do something with this tag&lt;br /&gt;
      int time = nParam2;&lt;br /&gt;
      byte[] b = (byte[]) obj;&lt;br /&gt;
      String s = new String(b);&lt;br /&gt;
      NlsId3Tag nlsID3 = new NlsId3Tag(b);&lt;br /&gt;
      // Sent ID3 Tags to App&lt;br /&gt;
      appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      if (appid3If != null)&lt;br /&gt;
      appid3If.onId3(nlsID3.NlsPayload);&lt;br /&gt;
      break;&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_MAX:&lt;br /&gt;
      // ignore this type of tag&lt;br /&gt;
      break;&lt;br /&gt;
      default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
      break;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== NextStream Player ====&lt;br /&gt;
ID3 tags will be received in the NexStream Player through &amp;lt;code&amp;gt;onTimedMetaRenderRender(NexPlayer mp,NexID3TagInformation metadata)&amp;lt;/code&amp;gt; callback API. A sample implementation for the callback is shown below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetaRenderRender(NexPlayer mp, NexID3TagInformation m)&lt;br /&gt;
  {&lt;br /&gt;
    text = m.getPrivateFrame();&lt;br /&gt;
    if (text != null)&lt;br /&gt;
      {&lt;br /&gt;
        data = text.getTextData();&lt;br /&gt;
        if (data != null)&lt;br /&gt;
          {&lt;br /&gt;
            // make sure to identify the beginning  of  the&lt;br /&gt;
            // Nielsen ID3 tag payload by searching for the&lt;br /&gt;
            // &amp;quot;www.nielsen.com&amp;quot; string on the ID3 tag and&lt;br /&gt;
            // passing to the App SDK all information that&lt;br /&gt;
            // follows. It should be:&lt;br /&gt;
            // nlsPayload = &amp;quot;www.nielsen.com&amp;quot; + dataFollowing&lt;br /&gt;
            nlsPayload = getDataAfterWwwNielsenCom(data);&lt;br /&gt;
            if (nlsPayload!= NULL)&lt;br /&gt;
            mAppSdk.sendID3(nlsPayload);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[sendID3()]] sends the extracted Nielsen ID3 payload to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
== Android SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[AppSDK()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadmetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3()]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[setPlayheadPosition()]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOutURLString()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getOptOutStatus()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi()]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getAppDisable()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query if the SDK is disabled or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastEvent()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last status&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastError()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last error&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[isValid()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to check if the SDK was successfully instantiated or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getMeterVersion()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getNielsenId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getDeviceId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current device id.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInBackground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app going to background.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInForeground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app coming to foreground&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[setDebug()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-andr.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''5.1.1.18 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14, skip ahead to: [[#Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14|Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18, Opt-Out related behavior has been changed in the following ways:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Version 5.1.1.18 or above, refer to documentation above ([[#Opt-out Android SDK Version 5.1.1.18 or above|Opt-out Android SDK Version 5.1.1.18 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**Capture user’s selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Opt Out of Ads for Personalization for the latest versions of the SDK (5.1.1.18 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Opt Out of Ads for Personalization&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in Google Play Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample Google Play Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
Constants with predefined error codes which the AppSdk object can generate.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Description !! Behavior&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || ERROR_FAILED_CREATE_URL_STRING || Failed generating ping string due to error on parsing || Include last error message from URL parser&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || ERROR_FAILED_RECEIVE_CONFIG || Failed to receive configuration file from Census || On 5th time, it will log event and keep requesting config 10 min apart&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || ERROR_FAILED_PARSING_CONFIG || Failed parsing the config file JSON string || Include json error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || ERROR_FAILED_PARSING_PLAY || Failed parsing the play() JSON string || Include JSON error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || ERROR_FAILED_PARSING_METADATA || Failed parsing the play() JSON string || Include JSON error number/short message from iOS or Android&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || ERROR_FAILED_GENERATING_PING || Failed creating ping before adding it to the UPLOAD table) || Include ping nol_url index, cadence to identify ping&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || ERROR_FAILED_PROCESSOR_START || Failed starting data processor thread. Normally, that means a product || Include processor that failed to start&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || ERROR_FAILED_PROCESS_ID3 || Failed processing data on a data processor. Normally, that means the input to a product || Include processor and data that failed to process (ID3 tag on a MTVR impression, for example)&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || ERROR_FAILED_HTTP_SEND || Failed sending HTTP or HTTPS requests || Include HTTP error number&lt;br /&gt;
|-&lt;br /&gt;
| 1010 || ERROR_FAILED_SENDING_PING || Failed sending pings (on ANDROID, the ping on the UPLOAD table) || Include ping up to 80 char from the end&lt;br /&gt;
|-&lt;br /&gt;
| 1011 || ERROR_FAILED_SENDING_TSV || Failed sending TSV requests || Include TSV request message&lt;br /&gt;
|-&lt;br /&gt;
| 1012 || ERROR_FAILED_SENDING_STATION_ID || Failed sending Station ID requests || Include Station ID request message&lt;br /&gt;
|-&lt;br /&gt;
| 1013 || ERROR_FAILED_ACCESSING_DB || Failed read/write from/to database table || Include SQL statement and data and SQLite error number/message&lt;br /&gt;
|-&lt;br /&gt;
| 1014 || ERROR_CHANGED_DEVICE_ID || Device ID changed&lt;br /&gt;
|-&lt;br /&gt;
| 1015 || ERROR_CHANGED_NUID || NUID changed&lt;br /&gt;
|-&lt;br /&gt;
| 1016 || ERROR_SDK_NOT_INITIALIZED || App SDK initialization failed&lt;br /&gt;
|-&lt;br /&gt;
| 1017 || ERROR_FAILED_SDK_SUSPEND || App SDK failed to suspend activities&lt;br /&gt;
|-&lt;br /&gt;
| 1018 || ERROR_INVALID_PARAMETERS || App SDK invalid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 1019 || ERROR_INVALID_STATE || App SDK called in incorrect state&lt;br /&gt;
|-&lt;br /&gt;
| 1020 || ERROR_FAILED_PROCESS_PLAYHEAD || App SDK failed processing playhead position&lt;br /&gt;
|-&lt;br /&gt;
| 1021 || ERROR_FAILED_PROCESS_METADATA || App SDK failed processing not-null, syntax valid JSON metadada&lt;br /&gt;
|-&lt;br /&gt;
| 1022 || ERROR_FAILED_PROCESS_STOP || App SDK failed processing stop&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
'''App SDK Event Codes '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2000 || EVENT_INITIATE || App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || EVENT_STARTUP || App SDK has started up. It will happen only after App SDK has received a valid config file. This is the location in the code to acquire the value of [[userOptOutURLString()]].&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || EVENT_SHUTDOWN || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1066</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1066"/>
		<updated>2017-07-12T19:51:51Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* App SDK Event Codes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== AppApiErrorCode ==&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1065</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1065"/>
		<updated>2017-07-12T19:51:38Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* App SDK Error Codes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Event Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== AppApiErrorCode ==&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1064</id>
		<title>Android SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1064"/>
		<updated>2017-07-12T19:50:27Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* App SDK Event Codes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*Create and initialize an instance object of &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class.&lt;br /&gt;
*The player application can use this object to collect HLS timed metadata through a [[sendID3()]] call.&lt;br /&gt;
The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package. It inherits from the closeable interface and exposes the public APIs the client’s app will use. Below is the declaration of the &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class: &amp;lt;code&amp;gt;public class AppSdk implements Closeable&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Up Development Environment ==&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Setting up in Eclipse IDE ===&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-properties-drm.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
&lt;br /&gt;
'''Library''':&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
'''Classes/package''':&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
 &lt;br /&gt;
=== Setting up in Android Studio IDE ===&lt;br /&gt;
Launch '''Android Studio''' and select '''Import project (Eclipse ADT)'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-setup-launch.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Browse for project destination directory and click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-import-project.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Go to '''File &amp;gt; Project Structure &amp;gt; App &amp;gt; Dependencies'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-pro-structure.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Click '''+''' to add library dependency.&lt;br /&gt;
&lt;br /&gt;
Select '''play-services''' and click '''OK'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-choose-library.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information, refer to https://developer.android.com/google/play-services/setup.html&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Android Application Life Cycle with respect to Nielsen App SDK ===&lt;br /&gt;
[[File:andr-init-img1.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 1: App SDK initialization ===&lt;br /&gt;
==== For API version 4.0.0 and above ====&lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject config = null;&lt;br /&gt;
 &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;uat-cert&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;INFO&amp;quot;) // only for debug builds&lt;br /&gt;
          .put(&amp;quot;custom_key1&amp;quot;, &amp;quot;custom_value1&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;custom_key2&amp;quot;, &amp;quot;custom_value2&amp;quot;);&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
==== Android Application Life Cycle with respect to Nielsen App SDK ====&lt;br /&gt;
[[File:andr-radioandvideo-app.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 2: App SDK libraries inclusion in project ===&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&lt;br /&gt;
*Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Nielsen App SDK Streaming Sessions ===&lt;br /&gt;
After ensuring that the SDK object has been initialized, link the streaming session APIs. The next steps are:&lt;br /&gt;
*Call [[play()]] when starting or resuming a streaming session. Use the channelName parameter to pass channel descriptor information. The channel name field is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.) which must be inserted on a JSON string.&lt;br /&gt;
*Load the CMS metadata by calling the [[loadMetadata()]] on the SDK object.&lt;br /&gt;
*Call [[stop()]] when ending or pausing a viewing session.&lt;br /&gt;
*During session playback, call the SDK [[setPlayheadPosition()]] and / or [[sendID3()]]&lt;br /&gt;
**Call [[setPlayheadPosition()]] every one second until the stream is stopped or paused. Normally this happens on Digital Audio measurements.&lt;br /&gt;
**Call [[sendID3()]] if the client relies on the Nielsen ID3 tags for its measurements; this call should happen whenever a new Nielsen ID3 metadata is available for processing. Normally this happens on DTVR and ID3 measurements.&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
*The client’s app must clearly identify the mode of operation (live vs. VOD) and stick to the type of playhead coordinates until the playback is completed. The client must reliably provide the appropriated playhead position value depending on the type of content streamed.&lt;br /&gt;
*If streaming live video content, the client must pass the current UTC time in seconds as playhead position.&lt;br /&gt;
*If streaming VOD (video on demand), the client must stream the offset from the beginning of the file as playhead position.&lt;br /&gt;
*For all Digital Audio listening, the client must pass the current UTC time in seconds as playhead position, regardless of station type.&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extracting ID3 tags from Android Players ===&lt;br /&gt;
==== ID3 Support Matrix ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Player Name !! Minimum supported version !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Android Native Media Player || Android 6 || Android 6 Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags, generates TimedMetaData.&lt;br /&gt;
|-&lt;br /&gt;
| Google ExoPlayer || Android 4.1 ||&lt;br /&gt;
|-&lt;br /&gt;
| Brightcove Player || Android 4.1 || Support for Android versions 2.3.3 and 4.0 is now deprecated. Learn more about why Brightcove is removing support for these versions as of January 1, 2016 in this [https://support.brightcove.com/en/perform/docs/announcement-brightcove-sdk-android-version-support|announcement]&lt;br /&gt;
|-&lt;br /&gt;
| Adobe PrimeTime Player || Android 4.2 ||&lt;br /&gt;
|-&lt;br /&gt;
| VisualOn Player || Android 2.3 || Android 5 is the latest supported version&lt;br /&gt;
|-&lt;br /&gt;
| NexStream Player || Android 1.6 || Supported till Android 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Android Native Media Player ====&lt;br /&gt;
As the Android Media Player versions (prior to Android 6 / Android API 23) do not support ID3, Nielsen has created a library that becomes an extension to the media player, thus MPX. This library extracts the ID3 tags and sends them to the app. For more information on how to use the MPX component, refer to the Nielsen-supplied sample application.&lt;br /&gt;
&lt;br /&gt;
Starting from '''Android 6 (Android API 23)''', Android Native Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags generate TimedMetadata. Once the HLS video starts, call onTimedMetaDataAvailable() as and when the player observes a TimedMetadata (ID3 tag).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;@Override&lt;br /&gt;
   public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data)&lt;br /&gt;
     {&lt;br /&gt;
       byte[] iD3PayloadArray = data.getMetaData();&lt;br /&gt;
       String iD3Payload = new String(iD3PayloadArray, StandardCharsets.UTF_8);&lt;br /&gt;
       if (null != iD3Payload &amp;amp;&amp;amp; iD3Payload.contains(&amp;quot;www.nielsen.com&amp;quot;))&lt;br /&gt;
         {&lt;br /&gt;
           int index = iD3Payload.indexOf(&amp;quot;www.nielsen.com&amp;quot;);&lt;br /&gt;
           String id3String = iD3Payload.substring(index, (index + 249));&lt;br /&gt;
           Log.d(TAG, &amp;quot;TimedMetaData ID3 Tag:&amp;quot; + id3String);&lt;br /&gt;
           appProcessID3tag(id3String);&lt;br /&gt;
         }&lt;br /&gt;
     }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ExoPlayer ====&lt;br /&gt;
he SDK is designed around an event-driven architecture where components emit events to allow other components to listen and respond to state changes.&lt;br /&gt;
&lt;br /&gt;
'''Player SDK Classes used:'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;com.google.android.exoplayer.demo.player.DemoPlayer&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since Nielsen App SDK is interested in extracting the Timed Metadata (ID3 Tags) in HLS and VOD on the EXO Player, trace the ID3_TAG emitted during video content played using EXOPlayer component as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;DemoPlayer implements ExoPlayer.Listener&lt;br /&gt;
—————————————————–&lt;br /&gt;
/**&lt;br /&gt;
* A listener for receiving ID3 metadata parsed from the media stream.&lt;br /&gt;
*/&lt;br /&gt;
public interface Id3MetadataListener&lt;br /&gt;
{&lt;br /&gt;
  void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata);&lt;br /&gt;
}&lt;br /&gt;
——————————————————-&lt;br /&gt;
MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String,&lt;br /&gt;
Object&amp;gt;&amp;gt; getId3MetadataRenderer()&lt;br /&gt;
  {&lt;br /&gt;
    return new MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;()&lt;br /&gt;
      {&lt;br /&gt;
        @Override&lt;br /&gt;
        public void onMetadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
          {&lt;br /&gt;
            if (id3MetadataListener != null)&lt;br /&gt;
              {&lt;br /&gt;
                id3MetadataListener.onId3Metadata(metadata);&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      };&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also in ''Player.java'' class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;Player implements DemoPlayer.Id3MetadataListener&lt;br /&gt;
—————————————————–&lt;br /&gt;
@SuppressWarnings(&amp;quot;rawtypes&amp;quot;)&lt;br /&gt;
@Override&lt;br /&gt;
public void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
{&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
      for (Object o : metadata.entrySet())&lt;br /&gt;
        {&lt;br /&gt;
          Map.Entry pairs = (Map.Entry) o;&lt;br /&gt;
          if (metadata.containsKey(TxxxMetadata.TYPE))&lt;br /&gt;
            {&lt;br /&gt;
              TxxxMetadata txxxMetadata = (TxxxMetadata) metadata&lt;br /&gt;
              .get(TxxxMetadata.TYPE);&lt;br /&gt;
            }&lt;br /&gt;
          else&lt;br /&gt;
            {&lt;br /&gt;
              String aStr = new String((byte[]) pairs.getValue());&lt;br /&gt;
              MainActivity.mAppSdk.sendID3(aStr);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  catch (Exception e)&lt;br /&gt;
    {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      Log.d(TAG, &amp;quot;onId3Metadata(): No Id3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-exo-retrievingID3tags.png|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Brightcove Player ====&lt;br /&gt;
While the Brightcove player plays the content, EventListener triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;SeamlessVideoDisplayComponent.ID3_TAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;brightcoveVideoView.getEventEmitter().on(SeamlessVideoDisplayComponent.ID3_TAG, new EventListener()&lt;br /&gt;
  {&lt;br /&gt;
    public void processEvent(Event event)&lt;br /&gt;
      {&lt;br /&gt;
        NlsId3Tag nlsID3 = new NlsId3Tag(event.properties.get(SeamlessVideoDisplayComponent.ID3_DATA).toString());&lt;br /&gt;
        Log.w(&amp;quot;ID3&amp;quot;, nlsID3.NlsPayload);&lt;br /&gt;
        // Sent ID3 Tags to App&lt;br /&gt;
        appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      }&lt;br /&gt;
      });&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Adobe PrimeTime Player ====&lt;br /&gt;
While the Adobe PrimeTime player plays the content, MediaPlayer.PlaybackEventListener triggers a callback when an ID3 packet is received (onTimedMetadata). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetadata(TimedMetadata id3Metadata)&lt;br /&gt;
{&lt;br /&gt;
  NlsId3Tag nlsID3 = new NlsId3Tag(id3Metadata.getMetadata().toString());&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;ID3 Timed Data –&amp;gt; &amp;quot; + nlsID3.NlsPayload);&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;PayLoad Size –&amp;gt; &amp;quot; + nlsID3.NlsPayload.length());&lt;br /&gt;
  appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== VisualOn Player ====&lt;br /&gt;
While the VisualOn player plays the content, &amp;lt;code&amp;gt;VOCommonPlayerListener&amp;lt;/code&amp;gt; triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;case VO_OSMP_SRC_CB_CUSTOMER_TAG:&lt;br /&gt;
{&lt;br /&gt;
  VO_OSMP_SRC_CUSTOMERTAGID tag = VO_OSMP_SRC_CUSTOMERTAGID.valueOf(nParam1);&lt;br /&gt;
  switch (tag)&lt;br /&gt;
    {&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG:&lt;br /&gt;
      // do something with this tag&lt;br /&gt;
      int time = nParam2;&lt;br /&gt;
      byte[] b = (byte[]) obj;&lt;br /&gt;
      String s = new String(b);&lt;br /&gt;
      NlsId3Tag nlsID3 = new NlsId3Tag(b);&lt;br /&gt;
      // Sent ID3 Tags to App&lt;br /&gt;
      appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      if (appid3If != null)&lt;br /&gt;
      appid3If.onId3(nlsID3.NlsPayload);&lt;br /&gt;
      break;&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_MAX:&lt;br /&gt;
      // ignore this type of tag&lt;br /&gt;
      break;&lt;br /&gt;
      default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
      break;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== NextStream Player ====&lt;br /&gt;
ID3 tags will be received in the NexStream Player through &amp;lt;code&amp;gt;onTimedMetaRenderRender(NexPlayer mp,NexID3TagInformation metadata)&amp;lt;/code&amp;gt; callback API. A sample implementation for the callback is shown below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetaRenderRender(NexPlayer mp, NexID3TagInformation m)&lt;br /&gt;
  {&lt;br /&gt;
    text = m.getPrivateFrame();&lt;br /&gt;
    if (text != null)&lt;br /&gt;
      {&lt;br /&gt;
        data = text.getTextData();&lt;br /&gt;
        if (data != null)&lt;br /&gt;
          {&lt;br /&gt;
            // make sure to identify the beginning  of  the&lt;br /&gt;
            // Nielsen ID3 tag payload by searching for the&lt;br /&gt;
            // &amp;quot;www.nielsen.com&amp;quot; string on the ID3 tag and&lt;br /&gt;
            // passing to the App SDK all information that&lt;br /&gt;
            // follows. It should be:&lt;br /&gt;
            // nlsPayload = &amp;quot;www.nielsen.com&amp;quot; + dataFollowing&lt;br /&gt;
            nlsPayload = getDataAfterWwwNielsenCom(data);&lt;br /&gt;
            if (nlsPayload!= NULL)&lt;br /&gt;
            mAppSdk.sendID3(nlsPayload);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[sendID3()]] sends the extracted Nielsen ID3 payload to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
== Android SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[AppSDK()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadmetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3()]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[setPlayheadPosition()]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOutURLString()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getOptOutStatus()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi()]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getAppDisable()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query if the SDK is disabled or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastEvent()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last status&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastError()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last error&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[isValid()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to check if the SDK was successfully instantiated or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getMeterVersion()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getNielsenId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getDeviceId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current device id.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInBackground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app going to background.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInForeground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app coming to foreground&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[setDebug()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-andr.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''5.1.1.18 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14, skip ahead to: [[#Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14|Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18, Opt-Out related behavior has been changed in the following ways:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Version 5.1.1.18 or above, refer to documentation above ([[#Opt-out Android SDK Version 5.1.1.18 or above|Opt-out Android SDK Version 5.1.1.18 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**Capture user’s selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Opt Out of Ads for Personalization for the latest versions of the SDK (5.1.1.18 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Opt Out of Ads for Personalization&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in Google Play Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample Google Play Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
Constants with predefined error codes which the AppSdk object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public static final int ERROR_FAILED_CREATE_URL_STRING = 1001;&lt;br /&gt;
// failed generating ping string due to error on parsing&lt;br /&gt;
// description – include last error message from URL parser&lt;br /&gt;
public static final int ERROR_FAILED_RECEIVE_CONFIG = 1002;&lt;br /&gt;
// failed to receive configuration file from Census&lt;br /&gt;
// description – on 5th time, it will log event and keep requesting config 10 min apart&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_CONFIG = 1003;&lt;br /&gt;
// failed parsing the config file JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_PLAY = 1004;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_METADATA = 1005;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include JSON error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_GENERATING_PING = 1006;&lt;br /&gt;
// failed creating ping before adding it to the UPLOAD table)&lt;br /&gt;
// description – include ping nol_url index, cadence to identify ping&lt;br /&gt;
public static final int ERROR_FAILED_PROCESSOR_START = 1007;&lt;br /&gt;
// failed starting data processor thread. Normally, that means a product&lt;br /&gt;
// description – include processor that failed to start&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_ID3 = 1008;&lt;br /&gt;
// failed processing data on a data processor. Normally, that means the input to a product&lt;br /&gt;
// description – include processor and data that failed to process (ID3 tag on a MTVR impression, for example)&lt;br /&gt;
public static final int ERROR_FAILED_HTTP_SEND = 1009;&lt;br /&gt;
// failed sending HTTP or HTTPS requests&lt;br /&gt;
// description – include HTTP error number&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_PING = 1010;&lt;br /&gt;
// failed sending pings (on ANDROID, the ping on the UPLOAD table)&lt;br /&gt;
// description – include ping up to 80 char from the end&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_TSV = 1011;&lt;br /&gt;
// failed sending TSV requests&lt;br /&gt;
// description – include TSV request message&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_STATION_ID = 1012;&lt;br /&gt;
// failed sending StationId requests&lt;br /&gt;
// description – include Station ID request message&lt;br /&gt;
public static final int ERROR_FAILED_ACCESSING_DB = 1013;&lt;br /&gt;
// failed read/write from/to database table&lt;br /&gt;
// description – include SQL statement and data and SQLite error number/message&lt;br /&gt;
public static final int ERROR_CHANGED_DEVICE_ID = 1014;&lt;br /&gt;
// device ID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_CHANGED_NUID = 1015;&lt;br /&gt;
// NUID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_SDK_NOT_INITIALIZED = 1016;&lt;br /&gt;
// App SDK initialization failed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_SDK_SUSPEND = 1017;&lt;br /&gt;
// App SDK failed to suspend activities&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_PARAMETERS = 1018;&lt;br /&gt;
// App SDK invalid parameters&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_STATE = 1019;&lt;br /&gt;
// App SDK called in incorrect state&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_PLAYHEAD = 1020;&lt;br /&gt;
// App SDK failed processing playhead position&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_METADATA = 1021;&lt;br /&gt;
// App SDK failed processing not-null, syntax valid JSON metadada&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_STOP = 1022;&lt;br /&gt;
// App SDK failed processing stop&lt;br /&gt;
// description – none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
'''App SDK Event Codes '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2000 || EVENT_INITIATE || App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || EVENT_STARTUP || App SDK has started up. It will happen only after App SDK has received a valid config file. This is the location in the code to acquire the value of [[userOptOutURLString()]].&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || EVENT_SHUTDOWN || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1063</id>
		<title>Android SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1063"/>
		<updated>2017-07-12T19:46:36Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Nielsen Privacy Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*Create and initialize an instance object of &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class.&lt;br /&gt;
*The player application can use this object to collect HLS timed metadata through a [[sendID3()]] call.&lt;br /&gt;
The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package. It inherits from the closeable interface and exposes the public APIs the client’s app will use. Below is the declaration of the &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class: &amp;lt;code&amp;gt;public class AppSdk implements Closeable&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Up Development Environment ==&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Setting up in Eclipse IDE ===&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-properties-drm.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
&lt;br /&gt;
'''Library''':&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
'''Classes/package''':&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
 &lt;br /&gt;
=== Setting up in Android Studio IDE ===&lt;br /&gt;
Launch '''Android Studio''' and select '''Import project (Eclipse ADT)'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-setup-launch.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Browse for project destination directory and click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-import-project.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Go to '''File &amp;gt; Project Structure &amp;gt; App &amp;gt; Dependencies'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-pro-structure.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Click '''+''' to add library dependency.&lt;br /&gt;
&lt;br /&gt;
Select '''play-services''' and click '''OK'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-choose-library.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information, refer to https://developer.android.com/google/play-services/setup.html&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Android Application Life Cycle with respect to Nielsen App SDK ===&lt;br /&gt;
[[File:andr-init-img1.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 1: App SDK initialization ===&lt;br /&gt;
==== For API version 4.0.0 and above ====&lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject config = null;&lt;br /&gt;
 &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;uat-cert&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;INFO&amp;quot;) // only for debug builds&lt;br /&gt;
          .put(&amp;quot;custom_key1&amp;quot;, &amp;quot;custom_value1&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;custom_key2&amp;quot;, &amp;quot;custom_value2&amp;quot;);&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
==== Android Application Life Cycle with respect to Nielsen App SDK ====&lt;br /&gt;
[[File:andr-radioandvideo-app.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 2: App SDK libraries inclusion in project ===&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&lt;br /&gt;
*Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Nielsen App SDK Streaming Sessions ===&lt;br /&gt;
After ensuring that the SDK object has been initialized, link the streaming session APIs. The next steps are:&lt;br /&gt;
*Call [[play()]] when starting or resuming a streaming session. Use the channelName parameter to pass channel descriptor information. The channel name field is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.) which must be inserted on a JSON string.&lt;br /&gt;
*Load the CMS metadata by calling the [[loadMetadata()]] on the SDK object.&lt;br /&gt;
*Call [[stop()]] when ending or pausing a viewing session.&lt;br /&gt;
*During session playback, call the SDK [[setPlayheadPosition()]] and / or [[sendID3()]]&lt;br /&gt;
**Call [[setPlayheadPosition()]] every one second until the stream is stopped or paused. Normally this happens on Digital Audio measurements.&lt;br /&gt;
**Call [[sendID3()]] if the client relies on the Nielsen ID3 tags for its measurements; this call should happen whenever a new Nielsen ID3 metadata is available for processing. Normally this happens on DTVR and ID3 measurements.&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
*The client’s app must clearly identify the mode of operation (live vs. VOD) and stick to the type of playhead coordinates until the playback is completed. The client must reliably provide the appropriated playhead position value depending on the type of content streamed.&lt;br /&gt;
*If streaming live video content, the client must pass the current UTC time in seconds as playhead position.&lt;br /&gt;
*If streaming VOD (video on demand), the client must stream the offset from the beginning of the file as playhead position.&lt;br /&gt;
*For all Digital Audio listening, the client must pass the current UTC time in seconds as playhead position, regardless of station type.&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extracting ID3 tags from Android Players ===&lt;br /&gt;
==== ID3 Support Matrix ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Player Name !! Minimum supported version !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Android Native Media Player || Android 6 || Android 6 Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags, generates TimedMetaData.&lt;br /&gt;
|-&lt;br /&gt;
| Google ExoPlayer || Android 4.1 ||&lt;br /&gt;
|-&lt;br /&gt;
| Brightcove Player || Android 4.1 || Support for Android versions 2.3.3 and 4.0 is now deprecated. Learn more about why Brightcove is removing support for these versions as of January 1, 2016 in this [https://support.brightcove.com/en/perform/docs/announcement-brightcove-sdk-android-version-support|announcement]&lt;br /&gt;
|-&lt;br /&gt;
| Adobe PrimeTime Player || Android 4.2 ||&lt;br /&gt;
|-&lt;br /&gt;
| VisualOn Player || Android 2.3 || Android 5 is the latest supported version&lt;br /&gt;
|-&lt;br /&gt;
| NexStream Player || Android 1.6 || Supported till Android 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Android Native Media Player ====&lt;br /&gt;
As the Android Media Player versions (prior to Android 6 / Android API 23) do not support ID3, Nielsen has created a library that becomes an extension to the media player, thus MPX. This library extracts the ID3 tags and sends them to the app. For more information on how to use the MPX component, refer to the Nielsen-supplied sample application.&lt;br /&gt;
&lt;br /&gt;
Starting from '''Android 6 (Android API 23)''', Android Native Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags generate TimedMetadata. Once the HLS video starts, call onTimedMetaDataAvailable() as and when the player observes a TimedMetadata (ID3 tag).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;@Override&lt;br /&gt;
   public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data)&lt;br /&gt;
     {&lt;br /&gt;
       byte[] iD3PayloadArray = data.getMetaData();&lt;br /&gt;
       String iD3Payload = new String(iD3PayloadArray, StandardCharsets.UTF_8);&lt;br /&gt;
       if (null != iD3Payload &amp;amp;&amp;amp; iD3Payload.contains(&amp;quot;www.nielsen.com&amp;quot;))&lt;br /&gt;
         {&lt;br /&gt;
           int index = iD3Payload.indexOf(&amp;quot;www.nielsen.com&amp;quot;);&lt;br /&gt;
           String id3String = iD3Payload.substring(index, (index + 249));&lt;br /&gt;
           Log.d(TAG, &amp;quot;TimedMetaData ID3 Tag:&amp;quot; + id3String);&lt;br /&gt;
           appProcessID3tag(id3String);&lt;br /&gt;
         }&lt;br /&gt;
     }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ExoPlayer ====&lt;br /&gt;
he SDK is designed around an event-driven architecture where components emit events to allow other components to listen and respond to state changes.&lt;br /&gt;
&lt;br /&gt;
'''Player SDK Classes used:'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;com.google.android.exoplayer.demo.player.DemoPlayer&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since Nielsen App SDK is interested in extracting the Timed Metadata (ID3 Tags) in HLS and VOD on the EXO Player, trace the ID3_TAG emitted during video content played using EXOPlayer component as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;DemoPlayer implements ExoPlayer.Listener&lt;br /&gt;
—————————————————–&lt;br /&gt;
/**&lt;br /&gt;
* A listener for receiving ID3 metadata parsed from the media stream.&lt;br /&gt;
*/&lt;br /&gt;
public interface Id3MetadataListener&lt;br /&gt;
{&lt;br /&gt;
  void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata);&lt;br /&gt;
}&lt;br /&gt;
——————————————————-&lt;br /&gt;
MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String,&lt;br /&gt;
Object&amp;gt;&amp;gt; getId3MetadataRenderer()&lt;br /&gt;
  {&lt;br /&gt;
    return new MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;()&lt;br /&gt;
      {&lt;br /&gt;
        @Override&lt;br /&gt;
        public void onMetadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
          {&lt;br /&gt;
            if (id3MetadataListener != null)&lt;br /&gt;
              {&lt;br /&gt;
                id3MetadataListener.onId3Metadata(metadata);&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      };&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also in ''Player.java'' class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;Player implements DemoPlayer.Id3MetadataListener&lt;br /&gt;
—————————————————–&lt;br /&gt;
@SuppressWarnings(&amp;quot;rawtypes&amp;quot;)&lt;br /&gt;
@Override&lt;br /&gt;
public void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
{&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
      for (Object o : metadata.entrySet())&lt;br /&gt;
        {&lt;br /&gt;
          Map.Entry pairs = (Map.Entry) o;&lt;br /&gt;
          if (metadata.containsKey(TxxxMetadata.TYPE))&lt;br /&gt;
            {&lt;br /&gt;
              TxxxMetadata txxxMetadata = (TxxxMetadata) metadata&lt;br /&gt;
              .get(TxxxMetadata.TYPE);&lt;br /&gt;
            }&lt;br /&gt;
          else&lt;br /&gt;
            {&lt;br /&gt;
              String aStr = new String((byte[]) pairs.getValue());&lt;br /&gt;
              MainActivity.mAppSdk.sendID3(aStr);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  catch (Exception e)&lt;br /&gt;
    {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      Log.d(TAG, &amp;quot;onId3Metadata(): No Id3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-exo-retrievingID3tags.png|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Brightcove Player ====&lt;br /&gt;
While the Brightcove player plays the content, EventListener triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;SeamlessVideoDisplayComponent.ID3_TAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;brightcoveVideoView.getEventEmitter().on(SeamlessVideoDisplayComponent.ID3_TAG, new EventListener()&lt;br /&gt;
  {&lt;br /&gt;
    public void processEvent(Event event)&lt;br /&gt;
      {&lt;br /&gt;
        NlsId3Tag nlsID3 = new NlsId3Tag(event.properties.get(SeamlessVideoDisplayComponent.ID3_DATA).toString());&lt;br /&gt;
        Log.w(&amp;quot;ID3&amp;quot;, nlsID3.NlsPayload);&lt;br /&gt;
        // Sent ID3 Tags to App&lt;br /&gt;
        appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      }&lt;br /&gt;
      });&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Adobe PrimeTime Player ====&lt;br /&gt;
While the Adobe PrimeTime player plays the content, MediaPlayer.PlaybackEventListener triggers a callback when an ID3 packet is received (onTimedMetadata). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetadata(TimedMetadata id3Metadata)&lt;br /&gt;
{&lt;br /&gt;
  NlsId3Tag nlsID3 = new NlsId3Tag(id3Metadata.getMetadata().toString());&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;ID3 Timed Data –&amp;gt; &amp;quot; + nlsID3.NlsPayload);&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;PayLoad Size –&amp;gt; &amp;quot; + nlsID3.NlsPayload.length());&lt;br /&gt;
  appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== VisualOn Player ====&lt;br /&gt;
While the VisualOn player plays the content, &amp;lt;code&amp;gt;VOCommonPlayerListener&amp;lt;/code&amp;gt; triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;case VO_OSMP_SRC_CB_CUSTOMER_TAG:&lt;br /&gt;
{&lt;br /&gt;
  VO_OSMP_SRC_CUSTOMERTAGID tag = VO_OSMP_SRC_CUSTOMERTAGID.valueOf(nParam1);&lt;br /&gt;
  switch (tag)&lt;br /&gt;
    {&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG:&lt;br /&gt;
      // do something with this tag&lt;br /&gt;
      int time = nParam2;&lt;br /&gt;
      byte[] b = (byte[]) obj;&lt;br /&gt;
      String s = new String(b);&lt;br /&gt;
      NlsId3Tag nlsID3 = new NlsId3Tag(b);&lt;br /&gt;
      // Sent ID3 Tags to App&lt;br /&gt;
      appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      if (appid3If != null)&lt;br /&gt;
      appid3If.onId3(nlsID3.NlsPayload);&lt;br /&gt;
      break;&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_MAX:&lt;br /&gt;
      // ignore this type of tag&lt;br /&gt;
      break;&lt;br /&gt;
      default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
      break;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== NextStream Player ====&lt;br /&gt;
ID3 tags will be received in the NexStream Player through &amp;lt;code&amp;gt;onTimedMetaRenderRender(NexPlayer mp,NexID3TagInformation metadata)&amp;lt;/code&amp;gt; callback API. A sample implementation for the callback is shown below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetaRenderRender(NexPlayer mp, NexID3TagInformation m)&lt;br /&gt;
  {&lt;br /&gt;
    text = m.getPrivateFrame();&lt;br /&gt;
    if (text != null)&lt;br /&gt;
      {&lt;br /&gt;
        data = text.getTextData();&lt;br /&gt;
        if (data != null)&lt;br /&gt;
          {&lt;br /&gt;
            // make sure to identify the beginning  of  the&lt;br /&gt;
            // Nielsen ID3 tag payload by searching for the&lt;br /&gt;
            // &amp;quot;www.nielsen.com&amp;quot; string on the ID3 tag and&lt;br /&gt;
            // passing to the App SDK all information that&lt;br /&gt;
            // follows. It should be:&lt;br /&gt;
            // nlsPayload = &amp;quot;www.nielsen.com&amp;quot; + dataFollowing&lt;br /&gt;
            nlsPayload = getDataAfterWwwNielsenCom(data);&lt;br /&gt;
            if (nlsPayload!= NULL)&lt;br /&gt;
            mAppSdk.sendID3(nlsPayload);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[sendID3()]] sends the extracted Nielsen ID3 payload to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
== Android SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[AppSDK()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadmetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3()]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[setPlayheadPosition()]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOutURLString()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getOptOutStatus()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi()]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getAppDisable()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query if the SDK is disabled or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastEvent()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last status&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastError()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last error&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[isValid()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to check if the SDK was successfully instantiated or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getMeterVersion()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getNielsenId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getDeviceId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current device id.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInBackground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app going to background.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInForeground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app coming to foreground&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[setDebug()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-andr.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''5.1.1.18 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14, skip ahead to: [[#Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14|Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18, Opt-Out related behavior has been changed in the following ways:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Version 5.1.1.18 or above, refer to documentation above ([[#Opt-out Android SDK Version 5.1.1.18 or above|Opt-out Android SDK Version 5.1.1.18 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**Capture user’s selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Opt Out of Ads for Personalization for the latest versions of the SDK (5.1.1.18 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Opt Out of Ads for Personalization&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in Google Play Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample Google Play Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
Constants with predefined error codes which the AppSdk object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public static final int ERROR_FAILED_CREATE_URL_STRING = 1001;&lt;br /&gt;
// failed generating ping string due to error on parsing&lt;br /&gt;
// description – include last error message from URL parser&lt;br /&gt;
public static final int ERROR_FAILED_RECEIVE_CONFIG = 1002;&lt;br /&gt;
// failed to receive configuration file from Census&lt;br /&gt;
// description – on 5th time, it will log event and keep requesting config 10 min apart&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_CONFIG = 1003;&lt;br /&gt;
// failed parsing the config file JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_PLAY = 1004;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_METADATA = 1005;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include JSON error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_GENERATING_PING = 1006;&lt;br /&gt;
// failed creating ping before adding it to the UPLOAD table)&lt;br /&gt;
// description – include ping nol_url index, cadence to identify ping&lt;br /&gt;
public static final int ERROR_FAILED_PROCESSOR_START = 1007;&lt;br /&gt;
// failed starting data processor thread. Normally, that means a product&lt;br /&gt;
// description – include processor that failed to start&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_ID3 = 1008;&lt;br /&gt;
// failed processing data on a data processor. Normally, that means the input to a product&lt;br /&gt;
// description – include processor and data that failed to process (ID3 tag on a MTVR impression, for example)&lt;br /&gt;
public static final int ERROR_FAILED_HTTP_SEND = 1009;&lt;br /&gt;
// failed sending HTTP or HTTPS requests&lt;br /&gt;
// description – include HTTP error number&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_PING = 1010;&lt;br /&gt;
// failed sending pings (on ANDROID, the ping on the UPLOAD table)&lt;br /&gt;
// description – include ping up to 80 char from the end&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_TSV = 1011;&lt;br /&gt;
// failed sending TSV requests&lt;br /&gt;
// description – include TSV request message&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_STATION_ID = 1012;&lt;br /&gt;
// failed sending StationId requests&lt;br /&gt;
// description – include Station ID request message&lt;br /&gt;
public static final int ERROR_FAILED_ACCESSING_DB = 1013;&lt;br /&gt;
// failed read/write from/to database table&lt;br /&gt;
// description – include SQL statement and data and SQLite error number/message&lt;br /&gt;
public static final int ERROR_CHANGED_DEVICE_ID = 1014;&lt;br /&gt;
// device ID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_CHANGED_NUID = 1015;&lt;br /&gt;
// NUID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_SDK_NOT_INITIALIZED = 1016;&lt;br /&gt;
// App SDK initialization failed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_SDK_SUSPEND = 1017;&lt;br /&gt;
// App SDK failed to suspend activities&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_PARAMETERS = 1018;&lt;br /&gt;
// App SDK invalid parameters&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_STATE = 1019;&lt;br /&gt;
// App SDK called in incorrect state&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_PLAYHEAD = 1020;&lt;br /&gt;
// App SDK failed processing playhead position&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_METADATA = 1021;&lt;br /&gt;
// App SDK failed processing not-null, syntax valid JSON metadada&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_STOP = 1022;&lt;br /&gt;
// App SDK failed processing stop&lt;br /&gt;
// description – none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public static final int EVENT_INITIATE = 2000;&lt;br /&gt;
// App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
public static final int EVENT_STARTUP = 2001;&lt;br /&gt;
// App SDK has started up. It will happen only after App SDK has received a valid config file. This is the location in the code to acquire the value of userOptOutURLString().&lt;br /&gt;
public static final int EVENT_SHUTDOWN = 2002;&lt;br /&gt;
// App SDK is shutting down. It will happen just before App SDK is destroyed&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''App SDK Event Codes '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2000 || EVENT_INITIATE || App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || EVENT_STARTUP || App SDK has started up. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || EVENT_SHUTDOWN || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1062</id>
		<title>Android SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1062"/>
		<updated>2017-07-12T19:42:48Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Opt-Out Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*Create and initialize an instance object of &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class.&lt;br /&gt;
*The player application can use this object to collect HLS timed metadata through a [[sendID3()]] call.&lt;br /&gt;
The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package. It inherits from the closeable interface and exposes the public APIs the client’s app will use. Below is the declaration of the &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class: &amp;lt;code&amp;gt;public class AppSdk implements Closeable&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Up Development Environment ==&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Setting up in Eclipse IDE ===&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-properties-drm.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
&lt;br /&gt;
'''Library''':&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
'''Classes/package''':&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
 &lt;br /&gt;
=== Setting up in Android Studio IDE ===&lt;br /&gt;
Launch '''Android Studio''' and select '''Import project (Eclipse ADT)'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-setup-launch.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Browse for project destination directory and click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-import-project.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Go to '''File &amp;gt; Project Structure &amp;gt; App &amp;gt; Dependencies'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-pro-structure.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Click '''+''' to add library dependency.&lt;br /&gt;
&lt;br /&gt;
Select '''play-services''' and click '''OK'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-choose-library.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information, refer to https://developer.android.com/google/play-services/setup.html&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Android Application Life Cycle with respect to Nielsen App SDK ===&lt;br /&gt;
[[File:andr-init-img1.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 1: App SDK initialization ===&lt;br /&gt;
==== For API version 4.0.0 and above ====&lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject config = null;&lt;br /&gt;
 &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;uat-cert&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;INFO&amp;quot;) // only for debug builds&lt;br /&gt;
          .put(&amp;quot;custom_key1&amp;quot;, &amp;quot;custom_value1&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;custom_key2&amp;quot;, &amp;quot;custom_value2&amp;quot;);&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
==== Android Application Life Cycle with respect to Nielsen App SDK ====&lt;br /&gt;
[[File:andr-radioandvideo-app.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 2: App SDK libraries inclusion in project ===&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&lt;br /&gt;
*Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Nielsen App SDK Streaming Sessions ===&lt;br /&gt;
After ensuring that the SDK object has been initialized, link the streaming session APIs. The next steps are:&lt;br /&gt;
*Call [[play()]] when starting or resuming a streaming session. Use the channelName parameter to pass channel descriptor information. The channel name field is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.) which must be inserted on a JSON string.&lt;br /&gt;
*Load the CMS metadata by calling the [[loadMetadata()]] on the SDK object.&lt;br /&gt;
*Call [[stop()]] when ending or pausing a viewing session.&lt;br /&gt;
*During session playback, call the SDK [[setPlayheadPosition()]] and / or [[sendID3()]]&lt;br /&gt;
**Call [[setPlayheadPosition()]] every one second until the stream is stopped or paused. Normally this happens on Digital Audio measurements.&lt;br /&gt;
**Call [[sendID3()]] if the client relies on the Nielsen ID3 tags for its measurements; this call should happen whenever a new Nielsen ID3 metadata is available for processing. Normally this happens on DTVR and ID3 measurements.&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
*The client’s app must clearly identify the mode of operation (live vs. VOD) and stick to the type of playhead coordinates until the playback is completed. The client must reliably provide the appropriated playhead position value depending on the type of content streamed.&lt;br /&gt;
*If streaming live video content, the client must pass the current UTC time in seconds as playhead position.&lt;br /&gt;
*If streaming VOD (video on demand), the client must stream the offset from the beginning of the file as playhead position.&lt;br /&gt;
*For all Digital Audio listening, the client must pass the current UTC time in seconds as playhead position, regardless of station type.&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extracting ID3 tags from Android Players ===&lt;br /&gt;
==== ID3 Support Matrix ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Player Name !! Minimum supported version !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Android Native Media Player || Android 6 || Android 6 Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags, generates TimedMetaData.&lt;br /&gt;
|-&lt;br /&gt;
| Google ExoPlayer || Android 4.1 ||&lt;br /&gt;
|-&lt;br /&gt;
| Brightcove Player || Android 4.1 || Support for Android versions 2.3.3 and 4.0 is now deprecated. Learn more about why Brightcove is removing support for these versions as of January 1, 2016 in this [https://support.brightcove.com/en/perform/docs/announcement-brightcove-sdk-android-version-support|announcement]&lt;br /&gt;
|-&lt;br /&gt;
| Adobe PrimeTime Player || Android 4.2 ||&lt;br /&gt;
|-&lt;br /&gt;
| VisualOn Player || Android 2.3 || Android 5 is the latest supported version&lt;br /&gt;
|-&lt;br /&gt;
| NexStream Player || Android 1.6 || Supported till Android 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Android Native Media Player ====&lt;br /&gt;
As the Android Media Player versions (prior to Android 6 / Android API 23) do not support ID3, Nielsen has created a library that becomes an extension to the media player, thus MPX. This library extracts the ID3 tags and sends them to the app. For more information on how to use the MPX component, refer to the Nielsen-supplied sample application.&lt;br /&gt;
&lt;br /&gt;
Starting from '''Android 6 (Android API 23)''', Android Native Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags generate TimedMetadata. Once the HLS video starts, call onTimedMetaDataAvailable() as and when the player observes a TimedMetadata (ID3 tag).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;@Override&lt;br /&gt;
   public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data)&lt;br /&gt;
     {&lt;br /&gt;
       byte[] iD3PayloadArray = data.getMetaData();&lt;br /&gt;
       String iD3Payload = new String(iD3PayloadArray, StandardCharsets.UTF_8);&lt;br /&gt;
       if (null != iD3Payload &amp;amp;&amp;amp; iD3Payload.contains(&amp;quot;www.nielsen.com&amp;quot;))&lt;br /&gt;
         {&lt;br /&gt;
           int index = iD3Payload.indexOf(&amp;quot;www.nielsen.com&amp;quot;);&lt;br /&gt;
           String id3String = iD3Payload.substring(index, (index + 249));&lt;br /&gt;
           Log.d(TAG, &amp;quot;TimedMetaData ID3 Tag:&amp;quot; + id3String);&lt;br /&gt;
           appProcessID3tag(id3String);&lt;br /&gt;
         }&lt;br /&gt;
     }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ExoPlayer ====&lt;br /&gt;
he SDK is designed around an event-driven architecture where components emit events to allow other components to listen and respond to state changes.&lt;br /&gt;
&lt;br /&gt;
'''Player SDK Classes used:'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;com.google.android.exoplayer.demo.player.DemoPlayer&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since Nielsen App SDK is interested in extracting the Timed Metadata (ID3 Tags) in HLS and VOD on the EXO Player, trace the ID3_TAG emitted during video content played using EXOPlayer component as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;DemoPlayer implements ExoPlayer.Listener&lt;br /&gt;
—————————————————–&lt;br /&gt;
/**&lt;br /&gt;
* A listener for receiving ID3 metadata parsed from the media stream.&lt;br /&gt;
*/&lt;br /&gt;
public interface Id3MetadataListener&lt;br /&gt;
{&lt;br /&gt;
  void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata);&lt;br /&gt;
}&lt;br /&gt;
——————————————————-&lt;br /&gt;
MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String,&lt;br /&gt;
Object&amp;gt;&amp;gt; getId3MetadataRenderer()&lt;br /&gt;
  {&lt;br /&gt;
    return new MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;()&lt;br /&gt;
      {&lt;br /&gt;
        @Override&lt;br /&gt;
        public void onMetadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
          {&lt;br /&gt;
            if (id3MetadataListener != null)&lt;br /&gt;
              {&lt;br /&gt;
                id3MetadataListener.onId3Metadata(metadata);&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      };&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also in ''Player.java'' class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;Player implements DemoPlayer.Id3MetadataListener&lt;br /&gt;
—————————————————–&lt;br /&gt;
@SuppressWarnings(&amp;quot;rawtypes&amp;quot;)&lt;br /&gt;
@Override&lt;br /&gt;
public void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
{&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
      for (Object o : metadata.entrySet())&lt;br /&gt;
        {&lt;br /&gt;
          Map.Entry pairs = (Map.Entry) o;&lt;br /&gt;
          if (metadata.containsKey(TxxxMetadata.TYPE))&lt;br /&gt;
            {&lt;br /&gt;
              TxxxMetadata txxxMetadata = (TxxxMetadata) metadata&lt;br /&gt;
              .get(TxxxMetadata.TYPE);&lt;br /&gt;
            }&lt;br /&gt;
          else&lt;br /&gt;
            {&lt;br /&gt;
              String aStr = new String((byte[]) pairs.getValue());&lt;br /&gt;
              MainActivity.mAppSdk.sendID3(aStr);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  catch (Exception e)&lt;br /&gt;
    {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      Log.d(TAG, &amp;quot;onId3Metadata(): No Id3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-exo-retrievingID3tags.png|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Brightcove Player ====&lt;br /&gt;
While the Brightcove player plays the content, EventListener triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;SeamlessVideoDisplayComponent.ID3_TAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;brightcoveVideoView.getEventEmitter().on(SeamlessVideoDisplayComponent.ID3_TAG, new EventListener()&lt;br /&gt;
  {&lt;br /&gt;
    public void processEvent(Event event)&lt;br /&gt;
      {&lt;br /&gt;
        NlsId3Tag nlsID3 = new NlsId3Tag(event.properties.get(SeamlessVideoDisplayComponent.ID3_DATA).toString());&lt;br /&gt;
        Log.w(&amp;quot;ID3&amp;quot;, nlsID3.NlsPayload);&lt;br /&gt;
        // Sent ID3 Tags to App&lt;br /&gt;
        appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      }&lt;br /&gt;
      });&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Adobe PrimeTime Player ====&lt;br /&gt;
While the Adobe PrimeTime player plays the content, MediaPlayer.PlaybackEventListener triggers a callback when an ID3 packet is received (onTimedMetadata). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetadata(TimedMetadata id3Metadata)&lt;br /&gt;
{&lt;br /&gt;
  NlsId3Tag nlsID3 = new NlsId3Tag(id3Metadata.getMetadata().toString());&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;ID3 Timed Data –&amp;gt; &amp;quot; + nlsID3.NlsPayload);&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;PayLoad Size –&amp;gt; &amp;quot; + nlsID3.NlsPayload.length());&lt;br /&gt;
  appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== VisualOn Player ====&lt;br /&gt;
While the VisualOn player plays the content, &amp;lt;code&amp;gt;VOCommonPlayerListener&amp;lt;/code&amp;gt; triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;case VO_OSMP_SRC_CB_CUSTOMER_TAG:&lt;br /&gt;
{&lt;br /&gt;
  VO_OSMP_SRC_CUSTOMERTAGID tag = VO_OSMP_SRC_CUSTOMERTAGID.valueOf(nParam1);&lt;br /&gt;
  switch (tag)&lt;br /&gt;
    {&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG:&lt;br /&gt;
      // do something with this tag&lt;br /&gt;
      int time = nParam2;&lt;br /&gt;
      byte[] b = (byte[]) obj;&lt;br /&gt;
      String s = new String(b);&lt;br /&gt;
      NlsId3Tag nlsID3 = new NlsId3Tag(b);&lt;br /&gt;
      // Sent ID3 Tags to App&lt;br /&gt;
      appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      if (appid3If != null)&lt;br /&gt;
      appid3If.onId3(nlsID3.NlsPayload);&lt;br /&gt;
      break;&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_MAX:&lt;br /&gt;
      // ignore this type of tag&lt;br /&gt;
      break;&lt;br /&gt;
      default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
      break;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== NextStream Player ====&lt;br /&gt;
ID3 tags will be received in the NexStream Player through &amp;lt;code&amp;gt;onTimedMetaRenderRender(NexPlayer mp,NexID3TagInformation metadata)&amp;lt;/code&amp;gt; callback API. A sample implementation for the callback is shown below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetaRenderRender(NexPlayer mp, NexID3TagInformation m)&lt;br /&gt;
  {&lt;br /&gt;
    text = m.getPrivateFrame();&lt;br /&gt;
    if (text != null)&lt;br /&gt;
      {&lt;br /&gt;
        data = text.getTextData();&lt;br /&gt;
        if (data != null)&lt;br /&gt;
          {&lt;br /&gt;
            // make sure to identify the beginning  of  the&lt;br /&gt;
            // Nielsen ID3 tag payload by searching for the&lt;br /&gt;
            // &amp;quot;www.nielsen.com&amp;quot; string on the ID3 tag and&lt;br /&gt;
            // passing to the App SDK all information that&lt;br /&gt;
            // follows. It should be:&lt;br /&gt;
            // nlsPayload = &amp;quot;www.nielsen.com&amp;quot; + dataFollowing&lt;br /&gt;
            nlsPayload = getDataAfterWwwNielsenCom(data);&lt;br /&gt;
            if (nlsPayload!= NULL)&lt;br /&gt;
            mAppSdk.sendID3(nlsPayload);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[sendID3()]] sends the extracted Nielsen ID3 payload to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
== Android SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[AppSDK()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadmetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3()]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[setPlayheadPosition()]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOutURLString()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getOptOutStatus()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi()]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getAppDisable()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query if the SDK is disabled or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastEvent()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last status&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastError()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last error&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[isValid()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to check if the SDK was successfully instantiated or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getMeterVersion()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getNielsenId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getDeviceId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current device id.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInBackground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app going to background.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInForeground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app coming to foreground&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[setDebug()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-andr.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''5.1.1.18 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14, skip ahead to: [[#Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14|Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18, Opt-Out related behavior has been changed in the following ways:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Version 5.1.1.18 or above, refer to documentation above ([[#Opt-out Android SDK Version 5.1.1.18 or above|Opt-out Android SDK Version 5.1.1.18 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**Capture user’s selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
Constants with predefined error codes which the AppSdk object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public static final int ERROR_FAILED_CREATE_URL_STRING = 1001;&lt;br /&gt;
// failed generating ping string due to error on parsing&lt;br /&gt;
// description – include last error message from URL parser&lt;br /&gt;
public static final int ERROR_FAILED_RECEIVE_CONFIG = 1002;&lt;br /&gt;
// failed to receive configuration file from Census&lt;br /&gt;
// description – on 5th time, it will log event and keep requesting config 10 min apart&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_CONFIG = 1003;&lt;br /&gt;
// failed parsing the config file JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_PLAY = 1004;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_METADATA = 1005;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include JSON error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_GENERATING_PING = 1006;&lt;br /&gt;
// failed creating ping before adding it to the UPLOAD table)&lt;br /&gt;
// description – include ping nol_url index, cadence to identify ping&lt;br /&gt;
public static final int ERROR_FAILED_PROCESSOR_START = 1007;&lt;br /&gt;
// failed starting data processor thread. Normally, that means a product&lt;br /&gt;
// description – include processor that failed to start&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_ID3 = 1008;&lt;br /&gt;
// failed processing data on a data processor. Normally, that means the input to a product&lt;br /&gt;
// description – include processor and data that failed to process (ID3 tag on a MTVR impression, for example)&lt;br /&gt;
public static final int ERROR_FAILED_HTTP_SEND = 1009;&lt;br /&gt;
// failed sending HTTP or HTTPS requests&lt;br /&gt;
// description – include HTTP error number&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_PING = 1010;&lt;br /&gt;
// failed sending pings (on ANDROID, the ping on the UPLOAD table)&lt;br /&gt;
// description – include ping up to 80 char from the end&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_TSV = 1011;&lt;br /&gt;
// failed sending TSV requests&lt;br /&gt;
// description – include TSV request message&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_STATION_ID = 1012;&lt;br /&gt;
// failed sending StationId requests&lt;br /&gt;
// description – include Station ID request message&lt;br /&gt;
public static final int ERROR_FAILED_ACCESSING_DB = 1013;&lt;br /&gt;
// failed read/write from/to database table&lt;br /&gt;
// description – include SQL statement and data and SQLite error number/message&lt;br /&gt;
public static final int ERROR_CHANGED_DEVICE_ID = 1014;&lt;br /&gt;
// device ID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_CHANGED_NUID = 1015;&lt;br /&gt;
// NUID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_SDK_NOT_INITIALIZED = 1016;&lt;br /&gt;
// App SDK initialization failed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_SDK_SUSPEND = 1017;&lt;br /&gt;
// App SDK failed to suspend activities&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_PARAMETERS = 1018;&lt;br /&gt;
// App SDK invalid parameters&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_STATE = 1019;&lt;br /&gt;
// App SDK called in incorrect state&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_PLAYHEAD = 1020;&lt;br /&gt;
// App SDK failed processing playhead position&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_METADATA = 1021;&lt;br /&gt;
// App SDK failed processing not-null, syntax valid JSON metadada&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_STOP = 1022;&lt;br /&gt;
// App SDK failed processing stop&lt;br /&gt;
// description – none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public static final int EVENT_INITIATE = 2000;&lt;br /&gt;
// App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
public static final int EVENT_STARTUP = 2001;&lt;br /&gt;
// App SDK has started up. It will happen only after App SDK has received a valid config file. This is the location in the code to acquire the value of userOptOutURLString().&lt;br /&gt;
public static final int EVENT_SHUTDOWN = 2002;&lt;br /&gt;
// App SDK is shutting down. It will happen just before App SDK is destroyed&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''App SDK Event Codes '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2000 || EVENT_INITIATE || App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || EVENT_STARTUP || App SDK has started up. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || EVENT_SHUTDOWN || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1061</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1061"/>
		<updated>2017-07-12T19:41:44Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Opt-Out Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Event Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== AppApiErrorCode ==&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Error Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1060</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1060"/>
		<updated>2017-07-12T19:40:07Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Displaying Opt-Out in a WebView */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.17 and above.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.12, refer to [[#Legacy_Opt-Out|Legacy Opt-Out Implementation for iOS]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to opt out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ &lt;br /&gt;
  // Handle it gracefully and retry later&lt;br /&gt;
} &lt;br /&gt;
 &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
  // show the view to the user&lt;br /&gt;
  [self.view addSubview:optOutView]; &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS’ system setting – “Limit Ad Tracking”. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the “Limit Ad Tracking” setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out_iOS.jpg]]&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to “About Nielsen Measurement” page for the users. Include “About Nielsen Measurement” and '''Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy_policy_iOS.jpg]]&lt;br /&gt;
&lt;br /&gt;
* URL to this web page should be called from SDK and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen’s SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;@property (readonly) BOOL optOutStatus;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
* App should provide a UI control like ‘close’ or ‘back’ button to close the ‘WebView’ / External browser.&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== Constants / Enumerations ===&lt;br /&gt;
The following are the details of Delegate Implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by a Event: %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
   – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by an Error: %@&amp;quot;, error);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== TVOS Implementation ====&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the client should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products are not used to identify consumer in any way. They help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows.&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking2.png]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Legacy Opt-Out ====&lt;br /&gt;
'''Supported SDK Versions''': 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 5.1.1.17 or above, refer to [[#Limit Ad Tracking|Limit Ad Tracking iOS Implementation]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in ‘WebView’ within the app and NOT in any external browser.&lt;br /&gt;
** Opening the Opt-Out page in any external browser takes the application control out of the Nielsen App SDK context.&lt;br /&gt;
** As the App SDK does not expose any direct http/https interface to interact with the world to get the user selection on Privacy page, there will be no way to interact/send notification to the App SDK regarding the user selection.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
Below are the steps to implement user Opt-Out using UIWebView.&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
&lt;br /&gt;
'''Implement WebView with Nielsen Opt-Out URL'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The Nielsen Privacy Page appears using UIWebView&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Privacy Page'''&lt;br /&gt;
&lt;br /&gt;
[[File:privacy-policy.jpg]]&lt;br /&gt;
&lt;br /&gt;
* There are two links – one for Opt-Out and one for Opt-In. Click the required link.&lt;br /&gt;
* Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
* The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the ‘WebView’. In order to do this, the application needs to&lt;br /&gt;
** Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
** Capture user’s selection&lt;br /&gt;
** Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Capture and forward user selection'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the ‘WebView’ URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
* &amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user’s selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ is closed, pass the status returned from ‘WebView’ to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Event Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== AppApiErrorCode ==&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Error Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1059</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1059"/>
		<updated>2017-07-12T19:39:20Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Capture and forward user selection */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ // Handle it gracefully and retry later} else&lt;br /&gt;
{[optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
// show the view to the user&lt;br /&gt;
[self.view addSubview:optOutView]; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.17 and above.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.12, refer to [[#Legacy_Opt-Out|Legacy Opt-Out Implementation for iOS]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to opt out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ &lt;br /&gt;
  // Handle it gracefully and retry later&lt;br /&gt;
} &lt;br /&gt;
 &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
  // show the view to the user&lt;br /&gt;
  [self.view addSubview:optOutView]; &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS’ system setting – “Limit Ad Tracking”. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the “Limit Ad Tracking” setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out_iOS.jpg]]&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to “About Nielsen Measurement” page for the users. Include “About Nielsen Measurement” and '''Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy_policy_iOS.jpg]]&lt;br /&gt;
&lt;br /&gt;
* URL to this web page should be called from SDK and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen’s SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;@property (readonly) BOOL optOutStatus;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
* App should provide a UI control like ‘close’ or ‘back’ button to close the ‘WebView’ / External browser.&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== Constants / Enumerations ===&lt;br /&gt;
The following are the details of Delegate Implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by a Event: %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
   – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by an Error: %@&amp;quot;, error);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== TVOS Implementation ====&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the client should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products are not used to identify consumer in any way. They help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows.&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking2.png]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Legacy Opt-Out ====&lt;br /&gt;
'''Supported SDK Versions''': 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 5.1.1.17 or above, refer to [[#Limit Ad Tracking|Limit Ad Tracking iOS Implementation]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in ‘WebView’ within the app and NOT in any external browser.&lt;br /&gt;
** Opening the Opt-Out page in any external browser takes the application control out of the Nielsen App SDK context.&lt;br /&gt;
** As the App SDK does not expose any direct http/https interface to interact with the world to get the user selection on Privacy page, there will be no way to interact/send notification to the App SDK regarding the user selection.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
Below are the steps to implement user Opt-Out using UIWebView.&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
&lt;br /&gt;
'''Implement WebView with Nielsen Opt-Out URL'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The Nielsen Privacy Page appears using UIWebView&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Privacy Page'''&lt;br /&gt;
&lt;br /&gt;
[[File:privacy-policy.jpg]]&lt;br /&gt;
&lt;br /&gt;
* There are two links – one for Opt-Out and one for Opt-In. Click the required link.&lt;br /&gt;
* Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
* The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the ‘WebView’. In order to do this, the application needs to&lt;br /&gt;
** Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
** Capture user’s selection&lt;br /&gt;
** Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Capture and forward user selection'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the ‘WebView’ URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
* &amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user’s selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ is closed, pass the status returned from ‘WebView’ to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Event Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== AppApiErrorCode ==&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Error Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1058</id>
		<title>Android SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1058"/>
		<updated>2017-07-12T19:32:22Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Opt-Out Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*Create and initialize an instance object of &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class.&lt;br /&gt;
*The player application can use this object to collect HLS timed metadata through a [[sendID3()]] call.&lt;br /&gt;
The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package. It inherits from the closeable interface and exposes the public APIs the client’s app will use. Below is the declaration of the &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class: &amp;lt;code&amp;gt;public class AppSdk implements Closeable&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Up Development Environment ==&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Setting up in Eclipse IDE ===&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-properties-drm.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
&lt;br /&gt;
'''Library''':&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
'''Classes/package''':&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
 &lt;br /&gt;
=== Setting up in Android Studio IDE ===&lt;br /&gt;
Launch '''Android Studio''' and select '''Import project (Eclipse ADT)'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-setup-launch.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Browse for project destination directory and click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-import-project.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Go to '''File &amp;gt; Project Structure &amp;gt; App &amp;gt; Dependencies'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-pro-structure.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Click '''+''' to add library dependency.&lt;br /&gt;
&lt;br /&gt;
Select '''play-services''' and click '''OK'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-choose-library.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information, refer to https://developer.android.com/google/play-services/setup.html&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Android Application Life Cycle with respect to Nielsen App SDK ===&lt;br /&gt;
[[File:andr-init-img1.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 1: App SDK initialization ===&lt;br /&gt;
==== For API version 4.0.0 and above ====&lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject config = null;&lt;br /&gt;
 &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;uat-cert&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;INFO&amp;quot;) // only for debug builds&lt;br /&gt;
          .put(&amp;quot;custom_key1&amp;quot;, &amp;quot;custom_value1&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;custom_key2&amp;quot;, &amp;quot;custom_value2&amp;quot;);&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
==== Android Application Life Cycle with respect to Nielsen App SDK ====&lt;br /&gt;
[[File:andr-radioandvideo-app.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 2: App SDK libraries inclusion in project ===&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&lt;br /&gt;
*Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Nielsen App SDK Streaming Sessions ===&lt;br /&gt;
After ensuring that the SDK object has been initialized, link the streaming session APIs. The next steps are:&lt;br /&gt;
*Call [[play()]] when starting or resuming a streaming session. Use the channelName parameter to pass channel descriptor information. The channel name field is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.) which must be inserted on a JSON string.&lt;br /&gt;
*Load the CMS metadata by calling the [[loadMetadata()]] on the SDK object.&lt;br /&gt;
*Call [[stop()]] when ending or pausing a viewing session.&lt;br /&gt;
*During session playback, call the SDK [[setPlayheadPosition()]] and / or [[sendID3()]]&lt;br /&gt;
**Call [[setPlayheadPosition()]] every one second until the stream is stopped or paused. Normally this happens on Digital Audio measurements.&lt;br /&gt;
**Call [[sendID3()]] if the client relies on the Nielsen ID3 tags for its measurements; this call should happen whenever a new Nielsen ID3 metadata is available for processing. Normally this happens on DTVR and ID3 measurements.&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
*The client’s app must clearly identify the mode of operation (live vs. VOD) and stick to the type of playhead coordinates until the playback is completed. The client must reliably provide the appropriated playhead position value depending on the type of content streamed.&lt;br /&gt;
*If streaming live video content, the client must pass the current UTC time in seconds as playhead position.&lt;br /&gt;
*If streaming VOD (video on demand), the client must stream the offset from the beginning of the file as playhead position.&lt;br /&gt;
*For all Digital Audio listening, the client must pass the current UTC time in seconds as playhead position, regardless of station type.&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extracting ID3 tags from Android Players ===&lt;br /&gt;
==== ID3 Support Matrix ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Player Name !! Minimum supported version !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Android Native Media Player || Android 6 || Android 6 Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags, generates TimedMetaData.&lt;br /&gt;
|-&lt;br /&gt;
| Google ExoPlayer || Android 4.1 ||&lt;br /&gt;
|-&lt;br /&gt;
| Brightcove Player || Android 4.1 || Support for Android versions 2.3.3 and 4.0 is now deprecated. Learn more about why Brightcove is removing support for these versions as of January 1, 2016 in this [https://support.brightcove.com/en/perform/docs/announcement-brightcove-sdk-android-version-support|announcement]&lt;br /&gt;
|-&lt;br /&gt;
| Adobe PrimeTime Player || Android 4.2 ||&lt;br /&gt;
|-&lt;br /&gt;
| VisualOn Player || Android 2.3 || Android 5 is the latest supported version&lt;br /&gt;
|-&lt;br /&gt;
| NexStream Player || Android 1.6 || Supported till Android 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Android Native Media Player ====&lt;br /&gt;
As the Android Media Player versions (prior to Android 6 / Android API 23) do not support ID3, Nielsen has created a library that becomes an extension to the media player, thus MPX. This library extracts the ID3 tags and sends them to the app. For more information on how to use the MPX component, refer to the Nielsen-supplied sample application.&lt;br /&gt;
&lt;br /&gt;
Starting from '''Android 6 (Android API 23)''', Android Native Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags generate TimedMetadata. Once the HLS video starts, call onTimedMetaDataAvailable() as and when the player observes a TimedMetadata (ID3 tag).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;@Override&lt;br /&gt;
   public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data)&lt;br /&gt;
     {&lt;br /&gt;
       byte[] iD3PayloadArray = data.getMetaData();&lt;br /&gt;
       String iD3Payload = new String(iD3PayloadArray, StandardCharsets.UTF_8);&lt;br /&gt;
       if (null != iD3Payload &amp;amp;&amp;amp; iD3Payload.contains(&amp;quot;www.nielsen.com&amp;quot;))&lt;br /&gt;
         {&lt;br /&gt;
           int index = iD3Payload.indexOf(&amp;quot;www.nielsen.com&amp;quot;);&lt;br /&gt;
           String id3String = iD3Payload.substring(index, (index + 249));&lt;br /&gt;
           Log.d(TAG, &amp;quot;TimedMetaData ID3 Tag:&amp;quot; + id3String);&lt;br /&gt;
           appProcessID3tag(id3String);&lt;br /&gt;
         }&lt;br /&gt;
     }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ExoPlayer ====&lt;br /&gt;
he SDK is designed around an event-driven architecture where components emit events to allow other components to listen and respond to state changes.&lt;br /&gt;
&lt;br /&gt;
'''Player SDK Classes used:'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;com.google.android.exoplayer.demo.player.DemoPlayer&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since Nielsen App SDK is interested in extracting the Timed Metadata (ID3 Tags) in HLS and VOD on the EXO Player, trace the ID3_TAG emitted during video content played using EXOPlayer component as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;DemoPlayer implements ExoPlayer.Listener&lt;br /&gt;
—————————————————–&lt;br /&gt;
/**&lt;br /&gt;
* A listener for receiving ID3 metadata parsed from the media stream.&lt;br /&gt;
*/&lt;br /&gt;
public interface Id3MetadataListener&lt;br /&gt;
{&lt;br /&gt;
  void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata);&lt;br /&gt;
}&lt;br /&gt;
——————————————————-&lt;br /&gt;
MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String,&lt;br /&gt;
Object&amp;gt;&amp;gt; getId3MetadataRenderer()&lt;br /&gt;
  {&lt;br /&gt;
    return new MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;()&lt;br /&gt;
      {&lt;br /&gt;
        @Override&lt;br /&gt;
        public void onMetadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
          {&lt;br /&gt;
            if (id3MetadataListener != null)&lt;br /&gt;
              {&lt;br /&gt;
                id3MetadataListener.onId3Metadata(metadata);&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      };&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also in ''Player.java'' class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;Player implements DemoPlayer.Id3MetadataListener&lt;br /&gt;
—————————————————–&lt;br /&gt;
@SuppressWarnings(&amp;quot;rawtypes&amp;quot;)&lt;br /&gt;
@Override&lt;br /&gt;
public void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
{&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
      for (Object o : metadata.entrySet())&lt;br /&gt;
        {&lt;br /&gt;
          Map.Entry pairs = (Map.Entry) o;&lt;br /&gt;
          if (metadata.containsKey(TxxxMetadata.TYPE))&lt;br /&gt;
            {&lt;br /&gt;
              TxxxMetadata txxxMetadata = (TxxxMetadata) metadata&lt;br /&gt;
              .get(TxxxMetadata.TYPE);&lt;br /&gt;
            }&lt;br /&gt;
          else&lt;br /&gt;
            {&lt;br /&gt;
              String aStr = new String((byte[]) pairs.getValue());&lt;br /&gt;
              MainActivity.mAppSdk.sendID3(aStr);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  catch (Exception e)&lt;br /&gt;
    {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      Log.d(TAG, &amp;quot;onId3Metadata(): No Id3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-exo-retrievingID3tags.png|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Brightcove Player ====&lt;br /&gt;
While the Brightcove player plays the content, EventListener triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;SeamlessVideoDisplayComponent.ID3_TAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;brightcoveVideoView.getEventEmitter().on(SeamlessVideoDisplayComponent.ID3_TAG, new EventListener()&lt;br /&gt;
  {&lt;br /&gt;
    public void processEvent(Event event)&lt;br /&gt;
      {&lt;br /&gt;
        NlsId3Tag nlsID3 = new NlsId3Tag(event.properties.get(SeamlessVideoDisplayComponent.ID3_DATA).toString());&lt;br /&gt;
        Log.w(&amp;quot;ID3&amp;quot;, nlsID3.NlsPayload);&lt;br /&gt;
        // Sent ID3 Tags to App&lt;br /&gt;
        appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      }&lt;br /&gt;
      });&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Adobe PrimeTime Player ====&lt;br /&gt;
While the Adobe PrimeTime player plays the content, MediaPlayer.PlaybackEventListener triggers a callback when an ID3 packet is received (onTimedMetadata). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetadata(TimedMetadata id3Metadata)&lt;br /&gt;
{&lt;br /&gt;
  NlsId3Tag nlsID3 = new NlsId3Tag(id3Metadata.getMetadata().toString());&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;ID3 Timed Data –&amp;gt; &amp;quot; + nlsID3.NlsPayload);&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;PayLoad Size –&amp;gt; &amp;quot; + nlsID3.NlsPayload.length());&lt;br /&gt;
  appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== VisualOn Player ====&lt;br /&gt;
While the VisualOn player plays the content, &amp;lt;code&amp;gt;VOCommonPlayerListener&amp;lt;/code&amp;gt; triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;case VO_OSMP_SRC_CB_CUSTOMER_TAG:&lt;br /&gt;
{&lt;br /&gt;
  VO_OSMP_SRC_CUSTOMERTAGID tag = VO_OSMP_SRC_CUSTOMERTAGID.valueOf(nParam1);&lt;br /&gt;
  switch (tag)&lt;br /&gt;
    {&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG:&lt;br /&gt;
      // do something with this tag&lt;br /&gt;
      int time = nParam2;&lt;br /&gt;
      byte[] b = (byte[]) obj;&lt;br /&gt;
      String s = new String(b);&lt;br /&gt;
      NlsId3Tag nlsID3 = new NlsId3Tag(b);&lt;br /&gt;
      // Sent ID3 Tags to App&lt;br /&gt;
      appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      if (appid3If != null)&lt;br /&gt;
      appid3If.onId3(nlsID3.NlsPayload);&lt;br /&gt;
      break;&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_MAX:&lt;br /&gt;
      // ignore this type of tag&lt;br /&gt;
      break;&lt;br /&gt;
      default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
      break;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== NextStream Player ====&lt;br /&gt;
ID3 tags will be received in the NexStream Player through &amp;lt;code&amp;gt;onTimedMetaRenderRender(NexPlayer mp,NexID3TagInformation metadata)&amp;lt;/code&amp;gt; callback API. A sample implementation for the callback is shown below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetaRenderRender(NexPlayer mp, NexID3TagInformation m)&lt;br /&gt;
  {&lt;br /&gt;
    text = m.getPrivateFrame();&lt;br /&gt;
    if (text != null)&lt;br /&gt;
      {&lt;br /&gt;
        data = text.getTextData();&lt;br /&gt;
        if (data != null)&lt;br /&gt;
          {&lt;br /&gt;
            // make sure to identify the beginning  of  the&lt;br /&gt;
            // Nielsen ID3 tag payload by searching for the&lt;br /&gt;
            // &amp;quot;www.nielsen.com&amp;quot; string on the ID3 tag and&lt;br /&gt;
            // passing to the App SDK all information that&lt;br /&gt;
            // follows. It should be:&lt;br /&gt;
            // nlsPayload = &amp;quot;www.nielsen.com&amp;quot; + dataFollowing&lt;br /&gt;
            nlsPayload = getDataAfterWwwNielsenCom(data);&lt;br /&gt;
            if (nlsPayload!= NULL)&lt;br /&gt;
            mAppSdk.sendID3(nlsPayload);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[sendID3()]] sends the extracted Nielsen ID3 payload to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
== Android SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[AppSDK()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadmetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3()]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[setPlayheadPosition()]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOutURLString()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getOptOutStatus()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi()]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getAppDisable()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query if the SDK is disabled or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastEvent()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last status&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastError()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last error&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[isValid()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to check if the SDK was successfully instantiated or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getMeterVersion()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getNielsenId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getDeviceId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current device id.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInBackground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app going to background.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInForeground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app coming to foreground&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[setDebug()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-andr.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''5.1.1.18 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14, skip ahead to: [[#Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14|Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18, Opt-Out related behavior has been changed in the following ways:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Version 5.1.1.18 or above, refer to documentation above ([[#Opt-out Android SDK Version 5.1.1.18 or above|Opt-out Android SDK Version 5.1.1.18 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**Capture user’s selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
&lt;br /&gt;
Opt-Out Implementation (Limit Ad Tracking)&lt;br /&gt;
&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.18 and above.'''&lt;br /&gt;
&lt;br /&gt;
If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.14, refer to Legacy Opt-Out.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to Nielsen “About Nielsen Measurement” page from within the app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as opt-out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.16, Opt-Out related behavior has been changed in multiple ways as mentioned below.&lt;br /&gt;
* SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
* Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via '''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For more information on FireTV please see Opt-Out Implementation in Amazon Devices.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Opting out through Google Settings'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg]]&lt;br /&gt;
&lt;br /&gt;
'''What SDK integration do developers need to take care of?'''&lt;br /&gt;
* Get the Opt-Out URL from SDK in order to show the page to end users in a ‘WebView’ / External browser. There is no change in this process.&lt;br /&gt;
* Do not handle/pass the response which is received from the hyperlinks for Opt-Out / Opt-In operations, as these hyperlinks will no longer exist.&lt;br /&gt;
* Ensure to provide a button which can close/exit the optout page screen&lt;br /&gt;
&lt;br /&gt;
'''Latest Opt-Out Page'''&lt;br /&gt;
&lt;br /&gt;
[[File:privacy_policy_andr.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
&lt;br /&gt;
[[File:optoutsequence-andr.jpg]]&lt;br /&gt;
&lt;br /&gt;
==== Legacy Opt-Out Implementation ====&lt;br /&gt;
'''Supported SDK Versions''': 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14.&lt;br /&gt;
&lt;br /&gt;
If using SDK Version 5.1.1.18 or above, refer to Opt-Out Implementation (Limit Ad Tracking).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to opt-out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to Nielsen “About Nielsen Measurement” page from within the app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking userOptOutURLString() and opened in ‘WebView’ within the app and NOT in any external browser.&lt;br /&gt;
** Opening the opt-out page in any external browser takes the application control out of the Nielsen App SDK context.&lt;br /&gt;
** As the App SDK does not expose any direct http/https interface to interact with the world to get the user selection on Privacy page, there will be no way to interact/send notification to the App SDK regarding the user selection.&lt;br /&gt;
* If the App SDK returns NULL as opt-out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the getOptOutStatus() method.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
&lt;br /&gt;
[[File:optoutsequence-andr.jpg]]&lt;br /&gt;
&lt;br /&gt;
Below are the steps to implement user opt-out using UIWebView.&lt;br /&gt;
* When a user clicks the Opt Out / Opt In link, the application should invoke [[userOptOutURLString()]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
* Present WebView with Nielsen opt-out URL&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* The Nielsen Privacy page appears using UIWebView&lt;br /&gt;
[[File:privacy-policy.jpg]]&lt;br /&gt;
* There are two '''click here''' links – one for Opt-Out and one for Opt-In. User clicks the required link.&lt;br /&gt;
* Capture user’s selection&lt;br /&gt;
* Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
* Capture and forward user selection&lt;br /&gt;
** &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ is closed, pass the status returned from ‘WebView’ to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (opt-out/opt-in), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Opt-Out Implementation for Amazon Devices ====&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – ‘Limit Ad Tracking’ (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.&lt;br /&gt;
&lt;br /&gt;
'''Retrieving Ad tracking Value'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Returns limit_ad_tracking value “0” if enabled&lt;br /&gt;
* Returns limit_ad_tracking value “1” if disabled&lt;br /&gt;
* Returns limit_ad_tracking value “2” if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
Constants with predefined error codes which the AppSdk object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public static final int ERROR_FAILED_CREATE_URL_STRING = 1001;&lt;br /&gt;
// failed generating ping string due to error on parsing&lt;br /&gt;
// description – include last error message from URL parser&lt;br /&gt;
public static final int ERROR_FAILED_RECEIVE_CONFIG = 1002;&lt;br /&gt;
// failed to receive configuration file from Census&lt;br /&gt;
// description – on 5th time, it will log event and keep requesting config 10 min apart&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_CONFIG = 1003;&lt;br /&gt;
// failed parsing the config file JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_PLAY = 1004;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_METADATA = 1005;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include JSON error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_GENERATING_PING = 1006;&lt;br /&gt;
// failed creating ping before adding it to the UPLOAD table)&lt;br /&gt;
// description – include ping nol_url index, cadence to identify ping&lt;br /&gt;
public static final int ERROR_FAILED_PROCESSOR_START = 1007;&lt;br /&gt;
// failed starting data processor thread. Normally, that means a product&lt;br /&gt;
// description – include processor that failed to start&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_ID3 = 1008;&lt;br /&gt;
// failed processing data on a data processor. Normally, that means the input to a product&lt;br /&gt;
// description – include processor and data that failed to process (ID3 tag on a MTVR impression, for example)&lt;br /&gt;
public static final int ERROR_FAILED_HTTP_SEND = 1009;&lt;br /&gt;
// failed sending HTTP or HTTPS requests&lt;br /&gt;
// description – include HTTP error number&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_PING = 1010;&lt;br /&gt;
// failed sending pings (on ANDROID, the ping on the UPLOAD table)&lt;br /&gt;
// description – include ping up to 80 char from the end&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_TSV = 1011;&lt;br /&gt;
// failed sending TSV requests&lt;br /&gt;
// description – include TSV request message&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_STATION_ID = 1012;&lt;br /&gt;
// failed sending StationId requests&lt;br /&gt;
// description – include Station ID request message&lt;br /&gt;
public static final int ERROR_FAILED_ACCESSING_DB = 1013;&lt;br /&gt;
// failed read/write from/to database table&lt;br /&gt;
// description – include SQL statement and data and SQLite error number/message&lt;br /&gt;
public static final int ERROR_CHANGED_DEVICE_ID = 1014;&lt;br /&gt;
// device ID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_CHANGED_NUID = 1015;&lt;br /&gt;
// NUID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_SDK_NOT_INITIALIZED = 1016;&lt;br /&gt;
// App SDK initialization failed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_SDK_SUSPEND = 1017;&lt;br /&gt;
// App SDK failed to suspend activities&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_PARAMETERS = 1018;&lt;br /&gt;
// App SDK invalid parameters&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_STATE = 1019;&lt;br /&gt;
// App SDK called in incorrect state&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_PLAYHEAD = 1020;&lt;br /&gt;
// App SDK failed processing playhead position&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_METADATA = 1021;&lt;br /&gt;
// App SDK failed processing not-null, syntax valid JSON metadada&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_STOP = 1022;&lt;br /&gt;
// App SDK failed processing stop&lt;br /&gt;
// description – none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public static final int EVENT_INITIATE = 2000;&lt;br /&gt;
// App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
public static final int EVENT_STARTUP = 2001;&lt;br /&gt;
// App SDK has started up. It will happen only after App SDK has received a valid config file. This is the location in the code to acquire the value of userOptOutURLString().&lt;br /&gt;
public static final int EVENT_SHUTDOWN = 2002;&lt;br /&gt;
// App SDK is shutting down. It will happen just before App SDK is destroyed&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''App SDK Event Codes '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2000 || EVENT_INITIATE || App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || EVENT_STARTUP || App SDK has started up. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || EVENT_SHUTDOWN || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Browser_SDK_API_Reference&amp;diff=1057</id>
		<title>Browser SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Browser_SDK_API_Reference&amp;diff=1057"/>
		<updated>2017-07-12T19:06:37Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Opt-Out Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Setting up Development Environment ==&lt;br /&gt;
=== Step 1: Configure Content Management System (CMS) ===&lt;br /&gt;
Configure CMS to send the required values (see table below). Any internal CMS_variable names can be used for passing the data.&lt;br /&gt;
&lt;br /&gt;
Ensure to capture these CMS_variable names in the SDK Configuration Form.&lt;br /&gt;
&lt;br /&gt;
For more information on setting variable names, see the SDK Configuration Form included within the SDK package.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Required Data !! Description !! Value&lt;br /&gt;
|-&lt;br /&gt;
| dataSrc || Used when both CMS metadata and ID3 data are present in the player. Setting this field tells the SDK whether to use the CMS metadata or the ID3 payload to derive the pings || cms&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || sfcode will be provided by Nielsen and specifies which Nielsen collection facility the app should connect to. Connect to a development server during development and switch to production server once app has been certified by Nielsen. || uat-cert dcr-cert&lt;br /&gt;
|-&lt;br /&gt;
| Asset Type || Type of asset: ad or content || preroll, midroll, postroll, or content&lt;br /&gt;
|-&lt;br /&gt;
| Asset ID || Unique identifier assigned to each asset || GUID, EIDR, ADID, or internal house ID&lt;br /&gt;
|-&lt;br /&gt;
| OCR Tag || OCR tag provided by Nielsen for implementation on the ad unit || Complete OCR URL&lt;br /&gt;
|-&lt;br /&gt;
| VC Program Name || VideoCensus program name. If no value is provided, DPR program name is populated in client-defined reporting in VC || Program name used for VC reporting&lt;br /&gt;
|-&lt;br /&gt;
| Title || Title of asset || Title used for reporting&lt;br /&gt;
|-&lt;br /&gt;
| Length || Duration of asset || Length in seconds, 86400 for live stream&lt;br /&gt;
|-&lt;br /&gt;
| Isfullepisode || Full episode flag	“yes” or “lf” – full episode “no” or “sf” – non full episode&lt;br /&gt;
|-&lt;br /&gt;
| segA || Segment A (this is not available for video reporting as the episode title is reported) || custom value&lt;br /&gt;
|-&lt;br /&gt;
| segB || Segment B || custom value&lt;br /&gt;
|-&lt;br /&gt;
| segC || Segment C || custom value&lt;br /&gt;
|-&lt;br /&gt;
| crossId1 || Standard episode ID || custom value&lt;br /&gt;
|-&lt;br /&gt;
| crossId2 || Content originator (required only for distributors) || custom value&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original air date and time in Eastern Time. For non-US countries, it should be local time. || YYYYMMDD HH24:MI:SS&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Content Management System for Digital Audio ====&lt;br /&gt;
Digital Audio measurement is for digital-only audio content. For Digital Audio, clients should provide the parameters shown in CMS Table for Digital Audio.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Required Data !! Description !! Value&lt;br /&gt;
|-&lt;br /&gt;
| dataSrc ** || Source of the data. For Digital Audio, pass dataSrc as “cms”. || cms&lt;br /&gt;
|-&lt;br /&gt;
type || Type of content . For Digital Audio, set type as “radio”. || radio&lt;br /&gt;
|-&lt;br /&gt;
assetid || Station identifier, should include call letters and band. || WXYZ-FM&lt;br /&gt;
|-&lt;br /&gt;
stationType || OTA station flag and / or OTA station type 0: Custom station built per user 1: OTA streaming station with the same ad load 2: OTA station with a different ad load 3: Multicast eRadio or online station 4: On Demand Audio (podcasting) || 0, 1, 2, 3, or 4&lt;br /&gt;
|-&lt;br /&gt;
provider || Name of Provider || XYZ Provider&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Complete the Nielsen SDK Configuration Form ===&lt;br /&gt;
The SDK is designed to map the &amp;lt;code&amp;gt;CMS_variable names&amp;lt;/code&amp;gt;. To support the custom mapping, the developer is required to complete the SDK Configuration Form. The form will be provided during onboarding along with this guide.&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Obtain the Nielsen Application ID (apid), sfcode and Browser SDK URLs ===&lt;br /&gt;
The Nielsen &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; are required to enable SDK functionality. Technical Account Manager will provide two apids and two sfcodes for each player configuration:&lt;br /&gt;
*'''Test apid and Test sfcode''': Use these IDs during development and testing&lt;br /&gt;
*'''Production apid and Production sfcode''': Use these IDs in production environment after Nielsen has tested and certified the player.&lt;br /&gt;
Browser SDK can support URLs that use any of the protocols – HTTPS and HTTP. Contact the Technical Account Manager to get the appropriate Browser SDK package that suits the requirements.&lt;br /&gt;
&lt;br /&gt;
=== Initialize Browser SDK ===&lt;br /&gt;
To initialize the SDK, parameters must be passed when calling the initialization function (&amp;lt;code&amp;gt;ggInitialize&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Create a global object with the values for the required parameters (sfcode, apid, apn, and nol_sdkDebug).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
var _nolggGlobalParams =&lt;br /&gt;
{&lt;br /&gt;
  apid: &amp;quot;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX&amp;quot;,&lt;br /&gt;
  sfcode: &amp;quot;dcr-cert&amp;quot;,&lt;br /&gt;
  apn: &amp;quot;sample player name / site name&amp;quot;,&lt;br /&gt;
  nol_sdkDebug: &amp;quot;console&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Use the debug parameter, nol_sdkDebug, for testing only. Remove the parameter before moving to production.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK , use the following methods:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
var gg = window.NOLCMB.getInstance(instanceName /*optional*/);&lt;br /&gt;
gg.ggInitialize(window._nolggGlobalParams);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
If no parameters are passed to getInstance(), the default instance name is used.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' To create a new instance of the player, send a different / new unique string. Sending the same unique string re-initializes the existing instance of the player.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' To measure static content on a page and integrate the SDK with a player for video measurement, it is recommended to create one SDK instance using &amp;lt;code&amp;gt;_nolggGlobalParams.apid&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SDK Initialization – Global Parameters ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameters !! Description !! Value !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| apid || UniqueID assigned to player/site. || Nielsen provided || Yes&lt;br /&gt;
|-&lt;br /&gt;
| apn || User-defined string value for describing the player/site. || Client provided || Yes&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Location of collection environment. During testing, all traffic should be directed to &amp;quot;dcr-cert&amp;quot;. || &amp;quot;dcr-cert&amp;quot; – testing &amp;quot;dcr&amp;quot; – production || Yes&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Debug Mode which allows output to be viewed in console. || &amp;quot;console&amp;quot; || No&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The debug parameter, &amp;lt;code&amp;gt;nol_sdkDebug&amp;lt;/code&amp;gt;, is only used for testing and should be removed before moving to production. The output is displayed in console debuggers when enabled.&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Browser SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method / Property !! Event # !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| [[loadMetadata (Browser)]] || 3 || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadMetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| [[play (Browser)]] || 5 || ✔ || ✘ || ✘ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. When the client passes in the channelName, they can change the CMS data stored by passing new values. If this event is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
'''VA Beacon:''' Called when content or ads start playing. The playhead position must be passed.&lt;br /&gt;
|-&lt;br /&gt;
| [[sendID3 (Browser)]] || 55 || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| [[setPlayheadPosition (Browser)]] || 49 || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| [[stop (Browser)]] || 7 || ✘ || ✘ || ✘ || ✔ || ✔ || Used when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| [[end (Browser)]] || 57 || ✔ || ✘ || ✔ || ✔ || ✔ || This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content 3) when the browser is refreshed or closed&lt;br /&gt;
|-&lt;br /&gt;
| [[staticstart (Browser)]] || 14 || ✘ || ✘ || ✘ || ✔ || ✔ || Used to send the metadata for the static page.&lt;br /&gt;
|-&lt;br /&gt;
| [[getOptOutStatus (Browser)]] || 4 || ✘ || ✘ || ✘ || ✘ || ✔ || '''VA Beacon Only:''' Sent only after calling stop. The current position must be passed. Not needed for new International (Germany) implementations.&lt;br /&gt;
|-&lt;br /&gt;
| [[updateOTT (Browser)]] || - || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify Browser SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| [[ onPaginate (Browser)]] || 30 || ✘ || ✘ || ✘ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| [[updateMetadata (Browser)]] || 35 || ✔ || ✔ || ✔ || ✔ || ✔ || This event is used for updating metadata parameters for the content or ad that is being played.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
The video player must have the ability to extract ID3 tags and supply them to the Browser SDK, based on the HLS standard.&lt;br /&gt;
*An ID3 tag spans two PES packets.&lt;br /&gt;
**In the first PES packet, look for www.nielsen.com, this is the start of the ID3 tag. Continue to parse the first PES packet until the undefined char &amp;quot;\ufffd&amp;quot; is found. This forms the first half of the ID3 tag&lt;br /&gt;
**In the second PES packet, identify the end pattern – a regEx of /(\/\d+){3}/ and look to remove the lowest index of either &amp;quot;\x00&amp;quot; and/or &amp;quot;\ufffd&amp;quot;. Now the second packet has been appended and the demarcation of the Nielsen-specific data has been defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Follow the procedure below, to extract Nielsen ID3 tags from an MPEG-2 transport stream (including HLS streams).&lt;br /&gt;
#Parse the Program Map Table (PMT) to find the PID of the metadata stream. Confirm the presence of the metadata descriptor described in section 2.3.3 of Apple’s “HTTP Live Streaming Metadata Spec.pdf”. Only private streams with metadata descriptor present should be considered as ID3-tag metadata streams.&lt;br /&gt;
#Parse the HLS/Transport stream for any '''PES header''' with the PID found in step 1.&lt;br /&gt;
#Follow standard MPEG-2 parsing procedures to locate the start of the payload of the PES packet.&lt;br /&gt;
#Copy the PES payload into a buffer.&lt;br /&gt;
#The ID3 tag spans 2 PES packets. Parse the stream for the next packet whose PID is set to the PID found in step 1. Typically the ID3 Tag is of 249 bytes. The steps below guide towards extraction of the ID3 tag&lt;br /&gt;
##In the first PES packet, look for &amp;quot;www.nielsen.com&amp;quot; , this is the start of the ID3 tag. Keep on parsing the first PES packet until the undefined char &amp;quot;\ufffd&amp;quot; is found. This forms the first half of the ID3 tag&lt;br /&gt;
##In the second PES packet, identify the end pattern, a regEx of /(\/\d+){3}/ and look to remove the lowest index of either “\x00” and/or “\ufffd”. Now the second packet has been appended and the demarcation of the Nielsen specific data has been defined. This segment can be simply substringed.&lt;br /&gt;
##Concatenate this substringed segment with the payload derived from the first packet get the ID3 payload.&lt;br /&gt;
#Check the length of the contents in the buffer to make sure that it is equal to the size of a Nielsen ID3 tag.&lt;br /&gt;
#Ensure that the ID3 byte array is converted into the string and escape it, so that the SDK can consume it.&lt;br /&gt;
Repeat steps 2 through 7 for all ID3 tags in the stream.&lt;br /&gt;
&lt;br /&gt;
'''References'''&lt;br /&gt;
*[http://www.iso.org/iso/catalogue_detail?csnumber=44169. ISO/IEC 13818-1:2007] Information technology – Generic coding of moving pictures and associated audio information: Systems&lt;br /&gt;
*https://developer.apple.com/library/ios/sdk/developers/AudioVideo/Conceptual/HTTP_Live_Streaming_Metadata_Spec/HTTP_Live_Streaming_Metadata_Spec.pdf&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Browser Opt-Out Implementation ==&lt;br /&gt;
The site in which video content is being measure via Nielsen methodology must provide the means for the user to opt-out of, or opt back into Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
For Browser-based applications, opt-out setting is stored via Nielsen cookie. Therefore, it is only necessary that users be made aware of measurement opt-out by incorporating the template below in the user interface.&lt;br /&gt;
&lt;br /&gt;
=== Sample Opt Out Template ===&lt;br /&gt;
Our properties may feature Nielsen’s proprietary measurement software which will allow to contribute to market research, like Nielsen’s TV Ratings. To learn more about this information, see http://www.nielsen.com/digitalprivacy. Nielsen’s software may collect your choices with regards to it.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;7&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
The site must provide a means for the user to opt‐out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt‐out option, it is mandatory to include the following two items in the site’s privacy policy&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings)&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at http://www.nielsen.com/digitalprivacy&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click '''Choices''' to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Our properties may feature Nielsen proprietary measurement software, which will allow you to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, refer to Nielsen Digital Measurement Privacy Policy at http://www.nielsen.com/digitalprivacy.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For information, please see Opt-Out Implementation below.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
The site must provide the means for the user to opt-out of, or opt back into Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
'''Sample Opt Out Template'''&lt;br /&gt;
&lt;br /&gt;
Our properties may feature Nielsen’s proprietary measurement software which will allow to contribute to market research, like Nielsen’s TV Ratings. To learn more about this information, please [http://www.nielsen.com/digitalprivacy| click here]. Nielsen’s software may collect your choices with regards to it.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
See [[Digital Measurement Testing#Testing Browser Implementation|Digital Measurement Testing - Testing Browser Implementation]].&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Browser_SDK_API_Reference&amp;diff=1056</id>
		<title>Browser SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Browser_SDK_API_Reference&amp;diff=1056"/>
		<updated>2017-07-12T19:05:41Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Nielsen Measurement Opt-Out */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Setting up Development Environment ==&lt;br /&gt;
=== Step 1: Configure Content Management System (CMS) ===&lt;br /&gt;
Configure CMS to send the required values (see table below). Any internal CMS_variable names can be used for passing the data.&lt;br /&gt;
&lt;br /&gt;
Ensure to capture these CMS_variable names in the SDK Configuration Form.&lt;br /&gt;
&lt;br /&gt;
For more information on setting variable names, see the SDK Configuration Form included within the SDK package.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Required Data !! Description !! Value&lt;br /&gt;
|-&lt;br /&gt;
| dataSrc || Used when both CMS metadata and ID3 data are present in the player. Setting this field tells the SDK whether to use the CMS metadata or the ID3 payload to derive the pings || cms&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || sfcode will be provided by Nielsen and specifies which Nielsen collection facility the app should connect to. Connect to a development server during development and switch to production server once app has been certified by Nielsen. || uat-cert dcr-cert&lt;br /&gt;
|-&lt;br /&gt;
| Asset Type || Type of asset: ad or content || preroll, midroll, postroll, or content&lt;br /&gt;
|-&lt;br /&gt;
| Asset ID || Unique identifier assigned to each asset || GUID, EIDR, ADID, or internal house ID&lt;br /&gt;
|-&lt;br /&gt;
| OCR Tag || OCR tag provided by Nielsen for implementation on the ad unit || Complete OCR URL&lt;br /&gt;
|-&lt;br /&gt;
| VC Program Name || VideoCensus program name. If no value is provided, DPR program name is populated in client-defined reporting in VC || Program name used for VC reporting&lt;br /&gt;
|-&lt;br /&gt;
| Title || Title of asset || Title used for reporting&lt;br /&gt;
|-&lt;br /&gt;
| Length || Duration of asset || Length in seconds, 86400 for live stream&lt;br /&gt;
|-&lt;br /&gt;
| Isfullepisode || Full episode flag	“yes” or “lf” – full episode “no” or “sf” – non full episode&lt;br /&gt;
|-&lt;br /&gt;
| segA || Segment A (this is not available for video reporting as the episode title is reported) || custom value&lt;br /&gt;
|-&lt;br /&gt;
| segB || Segment B || custom value&lt;br /&gt;
|-&lt;br /&gt;
| segC || Segment C || custom value&lt;br /&gt;
|-&lt;br /&gt;
| crossId1 || Standard episode ID || custom value&lt;br /&gt;
|-&lt;br /&gt;
| crossId2 || Content originator (required only for distributors) || custom value&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original air date and time in Eastern Time. For non-US countries, it should be local time. || YYYYMMDD HH24:MI:SS&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Content Management System for Digital Audio ====&lt;br /&gt;
Digital Audio measurement is for digital-only audio content. For Digital Audio, clients should provide the parameters shown in CMS Table for Digital Audio.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Required Data !! Description !! Value&lt;br /&gt;
|-&lt;br /&gt;
| dataSrc ** || Source of the data. For Digital Audio, pass dataSrc as “cms”. || cms&lt;br /&gt;
|-&lt;br /&gt;
type || Type of content . For Digital Audio, set type as “radio”. || radio&lt;br /&gt;
|-&lt;br /&gt;
assetid || Station identifier, should include call letters and band. || WXYZ-FM&lt;br /&gt;
|-&lt;br /&gt;
stationType || OTA station flag and / or OTA station type 0: Custom station built per user 1: OTA streaming station with the same ad load 2: OTA station with a different ad load 3: Multicast eRadio or online station 4: On Demand Audio (podcasting) || 0, 1, 2, 3, or 4&lt;br /&gt;
|-&lt;br /&gt;
provider || Name of Provider || XYZ Provider&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Complete the Nielsen SDK Configuration Form ===&lt;br /&gt;
The SDK is designed to map the &amp;lt;code&amp;gt;CMS_variable names&amp;lt;/code&amp;gt;. To support the custom mapping, the developer is required to complete the SDK Configuration Form. The form will be provided during onboarding along with this guide.&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Obtain the Nielsen Application ID (apid), sfcode and Browser SDK URLs ===&lt;br /&gt;
The Nielsen &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; are required to enable SDK functionality. Technical Account Manager will provide two apids and two sfcodes for each player configuration:&lt;br /&gt;
*'''Test apid and Test sfcode''': Use these IDs during development and testing&lt;br /&gt;
*'''Production apid and Production sfcode''': Use these IDs in production environment after Nielsen has tested and certified the player.&lt;br /&gt;
Browser SDK can support URLs that use any of the protocols – HTTPS and HTTP. Contact the Technical Account Manager to get the appropriate Browser SDK package that suits the requirements.&lt;br /&gt;
&lt;br /&gt;
=== Initialize Browser SDK ===&lt;br /&gt;
To initialize the SDK, parameters must be passed when calling the initialization function (&amp;lt;code&amp;gt;ggInitialize&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Create a global object with the values for the required parameters (sfcode, apid, apn, and nol_sdkDebug).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
var _nolggGlobalParams =&lt;br /&gt;
{&lt;br /&gt;
  apid: &amp;quot;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX&amp;quot;,&lt;br /&gt;
  sfcode: &amp;quot;dcr-cert&amp;quot;,&lt;br /&gt;
  apn: &amp;quot;sample player name / site name&amp;quot;,&lt;br /&gt;
  nol_sdkDebug: &amp;quot;console&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Use the debug parameter, nol_sdkDebug, for testing only. Remove the parameter before moving to production.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK , use the following methods:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
var gg = window.NOLCMB.getInstance(instanceName /*optional*/);&lt;br /&gt;
gg.ggInitialize(window._nolggGlobalParams);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
If no parameters are passed to getInstance(), the default instance name is used.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' To create a new instance of the player, send a different / new unique string. Sending the same unique string re-initializes the existing instance of the player.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' To measure static content on a page and integrate the SDK with a player for video measurement, it is recommended to create one SDK instance using &amp;lt;code&amp;gt;_nolggGlobalParams.apid&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SDK Initialization – Global Parameters ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameters !! Description !! Value !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| apid || UniqueID assigned to player/site. || Nielsen provided || Yes&lt;br /&gt;
|-&lt;br /&gt;
| apn || User-defined string value for describing the player/site. || Client provided || Yes&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Location of collection environment. During testing, all traffic should be directed to &amp;quot;dcr-cert&amp;quot;. || &amp;quot;dcr-cert&amp;quot; – testing &amp;quot;dcr&amp;quot; – production || Yes&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Debug Mode which allows output to be viewed in console. || &amp;quot;console&amp;quot; || No&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The debug parameter, &amp;lt;code&amp;gt;nol_sdkDebug&amp;lt;/code&amp;gt;, is only used for testing and should be removed before moving to production. The output is displayed in console debuggers when enabled.&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Browser SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method / Property !! Event # !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| [[loadMetadata (Browser)]] || 3 || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadMetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| [[play (Browser)]] || 5 || ✔ || ✘ || ✘ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. When the client passes in the channelName, they can change the CMS data stored by passing new values. If this event is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
'''VA Beacon:''' Called when content or ads start playing. The playhead position must be passed.&lt;br /&gt;
|-&lt;br /&gt;
| [[sendID3 (Browser)]] || 55 || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| [[setPlayheadPosition (Browser)]] || 49 || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| [[stop (Browser)]] || 7 || ✘ || ✘ || ✘ || ✔ || ✔ || Used when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| [[end (Browser)]] || 57 || ✔ || ✘ || ✔ || ✔ || ✔ || This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content 3) when the browser is refreshed or closed&lt;br /&gt;
|-&lt;br /&gt;
| [[staticstart (Browser)]] || 14 || ✘ || ✘ || ✘ || ✔ || ✔ || Used to send the metadata for the static page.&lt;br /&gt;
|-&lt;br /&gt;
| [[getOptOutStatus (Browser)]] || 4 || ✘ || ✘ || ✘ || ✘ || ✔ || '''VA Beacon Only:''' Sent only after calling stop. The current position must be passed. Not needed for new International (Germany) implementations.&lt;br /&gt;
|-&lt;br /&gt;
| [[updateOTT (Browser)]] || - || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify Browser SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| [[ onPaginate (Browser)]] || 30 || ✘ || ✘ || ✘ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| [[updateMetadata (Browser)]] || 35 || ✔ || ✔ || ✔ || ✔ || ✔ || This event is used for updating metadata parameters for the content or ad that is being played.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
The video player must have the ability to extract ID3 tags and supply them to the Browser SDK, based on the HLS standard.&lt;br /&gt;
*An ID3 tag spans two PES packets.&lt;br /&gt;
**In the first PES packet, look for www.nielsen.com, this is the start of the ID3 tag. Continue to parse the first PES packet until the undefined char &amp;quot;\ufffd&amp;quot; is found. This forms the first half of the ID3 tag&lt;br /&gt;
**In the second PES packet, identify the end pattern – a regEx of /(\/\d+){3}/ and look to remove the lowest index of either &amp;quot;\x00&amp;quot; and/or &amp;quot;\ufffd&amp;quot;. Now the second packet has been appended and the demarcation of the Nielsen-specific data has been defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Follow the procedure below, to extract Nielsen ID3 tags from an MPEG-2 transport stream (including HLS streams).&lt;br /&gt;
#Parse the Program Map Table (PMT) to find the PID of the metadata stream. Confirm the presence of the metadata descriptor described in section 2.3.3 of Apple’s “HTTP Live Streaming Metadata Spec.pdf”. Only private streams with metadata descriptor present should be considered as ID3-tag metadata streams.&lt;br /&gt;
#Parse the HLS/Transport stream for any '''PES header''' with the PID found in step 1.&lt;br /&gt;
#Follow standard MPEG-2 parsing procedures to locate the start of the payload of the PES packet.&lt;br /&gt;
#Copy the PES payload into a buffer.&lt;br /&gt;
#The ID3 tag spans 2 PES packets. Parse the stream for the next packet whose PID is set to the PID found in step 1. Typically the ID3 Tag is of 249 bytes. The steps below guide towards extraction of the ID3 tag&lt;br /&gt;
##In the first PES packet, look for &amp;quot;www.nielsen.com&amp;quot; , this is the start of the ID3 tag. Keep on parsing the first PES packet until the undefined char &amp;quot;\ufffd&amp;quot; is found. This forms the first half of the ID3 tag&lt;br /&gt;
##In the second PES packet, identify the end pattern, a regEx of /(\/\d+){3}/ and look to remove the lowest index of either “\x00” and/or “\ufffd”. Now the second packet has been appended and the demarcation of the Nielsen specific data has been defined. This segment can be simply substringed.&lt;br /&gt;
##Concatenate this substringed segment with the payload derived from the first packet get the ID3 payload.&lt;br /&gt;
#Check the length of the contents in the buffer to make sure that it is equal to the size of a Nielsen ID3 tag.&lt;br /&gt;
#Ensure that the ID3 byte array is converted into the string and escape it, so that the SDK can consume it.&lt;br /&gt;
Repeat steps 2 through 7 for all ID3 tags in the stream.&lt;br /&gt;
&lt;br /&gt;
'''References'''&lt;br /&gt;
*[http://www.iso.org/iso/catalogue_detail?csnumber=44169. ISO/IEC 13818-1:2007] Information technology – Generic coding of moving pictures and associated audio information: Systems&lt;br /&gt;
*https://developer.apple.com/library/ios/sdk/developers/AudioVideo/Conceptual/HTTP_Live_Streaming_Metadata_Spec/HTTP_Live_Streaming_Metadata_Spec.pdf&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Browser Opt-Out Implementation ==&lt;br /&gt;
The site in which video content is being measure via Nielsen methodology must provide the means for the user to opt-out of, or opt back into Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
For Browser-based applications, opt-out setting is stored via Nielsen cookie. Therefore, it is only necessary that users be made aware of measurement opt-out by incorporating the template below in the user interface.&lt;br /&gt;
&lt;br /&gt;
=== Sample Opt Out Template ===&lt;br /&gt;
Our properties may feature Nielsen’s proprietary measurement software which will allow to contribute to market research, like Nielsen’s TV Ratings. To learn more about this information, see http://www.nielsen.com/digitalprivacy. Nielsen’s software may collect your choices with regards to it.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;7&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
The site must provide a means for the user to opt‐out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt‐out option, it is mandatory to include the following two items in the site’s privacy policy&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings)&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at http://www.nielsen.com/digitalprivacy&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click '''Choices''' to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Our properties may feature Nielsen proprietary measurement software, which will allow you to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, refer to Nielsen Digital Measurement Privacy Policy at http://www.nielsen.com/digitalprivacy.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For information, please see Opt-Out Implementation below.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
See [[Digital Measurement Testing#Testing Browser Implementation|Digital Measurement Testing - Testing Browser Implementation]].&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1055</id>
		<title>Android SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1055"/>
		<updated>2017-07-12T18:55:19Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Nielsen Privacy Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*Create and initialize an instance object of &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class.&lt;br /&gt;
*The player application can use this object to collect HLS timed metadata through a [[sendID3()]] call.&lt;br /&gt;
The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package. It inherits from the closeable interface and exposes the public APIs the client’s app will use. Below is the declaration of the &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class: &amp;lt;code&amp;gt;public class AppSdk implements Closeable&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Up Development Environment ==&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Setting up in Eclipse IDE ===&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-properties-drm.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
&lt;br /&gt;
'''Library''':&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
'''Classes/package''':&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
 &lt;br /&gt;
=== Setting up in Android Studio IDE ===&lt;br /&gt;
Launch '''Android Studio''' and select '''Import project (Eclipse ADT)'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-setup-launch.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Browse for project destination directory and click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-import-project.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Go to '''File &amp;gt; Project Structure &amp;gt; App &amp;gt; Dependencies'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-pro-structure.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Click '''+''' to add library dependency.&lt;br /&gt;
&lt;br /&gt;
Select '''play-services''' and click '''OK'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-choose-library.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information, refer to https://developer.android.com/google/play-services/setup.html&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Android Application Life Cycle with respect to Nielsen App SDK ===&lt;br /&gt;
[[File:andr-init-img1.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 1: App SDK initialization ===&lt;br /&gt;
==== For API version 4.0.0 and above ====&lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject config = null;&lt;br /&gt;
 &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;uat-cert&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;INFO&amp;quot;) // only for debug builds&lt;br /&gt;
          .put(&amp;quot;custom_key1&amp;quot;, &amp;quot;custom_value1&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;custom_key2&amp;quot;, &amp;quot;custom_value2&amp;quot;);&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
==== Android Application Life Cycle with respect to Nielsen App SDK ====&lt;br /&gt;
[[File:andr-radioandvideo-app.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 2: App SDK libraries inclusion in project ===&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&lt;br /&gt;
*Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Nielsen App SDK Streaming Sessions ===&lt;br /&gt;
After ensuring that the SDK object has been initialized, link the streaming session APIs. The next steps are:&lt;br /&gt;
*Call [[play()]] when starting or resuming a streaming session. Use the channelName parameter to pass channel descriptor information. The channel name field is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.) which must be inserted on a JSON string.&lt;br /&gt;
*Load the CMS metadata by calling the [[loadMetadata()]] on the SDK object.&lt;br /&gt;
*Call [[stop()]] when ending or pausing a viewing session.&lt;br /&gt;
*During session playback, call the SDK [[setPlayheadPosition()]] and / or [[sendID3()]]&lt;br /&gt;
**Call [[setPlayheadPosition()]] every one second until the stream is stopped or paused. Normally this happens on Digital Audio measurements.&lt;br /&gt;
**Call [[sendID3()]] if the client relies on the Nielsen ID3 tags for its measurements; this call should happen whenever a new Nielsen ID3 metadata is available for processing. Normally this happens on DTVR and ID3 measurements.&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
*The client’s app must clearly identify the mode of operation (live vs. VOD) and stick to the type of playhead coordinates until the playback is completed. The client must reliably provide the appropriated playhead position value depending on the type of content streamed.&lt;br /&gt;
*If streaming live video content, the client must pass the current UTC time in seconds as playhead position.&lt;br /&gt;
*If streaming VOD (video on demand), the client must stream the offset from the beginning of the file as playhead position.&lt;br /&gt;
*For all Digital Audio listening, the client must pass the current UTC time in seconds as playhead position, regardless of station type.&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extracting ID3 tags from Android Players ===&lt;br /&gt;
==== ID3 Support Matrix ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Player Name !! Minimum supported version !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Android Native Media Player || Android 6 || Android 6 Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags, generates TimedMetaData.&lt;br /&gt;
|-&lt;br /&gt;
| Google ExoPlayer || Android 4.1 ||&lt;br /&gt;
|-&lt;br /&gt;
| Brightcove Player || Android 4.1 || Support for Android versions 2.3.3 and 4.0 is now deprecated. Learn more about why Brightcove is removing support for these versions as of January 1, 2016 in this [https://support.brightcove.com/en/perform/docs/announcement-brightcove-sdk-android-version-support|announcement]&lt;br /&gt;
|-&lt;br /&gt;
| Adobe PrimeTime Player || Android 4.2 ||&lt;br /&gt;
|-&lt;br /&gt;
| VisualOn Player || Android 2.3 || Android 5 is the latest supported version&lt;br /&gt;
|-&lt;br /&gt;
| NexStream Player || Android 1.6 || Supported till Android 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Android Native Media Player ====&lt;br /&gt;
As the Android Media Player versions (prior to Android 6 / Android API 23) do not support ID3, Nielsen has created a library that becomes an extension to the media player, thus MPX. This library extracts the ID3 tags and sends them to the app. For more information on how to use the MPX component, refer to the Nielsen-supplied sample application.&lt;br /&gt;
&lt;br /&gt;
Starting from '''Android 6 (Android API 23)''', Android Native Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags generate TimedMetadata. Once the HLS video starts, call onTimedMetaDataAvailable() as and when the player observes a TimedMetadata (ID3 tag).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;@Override&lt;br /&gt;
   public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data)&lt;br /&gt;
     {&lt;br /&gt;
       byte[] iD3PayloadArray = data.getMetaData();&lt;br /&gt;
       String iD3Payload = new String(iD3PayloadArray, StandardCharsets.UTF_8);&lt;br /&gt;
       if (null != iD3Payload &amp;amp;&amp;amp; iD3Payload.contains(&amp;quot;www.nielsen.com&amp;quot;))&lt;br /&gt;
         {&lt;br /&gt;
           int index = iD3Payload.indexOf(&amp;quot;www.nielsen.com&amp;quot;);&lt;br /&gt;
           String id3String = iD3Payload.substring(index, (index + 249));&lt;br /&gt;
           Log.d(TAG, &amp;quot;TimedMetaData ID3 Tag:&amp;quot; + id3String);&lt;br /&gt;
           appProcessID3tag(id3String);&lt;br /&gt;
         }&lt;br /&gt;
     }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ExoPlayer ====&lt;br /&gt;
he SDK is designed around an event-driven architecture where components emit events to allow other components to listen and respond to state changes.&lt;br /&gt;
&lt;br /&gt;
'''Player SDK Classes used:'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;com.google.android.exoplayer.demo.player.DemoPlayer&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since Nielsen App SDK is interested in extracting the Timed Metadata (ID3 Tags) in HLS and VOD on the EXO Player, trace the ID3_TAG emitted during video content played using EXOPlayer component as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;DemoPlayer implements ExoPlayer.Listener&lt;br /&gt;
—————————————————–&lt;br /&gt;
/**&lt;br /&gt;
* A listener for receiving ID3 metadata parsed from the media stream.&lt;br /&gt;
*/&lt;br /&gt;
public interface Id3MetadataListener&lt;br /&gt;
{&lt;br /&gt;
  void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata);&lt;br /&gt;
}&lt;br /&gt;
——————————————————-&lt;br /&gt;
MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String,&lt;br /&gt;
Object&amp;gt;&amp;gt; getId3MetadataRenderer()&lt;br /&gt;
  {&lt;br /&gt;
    return new MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;()&lt;br /&gt;
      {&lt;br /&gt;
        @Override&lt;br /&gt;
        public void onMetadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
          {&lt;br /&gt;
            if (id3MetadataListener != null)&lt;br /&gt;
              {&lt;br /&gt;
                id3MetadataListener.onId3Metadata(metadata);&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      };&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also in ''Player.java'' class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;Player implements DemoPlayer.Id3MetadataListener&lt;br /&gt;
—————————————————–&lt;br /&gt;
@SuppressWarnings(&amp;quot;rawtypes&amp;quot;)&lt;br /&gt;
@Override&lt;br /&gt;
public void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
{&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
      for (Object o : metadata.entrySet())&lt;br /&gt;
        {&lt;br /&gt;
          Map.Entry pairs = (Map.Entry) o;&lt;br /&gt;
          if (metadata.containsKey(TxxxMetadata.TYPE))&lt;br /&gt;
            {&lt;br /&gt;
              TxxxMetadata txxxMetadata = (TxxxMetadata) metadata&lt;br /&gt;
              .get(TxxxMetadata.TYPE);&lt;br /&gt;
            }&lt;br /&gt;
          else&lt;br /&gt;
            {&lt;br /&gt;
              String aStr = new String((byte[]) pairs.getValue());&lt;br /&gt;
              MainActivity.mAppSdk.sendID3(aStr);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  catch (Exception e)&lt;br /&gt;
    {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      Log.d(TAG, &amp;quot;onId3Metadata(): No Id3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-exo-retrievingID3tags.png|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Brightcove Player ====&lt;br /&gt;
While the Brightcove player plays the content, EventListener triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;SeamlessVideoDisplayComponent.ID3_TAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;brightcoveVideoView.getEventEmitter().on(SeamlessVideoDisplayComponent.ID3_TAG, new EventListener()&lt;br /&gt;
  {&lt;br /&gt;
    public void processEvent(Event event)&lt;br /&gt;
      {&lt;br /&gt;
        NlsId3Tag nlsID3 = new NlsId3Tag(event.properties.get(SeamlessVideoDisplayComponent.ID3_DATA).toString());&lt;br /&gt;
        Log.w(&amp;quot;ID3&amp;quot;, nlsID3.NlsPayload);&lt;br /&gt;
        // Sent ID3 Tags to App&lt;br /&gt;
        appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      }&lt;br /&gt;
      });&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Adobe PrimeTime Player ====&lt;br /&gt;
While the Adobe PrimeTime player plays the content, MediaPlayer.PlaybackEventListener triggers a callback when an ID3 packet is received (onTimedMetadata). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetadata(TimedMetadata id3Metadata)&lt;br /&gt;
{&lt;br /&gt;
  NlsId3Tag nlsID3 = new NlsId3Tag(id3Metadata.getMetadata().toString());&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;ID3 Timed Data –&amp;gt; &amp;quot; + nlsID3.NlsPayload);&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;PayLoad Size –&amp;gt; &amp;quot; + nlsID3.NlsPayload.length());&lt;br /&gt;
  appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== VisualOn Player ====&lt;br /&gt;
While the VisualOn player plays the content, &amp;lt;code&amp;gt;VOCommonPlayerListener&amp;lt;/code&amp;gt; triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;case VO_OSMP_SRC_CB_CUSTOMER_TAG:&lt;br /&gt;
{&lt;br /&gt;
  VO_OSMP_SRC_CUSTOMERTAGID tag = VO_OSMP_SRC_CUSTOMERTAGID.valueOf(nParam1);&lt;br /&gt;
  switch (tag)&lt;br /&gt;
    {&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG:&lt;br /&gt;
      // do something with this tag&lt;br /&gt;
      int time = nParam2;&lt;br /&gt;
      byte[] b = (byte[]) obj;&lt;br /&gt;
      String s = new String(b);&lt;br /&gt;
      NlsId3Tag nlsID3 = new NlsId3Tag(b);&lt;br /&gt;
      // Sent ID3 Tags to App&lt;br /&gt;
      appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      if (appid3If != null)&lt;br /&gt;
      appid3If.onId3(nlsID3.NlsPayload);&lt;br /&gt;
      break;&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_MAX:&lt;br /&gt;
      // ignore this type of tag&lt;br /&gt;
      break;&lt;br /&gt;
      default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
      break;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== NextStream Player ====&lt;br /&gt;
ID3 tags will be received in the NexStream Player through &amp;lt;code&amp;gt;onTimedMetaRenderRender(NexPlayer mp,NexID3TagInformation metadata)&amp;lt;/code&amp;gt; callback API. A sample implementation for the callback is shown below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetaRenderRender(NexPlayer mp, NexID3TagInformation m)&lt;br /&gt;
  {&lt;br /&gt;
    text = m.getPrivateFrame();&lt;br /&gt;
    if (text != null)&lt;br /&gt;
      {&lt;br /&gt;
        data = text.getTextData();&lt;br /&gt;
        if (data != null)&lt;br /&gt;
          {&lt;br /&gt;
            // make sure to identify the beginning  of  the&lt;br /&gt;
            // Nielsen ID3 tag payload by searching for the&lt;br /&gt;
            // &amp;quot;www.nielsen.com&amp;quot; string on the ID3 tag and&lt;br /&gt;
            // passing to the App SDK all information that&lt;br /&gt;
            // follows. It should be:&lt;br /&gt;
            // nlsPayload = &amp;quot;www.nielsen.com&amp;quot; + dataFollowing&lt;br /&gt;
            nlsPayload = getDataAfterWwwNielsenCom(data);&lt;br /&gt;
            if (nlsPayload!= NULL)&lt;br /&gt;
            mAppSdk.sendID3(nlsPayload);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[sendID3()]] sends the extracted Nielsen ID3 payload to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
== Android SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[AppSDK()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadmetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3()]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[setPlayheadPosition()]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOutURLString()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getOptOutStatus()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi()]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getAppDisable()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query if the SDK is disabled or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastEvent()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last status&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastError()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last error&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[isValid()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to check if the SDK was successfully instantiated or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getMeterVersion()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getNielsenId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getDeviceId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current device id.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInBackground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app going to background.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInForeground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app coming to foreground&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[setDebug()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-andr.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''5.1.1.18 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14, skip ahead to: [[#Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14|Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18, Opt-Out related behavior has been changed in the following ways:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Version 5.1.1.18 or above, refer to documentation above ([[#Opt-out Android SDK Version 5.1.1.18 or above|Opt-out Android SDK Version 5.1.1.18 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**Capture user’s selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
&lt;br /&gt;
Opt-Out Implementation (Limit Ad Tracking)&lt;br /&gt;
&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.18 and above.'''&lt;br /&gt;
&lt;br /&gt;
If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.14, refer to Legacy Opt-Out.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to Nielsen “About Nielsen Measurement” page from within the app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as opt-out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.16, Opt-Out related behavior has been changed in multiple ways as mentioned below.&lt;br /&gt;
* SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
* Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via '''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For more information on FireTV please see Opt-Out Implementation in Amazon Devices.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Opting out through Google Settings'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg]]&lt;br /&gt;
&lt;br /&gt;
'''What SDK integration do developers need to take care of?'''&lt;br /&gt;
* Get the Opt-Out URL from SDK in order to show the page to end users in a ‘WebView’ / External browser. There is no change in this process.&lt;br /&gt;
* Do not handle/pass the response which is received from the hyperlinks for Opt-Out / Opt-In operations, as these hyperlinks will no longer exist.&lt;br /&gt;
* Ensure to provide a button which can close/exit the optout page screen&lt;br /&gt;
&lt;br /&gt;
'''Latest Opt-Out Page'''&lt;br /&gt;
&lt;br /&gt;
[[File:privacy_policy_andr.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
&lt;br /&gt;
[[File:optoutsequence-andr.jpg]]&lt;br /&gt;
&lt;br /&gt;
==== Opt-Out Implementation for Amazon Devices ====&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – ‘Limit Ad Tracking’ (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.&lt;br /&gt;
&lt;br /&gt;
'''Retrieving Ad tracking Value'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Returns limit_ad_tracking value “0” if enabled&lt;br /&gt;
* Returns limit_ad_tracking value “1” if disabled&lt;br /&gt;
* Returns limit_ad_tracking value “2” if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
Constants with predefined error codes which the AppSdk object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public static final int ERROR_FAILED_CREATE_URL_STRING = 1001;&lt;br /&gt;
// failed generating ping string due to error on parsing&lt;br /&gt;
// description – include last error message from URL parser&lt;br /&gt;
public static final int ERROR_FAILED_RECEIVE_CONFIG = 1002;&lt;br /&gt;
// failed to receive configuration file from Census&lt;br /&gt;
// description – on 5th time, it will log event and keep requesting config 10 min apart&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_CONFIG = 1003;&lt;br /&gt;
// failed parsing the config file JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_PLAY = 1004;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_METADATA = 1005;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include JSON error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_GENERATING_PING = 1006;&lt;br /&gt;
// failed creating ping before adding it to the UPLOAD table)&lt;br /&gt;
// description – include ping nol_url index, cadence to identify ping&lt;br /&gt;
public static final int ERROR_FAILED_PROCESSOR_START = 1007;&lt;br /&gt;
// failed starting data processor thread. Normally, that means a product&lt;br /&gt;
// description – include processor that failed to start&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_ID3 = 1008;&lt;br /&gt;
// failed processing data on a data processor. Normally, that means the input to a product&lt;br /&gt;
// description – include processor and data that failed to process (ID3 tag on a MTVR impression, for example)&lt;br /&gt;
public static final int ERROR_FAILED_HTTP_SEND = 1009;&lt;br /&gt;
// failed sending HTTP or HTTPS requests&lt;br /&gt;
// description – include HTTP error number&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_PING = 1010;&lt;br /&gt;
// failed sending pings (on ANDROID, the ping on the UPLOAD table)&lt;br /&gt;
// description – include ping up to 80 char from the end&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_TSV = 1011;&lt;br /&gt;
// failed sending TSV requests&lt;br /&gt;
// description – include TSV request message&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_STATION_ID = 1012;&lt;br /&gt;
// failed sending StationId requests&lt;br /&gt;
// description – include Station ID request message&lt;br /&gt;
public static final int ERROR_FAILED_ACCESSING_DB = 1013;&lt;br /&gt;
// failed read/write from/to database table&lt;br /&gt;
// description – include SQL statement and data and SQLite error number/message&lt;br /&gt;
public static final int ERROR_CHANGED_DEVICE_ID = 1014;&lt;br /&gt;
// device ID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_CHANGED_NUID = 1015;&lt;br /&gt;
// NUID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_SDK_NOT_INITIALIZED = 1016;&lt;br /&gt;
// App SDK initialization failed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_SDK_SUSPEND = 1017;&lt;br /&gt;
// App SDK failed to suspend activities&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_PARAMETERS = 1018;&lt;br /&gt;
// App SDK invalid parameters&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_STATE = 1019;&lt;br /&gt;
// App SDK called in incorrect state&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_PLAYHEAD = 1020;&lt;br /&gt;
// App SDK failed processing playhead position&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_METADATA = 1021;&lt;br /&gt;
// App SDK failed processing not-null, syntax valid JSON metadada&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_STOP = 1022;&lt;br /&gt;
// App SDK failed processing stop&lt;br /&gt;
// description – none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public static final int EVENT_INITIATE = 2000;&lt;br /&gt;
// App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
public static final int EVENT_STARTUP = 2001;&lt;br /&gt;
// App SDK has started up. It will happen only after App SDK has received a valid config file. This is the location in the code to acquire the value of userOptOutURLString().&lt;br /&gt;
public static final int EVENT_SHUTDOWN = 2002;&lt;br /&gt;
// App SDK is shutting down. It will happen just before App SDK is destroyed&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''App SDK Event Codes '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2000 || EVENT_INITIATE || App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || EVENT_STARTUP || App SDK has started up. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || EVENT_SHUTDOWN || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=File:privacy_policy_andr.jpg&amp;diff=1054</id>
		<title>File:privacy policy andr.jpg</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=File:privacy_policy_andr.jpg&amp;diff=1054"/>
		<updated>2017-07-12T18:50:01Z</updated>

		<summary type="html">&lt;p&gt;Admin2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1053</id>
		<title>Android SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=Android_SDK_API_Reference&amp;diff=1053"/>
		<updated>2017-07-12T18:22:09Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Opt-out Android SDK Version 5.1.1.18 or above */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*Create and initialize an instance object of &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class.&lt;br /&gt;
*The player application can use this object to collect HLS timed metadata through a [[sendID3()]] call.&lt;br /&gt;
The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package. It inherits from the closeable interface and exposes the public APIs the client’s app will use. Below is the declaration of the &amp;lt;code&amp;gt;AppSdk&amp;lt;/code&amp;gt; class: &amp;lt;code&amp;gt;public class AppSdk implements Closeable&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting Up Development Environment ==&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Setting up in Eclipse IDE ===&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-properties-drm.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
&lt;br /&gt;
'''Library''':&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
'''Classes/package''':&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
 &lt;br /&gt;
=== Setting up in Android Studio IDE ===&lt;br /&gt;
Launch '''Android Studio''' and select '''Import project (Eclipse ADT)'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-setup-launch.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Browse for project destination directory and click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-import-project.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Go to '''File &amp;gt; Project Structure &amp;gt; App &amp;gt; Dependencies'''.&lt;br /&gt;
&lt;br /&gt;
[[File:andr-pro-structure.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Click '''+''' to add library dependency.&lt;br /&gt;
&lt;br /&gt;
Select '''play-services''' and click '''OK'''&lt;br /&gt;
&lt;br /&gt;
[[File:andr-choose-library.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
For more information, refer to https://developer.android.com/google/play-services/setup.html&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
=== Android Application Life Cycle with respect to Nielsen App SDK ===&lt;br /&gt;
[[File:andr-init-img1.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 1: App SDK initialization ===&lt;br /&gt;
==== For API version 4.0.0 and above ====&lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject config = null;&lt;br /&gt;
 &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;uat-cert&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;INFO&amp;quot;) // only for debug builds&lt;br /&gt;
          .put(&amp;quot;custom_key1&amp;quot;, &amp;quot;custom_value1&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;custom_key2&amp;quot;, &amp;quot;custom_value2&amp;quot;);&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
==== Android Application Life Cycle with respect to Nielsen App SDK ====&lt;br /&gt;
[[File:andr-radioandvideo-app.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Step 2: App SDK libraries inclusion in project ===&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&lt;br /&gt;
*Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Nielsen App SDK Streaming Sessions ===&lt;br /&gt;
After ensuring that the SDK object has been initialized, link the streaming session APIs. The next steps are:&lt;br /&gt;
*Call [[play()]] when starting or resuming a streaming session. Use the channelName parameter to pass channel descriptor information. The channel name field is a 32-character free-form text field containing the name of the program or feed being sent (such as ESPN2, Food Network, etc.) which must be inserted on a JSON string.&lt;br /&gt;
*Load the CMS metadata by calling the [[loadMetadata()]] on the SDK object.&lt;br /&gt;
*Call [[stop()]] when ending or pausing a viewing session.&lt;br /&gt;
*During session playback, call the SDK [[setPlayheadPosition()]] and / or [[sendID3()]]&lt;br /&gt;
**Call [[setPlayheadPosition()]] every one second until the stream is stopped or paused. Normally this happens on Digital Audio measurements.&lt;br /&gt;
**Call [[sendID3()]] if the client relies on the Nielsen ID3 tags for its measurements; this call should happen whenever a new Nielsen ID3 metadata is available for processing. Normally this happens on DTVR and ID3 measurements.&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
*The client’s app must clearly identify the mode of operation (live vs. VOD) and stick to the type of playhead coordinates until the playback is completed. The client must reliably provide the appropriated playhead position value depending on the type of content streamed.&lt;br /&gt;
*If streaming live video content, the client must pass the current UTC time in seconds as playhead position.&lt;br /&gt;
*If streaming VOD (video on demand), the client must stream the offset from the beginning of the file as playhead position.&lt;br /&gt;
*For all Digital Audio listening, the client must pass the current UTC time in seconds as playhead position, regardless of station type.&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extracting ID3 tags from Android Players ===&lt;br /&gt;
==== ID3 Support Matrix ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Player Name !! Minimum supported version !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Android Native Media Player || Android 6 || Android 6 Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags, generates TimedMetaData.&lt;br /&gt;
|-&lt;br /&gt;
| Google ExoPlayer || Android 4.1 ||&lt;br /&gt;
|-&lt;br /&gt;
| Brightcove Player || Android 4.1 || Support for Android versions 2.3.3 and 4.0 is now deprecated. Learn more about why Brightcove is removing support for these versions as of January 1, 2016 in this [https://support.brightcove.com/en/perform/docs/announcement-brightcove-sdk-android-version-support|announcement]&lt;br /&gt;
|-&lt;br /&gt;
| Adobe PrimeTime Player || Android 4.2 ||&lt;br /&gt;
|-&lt;br /&gt;
| VisualOn Player || Android 2.3 || Android 5 is the latest supported version&lt;br /&gt;
|-&lt;br /&gt;
| NexStream Player || Android 1.6 || Supported till Android 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Android Native Media Player ====&lt;br /&gt;
As the Android Media Player versions (prior to Android 6 / Android API 23) do not support ID3, Nielsen has created a library that becomes an extension to the media player, thus MPX. This library extracts the ID3 tags and sends them to the app. For more information on how to use the MPX component, refer to the Nielsen-supplied sample application.&lt;br /&gt;
&lt;br /&gt;
Starting from '''Android 6 (Android API 23)''', Android Native Media Player allows apps to register a callback to be invoked, when a selected track has the timed metadata available. Currently, only HTTP Live Streaming (HLS) data URI’s embedded with timed ID3 tags generate TimedMetadata. Once the HLS video starts, call onTimedMetaDataAvailable() as and when the player observes a TimedMetadata (ID3 tag).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;@Override&lt;br /&gt;
   public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data)&lt;br /&gt;
     {&lt;br /&gt;
       byte[] iD3PayloadArray = data.getMetaData();&lt;br /&gt;
       String iD3Payload = new String(iD3PayloadArray, StandardCharsets.UTF_8);&lt;br /&gt;
       if (null != iD3Payload &amp;amp;&amp;amp; iD3Payload.contains(&amp;quot;www.nielsen.com&amp;quot;))&lt;br /&gt;
         {&lt;br /&gt;
           int index = iD3Payload.indexOf(&amp;quot;www.nielsen.com&amp;quot;);&lt;br /&gt;
           String id3String = iD3Payload.substring(index, (index + 249));&lt;br /&gt;
           Log.d(TAG, &amp;quot;TimedMetaData ID3 Tag:&amp;quot; + id3String);&lt;br /&gt;
           appProcessID3tag(id3String);&lt;br /&gt;
         }&lt;br /&gt;
     }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== ExoPlayer ====&lt;br /&gt;
he SDK is designed around an event-driven architecture where components emit events to allow other components to listen and respond to state changes.&lt;br /&gt;
&lt;br /&gt;
'''Player SDK Classes used:'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;com.google.android.exoplayer.demo.player.DemoPlayer&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since Nielsen App SDK is interested in extracting the Timed Metadata (ID3 Tags) in HLS and VOD on the EXO Player, trace the ID3_TAG emitted during video content played using EXOPlayer component as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;DemoPlayer implements ExoPlayer.Listener&lt;br /&gt;
—————————————————–&lt;br /&gt;
/**&lt;br /&gt;
* A listener for receiving ID3 metadata parsed from the media stream.&lt;br /&gt;
*/&lt;br /&gt;
public interface Id3MetadataListener&lt;br /&gt;
{&lt;br /&gt;
  void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata);&lt;br /&gt;
}&lt;br /&gt;
——————————————————-&lt;br /&gt;
MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String,&lt;br /&gt;
Object&amp;gt;&amp;gt; getId3MetadataRenderer()&lt;br /&gt;
  {&lt;br /&gt;
    return new MetadataTrackRenderer.MetadataRenderer&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt;()&lt;br /&gt;
      {&lt;br /&gt;
        @Override&lt;br /&gt;
        public void onMetadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
          {&lt;br /&gt;
            if (id3MetadataListener != null)&lt;br /&gt;
              {&lt;br /&gt;
                id3MetadataListener.onId3Metadata(metadata);&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      };&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also in ''Player.java'' class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;Player implements DemoPlayer.Id3MetadataListener&lt;br /&gt;
—————————————————–&lt;br /&gt;
@SuppressWarnings(&amp;quot;rawtypes&amp;quot;)&lt;br /&gt;
@Override&lt;br /&gt;
public void onId3Metadata(Map&amp;lt;String, Object&amp;gt; metadata)&lt;br /&gt;
{&lt;br /&gt;
  try&lt;br /&gt;
    {&lt;br /&gt;
      for (Object o : metadata.entrySet())&lt;br /&gt;
        {&lt;br /&gt;
          Map.Entry pairs = (Map.Entry) o;&lt;br /&gt;
          if (metadata.containsKey(TxxxMetadata.TYPE))&lt;br /&gt;
            {&lt;br /&gt;
              TxxxMetadata txxxMetadata = (TxxxMetadata) metadata&lt;br /&gt;
              .get(TxxxMetadata.TYPE);&lt;br /&gt;
            }&lt;br /&gt;
          else&lt;br /&gt;
            {&lt;br /&gt;
              String aStr = new String((byte[]) pairs.getValue());&lt;br /&gt;
              MainActivity.mAppSdk.sendID3(aStr);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
  catch (Exception e)&lt;br /&gt;
    {&lt;br /&gt;
      e.printStackTrace();&lt;br /&gt;
      Log.d(TAG, &amp;quot;onId3Metadata(): No Id3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-exo-retrievingID3tags.png|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Brightcove Player ====&lt;br /&gt;
While the Brightcove player plays the content, EventListener triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;SeamlessVideoDisplayComponent.ID3_TAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;brightcoveVideoView.getEventEmitter().on(SeamlessVideoDisplayComponent.ID3_TAG, new EventListener()&lt;br /&gt;
  {&lt;br /&gt;
    public void processEvent(Event event)&lt;br /&gt;
      {&lt;br /&gt;
        NlsId3Tag nlsID3 = new NlsId3Tag(event.properties.get(SeamlessVideoDisplayComponent.ID3_DATA).toString());&lt;br /&gt;
        Log.w(&amp;quot;ID3&amp;quot;, nlsID3.NlsPayload);&lt;br /&gt;
        // Sent ID3 Tags to App&lt;br /&gt;
        appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      }&lt;br /&gt;
      });&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Adobe PrimeTime Player ====&lt;br /&gt;
While the Adobe PrimeTime player plays the content, MediaPlayer.PlaybackEventListener triggers a callback when an ID3 packet is received (onTimedMetadata). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetadata(TimedMetadata id3Metadata)&lt;br /&gt;
{&lt;br /&gt;
  NlsId3Tag nlsID3 = new NlsId3Tag(id3Metadata.getMetadata().toString());&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;ID3 Timed Data –&amp;gt; &amp;quot; + nlsID3.NlsPayload);&lt;br /&gt;
  Log.w(LOG_TAG, &amp;quot;PayLoad Size –&amp;gt; &amp;quot; + nlsID3.NlsPayload.length());&lt;br /&gt;
  appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== VisualOn Player ====&lt;br /&gt;
While the VisualOn player plays the content, &amp;lt;code&amp;gt;VOCommonPlayerListener&amp;lt;/code&amp;gt; triggers an event when an ID3 packet is received (&amp;lt;code&amp;gt;VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG&amp;lt;/code&amp;gt;). Upon receiving this event, collect the incoming ID3 tags and only pass the Nielsen payload of the PRIV frame to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;case VO_OSMP_SRC_CB_CUSTOMER_TAG:&lt;br /&gt;
{&lt;br /&gt;
  VO_OSMP_SRC_CUSTOMERTAGID tag = VO_OSMP_SRC_CUSTOMERTAGID.valueOf(nParam1);&lt;br /&gt;
  switch (tag)&lt;br /&gt;
    {&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_TIMEDTAG:&lt;br /&gt;
      // do something with this tag&lt;br /&gt;
      int time = nParam2;&lt;br /&gt;
      byte[] b = (byte[]) obj;&lt;br /&gt;
      String s = new String(b);&lt;br /&gt;
      NlsId3Tag nlsID3 = new NlsId3Tag(b);&lt;br /&gt;
      // Sent ID3 Tags to App&lt;br /&gt;
      appProcessID3tag(nlsID3.NlsPayload);&lt;br /&gt;
      if (appid3If != null)&lt;br /&gt;
      appid3If.onId3(nlsID3.NlsPayload);&lt;br /&gt;
      break;&lt;br /&gt;
      case VO_OSMP_SRC_CUSTOMERTAGID_MAX:&lt;br /&gt;
      // ignore this type of tag&lt;br /&gt;
      break;&lt;br /&gt;
      default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
      break;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== NextStream Player ====&lt;br /&gt;
ID3 tags will be received in the NexStream Player through &amp;lt;code&amp;gt;onTimedMetaRenderRender(NexPlayer mp,NexID3TagInformation metadata)&amp;lt;/code&amp;gt; callback API. A sample implementation for the callback is shown below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void onTimedMetaRenderRender(NexPlayer mp, NexID3TagInformation m)&lt;br /&gt;
  {&lt;br /&gt;
    text = m.getPrivateFrame();&lt;br /&gt;
    if (text != null)&lt;br /&gt;
      {&lt;br /&gt;
        data = text.getTextData();&lt;br /&gt;
        if (data != null)&lt;br /&gt;
          {&lt;br /&gt;
            // make sure to identify the beginning  of  the&lt;br /&gt;
            // Nielsen ID3 tag payload by searching for the&lt;br /&gt;
            // &amp;quot;www.nielsen.com&amp;quot; string on the ID3 tag and&lt;br /&gt;
            // passing to the App SDK all information that&lt;br /&gt;
            // follows. It should be:&lt;br /&gt;
            // nlsPayload = &amp;quot;www.nielsen.com&amp;quot; + dataFollowing&lt;br /&gt;
            nlsPayload = getDataAfterWwwNielsenCom(data);&lt;br /&gt;
            if (nlsPayload!= NULL)&lt;br /&gt;
            mAppSdk.sendID3(nlsPayload);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[sendID3()]] sends the extracted Nielsen ID3 payload to the App SDK for analysis.&lt;br /&gt;
&lt;br /&gt;
== Android SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[AppSDK()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is a preroll ad that needs to be associated with content metadata. The loadmetadata will first be called to populate the content metadata values and then the loadMetadata for ad metadata will be called. This allows sending a content ping with the ad info, even if the user bails out during the preroll ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3()]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[setPlayheadPosition()]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end()]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOutURLString()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getOptOutStatus()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi()]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[getAppDisable()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query if the SDK is disabled or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastEvent()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last status&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getLastError()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to query the SDK for the last error&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[isValid()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to check if the SDK was successfully instantiated or not.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getMeterVersion()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getNielsenId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[getDeviceId()]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current device id.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInBackground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app going to background.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[appInForeground()]] || ✘ || ✘ || ✘ || ✔ || ✔ || Used to capture the event of app coming to foreground&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[setDebug()]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[userOptOutURLString()]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[getOptOutStatus()]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-andr.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''5.1.1.18 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14, skip ahead to: [[#Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14|Opt-out Android SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18, Opt-Out related behavior has been changed in the following ways:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out Android SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.14''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using Android SDK Version 5.1.1.18 or above, refer to documentation above ([[#Opt-out Android SDK Version 5.1.1.18 or above|Opt-out Android SDK Version 5.1.1.18 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**Capture user’s selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut()]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private class MonitorWebView extends WebViewClient&lt;br /&gt;
{&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_OUT = “nielsenappsdk://1”;&lt;br /&gt;
  private static final String NIELSEN_URL_OPT_IN = “nielsenappsdk://0”;&lt;br /&gt;
 &lt;br /&gt;
  @Override&lt;br /&gt;
  public boolean shouldOverrideUrlLoading(WebView view, String url)&lt;br /&gt;
  {&lt;br /&gt;
    if (NIELSEN_URL_OPT_OUT.equals(url)&lt;br /&gt;
      || NIELSEN_URL_OPT_IN.equals(url))&lt;br /&gt;
    {&lt;br /&gt;
      // Get AppSdk instance from the host&lt;br /&gt;
      AppSdk appSdk = HostApp.getAppSdk();&lt;br /&gt;
      // Send the URL to the AppSdk instance&lt;br /&gt;
      appSdk.userOptOut(url);&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
Constants with predefined error codes which the AppSdk object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public static final int ERROR_FAILED_CREATE_URL_STRING = 1001;&lt;br /&gt;
// failed generating ping string due to error on parsing&lt;br /&gt;
// description – include last error message from URL parser&lt;br /&gt;
public static final int ERROR_FAILED_RECEIVE_CONFIG = 1002;&lt;br /&gt;
// failed to receive configuration file from Census&lt;br /&gt;
// description – on 5th time, it will log event and keep requesting config 10 min apart&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_CONFIG = 1003;&lt;br /&gt;
// failed parsing the config file JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_PLAY = 1004;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include json error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_PARSING_METADATA = 1005;&lt;br /&gt;
// failed parsing the play() JSON string&lt;br /&gt;
// description – include JSON error number/short message from iOS or Android&lt;br /&gt;
public static final int ERROR_FAILED_GENERATING_PING = 1006;&lt;br /&gt;
// failed creating ping before adding it to the UPLOAD table)&lt;br /&gt;
// description – include ping nol_url index, cadence to identify ping&lt;br /&gt;
public static final int ERROR_FAILED_PROCESSOR_START = 1007;&lt;br /&gt;
// failed starting data processor thread. Normally, that means a product&lt;br /&gt;
// description – include processor that failed to start&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_ID3 = 1008;&lt;br /&gt;
// failed processing data on a data processor. Normally, that means the input to a product&lt;br /&gt;
// description – include processor and data that failed to process (ID3 tag on a MTVR impression, for example)&lt;br /&gt;
public static final int ERROR_FAILED_HTTP_SEND = 1009;&lt;br /&gt;
// failed sending HTTP or HTTPS requests&lt;br /&gt;
// description – include HTTP error number&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_PING = 1010;&lt;br /&gt;
// failed sending pings (on ANDROID, the ping on the UPLOAD table)&lt;br /&gt;
// description – include ping up to 80 char from the end&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_TSV = 1011;&lt;br /&gt;
// failed sending TSV requests&lt;br /&gt;
// description – include TSV request message&lt;br /&gt;
public static final int ERROR_FAILED_SENDING_STATION_ID = 1012;&lt;br /&gt;
// failed sending StationId requests&lt;br /&gt;
// description – include Station ID request message&lt;br /&gt;
public static final int ERROR_FAILED_ACCESSING_DB = 1013;&lt;br /&gt;
// failed read/write from/to database table&lt;br /&gt;
// description – include SQL statement and data and SQLite error number/message&lt;br /&gt;
public static final int ERROR_CHANGED_DEVICE_ID = 1014;&lt;br /&gt;
// device ID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_CHANGED_NUID = 1015;&lt;br /&gt;
// NUID changed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_SDK_NOT_INITIALIZED = 1016;&lt;br /&gt;
// App SDK initialization failed&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_SDK_SUSPEND = 1017;&lt;br /&gt;
// App SDK failed to suspend activities&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_PARAMETERS = 1018;&lt;br /&gt;
// App SDK invalid parameters&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_INVALID_STATE = 1019;&lt;br /&gt;
// App SDK called in incorrect state&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_PLAYHEAD = 1020;&lt;br /&gt;
// App SDK failed processing playhead position&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_METADATA = 1021;&lt;br /&gt;
// App SDK failed processing not-null, syntax valid JSON metadada&lt;br /&gt;
// description – none&lt;br /&gt;
public static final int ERROR_FAILED_PROCESS_STOP = 1022;&lt;br /&gt;
// App SDK failed processing stop&lt;br /&gt;
// description – none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public static final int EVENT_INITIATE = 2000;&lt;br /&gt;
// App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
public static final int EVENT_STARTUP = 2001;&lt;br /&gt;
// App SDK has started up. It will happen only after App SDK has received a valid config file. This is the location in the code to acquire the value of userOptOutURLString().&lt;br /&gt;
public static final int EVENT_SHUTDOWN = 2002;&lt;br /&gt;
// App SDK is shutting down. It will happen just before App SDK is destroyed&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''App SDK Event Codes '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2000 || EVENT_INITIATE || App SDK is initiated. It will happen as soon as the App SDK is initialized&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || EVENT_STARTUP || App SDK has started up. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || EVENT_SHUTDOWN || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1052</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1052"/>
		<updated>2017-07-11T21:53:28Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Legacy Opt-Out */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ // Handle it gracefully and retry later} else&lt;br /&gt;
{[optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
// show the view to the user&lt;br /&gt;
[self.view addSubview:optOutView]; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(BOOL)webView:(UIWebView *)webView&lt;br /&gt;
shouldStartLoadWithRequest:(NSURLRequest *)request&lt;br /&gt;
navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
NSString *command = [NSString stringWithFormat:@&amp;quot;%@&amp;quot;,&lt;br /&gt;
request.URL];&lt;br /&gt;
if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
// Close the WebView&lt;br /&gt;
[self performSelector:@selector(closeOptOutView)&lt;br /&gt;
withObject:nil afterDelay:0];&lt;br /&gt;
return NO;&lt;br /&gt;
}&lt;br /&gt;
// Retrieve next URL if it's not opt-in/out selection&lt;br /&gt;
return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.17 and above.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.12, refer to [[#Legacy_Opt-Out|Legacy Opt-Out Implementation for iOS]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to opt out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ &lt;br /&gt;
  // Handle it gracefully and retry later&lt;br /&gt;
} &lt;br /&gt;
 &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
  // show the view to the user&lt;br /&gt;
  [self.view addSubview:optOutView]; &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS’ system setting – “Limit Ad Tracking”. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the “Limit Ad Tracking” setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out_iOS.jpg]]&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to “About Nielsen Measurement” page for the users. Include “About Nielsen Measurement” and '''Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy_policy_iOS.jpg]]&lt;br /&gt;
&lt;br /&gt;
* URL to this web page should be called from SDK and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen’s SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;@property (readonly) BOOL optOutStatus;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
* App should provide a UI control like ‘close’ or ‘back’ button to close the ‘WebView’ / External browser.&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== Constants / Enumerations ===&lt;br /&gt;
The following are the details of Delegate Implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by a Event: %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
   – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by an Error: %@&amp;quot;, error);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== TVOS Implementation ====&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the client should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products are not used to identify consumer in any way. They help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows.&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking2.png]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Legacy Opt-Out ====&lt;br /&gt;
'''Supported SDK Versions''': 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 5.1.1.17 or above, refer to [[#Limit Ad Tracking|Limit Ad Tracking iOS Implementation]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in ‘WebView’ within the app and NOT in any external browser.&lt;br /&gt;
** Opening the Opt-Out page in any external browser takes the application control out of the Nielsen App SDK context.&lt;br /&gt;
** As the App SDK does not expose any direct http/https interface to interact with the world to get the user selection on Privacy page, there will be no way to interact/send notification to the App SDK regarding the user selection.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
Below are the steps to implement user Opt-Out using UIWebView.&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
&lt;br /&gt;
'''Implement WebView with Nielsen Opt-Out URL'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The Nielsen Privacy Page appears using UIWebView&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Privacy Page'''&lt;br /&gt;
&lt;br /&gt;
[[File:privacy-policy.jpg]]&lt;br /&gt;
&lt;br /&gt;
* There are two links – one for Opt-Out and one for Opt-In. Click the required link.&lt;br /&gt;
* Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
* The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the ‘WebView’. In order to do this, the application needs to&lt;br /&gt;
** Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
** Capture user’s selection&lt;br /&gt;
** Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Capture and forward user selection'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the ‘WebView’ URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
* &amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user’s selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ is closed, pass the status returned from ‘WebView’ to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Event Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== AppApiErrorCode ==&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Error Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1051</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1051"/>
		<updated>2017-07-11T21:52:24Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Limit Ad Tracking */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ // Handle it gracefully and retry later} else&lt;br /&gt;
{[optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
// show the view to the user&lt;br /&gt;
[self.view addSubview:optOutView]; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(BOOL)webView:(UIWebView *)webView&lt;br /&gt;
shouldStartLoadWithRequest:(NSURLRequest *)request&lt;br /&gt;
navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
NSString *command = [NSString stringWithFormat:@&amp;quot;%@&amp;quot;,&lt;br /&gt;
request.URL];&lt;br /&gt;
if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
// Close the WebView&lt;br /&gt;
[self performSelector:@selector(closeOptOutView)&lt;br /&gt;
withObject:nil afterDelay:0];&lt;br /&gt;
return NO;&lt;br /&gt;
}&lt;br /&gt;
// Retrieve next URL if it's not opt-in/out selection&lt;br /&gt;
return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.17 and above.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.12, refer to [[#Legacy_Opt-Out|Legacy Opt-Out Implementation for iOS]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to opt out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ &lt;br /&gt;
  // Handle it gracefully and retry later&lt;br /&gt;
} &lt;br /&gt;
 &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
  // show the view to the user&lt;br /&gt;
  [self.view addSubview:optOutView]; &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS’ system setting – “Limit Ad Tracking”. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the “Limit Ad Tracking” setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out_iOS.jpg]]&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to “About Nielsen Measurement” page for the users. Include “About Nielsen Measurement” and '''Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy_policy_iOS.jpg]]&lt;br /&gt;
&lt;br /&gt;
* URL to this web page should be called from SDK and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen’s SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;@property (readonly) BOOL optOutStatus;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
* App should provide a UI control like ‘close’ or ‘back’ button to close the ‘WebView’ / External browser.&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== Constants / Enumerations ===&lt;br /&gt;
The following are the details of Delegate Implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by a Event: %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
   – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by an Error: %@&amp;quot;, error);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== TVOS Implementation ====&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the client should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products are not used to identify consumer in any way. They help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows.&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking2.png]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Legacy Opt-Out ====&lt;br /&gt;
'''Supported SDK Versions''': 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 5.1.1.17 or above, refer to Opt-Out Implementation (Limit Ad Tracking).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in ‘WebView’ within the app and NOT in any external browser.&lt;br /&gt;
** Opening the Opt-Out page in any external browser takes the application control out of the Nielsen App SDK context.&lt;br /&gt;
** As the App SDK does not expose any direct http/https interface to interact with the world to get the user selection on Privacy page, there will be no way to interact/send notification to the App SDK regarding the user selection.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
Below are the steps to implement user Opt-Out using UIWebView.&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
&lt;br /&gt;
'''Implement WebView with Nielsen Opt-Out URL'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The Nielsen Privacy Page appears using UIWebView&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Privacy Page'''&lt;br /&gt;
&lt;br /&gt;
[[File:privacy-policy.jpg]]&lt;br /&gt;
&lt;br /&gt;
* There are two links – one for Opt-Out and one for Opt-In. Click the required link.&lt;br /&gt;
* Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
* The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the ‘WebView’. In order to do this, the application needs to&lt;br /&gt;
** Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
** Capture user’s selection&lt;br /&gt;
** Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Capture and forward user selection'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the ‘WebView’ URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
* &amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user’s selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ is closed, pass the status returned from ‘WebView’ to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Event Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== AppApiErrorCode ==&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Error Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1050</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1050"/>
		<updated>2017-07-11T21:51:08Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* App SDK Error Codes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ // Handle it gracefully and retry later} else&lt;br /&gt;
{[optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
// show the view to the user&lt;br /&gt;
[self.view addSubview:optOutView]; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(BOOL)webView:(UIWebView *)webView&lt;br /&gt;
shouldStartLoadWithRequest:(NSURLRequest *)request&lt;br /&gt;
navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
NSString *command = [NSString stringWithFormat:@&amp;quot;%@&amp;quot;,&lt;br /&gt;
request.URL];&lt;br /&gt;
if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
// Close the WebView&lt;br /&gt;
[self performSelector:@selector(closeOptOutView)&lt;br /&gt;
withObject:nil afterDelay:0];&lt;br /&gt;
return NO;&lt;br /&gt;
}&lt;br /&gt;
// Retrieve next URL if it's not opt-in/out selection&lt;br /&gt;
return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.17 and above.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.12, refer to Opt-Out Implementation for iOS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to opt out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ &lt;br /&gt;
  // Handle it gracefully and retry later&lt;br /&gt;
} &lt;br /&gt;
 &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
  // show the view to the user&lt;br /&gt;
  [self.view addSubview:optOutView]; &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS’ system setting – “Limit Ad Tracking”. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the “Limit Ad Tracking” setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out_iOS.jpg]]&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to “About Nielsen Measurement” page for the users. Include “About Nielsen Measurement” and '''Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy_policy_iOS.jpg]]&lt;br /&gt;
&lt;br /&gt;
* URL to this web page should be called from SDK and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen’s SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;@property (readonly) BOOL optOutStatus;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
* App should provide a UI control like ‘close’ or ‘back’ button to close the ‘WebView’ / External browser.&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== Constants / Enumerations ===&lt;br /&gt;
The following are the details of Delegate Implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by a Event: %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
   – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by an Error: %@&amp;quot;, error);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== TVOS Implementation ====&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the client should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products are not used to identify consumer in any way. They help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows.&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking2.png]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Legacy Opt-Out ====&lt;br /&gt;
'''Supported SDK Versions''': 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 5.1.1.17 or above, refer to Opt-Out Implementation (Limit Ad Tracking).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in ‘WebView’ within the app and NOT in any external browser.&lt;br /&gt;
** Opening the Opt-Out page in any external browser takes the application control out of the Nielsen App SDK context.&lt;br /&gt;
** As the App SDK does not expose any direct http/https interface to interact with the world to get the user selection on Privacy page, there will be no way to interact/send notification to the App SDK regarding the user selection.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
Below are the steps to implement user Opt-Out using UIWebView.&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
&lt;br /&gt;
'''Implement WebView with Nielsen Opt-Out URL'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The Nielsen Privacy Page appears using UIWebView&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Privacy Page'''&lt;br /&gt;
&lt;br /&gt;
[[File:privacy-policy.jpg]]&lt;br /&gt;
&lt;br /&gt;
* There are two links – one for Opt-Out and one for Opt-In. Click the required link.&lt;br /&gt;
* Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
* The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the ‘WebView’. In order to do this, the application needs to&lt;br /&gt;
** Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
** Capture user’s selection&lt;br /&gt;
** Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Capture and forward user selection'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the ‘WebView’ URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
* &amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user’s selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ is closed, pass the status returned from ‘WebView’ to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Event Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== AppApiErrorCode ==&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Error Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1049</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1049"/>
		<updated>2017-07-11T21:51:00Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* AppApiErrorCode */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ // Handle it gracefully and retry later} else&lt;br /&gt;
{[optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
// show the view to the user&lt;br /&gt;
[self.view addSubview:optOutView]; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(BOOL)webView:(UIWebView *)webView&lt;br /&gt;
shouldStartLoadWithRequest:(NSURLRequest *)request&lt;br /&gt;
navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
NSString *command = [NSString stringWithFormat:@&amp;quot;%@&amp;quot;,&lt;br /&gt;
request.URL];&lt;br /&gt;
if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
// Close the WebView&lt;br /&gt;
[self performSelector:@selector(closeOptOutView)&lt;br /&gt;
withObject:nil afterDelay:0];&lt;br /&gt;
return NO;&lt;br /&gt;
}&lt;br /&gt;
// Retrieve next URL if it's not opt-in/out selection&lt;br /&gt;
return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.17 and above.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.12, refer to Opt-Out Implementation for iOS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to opt out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ &lt;br /&gt;
  // Handle it gracefully and retry later&lt;br /&gt;
} &lt;br /&gt;
 &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
  // show the view to the user&lt;br /&gt;
  [self.view addSubview:optOutView]; &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS’ system setting – “Limit Ad Tracking”. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the “Limit Ad Tracking” setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out_iOS.jpg]]&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to “About Nielsen Measurement” page for the users. Include “About Nielsen Measurement” and '''Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy_policy_iOS.jpg]]&lt;br /&gt;
&lt;br /&gt;
* URL to this web page should be called from SDK and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen’s SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;@property (readonly) BOOL optOutStatus;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
* App should provide a UI control like ‘close’ or ‘back’ button to close the ‘WebView’ / External browser.&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== Constants / Enumerations ===&lt;br /&gt;
The following are the details of Delegate Implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by a Event: %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
   – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by an Error: %@&amp;quot;, error);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== TVOS Implementation ====&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the client should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products are not used to identify consumer in any way. They help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows.&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking2.png]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Legacy Opt-Out ====&lt;br /&gt;
'''Supported SDK Versions''': 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 5.1.1.17 or above, refer to Opt-Out Implementation (Limit Ad Tracking).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in ‘WebView’ within the app and NOT in any external browser.&lt;br /&gt;
** Opening the Opt-Out page in any external browser takes the application control out of the Nielsen App SDK context.&lt;br /&gt;
** As the App SDK does not expose any direct http/https interface to interact with the world to get the user selection on Privacy page, there will be no way to interact/send notification to the App SDK regarding the user selection.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
Below are the steps to implement user Opt-Out using UIWebView.&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
&lt;br /&gt;
'''Implement WebView with Nielsen Opt-Out URL'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The Nielsen Privacy Page appears using UIWebView&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Privacy Page'''&lt;br /&gt;
&lt;br /&gt;
[[File:privacy-policy.jpg]]&lt;br /&gt;
&lt;br /&gt;
* There are two links – one for Opt-Out and one for Opt-In. Click the required link.&lt;br /&gt;
* Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
* The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the ‘WebView’. In order to do this, the application needs to&lt;br /&gt;
** Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
** Capture user’s selection&lt;br /&gt;
** Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Capture and forward user selection'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the ‘WebView’ URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
* &amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user’s selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ is closed, pass the status returned from ‘WebView’ to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Event Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== AppApiErrorCode ==&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1048</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1048"/>
		<updated>2017-07-11T21:50:24Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* App SDK Event Codes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ // Handle it gracefully and retry later} else&lt;br /&gt;
{[optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
// show the view to the user&lt;br /&gt;
[self.view addSubview:optOutView]; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(BOOL)webView:(UIWebView *)webView&lt;br /&gt;
shouldStartLoadWithRequest:(NSURLRequest *)request&lt;br /&gt;
navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
NSString *command = [NSString stringWithFormat:@&amp;quot;%@&amp;quot;,&lt;br /&gt;
request.URL];&lt;br /&gt;
if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
// Close the WebView&lt;br /&gt;
[self performSelector:@selector(closeOptOutView)&lt;br /&gt;
withObject:nil afterDelay:0];&lt;br /&gt;
return NO;&lt;br /&gt;
}&lt;br /&gt;
// Retrieve next URL if it's not opt-in/out selection&lt;br /&gt;
return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.17 and above.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.12, refer to Opt-Out Implementation for iOS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to opt out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ &lt;br /&gt;
  // Handle it gracefully and retry later&lt;br /&gt;
} &lt;br /&gt;
 &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
  // show the view to the user&lt;br /&gt;
  [self.view addSubview:optOutView]; &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS’ system setting – “Limit Ad Tracking”. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the “Limit Ad Tracking” setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out_iOS.jpg]]&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to “About Nielsen Measurement” page for the users. Include “About Nielsen Measurement” and '''Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy_policy_iOS.jpg]]&lt;br /&gt;
&lt;br /&gt;
* URL to this web page should be called from SDK and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen’s SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;@property (readonly) BOOL optOutStatus;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
* App should provide a UI control like ‘close’ or ‘back’ button to close the ‘WebView’ / External browser.&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== Constants / Enumerations ===&lt;br /&gt;
The following are the details of Delegate Implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by a Event: %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
   – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by an Error: %@&amp;quot;, error);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== TVOS Implementation ====&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the client should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products are not used to identify consumer in any way. They help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows.&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking2.png]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Legacy Opt-Out ====&lt;br /&gt;
'''Supported SDK Versions''': 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 5.1.1.17 or above, refer to Opt-Out Implementation (Limit Ad Tracking).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in ‘WebView’ within the app and NOT in any external browser.&lt;br /&gt;
** Opening the Opt-Out page in any external browser takes the application control out of the Nielsen App SDK context.&lt;br /&gt;
** As the App SDK does not expose any direct http/https interface to interact with the world to get the user selection on Privacy page, there will be no way to interact/send notification to the App SDK regarding the user selection.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
Below are the steps to implement user Opt-Out using UIWebView.&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
&lt;br /&gt;
'''Implement WebView with Nielsen Opt-Out URL'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The Nielsen Privacy Page appears using UIWebView&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Privacy Page'''&lt;br /&gt;
&lt;br /&gt;
[[File:privacy-policy.jpg]]&lt;br /&gt;
&lt;br /&gt;
* There are two links – one for Opt-Out and one for Opt-In. Click the required link.&lt;br /&gt;
* Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
* The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the ‘WebView’. In order to do this, the application needs to&lt;br /&gt;
** Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
** Capture user’s selection&lt;br /&gt;
** Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Capture and forward user selection'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the ‘WebView’ URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
* &amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user’s selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ is closed, pass the status returned from ‘WebView’ to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== App SDK Event Codes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== AppApiErrorCode ===&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1047</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1047"/>
		<updated>2017-07-11T21:50:12Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* AppApiEventCode */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ // Handle it gracefully and retry later} else&lt;br /&gt;
{[optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
// show the view to the user&lt;br /&gt;
[self.view addSubview:optOutView]; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(BOOL)webView:(UIWebView *)webView&lt;br /&gt;
shouldStartLoadWithRequest:(NSURLRequest *)request&lt;br /&gt;
navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
NSString *command = [NSString stringWithFormat:@&amp;quot;%@&amp;quot;,&lt;br /&gt;
request.URL];&lt;br /&gt;
if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
// Close the WebView&lt;br /&gt;
[self performSelector:@selector(closeOptOutView)&lt;br /&gt;
withObject:nil afterDelay:0];&lt;br /&gt;
return NO;&lt;br /&gt;
}&lt;br /&gt;
// Retrieve next URL if it's not opt-in/out selection&lt;br /&gt;
return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.17 and above.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.12, refer to Opt-Out Implementation for iOS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to opt out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ &lt;br /&gt;
  // Handle it gracefully and retry later&lt;br /&gt;
} &lt;br /&gt;
 &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
  // show the view to the user&lt;br /&gt;
  [self.view addSubview:optOutView]; &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS’ system setting – “Limit Ad Tracking”. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the “Limit Ad Tracking” setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out_iOS.jpg]]&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to “About Nielsen Measurement” page for the users. Include “About Nielsen Measurement” and '''Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy_policy_iOS.jpg]]&lt;br /&gt;
&lt;br /&gt;
* URL to this web page should be called from SDK and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen’s SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;@property (readonly) BOOL optOutStatus;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
* App should provide a UI control like ‘close’ or ‘back’ button to close the ‘WebView’ / External browser.&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== Constants / Enumerations ===&lt;br /&gt;
The following are the details of Delegate Implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by a Event: %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
   – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by an Error: %@&amp;quot;, error);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== TVOS Implementation ====&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the client should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products are not used to identify consumer in any way. They help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows.&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking2.png]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Legacy Opt-Out ====&lt;br /&gt;
'''Supported SDK Versions''': 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 5.1.1.17 or above, refer to Opt-Out Implementation (Limit Ad Tracking).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in ‘WebView’ within the app and NOT in any external browser.&lt;br /&gt;
** Opening the Opt-Out page in any external browser takes the application control out of the Nielsen App SDK context.&lt;br /&gt;
** As the App SDK does not expose any direct http/https interface to interact with the world to get the user selection on Privacy page, there will be no way to interact/send notification to the App SDK regarding the user selection.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
Below are the steps to implement user Opt-Out using UIWebView.&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
&lt;br /&gt;
'''Implement WebView with Nielsen Opt-Out URL'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The Nielsen Privacy Page appears using UIWebView&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Privacy Page'''&lt;br /&gt;
&lt;br /&gt;
[[File:privacy-policy.jpg]]&lt;br /&gt;
&lt;br /&gt;
* There are two links – one for Opt-Out and one for Opt-In. Click the required link.&lt;br /&gt;
* Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
* The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the ‘WebView’. In order to do this, the application needs to&lt;br /&gt;
** Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
** Capture user’s selection&lt;br /&gt;
** Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Capture and forward user selection'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the ‘WebView’ URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
* &amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user’s selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ is closed, pass the status returned from ‘WebView’ to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== AppApiEventCode ==&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== AppApiErrorCode ===&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1046</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1046"/>
		<updated>2017-07-11T21:49:25Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Opt-Out Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ // Handle it gracefully and retry later} else&lt;br /&gt;
{[optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
// show the view to the user&lt;br /&gt;
[self.view addSubview:optOutView]; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(BOOL)webView:(UIWebView *)webView&lt;br /&gt;
shouldStartLoadWithRequest:(NSURLRequest *)request&lt;br /&gt;
navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
NSString *command = [NSString stringWithFormat:@&amp;quot;%@&amp;quot;,&lt;br /&gt;
request.URL];&lt;br /&gt;
if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
// Close the WebView&lt;br /&gt;
[self performSelector:@selector(closeOptOutView)&lt;br /&gt;
withObject:nil afterDelay:0];&lt;br /&gt;
return NO;&lt;br /&gt;
}&lt;br /&gt;
// Retrieve next URL if it's not opt-in/out selection&lt;br /&gt;
return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.17 and above.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.12, refer to Opt-Out Implementation for iOS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to opt out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ &lt;br /&gt;
  // Handle it gracefully and retry later&lt;br /&gt;
} &lt;br /&gt;
 &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
  // show the view to the user&lt;br /&gt;
  [self.view addSubview:optOutView]; &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS’ system setting – “Limit Ad Tracking”. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the “Limit Ad Tracking” setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out_iOS.jpg]]&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to “About Nielsen Measurement” page for the users. Include “About Nielsen Measurement” and '''Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy_policy_iOS.jpg]]&lt;br /&gt;
&lt;br /&gt;
* URL to this web page should be called from SDK and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen’s SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;@property (readonly) BOOL optOutStatus;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
* App should provide a UI control like ‘close’ or ‘back’ button to close the ‘WebView’ / External browser.&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== Constants / Enumerations ===&lt;br /&gt;
The following are the details of Delegate Implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by a Event: %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
   – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by an Error: %@&amp;quot;, error);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== TVOS Implementation ====&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the client should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products are not used to identify consumer in any way. They help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows.&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs_OptOut_LimitAdTracking2.png]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Legacy Opt-Out ====&lt;br /&gt;
'''Supported SDK Versions''': 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 5.1.1.17 or above, refer to Opt-Out Implementation (Limit Ad Tracking).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to Opt-Out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in ‘WebView’ within the app and NOT in any external browser.&lt;br /&gt;
** Opening the Opt-Out page in any external browser takes the application control out of the Nielsen App SDK context.&lt;br /&gt;
** As the App SDK does not expose any direct http/https interface to interact with the world to get the user selection on Privacy page, there will be no way to interact/send notification to the App SDK regarding the user selection.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
Below are the steps to implement user Opt-Out using UIWebView.&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
&lt;br /&gt;
'''Implement WebView with Nielsen Opt-Out URL'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The Nielsen Privacy Page appears using UIWebView&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Privacy Page'''&lt;br /&gt;
&lt;br /&gt;
[[File:privacy-policy.jpg]]&lt;br /&gt;
&lt;br /&gt;
* There are two links – one for Opt-Out and one for Opt-In. Click the required link.&lt;br /&gt;
* Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
* The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the ‘WebView’. In order to do this, the application needs to&lt;br /&gt;
** Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
** Capture user’s selection&lt;br /&gt;
** Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Capture and forward user selection'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
    NSString *command = [NSString stringWithFormat:@”%@”,request.URL];&lt;br /&gt;
    if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
        // Close the WebView&lt;br /&gt;
        [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];&lt;br /&gt;
        return NO;&lt;br /&gt;
    }&lt;br /&gt;
    // Retrieve next URL if it’s not opt-in/out selection&lt;br /&gt;
    return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the ‘WebView’ URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
* &amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user’s selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': When ‘WebView’ is closed, pass the status returned from ‘WebView’ to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== AppApiEventCode ===&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== AppApiErrorCode ===&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
	<entry>
		<id>https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1045</id>
		<title>iOS SDK API Reference</title>
		<link rel="alternate" type="text/html" href="https://nielsentest.mywikis.net/w/index.php?title=iOS_SDK_API_Reference&amp;diff=1045"/>
		<updated>2017-07-11T21:16:41Z</updated>

		<summary type="html">&lt;p&gt;Admin2: /* Opt-Out Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
The iOS SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc. These SDKs leverage the following:&lt;br /&gt;
*Nielsen audio watermark technologies for TV audience measurement&lt;br /&gt;
*The industry supported ID3 metadata tag specification&lt;br /&gt;
*Nielsen Combined Beacon technology&lt;br /&gt;
App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Application crash events&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Importing Frameworks ==&lt;br /&gt;
'''Setting up your Xcode Development Environment'''&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 7.0 and above.&lt;br /&gt;
&lt;br /&gt;
SDK uses the NSURLSession available from iOS 7 instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK supports devices running on iOS 9 and above, as all communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues (The sharedInstance API that creates a singleton object in previous versions of App SDK is removed).&lt;br /&gt;
*Maximum of four SDK instances per appid are supported in this release. When a fifth SDK instance is launched,&lt;br /&gt;
**SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
**Destroy one or more old SDK instances before creating new ones.&lt;br /&gt;
&lt;br /&gt;
=== Stages of SDK Initialization ===&lt;br /&gt;
==== Step 1: App SDK Initialization ====&lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Setting up event and error notifications ====&lt;br /&gt;
Once the &amp;lt;code&amp;gt;NielsenAppApi&amp;lt;/code&amp;gt; object has been initialized, the next step is to enable notifications regarding ID3 tags extracted from the playing stream. In case of standard AVFoundation player, the SDK NSNotificationCenter API is used to&lt;br /&gt;
* Collect HLS timed metadata events (ID3 tags) during viewing sessions.&lt;br /&gt;
** Set up a timed metadata event listener method for receiving ID3 tags and calling Nielsen [[sendID3]].&lt;br /&gt;
* SDK uses the following NielsenAppApiDelegate protocol methods to notify its delegate (set during initialization) about event / error information.&lt;br /&gt;
** nielsenAppApi:eventOccurred&lt;br /&gt;
** nielsenAppApi:errorOccurred&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Ensure to add to your view controller’s &amp;lt;code&amp;gt;@interface&amp;lt;/code&amp;gt;.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event {NSLog(@&amp;quot;Sample player is Notified by a Event : %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
(void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error {NSLog(@&amp;quot;Sample player is Notified by an Error : %@&amp;quot;, error);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sample event confirmation to player application upon successful initialization of SDK =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;NielsenSDKSampleDebug[9028:237989] [Nls:0] -I- Analytics framework Status:&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;Event Description&amp;quot; = &amp;quot;Nielsen App SDK Version, ai.4.0.0.4 is initialized by the Player…&amp;quot;;&lt;br /&gt;
EventStatus = 2001;&lt;br /&gt;
TimeStamp = &amp;quot;2015-07-23 14:51:06 +0000&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Nielsen App SDK Streaming Sessions ====&lt;br /&gt;
After setting up observers for SDK events/errors and a listener method to process incoming Nielsen ID3 tags, the next steps are to&lt;br /&gt;
* Call [[play]] while starting or resuming a streaming session.&lt;br /&gt;
* Load CMS metadata using [[loadMetadata]].&lt;br /&gt;
* During session play, call [[playheadPosition]] every one second until the stream is stopped or interrupted (due to ad breaks or buffering).&lt;br /&gt;
* Call [[stop]] when pausing, ending a viewing session, or buffering is detected.&lt;br /&gt;
&lt;br /&gt;
'''Serialized JSON string from NSDictionary'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
NSData* jsonDataAppInfo = [NSJSONSerialization dataWithJSONObject:appInformation options:0 error:nil];&lt;br /&gt;
NSString *jsonAppInfoString = [[NSString alloc] initWithData:jsonDataAppInfo encoding:NSUTF8StringEncoding];&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:jsonAppInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK object handles filtering of ID3 tags and CMS tags, queuing/buffering of data, and all communications with Nielsen collection facility.&lt;br /&gt;
&lt;br /&gt;
===== Nielsen iOS App SDK Application Life Cycle =====&lt;br /&gt;
&lt;br /&gt;
[[File:initialization_appcycle.png|center|link=]]&lt;br /&gt;
&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Call &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; to move into this state. The SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[sendID3]] – Call this API when ID3 tags are identified in the stream.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## [[appDisableApi]] is called&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and [[sendID3]] / [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Finite-state machine table ===&lt;br /&gt;
This table provides the possible changes of state for the SDK instance, when it is in a specific state and receives an API call.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! API call received !! Initial State !! Idle State !! Processing State !! Disabled State&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt; || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|| IDLE STATE || - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[play]]&amp;lt;/code&amp;gt; &amp;amp; &amp;lt;code&amp;gt;[[loadMetadata]]&amp;lt;/code&amp;gt;|| - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[playheadPosition]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[sendID3]]&amp;lt;/code&amp;gt; || - || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[stop]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[end]]&amp;lt;/code&amp;gt; || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: YES || - || DISABLED&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
|| - || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[appDisableApi]]&amp;lt;/code&amp;gt;: NO || - || - || - || IDLE STATE (OR)&lt;br /&gt;
&lt;br /&gt;
DISABLED STATE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: YES || - || - || IDLE STATE || -&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[[userOptOut]]&amp;lt;/code&amp;gt;: NO || - || PROCESSING&lt;br /&gt;
&lt;br /&gt;
STATE&lt;br /&gt;
| - &lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| colspan = 5 | '-' indicates that no API call is expected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
&lt;br /&gt;
==== JSON for NSDictionary object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NSDictionary* appInformation = @{&lt;br /&gt;
                                  @&amp;quot;appid&amp;quot;: @&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appname&amp;quot;: @&amp;quot;Sample App Name&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;sfcode&amp;quot;: @&amp;quot;uat-cert&amp;quot;,&lt;br /&gt;
                                  @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
                                };&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;appversion&amp;lt;/code&amp;gt; are mandatory parameters while &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt; is optional. &amp;lt;code&amp;gt;nol_devDebug&amp;lt;/code&amp;gt; is meant for creating logs in test environments only.&lt;br /&gt;
&lt;br /&gt;
==== JSON string from raw NSString ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;NSString *appInfoString = @&amp;quot;{\&amp;quot;appid\&amp;quot; : \&amp;quot;TXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\&amp;quot;, \&amp;quot;appname\&amp;quot; : \&amp;quot;Sample App Name\&amp;quot;,\&amp;quot;appversion\&amp;quot; : \&amp;quot;2.0\&amp;quot;,\&amp;quot;sfcode\&amp;quot; : \&amp;quot;uat-cert\&amp;quot;}&amp;quot;;&lt;br /&gt;
NielsenAppAPi *appAPI = [[NielsenAppApi alloc] initWithAppInfo:appInfoString delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== JSON string from serialized NSDictionary ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NSDictionary* appInformation = @&lt;br /&gt;
{&lt;br /&gt;
@&amp;quot;appid&amp;quot;: @&amp;quot;appid&amp;quot;,&lt;br /&gt;
@&amp;quot;appname&amp;quot;: @&amp;quot;appname&amp;quot;,&lt;br /&gt;
@&amp;quot;appversion&amp;quot;: @&amp;quot;2.0&amp;quot;,&lt;br /&gt;
@&amp;quot;sfcode&amp;quot;: @&amp;quot;sfcode&amp;quot;,&lt;br /&gt;
@&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;INFO&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
nlsAppApiMeter = [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:self];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While using JSON format for sending metadat, ensure enough care in including [[special characters]] in the values for arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;{&lt;br /&gt;
@&amp;quot;type&amp;quot;: @&amp;quot;radio&amp;quot;, // To send &amp;quot;radio&amp;quot; in metadata string&lt;br /&gt;
@&amp;quot;assetid&amp;quot;: @&amp;quot;WXYZ-FM'101&amp;quot;,&lt;br /&gt;
@&amp;quot;stationType&amp;quot;: @&amp;quot;3&amp;quot;,&lt;br /&gt;
@&amp;quot;provider&amp;quot;: @&amp;quot;SampleProvider&amp;quot; // To send &amp;quot;SampleProvider&amp;quot; in metadata string&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For mandatory parameters like appid, appname, and appversion, please refer to the parameters table in &amp;lt;code&amp;gt;[[initWithAppInfo:delegate:]]&amp;lt;/code&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving ID3 Tags ==&lt;br /&gt;
ID3 tags have a payload of about 249 characters and start with &amp;quot;www.nielsen.com&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ID3 tags are extracted by observing a property called timedMetadata on the iOS player item. Now this is done via a concept called KVO (Key Value Observing), where you register interest in a property, and the runtime will let you know when it has changed.&lt;br /&gt;
&lt;br /&gt;
Both the iOS native players have the ability to extract ID3 tags, If any other player apart from iOS native players (AVPlayer, MPMoviePlayer) is used, check and ensure that the player has the capability to extract ID3 tags.&lt;br /&gt;
&lt;br /&gt;
=== Sample ID3 tags ===&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_&amp;lt;wbr /&amp;gt;JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe&amp;lt;wbr /&amp;gt;Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8&amp;lt;wbr /&amp;gt;QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Examples of extracting ID3 tags from the iOS Native Player ===&lt;br /&gt;
==== AVPlayer ====&lt;br /&gt;
ID3 tags will be received in the Player on AVMetadataItem Callback method.&lt;br /&gt;
'''Create &amp;amp; get the AVMetadataItem callback method'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;[self.player addObserver:self&lt;br /&gt;
        forKeyPath: kTimedMetadataKey&lt;br /&gt;
        options: NSKeyValueObservingOptionNew&lt;br /&gt;
        Context: MyStreamingMovieViewControllerTimedMetadataObserverContext];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)observeValueForKeyPath:(NSString*) path&lt;br /&gt;
                      ofObject: (id)object&lt;br /&gt;
                        change: (NSDictionary*)change&lt;br /&gt;
                       context: (void*)context&lt;br /&gt;
{&lt;br /&gt;
/* Set the AVPlayerLayer on the view to allow the AVPlayer object to display&lt;br /&gt;
     its content. */&lt;br /&gt;
    //[playerLayerView.playerLayer setPlayer:player];&lt;br /&gt;
/* AVPlayerItem &amp;quot;status&amp;quot; property value observer. */&lt;br /&gt;
if (context == MyStreamingMovieViewControllerTimedMetadataObserverContext)&lt;br /&gt;
        {&lt;br /&gt;
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];&lt;br /&gt;
            if (newMetadataArray != [NSNull null])&lt;br /&gt;
            {&lt;br /&gt;
                array = newMetadataArray;&lt;br /&gt;
                for (AVMetadataItem *metadataItem in array)&lt;br /&gt;
                  {&lt;br /&gt;
                    [self handleTimedMetadata: metadataItem];&lt;br /&gt;
                  }&lt;br /&gt;
            }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata: (AVMetadataItem*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
/* We expect the content to contain plists encoded as timed metadata. AVPlayer turns these into NSDictionaries. */&lt;br /&gt;
    id extraAttributeType = [timedMetadata extraAttributes];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
   if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
   {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
/* The  sendID3: sends the extracted Nielsen ID3 payload to the App SDK for analysis. */&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata stringValue];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
               // NSString *strMessage=[[@&amp;quot;ID3 Tag Received &amp;quot; stringByAppendingFormat:@&amp;quot;%d\n&amp;quot;,countForMetadata] stringByAppendingString:value];&lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Movie Player ====&lt;br /&gt;
ID3 tags will be received in the Player on MPTimedMetadata Callback method.&lt;br /&gt;
'''Sample Implementation of MPTimedMetadata callback'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void)handleTimedMetadata:(MPTimedMetadata*)timedMetadata&lt;br /&gt;
{&lt;br /&gt;
    id extraAttributeType = [timedMetadata  allMetadata];&lt;br /&gt;
    NSString * extraString= nil;&lt;br /&gt;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = [extraAttributeType valueForKey:@&amp;quot;info&amp;quot;];&lt;br /&gt;
    }&lt;br /&gt;
    else if([extraAttributeType isKindOfClass:[NSString class]])&lt;br /&gt;
    {&lt;br /&gt;
        extraString = extraAttributeType;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
  if ([(NSString *)[timedMetadata key] isEqualToString:@&amp;quot;PRIV&amp;quot;]&amp;amp;&amp;amp;[extraString rangeOfString:@&amp;quot;www.nielsen.com&amp;quot;].length&amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
     if ([[timedMetadata value] isKindOfClass:[NSData class]])&lt;br /&gt;
      {&lt;br /&gt;
            // Sending ID3 Tag&lt;br /&gt;
            [[NielsenAppApi sharedInstance]sendID3: extraString];&lt;br /&gt;
            NSString *value=[timedMetadata value];&lt;br /&gt;
            if (value != nil)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;br /&gt;
                [self appendLogConsoleText:extraString];&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        NSLog(@&amp;quot;Could not send ID3 tags&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    countForMetadata++;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' ID3 tags are not applicable for International (Germany)&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IOS SDK API Methods &amp;amp; Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Scenario !! Method / Property !! DTVR !! DAR !! Digital Audio !! DCR !! International (Germany) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Initialize || [[initWithAppInfo:delegate:]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to create a new instance of the SDK object&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[play]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when there is an ID3 fed product such as DTVR and the client does not want to send in all the CMS metadata that is sent in loadMetadata. This allows the client to send in at least the required “channel name” value associated to the ID3 feed. If this is not called then the “channel name” value populated will be the default value of “defaultChannelName”.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[loadMetadata]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to send ad or content metadata to the SDK in the form of JSON string. Application constructs a JSON hashmap and calls this API.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[sendID3]] || ✔ || ✘ || ✘ || ✘ || ✘ || Used to send the ID3 metadata.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[playheadPosition]] || ✘ || ✘ || ✔ || ✔ || ✔ || Used to send the playhead position.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[stop]] || ✔ || ✘ || ✔ || ✔ || ✔ || Used when playback is paused and when switching between ad and content or content and ad.&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[end]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used when content playback is complete. This is triggered 1) at the end of the content stream, 2) if the user switches to another piece of content&lt;br /&gt;
|-&lt;br /&gt;
| Measurement || [[updateOTT]] || ✘ || ✘ || ✘ || ✘ || ✔ || Used to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutURL]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to fetch the Nielsen opt-out web page URL.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[userOptOut]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to supply the response message from opt-out webpage to the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out || [[optOutStatus]] || ✔ || ✔ || ✔ || ✔ || ✔ || Call this API to retrieve the Opt-Out or Opt-In state.&lt;br /&gt;
|-&lt;br /&gt;
| Opt-out&lt;br /&gt;
| [[appDisableApi]]&lt;br /&gt;
(kill switch) &lt;br /&gt;
|| ✔ || ✔ || ✔ || ✔ || ✔ || Used to disable the SDK.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastErrorDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK error in the form of dictionary if any error has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[lastEventDict]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns SDK event in the form of dictionary if any event has occurred.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[meterVersion]] || ✔ || ✔ || ✔ || ✔ || ✔ || Returns the current SDK version.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[nielsenId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to get a string defining the Nielsen ID (NUID) number for the device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[demographicId]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to retrieve Demographic ID (Device ID) of the current device.&lt;br /&gt;
|-&lt;br /&gt;
| Log || [[debug]] || ✔ || ✔ || ✔ || ✔ || ✔ || Used to enable/disable debug flags. Newly introduced in SDK version 5.0.0 for International (Germany)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;About Nielsen Measurement&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking [[optOutURL]] and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ // Handle it gracefully and retry later} else&lt;br /&gt;
{[optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
// show the view to the user&lt;br /&gt;
[self.view addSubview:optOutView]; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
=== Sequence Diagram ===&lt;br /&gt;
[[File:optoutsequence-ios.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''5.1.1.17 or above''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Versions 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12, skip ahead to: [[#Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12|Opt-out SDK Version 1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-out SDK Version '''1.2.3, 4.0.0.8, 5.1.0, 5.1.1.12''' ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' If using SDK Version 5.1.1.17 or above, refer to documentation above ([[#Opt-out SDK Version 5.1.1.17 or above|Opt-out SDK Version 5.1.1.17 or above]])&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a user clicks the Opt-Out / Opt-In link, the application should invoke [[optOutURL]] to get the link to the Nielsen Privacy page from SDK.&lt;br /&gt;
=== Privacy Page ===&lt;br /&gt;
[[File:privacy-policy.jpg|link=]]&lt;br /&gt;
*There are two click here links – one for Opt-Out and one for Opt-In. Click the required link:&lt;br /&gt;
**&lt;br /&gt;
[[File:Opt-Out Combined.jpg|link=]]&lt;br /&gt;
*Click OK in the dialog that appears, to confirm the action.&lt;br /&gt;
*The Opt-Out occurs by opening a Nielsen-defined web page and passing the user choice from the 'WebView'. In order to do this, the application needs to&lt;br /&gt;
**Implement the UIWebView delegate method to open the Nielsen Privacy web page&lt;br /&gt;
**Capture user's selection&lt;br /&gt;
**Pass the selection back to the SDK via the [[userOptOut]].&lt;br /&gt;
&lt;br /&gt;
=== Capture and forward user selection ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(BOOL)webView:(UIWebView *)webView&lt;br /&gt;
shouldStartLoadWithRequest:(NSURLRequest *)request&lt;br /&gt;
navigationType:(UIWebViewNavigationType)navigationType&lt;br /&gt;
{&lt;br /&gt;
NSString *command = [NSString stringWithFormat:@&amp;quot;%@&amp;quot;,&lt;br /&gt;
request.URL];&lt;br /&gt;
if ([command isEqualToString:kNielsenWebClose]) {&lt;br /&gt;
// Close the WebView&lt;br /&gt;
[self performSelector:@selector(closeOptOutView)&lt;br /&gt;
withObject:nil afterDelay:0];&lt;br /&gt;
return NO;&lt;br /&gt;
}&lt;br /&gt;
// Retrieve next URL if it's not opt-in/out selection&lt;br /&gt;
return (![nAppApiObject userOptOut:command]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*The app gets the user selection string via webviews shouldStartLoadWithRequest and invokes [[userOptOut]] with user selection. The delegate method handles the 'WebView' URL requests, interprets the commands, and calls the SDK accordingly.&lt;br /&gt;
**&amp;lt;code&amp;gt;[nAppApiObject userOptOut:command]&amp;lt;/code&amp;gt; passes the user's selection on Nielsen Privacy page to the SDK to allow the SDK to perform the required functions.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When 'WebView' is closed, pass the status returned from 'WebView' to the SDK within the app.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user's choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TVOS Opt-out ==&lt;br /&gt;
To Opt-Out, users must have access to “About Nielsen Measurement” page.&lt;br /&gt;
&lt;br /&gt;
TVOS does not support creating instances of UIWebView and display web pages. Instead it makes use of a TVML page (built on TVML template) which displays information in a specific order.&lt;br /&gt;
&lt;br /&gt;
Opt-Out page is built on descriptiveAlertTemplate and appears as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
[[File:TVOs OptOut LimitAdTracking2.png|link=]]&lt;br /&gt;
&lt;br /&gt;
Users need to toggle the “Limit Ad Tracking” option in order to Opt-In / Opt-Out of Nielsen Measurement.&lt;br /&gt;
&lt;br /&gt;
To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NielsenAppApi Class Description ==&lt;br /&gt;
The NielsenAppApi class is the primary application interface to the Nielsen App SDK. For example, after an instance object of the NielsenAppApi class is created and initialized, it can be used by the calling application to collect HLS timed metadata using the SDK’s [[sendID3]]: method. These are the public methods and properties exposed by the NielsenAppApi class:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@interface NielsenAppApi: NSObject&lt;br /&gt;
&lt;br /&gt;
  @property (readonly) BOOL optOutStatus;&lt;br /&gt;
  @property (assign) BOOL appDisableApi;&lt;br /&gt;
  @property (assign) BOOL debug;&lt;br /&gt;
  @property (readonly) NSString *nielsenId;&lt;br /&gt;
  @property (readonly) NSString *demographicId;&lt;br /&gt;
  @property (readonly) NSString *optOutURL;&lt;br /&gt;
  @property (readonly) NSString *meterVersion;&lt;br /&gt;
  @property (readonly) NSDictionary *lastEventDict;&lt;br /&gt;
  @property (readonly) NSDictionary *lastErrorDict;&lt;br /&gt;
&lt;br /&gt;
  – (instancetype)initWithAppInfo:(id)appInfo delegate:(id)delegate;&lt;br /&gt;
&lt;br /&gt;
  – (void)play:(id)channelInfo;&lt;br /&gt;
  – (void)loadMetadata:(id)metadata;&lt;br /&gt;
  – (void)stop;&lt;br /&gt;
  – (void)end;&lt;br /&gt;
  – (void)playheadPosition:(long long)playheadPos;&lt;br /&gt;
  – (void)sendID3:(NSString *)data;&lt;br /&gt;
  – (void)updateOTT:(id)ottInfo;&lt;br /&gt;
  – (BOOL)userOptOut:(NSString *)optOut;&lt;br /&gt;
&lt;br /&gt;
  – (NSString *)getNielsenId _attribute((deprecated((“Please use nielsenId property instead.”))));&lt;br /&gt;
  – (NSString *)optOutURLString _attribute((deprecated((“Please use optOutURL property instead.”))));&lt;br /&gt;
  – (NSString *)getMeterVersion _attribute((deprecated((“Please use meterVersion property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastEventDict _attribute((deprecated((“Please use lastEventDict property instead.”))));&lt;br /&gt;
  – (NSDictionary *)getLastErrorDict _attribute((deprecated((“Please use lastErrorDict property instead.”))));&lt;br /&gt;
&lt;br /&gt;
  @protocol NielsenAppApiDelegate&amp;lt;NSObject&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  @optional&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event;&lt;br /&gt;
  – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nielsen Sample Applications ==&lt;br /&gt;
Nielsen iOS sample player application consists of two sample application based on native Players integrated with SDK framework. The player demonstrates all the supported functions of the SDK.&lt;br /&gt;
*NielsenVideoPlayer&lt;br /&gt;
*NielsenRadioPlayer&lt;br /&gt;
Implementation of Video and Audio sample apps is based on native iOS AVPlayer.&lt;br /&gt;
&lt;br /&gt;
The UI components of the iOS App SDK sample applications are common to both as shown below.&lt;br /&gt;
*From the Channel Selection buttons ⬇️ &amp;amp; ⬆️ , the user will be able select the channels to stream.&lt;br /&gt;
*The Info button ℹ️ displays information of the SDK version, current Nielsen ID used for the device, and the option for opt-out/opt-in.&lt;br /&gt;
*The Play ▶️ and Pause ⏸️ buttons will control the streaming of the selected channel.&lt;br /&gt;
*The area at the bottom of the window displays the current stream status.&lt;br /&gt;
*The Clear button 🔃 clears out the status window.&lt;br /&gt;
*The Email button 📧 can be used to email the tags and status in a text file to Nielsen.&lt;br /&gt;
If target device supports Picture-in-Picture playing, it could be activated by PIP button in the Video player window.&lt;br /&gt;
*Channel URLs and metadata are obtained from two locations:&lt;br /&gt;
**Channels 1 and 2 are configured from the Settings application. Channel URLs and metadata parameters can be modified.&lt;br /&gt;
**Channels starting from 3 are configured in specific JSON file. URLs to this JSON config file can be changed from the Settings application.&lt;br /&gt;
&lt;br /&gt;
== Nielsen Privacy Requirements ==&lt;br /&gt;
Privacy protections that Nielsen ensures to have with each App SDK integration are as follows.&lt;br /&gt;
*Disclosure of viewership data collection in app store description&lt;br /&gt;
*Disclosure of viewership data collection in EULA / Privacy Policy&lt;br /&gt;
*A link in the EULA/Privacy policy, or in another conspicuous location within the App, to a Nielsen-hosted web page outlining what Nielsen is collecting and how it is being used&lt;br /&gt;
*Method for users to opt-out of Nielsen measurement, any time while using the application&lt;br /&gt;
&lt;br /&gt;
=== Ratings Data Flow ===&lt;br /&gt;
Every view of creditable and watermarked content is measured by Nielsen.&lt;br /&gt;
[[File:RatingsDataFlow.png]]&lt;br /&gt;
&lt;br /&gt;
'''Information NOT Shared'''&lt;br /&gt;
* '''With Nielsen'''&lt;br /&gt;
** User's Identity&lt;br /&gt;
* '''With Data Provider'''&lt;br /&gt;
** Content information&lt;br /&gt;
** Whether user is viewing an ad or video content&lt;br /&gt;
** Player used to play the streaming (audio / video, etc.)&lt;br /&gt;
** Values being de-duped / aggregating for&lt;br /&gt;
&lt;br /&gt;
Nielsen collects only what it needs for audience measurement. Every view of creditable, watermarked content will be measured by Nielsen.&lt;br /&gt;
&lt;br /&gt;
=== Data Collected ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type of Information !! Parameter !! Transmitted to Nielsen? !! Sent to Provider?&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | Nielsen ID3 Watermark&lt;br /&gt;
|-&lt;br /&gt;
| FinalDistributor Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Program Content Timestamp || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Mobile Breakout Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Commercial Credit Code – Linear or Dynamic || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Time ShiftedViewing Code || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment Number || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Segment View Pattern || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;10&amp;quot; | Device/App Info&lt;br /&gt;
|-&lt;br /&gt;
| Device OSVersion || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Device Model || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Device Advertiser ID (Apple IDFA or Google AdID/Android ID) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Cache Buster || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| App Version || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| App Name || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| SDKDisabled Flag || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| ServerCode || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Channel or URL || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;9&amp;quot; | Nielsen Identifiers&lt;br /&gt;
|-&lt;br /&gt;
| Client ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Campaign ID || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| Nielsen Unique Device ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| Application ID || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| DeviceGroup (ex. Tablet, Smartphone, Desktop) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| OS Group (ex. Android, iOS, Windows) || Yes || Yes &lt;br /&gt;
|-&lt;br /&gt;
| SDKVersion || Yes || No&lt;br /&gt;
|-&lt;br /&gt;
| IP Address for DMA, Country Code || Yes || Yes &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Data is hashed, and encrypted using AES 128 before transmission to data provider.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ping sent to provider ====&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;https://provider.com/cgi-bin/brandlift.php&amp;lt;/nowiki&amp;gt;?campaign_id=ff12725d724fac7934cf6003f096b4cd&amp;lt;wbr /&amp;gt;&amp;amp;placement_id=a4164b8fba9ee7c873a9c72c7091bb58&amp;lt;wbr /&amp;gt;&amp;amp;creative_id=25280139b61a947e127a52f56c8a2fdd&amp;lt;wbr /&amp;gt;&amp;amp;segment1=9000&amp;lt;wbr /&amp;gt;&amp;amp;segment2=41&amp;lt;wbr /&amp;gt;&amp;amp;segment3=iOS&amp;lt;wbr /&amp;gt;&amp;amp;OSVer=iOS6.1&amp;lt;wbr /&amp;gt;&amp;amp;c9=&amp;lt;wbr /&amp;gt;&amp;amp;devgrp=tablet&amp;lt;wbr /&amp;gt;&amp;amp;h=f5f243fe6d&amp;lt;wbr /&amp;gt;&amp;amp;rnd=1376971827360&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This ping passes the following parameters to the provider:&lt;br /&gt;
* Campaign ID – (campaign, placement, creative)&lt;br /&gt;
* Country Code&lt;br /&gt;
* DMA&lt;br /&gt;
* OS Group (ex. iOS, Android)&lt;br /&gt;
* DeviceOS Version&lt;br /&gt;
* Device Advertiser ID&lt;br /&gt;
* DeviceGroup (ex. Tablet, Smartphone, Desktop)&lt;br /&gt;
* Cache Buster&lt;br /&gt;
&lt;br /&gt;
=== Nielsen Measurement Opt-Out ===&lt;br /&gt;
In accordance with Nielsen’s SDK licensing agreement, developers are required to provide basic informational data to users about Nielsen’s Privacy Policy with a navigation to additional information on Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
Nielsen currently uses Limit Ad Tracking for the latest versions of the SDK (5.1.1.17 and above). However, for older SDK versions, the app must provide a means for the user to opt out, or opt back in to Nielsen Measurement. Users can opt out of Nielsen online measurement research through this feature.&lt;br /&gt;
* If the user has this app running on more than one mobile device, the user will need to opt out of this measurement on each device.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': Opt Out feature does NOT rely on &amp;quot;Limit Ad Tracking&amp;quot; setting since Nielsen’s systems provide measurement metrics and do not serve ads to users.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the Description of the app in App Store, include a short description about Nielsen measurement, as below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Sample App Store Disclosure'''&lt;br /&gt;
This app features Nielsen proprietary measurement software which will allow you to contribute to market research, like Nielsen’s TV Ratings.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy for more information.&lt;br /&gt;
&lt;br /&gt;
[[File:measurement-samplescreen.jpg]]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both iOS-based and TVOS-based player applications need to confirm to Nielsen Privacy Requirements. Refer to the Opt-Out implementation guidelines for iOS and TVOS platforms respectively for more details.&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
==== Limit Ad Tracking ====&lt;br /&gt;
'''This implementation is valid for SDK Versions 5.1.1.17 and above.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': If using SDK Version 1.2.3, 4.0.0.8, 5.1.0 or 5.1.1.12, refer to Opt-Out Implementation for iOS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a global information and measurement leader, Nielsen is committed to protect the privacy and security of the data they collect, process and use. Nielsen strongly believes that the consumer should have a way to opt out of Nielsen measurement.&lt;br /&gt;
&lt;br /&gt;
The Nielsen digital measurement products help Nielsen and its clients to measure and analyze how consumers engage with media across online, mobile and emerging technologies while offering insights into consumer behavior.&lt;br /&gt;
&lt;br /&gt;
To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.&lt;br /&gt;
&lt;br /&gt;
To opt out, users must have access to “About Nielsen Measurement” page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
* URL to this web page should be called from SDK by invoking optOutURL and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status of a device, use the optOutStatus method.&lt;br /&gt;
'''Displaying Opt-Out in a WebView'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebView alloc]initWithFrame:self.view.bounds];&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = [nAppApiObject optOutURLString];&lt;br /&gt;
If(webAddress == nil)&lt;br /&gt;
{ &lt;br /&gt;
  // Handle it gracefully and retry later&lt;br /&gt;
} &lt;br /&gt;
 &lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
  // show the view to the user&lt;br /&gt;
  [self.view addSubview:optOutView]; &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS’ system setting – “Limit Ad Tracking”. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the “Limit Ad Tracking” setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out_iOS.jpg]]&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to “About Nielsen Measurement” page for the users. Include “About Nielsen Measurement” and '''Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app’s Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy_policy_iOS.jpg]]&lt;br /&gt;
&lt;br /&gt;
* URL to this web page should be called from SDK and opened in ‘WebView’ / External browser.&lt;br /&gt;
* If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
* To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen’s SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;@property (readonly) BOOL optOutStatus;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
* App should provide a UI control like ‘close’ or ‘back’ button to close the ‘WebView’ / External browser.&lt;br /&gt;
&lt;br /&gt;
'''Sequence Diagram'''&lt;br /&gt;
[[File:optoutsequence-ios.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Event and Error Handling ==&lt;br /&gt;
=== Constants / Enumerations ===&lt;br /&gt;
The following are the details of Delegate Implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
-(void)nielsenAppApi:(NielsenAppApi *)appApi eventOccurred:(NSDictionary *)event&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by a Event: %@&amp;quot;, event);&lt;br /&gt;
}&lt;br /&gt;
   – (void)nielsenAppApi:(NielsenAppApi *)appApi errorOccurred:(NSDictionary *)error&lt;br /&gt;
{&lt;br /&gt;
   NSLog(@&amp;quot;Sample player is Notified by an Error: %@&amp;quot;, error);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== AppApiEventCode ===&lt;br /&gt;
An enumeration with predefined App SDK event state transition codes.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiEventCode)&lt;br /&gt;
{&lt;br /&gt;
     AppApiStartup = 2001,&lt;br /&gt;
     AppApiShutdown = 2002,&lt;br /&gt;
}AppApiEventCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Event Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 2001 || AppApiStartup || App SDK has initialized successfully. It will happen only after App SDK has received a valid config file&lt;br /&gt;
|-&lt;br /&gt;
| 2002 || AppApiShutdown || App SDK is shutting down. It will happen just before App SDK is destroyed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== AppApiErrorCode ===&lt;br /&gt;
An enumeration with predefined error codes which the App SDK object can generate.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
typedef NS_ENUM(unsigned int, AppApiErrorCode)&lt;br /&gt;
{&lt;br /&gt;
   AppApiNetworkConnectionFailure = 1001,&lt;br /&gt;
   AppApiFileWriteFailure = 1002,&lt;br /&gt;
   AppApiFileReadFailure = 1003,&lt;br /&gt;
   AppApiEmptyValue = 1004,&lt;br /&gt;
   AppApiEmptyAppName = 1005,&lt;br /&gt;
   AppApiEmptyAppVersion = 1006,&lt;br /&gt;
   AppApiEmptyAppId = 1007,&lt;br /&gt;
   AppApiAnExceptionOccured = 1008,&lt;br /&gt;
   AppApiUnknownExceptionOccured = 1009&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== App SDK Error Codes ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Code !! Event Name !! Event Description&lt;br /&gt;
|-&lt;br /&gt;
| 1001 || AppApiNetworkConnectionFailure || App SDK Could not connect to server&lt;br /&gt;
|-&lt;br /&gt;
| 1002 || AppApiFileWriteFailure || App SDK Could not write to file&lt;br /&gt;
|-&lt;br /&gt;
| 1003 || AppApiFileReadFailure || App SDK Could not read data from file&lt;br /&gt;
|-&lt;br /&gt;
| 1004 || AppApiEmptyValue || Empty value Found.&lt;br /&gt;
|-&lt;br /&gt;
| 1005 || AppApiEmptyAppName || Cannot initialize SDK Object without an AppName(Player Name)&lt;br /&gt;
|-&lt;br /&gt;
| 1006 || AppApiEmptyAppVersion || Cannot initialize API Object without an AppVersion&lt;br /&gt;
|-&lt;br /&gt;
| 1007 || AppApiEmptyAppId || Cannot initialize API Object without an AppId&lt;br /&gt;
|-&lt;br /&gt;
| 1008 || AppApiAnExceptionOccured || Exception occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1009 || AppApiUnknownExceptionOccured || Unknown exception occurred&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Admin2</name></author>
	</entry>
</feed>