org.y20k.transistor.PlayerActivityFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.y20k.transistor.PlayerActivityFragment.java

Source

/**
 * PlayerActivityFragment.java
 * Implements the main fragment of the player activity
 * This fragment is a detail view with the ability to start and stop playback
 *
 * This file is part of
 * TRANSISTOR - Radio App for Android
 *
 * Copyright (c) 2015 - Y20K.org
 * Licensed under the MIT-License
 * http://opensource.org/licenses/MIT
 */

package org.y20k.transistor;

import android.Manifest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import org.y20k.transistor.core.Collection;
import org.y20k.transistor.helpers.DialogDelete;
import org.y20k.transistor.helpers.DialogRename;
import org.y20k.transistor.helpers.ImageHelper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * PlayerActivityFragment class
 */
public final class PlayerActivityFragment extends Fragment {

    /* Define log tag */
    private static final String LOG_TAG = PlayerActivityFragment.class.getSimpleName();

    /* Keys */
    private static final String STREAM_URL = "streamURL";
    private static final String STATION_NAME = "stationName";
    private static final String STATION_ID = "stationID";
    private static final String STATION_ID_CURRENT = "stationIDCurrent";
    private static final String STATION_ID_LAST = "stationIDLast";
    private static final String PLAYBACK = "playback";
    private static final String ACTION_PLAYBACK_STOPPED = "org.y20k.transistor.action.PLAYBACK_STOPPED";
    private static final int REQUEST_LOAD_IMAGE = 1;
    private static final int PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 1;

    /* Main class variables */
    private Activity mActivity;
    private View mRootView;
    private String mStationName;
    private String mStreamURL;
    private TextView mStationNameView;
    private ImageView mStationImageView;
    private ImageButton mPlaybackButton;
    private ImageView mPlaybackIndicator;
    private int mStationID;
    private int mStationIDCurrent;
    private int mStationIDLast;
    private boolean mPlayback;
    private Collection mCollection;
    private PlayerService mPlayerService;

    /* Constructor (default) */
    public PlayerActivityFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // get activity
        mActivity = getActivity();

        // get station name, URL and id from intent
        Intent intent = mActivity.getIntent();
        mStationID = intent.getIntExtra(STATION_ID, -1);
        mStationName = intent.getStringExtra(STATION_NAME);
        mStreamURL = intent.getStringExtra(STREAM_URL);

        // load playback state from preferences
        loadPlaybackState(mActivity);

        if (mStationID == -1) {
            // set station ID
            mStationID = mStationIDCurrent;
        }

        try {
            // get collection folder from external storage
            File folder = new File(mActivity.getExternalFilesDir("Collection").toString());
            // load collection
            mCollection = new Collection(folder);
        } catch (NullPointerException e) {
            // notify user and log exception
            Toast.makeText(mActivity, R.string.toastalert_no_external_storage, Toast.LENGTH_LONG).show();
            Log.e(LOG_TAG, "Unable to access external storage.");
            // finish activity
            mActivity.finish();
        }

        // get URL and name for stream
        mStreamURL = mCollection.getStations().get(mStationID).getStreamURL().toString();
        mStationName = mCollection.getStations().get(mStationID).getStationName();

        // fragment has options menu
        setHasOptionsMenu(true);

    }

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

        // TODO check connectivity
        // requires additional permission

        // set up button symbol and playback indicator
        setVisualState();

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        // set image for station
        Bitmap stationImageSmall;
        ImageHelper imageHelper;
        if (mCollection.getStations().get(mStationID).getStationImageFile().exists()) {
            stationImageSmall = BitmapFactory
                    .decodeFile(mCollection.getStations().get(mStationID).getStationImageFile().toString());
        } else {
            stationImageSmall = BitmapFactory.decodeResource(getResources(), R.drawable.ic_notesymbol);
        }
        imageHelper = new ImageHelper(stationImageSmall, mActivity);
        imageHelper.setBackgroundColor(R.color.transistor_grey_lighter);
        Bitmap stationImage = imageHelper.createCircularFramedImage(192);

        // initiate playback service
        mPlayerService = new PlayerService();

        // inflate rootview from xml
        mRootView = inflater.inflate(R.layout.fragment_player, container, false);

        // find views for station name and image and playback indicator
        mStationNameView = (TextView) mRootView.findViewById(R.id.player_textview_stationname);
        mStationImageView = (ImageView) mRootView.findViewById(R.id.player_imageview_station_icon);
        mPlaybackIndicator = (ImageView) mRootView.findViewById(R.id.player_playback_indicator);

        // set station image
        if (stationImage != null) {
            mStationImageView.setImageBitmap(stationImage);
        }

        // set text view to station name
        mStationNameView.setText(mStationName);

        // construct image button
        mPlaybackButton = (ImageButton) mRootView.findViewById(R.id.player_playback_button);

        // set listener to playback button
        mPlaybackButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                // playback stopped or new station - start playback
                if (!mPlayback || mStationID != mStationIDCurrent) {

                    // set playback true
                    mPlayback = true;
                    // rotate playback button
                    changeVisualState(mActivity);
                    // start player
                    mPlayerService.startActionPlay(mActivity, mStreamURL, mStationName);
                    Log.v(LOG_TAG, "Starting player service.");

                }
                // playback active - stop playback
                else {
                    // set playback false
                    mPlayback = false;
                    // rotate playback button
                    changeVisualState(mActivity);
                    // stop player
                    Log.v(LOG_TAG, "Stopping player service.");
                    mPlayerService.startActionStop(mActivity);
                }

                // save state of playback in settings store
                savePlaybackState(mActivity);
            }
        });

        // broadcast receiver: player service stopped playback
        BroadcastReceiver playbackStoppedReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                // set playback false
                mPlayback = false;
                // rotate playback button
                changeVisualState(context);
                // save state of playback to settings
                savePlaybackState(context);
            }
        };
        IntentFilter intentFilter = new IntentFilter(ACTION_PLAYBACK_STOPPED);
        LocalBroadcastManager.getInstance(mActivity).registerReceiver(playbackStoppedReceiver, intentFilter);

        return mRootView;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {

        // CASE ICON
        case R.id.menu_icon:

            // get system picker for images
            selectFromImagePicker();

            return true;

        // CASE RENAME
        case R.id.menu_rename:
            // construct rename dialog
            final DialogRename dialogRename = new DialogRename(mActivity, mCollection, mStationName, mStationID);
            dialogRename.setStationRenamedListener(new DialogRename.StationRenamedListener() {
                @Override
                public void stationRenamed() {
                    mStationNameView.setText(dialogRename.getStationName());
                }
            });
            // run dialog
            dialogRename.show();
            return true;

        // CASE DELETE
        case R.id.menu_delete:
            // stop playback
            mPlayerService.startActionStop(mActivity);
            // construct delete dialog
            DialogDelete dialogDelete = new DialogDelete(mActivity, mCollection, mStationID);
            dialogDelete.setStationDeletedListener(new DialogDelete.StationDeletedListener() {
                @Override
                public void stationDeleted() {
                    // start main activity
                    Intent mainActivityStartIntent = new Intent(mActivity, MainActivity.class);
                    startActivity(mainActivityStartIntent);
                    // finish player activity
                    mActivity.finish();
                }
            });
            // run dialog
            dialogDelete.show();
            return true;

        // CASE DEFAULT
        default:
            return super.onOptionsItemSelected(item);
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
        case PERMISSION_REQUEST_READ_EXTERNAL_STORAGE: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission granted - get system picker for images
                Intent pickImageIntent = new Intent(Intent.ACTION_PICK,
                        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(pickImageIntent, REQUEST_LOAD_IMAGE);
            } else {
                // permission denied
            }
        }
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_LOAD_IMAGE && resultCode == Activity.RESULT_OK && null != data) {
            // retrieve selected image from image picker
            processNewImage(data.getData());
        }
    }

    /* Processes new image and saves it to storage */
    private void processNewImage(Uri newImageUri) {

        ImageHelper imageHelper = new ImageHelper(newImageUri, mActivity);
        Bitmap newImage = imageHelper.getInputImage();

        if (newImage != null) {
            // write image to storage
            File stationImageFile = mCollection.getStations().get(mStationID).getStationImageFile();
            try (FileOutputStream out = new FileOutputStream(stationImageFile)) {
                newImage.compress(Bitmap.CompressFormat.PNG, 100, out);
            } catch (IOException e) {
                Log.e(LOG_TAG, "Unable to save: " + newImage.toString());
            }
            // change mStationImageView
            imageHelper.setBackgroundColor(R.color.transistor_grey_lighter);
            Bitmap stationImage = imageHelper.createCircularFramedImage(192);
            mStationImageView.setImageBitmap(stationImage);
        } else {
            Log.e(LOG_TAG, "Unable to get image from media picker: " + newImageUri.toString());
            // TODO handle error here
        }
    }

    /* Animate button and then set visual state */
    private void changeVisualState(Context context) {
        // get rotate animation from xml
        Animation rotate;
        if (mPlayback) {
            // if playback has been started get start animation
            rotate = AnimationUtils.loadAnimation(context, R.anim.rotate_clockwise_slow);
        } else {
            // if playback has been stopped get stop animation
            rotate = AnimationUtils.loadAnimation(context, R.anim.rotate_counterclockwise_fast);
        }

        // attach listener for animation end
        rotate.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                // set up button symbol and playback indicator afterwards
                setVisualState();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });

        // start animation of button
        mPlaybackButton.startAnimation(rotate);

    }

    /* Set button symbol and playback indicator */
    private void setVisualState() {

        // this station is running
        if (mPlayback && mStationID == mStationIDCurrent) {
            // change playback button image to stop
            mPlaybackButton.setImageResource(R.drawable.smbl_stop);
            // change playback indicator
            mPlaybackIndicator.setBackgroundResource(R.drawable.ic_playback_indicator_started_24dp);
        }
        // playback stopped
        else {
            // change playback button image to play
            mPlaybackButton.setImageResource(R.drawable.smbl_play);
            // change playback indicator
            mPlaybackIndicator.setBackgroundResource(R.drawable.ic_playback_indicator_stopped_24dp);
        }
    }

    /* Save station name and ID and playback state to SharedPreferences */
    private void savePlaybackState(Context context) {
        // playback started
        if (mPlayback) {
            mStationIDLast = mStationIDCurrent;
            mStationIDCurrent = mStationID;

        }
        // playback stopped
        else {
            mStationIDLast = mStationIDCurrent;
        }

        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = settings.edit();
        editor.putInt(STATION_ID_CURRENT, mStationIDCurrent);
        editor.putInt(STATION_ID_LAST, mStationIDLast);
        editor.putBoolean(PLAYBACK, mPlayback);
        editor.apply();

    }

    /* Loads playback state from preferences */
    private void loadPlaybackState(Context context) {
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
        mStationIDCurrent = settings.getInt(STATION_ID_CURRENT, -1);
        mStationIDLast = settings.getInt(STATION_ID_LAST, -1);
        mPlayback = settings.getBoolean(PLAYBACK, false);
    }

    /* Check permissions and start image picker */
    private void selectFromImagePicker() {
        // permission to read external storage granted
        if (ActivityCompat.checkSelfPermission(mActivity,
                Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {

            // get system picker for images
            Intent pickImageIntent = new Intent(Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(pickImageIntent, REQUEST_LOAD_IMAGE);
        }
        // permission to read external storage granted
        else {
            if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity,
                    Manifest.permission.READ_EXTERNAL_STORAGE)) {
                // ask for permission and explain why
                Snackbar snackbar = Snackbar.make(mRootView, R.string.snackbar_request_storage_access,
                        Snackbar.LENGTH_INDEFINITE);
                snackbar.setAction(R.string.dialog_generic_button_okay, new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        requestPermissions(new String[] { Manifest.permission.READ_EXTERNAL_STORAGE },
                                PERMISSION_REQUEST_READ_EXTERNAL_STORAGE);
                    }
                });
                snackbar.show();

            } else {
                // ask for permission without explanation
                requestPermissions(new String[] { Manifest.permission.READ_EXTERNAL_STORAGE },
                        PERMISSION_REQUEST_READ_EXTERNAL_STORAGE);
            }
        }
    }

}