應用程式的使用案例可能不需要進行有效的區域監控。 Places Service仍可用來將使用者的位置資料與其他Experience Platform產品整合。
開發人員會使用目標平台作業系統提供的API來收集裝置位置。
如果應用程式的使用案例需要進行作用中的地區監控,請參閱 將Places Service與您自己的監控解決方案搭配使用.
要使用Places服務而不監視活動區域,請執行以下操作:
應用程式開發人員必須使用 CoreLocation.framework
(iOS)或 Location
Google Play服務(Android)提供的API。
如需詳細資訊,請參閱下列檔案:
取得使用者位置後,您就可將其傳遞至SDK,以取得附近POI的清單。
以下是在Android中使用 BroadcastReceiver
:
public class LocationBroadcastReceiver extends BroadcastReceiver {
static final String ACTION_LOCATION_UPDATE = "locationUpdate";
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null || context == null) {
return;
}
final String action = intent.getAction();
if (!ACTION_LOCATION_UPDATE.equals(action)) {
return;
}
LocationResult result = LocationResult.extractResult(intent);
if (result == null) {
return;
}
Location currentLocation = result.getLastLocation();
if (currentLocation == null) {
return;
}
// ask the Places SDK for the 10 nearest Points of Interest based on the user's location
Places.getNearbyPointsOfInterest(currentLocation, 10,
new AdobeCallback<List<PlacesPOI>>() {
@Override
public void call(List<PlacesPOI> pois) {
// pois is the 10 nearest POIs based on the location
}
}, new AdobeCallback<PlacesRequestError>() {
@Override
public void call(PlacesRequestError placesRequestError) {
// Look for the placesRequestError and handle the error accordingly
}
}
);
}
}
以下是iOS的範例實作。 程式碼會顯示 locationManager:didUpdateLocations:
方法(在 CLLocationManagerDelegate
:
- (void) locationManager:(CLLocationManager*)manager didUpdateLocations:(NSArray<CLLocation*>*)locations {
// ask the Places SDK for the 10 nearest Points of Interest based on the user's location
[ACPPlaces getNearbyPointsOfInterest:[locations lastObject] limit:10 callback:^(NSArray<ACPPlacesPoi *> * _Nullable nearbyPoi) {
// nearbyPoi is the 10 nearest POIs based on the location
} errorCallback:^(ACPPlacesRequestError result) {
// log the error if we got one
NSLog(@"error: %lu", (unsigned long)result);
}];
}
以下是iOS的範例實作。 程式碼會顯示 locationManager(_:didUpdateLocations:)
方法(在 CLLocationManagerDelegate
:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// ask the Places SDK for the 10 nearest Points of Interest based on the user's location
ACPPlaces.getNearbyPoints(ofInterest: locations.last!, limit: 10, callback: { (nearbyPoi) in
// nearbyPoi is the 10 nearest POIs based on the location
}) { (error) in
// log the error if we have one
print("error: \(error)")
}
}
借由呼叫 getNearbyPointsOfInterest
API中,Places SDK會透過Launch中的資料元素,提供與裝置相關的所有POI資料。 使用 附加資料 規則中,Places資料可自動新增至未來Analytics請求。 這樣就不需要在收集裝置位置時對Analytics進行一次性呼叫。
請參閱 將位置內容新增至Analytics請求 以深入了解此主題。
捕獲Places資料的建議方法是 將Places資料附加至Analytics請求.
如果使用案例需要 地區登入事件 若要由SDK觸發,需依照下列說明手動完成。
由 getNearbyPointsOfInterest
API包含 自訂物件 指出使用者目前是否在POI內。 如果使用者位於POI中,您可以讓SDK觸發該地區的登入事件。
若要防止應用程式在單次造訪中觸發多個登入事件,請保留您知道使用者已進入的地區清單。 從SDK處理附近POI的回應時,僅當地區不在您的清單中時,才觸發登入事件。
在下列程式碼範例中, NSUserDefaults
(iOS)和 SharedPreferences
(Android)用於管理地區清單:
下列程式碼範例顯示回呼中提供之結果的處理方式 getNearbyPointsOfInterest
, List<PlacesPOI>
:
void handleUpdatedPOIs(final List<PlacesPOI> nearbyPois) {
// get the list of regions we know the user is already within from SharedPreferences
SharedPreferences preferences = getApplicationContext().getSharedPreferences("places", 0);
Set<String> regionsUserIsAlreadyIn = preferences.getStringSet("regionsUserIsAlreadyIn", new HashSet<String>());
// loop through new placesPOIS and post entry events for pois that aren't already in our list
// also create the new list of regions that the user is in
Set<String> updatedRegionsUserIsIn = new HashSet<String>();
for (PlacesPOI poi : nearbyPois) {
// check if the user is in this poi
if (poi.containsUser()) {
// the user is in the poi, now we need to make sure we haven't already recorded this entry event
if (!regionsUserIsAlreadyIn.contains(poi.getIdentifier())) {
Geofence poiGeofence = new Geofence.Builder()
.setRequestId(poi.getIdentifier())
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
.setCircularRegion(poi.getLatitude(), poi.getLongitude(), poi.getRadius())
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build();
Places.processGeofence(poiGeofence, Geofence.GEOFENCE_TRANSITION_ENTER);
}
// add the region to our new list of regions
updatedRegionsUserIsIn.add(poi.getIdentifier());
}
}
// update SharedPreferences with our new list of regions
SharedPreferences.Editor editor = getApplicationContext().getSharedPreferences("places", 0).edit();
editor.putStringSet("regionsUserIsAlreadyIn", updatedRegionsUserIsIn).apply();
}
下列程式碼範例顯示回呼中提供之結果的處理方式 getNearbyPointsOfInterest:limit:callback:errorCallback:
, NSArray<ACPPlacesPoi *> *
:
- (void) handleUpdatedPOIs:(NSArray<ACPPlacesPoi *> *)nearbyPois {
// get the list of regions we know the user is already within from user defaults
NSArray *regionsUserIsCurrentlyWithin = [[NSUserDefaults standardUserDefaults]
arrayForKey:@"regionsUserIsAlreadyIn"];
// loop through new nearbyPoi and post entry events for pois that aren't already in our list
// also creating the new list of known regions that the user is in
NSMutableArray *updatedRegionsUserIsCurrentlyWithin = [@[] mutableCopy];
for (ACPPlacesPoi *poi in nearbyPois) {
// check if the user is in this poi
if (poi.userIsWithin) {
// the user is in the poi, now we need to make sure we haven't already recorded the entry event
if (![regionsUserIsCurrentlyWithin containsObject:poi.identifier]) {
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(poi.latitude, poi.longitude)
radius:poi.radius
identifier:poi.identifier];
[ACPPlaces processRegionEvent:region forRegionEventType:ACPRegionEventTypeEntry];
}
// add the region to our updated list
[updatedRegionsUserIsCurrentlyWithin addObject:poi.identifier];
}
}
// update user defaults with the new list
[[NSUserDefaults standardUserDefaults] setObject:updatedRegionsUserIsCurrentlyWithin forKey:@"regionsUserIsAlreadyIn"];
}
下列程式碼範例顯示回呼中提供之結果的處理方式 getNearbyPoints(_ ofInterest: CLLocation, limit: UInt, callback: (([ACPPlacesPoi]?) -> Void)?, errorCallback: ((ACPPlacesRequestError) -> Void)?)
, [ACPPlacesPoi]
:
func handleUpdatedPOIs(_ nearbyPois:[ACPPlacesPoi]) {
// get the list of regions we know the user is already within from user defaults
let regionsUserIsCurrentlyWithin : [String] = UserDefaults.standard.array(forKey: "regionsUserIsAlreadyIn") as! [String]
// loop through new nearbyPoi and post entry events for pois that aren't already in our list
// also creating the new list of known regions that the user is in
var updatedRegionsUserIsCurrentlyWithin: [String] = []
for poi in nearbyPois {
// check if the user is in this poi
if poi.userIsWithin {
// the user is in the poi, now we need to make sure we haven't already recorded the entry event
if !regionsUserIsCurrentlyWithin.contains(poi.identifier!) {
let region = CLCircularRegion.init(center: CLLocationCoordinate2D.init(latitude: poi.latitude, longitude: poi.longitude), radius: CLLocationDistance(poi.radius), identifier: poi.identifier!)
ACPPlaces.processRegionEvent(region, for: .entry)
}
// add the region to our updated list
updatedRegionsUserIsCurrentlyWithin.append(poi.identifier!)
}
}
// update user defaults with the new list
UserDefaults.standard.set(updatedRegionsUserIsCurrentlyWithin, forKey: "regionsUserIsAlreadyIn")
}
以下程式碼範例會示範如何擷取裝置的目前位置、觸發必要的登入事件,以及確保在一次造訪中不會取得相同位置的多個登入項目。
此程式碼範例包含 在使用者進入POI時觸發登入事件.
這些片段是 僅限 範例。 開發人員必須決定要如何實作功能,決策應根據目標作業系統建議的最佳實務。
public class LocationBroadcastReceiver extends BroadcastReceiver {
static final String ACTION_LOCATION_UPDATE = "locationUpdate";
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null || context == null) {
return;
}
final String action = intent.getAction();
if (!ACTION_LOCATION_UPDATE.equals(action)) {
return;
}
LocationResult result = LocationResult.extractResult(intent);
if (result == null) {
return;
}
Location currentLocation = result.getLastLocation();
if (currentLocation == null) {
return;
}
// ask the Places SDK for the 10 nearest Points of Interest based on the user's location
Places.getNearbyPointsOfInterest(currentLocation, 10,
new AdobeCallback<List<PlacesPOI>>() {
@Override
public void call(List<PlacesPOI> pois) {
// pois is the 10 nearest POIs based on the location
handleUpdatedPOIs(pois);
}
}, new AdobeCallback<PlacesRequestError>() {
@Override
public void call(PlacesRequestError placesRequestError) {
// Look for the placesRequestError and handle the error accordingly
}
}
);
}
void handleUpdatedPOIs(final List<PlacesPOI> nearbyPois) {
// get the list of regions we know the user is already within from SharedPreferences
SharedPreferences preferences = getApplicationContext().getSharedPreferences("places", 0);
Set<String> regionsUserIsAlreadyIn = preferences.getStringSet("regionsUserIsAlreadyIn", new HashSet<String>());
// loop through new placesPOIS and post entry events for pois that aren't already in our list
// also create the new list of regions that the user is in
Set<String> updatedRegionsUserIsIn = new HashSet<String>();
for (PlacesPOI poi : nearbyPois) {
// check if the user is in this poi
if (poi.containsUser()) {
// the user is in the poi, now we need to make sure we haven't already recorded this entry event
if (!regionsUserIsAlreadyIn.contains(poi.getIdentifier())) {
Geofence poiGeofence = new Geofence.Builder()
.setRequestId(poi.getIdentifier())
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
.setCircularRegion(poi.getLatitude(), poi.getLongitude(), poi.getRadius())
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build();
Places.processGeofence(poiGeofence, Geofence.GEOFENCE_TRANSITION_ENTER);
}
// add the region to our new list of regions
updatedRegionsUserIsIn.add(poi.getIdentifier());
}
}
// update SharedPreferences with our new list of regions
SharedPreferences.Editor editor = getApplicationContext().getSharedPreferences("places", 0).edit();
editor.putStringSet("regionsUserIsAlreadyIn", updatedRegionsUserIsIn).apply();
}
}
- (void) locationManager:(CLLocationManager*)manager didUpdateLocations:(NSArray<CLLocation*>*)locations {
// ask the Places SDK for the 10 nearest Points of Interest based on the user's location
[ACPPlaces getNearbyPointsOfInterest:[locations lastObject] limit:10 callback:^(NSArray<ACPPlacesPoi *> * _Nullable nearbyPoi) {
// nearbyPoi is the 10 nearest POIs based on the location
[self handleUpdatedPOIs:nearbyPoi];
} errorCallback:^(ACPPlacesRequestError result) {
// log the error if we got one
NSLog(@"error: %lu", (unsigned long)result);
}];
}
- (void) handleUpdatedPOIs:(NSArray<ACPPlacesPoi *> *)nearbyPois {
// get the list of regions we know the user is already within from user defaults
NSArray *regionsUserIsCurrentlyWithin = [[NSUserDefaults standardUserDefaults]
arrayForKey:@"regionsUserIsAlreadyIn"];
// loop through new nearbyPoi and post entry events for pois that aren't already in our list
// also creating the new list of known regions that the user is in
NSMutableArray *updatedRegionsUserIsCurrentlyWithin = [@[] mutableCopy];
for (ACPPlacesPoi *poi in nearbyPois) {
// check if the user is in this poi
if (poi.userIsWithin) {
// the user is in the poi, now we need to make sure we haven't already recorded the entry event
if (![regionsUserIsCurrentlyWithin containsObject:poi.identifier]) {
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(poi.latitude, poi.longitude)
radius:poi.radius
identifier:poi.identifier];
[ACPPlaces processRegionEvent:region forRegionEventType:ACPRegionEventTypeEntry];
}
// add the region to our updated list
[updatedRegionsUserIsCurrentlyWithin addObject:poi.identifier];
}
}
// update user defaults with the new list
[[NSUserDefaults standardUserDefaults] setObject:updatedRegionsUserIsCurrentlyWithin forKey:@"regionsUserIsAlreadyIn"];
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// ask the Places SDK for the 10 nearest Points of Interest based on the user's location
ACPPlaces.getNearbyPoints(ofInterest: locations.last!, limit: 10, callback: { (nearbyPoi) in
// nearbyPoi is the 10 nearest POIs based on the location
self.handleUpdatedPOIs(nearbyPoi!)
}) { (error) in
// log the error if we have one
print("error: \(error)")
}
}
func handleUpdatedPOIs(_ nearbyPois:[ACPPlacesPoi]) {
// get the list of regions we know the user is already within from user defaults
let regionsUserIsCurrentlyWithin : [String] = UserDefaults.standard.array(forKey: "regionsUserIsAlreadyIn") as! [String]
// loop through new nearbyPoi and post entry events for pois that aren't already in our list
// also creating the new list of known regions that the user is in
var updatedRegionsUserIsCurrentlyWithin: [String] = []
for poi in nearbyPois {
// check if the user is in this poi
if poi.userIsWithin {
// the user is in the poi, now we need to make sure we haven't already recorded the entry event
if !regionsUserIsCurrentlyWithin.contains(poi.identifier!) {
let region = CLCircularRegion.init(center: CLLocationCoordinate2D.init(latitude: poi.latitude, longitude: poi.longitude), radius: CLLocationDistance(poi.radius), identifier: poi.identifier!)
ACPPlaces.processRegionEvent(region, for: .entry)
}
// add the region to our updated list
updatedRegionsUserIsCurrentlyWithin.append(poi.identifier!)
}
}
// update user defaults with the new list
UserDefaults.standard.set(updatedRegionsUserIsCurrentlyWithin, forKey: "regionsUserIsAlreadyIn")
}
除了觸發SDK中的Places Service登入事件外,由於觸發登入事件,定義POI的所有資料都可供SDK的其他人透過 data elements
Experience Platform Launch。 使用Experience Platform Launch rules
,您可以將Places Service資料動態附加至SDK處理的傳入事件。 例如,您可以附加使用者所在之POI的中繼資料,並以內容資料的形式將資料傳送至Analytics。
如需詳細資訊,請參閱 將Places服務與其他Adobe解決方案搭配使用.