Java tutorial
/* * Copyright 2014 WNCOutdoors.info * portions Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * AppInfoSettingsFragment.java * Fragment which controls the Settings tab under the App Info activity, * and provides information about the status of the Google Play Services * library on the user's device, as well as the status of offline maps * expansion file, and ability to download that if not completed yet. */ package info.wncwaterfalls.app; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.provider.Settings; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.google.android.vending.expansion.downloader.DownloadProgressInfo; import com.google.android.vending.expansion.downloader.Helpers; import com.google.android.vending.expansion.downloader.IDownloaderClient; import com.google.android.vending.expansion.downloader.IDownloaderService; import info.wncwaterfalls.app.R; import java.io.File; import java.io.FilenameFilter; import java.util.Locale; public class AppInfoSettingsFragment extends Fragment { private final String TAG = "AppInfoSettingsFragment"; private ProgressBar mPB; private TextView mGooglePlayServicesStatusText; private TextView mExpansionDownloadStatusText; private TextView mProgressFraction; private TextView mProgressPercent; private TextView mAverageSpeed; private TextView mTimeRemaining; private View mDashboard; private View mCellMessage; private Button mPauseButton; private Button mWiFiSettingsButton; private Button mClearMBTilesCacheButton; private boolean mStatePaused; private int mState; private OnExpansionFilesDownloadListener sExpansionFilesDownloadListener; // TODO: Move these outside this class // Interface for listening to requests for expansion files downloads // Containing activity must implement this. public interface OnExpansionFilesDownloadListener { public boolean getPlayServicesAvailable(); public boolean getNeedsExpansionFileDownload(); public boolean getUserPrefPauseDownload(); public boolean buildPendingDownloadIntent(); public void setUserPrefPauseDownload(boolean paused); public void serviceRequestContinueDownload(); public void serviceRequestPauseDownload(); public void serviceRequestSetDownloadFlags(int flags); } @Override public void onAttach(Activity activity) { super.onAttach(activity); // Make sure the containing activity implements the downloader listener interface try { sExpansionFilesDownloadListener = (OnExpansionFilesDownloadListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnExpansionFilesDownloadListener"); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_app_info_settings, container, false); initializeDownloadUI(view); return view; } @Override public void onResume() { // Don't bother checking for expansion file unless play services is available, because // without it we can't show maps. if (sExpansionFilesDownloadListener.getPlayServicesAvailable()) { setPlayServicesMessage(true); // Do we need the expansion file? if (sExpansionFilesDownloadListener.getNeedsExpansionFileDownload()) { // Yes. Are we paused? if (sExpansionFilesDownloadListener.getUserPrefPauseDownload()) { // Yes. Set state to paused. onDownloadStateChanged(IDownloaderClient.STATE_PAUSED_BY_REQUEST); } else { // No. Start or resume download. boolean reallyNeeded = sExpansionFilesDownloadListener.buildPendingDownloadIntent(); if (reallyNeeded) { clearCachedMBTilesFiles(); } } } else { // No. Set UI to show completion. onDownloadStateChanged(IDownloaderClient.STATE_COMPLETED); } } else { // No. Set UI to show that Play Services is not available. setPlayServicesMessage(false); mDashboard.setVisibility(View.GONE); } super.onResume(); } private void setPlayServicesMessage(boolean available) { // Set the Google Play Services availability message. if (available) { mGooglePlayServicesStatusText.setText("Google Play Services is available and up to date."); } else { mGooglePlayServicesStatusText .setText("Google Play Services is not installed, not available or out of date."); } } private void setState(int newState) { mState = newState; if (newState == IDownloaderClient.STATE_COMPLETED) { // Custom message mExpansionDownloadStatusText .setText("Offline maps are available. Load a map one time while online before going offline!"); } else { // System-provided message mExpansionDownloadStatusText.setText(Helpers.getDownloaderStringResourceIDFromState(newState)); } } private void setButtonPausedState(boolean paused) { mStatePaused = paused; int stringResourceID = paused ? R.string.text_button_resume : R.string.text_button_pause; mPauseButton.setText(stringResourceID); // Tell the activity sExpansionFilesDownloadListener.setUserPrefPauseDownload(paused); } // Tie UI controls into remote service calls for controlling the downloader. public void initializeDownloadUI(View view) { mPB = (ProgressBar) view.findViewById(R.id.progressBar); mGooglePlayServicesStatusText = (TextView) view.findViewById(R.id.googlePlayServicesStatusText); mExpansionDownloadStatusText = (TextView) view.findViewById(R.id.expansionDownloadStatusText); mProgressFraction = (TextView) view.findViewById(R.id.progressAsFraction); mProgressPercent = (TextView) view.findViewById(R.id.progressAsPercentage); mAverageSpeed = (TextView) view.findViewById(R.id.progressAverageSpeed); mTimeRemaining = (TextView) view.findViewById(R.id.progressTimeRemaining); mDashboard = view.findViewById(R.id.downloaderDashboard); mCellMessage = view.findViewById(R.id.approveCellular); mPauseButton = (Button) view.findViewById(R.id.pauseButton); mWiFiSettingsButton = (Button) view.findViewById(R.id.wifiSettingsButton); mClearMBTilesCacheButton = (Button) view.findViewById(R.id.clearCachedMBTilesButton); mClearMBTilesCacheButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { clearCachedMBTilesFiles(); } }); mPauseButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mStatePaused) { sExpansionFilesDownloadListener.serviceRequestContinueDownload(); } else { sExpansionFilesDownloadListener.serviceRequestPauseDownload(); } setButtonPausedState(!mStatePaused); } }); setButtonPausedState(mStatePaused); // Set text mWiFiSettingsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)); } }); Button resumeOnCell = (Button) view.findViewById(R.id.resumeOverCellular); resumeOnCell.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { sExpansionFilesDownloadListener .serviceRequestSetDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR); sExpansionFilesDownloadListener.serviceRequestContinueDownload(); mCellMessage.setVisibility(View.GONE); } }); } /** * The download state should trigger changes in the UI --- it may be useful * to show the state as being indeterminate at times. * * We're going with the sample-as-guideline-is-fine until testing proves otherwise. * * In our implementation, download state changes are forwarded from the Activity * to this Fragment. */ public void onDownloadStateChanged(int newState) { setState(newState); boolean showDashboard = true; boolean showCellMessage = false; boolean paused; boolean indeterminate; switch (newState) { case IDownloaderClient.STATE_IDLE: // STATE_IDLE means the service is listening, so it's // safe to start making calls via mRemoteService. paused = false; indeterminate = true; break; case IDownloaderClient.STATE_CONNECTING: case IDownloaderClient.STATE_FETCHING_URL: showDashboard = true; paused = false; indeterminate = true; break; case IDownloaderClient.STATE_DOWNLOADING: paused = false; showDashboard = true; indeterminate = false; break; case IDownloaderClient.STATE_FAILED_CANCELED: case IDownloaderClient.STATE_FAILED: case IDownloaderClient.STATE_FAILED_FETCHING_URL: case IDownloaderClient.STATE_FAILED_UNLICENSED: paused = true; showDashboard = false; indeterminate = false; break; case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION: case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION: showDashboard = false; paused = true; indeterminate = false; showCellMessage = true; break; case IDownloaderClient.STATE_PAUSED_BY_REQUEST: paused = true; indeterminate = false; break; case IDownloaderClient.STATE_PAUSED_ROAMING: case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE: paused = true; indeterminate = false; break; case IDownloaderClient.STATE_COMPLETED: showDashboard = false; paused = false; indeterminate = false; // TODO: validateXAPKZipFiles(); // Ugh. This should be done in the Activity break; default: paused = true; indeterminate = true; showDashboard = true; } int newDashboardVisibility = showDashboard ? View.VISIBLE : View.GONE; if (mDashboard.getVisibility() != newDashboardVisibility) { mDashboard.setVisibility(newDashboardVisibility); } int cellMessageVisibility = showCellMessage ? View.VISIBLE : View.GONE; if (mCellMessage.getVisibility() != cellMessageVisibility) { mCellMessage.setVisibility(cellMessageVisibility); } mPB.setIndeterminate(indeterminate); setButtonPausedState(paused); } // Sets the state of the various controls based on the progressinfo object // sent from the downloader service. public void onDownloadProgress(DownloadProgressInfo progress) { mAverageSpeed .setText(getString(R.string.kilobytes_per_second, Helpers.getSpeedString(progress.mCurrentSpeed))); mTimeRemaining .setText(getString(R.string.time_remaining, Helpers.getTimeRemaining(progress.mTimeRemaining))); progress.mOverallTotal = progress.mOverallTotal; mPB.setMax((int) (progress.mOverallTotal >> 8)); mPB.setProgress((int) (progress.mOverallProgress >> 8)); mProgressPercent.setText(Long.toString(progress.mOverallProgress * 100 / progress.mOverallTotal) + "%"); mProgressFraction .setText(Helpers.getDownloadProgressString(progress.mOverallProgress, progress.mOverallTotal)); } public void clearCachedMBTilesFiles() { // Clear all cached MBTiles files - to free up space or when // getting a new .obb package. File externalCacheDir = new File(getActivity().getExternalCacheDir(), "/mbtiles/"); // o java FilenameFilter mbtilesExtFilter = new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.toLowerCase(Locale.ENGLISH).endsWith(".mbtiles"); } }; File[] cachedMBTiles = externalCacheDir.listFiles(mbtilesExtFilter); if (cachedMBTiles != null) { int numFound = cachedMBTiles.length; for (File mbTilesFile : cachedMBTiles) { mbTilesFile.delete(); } CharSequence text = "Cleared " + numFound + " unzipped maps."; int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(getActivity(), text, duration); toast.show(); } } }