dcf399cc46c0a5dc66d384cd1017f60d44e74d9a
[JavaForFun] /
1 /**
2  * Copyright 2014 Gustavo Martin Morcuende
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package name.gumartinm.weather.information.fragment.map;
17
18 import java.io.IOException;
19 import java.util.List;
20 import java.util.Locale;
21
22 import android.app.Activity;
23 import android.content.Context;
24 import android.location.Address;
25 import android.location.Geocoder;
26 import android.os.AsyncTask;
27 import android.os.Bundle;
28 import android.support.v4.app.Fragment;
29 import android.util.Log;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.ViewGroup;
33
34 import name.gumartinm.weather.information.R;
35 import name.gumartinm.weather.information.model.WeatherLocation;
36
37 /**
38  * {@link http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html}
39  *
40  */
41 public class MapProgressFragment extends Fragment {
42
43         /**
44          * 
45          * Callback interface through which the fragment will report the
46          * task's progress and results back to the Activity.
47          */
48         public static interface TaskCallbacks {
49                 void onPostExecute(final WeatherLocation weatherLocation);
50         }
51         
52         private TaskCallbacks mCallbacks;
53         
54     @Override
55     public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
56                              final Bundle savedInstanceState) {
57     
58         // Inflate the layout for this fragment
59         return inflater.inflate(R.layout.weather_map_progress, container, false);
60     }
61     
62     /**
63      * This method will only be called once when the retained
64      * Fragment is first created.
65      */
66     @Override
67     public void onCreate(Bundle savedInstanceState) {
68         super.onCreate(savedInstanceState);
69         
70         // Retain this fragment across configuration changes.
71         this.setRetainInstance(true);
72         
73         final Bundle bundle = this.getArguments();
74         double latitude = bundle.getDouble("latitude");
75         double longitude = bundle.getDouble("longitude");
76         
77         // Create and execute the background task.
78         new GetAddressTask(this.getActivity().getApplicationContext()).execute(latitude, longitude);
79     }
80     
81         /**
82          * Hold a reference to the parent Activity so we can report the
83          * task's current progress and results. The Android framework 
84          * will pass us a reference to the newly created Activity after 
85          * each configuration change.
86          */
87         @Override
88         public void onAttach(final Activity activity) {
89                 super.onAttach(activity);
90                 mCallbacks = (TaskCallbacks) activity;
91         }
92         
93         /**
94          * Set the callback to null so we don't accidentally leak the 
95          * Activity instance.
96          */
97 //      @Override
98 //      public void onDetach() {
99 //              super.onDetach();
100 //              mCallbacks = null;
101 //      }
102         
103         /**
104          * I am not using onDetach because there are problems when my activity goes to background.
105          * 
106          * {@link http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html}
107          */
108         @Override
109         public void onPause() {
110                 super.onPause();
111                 mCallbacks = null;
112         }
113     
114     private class GetAddressTask extends AsyncTask<Object, Void, WeatherLocation> {
115         private static final String TAG = "GetAddressTask";
116         // Store the context passed to the AsyncTask when the system instantiates it.
117         private final Context localContext;
118
119         private GetAddressTask(final Context context) {
120                 this.localContext = context;    
121         }
122         
123         @Override
124         protected WeatherLocation doInBackground(final Object... params) {
125             final double latitude = (Double) params[0];
126             final double longitude = (Double) params[1];
127
128             WeatherLocation weatherLocation = this.doDefaultLocation(latitude, longitude);
129             try {
130                 weatherLocation = this.getLocation(latitude, longitude);
131             } catch (final Throwable e) { // Hopefully nothing goes wrong because of catching Throwable.
132                 Log.e(TAG, "GetAddressTask doInBackground exception: ", e);
133             }
134
135             return weatherLocation;
136         }
137
138         @Override
139         protected void onPostExecute(final WeatherLocation weatherLocation) {
140  
141             // Call updateUI on the UI thread.
142                 if (mCallbacks != null) {
143                         mCallbacks.onPostExecute(weatherLocation);
144                 }
145         }
146         
147         private WeatherLocation getLocation(final double latitude, final double longitude) throws IOException {
148                 // TODO: i18n Locale.getDefault()
149             final Geocoder geocoder = new Geocoder(this.localContext, Locale.US);
150             final List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
151
152             // Default values
153             WeatherLocation weatherLocation = this.doDefaultLocation(latitude, longitude);
154             
155             if (addresses != null && addresses.size() > 0) {
156                 if (addresses.get(0).getLocality() != null) {
157                         weatherLocation.setCity(addresses.get(0).getLocality());
158                 }
159                 if(addresses.get(0).getCountryName() != null) {
160                         weatherLocation.setCountry(addresses.get(0).getCountryName());
161                 }       
162             }
163
164             return weatherLocation;
165         }
166
167         private WeatherLocation doDefaultLocation(final double latitude, final double longitude) {
168                 // Default values
169             String city = this.localContext.getString(R.string.city_not_found);
170             String country = this.localContext.getString(R.string.country_not_found);
171
172             return new WeatherLocation()
173                         .setLatitude(latitude)
174                         .setLongitude(longitude)
175                         .setCity(city)
176                         .setCountry(country);
177         }
178     }
179 }