アプリケーションの使用例では、アクティブな地域の監視が必要でない場合があります。 引き続きPlaces Serviceを使用して、ユーザーの場所データを他のExperience Platform製品と統合できます。
開発者は、ターゲットプラットフォームのオペレーティングシステムが提供するAPIを使用してデバイスの場所を収集します。
アプリの使用例でアクティブな地域の監視が必要な場合は、「場所モニター拡張機能の 使用」を参照してください。
アクティブな地域の監視を行わずにPlaces Serviceを使用するには:
アプリの開発者は、(iOS)またはGoogle Play Services(Android)が提供するAPIを使用して CoreLocation.framework
Location
、デバイスの現在の場所を収集する必要があります。
詳しくは、次のドキュメントを参照してください。
ユーザーの場所を取得したら、それを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)")
}
}
Places SDKは、 getNearbyPointsOfInterest
APIを呼び出すことで、デバイスに関連するすべてのPOIデータを、Launchのデータ要素から利用できるようにします。 「 データの添付 」ルールを使用すると、今後Analyticsにリクエストする際に、自動的に場所データを追加できます。 これにより、デバイスの場所が収集された時点でAnalyticsに対して1回限りの呼び出しを行う必要がなくなります。
このトピックについて詳しくは、 Analyticsリクエストの場所のコンテキスト (英語のみ)を参照してください。
場所データを取り込むための推奨される方法は、場所データをAnalyticsリクエストに 添付することです。
使用事例で、SDKによってトリガーされる 地域エントリイベント が必要な場合は、以下に示すように、手動で行う必要があります。
APIから返されるリストには、ユーザーが現在POI内にいるかどうかを示す getNearbyPointsOfInterest
カスタムオブジェクト が含まれています。 ユーザーがPOIにいる場合は、SDKでその地域のエントリイベントをトリガーするように設定できます。
1回の訪問で複数の入口イベントがトリガーされないようにするには、ユーザーが入力した地域のリストを維持します。 SDKから近くのPOIの応答を処理する場合、リストに領域がない場合にのみエントリイベントをトリガーします。
以下のコードの例では、 NSUserDefaults
(iOS)と SharedPreferences
(Android)を使用して地域のリストを管理しています。
次のコードの例は、のコールバックで提供された結果の処理を示し getNearbyPointsOfInterest
ます。a 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")
}
以下のコードサンプルでは、デバイスの現在の場所を取得し、必要なエントリイベントをトリガーし、1回の訪問で同じ場所に対して複数のエントリを取得しないようにする方法を示します。
このコードのサンプルには、ユーザーが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")
}
Places ServiceエントリイベントをSDKでトリガーするだけでなく、エントリイベントがトリガーされるので、POIを定義するすべてのデータを、Experience Platform Launch内の残りのSDKで使用でき data elements
ます。 Experience Platform Launch rules
を使用すると、SDKで処理される受信イベントにPlaces Serviceデータを動的に添付できます。 例えば、ユーザーが存在するPOIのメタデータを添付し、そのデータをコンテキストデータとしてAnalyticsに送信できます。
詳細については、「Places Serviceを他のAdobeソリューションと共に 使用する」を参照してください。