From 4fc6238f3243eb0f46ea4a84a1f9a907577fd92e Mon Sep 17 00:00:00 2001 From: pulce Date: Sat, 11 Apr 2015 14:55:25 +0200 Subject: [PATCH] V2.0.0 --- AndroidManifest.xml | 18 +- ChangeLog | 10 +- res/layout-w700dp/dialog_ref_del.xml | 60 +++ res/layout/activity_file_preference.xml | 2 +- res/layout/activity_main_list.xml | 16 + res/layout/activity_main_twopane.xml | 35 ++ res/layout/activity_station.xml | 14 + res/layout/activity_station_pic.xml | 23 -- res/layout/activity_station_text.xml | 28 -- .../{activity_main.xml => frag_main.xml} | 0 res/layout/frag_station.xml | 25 ++ res/menu/station_menu.xml | 12 + res/values-de/strings.xml | 3 +- res/values-w700dp/refs.xml | 12 + res/values-w820dp/dimens.xml | 10 - res/values/strings.xml | 3 +- res/xml/pref_general.xml | 2 +- src/com/windnow/MainActivity.java | 370 ++++++++---------- src/com/windnow/MainFragment.java | 104 +++++ src/com/windnow/Station.java | 7 + src/com/windnow/StationActivity.java | 126 ++++++ src/com/windnow/StationFragment.java | 247 ++++++++++++ src/com/windnow/StationListAdapter.java | 4 +- src/com/windnow/StationPicActivity.java | 164 -------- src/com/windnow/StationTextActivity.java | 97 ----- .../windnow/{ => classes}/AboutDialog.java | 4 +- src/com/windnow/classes/CheckForUpdates.java | 89 +++++ src/com/windnow/classes/DownloadStation.java | 108 +++++ .../windnow/classes/InterfaceDlUpdate.java | 27 ++ .../FilePreferenceActivity.java | 7 +- .../FilePreferenceAdapter.java | 4 +- .../FilePreferenceAdapterOption.java | 2 +- .../{ => preferences}/SettingsActivity.java | 9 +- .../windnow/{ => statics}/LoadSaveOps.java | 16 +- .../windnow/{ => statics}/OnlyContext.java | 2 +- 35 files changed, 1112 insertions(+), 548 deletions(-) create mode 100755 res/layout-w700dp/dialog_ref_del.xml create mode 100755 res/layout/activity_main_list.xml create mode 100644 res/layout/activity_main_twopane.xml create mode 100755 res/layout/activity_station.xml delete mode 100755 res/layout/activity_station_pic.xml delete mode 100755 res/layout/activity_station_text.xml rename res/layout/{activity_main.xml => frag_main.xml} (100%) create mode 100755 res/layout/frag_station.xml create mode 100755 res/menu/station_menu.xml create mode 100755 res/values-w700dp/refs.xml delete mode 100755 res/values-w820dp/dimens.xml create mode 100644 src/com/windnow/MainFragment.java create mode 100644 src/com/windnow/StationActivity.java create mode 100755 src/com/windnow/StationFragment.java delete mode 100755 src/com/windnow/StationPicActivity.java delete mode 100755 src/com/windnow/StationTextActivity.java rename src/com/windnow/{ => classes}/AboutDialog.java (97%) create mode 100644 src/com/windnow/classes/CheckForUpdates.java create mode 100644 src/com/windnow/classes/DownloadStation.java create mode 100644 src/com/windnow/classes/InterfaceDlUpdate.java rename src/com/windnow/{ => preferences}/FilePreferenceActivity.java (97%) rename src/com/windnow/{ => preferences}/FilePreferenceAdapter.java (96%) rename src/com/windnow/{ => preferences}/FilePreferenceAdapterOption.java (96%) rename src/com/windnow/{ => preferences}/SettingsActivity.java (95%) rename src/com/windnow/{ => statics}/LoadSaveOps.java (93%) rename src/com/windnow/{ => statics}/OnlyContext.java (98%) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 19b3193..8f76c0e 100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="8" + android:versionName="2.0.0" > @@ -41,23 +41,23 @@ diff --git a/ChangeLog b/ChangeLog index f382096..69c5fa3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -28,4 +28,12 @@ V1.2.0------------------ V1.2.1------------------ Bugfixing: -Stations appear several times. \ No newline at end of file +Stations appear several times. + +V2.0.0------------------ +- User Interface: swype stations +- User Interface: two-column-layout on wide screens +- Cache management: old (unused) pic files get deleted +- Windsock of a station is now colored if and only if download is younger than 1 day +- Refresh visible station with menu button +- Code cleanup \ No newline at end of file diff --git a/res/layout-w700dp/dialog_ref_del.xml b/res/layout-w700dp/dialog_ref_del.xml new file mode 100755 index 0000000..28d3a3c --- /dev/null +++ b/res/layout-w700dp/dialog_ref_del.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/activity_file_preference.xml b/res/layout/activity_file_preference.xml index ba84b0d..879c648 100755 --- a/res/layout/activity_file_preference.xml +++ b/res/layout/activity_file_preference.xml @@ -2,7 +2,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".FilePreferenceActivity" > + tools:context="com.windnow.preferences.FilePreferenceActivity" > + + + + + + diff --git a/res/layout/activity_main_twopane.xml b/res/layout/activity_main_twopane.xml new file mode 100644 index 0000000..4f4796e --- /dev/null +++ b/res/layout/activity_main_twopane.xml @@ -0,0 +1,35 @@ + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/activity_station.xml b/res/layout/activity_station.xml new file mode 100755 index 0000000..240d1a4 --- /dev/null +++ b/res/layout/activity_station.xml @@ -0,0 +1,14 @@ + + + \ No newline at end of file diff --git a/res/layout/activity_station_pic.xml b/res/layout/activity_station_pic.xml deleted file mode 100755 index f04a6fd..0000000 --- a/res/layout/activity_station_pic.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/res/layout/activity_station_text.xml b/res/layout/activity_station_text.xml deleted file mode 100755 index 61e44f6..0000000 --- a/res/layout/activity_station_text.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/res/layout/activity_main.xml b/res/layout/frag_main.xml similarity index 100% rename from res/layout/activity_main.xml rename to res/layout/frag_main.xml diff --git a/res/layout/frag_station.xml b/res/layout/frag_station.xml new file mode 100755 index 0000000..f14ef95 --- /dev/null +++ b/res/layout/frag_station.xml @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file diff --git a/res/menu/station_menu.xml b/res/menu/station_menu.xml new file mode 100755 index 0000000..a4aa7a5 --- /dev/null +++ b/res/menu/station_menu.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 944d1d9..fabd1d0 100755 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -14,7 +14,7 @@ Station Einstellungen Contact: pulce@gmx.at \n - Copyright 2014 \n + Copyright 2015 \n by Florian Hauser Dependencies:\n jsoup - http://jsoup.org/ \n @@ -53,6 +53,7 @@ Es gibt drei Möglichkeiten um neue Stationen anzulegen:\n Diese Station wirklich löschen? Station neu laden Station löschen + Station maximieren Nicht geladen "Geladen: " Hilfe diff --git a/res/values-w700dp/refs.xml b/res/values-w700dp/refs.xml new file mode 100755 index 0000000..0615aa4 --- /dev/null +++ b/res/values-w700dp/refs.xml @@ -0,0 +1,12 @@ + + + + @layout/activity_main_twopane + + diff --git a/res/values-w820dp/dimens.xml b/res/values-w820dp/dimens.xml deleted file mode 100755 index f3e7020..0000000 --- a/res/values-w820dp/dimens.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - 64dp - - diff --git a/res/values/strings.xml b/res/values/strings.xml index 2805c9e..f748967 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -14,7 +14,7 @@ Station Settings Contact: pulce@gmx.at \n - Copyright 2014 \n + Copyright 2015 \n by Florian Hauser Dependencies:\n jsoup - http://jsoup.org/ \n @@ -52,6 +52,7 @@ There are three ways to create new stations:\n Really delete this station? Refresh Station Delete Station + Open station full-screen Not loaded "Downloaded: " Help diff --git a/res/xml/pref_general.xml b/res/xml/pref_general.xml index 5876720..8e99619 100755 --- a/res/xml/pref_general.xml +++ b/res/xml/pref_general.xml @@ -6,7 +6,7 @@ android:title="@string/menu_sel_stationsfile" > diff --git a/src/com/windnow/MainActivity.java b/src/com/windnow/MainActivity.java index f71acc5..ec5a311 100755 --- a/src/com/windnow/MainActivity.java +++ b/src/com/windnow/MainActivity.java @@ -1,34 +1,32 @@ package com.windnow; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URL; -import java.net.URLConnection; import java.util.ArrayList; -import java.util.Calendar; -import android.support.v7.app.ActionBarActivity; + +import com.windnow.classes.AboutDialog; +import com.windnow.classes.CheckForUpdates; +import com.windnow.classes.DownloadStation; +import com.windnow.classes.InterfaceDlUpdate; +import com.windnow.preferences.SettingsActivity; +import com.windnow.statics.LoadSaveOps; + +import android.support.v4.app.FragmentActivity; import android.annotation.SuppressLint; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; -import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; -import android.preference.PreferenceManager; +import android.os.Parcelable; +import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; -import android.widget.ListView; import android.widget.Spinner; import android.widget.Toast; @@ -55,95 +53,115 @@ */ @SuppressLint({ "InflateParams", "NewApi" }) -public class MainActivity extends ActionBarActivity { +public class MainActivity extends FragmentActivity implements + InterfaceDlUpdate, MainFragment.Callbacks { - private static final String VERSIONID = "1.2.1"; - private static final String APPURL = "https://github.com/pulce/WindNow/releases/latest"; + public static final String VERSIONID = "2.0.0"; + public static final String APPURL = "https://github.com/pulce/WindNow/releases/latest"; - private StationListAdapter stAda; private String sharedUrl = null; - public static int maxRetries; private static int stationToEdit; public static final int DIALOG_NEW_STAT = -1; public static final int DIALOG_EDIT_STAT = -2; public static final int DIALOG_SHARE_STAT = -3; public static final int ACT_PREF = 1; - static final ArrayList objects = new ArrayList(); + public static final int ACT_STATION = 2; + public static final ArrayList objects = new ArrayList(); + + private static final String LIST_STATE = "listState"; + + private boolean mTwoPane; + private Station activeStation; + private Parcelable savedListState = null; @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - maxRetries = Integer.parseInt(PreferenceManager - .getDefaultSharedPreferences(OnlyContext.getContext()) - .getString("pref_list", "5")); - if (objects.size() == 0) { - try { - objects.addAll(LoadSaveOps.loadStations()); - } catch (Exception e) { - LoadSaveOps.printErrorToLog(e); - Toast.makeText(this, - getString(R.string.error_loading_stations_file), - Toast.LENGTH_SHORT).show(); - } - } - final ListView listview = (ListView) findViewById(R.id.listview); - stAda = new StationListAdapter(this, R.layout.main_list_item, objects); - listview.setAdapter(stAda); - listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, final View view, - int position, long id) { - if (objects.get(position).isvalued()) { - Intent sText = objects.get(position).getType() == Station.PIC ? new Intent( - getApplicationContext(), StationPicActivity.class) - : new Intent(getApplicationContext(), - StationTextActivity.class); - sText.putExtra("txt", objects.get(position).getUrl()); - sText.putExtra( - "name", - objects.get(position).getName() - + "\n" - + getString(R.string.downloaded_at) - + Station.sdf.format(objects.get(position) - .getDate())); - sText.putStringArrayListExtra("tabTxt", - objects.get(position).getTabTxt()); - startActivity(sText); - } - } - }); + setContentView(R.layout.activity_main_list); - listview.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { - @Override - public boolean onItemLongClick(AdapterView parent, View view, - int position, long id) { - showDialog(position); - return true; - } - - }); + if (findViewById(R.id.station_container) != null) { + mTwoPane = true; + } Intent intent = getIntent(); String action = intent.getAction(); String type = intent.getType(); - if (Intent.ACTION_SEND.equals(action) && type != null) { sharedUrl = intent.getStringExtra(Intent.EXTRA_TEXT); showDialog(DIALOG_SHARE_STAT); } } + /** + * Method needed to restore scroll position + */ + @Override + protected void onRestoreInstanceState(Bundle state) { + super.onRestoreInstanceState(state); + savedListState = state.getParcelable(LIST_STATE); + } + + /** + * Method needed to restore scroll position + */ + @Override + protected void onResume() { + super.onResume(); + if (savedListState != null) { + ((MainFragment) getSupportFragmentManager().findFragmentById( + R.id.main_list)).getListView().onRestoreInstanceState( + savedListState); + } + savedListState = null; + } + + /** + * Method needed to restore scroll position + */ + @Override + protected void onSaveInstanceState(Bundle state) { + super.onSaveInstanceState(state); + savedListState = ((MainFragment) getSupportFragmentManager() + .findFragmentById(R.id.main_list)).getListView() + .onSaveInstanceState(); + state.putParcelable(LIST_STATE, savedListState); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } + private void refreshView() { + MainFragment fragment = (MainFragment) getSupportFragmentManager() + .findFragmentById(R.id.main_list); + if (fragment != null && fragment.isInLayout()) { + fragment.refreshAdapter(); + } + } + + private void refreshDetail(Station st) { + StationFragment stfragment = (StationFragment) getSupportFragmentManager() + .findFragmentById(R.id.station_container); + if (stfragment != null && st == activeStation && mTwoPane) { + Bundle bundle = new Bundle(); + bundle.putInt("position", objects.indexOf(st)); + Log.d("Replacing....", activeStation.getName()); + StationFragment frag = new StationFragment(); + frag.setArguments(bundle); + getSupportFragmentManager().beginTransaction() + .replace(R.id.station_container, frag).commit(); + } + + } + protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == ACT_PREF) { - stAda.notifyDataSetChanged(); + refreshView(); + } else if (requestCode == ACT_STATION) { + } } @@ -166,12 +184,12 @@ public boolean onOptionsItemSelected(MenuItem item) { showDialog(DIALOG_NEW_STAT); break; case R.id.action_refresh: - for (Station st : objects) { + for (Station st : getObjects()) { initiateDl(st); } break; case R.id.action_update: - new CheckForUpdates().execute(VERSIONID); + new CheckForUpdates(this).execute(VERSIONID); break; default: break; @@ -185,127 +203,25 @@ private void initiateDl(Station st) { } st.setLoaded(false); st.setStatus(Station.DOWNLOADING); - stAda.notifyDataSetChanged(); + refreshView(); + // stAda.notifyDataSetChanged(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - new DownloadStation(st) + new DownloadStation(this, st) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else { - new DownloadStation(st).execute(); + new DownloadStation(this, st).execute(); } } - /** - * - * AsyncTask to download the content... - * - */ - private class DownloadStation extends AsyncTask { - private Station station; - - private DownloadStation(Station station) { - this.station = station; - } - - @Override - protected Void doInBackground(Void... v) { - for (int dlTry = 1; dlTry <= maxRetries; dlTry++) { - try { - station.setProgress(0); - String filename = "pic" + station.getUrl().hashCode(); - int IO_BUFFER_SIZE = 4 * 1024; - URLConnection uc = new URL(station.getUrl()) - .openConnection(); - int contentLength = uc.getContentLength(); - InputStream input = new BufferedInputStream( - uc.getInputStream(), IO_BUFFER_SIZE); - OutputStream out = new BufferedOutputStream(OnlyContext - .getContext().openFileOutput(filename, - OnlyContext.MODE_PRIVATE), IO_BUFFER_SIZE); - byte[] b = new byte[IO_BUFFER_SIZE]; - int read; - long total = 0; - while ((read = input.read(b)) != -1) { - total += read; - if (contentLength > 0) { - station.setProgress((int) ((total * 100) / contentLength)); - publishProgress(); - } - out.write(b, 0, read); - } - input.close(); - out.close(); - - station.setLoaded(true); - station.setValued(true); - station.setStatus(Station.LOADED); - station.setDate(Calendar.getInstance().getTime()); - - if (station.getType() != Station.PIC) { - station.parseCache(); - } - break; - } catch (IOException e) { - if (dlTry == maxRetries) { - station.setStatus(Station.DOWNLOAD_ERROR); - } - LoadSaveOps.printErrorToLog(e); - e.printStackTrace(); - } - } - return null; - } - - protected void onProgressUpdate(Void... p) { - stAda.notifyDataSetChanged(); - } - - @Override - protected void onPostExecute(Void v) { - stAda.notifyDataSetChanged(); - } + @Override + public void onTaskUpdate(Station st) { + refreshView(); } - private class CheckForUpdates extends AsyncTask { - private String answer = getString(R.string.check_for_updates_failed); - - @Override - protected Boolean doInBackground(String... org) { - String tag; - try { - URLConnection con = new URL(APPURL).openConnection(); - con.connect(); - InputStream is = con.getInputStream(); - String gt = con.getURL().toString(); - if (gt == null) { - return false; - } - String[] spl = gt.split("/"); - tag = spl[spl.length - 1]; - is.close(); - } catch (IOException e) { - return false; - } - if (tag.equals(VERSIONID)) { - answer = getString(R.string.already_latest_version) + " " - + VERSIONID + "."; - return false; - } - answer = "Version " + tag + " " - + getString(R.string.new_version_available) + " " - + VERSIONID + "."; - return true; - } - - @Override - protected void onPostExecute(Boolean newVersion) { - Toast.makeText(getApplicationContext(), answer, Toast.LENGTH_LONG) - .show(); - if (newVersion) { - Intent browse = new Intent(Intent.ACTION_VIEW, - Uri.parse(APPURL)); - startActivity(browse); - } - } + @Override + public void onTaskResult(Station st) { + refreshView(); + refreshDetail(st); } @Override @@ -339,7 +255,7 @@ protected void onPrepareDialog(final int id, Dialog dialog) { final AlertDialog alertDialog = (AlertDialog) dialog; final boolean edit = id == DIALOG_EDIT_STAT; final boolean share = id == DIALOG_SHARE_STAT; - int position = objects.size(); + int position = getObjects().size(); switch (id) { case DIALOG_SHARE_STAT: case DIALOG_EDIT_STAT: @@ -349,8 +265,8 @@ protected void onPrepareDialog(final int id, Dialog dialog) { final EditText stationUrl = (EditText) alertDialog .findViewById(R.id.newStationUrl); if (edit) { - stationName.setText(objects.get(stationToEdit).getName()); - stationUrl.setText(objects.get(stationToEdit).getUrl()); + stationName.setText(getObjects().get(stationToEdit).getName()); + stationUrl.setText(getObjects().get(stationToEdit).getUrl()); position = stationToEdit; } if (share) { @@ -360,7 +276,8 @@ protected void onPrepareDialog(final int id, Dialog dialog) { final Spinner dropdown = (Spinner) alertDialog .findViewById(R.id.spinner1); ArrayList items = new ArrayList(); - for (int i = 1; i <= (edit ? objects.size() : objects.size() + 1); i++) { + for (int i = 1; i <= (edit ? getObjects().size() : getObjects() + .size() + 1); i++) { items.add(i); } ArrayAdapter adapter = new ArrayAdapter(this, @@ -374,18 +291,19 @@ protected void onPrepareDialog(final int id, Dialog dialog) { public void onClick(View v) { Station newStation; if (edit) { - newStation = objects.get(stationToEdit); + newStation = getObjects().get(stationToEdit); newStation.setName(stationName.getText().toString()); newStation.setUrl(stationUrl.getText().toString()); - objects.remove(newStation); + getObjects().remove(newStation); } else { newStation = new Station(stationName.getText() .toString(), stationUrl.getText().toString()); } - objects.add((Integer) dropdown.getSelectedItem() - 1, + getObjects().add((Integer) dropdown.getSelectedItem() - 1, newStation); - stAda.notifyDataSetChanged(); - LoadSaveOps.saveStations(objects); + refreshView(); + // stAda.notifyDataSetChanged(); + LoadSaveOps.saveStations(getObjects()); alertDialog.dismiss(); } }); @@ -403,11 +321,12 @@ public void onClick(View v) { Button refButton = (Button) alertDialog.findViewById(R.id.refresh); Button editButton = (Button) alertDialog.findViewById(R.id.edit_st); Button delButton = (Button) alertDialog.findViewById(R.id.delete); + Button fullButton = (Button) alertDialog.findViewById(R.id.fullscreen); refButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { alertDialog.dismiss(); - initiateDl(objects.get(id)); + initiateDl(getObjects().get(id)); } }); editButton.setOnClickListener(new View.OnClickListener() { @@ -427,9 +346,9 @@ public void onClick(View v) { public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_POSITIVE: - objects.remove(id); - LoadSaveOps.saveStations(objects); - stAda.notifyDataSetChanged(); + getObjects().remove(id); + LoadSaveOps.saveStations(getObjects()); + refreshView(); break; case DialogInterface.BUTTON_NEGATIVE: break; @@ -446,7 +365,62 @@ public void onClick(DialogInterface dialog, int which) { alertDialog.dismiss(); } }); + if (fullButton != null) { + fullButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + alertDialog.dismiss(); + Bundle bundle = new Bundle(); + bundle.putInt("position", id); + Intent sText = new Intent(getApplicationContext(), + StationActivity.class); + sText.putExtras(bundle); + startActivity(sText); + } + }); + } break; } } + + @Override + public void onItemSelected(Station st) { + if (st.isvalued()) { + activeStation = st; + Bundle bundle = new Bundle(); + bundle.putInt("position", getObjects().indexOf(st)); + if (mTwoPane) { + StationFragment fragment = new StationFragment(); + fragment.setArguments(bundle); + getSupportFragmentManager().beginTransaction() + .replace(R.id.station_container, fragment).commit(); + } else { + Intent sText = new Intent(getApplicationContext(), + StationActivity.class); + sText.putExtras(bundle); + startActivityForResult(sText, 0); + } + } + } + + @SuppressWarnings("deprecation") + @Override + public void OnItemLongClicked(int position) { + showDialog(position); + } + + @Override + public ArrayList getObjects() { + if (objects.size() == 0) { + try { + objects.addAll(LoadSaveOps.loadStations()); + } catch (Exception e) { + LoadSaveOps.printErrorToLog(e); + Toast.makeText(this, + getString(R.string.error_loading_stations_file), + Toast.LENGTH_SHORT).show(); + } + } + return objects; + } } diff --git a/src/com/windnow/MainFragment.java b/src/com/windnow/MainFragment.java new file mode 100644 index 0000000..24f4079 --- /dev/null +++ b/src/com/windnow/MainFragment.java @@ -0,0 +1,104 @@ +package com.windnow; + +import java.util.ArrayList; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemLongClickListener; +import android.widget.ListView; + +/** + * + * This Class is part of WindNow. + * + * + * @author Florian Hauser Copyright (C) 2015 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +public class MainFragment extends ListFragment { + + private Callbacks mCallbacks = sDummyCallbacks; + private StationListAdapter stAda; + ArrayList objects; + + public interface Callbacks { + public void onItemSelected(Station st); + public void OnItemLongClicked(int position); + public ArrayList getObjects(); + } + + private static Callbacks sDummyCallbacks = new Callbacks() { + @Override + public void onItemSelected(Station st) {} + public void OnItemLongClicked(int position) {} + public ArrayList getObjects() {return null;} + }; + + public MainFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.objects = mCallbacks.getObjects(); + stAda = new StationListAdapter(getActivity(), R.layout.main_list_item, objects); + this.setListAdapter(stAda); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getListView().setOnItemLongClickListener(new OnItemLongClickListener() { + + @Override + public boolean onItemLongClick(AdapterView arg0, View arg1, + int position, long arg3) { + mCallbacks.OnItemLongClicked(position); + return true; + } + }); + + } + + public void refreshAdapter() { + stAda.notifyDataSetChanged(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (!(activity instanceof Callbacks)) { + throw new IllegalStateException( + "Activity must implement fragment's callbacks."); + } + mCallbacks = (Callbacks) activity; + } + + @Override + public void onDetach() { + super.onDetach(); + mCallbacks = sDummyCallbacks; + } + + @Override + public void onListItemClick(ListView listView, View view, int position, + long id) { + super.onListItemClick(listView, view, position, id); + mCallbacks.onItemSelected(objects.get(position)); + } +} diff --git a/src/com/windnow/Station.java b/src/com/windnow/Station.java index c7b0420..670a080 100755 --- a/src/com/windnow/Station.java +++ b/src/com/windnow/Station.java @@ -13,6 +13,9 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; +import com.windnow.statics.LoadSaveOps; +import com.windnow.statics.OnlyContext; + /** * * This Class is part of WindNow. @@ -80,9 +83,13 @@ else if (url.contains("wetterdienst.de") && url.contains("Aktuell")) { // Check loaded String filename = "pic" + this.url.hashCode(); File file = OnlyContext.getContext().getFileStreamPath(filename); + long now = System.currentTimeMillis(); if (file != null && file.exists()) { this.date = new Date(file.lastModified()); this.status = LOADED; + if (now - file.lastModified() < 1000L*60*60*24) { + this.loaded = true; + } if (this.type != PIC) { parseCache(); } diff --git a/src/com/windnow/StationActivity.java b/src/com/windnow/StationActivity.java new file mode 100644 index 0000000..0fae9dc --- /dev/null +++ b/src/com/windnow/StationActivity.java @@ -0,0 +1,126 @@ +package com.windnow; + +import com.windnow.classes.DownloadStation; +import com.windnow.classes.InterfaceDlUpdate; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.Menu; +import android.view.MenuItem; + +/** + * + * This Class is part of WindNow. + * + * @author Florian Hauser Copyright (C) 2015 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +public class StationActivity extends FragmentActivity implements + InterfaceDlUpdate { + + private ViewPager mPager; + private PagerAdapter mPagerAdapter; + + @SuppressLint("NewApi") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_station); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + getActionBar().setDisplayHomeAsUpEnabled(true); + } + mPager = (ViewPager) findViewById(R.id.station_container); + mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); + mPager.setAdapter(mPagerAdapter); + mPager.setCurrentItem(getIntent().getExtras().getInt("position")); + mPagerAdapter.notifyDataSetChanged(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.station_menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + //Intent intent = new Intent(this, MainActivity.class); + //intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // Resume saved + Intent returnIntent = new Intent(); + returnIntent.putExtra("selected", mPager.getCurrentItem()); + setResult(RESULT_OK,returnIntent); + finish(); + break; + //NavUtils.navigateUpTo(this, intent); + //return true; + case R.id.action_hot_refresh: + Station st = MainActivity.objects.get(mPager.getCurrentItem()); + if (st.getStatus() == Station.DOWNLOADING) { + break; + } + st.setLoaded(false); + st.setStatus(Station.DOWNLOADING); + new DownloadStation(this, st).execute(); + + } + return super.onOptionsItemSelected(item); + } + + private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { + public ScreenSlidePagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + Bundle bundle = new Bundle(); + if (position >= MainActivity.objects.size()) + position = 0; + bundle.putInt("position", position); + StationFragment fragment = new StationFragment(); + fragment.setArguments(bundle); + return fragment; + + } + + @Override + public int getCount() { + return MainActivity.objects.size(); + } + } + + @Override + public void onTaskUpdate(Station st) { + // TODO Left blank for the moment - maybe something fancy one day? + } + + @Override + public void onTaskResult(Station st) { + mPager.setAdapter(mPagerAdapter); + mPager.setCurrentItem(MainActivity.objects.indexOf(st)); + mPagerAdapter.notifyDataSetChanged(); + } +} \ No newline at end of file diff --git a/src/com/windnow/StationFragment.java b/src/com/windnow/StationFragment.java new file mode 100755 index 0000000..cb4f364 --- /dev/null +++ b/src/com/windnow/StationFragment.java @@ -0,0 +1,247 @@ +package com.windnow; + +import java.io.FileInputStream; + +import com.windnow.statics.LoadSaveOps; + +import android.annotation.SuppressLint; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.graphics.PointF; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.FloatMath; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.TableLayout; +import android.widget.TableRow; +import android.widget.TextView; +import android.widget.ImageView.ScaleType; +import android.widget.TableLayout.LayoutParams; + +/** + * + * This Class is part of WindNow. + * + * + * @author Florian Hauser Copyright (C) 2015 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +public class StationFragment extends Fragment { + + public static final String ARG_ITEM_ID = "item_id"; + private View rootView; + private TableLayout tl; + private Matrix matrix = new Matrix(); + private Matrix savedMatrix = new Matrix(); + private PointF startPoint = new PointF(); + private PointF midPoint = new PointF(); + private float oldDist = 1f; + static final int NONE = 0; + static final int DRAG = 1; + static final int ZOOM = 2; + int mode = NONE; + + private Station st; + + public StationFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments().containsKey("position")) { + st = MainActivity.objects.get(getArguments().getInt("position")); + } + } + + @SuppressLint("RtlHardcoded") + private void printTableRow(String line) { + String[] words = line.split("&/"); + TableRow tr = new TableRow(getActivity()); + TableRow.LayoutParams params = new TableRow.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + params.gravity = Gravity.FILL_HORIZONTAL; + tr.setLayoutParams(params); + + TableRow.LayoutParams tvParams = new TableRow.LayoutParams( + TableRow.LayoutParams.WRAP_CONTENT, + TableRow.LayoutParams.WRAP_CONTENT); + tvParams.setMargins(0, 0, 6, 0); + + for (int i = words.length - 1; i >= 0; i--) { + TextView txv = new TextView(getActivity()); + txv.setLayoutParams(tvParams); + txv.setText(words[i]); + txv.setGravity(i == 0 ? Gravity.LEFT : Gravity.LEFT); + tr.addView(txv, 0); + } + tl.addView(tr); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + rootView = inflater + .inflate(R.layout.frag_station, container, false); + LinearLayout la = (LinearLayout) rootView + .findViewById(R.id.stationTextLayout); + + TextView tv = (TextView) rootView.findViewById(R.id.textView1); + tv.setText(st.getName()); + + if (st.getType() == Station.PIC && st.isvalued()) { + final ImageView imageDetail = new ImageView(getActivity()); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT); + imageDetail.setLayoutParams(layoutParams); + la.addView(imageDetail); + imageDetail.setScaleType(ScaleType.MATRIX); + String filename = "pic" + st.getUrl().hashCode(); + Bitmap pic = null; + try { + FileInputStream is = getActivity().openFileInput(filename); + pic = BitmapFactory.decodeStream(is); + is.close(); + imageDetail.setImageBitmap(pic); + } catch (Exception e) { + LoadSaveOps.printErrorToLog(e); + } + /* Could scale Pic Fullscreen on start. Buggy! + * final int startx = pic.getWidth(); final int starty = + * pic.getHeight(); + * + * ViewTreeObserver vto = tv.getViewTreeObserver(); + * vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { + * + * @Override public void onGlobalLayout() { //LayerDrawable ld = + * (LayerDrawable)imageDetail.getBackground(); //ld.setLayerInset(1, + * 0, imageDetail.getHeight() / 2, 0, 0); Log.d("Heeeeeeereeeeeee", + * "" + startx + " " + imageDetail.getWidth()); + * savedMatrix.set(matrix); float scalex = + * imageDetail.getWidth()/startx; float scaley = + * imageDetail.getHeight()/starty; //matrix.postScale(startx, + * starty, imageDetail.getWidth(), // imageDetail.getHeight()); + * matrix.postScale(Math.min(scalex, scaley),Math.min(scalex, + * scaley)); imageDetail.setImageMatrix(matrix); + * + * ViewTreeObserver obs = imageDetail.getViewTreeObserver(); + * + * if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + * obs.removeOnGlobalLayoutListener(this); } else { + * obs.removeGlobalOnLayoutListener(this); } } + * + * }); + */ + + imageDetail.setOnTouchListener(new View.OnTouchListener() { + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouch(View v, MotionEvent event) { + + ImageView view = (ImageView) v; + switch (event.getAction() & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + + savedMatrix.set(matrix); + startPoint.set(event.getX(), event.getY()); + mode = DRAG; + break; + + case MotionEvent.ACTION_POINTER_DOWN: + + oldDist = spacing(event); + + if (oldDist > 10f) { + savedMatrix.set(matrix); + midPoint(midPoint, event); + mode = ZOOM; + } + break; + + case MotionEvent.ACTION_UP: + + case MotionEvent.ACTION_POINTER_UP: + mode = NONE; + break; + + case MotionEvent.ACTION_MOVE: + if (mode == DRAG) { + matrix.set(savedMatrix); + matrix.postTranslate(event.getX() - startPoint.x, + event.getY() - startPoint.y); + } else if (mode == ZOOM) { + float newDist = spacing(event); + if (newDist > 10f) { + matrix.set(savedMatrix); + float scale = newDist / oldDist; + matrix.postScale(scale, scale, midPoint.x, + midPoint.y); + matrix.postTranslate(event.getX() + - startPoint.x, event.getY() + - startPoint.y); // new + } + } + break; + + } + view.setImageMatrix(matrix); + + return true; + } + + @SuppressLint("FloatMath") + private float spacing(MotionEvent event) { + float x = event.getX(0) - event.getX(1); + float y = event.getY(0) - event.getY(1); + return FloatMath.sqrt(x * x + y * y); + } + + private void midPoint(PointF point, MotionEvent event) { + float x = event.getX(0) + event.getX(1); + float y = event.getY(0) + event.getY(1); + point.set(x / 2, y / 2); + } + }); + + } else if (st.isvalued()){ + + ScrollView sv = new ScrollView(getActivity()); + la.addView(sv); + tl = new TableLayout(getActivity()); + sv.addView(tl); + + for (String row : st.getTabTxt()) { + printTableRow(row); + } + } + + return rootView; + } + + public void refresh() { + // Dummy + } + +} diff --git a/src/com/windnow/StationListAdapter.java b/src/com/windnow/StationListAdapter.java index a39c197..cac159c 100755 --- a/src/com/windnow/StationListAdapter.java +++ b/src/com/windnow/StationListAdapter.java @@ -2,6 +2,8 @@ import java.util.List; +import com.windnow.statics.OnlyContext; + import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -57,7 +59,7 @@ public StationListAdapter(Context context, int textViewResourceId, public Station getItem(int i) { return objects.get(i); } - + @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; diff --git a/src/com/windnow/StationPicActivity.java b/src/com/windnow/StationPicActivity.java deleted file mode 100755 index eddccec..0000000 --- a/src/com/windnow/StationPicActivity.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.windnow; - -import java.io.FileInputStream; - -import android.support.v4.app.NavUtils; -import android.support.v7.app.ActionBarActivity; -import android.os.Build; -import android.os.Bundle; -import android.view.MenuItem; -import android.annotation.SuppressLint; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Matrix; -import android.graphics.PointF; -import android.util.FloatMath; -import android.view.MotionEvent; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -/** - * - * This Class is part of WindNow. - * - * It is the activity representing pure picture stations. - * - * @author Florian Hauser Copyright (C) 2014 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -public class StationPicActivity extends ActionBarActivity { - - private ImageView imageDetail; - private Matrix matrix = new Matrix(); - private Matrix savedMatrix = new Matrix(); - private PointF startPoint = new PointF(); - private PointF midPoint = new PointF(); - private float oldDist = 1f; - static final int NONE = 0; - static final int DRAG = 1; - static final int ZOOM = 2; - int mode = NONE; - - @SuppressLint("NewApi") - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_station_pic); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { - getActionBar().setDisplayHomeAsUpEnabled(true); - } - TextView tv = (TextView) findViewById(R.id.textViewPicName); - tv.setText(getIntent().getExtras().getString("name")); - imageDetail = (ImageView) findViewById(R.id.imageView1); - String filename = "pic" - + getIntent().getExtras().getString("txt").hashCode(); - Bitmap pic = null; - try { - FileInputStream is = this.openFileInput(filename); - pic = BitmapFactory.decodeStream(is); - is.close(); - imageDetail.setImageBitmap(pic); - } catch (Exception e) { - LoadSaveOps.printErrorToLog(e); - } - - imageDetail.setOnTouchListener(new View.OnTouchListener() { - @SuppressLint("ClickableViewAccessibility") - @Override - public boolean onTouch(View v, MotionEvent event) { - - ImageView view = (ImageView) v; - switch (event.getAction() & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - - savedMatrix.set(matrix); - startPoint.set(event.getX(), event.getY()); - mode = DRAG; - break; - - case MotionEvent.ACTION_POINTER_DOWN: - - oldDist = spacing(event); - - if (oldDist > 10f) { - savedMatrix.set(matrix); - midPoint(midPoint, event); - mode = ZOOM; - } - break; - - case MotionEvent.ACTION_UP: - - case MotionEvent.ACTION_POINTER_UP: - mode = NONE; - - break; - - case MotionEvent.ACTION_MOVE: - if (mode == DRAG) { - matrix.set(savedMatrix); - matrix.postTranslate(event.getX() - startPoint.x, - event.getY() - startPoint.y); - } else if (mode == ZOOM) { - float newDist = spacing(event); - if (newDist > 10f) { - matrix.set(savedMatrix); - float scale = newDist / oldDist; - matrix.postScale(scale, scale, midPoint.x, - midPoint.y); - matrix.postTranslate(event.getX() - startPoint.x, - event.getY() - startPoint.y); // new - } - } - break; - - } - view.setImageMatrix(matrix); - - return true; - } - - @SuppressLint("FloatMath") - private float spacing(MotionEvent event) { - float x = event.getX(0) - event.getX(1); - float y = event.getY(0) - event.getY(1); - return FloatMath.sqrt(x * x + y * y); - } - - private void midPoint(PointF point, MotionEvent event) { - float x = event.getX(0) + event.getX(1); - float y = event.getY(0) + event.getY(1); - point.set(x / 2, y / 2); - } - }); - - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - Intent intent = new Intent(this, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // Resume saved - // State! - NavUtils.navigateUpTo(this, intent); - return true; - } - return super.onOptionsItemSelected(item); - } -} diff --git a/src/com/windnow/StationTextActivity.java b/src/com/windnow/StationTextActivity.java deleted file mode 100755 index ea55a61..0000000 --- a/src/com/windnow/StationTextActivity.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.windnow; - -import java.util.ArrayList; - -import android.support.v4.app.NavUtils; -import android.support.v7.app.ActionBarActivity; -import android.annotation.SuppressLint; -import android.content.Intent; -import android.os.Build; -import android.os.Bundle; -import android.view.Gravity; -import android.view.MenuItem; -import android.widget.TableLayout; -import android.widget.TableRow; -import android.widget.TextView; -import android.widget.TableLayout.LayoutParams; - -/** - * - * This Class is part of WindNow. - * - * It is the activity representing wetteronline text stations. - * - * @author Florian Hauser Copyright (C) 2014 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -public class StationTextActivity extends ActionBarActivity { - - @SuppressLint("NewApi") - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_station_text); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { - getActionBar().setDisplayHomeAsUpEnabled(true); - } - TextView tv = (TextView) findViewById(R.id.textView1); - tv.setText(getIntent().getExtras().getString("name")); - ArrayList tabTxt = getIntent().getStringArrayListExtra("tabTxt"); - for (String row:tabTxt) { - printTableRow(row); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - Intent intent = new Intent(this, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // Resume saved - // State! - NavUtils.navigateUpTo(this, intent); - return true; - } - return super.onOptionsItemSelected(item); - } - - @SuppressLint("RtlHardcoded") - private void printTableRow(String line) { - TableLayout tl = (TableLayout) findViewById(R.id.tableLayout); - - String[] words = line.split("&/"); - TableRow tr = new TableRow(this); - TableRow.LayoutParams params = new TableRow.LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - params.gravity = Gravity.FILL_HORIZONTAL; - tr.setLayoutParams(params); - - TableRow.LayoutParams tvParams = new TableRow.LayoutParams( - TableRow.LayoutParams.WRAP_CONTENT, - TableRow.LayoutParams.WRAP_CONTENT); - tvParams.setMargins(0, 0, 6, 0); - - for (int i = words.length-1; i >= 0; i--) { - TextView txv = new TextView(this); - txv.setLayoutParams(tvParams); - txv.setText(words[i]); - txv.setGravity(i == 0 ? Gravity.LEFT : Gravity.LEFT); - tr.addView(txv, 0); - } - tl.addView(tr); - } -} diff --git a/src/com/windnow/AboutDialog.java b/src/com/windnow/classes/AboutDialog.java similarity index 97% rename from src/com/windnow/AboutDialog.java rename to src/com/windnow/classes/AboutDialog.java index 23742fb..a9d52c1 100755 --- a/src/com/windnow/AboutDialog.java +++ b/src/com/windnow/classes/AboutDialog.java @@ -1,4 +1,6 @@ -package com.windnow; +package com.windnow.classes; + +import com.windnow.R; import android.app.Dialog; import android.content.Context; diff --git a/src/com/windnow/classes/CheckForUpdates.java b/src/com/windnow/classes/CheckForUpdates.java new file mode 100644 index 0000000..d816ff8 --- /dev/null +++ b/src/com/windnow/classes/CheckForUpdates.java @@ -0,0 +1,89 @@ +package com.windnow.classes; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.AsyncTask; +import android.widget.Toast; + +import com.windnow.MainActivity; +import com.windnow.R; + +/** + * + * This Class is part of WindNow. + * + * @author Florian Hauser Copyright (C) 2015 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +public class CheckForUpdates extends AsyncTask { + private String answer; + private Context context; + + public CheckForUpdates(Context context) { + this.context = context; + this.answer = context.getString( + R.string.check_for_updates_failed); + } + + @Override + protected Boolean doInBackground(String... org) { + String tag; + try { + URLConnection con = new URL(MainActivity.APPURL).openConnection(); + con.connect(); + InputStream is = con.getInputStream(); + String gt = con.getURL().toString(); + if (gt == null) { + return false; + } + String[] spl = gt.split("/"); + tag = spl[spl.length - 1]; + is.close(); + } catch (IOException e) { + return false; + } + if (tag.equals(MainActivity.VERSIONID)) { + answer = context.getString( + R.string.already_latest_version) + + " " + MainActivity.VERSIONID + "."; + return false; + } + answer = "Version " + + tag + + " " + + context.getString( + R.string.new_version_available) + " " + + MainActivity.VERSIONID + "."; + return true; + } + + @Override + protected void onPostExecute(Boolean newVersion) { + Toast.makeText(context.getApplicationContext(), answer, Toast.LENGTH_LONG) + .show(); + if (newVersion) { + Intent browse = new Intent(Intent.ACTION_VIEW, + Uri.parse(MainActivity.APPURL)); + context.startActivity(browse); + } + } + +} \ No newline at end of file diff --git a/src/com/windnow/classes/DownloadStation.java b/src/com/windnow/classes/DownloadStation.java new file mode 100644 index 0000000..408f155 --- /dev/null +++ b/src/com/windnow/classes/DownloadStation.java @@ -0,0 +1,108 @@ +package com.windnow.classes; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.Calendar; + +import android.os.AsyncTask; +import android.preference.PreferenceManager; + +import com.windnow.Station; +import com.windnow.statics.LoadSaveOps; +import com.windnow.statics.OnlyContext; + +/** + * + * This Class is part of WindNow. + * + * @author Florian Hauser Copyright (C) 2015 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +public class DownloadStation extends AsyncTask { + private Station station; + private int maxRetries; + private InterfaceDlUpdate update; + + public DownloadStation(InterfaceDlUpdate update, Station station) { + this.station = station; + this.maxRetries = Integer.parseInt(PreferenceManager + .getDefaultSharedPreferences(OnlyContext.getContext()) + .getString("pref_list", "5")); + this.update = update; + } + + @Override + protected Void doInBackground(Void... v) { + for (int dlTry = 1; dlTry <= maxRetries; dlTry++) { + try { + station.setProgress(0); + String filename = "pic" + station.getUrl().hashCode(); + int IO_BUFFER_SIZE = 4 * 1024; + URLConnection uc = new URL(station.getUrl()) + .openConnection(); + int contentLength = uc.getContentLength(); + InputStream input = new BufferedInputStream( + uc.getInputStream(), IO_BUFFER_SIZE); + OutputStream out = new BufferedOutputStream(OnlyContext + .getContext().openFileOutput(filename, + OnlyContext.MODE_PRIVATE), IO_BUFFER_SIZE); + byte[] b = new byte[IO_BUFFER_SIZE]; + int read; + long total = 0; + while ((read = input.read(b)) != -1) { + total += read; + if (contentLength > 0) { + station.setProgress((int) ((total * 100) / contentLength)); + publishProgress(); + } + out.write(b, 0, read); + } + input.close(); + out.close(); + + station.setLoaded(true); + station.setValued(true); + station.setStatus(Station.LOADED); + station.setDate(Calendar.getInstance().getTime()); + + if (station.getType() != Station.PIC) { + station.parseCache(); + } + break; + } catch (IOException e) { + if (dlTry == maxRetries) { + station.setStatus(Station.DOWNLOAD_ERROR); + } + LoadSaveOps.printErrorToLog(e); + e.printStackTrace(); + } + } + return null; + } + + protected void onProgressUpdate(Void... p) { + update.onTaskUpdate(station); + } + + @Override + protected void onPostExecute(Void v) { + update.onTaskResult(station); + } +} diff --git a/src/com/windnow/classes/InterfaceDlUpdate.java b/src/com/windnow/classes/InterfaceDlUpdate.java new file mode 100644 index 0000000..187aa54 --- /dev/null +++ b/src/com/windnow/classes/InterfaceDlUpdate.java @@ -0,0 +1,27 @@ +package com.windnow.classes; + +import com.windnow.Station; + +/** + * + * This Class is part of WindNow. + * + * @author Florian Hauser Copyright (C) 2015 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +public interface InterfaceDlUpdate { + void onTaskUpdate(Station st); + void onTaskResult(Station st); +} diff --git a/src/com/windnow/FilePreferenceActivity.java b/src/com/windnow/preferences/FilePreferenceActivity.java similarity index 97% rename from src/com/windnow/FilePreferenceActivity.java rename to src/com/windnow/preferences/FilePreferenceActivity.java index 037687e..ae2ea9b 100755 --- a/src/com/windnow/FilePreferenceActivity.java +++ b/src/com/windnow/preferences/FilePreferenceActivity.java @@ -1,4 +1,4 @@ -package com.windnow; +package com.windnow.preferences; import java.io.File; import java.util.ArrayList; @@ -6,6 +6,11 @@ import java.util.List; import java.util.Stack; +import com.windnow.MainActivity; +import com.windnow.R; +import com.windnow.Station; +import com.windnow.statics.LoadSaveOps; + import android.os.Build; import android.os.Bundle; import android.os.Environment; diff --git a/src/com/windnow/FilePreferenceAdapter.java b/src/com/windnow/preferences/FilePreferenceAdapter.java similarity index 96% rename from src/com/windnow/FilePreferenceAdapter.java rename to src/com/windnow/preferences/FilePreferenceAdapter.java index e82df63..5c780f2 100755 --- a/src/com/windnow/FilePreferenceAdapter.java +++ b/src/com/windnow/preferences/FilePreferenceAdapter.java @@ -1,7 +1,9 @@ -package com.windnow; +package com.windnow.preferences; import java.util.List; +import com.windnow.R; + import android.content.Context; import android.view.LayoutInflater; import android.view.View; diff --git a/src/com/windnow/FilePreferenceAdapterOption.java b/src/com/windnow/preferences/FilePreferenceAdapterOption.java similarity index 96% rename from src/com/windnow/FilePreferenceAdapterOption.java rename to src/com/windnow/preferences/FilePreferenceAdapterOption.java index 7df69b0..d18273b 100755 --- a/src/com/windnow/FilePreferenceAdapterOption.java +++ b/src/com/windnow/preferences/FilePreferenceAdapterOption.java @@ -1,4 +1,4 @@ -package com.windnow; +package com.windnow.preferences; import java.util.Locale; diff --git a/src/com/windnow/SettingsActivity.java b/src/com/windnow/preferences/SettingsActivity.java similarity index 95% rename from src/com/windnow/SettingsActivity.java rename to src/com/windnow/preferences/SettingsActivity.java index f2bfec8..f4f0ac2 100755 --- a/src/com/windnow/SettingsActivity.java +++ b/src/com/windnow/preferences/SettingsActivity.java @@ -1,4 +1,7 @@ -package com.windnow; +package com.windnow.preferences; + +import com.windnow.MainActivity; +import com.windnow.R; import android.annotation.SuppressLint; import android.annotation.TargetApi; @@ -97,12 +100,8 @@ protected void onPause() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - SharedPreferences prefs = PreferenceManager - .getDefaultSharedPreferences(this); Preference p = findPreference(key); if (p.getKey().equals("pref_list") && p instanceof ListPreference) { - MainActivity.maxRetries = Integer.parseInt(prefs.getString( - "pref_list", "5")); ListPreference listPref = (ListPreference) p; p.setSummary(getString(R.string.maximum_number_summary) + " " + listPref.getValue()); diff --git a/src/com/windnow/LoadSaveOps.java b/src/com/windnow/statics/LoadSaveOps.java similarity index 93% rename from src/com/windnow/LoadSaveOps.java rename to src/com/windnow/statics/LoadSaveOps.java index e2fee47..9fc663c 100755 --- a/src/com/windnow/LoadSaveOps.java +++ b/src/com/windnow/statics/LoadSaveOps.java @@ -1,4 +1,4 @@ -package com.windnow; +package com.windnow.statics; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -13,6 +13,8 @@ import java.util.Arrays; import java.util.Date; +import com.windnow.Station; + import android.annotation.SuppressLint; import android.content.SharedPreferences; import android.content.res.AssetManager; @@ -68,8 +70,16 @@ static File getErrorFile() { } public static ArrayList loadStations() throws Exception { - ArrayList stations = new ArrayList(); mkLocalDir(); + //Manage Cache + File[] files = OnlyContext.getContext().getFilesDir().listFiles(); + long now = System.currentTimeMillis(); + for (File fl:files) { + if (now - fl.lastModified() > 1000L*60*60*24*90) { + fl.delete(); + } + } + ArrayList stations = new ArrayList(); BufferedReader br = null; boolean saveFile = !getStationsFile().exists(); if (saveFile) { @@ -111,7 +121,7 @@ public static void saveStations(ArrayList stations) { } } - static void printErrorToLog(Exception e) { + public static void printErrorToLog(Exception e) { try { mkLocalDir(); boolean append = false; diff --git a/src/com/windnow/OnlyContext.java b/src/com/windnow/statics/OnlyContext.java similarity index 98% rename from src/com/windnow/OnlyContext.java rename to src/com/windnow/statics/OnlyContext.java index f9977e8..948bdba 100755 --- a/src/com/windnow/OnlyContext.java +++ b/src/com/windnow/statics/OnlyContext.java @@ -1,4 +1,4 @@ -package com.windnow; +package com.windnow.statics; import android.app.Application; import android.content.Context;