com.cosmicsubspace.nerdyaudio.ui.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.cosmicsubspace.nerdyaudio.ui.MainActivity.java

Source

//Licensed under the MIT License.
//Include the license text thingy if you're gonna use this.
//Copyright (c) 2016 Chansol Yang

package com.cosmicsubspace.nerdyaudio.ui;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.design.widget.TabLayout;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.Toast;

import com.cosmicsubspace.nerdyaudio.R;
import com.cosmicsubspace.nerdyaudio.animation.MixNode;
import com.cosmicsubspace.nerdyaudio.animation.TestMixable;
import com.cosmicsubspace.nerdyaudio.audio.AudioPlayer;
import com.cosmicsubspace.nerdyaudio.audio.VisualizationBuffer;
import com.cosmicsubspace.nerdyaudio.audio.Waveform;
import com.cosmicsubspace.nerdyaudio.file.FileManager;
import com.cosmicsubspace.nerdyaudio.file.MusicInformation;
import com.cosmicsubspace.nerdyaudio.file.QueueManager;
import com.cosmicsubspace.nerdyaudio.helper.ErrorLogger;
import com.cosmicsubspace.nerdyaudio.helper.Log2;
import com.cosmicsubspace.nerdyaudio.interaction.VolumeControls;
import com.cosmicsubspace.nerdyaudio.service.BackgroundMusicService;
import com.cosmicsubspace.nerdyaudio.visuals.PlayControlsView;
import com.cosmicsubspace.nerdyaudio.visuals.VisualizationView;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;

//TODO : Prettier Queue Elements
//TODO : Better Library Browser
//TODO : Colorize Visuals
//TODO : Better UI Colors
//TODO : Shuffle & Repeat
//TODO : Waveform color always accent?
//TODO : Playlist/state save on exit
//TODO : Headphone Controls
//TODO : Playback device selection
//TODO : Dynamic Range Compression
//TODO : Lowpass on FFT result
//TODO : Spline interpolation on FFT result
//TODO : Pocket Play / Cinema Mode
//TODO : Display audio length on queue/file
//TODO : ClashWithDash.mp3 error
//TODO : Replace assertions with exceptions.

/**
 * Other Libraries:
 * Clans FAB [Apache]
 * Ringdroid [Apache]
 * Ninthavenue FileChooser [PD]
 * Meapsoft FFT [GPL v2]
 * Dragsortrecycler [Apache]
 */

public class MainActivity extends AppCompatActivity implements View.OnClickListener, DrawerLayout.DrawerListener {
    public final String LOG_TAG = "CS_AFN";
    Waveform wf;
    PlayControlsView wfv;
    AudioPlayer ap;
    VisualizationBuffer vb;
    QueueManager qm;
    FileManager fm;
    VisualizationManager vm;
    SidebarSettings sbs;

    private Handler mHandler = new Handler();

    VisualizationView vv;

    DrawerLayout dl;

    RelativeLayout settingBtn;
    ScrollView sideContainer;

    SharedPreferences sf;

    VolumeControls volCtrl;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        final Thread.UncaughtExceptionHandler orig = Thread.getDefaultUncaughtExceptionHandler();
        final Context c = getApplicationContext();
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable e) {
                Log2.log(0, this, "UncaughtException logged:", Log2.logToString(e));
                //Toast.makeText(c, ErrorLogger.logToString(e), Toast.LENGTH_SHORT).show();
                FileWriter f;
                try {
                    f = new FileWriter(new File(Environment.getExternalStorageDirectory() + "/AFN_exceptions.txt"),
                            true);
                    f.write("\n\n\n" + DateFormat.getDateTimeInstance().format(new Date()) + "\n");
                    f.write(Log2.logToString(e));
                    f.flush();
                    f.close();
                } catch (IOException e1) {
                    Log2.log(e1);
                } //Double exception?

                Log2.dumpLogsAsync();

                orig.uncaughtException(thread, e);
            }
        });

        requestPermission();

        Log2.log(1, this, "MainActivity Created!");

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        sf = getPreferences(Context.MODE_PRIVATE);

        String[] files = fileList();
        for (String i : files) {
            Log2.log(1, this, "File: " + i);
        }

        qm = QueueManager.getInstance();
        ap = AudioPlayer.getInstance();
        vb = VisualizationBuffer.getInstance();
        fm = FileManager.getInstance();
        wf = Waveform.getInstance();
        sbs = SidebarSettings.instantiate(getApplicationContext());
        vm = VisualizationManager.getInstance();

        volCtrl = new VolumeControls(getApplicationContext(), qm);

        //ap.setBufferFeedListener(vb);

        qm.passContext(getApplicationContext());
        fm.loadFromFile(this);

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        tabLayout.addTab(tabLayout.newTab().setText("Library"));
        tabLayout.addTab(tabLayout.newTab().setText("Queue"));
        tabLayout.addTab(tabLayout.newTab().setText("Filters"));
        tabLayout.addTab(tabLayout.newTab().setText("Now Playing"));
        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);

        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                int pos = tab.getPosition();
                if (pos == 0)
                    ft.replace(R.id.tab_area, new LibraryFragment());
                else if (pos == 1)
                    ft.replace(R.id.tab_area, new QueueFragment());
                else if (pos == 2)
                    ft.replace(R.id.tab_area, new FiltersFragment());
                else if (pos == 3)
                    ft.replace(R.id.tab_area, new NowPlayingFragment());

                ft.commit();
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
        getSupportFragmentManager().beginTransaction().replace(R.id.tab_area, new LibraryFragment()).commit();

        wfv = (PlayControlsView) findViewById(R.id.waveform);
        wfv.setSpacing(0);
        wfv.setTimestampVisibility(true);
        wfv.setTimestampSize(16);
        wfv.setTimestampColor(Color.WHITE);

        wfv.setTimestampOffset(30, 10);
        wfv.setTimestampBackgroundColor(Color.argb(128, 0, 0, 0));

        wfv.setWaveform(wf);
        qm.addQueueListener(wfv);
        qm.addProgressStringListener(wfv);

        vv = (VisualizationView) findViewById(R.id.visualization);

        dl = (DrawerLayout) findViewById(R.id.drawer_layout);

        dl.setDrawerListener(this);

        settingBtn = (RelativeLayout) findViewById(R.id.settings_btn);
        settingBtn.setOnClickListener(this);

        //statusText=(TextView)findViewById(R.id.status);

        sideContainer = (ScrollView) findViewById(R.id.drawer_scroll);
        sideContainer.addView(sbs.getView(getLayoutInflater(), sideContainer, null));

    }

    private static final int PERM_REQ_INTENT = 217;

    private void requestPermission() {
        // Here, thisActivity is the current activity
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.READ_EXTERNAL_STORAGE)) {

                // Show an expanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

            } else {

                // No explanation needed, we can request the permission.

                ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.READ_EXTERNAL_STORAGE },
                        PERM_REQ_INTENT);

                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
        case PERM_REQ_INTENT: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                //Toast.makeText(this, "Permission Granted!", Toast.LENGTH_SHORT).show();

            } else {
                Log2.log(3, this, "Ext. Storage permission denied.");
                Toast.makeText(this, "Permission Denied!", Toast.LENGTH_SHORT).show();
                Toast.makeText(this, "You won't be able to play music...", Toast.LENGTH_SHORT).show();
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
        }
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();
        if (id == R.id.db_5) {
            for (int i = 0; i < fm.getMusics().size(); i++) {
                qm.addMusic(fm.getMusics().get(i));
            }
            //qm.prepareWaveform();

        } else if (id == R.id.db_3) {
            qm.parseQueueFromFile(new File("storage/sdcard0/PlaylistBackup/R1.txt"));
        } else if (id == R.id.db_4) {
            qm.addMusic(new MusicInformation("storage/extSdCard/00_Personal_DATA/1_Music/AC24/M_5PM.mp3", this));
        } else if (id == R.id.db_1) {
            MixNode<TestMixable> mn = new MixNode<TestMixable>("T");
            MixNode<TestMixable> mn1 = new MixNode<TestMixable>("T1", new TestMixable(0));
            MixNode<TestMixable> mn2 = new MixNode<TestMixable>("T2", new TestMixable(10));
            mn.addNode(mn1);
            mn.addNode(mn2);

            for (int i = 0; i < 100; i++) {
                mn1.getInfluence().set(i / 100.0f);
                mn2.getInfluence().set(1.0f - i / 100.0f);
                Log2.log(2, this, mn.getValue(0).value);
            }
        } else if (id == R.id.db_6) {
            Log2.log(2, this, "Starting Service....");
            Intent itt = new Intent(this, BackgroundMusicService.class);
            itt.setAction(BackgroundMusicService.START_SERVICE);
            startService(itt);
        } else if (id == R.id.db_7) {
            Log2.log(2, this, "Stopping Service....");
            Intent itt = new Intent(this, BackgroundMusicService.class);
            itt.setAction(BackgroundMusicService.STOP_SERVICE);
            startService(itt);
            //int a=0/0;
        }
        return true;
    }

    @Override
    public void onStart() {
        super.onStart();
        //Toast.makeText(this, "onStart", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onResume() {
        super.onResume();
        mHandler.removeCallbacks(mUpdateClockTask);
        mHandler.postDelayed(mUpdateClockTask, 100);
        if (wfv != null)
            wfv.refreshPlaying();

        Log2.log(2, this, "Stopping Service....");
        Intent itt = new Intent(this, BackgroundMusicService.class);
        itt.setAction(BackgroundMusicService.STOP_SERVICE);
        startService(itt);
    }

    @Override
    public void onPause() {
        super.onPause();
        mHandler.removeCallbacks(mUpdateClockTask);
        vm.saveSettings();

        if (ap.isPlaying()) {
            Log2.log(2, this, "Starting Service....");
            Intent itt = new Intent(this, BackgroundMusicService.class);
            itt.setAction(BackgroundMusicService.START_SERVICE);
            startService(itt);
        }
    }

    @Override
    public void onStop() {
        Log2.dumpLogsAsync();

        super.onStop();
    }

    @Override
    public void onDestroy() {
        Log2.log(2, this, "I'm dyingggggggggg");
        super.onDestroy();
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        /*
        if (id==R.id.controls_play){
        if (ap!=null){
            if (ap.isPlaying()){
                ap.pause();
                play.setBackgroundResource(R.drawable.ic_play_arrow_white_48dp);
            }else if (ap.isPaused()){
                ap.playAudio();
                play.setBackgroundResource(R.drawable.ic_pause_white_48dp);
            }else{
                qm.play();
                play.setBackgroundResource(R.drawable.ic_pause_white_48dp);
            }
        }
        }else if (id==R.id.settings_btn){
        dl.openDrawer(Gravity.RIGHT);
        }else if (id==R.id.controls_fastforward){
        qm.playNextFile();
        }else if (id==R.id.controls_rewind){
        qm.playPreviousFile();
        }*/
        if (id == R.id.settings_btn) {
            dl.openDrawer(Gravity.RIGHT);
        }
    }

    public void updateStatusString() {
        //statusText.setText(qm.getStatusString());
    }

    private Runnable mUpdateClockTask = new Runnable() {
        public void run() {
            updateStatusString();
            mHandler.postDelayed(mUpdateClockTask, 1000);
        }
    };

    @Override
    public void onDrawerSlide(View drawerView, float slideOffset) {

    }

    @Override
    public void onDrawerOpened(View drawerView) {

    }

    @Override
    public void onDrawerClosed(View drawerView) {

    }

    @Override
    public void onDrawerStateChanged(int newState) {

    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (sbs.getVolumeControlsEnabled() && volCtrl.event(event)) { //enabled AND consumed.
            return true;
        } else
            return super.dispatchKeyEvent(event);
    }

}