org.immopoly.android.api.IS24ApiService.java Source code

Java tutorial

Introduction

Here is the source code for org.immopoly.android.api.IS24ApiService.java

Source

/*
 * This is the Android component of Immopoly
 * http://immopoly.appspot.com
 * Copyright (C) 2011 Tobias Sasse
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/.
 */

package org.immopoly.android.api;

import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.util.Log;

import org.immopoly.android.constants.Const;
import org.immopoly.android.helper.WebHelper;
import org.immopoly.android.model.Flats;
import org.immopoly.android.model.OAuthData;
import org.json.JSONException;
import org.json.JSONObject;

import java.net.MalformedURLException;
import java.net.URL;

public class IS24ApiService extends IntentService {

    public static final String API_RECEIVER = "api_receiver";
    public static final String LAT = "lat";
    public static final String LNG = "lng";
    public static final String NO_FLATS = "no_flats";

    public static final int STATUS_RUNNING = 1;
    public static final int STATUS_FINISHED = 2;
    public static final int STATUS_ERROR = 3;

    public IS24ApiService() {
        super("");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        final ResultReceiver receiver = intent.getParcelableExtra(API_RECEIVER);
        double lat = intent.getDoubleExtra(LAT, 0.0);
        double lon = intent.getDoubleExtra(LNG, 0.0);
        Bundle b = new Bundle();
        Log.d(Const.LOG_TAG, "IS24 search started");
        try {
            receiver.send(STATUS_RUNNING, Bundle.EMPTY);
            final float[] radii = Const.SEARCH_RADII;
            // search for flats in radii[i]. finish if enough flats found (1 is enough in the last run)
            for (int i = 0; i < radii.length; i++) {
                int min = i == radii.length - 1 ? 1 : Const.SEARCH_MIN_RESULTS;
                Flats flats = loadFlats(lat, lon, radii[i], min, Const.SEARCH_MAX_RESULTS);
                if (flats != null) {
                    Log.d(Const.LOG_TAG, "IS24 search finished. #flats: " + flats.size());
                    b.putParcelableArrayList("flats", flats);
                    receiver.send(STATUS_FINISHED, b);
                    this.stopSelf();
                    return;
                }
            }
            // no flats found
            Log.d(Const.LOG_TAG, "IS24 search finished with no flats: ");
            b.putString(Intent.EXTRA_TEXT, NO_FLATS);
        } catch (Exception e) {
            Log.e(Const.LOG_TAG, "IS24 search caught Exception: ", e);
        }
        receiver.send(STATUS_ERROR, b);
        this.stopSelf();
    }

    /**
     * Runs an IS2 search with the given lat,lon,r
     * Returns at most 'max' Flats or null if there are less than 'min' flats.   
     * @param lat Latitude
     * @param lon Longitude
     * @param r Radius
     * @param min minimum nuber of flats
     * @param max maximum nuber of flats
     * @return Flats or null
     * @throws JSONException. MalformedURLException, NullPointerException 
     */
    private Flats loadFlats(double lat, double lon, float r, int min, int max)
            throws JSONException, MalformedURLException {
        Log.d(Const.LOG_TAG,
                "IS24 search: Lat: " + lat + " Lon: " + lon + " R: " + r + " min: " + min + " max: " + max);
        // get the first result page and extract paging info
        JSONObject json = loadPage(lat, lon, r, 1); // IS24 page nr starts at 1
        JSONObject resultList = json.getJSONObject("resultlist.resultlist");
        JSONObject pagingInfo = resultList.getJSONObject("paging");
        int numPages = pagingInfo.getInt("numberOfPages");
        int results = pagingInfo.getInt("numberOfHits");
        int pageSize = pagingInfo.getInt("pageSize");

        Log.d(Const.LOG_TAG, "IS24 search got first page, numPages: " + numPages + " results: " + results
                + " pageSize: " + pageSize);
        // return if there aren't enough results
        if (results < min || numPages * pageSize < min || results <= 0)
            return null;

        // parse flats from 1st result page
        Flats flats = new Flats(max);
        flats.parse(json);

        // calc pages to get
        int pages = max / pageSize;
        if (pages >= 0 && max % pageSize > 0)
            pages++;
        if (pages > numPages) // if this happens theres something wrong here or in the json
            pages = numPages;

        // evtly get more pages
        for (int i = 2; i <= pages; i++) {
            json = loadPage(lat, lon, r, i);
            flats.parse(json);
            Log.d(Const.LOG_TAG, "IS24 search got page " + i + "/" + pages + " #flats: " + flats.size());
        }

        // restrict number of results
        if (flats.size() > max) {
            Flats lessFlats = new Flats(max);
            lessFlats.addAll(flats.subList(0, max));
            flats = lessFlats;
        }
        return flats;
    }

    /**
     * Gets result page number 'page' from IS24 for the given lat,lon,r
     * @param lat
     * @param lon
     * @param r
     * @param page
     * @return
     * @throws MalformedURLException
     * @throws JSONException
     */
    private JSONObject loadPage(double lat, double lon, float r, int page)
            throws MalformedURLException, JSONException {
        URL url = new URL(OAuthData.SERVER + OAuthData.SEARCH_PREFIX
                + "search/radius.json?realEstateType=apartmentrent&pagenumber=" + page + "&geocoordinates=" + lat
                + ";" + lon + ";" + r);
        JSONObject obj = WebHelper.getHttpData(url, true, this);
        if (obj == null) { // does this ever happen?
            throw new JSONException("Got (JSONObject) null for search result. Lat: " + lat + "Lon: " + lon + " R: "
                    + r + " pageNr: " + page);
        }
        return obj;
    }
}