Android Open Source - RSSFeedReader-App Modify Sources






From Project

Back to project page RSSFeedReader-App.

License

The source code is released under:

GNU General Public License

If you think the Android project RSSFeedReader-App listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package tan.chesley.rssfeedreader;
/* w  w  w.  j  av a  2s  .c o  m*/
import android.app.ActionBar;
import android.app.Activity;
import android.app.ListActivity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class ModifySources extends ListActivity implements ModifySourceDialogFragment.ModifySourceCallbacks, AddSourceDialogFragment.AddSourceCallbacks{

    private static final String TAG_SOURCES = "tan.chesley.rssfeedreader.sources";
    private static final String TAG_MODIFY_SOURCE_DIALOG_FRAGMENT = "tan.chesley.rssfeedreader.modifysourcedialogfragment";
    private static final String TAG_ADD_SOURCE_DIALOG_FRAGMENT = "tan.chesley.rssfeedreader.addsourcedialogfragment";
    private static final int TAG_IMPORT_FILE_RESULT_CODE = 467678; // "import" in phone number representation
    private static final int TAG_EXPORT_FILE_RESULT_CODE = 397678; // "export" in phone number representation
    private final Activity activity = this;
    private ArrayList<String> sources;
    private boolean isAutomaticChange;

    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        BrightnessControl.toggleBrightness(getApplicationContext(), this);
        getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_USE_LOGO | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_HOME_AS_UP);
        int titleId = getResources().getIdentifier("action_bar_title", "id",
                                                   "android");
        TextView title = (TextView) findViewById(titleId);
        if (title != null) {
            setTitle(getResources().getString(R.string.sources));
            title.setTextColor(getResources().getColor(
                (R.color.AppPrimaryTextColor)));
        }
        setContentView(R.layout.modify_sources);
        if (savedInstanceState != null) {
            sources = savedInstanceState.getStringArrayList(TAG_SOURCES);
        }
        else {
            SourcesOpenHelper sourceDbHelper = new SourcesOpenHelper(this);
            sources = sourceDbHelper.getSourcesArrayList();
        }
        showListView(false);
    }

    @Override
    protected void onListItemClick (ListView l, View v, final int position, long id) {
        ModifySourceDialogFragment dialog = new ModifySourceDialogFragment();
        Bundle args = new Bundle();
        args.putString(ModifySourceDialogFragment.TAG_SOURCE, sources.get(position));
        dialog.setArguments(args);
        dialog.show(getFragmentManager(), TAG_MODIFY_SOURCE_DIALOG_FRAGMENT);
    }

    @Override
    protected void onSaveInstanceState (Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putStringArrayList(TAG_SOURCES, sources);
    }

    private class SourcesAdapter extends ArrayAdapter<String> {
        public SourcesAdapter(ListActivity context) {
            super(context, R.layout.sources_list_item, sources);
        }

        @Override
        public View getView (int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = getLayoutInflater().inflate(
                    R.layout.sources_list_item, parent, false);
            }
            TextView sourceTextView = (TextView) convertView.findViewById(R.id.sourceTextView);
            TextView positionTextView = (TextView) convertView.findViewById(R.id.positionTextView);
            ToggleButton disabledToggleButton = (ToggleButton) convertView.findViewById(R.id.disabledToggleButton);
            disabledToggleButton.setOnCheckedChangeListener(new ToggleButtonOnCheckedChangeListener(sourceTextView));
            SourcesOpenHelper dbHelper = new SourcesOpenHelper(activity);
            String source = getItem(position);
            // Check if the source is disabled and change its appearance as appropriate
            if (!dbHelper.isEnabled(source)) {
                sourceTextView.setTextColor(getResources().getColor(R.color.DisabledTextColor));
                isAutomaticChange = true;
                disabledToggleButton.setChecked(false);
                isAutomaticChange = false;
            }
            else {
                sourceTextView.setTextColor(getResources().getColor(R.color.AppPrimaryTextColor));
                isAutomaticChange = true;
                disabledToggleButton.setChecked(true);
                isAutomaticChange = false;
            }
            sourceTextView.setText(source);
            positionTextView.setText(Integer.toString(position + 1)); // Add 1 for One-based indexing
            return convertView;
        }
    }

    public class ToggleButtonOnCheckedChangeListener implements CompoundButton.OnCheckedChangeListener {
        private TextView sourceTextView;
        public ToggleButtonOnCheckedChangeListener(TextView sourceTextView) {
            this.sourceTextView = sourceTextView;
        }
        @Override
        public void onCheckedChanged (CompoundButton compoundButton, boolean b) {
            if (b) {
                sourceTextView.setTextColor(getResources().getColor(R.color.AppPrimaryTextColor));
            }
            else {
                sourceTextView.setTextColor(getResources().getColor(R.color.DisabledTextColor));
            }
            if (!isAutomaticChange) {
                SourcesOpenHelper dbHelper = new SourcesOpenHelper(activity);
                dbHelper.setEnabled(sourceTextView.getText().toString(), b);
            }
        }
    }

    public void showListView(boolean updateSources) {
        if (updateSources) {
            SourcesOpenHelper dbHelper = new SourcesOpenHelper(this);
            sources = dbHelper.getSourcesArrayList();
        }
        getListView().setAdapter(new SourcesAdapter(this));
    }

    public void onModifySourceCallback() {
        showListView(true);
    }

    public void onAddSourceCallback() {
        showListView(true);
    }

    @Override
    public boolean onCreateOptionsMenu (Menu menu) {
        getMenuInflater().inflate(R.menu.modifysources, menu);
        return true;
    }

    @Override
    public boolean onMenuItemSelected (int featureId, MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_new) {
            AddSourceDialogFragment dialog = new AddSourceDialogFragment();
            dialog.show(getFragmentManager(), TAG_ADD_SOURCE_DIALOG_FRAGMENT);
            return true;
        }
        else if (id == R.id.action_import) {
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("file/*");
            PackageManager pm = getPackageManager();
            List<ResolveInfo> activities = pm.queryIntentActivities(intent, 0);
            if (activities.size() > 0) {
                startActivityForResult(intent, TAG_IMPORT_FILE_RESULT_CODE);
            } else {
                Toaster.showToast(this, getResources().getString(R.string.importFailedNoFileBrowser), Toast.LENGTH_LONG);
            }
            return true;
        }
        else if (id == R.id.action_export) {
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                File sdCard = Environment.getExternalStorageDirectory();
                File path = new File(sdCard.getAbsolutePath() + "/tan.chesley.rssfeedreader/feeds");
                path.mkdirs();
                File file = new File(path, "feeds-export.txt");
                try {
                    BufferedWriter writer = new BufferedWriter(new FileWriter(file));
                    String[] sources = new SourcesOpenHelper(this).getSources();
                    writer.write("tan.chesley.rssfeedreader.export\n");
                    for (String s : sources) {
                        writer.write(s + "\n");
                    }
                    writer.close();
                    Toaster.showToast(this, getResources().getString(R.string.successfulExportToFile) + file.getAbsolutePath(), Toast.LENGTH_LONG);
                } catch (IOException e) {
                    Toaster.showToast(this, getResources().getString(R.string.errorOccurredDuringWrite), Toast.LENGTH_LONG);
                    e.printStackTrace();
                }
            }
            else {
                Toaster.showToast(this, getResources().getString(R.string.noExternalStorageAccess), Toast.LENGTH_LONG);
            }
            return true;
        }
        return super.onMenuItemSelected(featureId, item);
    }

    @Override
    protected void onActivityResult (int requestCode, int resultCode, Intent data) {
        if (requestCode == TAG_IMPORT_FILE_RESULT_CODE) {
            if (resultCode == RESULT_OK) {
                Uri uri = data.getData();
                String filePath = uri.getPath();
                Log.e("Import", "File chosen: " + filePath);
                try {
                    BufferedReader reader;
                    if (uri.getScheme().equals("content")) {
                        InputStream inputStream = getContentResolver().openInputStream(uri);
                        reader = new BufferedReader(new InputStreamReader(inputStream));
                    }
                    else {
                        File file = new File(filePath);
                        reader = new BufferedReader(new FileReader(file));
                    }
                    String line = reader.readLine();
                    if (line != null && line.equals("tan.chesley.rssfeedreader.export")) {
                        SourcesOpenHelper dbHelper = new SourcesOpenHelper(this);
                        while ((line = reader.readLine()) != null) {
                            dbHelper.addSource(line, 1);
                        }
                        Toaster.showToast(this, getResources().getString(R.string.successfulImportFromFile) + filePath, Toast.LENGTH_LONG);
                        // Reload ListView items
                        showListView(true);
                    }
                    else {
                        Log.e("File format not recognized: ", line);
                        Toaster.showToast(this, getResources().getString(R.string.invalidFileFormat), Toast.LENGTH_LONG);
                    }
                    reader.close();
                    // TODO validate sources that are imported
                } catch (IOException e) {
                    Toaster.showToast(this, getResources().getString(R.string.errorOccurredDuringRead), Toast.LENGTH_LONG);
                    e.printStackTrace();
                }
            }
        }
    }

    public void validateAndAddSource(String s) {
        ValidationAsyncTask task = new ValidationAsyncTask();
        task.execute(s);
    }

    private class ValidationAsyncTask extends AsyncTask<String, Void, Void> {

        final long validationTimeout = 3000;
        final long startTime = System.currentTimeMillis();
        private String s = "";
        private boolean isValidFeed = true;

        @Override
        protected Void doInBackground (String... strings) {
            s = strings[0];
            SAXParserFactory mySAXParserFactory = SAXParserFactory
                .newInstance();
            SAXParser mySAXParser = null;
            XMLReader myXMLReader = null;
            try {
                mySAXParser = mySAXParserFactory.newSAXParser();
                myXMLReader = mySAXParser.getXMLReader();
            } catch (SAXException e) {
                e.printStackTrace();
                Log.e("Validation", "Could not connect to RSS feed! Error 1");
                isValidFeed = false;
                return null;
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
                Log.e("Validation", "Could not connect to RSS feed! Error 2.");
                isValidFeed = false;
                return null;
            }
            if (System.currentTimeMillis() - startTime > validationTimeout) {
                Log.e("Validation", "Validation timeout reached.");
                isValidFeed = false;
                return null;
            }
            DefaultHandler myRSSValidationHandler = new DefaultHandler();
            myXMLReader.setContentHandler(myRSSValidationHandler);
            InputSource myInputSource;
            InputStream feedStream;
            URL url = null;
            try {
                url = new URL(s);
            } catch (MalformedURLException e) {
                e.printStackTrace();
                Log.e("Validation", "Cannot connect to RSS feed! Error 3.");
                isValidFeed = false;
                return null;
            }
            if (System.currentTimeMillis() - startTime > validationTimeout) {
                Log.e("Validation", "Validation timeout reached.");
                isValidFeed = false;
                return null;
            }
            try {
                feedStream = url.openStream();
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("Validation", "Cannot connect to RSS feed! Error 4.");
                isValidFeed = false;
                return null;
            }
            if (System.currentTimeMillis() - startTime > validationTimeout) {
                Log.e("Validation", "Validation timeout reached.");
                isValidFeed = false;
                return null;
            }
            myInputSource = new InputSource(feedStream);
            try {
                myXMLReader.parse(myInputSource);
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("Validation", "Cannot connect to RSS feed! Error 5.");
                isValidFeed = false;
                return null;
            } catch (SAXException e) {
                e.printStackTrace();
                Log.e("Validation", "Cannot connect to RSS feed! Error 6.");
                isValidFeed = false;
                return null;
            }
            return null;
        }


        @Override
        protected void onPreExecute () {
            super.onPreExecute();
            Toaster.showToast(activity, getResources().getString(R.string.validatingNewSource), Toast.LENGTH_SHORT);
        }

        @Override
        protected void onPostExecute (Void aVoid) {
            super.onPostExecute(aVoid);
            if (isValidFeed) {
                SourcesOpenHelper dbHelper = new SourcesOpenHelper(getApplicationContext());
                dbHelper.addSource(s, SourcesOpenHelper.ENABLED);
                Toaster.showToast(activity, getResources().getString(R.string.validSource), Toast.LENGTH_SHORT);
                showListView(true);
            }
            else {
                Log.e("Validation", s + " is an invalid source.");
                Toaster.showToast(activity, getResources().getString(R.string.invalidSource), Toast.LENGTH_LONG);
            }
        }
    }
}




Java Source Code List

android.support.v4.app.FixedFragmentStatePagerAdapter.java
tan.chesley.rssfeedreader.AddSourceDialogFragment.java
tan.chesley.rssfeedreader.ArticleAgeLimitNumberPickerDialog.java
tan.chesley.rssfeedreader.ArticleViewFragment.java
tan.chesley.rssfeedreader.ArticleView.java
tan.chesley.rssfeedreader.AutosyncTimePickerDialog.java
tan.chesley.rssfeedreader.BrightnessControl.java
tan.chesley.rssfeedreader.DepthPageTransformer.java
tan.chesley.rssfeedreader.HeadlinesFragment.java
tan.chesley.rssfeedreader.MaxArticlesNumberPickerDialog.java
tan.chesley.rssfeedreader.MaxDatabaseSizeNumberPickerDialog.java
tan.chesley.rssfeedreader.ModifySourceDialogFragment.java
tan.chesley.rssfeedreader.ModifySources.java
tan.chesley.rssfeedreader.NumberPickerDialogPreference.java
tan.chesley.rssfeedreader.RSSDataBundleOpenHelper.java
tan.chesley.rssfeedreader.RSSDataBundle.java
tan.chesley.rssfeedreader.RSSFeed.java
tan.chesley.rssfeedreader.RSSHandler.java
tan.chesley.rssfeedreader.RssSyncService.java
tan.chesley.rssfeedreader.SettingsActivity.java
tan.chesley.rssfeedreader.SettingsFragment.java
tan.chesley.rssfeedreader.SourcesOpenHelper.java
tan.chesley.rssfeedreader.SyncTimeoutNumberPickerDialog.java
tan.chesley.rssfeedreader.TaskFragment.java
tan.chesley.rssfeedreader.TimePickerDialogPreference.java
tan.chesley.rssfeedreader.Toaster.java