summaryrefslogtreecommitdiff
path: root/java/com/android/incallui/calllocation/impl/ReverseGeocodeTask.java
blob: f4592d4c8fbe4957ab24f8f03db3c8a8cc508e16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.incallui.calllocation.impl;

import android.location.Location;
import android.net.TrafficStats;
import android.os.AsyncTask;
import com.android.dialer.common.LogUtil;
import com.android.dialer.constants.TrafficStatsTags;
import com.android.incallui.calllocation.impl.LocationPresenter.LocationUi;
import java.lang.ref.WeakReference;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

class ReverseGeocodeTask extends AsyncTask<Location, Void, String> {

  // Below are the JSON keys for the reverse geocode response.
  // Source: https://developers.google.com/maps/documentation/geocoding/#ReverseGeocoding
  private static final String JSON_KEY_RESULTS = "results";
  private static final String JSON_KEY_ADDRESS = "formatted_address";
  private static final String JSON_KEY_ADDRESS_COMPONENTS = "address_components";
  private static final String JSON_KEY_PREMISE = "premise";
  private static final String JSON_KEY_TYPES = "types";
  private static final String JSON_KEY_LONG_NAME = "long_name";
  private static final String JSON_KEY_SHORT_NAME = "short_name";

  private WeakReference<LocationUi> uiReference;

  public ReverseGeocodeTask(WeakReference<LocationUi> uiReference) {
    this.uiReference = uiReference;
  }

  @Override
  protected String doInBackground(Location... locations) {
    LocationUi ui = uiReference.get();
    if (ui == null) {
      return null;
    }
    if (locations == null || locations.length == 0) {
      LogUtil.e("ReverseGeocodeTask.onLocationChanged", "No location provided");
      return null;
    }

    try {
      String address = null;
      String url = LocationUrlBuilder.getReverseGeocodeUrl(locations[0]);

      TrafficStats.setThreadStatsTag(TrafficStatsTags.REVERSE_GEOCODE_TAG);
      String jsonResponse = HttpFetcher.getRequestAsString(ui.getContext(), url);

      // Parse the JSON response for the formatted address of the first result.
      JSONObject responseObject = new JSONObject(jsonResponse);
      if (responseObject != null) {
        JSONArray results = responseObject.optJSONArray(JSON_KEY_RESULTS);
        if (results != null && results.length() > 0) {
          JSONObject topResult = results.optJSONObject(0);
          if (topResult != null) {
            address = topResult.getString(JSON_KEY_ADDRESS);

            // Strip off the Premise component from the address, if present.
            JSONArray components = topResult.optJSONArray(JSON_KEY_ADDRESS_COMPONENTS);
            if (components != null) {
              boolean stripped = false;
              for (int i = 0; !stripped && i < components.length(); i++) {
                JSONObject component = components.optJSONObject(i);
                JSONArray types = component.optJSONArray(JSON_KEY_TYPES);
                if (types != null) {
                  for (int j = 0; !stripped && j < types.length(); j++) {
                    if (JSON_KEY_PREMISE.equals(types.getString(j))) {
                      String premise = null;
                      if (component.has(JSON_KEY_SHORT_NAME)
                          && address.startsWith(component.getString(JSON_KEY_SHORT_NAME))) {
                        premise = component.getString(JSON_KEY_SHORT_NAME);
                      } else if (component.has(JSON_KEY_LONG_NAME)
                          && address.startsWith(component.getString(JSON_KEY_LONG_NAME))) {
                        premise = component.getString(JSON_KEY_SHORT_NAME);
                      }
                      if (premise != null) {
                        int index = address.indexOf(',', premise.length());
                        if (index > 0 && index < address.length()) {
                          address = address.substring(index + 1).trim();
                        }
                        stripped = true;
                        break;
                      }
                    }
                  }
                }
              }
            }

            // Strip off the country, if its USA.  Note: unfortunately the country in the formatted
            // address field doesn't match the country in the address component fields (USA != US)
            // so we can't easily strip off the country for all cases, thus this hack.
            if (address.endsWith(", USA")) {
              address = address.substring(0, address.length() - 5);
            }
          }
        }
      }

      return address;
    } catch (AuthException ex) {
      LogUtil.e("ReverseGeocodeTask.onLocationChanged", "AuthException", ex);
      return null;
    } catch (JSONException ex) {
      LogUtil.e("ReverseGeocodeTask.onLocationChanged", "JSONException", ex);
      return null;
    } catch (Exception ex) {
      LogUtil.e("ReverseGeocodeTask.onLocationChanged", "Exception!!!", ex);
      return null;
    } finally {
      TrafficStats.clearThreadStatsTag();
    }
  }

  @Override
  protected void onPostExecute(String address) {
    LocationUi ui = uiReference.get();
    if (ui == null) {
      return;
    }

    try {
      ui.setAddress(address);
    } catch (Exception ex) {
      LogUtil.e("ReverseGeocodeTask.onPostExecute", "Exception!!!", ex);
    }
  }
}