tm.alashow.datmusic.ui.activity.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for tm.alashow.datmusic.ui.activity.MainActivity.java

Source

/*
 * Copyright 2015. Alashov Berkeli
 *
 *    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.
 */

package tm.alashow.datmusic.ui.activity;

import android.app.DownloadManager;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.SearchView;
import android.text.TextUtils;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.cocosw.bottomsheet.BottomSheet;
import com.google.android.gcm.GCMRegistrar;
import com.loopj.android.http.JsonHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import com.pnikosis.materialishprogress.ProgressWheel;
import com.squareup.picasso.Picasso;

import org.json.JSONArray;
import org.json.JSONObject;

import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Random;

import butterknife.Bind;
import cz.msebera.android.httpclient.Header;
import tm.alashow.datmusic.Config;
import tm.alashow.datmusic.R;
import tm.alashow.datmusic.android.IntentManager;
import tm.alashow.datmusic.model.Audio;
import tm.alashow.datmusic.ui.adapter.AudioListAdapter;
import tm.alashow.datmusic.util.ApiClient;
import tm.alashow.datmusic.util.AudioWife;
import tm.alashow.datmusic.util.U;
import tr.xip.errorview.ErrorView;

/**
 * Created by alashov on 21/03/15.
 */
public class MainActivity extends BaseActivity {

    private ArrayList<Audio> audioList = new ArrayList<>();
    private AudioListAdapter audioListAdapter;
    private MediaPlayer mMediaPlayer;
    private LayoutInflater layoutInflater;
    private SearchView mSearchView;
    private String oldQuery = "";

    //Preferences
    private String CONFIG_SORT;
    private String CONFIG_COUNT;
    private int CONFIG_PERFORMER_ONLY;

    @Bind(R.id.refreshLayout)
    SwipeRefreshLayout swipeRefreshLayout;
    @Bind(R.id.listView)
    ListView mListView;
    @Bind(R.id.progress)
    ProgressWheel progressBar;
    @Bind(R.id.errorView)
    ErrorView errorView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        layoutInflater = LayoutInflater.from(this);

        setTitle(R.string.app_name);

        U.setColorScheme(swipeRefreshLayout);
        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                search(oldQuery, true);
            }
        });
        errorView.setOnRetryListener(new ErrorView.RetryListener() {
            @Override
            public void onRetry() {
                U.hideView(errorView);
                search(oldQuery);
            }
        });

        getConfig();

        //GCM Registration
        try {
            GCMRegistrar.checkDevice(this);
            GCMRegistrar.checkManifest(this);
            final String regId = GCMRegistrar.getRegistrationId(this);
            if (regId.equals("")) {
                GCMRegistrar.register(this, Config.GCM_SENDER_ID);
            } else {

                RequestParams params = new RequestParams();
                params.put("reg_id", regId);
                params.put("id", U.getDeviceId(this));

                ApiClient.get(Config.ENDPOINT_API + "reg_id.php", params, new JsonHttpResponseHandler() {
                    @Override
                    public void onSuccess(int statusCode, Header[] headers, JSONObject response) {

                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            String queryExtra = getIntent().getExtras().getString(Config.EXTRA_QUERY);
            if (queryExtra != null && TextUtils.getTrimmedLength(queryExtra) > 1) {
                search(queryExtra);
                if (mSearchView != null) {
                    mSearchView.setIconified(false);
                    mSearchView.setQuery(queryExtra, false);
                }
            } else {
                searchWithRandomArtist();
            }
        } else {
            searchWithRandomArtist();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        getConfig();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        MenuItem searchItem = menu.findItem(R.id.search);
        mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
        if (mSearchView != null) {
            mSearchView.setQueryHint(getString(R.string.search_hint));

            mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String query) {
                    mSearchView.clearFocus(); //Hide keyboard
                    search(query);
                    return false;
                }

                @Override
                public boolean onQueryTextChange(String query) {
                    return true;
                }
            });
        }
        return true;
    }

    private void searchWithRandomArtist() {
        String[] artists = { "2 Cellos", "Agnes Obel", "Aloe Black", "Andrew Belle", "Angus Stone", "Aquilo",
                "Arctic Monkeys", "Avicii", "Balmorhea", "Barcelona", "Bastille", "Ben Howard", "Benj Heard",
                "Birdy", "Broods", "Calvin Harris", "Charlotte OC", "City of The Sun", "Civil Twilight",
                "Clint Mansell", "Coldplay", "Daft Punk", "Damien Rice", "Daniela Andrade", "Daughter",
                "David O'Dowda", "Dawn Golden", "Dirk Maassen", "Ed Sheeran", "Eminem", "Fabrizio Paterlini",
                "Fink", "Fleurie", "Florence and The Machine", "Gem club", "Glass Animals", "Greg Haines",
                "Greg Maroney", "Groen Land", "Halsey", "Hans Zimmer", "Hozier", "Imagine Dragons",
                "Ingrid Michaelson", "Jamie XX", "Jarryd James", "Jasmin Thompson", "Jaymes Young", "Jessie J",
                "Josef Salvat", "Julia Kent", "Kai Engel", "Keaton Henson", "Kendra Logozar", "Kina Grannis",
                "Kodaline", "Kygo", "Kyle Landry", "Lana Del Rey", "Lera Lynn", "Lights & Motion", "Linus Young",
                "Lo-Fang", "Lorde", "Ludovico Einaudi", "M83", "MONO", "MS MR", "Macklemore", "Mammals", "Maroon 5",
                "Martin Garrix", "Mattia Cupelli", "Max Richter", "Message To Bears", "Mogwai", "Mumford & Sons",
                "Nils Frahm", "ODESZA", "Oasis", "Of Monsters and Men", "Oh Wonder", "Philip Glass", "Phoebe Ryan",
                "Rachel Grimes", "Radiohead", "Ryan Keen", "Sam Smith", "Seinabo Sey", "Sia", "Takahiro Kido",
                "The Irrepressibles", "The Neighbourhood", "The xx", "Tom Odell", "VLNY", "Wye Oak",
                "X ambassadors", "Yann Tiersen", "Yiruma", "Young Summer", "Zack Hemsey", "Zinovia", "deadmau5",
                "pg.lost", "lafur Arnalds", "?" };

        String artist = artists[new Random().nextInt(artists.length)];

        search(artist);
    }

    private void search(String query) {
        search(query, false, -1, null, false);
    }

    private void search(String query, boolean refresh) {
        search(query, refresh, -1, null, false);
    }

    private void search(String query, long captchaSid, String captchaKey) {
        search(query, false, captchaSid, captchaKey, false);
    }

    private void search(String query, final boolean refresh, long captchaSid, String captchaKey,
            boolean performerOnly) {
        oldQuery = query;
        RequestParams params = new RequestParams();

        params.put("q", query);
        params.put("autocomplete", Config.VK_CONFIG_AUTOCOMPLETE);
        params.put("sort", CONFIG_SORT);
        params.put("count", CONFIG_COUNT);

        params.put("performer_only", (performerOnly) ? 1 : CONFIG_PERFORMER_ONLY);

        if (captchaSid > 1) {
            params.put("captcha_sid", captchaSid);
            params.put("captcha_key", captchaKey);
        }

        //change search method to getPopular, if query empty. get popular music.

        ApiClient.get(Config.SEARCH, params, new JsonHttpResponseHandler() {
            @Override
            public void onStart() {
                U.hideView(errorView);
                if (refresh) {
                    swipeRefreshLayout.setRefreshing(true);
                } else {
                    U.showView(progressBar);
                    U.hideView(mListView);
                }
            }

            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
                try {
                    clearList();//clear old data
                    if (response.has("error")) { //if we have error
                        //Result errors
                        JSONObject errorObject = response.getJSONObject("error");
                        int errorCode = errorObject.getInt("error_code");
                        //showing error
                        switch (errorCode) {
                        case 5:
                            showError("token");
                            break;
                        case 6: // "Too many requests per second" error, retry
                            search(oldQuery);
                            break;
                        case 14:
                            showCaptcha(errorObject.getString("captcha_img"), errorObject.getLong("captcha_sid"));
                            showError("captcha");
                            break;
                        default:
                            showError(errorObject.getString("error_msg"));
                            break;
                        }
                        return;
                    }
                    JSONArray audios = response.getJSONArray("response");
                    if (audios.length() >= 2) {
                        for (int i = 1; i < audios.length(); i++)
                            audioList.add(new Audio((JSONObject) audios.get(i)));
                        audioListAdapter = new AudioListAdapter(MainActivity.this, audioList);
                        mListView.setAdapter(audioListAdapter);
                        mListView.setFastScrollEnabled(audioList.size() > 10);

                        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                            @Override
                            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                                final Audio audio = audioList.get(position);
                                final BottomSheet bottomSheet = new BottomSheet.Builder(MainActivity.this)
                                        .title(audio.getArtist() + " - " + audio.getTitle())
                                        .sheet(R.menu.audio_actions)
                                        .listener(new DialogInterface.OnClickListener() {
                                            @Override
                                            public void onClick(DialogInterface dialog, int which) {
                                                switch (which) {
                                                case R.id.download:
                                                    DownloadManager mgr = (DownloadManager) getSystemService(
                                                            DOWNLOAD_SERVICE);
                                                    Uri downloadUri = Uri.parse(audio.getDownloadUrl());
                                                    DownloadManager.Request request = new DownloadManager.Request(
                                                            downloadUri);

                                                    if (U.isAboveOfVersion(11)) {
                                                        request.setNotificationVisibility(
                                                                DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                                                    }

                                                    request.setAllowedNetworkTypes(
                                                            DownloadManager.Request.NETWORK_WIFI
                                                                    | DownloadManager.Request.NETWORK_MOBILE);
                                                    mgr.enqueue(request);
                                                    break;
                                                case R.id.play:
                                                    playAudio(audio);
                                                    break;
                                                case R.id.copy:
                                                    if (!U.isAboveOfVersion(11)) {
                                                        android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getSystemService(
                                                                CLIPBOARD_SERVICE);
                                                        clipboard.setText(audio.getSecureDownloadUrl());
                                                    } else {
                                                        android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(
                                                                CLIPBOARD_SERVICE);
                                                        android.content.ClipData clip = android.content.ClipData
                                                                .newPlainText("Link", audio.getSecureDownloadUrl());
                                                        clipboard.setPrimaryClip(clip);
                                                        U.showCenteredToast(MainActivity.this,
                                                                R.string.audio_copied);
                                                    }
                                                    break;
                                                case R.id.share:
                                                    String shareText = getString(R.string.share_text)
                                                            + audio.getSecureDownloadUrl();
                                                    Intent sendIntent = new Intent();
                                                    sendIntent.setAction(Intent.ACTION_SEND);
                                                    sendIntent.putExtra(Intent.EXTRA_TEXT, shareText);
                                                    sendIntent.setType("text/plain");
                                                    startActivity(sendIntent);
                                                }
                                            }
                                        }).show();

                                //If file size already set, show it
                                if (audio.getBytes() > 1) {
                                    setSizeAndBitrate(bottomSheet, audio);
                                } else {
                                    try {
                                        new Thread(new Runnable() {
                                            @Override
                                            public void run() {
                                                try {
                                                    URLConnection ucon;
                                                    final URL uri = new URL(audio.getDownloadUrl());
                                                    ucon = uri.openConnection();
                                                    ucon.connect();
                                                    final long bytes = Long
                                                            .parseLong(ucon.getHeaderField("content-length"));
                                                    runOnUiThread(new Runnable() {
                                                        @Override
                                                        public void run() {
                                                            audio.setBytes(bytes);
                                                            setSizeAndBitrate(bottomSheet, audio);
                                                        }
                                                    });
                                                } catch (Exception e) {
                                                    e.printStackTrace();
                                                }
                                            }
                                        }).start();
                                    } catch (final Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        });

                        if (refresh) {
                            swipeRefreshLayout.setRefreshing(false);
                        } else {
                            U.hideView(progressBar);
                        }
                    } else {
                        showError("notFound");
                    }
                } catch (Exception e) {
                    U.showCenteredToast(MainActivity.this, R.string.exception);
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
                showError("network");
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) {
                showError("network");
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONArray errorResponse) {
                showError("network");
            }

            @Override
            public void onFinish() {
                U.showView(mListView);
                if (refresh) {
                    swipeRefreshLayout.setRefreshing(false);
                } else {
                    U.hideView(progressBar);
                }
            }
        });
    }

    /**
     * Set file size and audio bitrate to download menu
     *
     * @param bottomSheet menu where located download button
     * @param audio       file for get info
     */
    private void setSizeAndBitrate(BottomSheet bottomSheet, Audio audio) {
        MenuItem menuItem = bottomSheet.getMenu().findItem(R.id.download);
        long bitrate = audio.getBytes() / audio.getDuration() / 120;
        menuItem.setTitle(String.format(Locale.US, "%s (%s ~ %d kbps)", menuItem.getTitle(),
                U.humanReadableByteCount(audio.getBytes(), false), bitrate));
        bottomSheet.invalidate();
    }

    /**
     * Shows error by given error type
     *
     * @param error errors type or error message
     */
    private void showError(String error) {
        U.showView(errorView);
        switch (error) {
        case "network":
            errorView.setSubtitle(R.string.network_error);
            break;
        case "token":
            errorView.setSubtitle(R.string.error_token);
            break;
        case "notFound":
            errorView.setSubtitle(R.string.error_not_found);
            break;
        case "captcha":
            errorView.setSubtitle(R.string.error_captcha);
            break;
        default:
            errorView.setSubtitle(getString(R.string.error) + ": " + error);
            break;
        }
    }

    /**
     * Clear array and listview
     */
    private void clearList() {
        mListView.setAdapter(null);
        audioList.clear();
        mListView.setFastScrollEnabled(false);
    }

    /**
     * stop playing audio
     */
    private void resetPlayer() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.reset();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    private void showCaptcha(final String captchaImage, final long captchaSid) {
        View rootView = layoutInflater.inflate(R.layout.layout_captcha, null);
        final ImageView captchaImageView = (ImageView) rootView.findViewById(R.id.captcha);
        final EditText captchaKeyView = (EditText) rootView.findViewById(R.id.key);

        Picasso.with(this).load(captchaImage + "&v=" + System.currentTimeMillis())
                .placeholder(getResources().getColor(R.color.image_placeholder)).into(captchaImageView);

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setView(rootView);
        builder.setPositiveButton(R.string.captcha_submit, null);
        builder.setNegativeButton(R.string.captcha_reload, null);

        final AlertDialog alertDialog = builder.create();
        alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                Button submitButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
                Button reloadButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);

                submitButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        String captchaKey = captchaKeyView.getText().toString();
                        if (TextUtils.getTrimmedLength(captchaKey) >= 1) {
                            search(oldQuery, captchaSid, captchaKey);
                            alertDialog.dismiss();
                        } else {
                            U.showCenteredToast(MainActivity.this, R.string.captcha_empty);
                        }
                    }
                });

                reloadButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Picasso.with(MainActivity.this).load(captchaImage + "&v=" + System.currentTimeMillis())
                                .placeholder(getResources().getColor(R.color.image_placeholder))
                                .into(captchaImageView);
                    }
                });
            }
        });
        alertDialog.show();
    }

    private void getConfig() {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        if (sharedPreferences.getBoolean("languageChanged", false)) {
            PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("languageChanged", false).apply();
            IntentManager.with(this).main();
            finish();
        }
        CONFIG_COUNT = sharedPreferences.getString("searchCount", Config.VK_CONFIG_COUNT);
        CONFIG_SORT = sharedPreferences.getString("searchSort", Config.VK_CONFIG_SORT);
        CONFIG_PERFORMER_ONLY = (sharedPreferences.getBoolean("performerOnly", false)) ? 1 : 0;
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        getConfig();
        super.onConfigurationChanged(newConfig);
    }

    public void playAudio(final Audio audio) {
        final LinearLayout rootView = new LinearLayout(this);
        ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper(this,
                R.style.Base_Theme_AppCompat_Light_Dialog);
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(contextThemeWrapper);
        alertDialogBuilder.setView(rootView);
        alertDialogBuilder.setNegativeButton(R.string.audio_player_close, null);

        final AlertDialog alertDialog = alertDialogBuilder.create();
        alertDialog.setCanceledOnTouchOutside(false);

        alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                //change flat button color
                alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE)
                        .setTextColor(getResources().getColor(R.color.primary));
            }
        });
        //destroy mediaPlayer when dialog dismissed
        alertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {
                resetPlayer();
            }
        });

        new PrepareAudioTask(rootView, new OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mediaPlayer, AudioWife audioWife) {
                mMediaPlayer = mediaPlayer;
                alertDialog.show();
                TextView nameView = (TextView) rootView.findViewById(R.id.name);
                if (nameView != null) {
                    nameView.setText(audio.getArtist() + " - " + audio.getTitle());
                }
                audioWife.play();
            }

            @Override
            public void onError(Exception e) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        U.showCenteredToast(MainActivity.this, R.string.exception);
                    }
                });
            }
        }).execute(Uri.parse(audio.getStreamUrl()));
    }

    /**
     * Shows progress dialog while preparing mediaPlayer
     */
    public class PrepareAudioTask extends AsyncTask<Uri, Void, Void> {
        private AudioWife audioWife;
        private ViewGroup rootView;
        private OnPreparedListener onPreparedListener;
        private ProgressDialog progressDialog;
        private boolean cancelled = false;

        public PrepareAudioTask(ViewGroup rootView, OnPreparedListener onPreparedListener) {
            this.rootView = rootView;
            this.onPreparedListener = onPreparedListener;
            progressDialog = U.createActionLoading(MainActivity.this);
            progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.audio_player_close),
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            cancelled = true;
                            progressDialog.dismiss();
                            if (audioWife != null) {
                                audioWife.release();
                            }
                        }
                    });
        }

        @Override
        protected void onPreExecute() {
            progressDialog.show();
        }

        @Override
        protected Void doInBackground(Uri... params) {
            try {
                audioWife = AudioWife.getInstance().init(MainActivity.this, params[0], new OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mediaPlayer, AudioWife audioWife) {
                        if (!cancelled) {
                            progressDialog.dismiss();
                            onPreparedListener.onPrepared(mediaPlayer, audioWife);
                        }
                    }

                    @Override
                    public void onError(Exception e) {
                        if (!cancelled) {
                            onPreparedListener.onError(e);
                            progressDialog.dismiss();
                        }
                    }
                }).useDefaultUi(rootView, layoutInflater);
            } catch (Exception e) {
                e.printStackTrace();
                progressDialog.dismiss();
                onPreparedListener.onError(e);
            }
            return null;
        }
    }

    public interface OnPreparedListener {
        /**
         * called when audio prepared
         *
         * @param mediaPlayer mediaPlayer
         * @param audioWife   instance
         */
        void onPrepared(MediaPlayer mediaPlayer, AudioWife audioWife);

        /**
         * called when catch exception
         *
         * @param e exception
         */
        void onError(Exception e);
    }

    @Override
    protected int getLayoutResourceId() {
        return R.layout.activity_main;
    }

    @Override
    protected Boolean isChildActivity() {
        return false;
    }

    @Override
    protected String getActivityTag() {
        return Config.ACTIVITY_TAG_MAIN;
    }
}