如何在后台将检测到的信标信息的详细信息发送到服务器?

时间:2018-10-04 09:32:09

标签: android ibeacon ibeacon-android

我正在开发一个应用程序,该应用程序需要检测您所在区域附近的可用信标,并且需要使用API​​调用将检测到的信标详细信息发送到我的服务器。 我正在获取信标详细信息,但无法从发现任何信标的应用程序后台将详细信息发送到我的服务器。

这是信标的详细信息;

    private class ScanProcessor extends AsyncTask<ScanData, Void, Void> {

        @Override
        protected Void doInBackground(ScanData... params) {
            ScanData scanData = params[0];

           IBeacon iBeacon = IBeacon.fromScanData(scanData.scanRecord, scanData.rssi);
           if (iBeacon != null) {
               lastIBeaconDetectionTime = new Date();
               trackedBeacons.add(iBeacon);
               Log.d(TAG, "iBeacon detected :"+iBeacon.getProximityUuid()+" Major: "+iBeacon.getMajor()+" Minor: "+iBeacon.getMinor()+" accuracy: "+iBeacon.getAccuracy()+" proximity: "+iBeacon.getProximity());

               List<Region> matchedRegions = matchingRegions(iBeacon, monitoredRegionState.keySet());
               Iterator<Region> matchedRegionIterator = matchedRegions.iterator();
               while (matchedRegionIterator.hasNext()) {
                   Region region = matchedRegionIterator.next();
                   MonitorState state = monitoredRegionState.get(region);
//                 if (state.markInside()) {
//                        state.getCallback().call(IBeaconService.this, "monitoringData", new MonitoringData(state.isInside(), region));
//                 }
               }

               Log.d(TAG, "looking for ranging region matches for this ibeacon");
               matchedRegions = matchingRegions(iBeacon, rangedRegionState.keySet());
               matchedRegionIterator = matchedRegions.iterator();
               while (matchedRegionIterator.hasNext()) {
                   Region region = matchedRegionIterator.next();
                   Log.d(TAG, "matches ranging region: "+region);
                   RangeState rangeState = rangedRegionState.get(region);
                   rangeState.addIBeacon(iBeacon);                 
               }

           }
           //I see a device: 00:02:72:C5:EC:33 with scan data: 02 01 1A 1A FF 4C 00 02 15 84 2A F9 C4 08 F5 11 E3 92 82 F2 3C 91 AE C0 5E D0 00 00 69 C5 0000000000000000000000000000000000000000000000000000000000000000
           //
           // 9: proximityUuid (16 bytes) 84 2A F9 C4 08 F5 11 E3 92 82 F2 3C 91 AE C0 5E
           // 25: major (2 bytes unsigned int)
           // 27: minor (2 bytes unsigned int)
           // 29: tx power (1 byte signed int)          
            return null;
        }      

        @Override
        protected void onPostExecute(Void result) {
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(Void... values) {
        }
    }   

当我在应用程序后台发现信标时,请帮助我如何将信标详细信息发送到服务器。

2 个答案:

答案 0 :(得分:0)

首先,AsyncTask需要ui线程才能工作,您可以使用任何其他线程api:HandlerThreadcustom handlerExecutorService或仅是普通线程。您可以从herehere阅读更多详细信息。

另一则仅供参考,以从后台检测信标,我希望您不使用常规服务,否则可能会在Oreo及以上设备上引起问题。请改为使用前景服务。从here中了解服务here及其原因。

答案 1 :(得分:0)

虽然您没有显示任何尝试将数据发送到服务器的代码,但是由于您已成功使用AsyncTask处理信标数据,因此您也可以使用另一个AsyncTask将数据发送到服务器-主体是相同的

示例:

public class AsyncCaller extends AsyncTask<Void, Void, Void> {

    public RestResponseHandler mResponseHandler;
    public String mUrl;
    public String mOperation;
    public String mRequestBody;
    public Map<String,String> mRequestHeaders;
    Map<String,List<String>> mResponseHeaders;
    int mResponseCode;
    String mResponseBody;
    Exception mException;


    public AsyncCaller prepareCall(String url, String operation, String requestBody, Map<String,String> headers, RestResponseHandler responseHandler) {
        mResponseHandler = responseHandler;
        mOperation = operation;
        mRequestBody = requestBody;
        mUrl = url;
        mRequestHeaders = mRequestHeaders;
        return this;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mRequestActive = true;
    }

    @Override
    protected Void doInBackground(Void... params) {
        Log.d(TAG, "start doInBackground");

        mException = null;
        try {
            sendRequest();
        }
        catch (Exception e) {
            Log.e(TAG, "Cannot send request", e);
            mException = new Exception("Cannot send request", e);
        }
        Log.d(TAG, "finish doInBackground");
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        Log.d(TAG, "start onPostExecute");
        super.onPostExecute(result);
        mRequestActive = false;
        if (mResponseHandler != null) {
            if (mException != null) {
                mResponseHandler.onFail(mException);
            }
            else {
                mResponseHandler.onResponse(mResponseCode, mResponseHeaders, mResponseBody );
            }
        }
        Log.d(TAG, "finish onPostExecute");
    }

    public void sendRequest() throws Exception {
        StringBuilder responseBuilder = new StringBuilder();
        HttpURLConnection conn = null;
        URL url = new URL(mUrl);
        mResponseCode = -1;
        mResponseBody = null;
        mResponseHeaders = null;
        Log.d(TAG, "calling service at " + mUrl);
        conn = (HttpURLConnection) url.openConnection();
        for (String headerKey : mRequestHeaders.keySet()) {
            conn.addRequestProperty(headerKey, mRequestHeaders.get(headerKey));
        }
        conn.setRequestMethod(mOperation.toUpperCase());
        if (mRequestBody != null) {
            OutputStream out = conn.getOutputStream();
            try {
                Writer writer = new OutputStreamWriter(out, "UTF-8");
                Log.d(TAG, "posting: " + mRequestBody);
                writer.write(mRequestBody);
                writer.close();
            } finally {
                if (out != null) {
                    out.close();
                }
            }
        }
        mResponseCode = conn.getResponseCode();
        mResponseHeaders = conn.getHeaderFields();


        Log.d(TAG, "response code is " + conn.getResponseCode());
        BufferedReader in = null;
        try {
            if (mResponseCode >= 200 && mResponseCode <= 299) {
                in = new BufferedReader(
                        new InputStreamReader(
                                conn.getInputStream())
                );

            }
            else {
                in = new BufferedReader(
                        new InputStreamReader(
                                conn.getErrorStream()
                        )
                );

            }
            String inputLine;
            while ((inputLine = in.readLine()) != null)
                responseBuilder.append(inputLine);
            in.close();
            Log.d(TAG, "response is " + responseBuilder.toString());
            mResponseBody = responseBuilder.toString();
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }
}

public interface RestResponseHandler {
    public void onFail(Exception e);
    public void onResponse(int httpStatus, Map<String,List<String>> headers, String body);
}

然后您可以通过以下方式调用它:

    mAsyncCsller = new AsyncCaller();
    mAsyncCaller.mUrl = "https://myserver.ner/path";
    mAsyncCaller.mOperation = "POST";
    mAsyncCaller.mRequestBody = "{\uuid\":\""+beacon.getId1()+"\"}";
    mAsyncCaller.mRequestHeaders = new HashMap<String,String>();
    mAsyncCaller.mResponseHandler = null;
    mAsyncCaller.execute(null, null, null);

请注意不要过于频繁地将数据发送到服务器。服务器调用可能要花费一秒钟或更长时间,而且比这更频繁地检测到信标。如果发送数据的频率太高,您将用完线程并使服务器超载。考虑分批处理您的呼叫,以便每60秒将多个信标检测发送到服务器。