Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 package org.adblockplus.android; | |
2 | |
3 import java.io.IOException; | |
4 import java.io.InputStream; | |
5 import java.io.OutputStream; | |
6 import java.util.Calendar; | |
7 import java.util.Date; | |
8 import java.util.List; | |
9 | |
10 import android.app.ActivityManager; | |
11 import android.app.ActivityManager.RunningServiceInfo; | |
12 import android.app.AlertDialog; | |
13 import android.content.BroadcastReceiver; | |
14 import android.content.Context; | |
15 import android.content.DialogInterface; | |
16 import android.content.DialogInterface.OnDismissListener; | |
17 import android.content.Intent; | |
18 import android.content.IntentFilter; | |
19 import android.content.SharedPreferences; | |
20 import android.content.pm.PackageManager.NameNotFoundException; | |
21 import android.content.res.AssetManager; | |
22 import android.net.Uri; | |
23 import android.os.Bundle; | |
24 import android.preference.CheckBoxPreference; | |
25 import android.preference.ListPreference; | |
26 import android.preference.PreferenceManager; | |
27 import android.text.format.DateFormat; | |
28 import android.util.Log; | |
29 import android.view.Menu; | |
30 import android.view.MenuInflater; | |
31 import android.view.MenuItem; | |
32 import android.view.View; | |
33 import android.view.Window; | |
34 import android.widget.TextView; | |
35 | |
36 /** | |
37 * Main settings UI. | |
38 */ | |
39 public class Preferences extends SummarizedPreferences | |
40 { | |
41 private final static String TAG = "Preferences"; | |
Felix Dahlke
2012/10/09 14:27:29
As in AdvancedPreferences, "static final"?
Andrey Novikov
2012/10/12 13:19:14
Done.
| |
42 | |
43 private AboutDialog aboutDialog; | |
44 private boolean showAbout = false; | |
45 private String configurationMsg; | |
46 private String subscriptionSummary; | |
47 | |
48 @Override | |
49 public void onCreate(Bundle savedInstanceState) | |
50 { | |
51 requestWindowFeature(Window.FEATURE_NO_TITLE); | |
52 | |
53 super.onCreate(savedInstanceState); | |
54 | |
55 PreferenceManager.setDefaultValues(this, R.xml.preferences, false); | |
56 PreferenceManager.setDefaultValues(this, R.xml.preferences_advanced, false); | |
57 setContentView(R.layout.preferences); | |
58 addPreferencesFromResource(R.xml.preferences); | |
59 | |
60 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this ); | |
61 | |
62 // Check if we need to update assets | |
63 int lastVersion = prefs.getInt(getString(R.string.pref_version), 0); | |
64 try | |
65 { | |
66 int thisVersion = getPackageManager().getPackageInfo(getPackageName(), 0). versionCode; | |
67 if (lastVersion != thisVersion) | |
68 { | |
69 copyAssets(); | |
70 SharedPreferences.Editor editor = prefs.edit(); | |
71 editor.putInt(getString(R.string.pref_version), thisVersion); | |
72 editor.commit(); | |
73 } | |
74 } | |
75 catch (NameNotFoundException e) | |
76 { | |
77 copyAssets(); | |
Felix Dahlke
2012/10/09 14:27:29
Why can this getPackageInfo fail while those in Ab
Andrey Novikov
2012/10/12 13:19:14
It can not. But I prefer to be reinsured in this c
| |
78 } | |
79 } | |
80 | |
81 @Override | |
82 protected void onStart() | |
83 { | |
84 super.onStart(); | |
85 AdblockPlus application = AdblockPlus.getApplication(); | |
86 application.startEngine(); | |
87 application.startInteractive(); | |
88 } | |
89 | |
90 @Override | |
91 public void onResume() | |
Felix Dahlke
2012/10/09 14:27:29
Another long method, same comment as for AdvancedP
Andrey Novikov
2012/10/12 13:19:14
Same comment :) See code comments - they are for y
| |
92 { | |
93 super.onResume(); | |
94 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this ); | |
95 | |
96 final AdblockPlus application = AdblockPlus.getApplication(); | |
97 | |
98 // Construct subscription list | |
99 RefreshableListPreference subscriptionList = (RefreshableListPreference) fin dPreference(getString(R.string.pref_subscription)); | |
100 List<Subscription> subscriptions = application.getSubscriptions(); | |
101 String[] entries = new String[subscriptions.size()]; | |
102 String[] entryValues = new String[subscriptions.size()]; | |
103 String current = prefs.getString(getString(R.string.pref_subscription), (Str ing) null); | |
104 int i = 0; | |
105 for (Subscription subscription : subscriptions) | |
106 { | |
107 entries[i] = subscription.title; | |
108 entryValues[i] = subscription.url; | |
109 i++; | |
110 } | |
111 subscriptionList.setEntries(entries); | |
112 subscriptionList.setEntryValues(entryValues); | |
113 | |
114 boolean firstRun = false; | |
115 | |
116 // If there is no current subscription autoselect one | |
117 if (current == null) | |
118 { | |
119 firstRun = true; | |
120 Subscription offer = application.offerSubscription(); | |
121 current = offer.url; | |
122 if (offer != null) | |
123 { | |
124 subscriptionList.setValue(offer.url); | |
125 application.setSubscription(offer); | |
126 new AlertDialog.Builder(this).setTitle(R.string.app_name).setMessage(Str ing.format(getString(R.string.msg_subscription_offer, offer.title))).setIcon(and roid.R.drawable.ic_dialog_info) | |
127 .setPositiveButton(R.string.ok, null).create().show(); | |
128 } | |
129 } | |
130 | |
131 // Enable manual subscription refresh | |
132 subscriptionList.setOnRefreshClickListener(new View.OnClickListener() { | |
Felix Dahlke
2012/10/09 14:27:29
Brace on its own line please.
Andrey Novikov
2012/10/12 13:19:14
Done.
| |
133 @Override | |
134 public void onClick(View v) | |
135 { | |
136 application.refreshSubscription(); | |
137 } | |
138 }); | |
139 | |
140 // Set subscription status message | |
141 if (subscriptionSummary != null) | |
142 subscriptionList.setSummary(subscriptionSummary); | |
143 else | |
144 setPrefSummary(subscriptionList); | |
145 | |
146 // Time to start listening for events | |
147 registerReceiver(receiver, new IntentFilter(AdblockPlus.BROADCAST_SUBSCRIPTI ON_STATUS)); | |
148 registerReceiver(receiver, new IntentFilter(AdblockPlus.BROADCAST_FILTER_MAT CHES)); | |
149 registerReceiver(receiver, new IntentFilter(ProxyService.BROADCAST_STATE_CHA NGED)); | |
150 registerReceiver(receiver, new IntentFilter(ProxyService.BROADCAST_PROXY_FAI LED)); | |
151 | |
152 final String url = current; | |
153 | |
154 // Initialize subscription verification | |
155 (new Thread() { | |
Felix Dahlke
2012/10/09 14:27:29
Brace on its own line please.
Andrey Novikov
2012/10/12 13:19:14
Done.
| |
156 @Override | |
157 public void run() | |
158 { | |
159 if (!application.verifySubscriptions()) | |
160 { | |
161 Subscription subscription = application.getSubscription(url); | |
162 application.setSubscription(subscription); | |
163 } | |
164 } | |
165 }).start(); | |
166 | |
167 // Check if service is running and update UI accordingly | |
168 boolean enabled = prefs.getBoolean(getString(R.string.pref_enabled), false); | |
169 if (enabled && !isServiceRunning()) | |
170 { | |
171 setEnabled(false); | |
172 enabled = false; | |
Felix Dahlke
2012/10/09 14:27:29
enabled isn't read past this point, Setting it to
Andrey Novikov
2012/10/12 13:19:14
Done.
| |
173 } | |
174 // Run service if this is first application run | |
175 else if (!enabled && firstRun) | |
176 { | |
177 startService(new Intent(this, ProxyService.class)); | |
178 setEnabled(true); | |
179 } | |
180 | |
181 // Process screen rotation | |
182 if (configurationMsg != null) | |
183 showConfigurationMsg(configurationMsg); | |
184 | |
185 if (showAbout) | |
186 onAbout(findViewById(R.id.btn_about)); | |
187 } | |
188 | |
189 @Override | |
190 public void onPause() | |
191 { | |
192 super.onPause(); | |
193 unregisterReceiver(receiver); | |
194 } | |
195 | |
196 @Override | |
197 protected void onStop() | |
198 { | |
199 super.onStop(); | |
200 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this ); | |
201 boolean enabled = prefs.getBoolean(getString(R.string.pref_enabled), false); | |
202 AdblockPlus application = AdblockPlus.getApplication(); | |
203 application.stopInteractive(); | |
204 if (!enabled) | |
205 application.stopEngine(true); | |
206 | |
207 if (aboutDialog != null) | |
208 aboutDialog.dismiss(); | |
209 } | |
210 | |
211 @Override | |
212 public boolean onCreateOptionsMenu(Menu menu) | |
213 { | |
214 MenuInflater inflater = getMenuInflater(); | |
215 inflater.inflate(R.menu.menu_preferences, menu); | |
216 return true; | |
217 } | |
218 | |
219 @Override | |
220 public boolean onOptionsItemSelected(MenuItem item) | |
221 { | |
222 switch (item.getItemId()) | |
223 { | |
224 case R.id.menu_advanced: | |
225 startActivity(new Intent(this, AdvancedPreferences.class)); | |
226 return true; | |
227 default: | |
228 return super.onOptionsItemSelected(item); | |
229 } | |
230 } | |
231 | |
232 private void setEnabled(boolean enabled) | |
233 { | |
234 SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferen ces(this).edit(); | |
235 editor.putBoolean(getString(R.string.pref_enabled), enabled); | |
236 editor.commit(); | |
237 ((CheckBoxPreference) findPreference(getString(R.string.pref_enabled))).setC hecked(enabled); | |
238 } | |
239 | |
240 /** | |
241 * Checks if ProxyService is running. | |
242 * | |
243 * @return true if service is running | |
244 */ | |
245 private boolean isServiceRunning() | |
246 { | |
247 ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVIC E); | |
248 // Actually it returns not only running services, so extra check is required | |
249 for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VAL UE)) | |
250 { | |
251 if ("org.adblockplus.android.ProxyService".equals(service.service.getClass Name()) && service.pid > 0) | |
252 return true; | |
253 } | |
254 return false; | |
255 } | |
256 | |
257 /** | |
258 * Copies file assets from installation package to filesystem. | |
259 */ | |
260 private void copyAssets() | |
261 { | |
262 AssetManager assetManager = getAssets(); | |
263 String[] files = null; | |
264 try | |
265 { | |
266 files = assetManager.list("install"); | |
267 } | |
268 catch (IOException e) | |
269 { | |
270 Log.e(TAG, e.getMessage()); | |
Felix Dahlke
2012/10/09 14:27:29
Why not pass e as the third parameter, like below?
Andrey Novikov
2012/10/12 13:19:14
Done.
| |
271 } | |
272 for (int i = 0; i < files.length; i++) | |
273 { | |
274 InputStream in = null; | |
Felix Dahlke
2012/10/09 14:27:29
in and out can be declared in the try block, they
Andrey Novikov
2012/10/12 13:19:14
Done.
| |
275 OutputStream out = null; | |
276 try | |
277 { | |
278 Log.d(TAG, "Copy: install/" + files[i]); | |
279 in = assetManager.open("install/" + files[i]); | |
280 out = openFileOutput(files[i], MODE_PRIVATE); | |
281 byte[] buffer = new byte[1024]; | |
282 int read; | |
283 while ((read = in.read(buffer)) != -1) | |
284 { | |
285 out.write(buffer, 0, read); | |
286 } | |
287 in.close(); | |
288 in = null; | |
Felix Dahlke
2012/10/09 14:27:29
You don't need to set in/out to null, they aren't
Andrey Novikov
2012/10/12 13:19:14
Done.
| |
289 out.flush(); | |
290 out.close(); | |
291 out = null; | |
292 | |
293 } | |
294 catch (Exception e) | |
295 { | |
296 Log.e(TAG, "Asset copy error", e); | |
297 } | |
298 } | |
299 } | |
300 | |
301 /** | |
302 * Redirects user to configuration URL. | |
303 */ | |
304 public void onHelp(View view) | |
305 { | |
306 Uri uri = Uri.parse(getString(R.string.configuring_url)); | |
307 final Intent intent = new Intent(Intent.ACTION_VIEW, uri); | |
Felix Dahlke
2012/10/09 14:27:29
Why make intent final?
Andrey Novikov
2012/10/12 13:19:14
No reason, just copied url opening code from sampl
| |
308 startActivity(intent); | |
309 } | |
310 | |
311 /** | |
312 * Shows about dialog. | |
313 */ | |
314 public void onAbout(View view) | |
315 { | |
316 aboutDialog = new AboutDialog(this); | |
317 aboutDialog.setOnDismissListener(new OnDismissListener() { | |
318 | |
319 @Override | |
320 public void onDismiss(DialogInterface dialog) | |
321 { | |
322 showAbout = false; | |
Felix Dahlke
2012/10/09 14:27:29
Naming nit pick: This sounds imperative, how about
Andrey Novikov
2012/10/12 13:19:14
For me name is correct - it flags if have to show
| |
323 aboutDialog = null; | |
324 } | |
325 }); | |
326 showAbout = true; | |
327 aboutDialog.show(); | |
328 } | |
329 | |
330 @Override | |
331 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Str ing key) | |
332 { | |
333 if (getString(R.string.pref_enabled).equals(key)) | |
334 { | |
335 boolean enabled = sharedPreferences.getBoolean(key, false); | |
336 if (enabled && !isServiceRunning()) | |
337 startService(new Intent(this, ProxyService.class)); | |
338 else if (!enabled && isServiceRunning()) | |
Felix Dahlke
2012/10/09 14:27:29
I'd feel safer is isServiceRunning() was called ju
Andrey Novikov
2012/10/12 13:19:14
Done.
| |
339 stopService(new Intent(this, ProxyService.class)); | |
340 } | |
341 if (getString(R.string.pref_subscription).equals(key)) | |
342 { | |
343 String current = sharedPreferences.getString(key, null); | |
344 AdblockPlus application = AdblockPlus.getApplication(); | |
345 Subscription subscription = application.getSubscription(current); | |
346 application.setSubscription(subscription); | |
347 } | |
348 super.onSharedPreferenceChanged(sharedPreferences, key); | |
349 } | |
350 | |
351 private void showConfigurationMsg(String message) | |
352 { | |
353 TextView msg = (TextView) findViewById(R.id.txt_configuration); | |
354 msg.setText(message); | |
355 msg.setVisibility(View.VISIBLE); | |
356 configurationMsg = message; | |
357 } | |
358 | |
359 private void hideConfigurationMsg() | |
360 { | |
361 if (configurationMsg == null) | |
362 return; | |
363 TextView msg = (TextView) findViewById(R.id.txt_configuration); | |
364 msg.setVisibility(View.GONE); | |
365 configurationMsg = null; | |
366 } | |
367 | |
368 private BroadcastReceiver receiver = new BroadcastReceiver() { | |
Felix Dahlke
2012/10/09 14:27:29
Brace on a new line please.
Andrey Novikov
2012/10/12 13:19:14
Done.
| |
369 @Override | |
370 public void onReceive(final Context context, Intent intent) | |
Felix Dahlke
2012/10/09 14:27:29
Why make context final?
Andrey Novikov
2012/10/12 13:19:14
It was previously used in a new thread, fixed.
| |
371 { | |
372 String action = intent.getAction(); | |
373 Bundle extra = intent.getExtras(); | |
374 if (action.equals(ProxyService.BROADCAST_STATE_CHANGED)) | |
375 { | |
376 if (extra.getBoolean("enabled")) | |
377 { | |
378 // If service is enabled in manual mode, show configuration message | |
379 if (extra.getBoolean("manual")) | |
380 { | |
381 showConfigurationMsg(getString(R.string.msg_configuration, extra.get Int("port"))); | |
382 } | |
383 } | |
384 else | |
385 { | |
386 setEnabled(false); | |
387 hideConfigurationMsg(); | |
388 } | |
389 } | |
390 if (action.equals(AdblockPlus.BROADCAST_FILTER_MATCHES)) | |
391 { | |
392 // Hide configuration message if traffic is detected | |
393 hideConfigurationMsg(); | |
394 } | |
395 if (action.equals(ProxyService.BROADCAST_PROXY_FAILED)) | |
396 { | |
397 String msg = extra.getString("msg"); | |
398 new AlertDialog.Builder(Preferences.this).setTitle(R.string.error).setMe ssage(msg).setIcon(android.R.drawable.ic_dialog_alert).setPositiveButton(R.strin g.ok, null).create().show(); | |
399 setEnabled(false); | |
400 } | |
401 if (action.equals(AdblockPlus.BROADCAST_SUBSCRIPTION_STATUS)) | |
402 { | |
403 final String text = extra.getString("text"); | |
404 final long time = extra.getLong("time"); | |
405 runOnUiThread(new Runnable() { | |
406 public void run() | |
407 { | |
408 setSubscriptionStatus(text, time); | |
409 } | |
410 }); | |
411 } | |
412 } | |
413 }; | |
414 | |
415 /** | |
416 * Constructs and updates subscription status text. | |
417 * | |
418 * @param text | |
419 * status message | |
420 * @param time | |
421 * time of last change | |
422 */ | |
423 private void setSubscriptionStatus(String text, long time) | |
424 { | |
425 ListPreference subscriptionList = (ListPreference) findPreference(getString( R.string.pref_subscription)); | |
426 CharSequence summary = subscriptionList.getEntry(); | |
427 StringBuilder builder = new StringBuilder(); | |
428 if (summary != null) | |
429 { | |
430 builder.append(summary); | |
431 if (text != "") | |
432 { | |
433 builder.append(" ("); | |
434 int id = getResources().getIdentifier(text, "string", getPackageName()); | |
435 if (id > 0) | |
436 builder.append(getString(id, text)); | |
437 else | |
438 builder.append(text); | |
439 if (time > 0) | |
440 { | |
441 builder.append(": "); | |
442 Calendar calendar = Calendar.getInstance(); | |
443 calendar.setTimeInMillis(time); | |
444 Date date = calendar.getTime(); | |
445 builder.append(DateFormat.getDateFormat(this).format(date)); | |
446 builder.append(" "); | |
447 builder.append(DateFormat.getTimeFormat(this).format(date)); | |
448 } | |
449 builder.append(")"); | |
450 } | |
451 subscriptionSummary = builder.toString(); | |
452 subscriptionList.setSummary(subscriptionSummary); | |
453 } | |
454 } | |
455 | |
456 @Override | |
457 protected void onRestoreInstanceState(Bundle state) | |
458 { | |
459 super.onRestoreInstanceState(state); | |
460 showAbout = state.getBoolean("showAbout"); | |
461 configurationMsg = state.getString("configurationMsg"); | |
462 subscriptionSummary = state.getString("subscriptionSummary"); | |
463 } | |
464 | |
465 @Override | |
466 protected void onSaveInstanceState(Bundle outState) | |
467 { | |
468 outState.putString("subscriptionSummary", subscriptionSummary); | |
469 outState.putString("configurationMsg", configurationMsg); | |
470 outState.putBoolean("showAbout", showAbout); | |
471 super.onSaveInstanceState(outState); | |
472 } | |
473 } | |
OLD | NEW |