Since April 25, 2023, Apple has required apps submitted to the App Store to be built with Xcode 14.1 or later. The Experience Platform Mobile SDKs and extensions outlined below were built with prior versions of Xcode and are no longer compatible with iOS and iPadOS given Apple’s current App Store requirements. Consequently, on August 31, 2023, Adobe will be deprecating support for the following Experience Platform Mobile SDKs and wrapper extensions:
After August 31, 2023, applications already submitted to the App Store that contain these SDKs and wrapper extensions will continue to operate, however, Adobe will not be providing security updates or bug fixes, and these SDKs and wrapper extensions will be provided as-is exclusive of any warranty, due to the App Store policy outlined above.
We encourage all customers to migrate to the latest Adobe Experience Platform versions of the Mobile SDK to ensure continued compatibility and support. Documentation for the latest versions of the Adobe Experience Platform Mobile SDKs can be found here. The iOS migration guide can be found here.
Xamarin development requires the installation of Microsoft Visual Studio. Information regarding installation for Xamarin development is available for Mac or Windows.
An Apple developer account and the latest version of Xcode (available from the App Store) are required if you are building an iOS or tvOS app.
Package Manager Installation
The ACPCore Xamarin NuGet package for Android or iOS or tvOS can be added to your project by right clicking the "Packages" folder within the project you are working on then selecting "Manage NuGet Packages". In the window that opens, ensure that your selected source is nuget.org
and search for "Adobe.ACP". After selecting the Xamarin AEP SDK packages that are required, click on the "Add Packages" button. After exiting the "Add Packages" menu, right click the main solution or the "Packages" folder and select "Restore" to ensure the added packages are downloaded.
Manual installation
Local ACPCore NuGet packages can be created via the included Makefile. If building for the first time, run:
make setup
followed by:
make release
The created NuGet packages can be found in the bin
directory. This directory can be added as a local nuget source and packages within the directory can be added to a Xamarin project following the steps in the "Package Manager Installation" above.
The ACPCore binding can be opened by loading the ACPCoreBinding.sln with Visual Studio. The following targets are available in the solution:
- Adobe.ACPCore.iOS - The ACPCore iOS bindings which includes ACPCore, ACPIdentity, ACPLifecycle, and ACPSignal.
- Adobe.ACPCore.tvOS - The ACPCore tvOS bindings which includes ACPCore, ACPIdentity, ACPLifecycle, and ACPSignal.
- Adobe.ACPCore.Android - The ACPCore Android binding.
- Adobe.ACPCoreBridge.Android - The ACPCoreBridge Android binding. This is used by the Xamarin Android ACPGriffon binding to correctly start a Griffon session from within an app activity.
- Adobe.ACPCIdentity.Android - The ACPIdentity Android binding.
- Adobe.ACPLifecycle.Android - The ACPLifecycle Android binding.
- Adobe.ACPSIgnal.Android - The ACPSignal Android binding.
- ACPCoreTestApp - The Xamarin.Forms base app used by the iOS and Android test apps.
- ACPCoreTestApp.iOS - The Xamarin.Forms based iOS manual test app.
- ACPCoreTestApp.tvOS - The Storyboard based tvOS manual test app.
- ACPCoreTestApp.Android - The Xamarin.Forms based Android manual test app.
- ACPCoreiOSUnitTests - iOS unit test app.
- ACPCoreAndroidUnitTests - Android unit test app.
iOS:
// Import the SDK
using Com.Adobe.Marketing.Mobile;
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
// set the wrapper type
ACPCore.SetWrapperType(ACPMobileWrapperType.Xamarin);
// set launch config
ACPCore.ConfigureWithAppID("yourAppId");
// register SDK extensions
ACPIdentity.RegisterExtension();
ACPLifecycle.RegisterExtension();
ACPSignal.RegisterExtension();
// start core
ACPCore.Start(null);
// register dependency service to link interface from App base project
DependencyService.Register<IExtensionService, ExtensionService>();
return base.FinishedLaunching(app, options);
}
Android:
// Import the SDK
using Com.Adobe.Marketing.Mobile;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
// set the wrapper type
ACPCore.SetWrapperType(WrapperType.Xamarin);
// set launch config
ACPCore.ConfigureWithAppID("yourAppId");
// register SDK extensions
ACPCore.Application = this.Application;
ACPIdentity.RegisterExtension();
ACPLifecycle.RegisterExtension();
ACPSignal.RegisterExtension();
// start core
ACPCore.Start(null);
// register dependency service to link interface from App base project
DependencyService.Register<IExtensionService, ExtensionService>();
}
iOS and Android
Console.WriteLine(ACPCore.ExtensionVersion());
iOS
var config = new NSMutableDictionary<NSString, NSObject>
{
["someConfigKey"] = new NSString("configValue")
};
ACPCore.UpdateConfiguration(config);
Android
var config = new Dictionary<string, Java.Lang.Object>();
config.Add("someConfigKey", "configValue");
ACPCore.UpdateConfiguration(config);
iOS
ACPCore.LogLevel = ACPMobileLogLevel.Error;
ACPCore.LogLevel = ACPMobileLogLevel.Warning;
ACPCore.LogLevel = ACPMobileLogLevel.Debug;
ACPCore.LogLevel = ACPMobileLogLevel.Verbose;
Android
ACPCore.LogLevel = LoggingMode.Error;
ACPCore.LogLevel = LoggingMode.Warning;
ACPCore.LogLevel = LoggingMode.Debug;
ACPCore.LogLevel = LoggingMode.Verbose;
iOS
var callback = new Action<ACPMobilePrivacyStatus>(handleCallback);
ACPCore.GetPrivacyStatus(callback);
private void handleCallback(ACPMobilePrivacyStatus privacyStatus)
{
Console.WriteLine("Privacy status: " + privacyStatus.ToString());
}
Android
ACPCore.GetPrivacyStatus(new StringCallback());
class StringCallback : Java.Lang.Object, IAdobeCallback
{
public void Call(Java.Lang.Object stringContent)
{
if (stringContent != null)
{
Console.WriteLine(stringContent);
}
else
{
Console.WriteLine("null content in string callback");
}
}
}
iOS
ACPCore.SetPrivacyStatus(ACPMobilePrivacyStatus.OptIn);
Android
ACPCore.SetPrivacyStatus(MobilePrivacyStatus.OptIn);
iOS
var callback = new Action<NSString>(handleCallback);
ACPCore.GetSdkIdentities(callback);
private void handleCallback(NSString content)
{
Console.WriteLine("String callback: " + content);
}
Android
ACPCore.GetSdkIdentities(new StringCallback());
class StringCallback : Java.Lang.Object, IAdobeCallback
{
public void Call(Java.Lang.Object stringContent)
{
if (stringContent != null)
{
Console.WriteLine(stringContent);
}
else
{
Console.WriteLine("null content in string callback");
}
}
}
iOS
var data = new NSMutableDictionary<NSString, NSObject>
{
["dispatchResponseEventKey"] = new NSString("dispatchResponseEventValue")
};
ACPExtensionEvent sdkEvent = ACPExtensionEvent.ExtensionEventWithName("eventName", "eventType", "eventSource", data, out _);
ACPCore.DispatchEvent(sdkEvent, out error);
Android
var data = new Dictionary<string, Java.Lang.Object>();
data.Add("testEvent", true);
Event sdkEvent = new Event.Builder("eventName", "eventType", "eventSource").SetEventData(data).Build();
ACPCore.DispatchEvent(sdkEvent, new ErrorCallback());
class ErrorCallback : Java.Lang.Object, IExtensionErrorCallback
{
public void Call(Java.Lang.Object sdkEvent)
{
Console.WriteLine("AEP SDK event data: " + sdkEvent.ToString());
}
public void Error(Java.Lang.Object error)
{
Console.WriteLine("AEP SDK Error: " + error.ToString());
}
}
iOS
var data = new NSMutableDictionary<NSString, NSObject>
{
["dispatchResponseEventKey"] = new NSString("dispatchResponseEventValue")
};
ACPExtensionEvent sdkEvent = ACPExtensionEvent.ExtensionEventWithName("eventName", "eventType", "eventSource", data, out _);
Action<ACPExtensionEvent> callback = new Action<ACPExtensionEvent>(handleCallback);
ACPCore.DispatchEventWithResponseCallback(sdkEvent, callback, out error);
private void handleCallback(ACPExtensionEvent responseEvent)
{
Console.WriteLine("Response event name: "+ responseEvent.EventName.ToString() + " type: " + responseEvent.EventType.ToString() + " source: " + responseEvent.EventSource.ToString() + " data: " + responseEvent.EventData.ToString());
}
Android
var data = new Dictionary<string, Java.Lang.Object>();
data.Add("testEvent", true);
Event sdkEvent = new Event.Builder("eventName", "eventType", "eventSource").SetEventData(data).Build();
ACPCore.DispatchEventWithResponseCallback(sdkEvent, new StringCallback(), new ErrorCallback());
class StringCallback : Java.Lang.Object, IAdobeCallback
{
public void Call(Java.Lang.Object stringContent)
{
if (stringContent != null)
{
Console.WriteLine(stringContent);
}
else
{
Console.WriteLine("null content in string callback");
}
}
}
class ErrorCallback : Java.Lang.Object, IExtensionErrorCallback
{
public void Call(Java.Lang.Object sdkEvent)
{
Console.WriteLine("AEP SDK event data: " + sdkEvent.ToString());
}
public void Error(Java.Lang.Object error)
{
Console.WriteLine("AEP SDK Error: " + error.ToString());
}
}
iOS
var data = new NSMutableDictionary<NSString, NSObject>
{
["dispatchResponseEventKey"] = new NSString("dispatchResponseEventValue")
};
ACPExtensionEvent requestEvent = ACPExtensionEvent.ExtensionEventWithName("eventName", "eventType", "eventSource", data, out _);
ACPExtensionEvent responseEvent = ACPExtensionEvent.ExtensionEventWithName("eventName", "eventType", "eventSource", data, out _);
ACPCore.DispatchResponseEvent(responseEvent, requestEvent, out error));
Android
var data = new Dictionary<string, Java.Lang.Object>();
data.Add("testDispatchResponseEvent", "true");
Event requestEvent = new Event.Builder("eventName", "eventType", "eventSource").SetEventData(data).Build();
Event responseEvent = new Event.Builder("eventName", "eventType", "eventSource").SetEventData(data).Build();
ACPCore.DispatchResponseEvent(responseEvent, requestEvent, new ErrorCallback());
class ErrorCallback : Java.Lang.Object, IExtensionErrorCallback
{
public void Call(Java.Lang.Object sdkEvent)
{
Console.WriteLine("AEP SDK event data: " + sdkEvent.ToString());
}
public void Error(Java.Lang.Object error)
{
Console.WriteLine("AEP SDK Error: " + error.ToString());
}
}
iOS only
ACPCore.DownloadRules();
iOS and Android
ACPCore.SetAdvertisingIdentifier("testAdvertisingIdentifier");
iOS
var data = new NSMutableDictionary<NSString, NSString>
{
["key"] = new NSString("value")
};
ACPCore.TrackAction("action", data);
Android
var data = new Dictionary<string, string>();
data.Add("key", "value");
ACPCore.TrackAction("action", data);
iOS
var data = new NSMutableDictionary<NSString, NSString>
{
["key"] = new NSString("value")
};
ACPCore.TrackState("state", data);
Android
var data = new Dictionary<string, string>();
data.Add("key", "value");
ACPCore.TrackState("state", data);
iOS and Android
Console.WriteLine(ACPIdentity.ExtensionVersion());
iOS
ACPIdentity.SyncIdentifier("name", "john", ACPMobileVisitorAuthenticationState.Authenticated);
Android
ACPIdentity.SyncIdentifier("name", "john", VisitorID.AuthenticationState.Authenticated);
iOS
var ids = new NSMutableDictionary<NSString, NSObject>
{
["lastName"] = new NSString("doe"),
["age"] = new NSString("38"),
["zipcode"] = new NSString("94403")
};
ACPIdentity.SyncIdentifiers(ids);
Android
var ids = new Dictionary<string, string>();
ids.Add("lastname", "doe");
ids.Add("age", "38");
ids.Add("zipcode", "94403");
ACPIdentity.SyncIdentifiers(ids);
iOS
var ids = new NSMutableDictionary<NSString, NSObject>
{
["lastName"] = new NSString("doe"),
["age"] = new NSString("38"),
["zipcode"] = new NSString("94403")
};
ACPIdentity.SyncIdentifiers(ids, ACPMobileVisitorAuthenticationState.LoggedOut);
Android
var ids = new Dictionary<string, string>();
ids.Add("lastname", "doe");
ids.Add("age", "38");
ids.Add("zipcode", "94403");
ACPIdentity.SyncIdentifiers(ids, VisitorID.AuthenticationState.LoggedOut);
iOS
var callback = new Action<NSUrl>(handleCallback);
var url = new NSUrl("https://example.com");
ACPIdentity.AppendToUrl(url, callback);
private void handleCallback(NSString content)
{
Console.WriteLine("String callback: " + content);
}
Android
ACPIdentity.AppendVisitorInfoForURL("https://example.com", new StringCallback());
class StringCallback : Java.Lang.Object, IAdobeCallback
{
public void Call(Java.Lang.Object stringContent)
{
if (stringContent != null)
{
Console.WriteLine(stringContent);
}
else
{
Console.WriteLine("null content in string callback");
}
}
}
iOS
var callback = new Action<NSString> (handleCallback);
ACPIdentity.GetUrlVariables(callback);
private void handleCallback(NSString content)
{
Console.WriteLine("String callback: " + content);
}
Android
ACPIdentity.GetUrlVariables(new StringCallback());
class StringCallback : Java.Lang.Object, IAdobeCallback
{
public void Call(Java.Lang.Object stringContent)
{
if (stringContent != null)
{
Console.WriteLine(stringContent);
}
else
{
Console.WriteLine("null content in string callback");
}
}
}
iOS
var callback = new Action<ACPMobileVisitorId[]>(handleCallback);
ACPIdentity.GetIdentifiers(callback);
private void handleCallback(ACPMobileVisitorId[] ids)
{
String visitorIdsString = "[]";
if (ids.Length != 0)
{
visitorIdsString = "";
foreach (ACPMobileVisitorId id in ids)
{
visitorIdsString = visitorIdsString + "[Id: " + id.Identifier + ", Type: " + id.IdType + ", Origin: " + id.IdOrigin + ", Authentication: " + id.AuthenticationState + "]";
}
}
Console.WriteLine("Retrieved visitor ids: " + visitorIdsString);
}
Android
ACPIdentity.GetIdentifiers(new GetIdentifiersCallback());
class GetIdentifiersCallback : Java.Lang.Object, IAdobeCallback
{
public void Call(Java.Lang.Object visitorIDs)
{
JavaList ids = null;
System.String visitorIdsString = "[]";
if (visitorIDs != null)
{
ids = (JavaList)visitorIDs;
if (!ids.IsEmpty)
{
visitorIdsString = "";
foreach (VisitorID id in ids)
{
visitorIdsString = visitorIdsString + "[Id: " + id.Id + ", Type: " + id.IdType + ", Origin: " + id.IdOrigin + ", Authentication: " + id.GetAuthenticationState() + "]";
}
}
}
Console.WriteLine("Retrieved visitor ids: " + visitorIdsString);
}
}
iOS
var callback = new Action<NSString>(handleCallback);
ACPIdentity.GetExperienceCloudId(callback);
private void handleCallback(NSString content)
{
Console.WriteLine("String callback: " + content);
}
Android
ACPIdentity.GetExperienceCloudId(new StringCallback());
class StringCallback : Java.Lang.Object, IAdobeCallback
{
public void Call(Java.Lang.Object stringContent)
{
if (stringContent != null)
{
Console.WriteLine(stringContent);
}
else
{
Console.WriteLine("null content in string callback");
}
}
}
iOS and Android
Console.WriteLine(ACPLifecycle.ExtensionVersion());
iOS
public override void OnActivated(UIApplication uiApplication)
{
base.OnActivated(uiApplication);
ACPCore.LifecycleStart(null);
}
Android
protected override void OnResume()
{
base.OnResume();
ACPCore.Application = this.Application;
ACPCore.LifecycleStart(null);
}
Pausing a Lifecycle session
iOS
public override void OnResignActivation(UIApplication uiApplication)
{
base.OnResignActivation(uiApplication);
ACPCore.LifecyclePause();
}
Android
protected override void OnPause()
{
base.OnPause();
ACPCore.LifecyclePause();
}
iOS and Android
Console.WriteLine(ACPSignal.ExtensionVersion());
iOS and Android unit tests are included within the ACPCore binding solution. They must be built from within Visual Studio then manually triggered from the unit test app that is deployed to an iOS or Android device.
A Xamarin Forms sample app is provided in the Xamarin ACPCore solution file.
Looking to contribute to this project? Please review our Contributing guidelines prior to opening a pull request.
We look forward to working with you!
This project is licensed under the Apache V2 License. See LICENSE for more information.