]> www.average.org Git - WhereAmI.git/blob - src/org/average/whereami/WhereAmI.java
Stay alive unless closed from menu
[WhereAmI.git] / src / org / average / whereami / WhereAmI.java
1 package org.average.whereami;
2
3 import org.average.whereami.WhereAmIprefs;
4 import org.average.whereami.APIBase;
5 import org.average.whereami.Oracle;
6 import org.average.whereami.PhoneLog;
7 import org.average.whereami.LastLocation;
8
9 import java.util.Random;
10
11 import android.app.Activity;
12 import android.net.wifi.WifiManager;
13 import android.os.Build;
14 import android.os.Bundle;
15 import android.os.AsyncTask;
16 import android.os.Handler;
17 import android.os.SystemClock;
18 import android.net.ConnectivityManager;
19 import android.net.NetworkInfo;
20 import android.content.BroadcastReceiver;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.content.Context;
24 import android.content.res.Resources;
25 import android.content.SharedPreferences;
26 import android.preference.PreferenceManager;
27 import android.text.format.Time;
28 import android.util.Log;
29 import android.view.View;
30 import android.view.KeyEvent;
31 import android.view.Menu;
32 import android.view.MenuInflater;
33 import android.view.MenuItem;
34 import android.view.Window;
35 import android.view.WindowManager;
36 import android.widget.TextView;
37
38 public class WhereAmI extends Activity
39 {
40     final String TAG = getClass().getName();
41
42     private WifiManager wifiman;
43     private Boolean managewifi = false;
44     private Long updatedelay = 60000L;
45     private Integer runningtasks = 0;
46     private SharedPreferences prefs;
47     private PersistentStore store;
48     private Random random = new Random();
49     private Boolean revive = false;
50     private Context context;
51
52     private class UpdateTarget {
53         private TextView tv;
54         private Oracle updater;
55         private BgUpdate task;
56
57         private class BgUpdate extends AsyncTask<Void, Void, String> {
58             @Override
59             protected String doInBackground(Void... params) {
60                 Log.v(TAG, "BgUpdate " + updater + " starting");
61                 Utterance result = updater.getResult();
62                 for (int i = 2; !result.success && i <= 3; i++) {
63                     SystemClock.sleep(1000 + random.nextInt(1000));
64                     result = updater.getResult();
65                 }
66                 if (!result.success) {
67                     Log.e(TAG, "After third attempt still " +
68                                 result.message);
69                 }
70                 return result.message;
71             }
72         
73             @Override
74             protected void onPostExecute(String str) {
75                 Log.v(TAG, "BgUpdate callback executing");
76                 tv.setText(str);
77                 runningtasks--;
78                 if (runningtasks <= 0) {
79                     if (managewifi) {
80                         boolean wifion = wifiman.setWifiEnabled(false);
81                         Log.v(TAG, "disabling wifi result " + wifion);
82                     }
83                     Time tm = new Time();
84                     tm.setToNow();
85                     tvs.setText(R.string.lasttry);
86                     tvs.append(tm.format(" %d/%m/%Y %H:%M"));
87                 }
88             }
89
90             @Override
91             protected void onCancelled() {
92                 Log.v(TAG, "BgUpdate callback cancelled");
93                 runningtasks--;
94             }
95         }
96
97         public UpdateTarget(TextView tv, Oracle updater) {
98             this.tv = tv;
99             this.updater = updater;
100         }
101
102         public void launch() {
103             tv.setText(R.string.updating);
104             task = new BgUpdate();
105             task.execute();
106         }
107
108         public void cancel() {
109             task.cancel(true);
110         }
111     }
112     private UpdateTarget[] ut;
113
114     private TextView tvt, tvd, tvs;
115     private Resources res;
116     private String[] month;
117     private String[] wday;
118
119     private Handler mHandler = new Handler();
120
121     private Runnable reviveSelf = new Runnable() {
122         public void run() {
123             Log.v(TAG, "trying to revive self");
124             Intent intent = new Intent(Intent.ACTION_MAIN);
125             intent.addCategory(Intent.CATEGORY_LAUNCHER );
126             intent.setClass(context, WhereAmI.class);
127             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
128             intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
129             intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
130             intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
131             startActivity(intent);
132         }
133     };
134
135     private Runnable updateClock = new Runnable () {
136         public void run() {
137             long now = System.currentTimeMillis();
138             Time tm = new Time();
139             tm.set(now);
140             tvt.setText(tm.format("%H:%M"));
141             tm.set(now + 60000);
142             tm.second=0;
143             long next = tm.toMillis(false);
144             mHandler.postDelayed(this, next-now+1);
145         }
146     };
147
148     private Runnable updateCal = new Runnable () {
149         public void run() {
150             long now = System.currentTimeMillis();
151             Time tm = new Time();
152             tm.set(now);
153             tvd.setText(
154                        wday[tm.weekDay] +
155                        tm.format("\n%d ") +
156                        month[tm.month] +
157                        tm.format(" %Y"));
158             tm.set(now + 86400000);
159             tm.hour=0;
160             tm.minute=0;
161             tm.second=0;
162             long next = tm.toMillis(false);
163             mHandler.postDelayed(this, next-now+1);
164         }
165     };
166
167     private Runnable updateInfo = new Runnable () {
168         public void run() {
169             Log.v(TAG, "updateInfo starting");
170             if (managewifi) {
171                 IntentFilter intentFilter =
172                     new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
173                 registerReceiver(connChanged,intentFilter);
174                 connChangedRegistered = true;
175                 boolean wifion = wifiman.setWifiEnabled(true);
176                 Log.v(TAG, "enabling wifi result " + wifion);
177             } else {
178                 for (int i = 0; i < ut.length; i++) {
179                     runningtasks++;
180                     ut[i].launch();
181                 }
182             }
183             mHandler.postDelayed(resetInfo, 50000);
184             mHandler.postDelayed(this, updatedelay);
185         }
186     };
187
188     private Runnable resetInfo = new Runnable () {
189         public void run() {
190             Log.v(TAG, "resetInfo starting");
191             if (connChangedRegistered) {
192                 unregisterReceiver(connChanged);
193                 connChangedRegistered = false;
194             }
195             if (runningtasks > 0) {
196                 for (int i = 0; i < ut.length; i++) {
197                     ut[i].cancel();
198                 }
199                 runningtasks = 0;
200                 Time tm = new Time();
201                 tm.setToNow();
202                 tvs.setText(R.string.failtry);
203                 tvs.append(tm.format(" %d/%m/%Y %H:%M"));
204             }
205             if (managewifi) {
206                 boolean wifion = wifiman.setWifiEnabled(false);
207                 Log.v(TAG, "disabling wifi result " + wifion);
208             }
209         }
210     };
211
212     private boolean connChangedRegistered = false;
213     private final BroadcastReceiver connChanged = new BroadcastReceiver() {
214         @Override
215         public void onReceive(Context context, Intent intent) {
216             ConnectivityManager cm = (ConnectivityManager)context.
217                            getSystemService(Context.CONNECTIVITY_SERVICE);
218             NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
219             boolean isConnected = activeNetwork != null &&
220                                   activeNetwork.isConnectedOrConnecting();
221             Log.v(TAG, "Connectivity changed to " + isConnected);
222             if (isConnected) {
223                 for (int i = 0; i < ut.length; i++) {
224                     runningtasks++;
225                     ut[i].launch();
226                 }
227             }
228         }
229     };
230
231     /** Called when the activity is first created. */
232     @Override
233     public void onCreate(Bundle savedInstanceState) {
234         super.onCreate(savedInstanceState);
235         context = this;
236         if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.FROYO) {
237             Log.v(TAG, "Disabling keepalive for build version " +
238                        Build.VERSION.SDK_INT);
239             System.setProperty("http.keepAlive", "false");
240         } else {
241             Log.v(TAG, "Post-Froyo version " +
242                         Build.VERSION.SDK_INT);
243         }
244         prefs = PreferenceManager.getDefaultSharedPreferences(this);
245         store = new PersistentStore(prefs);
246         wifiman = (WifiManager)getSystemService(Context.WIFI_SERVICE);
247         requestWindowFeature(Window.FEATURE_NO_TITLE);
248         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
249         setContentView(R.layout.main);
250         res = getResources();
251         month = res.getStringArray(R.array.month);
252         wday = res.getStringArray(R.array.wday);
253         tvt = (TextView)findViewById(R.id.time);
254         tvd = (TextView)findViewById(R.id.date);
255         tvs = (TextView)findViewById(R.id.timestamp);
256         APIBase base = new APIBase(res, store);
257         ut = new UpdateTarget[] {
258             new UpdateTarget((TextView)findViewById(R.id.phonecall),
259                              new PhoneLog(base)),
260             new UpdateTarget((TextView)findViewById(R.id.location),
261                              new LastLocation(base))
262         };
263     }
264
265     /** Called when reactivated */
266     @Override
267     public void onResume() {
268         super.onResume();
269         boolean fullscreen = prefs.getBoolean("fullscreen", false);
270         managewifi = prefs.getBoolean("managewifi", false);
271         updatedelay = Long.parseLong(prefs.getString("updateperiod", "1200000"));
272         Log.v("WhereAmI", "fullscreen: " + fullscreen +
273                           ", managewifi: " + managewifi +
274                           ", updatedelay: " + updatedelay);
275         if (fullscreen) {
276             getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
277             getWindow().clearFlags(WindowManager.LayoutParams.
278                                                   FLAG_FORCE_NOT_FULLSCREEN);
279         } else {
280             getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
281         }
282         revive = true;
283         mHandler.post(updateClock);
284         mHandler.post(updateCal);
285         mHandler.post(updateInfo);
286         Log.v(TAG, "update tasks scheduled");
287     }
288
289     /** Called when put to background */
290     @Override
291     public void onPause() {
292         super.onPause();
293         Log.v(TAG, "going background");
294         resetInfo.run();
295         mHandler.removeCallbacks(updateClock);
296         mHandler.removeCallbacks(updateCal);
297         mHandler.removeCallbacks(updateInfo);
298         if (revive) {
299             Log.v(TAG, "scheduling revival");
300             mHandler.postDelayed(reviveSelf, 6000); // 6 second delay
301         }
302     }
303
304     /** Called when the activity is destroyed. */
305     @Override
306     public void onDestroy() {
307         super.onDestroy();
308         Log.v(TAG, "going down");
309     }
310
311     /** Called when the menu is activated. */
312     @Override
313     public boolean onCreateOptionsMenu(Menu menu) {
314         MenuInflater inflater = getMenuInflater();
315         inflater.inflate(R.menu.main_menu, menu);
316         return true;
317     }
318
319     /** Called when the menu item is selected */
320     @Override
321     public boolean onOptionsItemSelected(MenuItem item) {
322         switch (item.getItemId()) {
323         case R.id.quit:
324             revive = false;
325             finish();
326             return true;
327         case R.id.authorize:
328             Log.v(TAG, "authorize requested");
329             startActivity(new Intent(this, Authorize.class));
330             return true;
331         case R.id.settings:
332             Log.v(TAG, "settings requested");
333             startActivity(new Intent(this, WhereAmIprefs.class));
334             return true;
335         default:
336             return super.onOptionsItemSelected(item);
337         }
338     }
339
340     /** Override "back" button. Can still quit via menu. */
341     @Override
342     public boolean onKeyDown(int keyCode, KeyEvent event) {
343         if (keyCode == KeyEvent.KEYCODE_BACK) {
344             return true;
345         }
346         return super.onKeyDown(keyCode, event);
347     }
348 }