次の方法で共有


ILocation::GetReportStatus メソッド (locationapi.h)

[Win32 Location API は、[要件] セクションで指定されたオペレーティング システムで使用できます。 今後のバージョンでは変更されるか、利用できなくなる場合もあります。 代わりに、 Windows.Devices.Geolocation API を使用します。 ]

指定したレポートの種類の状態を取得します。

構文

HRESULT GetReportStatus(
  [in]  REFIID                 reportType,
  [out] LOCATION_REPORT_STATUS *pStatus
);

パラメーター

[in] reportType

間隔を取得するレポートの種類を指定する REFIID

[out] pStatus

指定 したレポート の現在の状態を受け取るLOCATION_REPORT_STATUSのアドレス。

戻り値

このメソッドは HRESULT を返します。 有効な値を次の表に示しますが、これ以外にもあります。

リターン コード 説明
S_OK
メソッドが成功しました。
HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
reportType は、 IID_ILatLongReport または IID_ICivicAddressReport以外です。
E_INVALIDARG
pStatusNULL です

解説

このメソッドは、新しいレポートのレポートの状態を取得します。 このメソッドによって報告された状態に関係なく、最新のレポートは ILocation::GetReport を通じて引き続き使用できます。

既知の問題

アプリケーションが最初に起動されたとき、または新しい場所センサーが有効になっている場合、 GetReportStatus は、場所レポートが使用可能になる直前に 、REPORT_RUNNING の状態を報告する場合があります。

したがって、 GetReportStatusREPORT_RUNNINGの状態を示している場合でも、 GetReport を最初に呼び出すと、エラー ( ERROR_NO_DATA) または予期される場所センサーからの値が返されます。 これは、次のケースで発生する可能性があります。

  1. アプリケーションは、REPORT_RUNNINGのレポートの状態が返されるまで GetReportStatus を使用して状態をポーリングし、GetReport を呼び出します。
  2. 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

関連項目

ILocation