Метод ILocation::GetReportStatus (locationapi.h)
[API расположения Win32 доступен для использования в операционных системах, указанных в разделе Требования. В последующих версиях он может быть изменен или недоступен. Вместо этого используйте API Windows.Devices.Geolocation . ]
Извлекает состояние для указанного типа отчета.
Синтаксис
HRESULT GetReportStatus(
[in] REFIID reportType,
[out] LOCATION_REPORT_STATUS *pStatus
);
Параметры
[in] reportType
REFIID , указывающий тип отчета, для которого требуется получить интервал.
[out] pStatus
Адрес LOCATION_REPORT_STATUS , получающего текущее состояние указанного отчета.
Возвращаемое значение
Метод возвращает HRESULT. Допустимые значения включают, но не ограничиваются, значения, приведенные в следующей таблице.
Код возврата | Описание |
---|---|
|
Метод выполнен успешно. |
|
параметр reportType отличается от IID_ILatLongReport или IID_ICivicAddressReport. |
|
pStatus имеет значение NULL. |
Комментарии
Этот метод извлекает состояние отчета для новых отчетов. Последние отчеты остаются доступными через ILocation::GetReport, независимо от состояния, сообщаемого этим методом.
Известные проблемы
При первом запуске приложения или включении нового датчика расположения GetReportStatus может сообщить о состоянии REPORT_RUNNING незадолго до того, как отчет о расположении будет доступен.Таким образом, первоначальный вызов GetReport вернет ошибку (ERROR_NO_DATA) или значение, не полученное от ожидаемого датчика расположения, даже если GetReportStatus указывает состояние REPORT_RUNNING. Это может происходить в следующих случаях:
- Приложение опрашивает состояние с помощью GetReportStatus , пока не будет возвращено состояние отчета REPORT_RUNNING , а затем вызывает GetReport.
- GetReportStatus вызывается при запуске приложения. Это может произойти после создания объекта location или после вызова RequestPermissions.
Приложение может устранить эту проблему, реализовав следующее обходное решение. Обходной путь включает подписку на события отчета о расположении.
Обходное решение: подписка на события
Приложение может подписаться на события отчета и дождаться отчета из события OnLocationChanged или OnStatusChanged . Приложение должно ожидать указанное конечное количество времени.В следующем примере показано приложение, которое ожидает отчета о расположении типа ILatLongReport. Если отчет успешно получен в течение указанного промежутка времени, он выводит сообщение, указывающее, что данные получены.
В следующем примере кода показано, как приложение может вызывать функцию с именем WaitForLocationReport , которая регистрирует события и ожидает первого отчета о расположении. WaitForLocationReport ожидает события, заданного объектом обратного вызова. Функция WaitForLocationReport и объект обратного вызова определяются в следующих примерах.
// main.cpp
// An application that demonstrates how to wait for a location report.
// This sample waits for latitude/longitude reports but can be modified
// to wait for civic address reports by replacing IID_ILatLongReport
// with IID_ICivicAddressReport in the following code.
#include "WaitForLocationReport.h"
#define DEFAULT_WAIT_FOR_LOCATION_REPORT 500 // Wait for half a second.
int wmain()
{
// You may use the flags COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE
// to specify the multi-threaded concurrency model.
HRESULT hr = ::CoInitializeEx(NULL,
COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
int args;
PWSTR *pszArgList = ::CommandLineToArgvW(::GetCommandLineW(), &args);
DWORD const dwTimeToWait =
(2 == args) ? static_cast<DWORD>(_wtoi(pszArgList[1])) : DEFAULT_WAIT_FOR_LOCATION_REPORT;
::LocalFree(pszArgList);
wprintf_s(L"Wait time set to %lu\n", dwTimeToWait);
ILocation *pLocation; // This is the main Location interface.
hr = CoCreateInstance(CLSID_Location, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&pLocation));
if (SUCCEEDED(hr))
{
// Array of report types to listen for.
// Replace IID_ILatLongReport with IID_ICivicAddressReport
// for civic address reports.
IID REPORT_TYPES[] = { IID_ILatLongReport };
// Request permissions for this user account to receive location data for all the
// types defined in REPORT_TYPES (which is currently just one report)
// TRUE means a synchronous request.
if (FAILED(pLocation->RequestPermissions(NULL, REPORT_TYPES, ARRAYSIZE(REPORT_TYPES), TRUE)))
{
wprintf_s(L"Warning: Unable to request permissions.\n");
}
ILocationReport *pLocationReport; // This is our location report object
// Replace IID_ILatLongReport with IID_ICivicAddressReport for civic address reports
hr = ::WaitForLocationReport(pLocation, IID_ILatLongReport, dwTimeToWait, &pLocationReport);
if (SUCCEEDED(hr))
{
wprintf_s(L"Successfully received data via GetReport().\n");
pLocationReport->Release();
}
else if (RPC_S_CALLPENDING == hr)
{
wprintf_s(L"No LatLong data received. Wait time of %lu elapsed.\n", dwTimeToWait);
}
pLocation->Release();
}
::CoUninitialize();
}
return 0;
}
Следующий пример кода разделен на WaitForLocationReport.h и WaitForLocationReport.cpp. WaitForLocationReport.h содержит заголовок для функции WaitForLocationReport . WaitForLocationReport.cpp содержит определение функции WaitForLocationReport и определение объекта обратного вызова, который она использует. Объект обратного вызова предоставляет реализации методов обратного вызова OnLocationChanged и OnStatusChanged . В этих методах он задает событие, которое сигнализирует о доступности отчета.
// WaitForLocationReport.h
// Header for the declaration of the WaitForLocationReport function.
#pragma once
#include <windows.h>
#include <LocationApi.h>
#include <wchar.h>
HRESULT WaitForLocationReport(
ILocation* pLocation, // Location object.
REFIID reportType, // Type of report.
DWORD dwTimeToWait, // Milliseconds to wait.
ILocationReport** ppLocationReport // Receives the location report.
);
// WaitForLocationReport.cpp
// Contains definitions of the WaitForLocationReport function and
// the callback object that it uses.
#include "WaitForLocationReport.h"
#include <shlwapi.h>
#include <new>
// Implementation of the callback interface that receives location reports.
class CLocationCallback : public ILocationEvents
{
public:
CLocationCallback() : _cRef(1), _hDataEvent(::CreateEvent(
NULL, // Default security attributes.
FALSE, // Auto-reset event.
FALSE, // Initial state is nonsignaled.
NULL)) // No event name.
{
}
virtual ~CLocationCallback()
{
if (_hDataEvent)
{
::CloseHandle(_hDataEvent);
}
}
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
if ((riid == IID_IUnknown) ||
(riid == IID_ILocationEvents))
{
*ppv = static_cast<ILocationEvents*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
IFACEMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&_cRef);
}
IFACEMETHODIMP_(ULONG) Release()
{
long cRef = InterlockedDecrement(&_cRef);
if (!cRef)
{
delete this;
}
return cRef;
}
// ILocationEvents
// This is called when there is a new location report.
IFACEMETHODIMP OnLocationChanged(REFIID /*reportType*/, ILocationReport* /*pLocationReport*/)
{
::SetEvent(_hDataEvent);
return S_OK;
}
// This is called when the status of a report type changes.
// The LOCATION_REPORT_STATUS enumeration is defined in LocApi.h in the SDK
IFACEMETHODIMP OnStatusChanged(REFIID /*reportType*/, LOCATION_REPORT_STATUS status)
{
if (REPORT_RUNNING == status)
{
::SetEvent(_hDataEvent);
}
return S_OK;
}
HANDLE GetEventHandle()
{
return _hDataEvent;
}
private:
long _cRef;
HANDLE _hDataEvent; // Data Event Handle
};
// Waits to receive a location report.
// This function waits for the callback object to signal when
// a report event or status event occurs, and then calls GetReport.
// Even if no report event or status event is received before the timeout,
// this function still queries for the last known report by calling GetReport.
// The last known report may be cached data from a location sensor that is not
// reporting events, or data from the default location provider.
//
// Returns S_OK if the location report has been returned
// or RPC_S_CALLPENDING if the timeout expired.
HRESULT WaitForLocationReport(
ILocation* pLocation, // Location object.
REFIID reportType, // Type of report to wait for.
DWORD dwTimeToWait, // Milliseconds to wait.
ILocationReport **ppLocationReport // Receives the location report.
)
{
*ppLocationReport = NULL;
CLocationCallback *pLocationCallback = new(std::nothrow) CLocationCallback();
HRESULT hr = pLocationCallback ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
HANDLE hEvent = pLocationCallback->GetEventHandle();
hr = hEvent ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
// Tell the Location API that we want to register for a report.
hr = pLocation->RegisterForReport(pLocationCallback, reportType, 0);
if (SUCCEEDED(hr))
{
DWORD dwIndex;
HRESULT hrWait = CoWaitForMultipleHandles(0, dwTimeToWait, 1, &hEvent, &dwIndex);
if ((S_OK == hrWait) || (RPC_S_CALLPENDING == hrWait))
{
// Even if there is a timeout indicated by RPC_S_CALLPENDING
// attempt to query the report to return the last known report.
hr = pLocation->GetReport(reportType, ppLocationReport);
if (FAILED(hr) && (RPC_S_CALLPENDING == hrWait))
{
// Override hr error if the request timed out and
// no data is available from the last known report.
hr = hrWait; // RPC_S_CALLPENDING
}
}
// Unregister from reports from the Location API.
pLocation->UnregisterForReport(reportType);
}
}
pLocationCallback->Release();
}
return hr;
}
Требования
Минимальная версия клиента | Windows 7 [только классические приложения],Windows 7 |
Минимальная версия сервера | Ни одна версия не поддерживается |
Целевая платформа | Windows |
Header | locationapi.h |
DLL | LocationAPI.dll |