WeatherInformation: usind broadcastrecevier
authorgu.martinm@gmail.com <gu.martinm@gmail.com>
Mon, 15 Sep 2014 17:52:14 +0000 (19:52 +0200)
committergu.martinm@gmail.com <gu.martinm@gmail.com>
Mon, 15 Sep 2014 17:52:14 +0000 (19:52 +0200)
Because there are many problems when screen rotates I am going to use
local broadcast receiver. Android sucks a lot!!!!

Android/WeatherInformation/src/de/example/exampletdd/MapActivity.java
Android/WeatherInformation/src/de/example/exampletdd/fragment/current/CurrentFragment.java
Android/WeatherInformation/src/de/example/exampletdd/fragment/overview/OverviewFragment.java

index 92fea33..7df3ba0 100644 (file)
@@ -7,8 +7,10 @@ import java.util.Locale;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.Dialog;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.IntentSender.SendIntentException;
 import android.location.Address;
 import android.location.Geocoder;
@@ -18,10 +20,10 @@ import android.os.Build;
 import android.os.Bundle;
 import android.support.v4.app.DialogFragment;
 import android.support.v4.app.FragmentActivity;
+import android.support.v4.content.LocalBroadcastManager;
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
-import android.widget.ProgressBar;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -53,14 +55,16 @@ public class MapActivity extends FragmentActivity implements
        // Request code to use when launching the resolution activity
     private static final int REQUEST_RESOLVE_ERROR = 1001;
     private WeatherLocation mRestoreUI;
+    private BroadcastReceiver mReceiver;
        
     // Google Play Services Map
     private GoogleMap mMap;
     // TODO: read and store from different threads? Hopefully always from UI thread.
     private Marker mMarker;
-    private ProgressBar mActivityIndicator;
-    // true progress bar visible/false progress bar gone
-    private boolean mIsProgressBarVisible;
+    // IT IS IMPOSSIBLE IF SCREEN MAY ROTATE!!!! ANDROID SUCKS!!!!
+//    private ProgressBar mActivityIndicator;
+//    // true progress bar visible/false progress bar gone
+//    private boolean mIsProgressBarVisible;
     
     // Google Play Services Location
     private GoogleApiClient mGoogleApiClient;
@@ -99,15 +103,15 @@ public class MapActivity extends FragmentActivity implements
         this.mMap.setOnMapLongClickListener(new MapActivityOnMapLongClickListener(this));
         
         // Progress bar. View and status (we keep status even after screen rotations.
-        this.mActivityIndicator = (ProgressBar) this.findViewById(R.id.weather_map_progress);
-        if (savedInstanceState != null) {
-               this.mIsProgressBarVisible = savedInstanceState.getBoolean("mIsProgressBarVisible", false);
-        }
-        if (this.mIsProgressBarVisible) {
-               this.mActivityIndicator.setVisibility(View.VISIBLE);
-        } else {
-               this.mActivityIndicator.setVisibility(View.GONE);
-        }
+//        this.mActivityIndicator = (ProgressBar) this.findViewById(R.id.weather_map_progress);
+//        if (savedInstanceState != null) {
+//             this.mIsProgressBarVisible = savedInstanceState.getBoolean("mIsProgressBarVisible", false);
+//        }
+//        if (this.mIsProgressBarVisible) {
+//             this.mActivityIndicator.setVisibility(View.VISIBLE);
+//        } else {
+//             this.mActivityIndicator.setVisibility(View.GONE);
+//        }
     }
     
     @Override
@@ -138,7 +142,7 @@ public class MapActivity extends FragmentActivity implements
                // just once
                this.mRestoreUI = null;
         } else {
-               final DatabaseQueries query = new DatabaseQueries(this);
+               final DatabaseQueries query = new DatabaseQueries(this.getApplicationContext());
                weatherLocation = query.queryDataBase();
         }
         
@@ -169,7 +173,7 @@ public class MapActivity extends FragmentActivity implements
             savedInstanceState.putSerializable("WeatherLocation", location);
         }
        // Save progress bar status.
-       savedInstanceState.putBoolean("mIsProgressBarVisible", this.mIsProgressBarVisible);
+//     savedInstanceState.putBoolean("mIsProgressBarVisible", this.mIsProgressBarVisible);
                
        // Google Play Services
        // To keep track of the boolean across activity restarts (such as when
@@ -190,7 +194,7 @@ public class MapActivity extends FragmentActivity implements
             final String cityString = city.getText().toString();
             final String countryString = country.getText().toString();
             
-               final DatabaseQueries query = new DatabaseQueries(this);
+               final DatabaseQueries query = new DatabaseQueries(this.getApplicationContext());
                final WeatherLocation weatherLocation = query.queryDataBase();
             if (weatherLocation != null) {
                weatherLocation
@@ -265,9 +269,9 @@ public class MapActivity extends FragmentActivity implements
         protected void onPreExecute() {
                // TODO: The same with Overview and Current? I guess so...
                // Show the activity indicator
-               final MapActivity activity = (MapActivity) this.localContext;
-               activity.mActivityIndicator.setVisibility(View.VISIBLE);
-               activity.mIsProgressBarVisible = true;
+//             final MapActivity activity = (MapActivity) this.localContext;
+//             activity.mActivityIndicator.setVisibility(View.VISIBLE);
+//             activity.mIsProgressBarVisible = true;
         }
         
         @Override
@@ -287,20 +291,18 @@ public class MapActivity extends FragmentActivity implements
 
         @Override
         protected void onPostExecute(final WeatherLocation weatherLocation) {
-               final MapActivity activity = (MapActivity) this.localContext;
-               activity.mActivityIndicator.setVisibility(View.GONE);
-               activity.mIsProgressBarVisible = false;
-               
                // TODO: Is AsyncTask calling this method even when RunTimeException in doInBackground method?
-               // I hope so, otherwise I must catch(Throwable) in doInBackground method :(             
-            if (weatherLocation == null) {
-               // TODO: if user changed activity, where is this going to appear?
-                final DialogFragment newFragment = ErrorDialogFragment.newInstance(R.string.error_dialog_location_error);
-                newFragment.show(activity.getSupportFragmentManager(), "errorDialog");
-                return;
-            }
+               // I hope so, otherwise I must catch(Throwable) in doInBackground method :(
+               if (weatherLocation == null) {
+                       // Nothing to do
+                       // TODO: Should I show some error message? I am not doing it on WP8 Should I do it on WP8?
+                       return;
+               }
 
-            activity.updateUI(weatherLocation);
+            // Call updateUI on the UI thread.
+            final Intent weatherLocationData = new Intent("de.example.exampletdd.UPDATEWEATHERLOCATION");
+            weatherLocationData.putExtra("weatherLocation", weatherLocation);
+            LocalBroadcastManager.getInstance(this.localContext).sendBroadcastSync(weatherLocationData);
         }
         
         private WeatherLocation getLocation(final double latitude, final double longitude) throws IOException {
@@ -434,6 +436,36 @@ public class MapActivity extends FragmentActivity implements
         if (!mResolvingError) {
             mGoogleApiClient.connect();
         }
+
+        this.mReceiver = new BroadcastReceiver() {
+
+                       @Override
+                       public void onReceive(final Context context, final Intent intent) {
+                               final String action = intent.getAction();
+                               if (action.equals("de.example.exampletdd.UPDATEWEATHERLOCATION")) {
+                                       final WeatherLocation weatherLocation = (WeatherLocation) intent.getSerializableExtra("weatherLocation");
+
+//                             MapActivity.this.mActivityIndicator.setVisibility(View.GONE);
+//                             MapActivity.this.mIsProgressBarVisible = false;
+
+                               // TODO: Is AsyncTask calling this method even when RunTimeException in doInBackground method?
+                               // I hope so, otherwise I must catch(Throwable) in doInBackground method :(
+                           if (weatherLocation == null) {
+                               final DialogFragment newFragment = ErrorDialogFragment.newInstance(R.string.error_dialog_location_error);
+                               newFragment.setRetainInstance(true);
+                               newFragment.show(MapActivity.this.getSupportFragmentManager(), "errorDialog");
+                               return;
+                           }
+
+                           MapActivity.this.updateUI(weatherLocation);
+                               }
+                       }
+        };
+
+        // Register receiver
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction("de.example.exampletdd.UPDATEWEATHERLOCATION");
+        LocalBroadcastManager.getInstance(this.getApplicationContext()).registerReceiver(this.mReceiver, filter);
     }
     
     /**
@@ -449,6 +481,8 @@ public class MapActivity extends FragmentActivity implements
        mGoogleApiClient.unregisterConnectionFailedListener(this);
         mGoogleApiClient.disconnect();
 
+        LocalBroadcastManager.getInstance(this.getApplicationContext()).unregisterReceiver(this.mReceiver);
+
         super.onStop();
     }
     
@@ -492,6 +526,8 @@ public class MapActivity extends FragmentActivity implements
     /**
      * Called by Location Services if the attempt to
      * Location Services fails.
+     *
+     * IT NEVER DOES ANYTHING. ANDROID SUCKS!!!
      */
        @Override
        public void onConnectionFailed(final ConnectionResult result) {
@@ -535,6 +571,8 @@ public class MapActivity extends FragmentActivity implements
      * LocationUpdateRemover and LocationUpdateRequester may call startResolutionForResult() to
      * start an Activity that handles Google Play services problems. The result of this
      * call returns here, to onActivityResult.
+     *
+     * IT NEVER DOES ANYTHING. ANDROID SUCKS!!!
      */
     @Override
     protected void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
index b605248..ca61875 100644 (file)
@@ -13,6 +13,10 @@ import java.util.Locale;
 
 import org.apache.http.client.ClientProtocolException;
 
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -21,6 +25,7 @@ import android.os.AsyncTask;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
 import android.support.v4.app.Fragment;
+import android.support.v4.content.LocalBroadcastManager;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -42,6 +47,7 @@ import de.example.exampletdd.service.ServiceParser;
 
 public class CurrentFragment extends Fragment {
     private static final String TAG = "CurrentFragment";
+    private BroadcastReceiver mReceiver;
 
     @Override
     public void onCreate(final Bundle savedInstanceState) {
@@ -75,10 +81,45 @@ public class CurrentFragment extends Fragment {
     }
 
     @Override
+    public void onStart() {
+       super.onStart();
+
+        this.mReceiver = new BroadcastReceiver() {
+
+                       @Override
+                       public void onReceive(final Context context, final Intent intent) {
+                               final String action = intent.getAction();
+                               if (action.equals("de.example.exampletdd.UPDATECURRENT")) {
+                                       final Current current = (Current) intent.getSerializableExtra("current");
+
+                                       if (current != null) {
+                                               CurrentFragment.this.updateUI(current);
+
+                                   final WeatherInformationApplication application =
+                                               (WeatherInformationApplication) getActivity().getApplication();
+                                   application.setCurrent(current);
+
+                                   final DatabaseQueries query = new DatabaseQueries(CurrentFragment.this.getActivity().getApplicationContext());
+                                   final WeatherLocation weatherLocation = query.queryDataBase();
+                                   weatherLocation.setLastCurrentUIUpdate(new Date());
+                                   query.updateDataBase(weatherLocation);
+                                       }
+                               }
+                       }
+        };
+
+        // Register receiver
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction("de.example.exampletdd.UPDATECURRENT");
+        LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext())
+                                                       .registerReceiver(this.mReceiver, filter);
+    }
+
+    @Override
     public void onResume() {
         super.onResume();
 
-        final DatabaseQueries query = new DatabaseQueries(this.getActivity());
+        final DatabaseQueries query = new DatabaseQueries(this.getActivity().getApplicationContext());
         final WeatherLocation weatherLocation = query.queryDataBase();
         if (weatherLocation == null) {
             // Nothing to do.
@@ -95,7 +136,7 @@ public class CurrentFragment extends Fragment {
             // Load remote data (aynchronous)
             // Gets the data from the web.
             final CurrentTask task = new CurrentTask(
-                       this,
+                       this.getActivity().getApplicationContext(),
                     new CustomHTTPClient(AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")),
                     new ServiceParser(new JPOSWeatherParser()));
 
@@ -121,6 +162,13 @@ public class CurrentFragment extends Fragment {
         super.onSaveInstanceState(savedInstanceState);
     }
 
+    @Override
+    public void onStop() {
+        LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()).unregisterReceiver(this.mReceiver);
+
+        super.onStop();
+    }
+
     private void updateUI(final Current current) {
        
         final SharedPreferences sharedPreferences = PreferenceManager
@@ -287,13 +335,14 @@ public class CurrentFragment extends Fragment {
     //       I mean, if OverviewTask shows one progress dialog and CurrentTask does the same I will have
     //       have two progress dialogs... How may I solve this problem? I HATE ANDROID.
     private class CurrentTask extends AsyncTask<Object, Void, Current> {
-        private final Fragment localFragment;
+       // Store the context passed to the AsyncTask when the system instantiates it.
+        private final Context localContext;
         final CustomHTTPClient weatherHTTPClient;
         final ServiceParser weatherService;
 
-        public CurrentTask(final Fragment fragment, final CustomHTTPClient weatherHTTPClient,
+        public CurrentTask(final Context context, final CustomHTTPClient weatherHTTPClient,
                        final ServiceParser weatherService) {
-               this.localFragment = fragment;
+               this.localContext = context;
             this.weatherHTTPClient = weatherHTTPClient;
             this.weatherService = weatherService;
         }
@@ -353,16 +402,9 @@ public class CurrentFragment extends Fragment {
                }
 
             // Call updateUI on the UI thread.
-               updateUI(current);
-
-            final WeatherInformationApplication application =
-                       (WeatherInformationApplication) getActivity().getApplication();
-            application.setCurrent(current);
-
-            final DatabaseQueries query = new DatabaseQueries(this.localFragment.getActivity());
-            final WeatherLocation weatherLocation = query.queryDataBase();
-            weatherLocation.setLastCurrentUIUpdate(new Date());
-            query.updateDataBase(weatherLocation);
+            final Intent currentData = new Intent("de.example.exampletdd.UPDATECURRENT");
+            currentData.putExtra("current", current);
+            LocalBroadcastManager.getInstance(this.localContext).sendBroadcastSync(currentData);
         }
     }
 }
index ef3f73f..bb9b881 100644 (file)
@@ -15,8 +15,11 @@ import java.util.Locale;
 
 import org.apache.http.client.ClientProtocolException;
 
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -24,8 +27,8 @@ import android.net.http.AndroidHttpClient;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
-import android.support.v4.app.Fragment;
 import android.support.v4.app.ListFragment;
+import android.support.v4.content.LocalBroadcastManager;
 import android.util.Log;
 import android.view.View;
 import android.widget.ListView;
@@ -45,6 +48,7 @@ import de.example.exampletdd.service.ServiceParser;
 
 public class OverviewFragment extends ListFragment {
     private static final String TAG = "OverviewFragment";
+    private BroadcastReceiver mReceiver;
 
     @Override
     public void onCreate(final Bundle savedInstanceState) {
@@ -79,10 +83,45 @@ public class OverviewFragment extends ListFragment {
     }
 
     @Override
+    public void onStart() {
+       super.onStart();
+
+        this.mReceiver = new BroadcastReceiver() {
+
+                       @Override
+                       public void onReceive(final Context context, final Intent intent) {
+                               final String action = intent.getAction();
+                               if (action.equals("de.example.exampletdd.UPDATEFORECAST")) {
+                                       final Forecast forecast = (Forecast) intent.getSerializableExtra("forecast");
+
+                                       if (forecast != null) {
+                                               OverviewFragment.this.updateUI(forecast);
+
+                                   final WeatherInformationApplication application =
+                                               (WeatherInformationApplication) getActivity().getApplication();
+                                   application.setForecast(forecast);
+
+                                   final DatabaseQueries query = new DatabaseQueries(OverviewFragment.this.getActivity().getApplicationContext());
+                                   final WeatherLocation weatherLocation = query.queryDataBase();
+                                   weatherLocation.setLastForecastUIUpdate(new Date());
+                                   query.updateDataBase(weatherLocation);
+                                       }
+                               }
+                       }
+        };
+
+        // Register receiver
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction("de.example.exampletdd.UPDATEFORECAST");
+        LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext())
+                                                       .registerReceiver(this.mReceiver, filter);
+    }
+
+    @Override
     public void onResume() {
         super.onResume();
 
-        final DatabaseQueries query = new DatabaseQueries(this.getActivity());
+        final DatabaseQueries query = new DatabaseQueries(this.getActivity().getApplicationContext());
         final WeatherLocation weatherLocation = query.queryDataBase();
         if (weatherLocation == null) {
             // Nothing to do.
@@ -99,7 +138,7 @@ public class OverviewFragment extends ListFragment {
             // Load remote data (aynchronous)
             // Gets the data from the web.
             final OverviewTask task = new OverviewTask(
-                       this,
+                       this.getActivity().getApplicationContext(),
                     new CustomHTTPClient(AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")),
                     new ServiceParser(new JPOSWeatherParser()));
 
@@ -126,6 +165,13 @@ public class OverviewFragment extends ListFragment {
     }
 
     @Override
+    public void onStop() {
+        LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()).unregisterReceiver(this.mReceiver);
+
+        super.onStop();
+    }
+
+    @Override
     public void onListItemClick(final ListView l, final View v, final int position, final long id) {
         final SpecificFragment fragment = (SpecificFragment) this
                 .getFragmentManager().findFragmentById(R.id.weather_specific_fragment);
@@ -255,24 +301,26 @@ public class OverviewFragment extends ListFragment {
     //       I mean, if OverviewTask shows one progress dialog and CurrentTask does the same I will have
     //       have two progress dialogs... How may I solve this problem? I HATE ANDROID.
     private class OverviewTask extends AsyncTask<Object, Void, Forecast> {
-       private final Fragment localFragment;
+       // Store the context passed to the AsyncTask when the system instantiates it.
+        private final Context localContext;
         private final CustomHTTPClient weatherHTTPClient;
         private final ServiceParser weatherService;
 
-        public OverviewTask(final Fragment fragment, final CustomHTTPClient weatherHTTPClient,
+        public OverviewTask(final Context context, final CustomHTTPClient weatherHTTPClient,
                        final ServiceParser weatherService) {
-               this.localFragment = fragment;
+               this.localContext = context;
             this.weatherHTTPClient = weatherHTTPClient;
             this.weatherService = weatherService;
         }
 
         @Override
         protected void onPreExecute() {
-               final OverviewFragment overview = (OverviewFragment) this.localFragment;
-               overview.setListAdapter(null);
-            // TODO: string static resource
-               overview.setEmptyText("No data available");
-               overview.setListShownNoAnimation(false);
+               // IMPOSSIBLE IF I USE JUST Context (I like Context because it doesn't die like Activity does when screen rotates)
+//             final OverviewFragment overview = (OverviewFragment) this.localFragment;
+//             overview.setListAdapter(null);
+//            // TODO: string static resource
+//             overview.setEmptyText("No data available");
+//             overview.setListShownNoAnimation(false);
         }
         
         @Override
@@ -320,10 +368,11 @@ public class OverviewFragment extends ListFragment {
         protected void onPostExecute(final Forecast forecast) {
                // TODO: Is AsyncTask calling this method even when RunTimeException in doInBackground method?
                // I hope so, otherwise I must catch(Throwable) in doInBackground method :(
-               final OverviewFragment overview = (OverviewFragment) this.localFragment;
-               // TODO: string static resource
-               overview.setEmptyText("Error trying to download remote data");
-               overview.setListShownNoAnimation(true);
+               // IMPOSSIBLE IF I USE JUST Context (I like Context because it doesn't die like Activity does when screen rotates)
+//             final OverviewFragment overview = (OverviewFragment) this.localFragment;
+//             // TODO: string static resource
+//             overview.setEmptyText("Error trying to download remote data");
+//             overview.setListShownNoAnimation(true);
                
                if (forecast == null) {
                        // Nothing to do
@@ -332,16 +381,9 @@ public class OverviewFragment extends ListFragment {
                }
 
             // Call updateUI on the UI thread.
-            updateUI(forecast);
-
-            final WeatherInformationApplication application =
-                       (WeatherInformationApplication) getActivity().getApplication();
-            application.setForecast(forecast);
-
-            final DatabaseQueries query = new DatabaseQueries(this.localFragment.getActivity());
-            final WeatherLocation weatherLocation = query.queryDataBase();
-            weatherLocation.setLastForecastUIUpdate(new Date());
-            query.updateDataBase(weatherLocation);
+               final Intent forecastData = new Intent("de.example.exampletdd.UPDATEFORECAST");
+               forecastData.putExtra("forecast", forecast);
+            LocalBroadcastManager.getInstance(this.localContext).sendBroadcastSync(forecastData);
         }
     }
 }