clean lines on import
[adBlock.git] / src / de / ub0r / android / adBlock / AdBlock.java
blob941b9667585a406a6021b2372e6c0c515ad476a5
1 /*
2 * Copyright (C) 2009 Felix Bechstein
3 *
4 * This file is part of AdBlock.
5 *
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free Software
8 * Foundation; either version 3 of the License, or (at your option) any later
9 * version.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 * details.
16 * You should have received a copy of the GNU General Public License along with
17 * this program; If not, see <http://www.gnu.org/licenses/>.
19 package de.ub0r.android.adBlock;
21 import java.io.BufferedReader;
22 import java.io.IOException;
23 import java.io.InputStreamReader;
24 import java.net.HttpURLConnection;
25 import java.net.MalformedURLException;
26 import java.net.URL;
27 import java.util.ArrayList;
29 import android.app.Activity;
30 import android.app.AlertDialog;
31 import android.app.Dialog;
32 import android.content.ActivityNotFoundException;
33 import android.content.DialogInterface;
34 import android.content.Intent;
35 import android.content.SharedPreferences;
36 import android.net.Uri;
37 import android.os.AsyncTask;
38 import android.os.Bundle;
39 import android.preference.PreferenceManager;
40 import android.util.Log;
41 import android.view.Menu;
42 import android.view.MenuInflater;
43 import android.view.MenuItem;
44 import android.view.View;
45 import android.view.View.OnClickListener;
46 import android.widget.AdapterView;
47 import android.widget.ArrayAdapter;
48 import android.widget.Button;
49 import android.widget.EditText;
50 import android.widget.LinearLayout;
51 import android.widget.ListView;
52 import android.widget.TextView;
53 import android.widget.Toast;
54 import android.widget.AdapterView.OnItemClickListener;
56 /**
57 * Main Activity to control ad blocking Proxy.
59 * @author Felix Bechstein
61 public class AdBlock extends Activity implements OnClickListener,
62 OnItemClickListener {
64 /** Tag for output. */
65 private static final String TAG = "AdBlock";
67 /** Prefs: name for last version run. */
68 private static final String PREFS_LAST_RUN = "lastrun";
69 /** Preferences: import url. */
70 private static final String PREFS_IMPORT_URL = "importurl";
72 /** Filename for export of filter. */
73 // private static final String FILENAME_EXPORT = "/sdcard/filter.txt";
74 /** ItemDialog: edit. */
75 private static final short ITEM_DIALOG_EDIT = 0;
76 /** ItemDialog: delete. */
77 private static final short ITEM_DIALOG_DELETE = 1;
79 /** Dialog: about. */
80 private static final int DIALOG_ABOUT = 0;
81 /** Dialog: import. */
82 private static final int DIALOG_IMPORT = 1;
83 /** Dialog: update. */
84 private static final int DIALOG_UPDATE = 2;
86 /** Prefs. */
87 private SharedPreferences preferences;
88 /** Prefs. import URL. */
89 private String importUrl = null;
91 /** The filter. */
92 private ArrayList<String> filter = new ArrayList<String>();
93 /** The ArrayAdapter. */
94 private ArrayAdapter<String> adapter = null;
96 /** Editmode? */
97 private int itemToEdit = -1;
99 /**
100 * Import filter from URL on background.
102 * @author Felix Bechstein
104 class Importer extends AsyncTask<String, Boolean, Boolean> {
105 /** Error message. */
106 private String message = "";
109 * Do the work.
111 * @param dummy
112 * nothing here
113 * @return successful?
115 @Override
116 protected final Boolean doInBackground(final String... dummy) {
117 try {
118 HttpURLConnection c = (HttpURLConnection) (new URL(
119 AdBlock.this.importUrl)).openConnection();
120 int resp = c.getResponseCode();
121 if (resp != 200) {
122 return false;
124 BufferedReader reader = new BufferedReader(
125 new InputStreamReader(c.getInputStream()));
126 AdBlock.this.filter.clear();
127 while (true) {
128 String s = reader.readLine();
129 if (s == null) {
130 break;
132 s = s.trim();
133 if (s.length() > 0) {
134 AdBlock.this.filter.add(s);
137 reader.close();
138 return true;
139 } catch (MalformedURLException e) {
140 Log.e(AdBlock.TAG, null, e);
141 this.message = e.toString();
142 return false;
143 } catch (IOException e) {
144 this.message = e.toString();
145 Log.e(AdBlock.TAG, null, e);
146 return false;
151 * Merge imported filter to the real one.
153 * @param result
154 * nothing here
156 @Override
157 protected final void onPostExecute(final Boolean result) {
158 if (result.booleanValue()) {
159 Toast.makeText(AdBlock.this, "imported", Toast.LENGTH_LONG)
160 .show();
161 AdBlock.this.adapter.notifyDataSetChanged();
162 } else {
163 Toast.makeText(AdBlock.this, "failed: " + this.message,
164 Toast.LENGTH_LONG).show();
170 * {@inheritDoc}
172 @Override
173 public final void onCreate(final Bundle savedInstanceState) {
174 super.onCreate(savedInstanceState);
175 this.setContentView(R.layout.main);
177 this.preferences = PreferenceManager.getDefaultSharedPreferences(this);
178 // display changelog?
179 String v0 = this.preferences.getString(PREFS_LAST_RUN, "");
180 String v1 = this.getString(R.string.app_version);
181 if (!v0.equals(v1)) {
182 SharedPreferences.Editor editor = this.preferences.edit();
183 editor.putString(PREFS_LAST_RUN, v1);
184 editor.commit();
185 this.showDialog(DIALOG_UPDATE);
188 ((EditText) this.findViewById(R.id.port)).setText(this.preferences
189 .getString(Proxy.PREFS_PORT, "8080"));
190 String f = this.preferences.getString(Proxy.PREFS_FILTER, this
191 .getString(R.string.default_filter));
192 for (String s : f.split("\n")) {
193 if (s.length() > 0) {
194 this.filter.add(s);
197 this.importUrl = this.preferences.getString(PREFS_IMPORT_URL, "");
199 ((Button) this.findViewById(R.id.start_service))
200 .setOnClickListener(this);
201 ((Button) this.findViewById(R.id.stop_service))
202 .setOnClickListener(this);
203 ((Button) this.findViewById(R.id.filter_add_)).setOnClickListener(this);
204 ListView lv = (ListView) this.findViewById(R.id.filter);
205 this.adapter = new ArrayAdapter<String>(this,
206 R.layout.simple_list_item_1, this.filter);
207 lv.setAdapter(this.adapter);
208 lv.setTextFilterEnabled(true);
209 lv.setOnItemClickListener(this);
211 this.startService(new Intent(this, Proxy.class));
214 /** Save Preferences. */
215 private void savePreferences() {
216 SharedPreferences.Editor editor = this.preferences.edit();
217 editor.putString(Proxy.PREFS_PORT, ((EditText) this
218 .findViewById(R.id.port)).getText().toString());
219 StringBuilder sb = new StringBuilder();
220 for (String s : this.filter) {
221 if (s.indexOf("admob") < 0 // won't block admob
222 && s.indexOf("google") < 0) { // won't block google
223 sb.append(s + "\n");
226 editor.putString(Proxy.PREFS_FILTER, sb.toString());
227 editor.putString(PREFS_IMPORT_URL, this.importUrl);
228 editor.commit();
232 * {@inheritDoc}
234 @Override
235 public final void onPause() {
236 super.onPause();
237 this.savePreferences();
241 * {@inheritDoc}
243 @Override
244 public final void onClick(final View v) {
245 switch (v.getId()) {
246 case R.id.start_service:
247 this.savePreferences();
248 this.startService(new Intent(this, Proxy.class));
249 break;
250 case R.id.stop_service:
251 this.stopService(new Intent(this, Proxy.class));
252 case R.id.filter_add_:
253 EditText et = (EditText) this.findViewById(R.id.filter_add);
254 String f = et.getText().toString();
255 if (f.length() > 0) {
256 if (this.itemToEdit >= 0) {
257 this.filter.remove(this.itemToEdit);
258 this.itemToEdit = -1;
260 this.filter.add(f);
261 et.setText("");
262 this.adapter.notifyDataSetChanged();
264 break;
265 case R.id.cancel:
266 this.dismissDialog(DIALOG_IMPORT);
267 break;
268 case R.id.ok:
269 this.dismissDialog(DIALOG_IMPORT);
270 this.importUrl = ((EditText) v.getRootView().findViewById(
271 R.id.import_url)).getText().toString();
272 new Importer().execute((String[]) null);
273 break;
274 default:
275 break;
280 * {@inheritDoc}
282 @Override
283 public final boolean onCreateOptionsMenu(final Menu menu) {
284 MenuInflater inflater = this.getMenuInflater();
285 inflater.inflate(R.menu.menu, menu);
286 return true;
290 * {@inheritDoc}
292 public final boolean onOptionsItemSelected(final MenuItem item) {
293 switch (item.getItemId()) {
294 case R.id.item_about: // start about dialog
295 this.showDialog(DIALOG_ABOUT);
296 return true;
297 case R.id.item_import:
298 this.showDialog(DIALOG_IMPORT);
299 return true;
300 case R.id.item_donate:
301 try {
302 this.startActivity(new Intent(Intent.ACTION_VIEW, Uri
303 .parse(this.getString(R.string.donate_url))));
304 } catch (ActivityNotFoundException e) {
305 Log.e(TAG, "no browser", e);
307 return true;
308 case R.id.item_more:
309 try {
310 this.startActivity(new Intent(Intent.ACTION_VIEW, Uri
311 .parse("market://search?q=pub:\"Felix Bechstein\"")));
312 } catch (ActivityNotFoundException e) {
313 Log.e(TAG, "no market", e);
315 return true;
316 // case R.id.item_export:
317 // try {
318 // // OutputStream os = this.openFileOutput(FILENAME_EXPORT,
319 // // MODE_WORLD_READABLE);
320 // File file = new File(FILENAME_EXPORT);
321 // if (!file.createNewFile()) {
322 // file.delete();
323 // file.createNewFile();
324 // }
325 // OutputStream os = new FileOutputStream(file);
326 // BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
327 // os));
328 // for (String s : this.filter) {
329 // if (s.indexOf("admob") < 0) { // won't block admob
330 // bw.append(s + "\n");
331 // }
332 // }
333 // bw.close();
334 // os.close();
335 // Toast.makeText(this, "exported to " + FILENAME_EXPORT,
336 // Toast.LENGTH_LONG).show();
337 // } catch (IOException e) {
338 // Log.e(this.TAG, null, e);
339 // Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
340 // }
341 // return true;
342 default:
343 return false;
348 * {@inheritDoc}
350 @Override
351 protected final Dialog onCreateDialog(final int id) {
352 Dialog d;
353 switch (id) {
354 case DIALOG_ABOUT:
355 d = new Dialog(this);
356 d.setContentView(R.layout.about);
357 d.setTitle(this.getString(R.string.about_) + " v"
358 + this.getString(R.string.app_version));
359 return d;
360 case DIALOG_IMPORT:
361 d = new Dialog(this);
362 d.setContentView(R.layout.import_url);
363 d.setTitle(this.getString(R.string.import_url_));
364 ((Button) d.findViewById(R.id.ok)).setOnClickListener(this);
365 ((Button) d.findViewById(R.id.cancel)).setOnClickListener(this);
366 return d;
367 case DIALOG_UPDATE:
368 final AlertDialog.Builder builder = new AlertDialog.Builder(this);
369 builder.setTitle(R.string.changelog_);
370 final String[] changes = this.getResources().getStringArray(
371 R.array.updates);
372 final StringBuilder buf = new StringBuilder(changes[0]);
373 for (int i = 1; i < changes.length; i++) {
374 buf.append("\n\n");
375 buf.append(changes[i]);
377 builder.setIcon(android.R.drawable.ic_menu_info_details);
378 builder.setMessage(buf.toString());
379 builder.setCancelable(true);
380 builder.setPositiveButton(android.R.string.ok,
381 new DialogInterface.OnClickListener() {
382 public void onClick(final DialogInterface dialog,
383 final int id) {
384 dialog.cancel();
387 return builder.create();
388 default:
389 return null;
394 * {@inheritDoc}
396 @Override
397 protected final void onPrepareDialog(final int id, final Dialog dialog) {
398 super.onPrepareDialog(id, dialog);
399 switch (id) {
400 case DIALOG_IMPORT:
401 ((EditText) dialog.findViewById(R.id.import_url))
402 .setText(this.importUrl);
403 break;
404 default:
405 break;
410 * {@inheritDoc}
412 @Override
413 public final void onItemClick(final AdapterView<?> parent, final View v,
414 final int position, final long id) {
416 AlertDialog.Builder builder = new AlertDialog.Builder(this);
417 builder.setItems(
418 this.getResources().getStringArray(R.array.itemDialog),
419 new DialogInterface.OnClickListener() {
420 public void onClick(final DialogInterface dialog,
421 final int item) {
422 switch (item) {
423 case ITEM_DIALOG_EDIT:
424 AdBlock.this.itemToEdit = position;
425 ((EditText) AdBlock.this
426 .findViewById(R.id.filter_add))
427 .setText(AdBlock.this.adapter
428 .getItem(position));
429 break;
430 case ITEM_DIALOG_DELETE:
431 AdBlock.this.filter.remove(position);
432 AdBlock.this.adapter.notifyDataSetChanged();
433 break;
434 default:
435 break;
439 AlertDialog alert = builder.create();
440 alert.show();