Java tutorial
/* * Copyright 20132016 Michael von Glasow. * * This file is part of LSRN Tools. * * LSRN Tools 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. * * LSRN Tools 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 LSRN Tools. If not, see <http://www.gnu.org/licenses/>. */ package com.vonglasow.michael.satstat.ui; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.mapsforge.map.android.util.AndroidUtil; import org.mapsforge.map.layer.cache.TileCache; import com.vonglasow.michael.satstat.Const; import com.vonglasow.michael.satstat.PasvLocListenerService; import com.vonglasow.michael.satstat.R; import android.Manifest; import android.location.LocationManager; import android.net.Uri; import android.os.Bundle; import android.preference.ListPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.ActionBar; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.widget.EditText; import android.widget.ImageButton; import android.widget.Toast; import android.annotation.SuppressLint; import android.app.NotificationManager; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.pm.PackageManager; public class SettingsActivity extends AppCompatActivity implements OnPreferenceClickListener, OnSharedPreferenceChangeListener { public static final String TAG = SettingsActivity.class.getSimpleName(); public static final int REQUEST_CODE_PICK_MAP_PATH = 1; /** * A string array that specifies the name of the intent to use, and the scheme to use with it * when setting the data for the intent. * * @author k9mail, mvglasow */ private static final String[][] PICK_DIRECTORY_INTENTS = { { Intent.ACTION_PICK, "folder://" }, // CM File Manager, Blackmoon File Browser, possibly others { "org.openintents.action.PICK_DIRECTORY", "file://" }, // OI File Manager, possibly others { "com.estrongs.action.PICK_DIRECTORY", "file://" }, // ES File Explorer { "com.androidworkz.action.PICK_DIRECTORY", "file://" } }; private SharedPreferences mSharedPreferences; Preference prefMapPath; String prefMapPathValue = Const.MAP_PATH_DEFAULT; Preference prefMapDownload; Preference prefMapPurge; @SuppressLint("NewApi") @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_PICK_MAP_PATH) { if (resultCode == RESULT_OK) { setMapPath(data.getData().getPath()); } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); // Show the Up button in the action bar. ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); // Display the fragment as the main content. getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit(); mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); // some logic to use the pre-1.7 setting KEY_PREF_UPDATE_WIFI as a // fallback if KEY_PREF_UPDATE_NETWORKS is not set if (!mSharedPreferences.contains(Const.KEY_PREF_UPDATE_NETWORKS)) { Set<String> fallbackUpdateNetworks = new HashSet<String>(); if (mSharedPreferences.getBoolean(Const.KEY_PREF_UPDATE_WIFI, false)) { fallbackUpdateNetworks.add(Const.KEY_PREF_UPDATE_NETWORKS_WIFI); } SharedPreferences.Editor spEditor = mSharedPreferences.edit(); spEditor.putStringSet(Const.KEY_PREF_UPDATE_NETWORKS, fallbackUpdateNetworks); spEditor.commit(); } // by default, show GPS and network location in map if (!mSharedPreferences.contains(Const.KEY_PREF_LOC_PROV)) { Set<String> defaultLocProvs = new HashSet<String>( Arrays.asList(new String[] { LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER })); SharedPreferences.Editor spEditor = mSharedPreferences.edit(); spEditor.putStringSet(Const.KEY_PREF_LOC_PROV, defaultLocProvs); spEditor.commit(); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: onBackPressed(); return true; } return super.onOptionsItemSelected(item); } /** * @author k9mail, mvglasow */ @Override public boolean onPreferenceClick(Preference preference) { if (preference == prefMapPath) { boolean success = false; int i = 0; do { String intentAction = PICK_DIRECTORY_INTENTS[i][0]; String uriPrefix = PICK_DIRECTORY_INTENTS[i][1]; Intent intent = new Intent(intentAction); if (uriPrefix != null) intent.setData(Uri.parse(uriPrefix + prefMapPathValue)); try { startActivityForResult(intent, REQUEST_CODE_PICK_MAP_PATH); Log.i("SettingsActivity", String.format("Sending intent: %s", intentAction)); success = true; } catch (ActivityNotFoundException e) { // Try the next intent in the list i++; } } while (!success && (i < PICK_DIRECTORY_INTENTS.length)); if (!success) { //No app for folder browsing is installed, show a fallback dialog AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(getString(R.string.pref_map_path)); LayoutInflater inflater = LayoutInflater.from(this); final View alertView = inflater.inflate(R.layout.alert_map_path, null); final EditText editPath = (EditText) alertView.findViewById(R.id.editPath); editPath.setText(prefMapPathValue); final ImageButton btnOiFilemanager = (ImageButton) alertView.findViewById(R.id.btn_oi_filemanager); btnOiFilemanager.setTag(Uri.parse("market://details?id=org.openintents.filemanager")); final ImageButton btnCmFilemanager = (ImageButton) alertView.findViewById(R.id.btn_cm_filemanager); btnCmFilemanager.setTag(Uri.parse("market://details?id=com.cyanogenmod.filemanager.ics")); final View.OnClickListener clickListener = new View.OnClickListener() { @Override public void onClick(View v) { if (v.getTag() instanceof Uri) startActivity(new Intent(Intent.ACTION_VIEW, (Uri) v.getTag())); } }; builder.setView(alertView); btnOiFilemanager.setOnClickListener(clickListener); btnCmFilemanager.setOnClickListener(clickListener); builder.setPositiveButton(getString(R.string.action_ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { setMapPath(editPath.getText().toString()); } }); builder.setNegativeButton(getString(R.string.action_cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { // NOP } }); builder.show(); success = true; } return success; } else if (preference == prefMapDownload) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) startActivity(new Intent(this, MapDownloadActivity.class)); else ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, Const.PERM_REQUEST_MAP_DOWNLOAD); return true; } else if (preference == prefMapPurge) { TileCache mapRendererTileCache = AndroidUtil.createExternalStorageTileCache(this, Const.TILE_CACHE_INTERNAL_RENDER_THEME, 0, 256, true); TileCache mapDownloadTileCache = AndroidUtil.createExternalStorageTileCache(this, Const.TILE_CACHE_OSM, 0, 256, true); mapRendererTileCache.purge(); mapDownloadTileCache.purge(); mapRendererTileCache.destroy(); mapDownloadTileCache.destroy(); /* * This is a hack to have the map view (if it is active) redraw the map: * Setting the preference to true causes the listener in MainView to fire. * The listener will, in turn, determine if a map view is active and, if so, * cause it to reload all tile layers, then reset the preference to false. */ SharedPreferences.Editor spEditor = mSharedPreferences.edit(); spEditor.putBoolean(Const.KEY_PREF_MAP_PURGE, true); spEditor.commit(); String message = getString(R.string.status_map_purged); Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); return true; } else return false; } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { if ((requestCode == Const.PERM_REQUEST_MAP_DOWNLOAD) && (grantResults.length > 0)) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) startActivity(new Intent(this, MapDownloadActivity.class)); else { String message = getString(R.string.status_perm_map_download); Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); } } else if ((requestCode == Const.PERM_REQUEST_LOCATION_PREF) && (grantResults.length > 0)) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { NotificationManager notificationManager = (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE); notificationManager.cancel(Const.PERM_REQUEST_LOCATION_NOTIFICATION); } else Log.i(TAG, "ACCESS_FINE_LOCATION permission not granted, a notification will appear when it is needed"); } } @Override protected void onResume() { super.onResume(); mSharedPreferences.registerOnSharedPreferenceChangeListener(this); SettingsFragment sf = (SettingsFragment) getFragmentManager().findFragmentById(android.R.id.content); Preference prefUpdateLast = sf.findPreference(Const.KEY_PREF_UPDATE_LAST); final long value = mSharedPreferences.getLong(Const.KEY_PREF_UPDATE_LAST, 0); prefUpdateLast.setSummary(String.format(getString(R.string.pref_lastupdate_summary), value)); } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { boolean needsLocationPerm = false; if (key.equals(Const.KEY_PREF_NOTIFY_FIX) || key.equals(Const.KEY_PREF_NOTIFY_SEARCH)) { boolean notifyFix = sharedPreferences.getBoolean(Const.KEY_PREF_NOTIFY_FIX, false); boolean notifySearch = sharedPreferences.getBoolean(Const.KEY_PREF_NOTIFY_SEARCH, false); if (!(notifyFix || notifySearch)) { Intent stopServiceIntent = new Intent(this, PasvLocListenerService.class); this.stopService(stopServiceIntent); } else if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { needsLocationPerm = true; } } else if (key.equals(Const.KEY_PREF_UPDATE_FREQ)) { // this piece of code is necessary because Android has no way // of updating the preference summary automatically. I am // told the absence of such functionality is a feature... SettingsFragment sf = (SettingsFragment) getFragmentManager().findFragmentById(android.R.id.content); ListPreference prefUpdateFreq = (ListPreference) sf.findPreference(Const.KEY_PREF_UPDATE_FREQ); final String value = sharedPreferences.getString(key, key); final int index = prefUpdateFreq.findIndexOfValue(value); if (index >= 0) { final String summary = (String) prefUpdateFreq.getEntries()[index]; prefUpdateFreq.setSummary(summary); } } else if (key.equals(Const.KEY_PREF_MAP_PATH)) { SettingsFragment sf = (SettingsFragment) getFragmentManager().findFragmentById(android.R.id.content); Preference prefMapPath = sf.findPreference(Const.KEY_PREF_MAP_PATH); prefMapPathValue = mSharedPreferences.getString(Const.KEY_PREF_MAP_PATH, prefMapPathValue); prefMapPath.setSummary(prefMapPathValue); } else if (key.equals(Const.KEY_PREF_UPDATE_NETWORKS)) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { Set<String> updateNetworks = sharedPreferences.getStringSet(Const.KEY_PREF_UPDATE_NETWORKS, new HashSet<String>()); if (!updateNetworks.isEmpty()) needsLocationPerm = true; } } if (needsLocationPerm) ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, Const.PERM_REQUEST_LOCATION_PREF); } @Override protected void onStart() { super.onStart(); SettingsFragment sf = (SettingsFragment) getFragmentManager().findFragmentById(android.R.id.content); prefMapPath = sf.findPreference(Const.KEY_PREF_MAP_PATH); prefMapPathValue = mSharedPreferences.getString(Const.KEY_PREF_MAP_PATH, prefMapPathValue); prefMapPath.setSummary(prefMapPathValue); prefMapPath.setOnPreferenceClickListener(this); prefMapDownload = sf.findPreference(Const.KEY_PREF_MAP_DOWNLOAD); prefMapDownload.setOnPreferenceClickListener(this); prefMapPurge = sf.findPreference(Const.KEY_PREF_MAP_PURGE); prefMapPurge.setOnPreferenceClickListener(this); } @Override protected void onStop() { mSharedPreferences.unregisterOnSharedPreferenceChangeListener(this); super.onStop(); } protected void setMapPath(String path) { SharedPreferences.Editor spEditor = mSharedPreferences.edit(); spEditor.putString(Const.KEY_PREF_MAP_PATH, path); spEditor.commit(); } public static class SettingsFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Load the preferences from an XML resource addPreferencesFromResource(R.xml.preferences); } } }