ILocation::GetReportStatus 方法 (locationapi.h)
[Win32 位置 API 可用于“要求”部分中指定的操作系统。 它可能在后续版本中变更或不可用。 请改用 Windows.Devices.Geolocation API。 ]
检索指定报表类型的状态。
语法
HRESULT GetReportStatus(
[in] REFIID reportType,
[out] LOCATION_REPORT_STATUS *pStatus
);
parameters
[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。 在创建位置对象或调用 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 |
标头 | locationapi.h |
DLL | LocationAPI.dll |