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 static final String TAG = "Preferences"; |
| 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(); |
| 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() |
| 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() |
| 133 { |
| 134 @Override |
| 135 public void onClick(View v) |
| 136 { |
| 137 application.refreshSubscription(); |
| 138 } |
| 139 }); |
| 140 |
| 141 // Set subscription status message |
| 142 if (subscriptionSummary != null) |
| 143 subscriptionList.setSummary(subscriptionSummary); |
| 144 else |
| 145 setPrefSummary(subscriptionList); |
| 146 |
| 147 // Time to start listening for events |
| 148 registerReceiver(receiver, new IntentFilter(AdblockPlus.BROADCAST_SUBSCRIPTI
ON_STATUS)); |
| 149 registerReceiver(receiver, new IntentFilter(AdblockPlus.BROADCAST_FILTER_MAT
CHES)); |
| 150 registerReceiver(receiver, new IntentFilter(ProxyService.BROADCAST_STATE_CHA
NGED)); |
| 151 registerReceiver(receiver, new IntentFilter(ProxyService.BROADCAST_PROXY_FAI
LED)); |
| 152 |
| 153 final String url = current; |
| 154 |
| 155 // Initialize subscription verification |
| 156 (new Thread() |
| 157 { |
| 158 @Override |
| 159 public void run() |
| 160 { |
| 161 if (!application.verifySubscriptions()) |
| 162 { |
| 163 Subscription subscription = application.getSubscription(url); |
| 164 application.setSubscription(subscription); |
| 165 } |
| 166 } |
| 167 }).start(); |
| 168 |
| 169 // Check if service is running and update UI accordingly |
| 170 boolean enabled = prefs.getBoolean(getString(R.string.pref_enabled), false); |
| 171 if (enabled && !isServiceRunning()) |
| 172 { |
| 173 setEnabled(false); |
| 174 } |
| 175 // Run service if this is first application run |
| 176 else if (!enabled && firstRun) |
| 177 { |
| 178 startService(new Intent(this, ProxyService.class)); |
| 179 setEnabled(true); |
| 180 } |
| 181 |
| 182 // Process screen rotation |
| 183 if (configurationMsg != null) |
| 184 showConfigurationMsg(configurationMsg); |
| 185 |
| 186 if (showAbout) |
| 187 onAbout(findViewById(R.id.btn_about)); |
| 188 } |
| 189 |
| 190 @Override |
| 191 public void onPause() |
| 192 { |
| 193 super.onPause(); |
| 194 unregisterReceiver(receiver); |
| 195 } |
| 196 |
| 197 @Override |
| 198 protected void onStop() |
| 199 { |
| 200 super.onStop(); |
| 201 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this
); |
| 202 boolean enabled = prefs.getBoolean(getString(R.string.pref_enabled), false); |
| 203 AdblockPlus application = AdblockPlus.getApplication(); |
| 204 application.stopInteractive(); |
| 205 if (!enabled) |
| 206 application.stopEngine(true); |
| 207 |
| 208 if (aboutDialog != null) |
| 209 aboutDialog.dismiss(); |
| 210 } |
| 211 |
| 212 @Override |
| 213 public boolean onCreateOptionsMenu(Menu menu) |
| 214 { |
| 215 MenuInflater inflater = getMenuInflater(); |
| 216 inflater.inflate(R.menu.menu_preferences, menu); |
| 217 return true; |
| 218 } |
| 219 |
| 220 @Override |
| 221 public boolean onOptionsItemSelected(MenuItem item) |
| 222 { |
| 223 switch (item.getItemId()) |
| 224 { |
| 225 case R.id.menu_advanced: |
| 226 startActivity(new Intent(this, AdvancedPreferences.class)); |
| 227 return true; |
| 228 default: |
| 229 return super.onOptionsItemSelected(item); |
| 230 } |
| 231 } |
| 232 |
| 233 private void setEnabled(boolean enabled) |
| 234 { |
| 235 SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferen
ces(this).edit(); |
| 236 editor.putBoolean(getString(R.string.pref_enabled), enabled); |
| 237 editor.commit(); |
| 238 ((CheckBoxPreference) findPreference(getString(R.string.pref_enabled))).setC
hecked(enabled); |
| 239 } |
| 240 |
| 241 /** |
| 242 * Checks if ProxyService is running. |
| 243 * |
| 244 * @return true if service is running |
| 245 */ |
| 246 private boolean isServiceRunning() |
| 247 { |
| 248 ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVIC
E); |
| 249 // Actually it returns not only running services, so extra check is required |
| 250 for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VAL
UE)) |
| 251 { |
| 252 if ("org.adblockplus.android.ProxyService".equals(service.service.getClass
Name()) && service.pid > 0) |
| 253 return true; |
| 254 } |
| 255 return false; |
| 256 } |
| 257 |
| 258 /** |
| 259 * Copies file assets from installation package to filesystem. |
| 260 */ |
| 261 private void copyAssets() |
| 262 { |
| 263 AssetManager assetManager = getAssets(); |
| 264 String[] files = null; |
| 265 try |
| 266 { |
| 267 files = assetManager.list("install"); |
| 268 } |
| 269 catch (IOException e) |
| 270 { |
| 271 Log.e(TAG, "Failed to get assets list", e); |
| 272 } |
| 273 for (int i = 0; i < files.length; i++) |
| 274 { |
| 275 try |
| 276 { |
| 277 Log.d(TAG, "Copy: install/" + files[i]); |
| 278 InputStream in = assetManager.open("install/" + files[i]); |
| 279 OutputStream out = openFileOutput(files[i], MODE_PRIVATE); |
| 280 byte[] buffer = new byte[1024]; |
| 281 int read; |
| 282 while ((read = in.read(buffer)) != -1) |
| 283 { |
| 284 out.write(buffer, 0, read); |
| 285 } |
| 286 in.close(); |
| 287 out.flush(); |
| 288 out.close(); |
| 289 } |
| 290 catch (Exception e) |
| 291 { |
| 292 Log.e(TAG, "Asset copy error", e); |
| 293 } |
| 294 } |
| 295 } |
| 296 |
| 297 /** |
| 298 * Redirects user to configuration URL. |
| 299 */ |
| 300 public void onHelp(View view) |
| 301 { |
| 302 Uri uri = Uri.parse(getString(R.string.configuring_url)); |
| 303 Intent intent = new Intent(Intent.ACTION_VIEW, uri); |
| 304 startActivity(intent); |
| 305 } |
| 306 |
| 307 /** |
| 308 * Shows about dialog. |
| 309 */ |
| 310 public void onAbout(View view) |
| 311 { |
| 312 aboutDialog = new AboutDialog(this); |
| 313 aboutDialog.setOnDismissListener(new OnDismissListener() |
| 314 { |
| 315 |
| 316 @Override |
| 317 public void onDismiss(DialogInterface dialog) |
| 318 { |
| 319 showAbout = false; |
| 320 aboutDialog = null; |
| 321 } |
| 322 }); |
| 323 showAbout = true; |
| 324 aboutDialog.show(); |
| 325 } |
| 326 |
| 327 @Override |
| 328 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Str
ing key) |
| 329 { |
| 330 if (getString(R.string.pref_enabled).equals(key)) |
| 331 { |
| 332 boolean enabled = sharedPreferences.getBoolean(key, false); |
| 333 boolean serviceRunning = isServiceRunning(); |
| 334 if (enabled && !serviceRunning) |
| 335 startService(new Intent(this, ProxyService.class)); |
| 336 else if (!enabled && serviceRunning) |
| 337 stopService(new Intent(this, ProxyService.class)); |
| 338 } |
| 339 if (getString(R.string.pref_subscription).equals(key)) |
| 340 { |
| 341 String current = sharedPreferences.getString(key, null); |
| 342 AdblockPlus application = AdblockPlus.getApplication(); |
| 343 Subscription subscription = application.getSubscription(current); |
| 344 application.setSubscription(subscription); |
| 345 } |
| 346 super.onSharedPreferenceChanged(sharedPreferences, key); |
| 347 } |
| 348 |
| 349 private void showConfigurationMsg(String message) |
| 350 { |
| 351 TextView msg = (TextView) findViewById(R.id.txt_configuration); |
| 352 msg.setText(message); |
| 353 msg.setVisibility(View.VISIBLE); |
| 354 configurationMsg = message; |
| 355 } |
| 356 |
| 357 private void hideConfigurationMsg() |
| 358 { |
| 359 if (configurationMsg == null) |
| 360 return; |
| 361 TextView msg = (TextView) findViewById(R.id.txt_configuration); |
| 362 msg.setVisibility(View.GONE); |
| 363 configurationMsg = null; |
| 364 } |
| 365 |
| 366 private BroadcastReceiver receiver = new BroadcastReceiver() |
| 367 { |
| 368 @Override |
| 369 public void onReceive(Context context, Intent intent) |
| 370 { |
| 371 String action = intent.getAction(); |
| 372 Bundle extra = intent.getExtras(); |
| 373 if (action.equals(ProxyService.BROADCAST_STATE_CHANGED)) |
| 374 { |
| 375 if (extra.getBoolean("enabled")) |
| 376 { |
| 377 // If service is enabled in manual mode, show configuration message |
| 378 if (extra.getBoolean("manual")) |
| 379 { |
| 380 showConfigurationMsg(getString(R.string.msg_configuration, extra.get
Int("port"))); |
| 381 } |
| 382 } |
| 383 else |
| 384 { |
| 385 setEnabled(false); |
| 386 hideConfigurationMsg(); |
| 387 } |
| 388 } |
| 389 if (action.equals(AdblockPlus.BROADCAST_FILTER_MATCHES)) |
| 390 { |
| 391 // Hide configuration message if traffic is detected |
| 392 hideConfigurationMsg(); |
| 393 } |
| 394 if (action.equals(ProxyService.BROADCAST_PROXY_FAILED)) |
| 395 { |
| 396 String msg = extra.getString("msg"); |
| 397 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(); |
| 398 setEnabled(false); |
| 399 } |
| 400 if (action.equals(AdblockPlus.BROADCAST_SUBSCRIPTION_STATUS)) |
| 401 { |
| 402 final String text = extra.getString("text"); |
| 403 final long time = extra.getLong("time"); |
| 404 runOnUiThread(new Runnable() |
| 405 { |
| 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 |