com.mantz_it.rfanalyzer.SettingsFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.mantz_it.rfanalyzer.SettingsFragment.java

Source

package com.mantz_it.rfanalyzer;

import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.SwitchPreference;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.preference.PreferenceManager;
import android.widget.Toast;

import java.io.File;

import static com.mantz_it.rfanalyzer.SettingsActivity.PERMISSION_REQUEST_LOGGING_WRITE_FILES;

/**
 * <h1>RF Analyzer - Settings Fragment</h1>
 *
 * Module:      SettingsFragment.java
 * Description: This fragment shows all app settings
 *
 * @author Dennis Mantz
 *
 * Copyright (C) 2014 Dennis Mantz
 * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
 *
 * This library 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 2 of the License, or (at your option) any later version.
 *
 * This library 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 library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
public class SettingsFragment extends PreferenceFragment
        implements SharedPreferences.OnSharedPreferenceChangeListener, Preference.OnPreferenceClickListener {

    private static final int FILESOURCE_RESULT_CODE = 1;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);

        // Add click listener to preferences which use external apps:
        Preference pref = findPreference(getString(R.string.pref_filesource_file));
        pref.setOnPreferenceClickListener(this);
        pref = findPreference(getString(R.string.pref_showLog));
        pref.setOnPreferenceClickListener(this);

    }

    @Override
    public void onResume() {
        super.onResume();

        // Screen Orientation:
        String screenOrientation = getPreferenceScreen().getSharedPreferences()
                .getString(getString(R.string.pref_screenOrientation), "auto");
        setScreenOrientation(screenOrientation);

        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
        updateSummaries();
    }

    @Override
    public void onPause() {
        super.onPause();
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    }

    @Override
    public boolean onPreferenceClick(Preference preference) {
        // FileSource file:
        if (preference.getKey().equals(getString(R.string.pref_filesource_file))) {
            try {
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.setType("*/*");
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                startActivityForResult(Intent.createChooser(intent, "Select a file (8-bit complex IQ samples)"),
                        FILESOURCE_RESULT_CODE);

                // No error so far... let's dismiss the text input dialog:
                Dialog dialog = ((EditTextPreference) preference).getDialog();
                if (dialog != null)
                    dialog.dismiss();
                return true;
            } catch (ActivityNotFoundException e) {
                Toast.makeText(SettingsFragment.this.getActivity(), "No file browser is installed!",
                        Toast.LENGTH_LONG).show();
                // Note that there is still the text dialog visible for the user to input a file path... so no more error handling necessary
            }
            return false;
        }
        // Show Log:
        else if (preference.getKey().equals(getString(R.string.pref_showLog))) {
            try {
                String logfile = ((EditTextPreference) findPreference(getString(R.string.pref_logfile))).getText();
                Uri uri = Uri.fromFile(new File(logfile));
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(uri, "text/plain");
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                this.startActivity(intent);
                return true;
            } catch (ActivityNotFoundException e) {
                Toast.makeText(SettingsFragment.this.getActivity(), "No text viewer is installed!",
                        Toast.LENGTH_LONG).show();
            }
            return false;
        }
        return false;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (data != null) {
            switch (requestCode) {
            case FILESOURCE_RESULT_CODE:
                Uri uri = data.getData();
                if (uri != null) {
                    String filepath = FileUtils.getPath(getActivity(), uri);
                    if (filepath != null) {
                        ((EditTextPreference) findPreference(getString(R.string.pref_filesource_file)))
                                .setText(filepath);
                        updateFileSourcePrefs();
                    } else {
                        Toast.makeText(SettingsFragment.this.getActivity(),
                                "Can't resolve file path from: " + uri.toString(), Toast.LENGTH_LONG).show();
                    }
                }
                break;
            default:
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {

        // update the summeries:
        updateSummaries();

        // Screen Orientation:
        String screenOrientation = sharedPreferences.getString(getString(R.string.pref_screenOrientation), "auto");
        setScreenOrientation(screenOrientation);

        // check WRITE_EXTERNAL_STORAGE permission if logging is active:
        if (sharedPreferences.getBoolean(getString(R.string.pref_logging), false)) {
            if (ContextCompat.checkSelfPermission(this.getActivity(),
                    "android.permission.WRITE_EXTERNAL_STORAGE") != PackageManager.PERMISSION_GRANTED) {
                // request permission:
                ActivityCompat.requestPermissions(this.getActivity(),
                        new String[] { "android.permission.WRITE_EXTERNAL_STORAGE" },
                        PERMISSION_REQUEST_LOGGING_WRITE_FILES);
            }
        }
    }

    /**
     * Will go through each preference element and initialize/update the summary according to its value.
     * @note this will also correct invalid user inputs on EdittextPreferences!
     */
    public void updateSummaries() {
        // Source Type
        ListPreference listPref = (ListPreference) findPreference(getString(R.string.pref_sourceType));
        listPref.setSummary(getString(R.string.pref_sourceType_summ, listPref.getEntry()));

        // Direct Sampling
        listPref = (ListPreference) findPreference(getString(R.string.pref_rtlsdr_directSamp));
        listPref.setSummary(getString(R.string.pref_rtlsdr_directSamp_summ, listPref.getEntry()));

        // Frequency display
        listPref = (ListPreference) findPreference(getString(R.string.pref_surface_unit));
        listPref.setSummary(getString(R.string.pref_surface_unit_summ, listPref.getEntry()));

        // FileSource Frequency
        EditTextPreference editTextPref = (EditTextPreference) findPreference(
                getString(R.string.pref_filesource_frequency));
        if (editTextPref.getText().length() == 0)
            editTextPref.setText(getString(R.string.pref_filesource_frequency_default));
        editTextPref.setSummary(getString(R.string.pref_filesource_frequency_summ, editTextPref.getText()));

        // FileSource Sample Rate
        editTextPref = (EditTextPreference) findPreference(getString(R.string.pref_filesource_sampleRate));
        if (editTextPref.getText().length() == 0)
            editTextPref.setText(getString(R.string.pref_filesource_sampleRate_default));
        editTextPref.setSummary(getString(R.string.pref_filesource_sampleRate_summ, editTextPref.getText()));

        // FileSource File
        editTextPref = (EditTextPreference) findPreference(getString(R.string.pref_filesource_file));
        editTextPref.setSummary(getString(R.string.pref_filesource_file_summ, editTextPref.getText()));

        // FileSource Format
        listPref = (ListPreference) findPreference(getString(R.string.pref_filesource_format));
        listPref.setSummary(getString(R.string.pref_filesource_format_summ, listPref.getEntry()));

        // HackRF frequency shift
        editTextPref = (EditTextPreference) findPreference(getString(R.string.pref_hackrf_frequencyOffset));
        if (editTextPref.getText().length() == 0)
            editTextPref.setText("0");
        editTextPref.setSummary(getString(R.string.pref_hackrf_frequencyOffset_summ, editTextPref.getText()));

        // RTL-SDR IP
        editTextPref = (EditTextPreference) findPreference(getString(R.string.pref_rtlsdr_ip));
        editTextPref.setSummary(getString(R.string.pref_rtlsdr_ip_summ, editTextPref.getText()));

        // RTL-SDR Port
        editTextPref = (EditTextPreference) findPreference(getString(R.string.pref_rtlsdr_port));
        editTextPref.setSummary(getString(R.string.pref_rtlsdr_port_summ, editTextPref.getText()));

        // RTL-SDR frequency correction
        editTextPref = (EditTextPreference) findPreference(getString(R.string.pref_rtlsdr_frequencyCorrection));
        if (editTextPref.getText().length() == 0)
            editTextPref.setText(getString(R.string.pref_rtlsdr_frequencyCorrection_default));
        editTextPref.setSummary(getString(R.string.pref_rtlsdr_frequencyCorrection_summ, editTextPref.getText()));

        // RTL-SDR frequency shift
        editTextPref = (EditTextPreference) findPreference(getString(R.string.pref_rtlsdr_frequencyOffset));
        if (editTextPref.getText().length() == 0)
            editTextPref.setText("0");
        editTextPref.setSummary(getString(R.string.pref_rtlsdr_frequencyOffset_summ, editTextPref.getText()));

        // FFT size
        listPref = (ListPreference) findPreference(getString(R.string.pref_fftSize));
        listPref.setSummary(getString(R.string.pref_fftSize_summ, listPref.getEntry()));

        // Color map type
        listPref = (ListPreference) findPreference(getString(R.string.pref_colorMapType));
        listPref.setSummary(getString(R.string.pref_colorMapType_summ, listPref.getEntry()));

        // FFT drawing type
        listPref = (ListPreference) findPreference(getString(R.string.pref_fftDrawingType));
        listPref.setSummary(getString(R.string.pref_fftDrawingType_summ, listPref.getEntry()));

        // Averaging
        listPref = (ListPreference) findPreference(getString(R.string.pref_averaging));
        listPref.setSummary(getString(R.string.pref_averaging_summ, listPref.getEntry()));

        // Screen Orientation
        listPref = (ListPreference) findPreference(getString(R.string.pref_screenOrientation));
        listPref.setSummary(getString(R.string.pref_screenOrientation_summ, listPref.getEntry()));

        // Spectrum Waterfall Ratio
        listPref = (ListPreference) findPreference(getString(R.string.pref_spectrumWaterfallRatio));
        listPref.setSummary(getString(R.string.pref_spectrumWaterfallRatio_summ, listPref.getEntry()));

        // Font Size
        listPref = (ListPreference) findPreference(getString(R.string.pref_fontSize));
        listPref.setSummary(getString(R.string.pref_fontSize_summ, listPref.getEntry()));

        // Frame Rate
        SwitchPreference switchPref = (SwitchPreference) findPreference(getString(R.string.pref_dynamicFrameRate));
        listPref = (ListPreference) findPreference(getString(R.string.pref_frameRate));
        if (switchPref.isChecked())
            listPref.setSummary(getString(R.string.pref_frameRate_summ, "auto"));
        else
            listPref.setSummary(getString(R.string.pref_frameRate_summ, listPref.getEntry()));

        // Logfile
        editTextPref = (EditTextPreference) findPreference(getString(R.string.pref_logfile));
        editTextPref.setSummary(getString(R.string.pref_logfile_summ, editTextPref.getText()));

        // Shared preferences updated in e.g. the onRequestPermissionResult() method are
        // not automatically updated in the preference fragment gui. do it manually:
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
        switchPref = (SwitchPreference) findPreference(getString(R.string.pref_logging));
        switchPref.setChecked(preferences.getBoolean(getString(R.string.pref_logging), false));
    }

    /**
     * Will set the screen orientation of the hosting activity
     *
     * @param orientation      auto, landscape, portrait, reverse_landscape or reverse_portrait
     */
    public void setScreenOrientation(String orientation) {
        if (orientation.equals("auto"))
            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        else if (orientation.equals("landscape"))
            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        else if (orientation.equals("portrait"))
            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        else if (orientation.equals("reverse_landscape"))
            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        else if (orientation.equals("reverse_portrait"))
            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
    }

    /**
     * Extract the path from an uri
     * This code was published on StackOverflow by dextor
     *
     * @param contentUri      uri that contains the file path
     * @return absolute file path as string
     */
    private String getRealPathFromURI(Uri contentUri) {
        String[] proj = { MediaStore.Images.Media.DATA };
        CursorLoader loader = new CursorLoader(this.getActivity(), contentUri, proj, null, null, null);
        Cursor cursor = loader.loadInBackground();
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }

    /**
     * Will try to extract the file source preferences (frequency, sample rate, format) from the filename
     */
    public void updateFileSourcePrefs() {
        EditTextPreference etp_filename = (EditTextPreference) findPreference(
                getString(R.string.pref_filesource_file));
        EditTextPreference etp_frequency = (EditTextPreference) findPreference(
                getString(R.string.pref_filesource_frequency));
        EditTextPreference etp_sampleRate = (EditTextPreference) findPreference(
                getString(R.string.pref_filesource_sampleRate));
        ListPreference lp_format = (ListPreference) findPreference(getString(R.string.pref_filesource_format));
        String filename = etp_filename.getText();

        // Format. Search for strings like hackrf, rtl-sdr, ...
        if (filename.matches(".*hackrf.*") || filename.matches(".*HackRF.*") || filename.matches(".*HACKRF.*")
                || filename.matches(".*hackrfone.*"))
            lp_format.setValue("0");
        if (filename.matches(".*rtlsdr.*") || filename.matches(".*rtl-sdr.*") || filename.matches(".*RTLSDR.*")
                || filename.matches(".*RTL-SDR.*"))
            lp_format.setValue("1");

        // Sampe Rate. Search for pattern XXXXXXXSps
        if (filename.matches(".*(_|-|\\s)([0-9]+)(sps|Sps|SPS).*"))
            etp_sampleRate.setText(filename.replaceFirst(".*(_|-|\\s)([0-9]+)(sps|Sps|SPS).*", "$2"));
        if (filename.matches(".*(_|-|\\s)([0-9]+)(msps|Msps|MSps|MSPS).*"))
            etp_sampleRate.setText(
                    "" + Integer.valueOf(filename.replaceFirst(".*(_|-|\\s)([0-9]+)(msps|Msps|MSps|MSPS).*", "$2"))
                            * 1000000);

        // Frequency. Search for pattern XXXXXXXHz
        if (filename.matches(".*(_|-|\\s)([0-9]+)(hz|Hz|HZ).*"))
            etp_frequency.setText(filename.replaceFirst(".*(_|-|\\s)([0-9]+)(hz|Hz|HZ).*", "$2"));
        if (filename.matches(".*(_|-|\\s)([0-9]+)(mhz|Mhz|MHz|MHZ).*"))
            etp_frequency.setText(
                    "" + Integer.valueOf(filename.replaceFirst(".*(_|-|\\s)([0-9]+)(mhz|Mhz|MHz|MHZ).*", "$2"))
                            * 1000000);
    }
}