Java tutorial
/* * Copyright (C) 2016 SMedic * * 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 com.smedic.tubtub; import android.Manifest; import android.annotation.TargetApi; import android.app.SearchManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.database.MatrixCursor; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import android.provider.BaseColumns; import android.support.annotation.NonNull; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.app.LoaderManager; import android.support.v4.content.ContextCompat; import android.support.v4.content.Loader; import android.support.v4.view.MenuItemCompat; import android.support.v4.view.ViewPager; import android.support.v4.widget.CursorAdapter; import android.support.v4.widget.SimpleCursorAdapter; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.SearchView; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.Window; import android.view.WindowManager; import com.flask.colorpicker.ColorPickerView; import com.flask.colorpicker.OnColorSelectedListener; import com.flask.colorpicker.builder.ColorPickerClickListener; import com.flask.colorpicker.builder.ColorPickerDialogBuilder; import com.smedic.tubtub.database.YouTubeSqlDb; import com.smedic.tubtub.fragments.FavoritesFragment; import com.smedic.tubtub.fragments.PlaylistsFragment; import com.smedic.tubtub.fragments.RecentlyWatchedFragment; import com.smedic.tubtub.fragments.SearchFragment; import com.smedic.tubtub.interfaces.OnFavoritesSelected; import com.smedic.tubtub.interfaces.OnItemSelected; import com.smedic.tubtub.model.ItemType; import com.smedic.tubtub.model.YouTubeVideo; import com.smedic.tubtub.utils.Config; import com.smedic.tubtub.utils.NetworkConf; import com.smedic.tubtub.utils.Utils; import com.smedic.tubtub.youtube.SuggestionsLoader; import java.util.ArrayList; import java.util.Collections; import java.util.List; import pub.devrel.easypermissions.AfterPermissionGranted; import pub.devrel.easypermissions.EasyPermissions; import static com.smedic.tubtub.R.layout.suggestions; enum Pane { FAVOURITES, RECENTLY_WATCHED, SEARCH, PLAYLIST } /** * Activity that manages fragments and action bar */ public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks, OnItemSelected, OnFavoritesSelected { private static final String TAG = "SMEDIC MAIN ACTIVITY"; private Toolbar toolbar; private TabLayout tabLayout; private ViewPager viewPager; private static final int PERMISSIONS = 1; private static final String PREF_BACKGROUND_COLOR = "BACKGROUND_COLOR"; private static final String PREF_TEXT_COLOR = "TEXT_COLOR"; private int initialColor = 0xffff0040; private int initialColors[] = new int[2]; private SearchFragment searchFragment; private RecentlyWatchedFragment recentlyPlayedFragment; private FavoritesFragment favoritesFragment; private PlaylistsFragment playlistsFragment; private int[] tabIcons = { R.drawable.ic_action_heart, R.drawable.ic_recently_wached, R.drawable.ic_search, R.drawable.ic_action_playlist }; private NetworkConf networkConf; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); YouTubeSqlDb.getInstance().init(this); toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(false); viewPager = (ViewPager) findViewById(R.id.viewpager); viewPager.setOffscreenPageLimit(3); setupViewPager(viewPager); tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.setupWithViewPager(viewPager); networkConf = new NetworkConf(this); setupTabIcons(); loadColor(); requestPermissions(); /* If a share intent is received when app is not open, process it on create */ handleIntent(getIntent()); } @AfterPermissionGranted(PERMISSIONS) private void requestPermissions() { final String[] perms = { Manifest.permission.WAKE_LOCK }; if (!EasyPermissions.hasPermissions(this, perms)) { // Do not have permissions, request them now EasyPermissions.requestPermissions(this, getString(R.string.all_permissions_request), PERMISSIONS, perms); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); } /** * Override super.onNewIntent() so that calls to getIntent() will return the * latest intent that was used to start this Activity rather than the first * intent. */ @Override public void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); handleIntent(intent); } /** * Handle search intent and queries YouTube for videos * * @param intent */ private void handleIntent(Intent intent) { final String action = intent.getAction(); if (action.equals(Intent.ACTION_SEARCH)) { String query = intent.getStringExtra(SearchManager.QUERY); viewPager.setCurrentItem(Pane.SEARCH.ordinal(), true); //switch to search fragment if (searchFragment != null) searchFragment.searchQuery(query); if (playlistsFragment != null) playlistsFragment.searchQuery(query); } else if (action.equals(Intent.ACTION_SEND)) { final String url = intent.getStringExtra(Intent.EXTRA_TEXT); Log.d(TAG, "Intent received: " + url); final String id = Utils.extractId(url); if (id == null) return; if (url.contains("playlist")) { viewPager.setCurrentItem(Pane.PLAYLIST.ordinal(), true); playlistsFragment.searchId(id); } else if (searchFragment != null) { viewPager.setCurrentItem(Pane.SEARCH.ordinal(), true); searchFragment.searchId(id); } } } /** * Setups icons for 3 tabs */ private void setupTabIcons() { tabLayout.getTabAt(0).setIcon(tabIcons[0]); tabLayout.getTabAt(1).setIcon(tabIcons[1]); tabLayout.getTabAt(2).setIcon(tabIcons[2]); tabLayout.getTabAt(3).setIcon(tabIcons[3]); } /** * Setups viewPager for switching between pages according to the selected tab * * @param viewPager */ private void setupViewPager(ViewPager viewPager) { ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); searchFragment = SearchFragment.newInstance(); recentlyPlayedFragment = RecentlyWatchedFragment.newInstance(); favoritesFragment = FavoritesFragment.newInstance(); playlistsFragment = PlaylistsFragment.newInstance(); adapter.addFragment(favoritesFragment, null); adapter.addFragment(recentlyPlayedFragment, null); adapter.addFragment(searchFragment, null); adapter.addFragment(playlistsFragment, null); viewPager.setAdapter(adapter); } @Override public void onPermissionsGranted(int requestCode, List<String> perms) { Log.d(TAG, "onPermissionsGranted:"); } @Override public void onPermissionsDenied(int requestCode, List<String> perms) { Log.d(TAG, "onPermissionsDenied: "); } @Override public void onVideoSelected(YouTubeVideo video) { if (!networkConf.isNetworkAvailable()) { networkConf.createNetErrorDialog(); return; } Intent serviceIntent = new Intent(this, BackgroundAudioService.class); serviceIntent.setAction(BackgroundAudioService.ACTION_PLAY); serviceIntent.putExtra(Config.YOUTUBE_TYPE, ItemType.YOUTUBE_MEDIA_TYPE_VIDEO); serviceIntent.putExtra(Config.YOUTUBE_TYPE_VIDEO, video); startService(serviceIntent); } @Override public void onPlaylistSelected(List<YouTubeVideo> playlist, int position) { if (!networkConf.isNetworkAvailable()) { networkConf.createNetErrorDialog(); return; } Intent serviceIntent = new Intent(this, BackgroundAudioService.class); serviceIntent.setAction(BackgroundAudioService.ACTION_PLAY); serviceIntent.putExtra(Config.YOUTUBE_TYPE, ItemType.YOUTUBE_MEDIA_TYPE_PLAYLIST); serviceIntent.putExtra(Config.YOUTUBE_TYPE_PLAYLIST, (ArrayList) playlist); serviceIntent.putExtra(Config.YOUTUBE_TYPE_PLAYLIST_VIDEO_POS, position); startService(serviceIntent); } @Override public void onFavoritesSelected(YouTubeVideo video, boolean isChecked) { if (isChecked) { favoritesFragment.addToFavoritesList(video); } else { favoritesFragment.removeFromFavorites(video); } } /** * Class which provides adapter for fragment pager */ class ViewPagerAdapter extends FragmentPagerAdapter { private final List<Fragment> mFragmentList = new ArrayList<>(); private final List<String> mFragmentTitleList = new ArrayList<>(); public ViewPagerAdapter(FragmentManager manager) { super(manager); } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } @Override public int getCount() { return mFragmentList.size(); } public void addFragment(Fragment fragment, String title) { mFragmentList.add(fragment); mFragmentTitleList.add(title); } @Override public CharSequence getPageTitle(int position) { return mFragmentTitleList.get(position); } } /** * Options menu in action bar * * @param menu * @return */ @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); MenuItem searchItem = menu.findItem(R.id.action_search); SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); if (searchView != null) { searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); } //suggestions final CursorAdapter suggestionAdapter = new SimpleCursorAdapter(this, suggestions, null, new String[] { SearchManager.SUGGEST_COLUMN_TEXT_1 }, new int[] { android.R.id.text1 }, 0); final List<String> suggestions = new ArrayList<>(); searchView.setSuggestionsAdapter(suggestionAdapter); searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() { @Override public boolean onSuggestionSelect(int position) { return false; } @Override public boolean onSuggestionClick(int position) { searchView.setQuery(suggestions.get(position), false); searchView.clearFocus(); Intent suggestionIntent = new Intent(Intent.ACTION_SEARCH); suggestionIntent.putExtra(SearchManager.QUERY, suggestions.get(position)); handleIntent(suggestionIntent); return true; } }); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String s) { return false; //if true, no new intent is started } @Override public boolean onQueryTextChange(final String query) { // check network connection. If not available, do not query. // this also disables onSuggestionClick triggering if (query.length() > 2) { //make suggestions after 3rd letter if (networkConf.isNetworkAvailable()) { suggestionLoader(suggestions, suggestionAdapter, query).forceLoad(); return true; } } return false; } }); return true; } private Loader suggestionLoader(final List<String> suggestions, final CursorAdapter suggestionAdapter, final String query) { return getSupportLoaderManager().restartLoader(4, null, new LoaderManager.LoaderCallbacks<List<String>>() { @Override public Loader<List<String>> onCreateLoader(final int id, final Bundle args) { return new SuggestionsLoader(getApplicationContext(), query); } @Override public void onLoadFinished(Loader<List<String>> loader, List<String> data) { if (data == null) return; suggestions.clear(); suggestions.addAll(data); String[] columns = { BaseColumns._ID, SearchManager.SUGGEST_COLUMN_TEXT_1 }; MatrixCursor cursor = new MatrixCursor(columns); for (int i = 0; i < data.size(); i++) { String[] tmp = { Integer.toString(i), data.get(i) }; cursor.addRow(tmp); } suggestionAdapter.swapCursor(cursor); } @Override public void onLoaderReset(Loader<List<String>> loader) { suggestions.clear(); suggestions.addAll(Collections.<String>emptyList()); } }); } /** * Handles selected item from action bar * * @param item * @return */ @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_about) { AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create(); alertDialog.setTitle(getString(R.string.myName)); alertDialog.setIcon(R.mipmap.ic_launcher); alertDialog.setMessage(getString(R.string.app_name) + " " + BuildConfig.VERSION_NAME + "\n\n" + getString(R.string.email) + "\n\n" + getString(R.string.date) + "\n"); alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); alertDialog.show(); return true; } else if (id == R.id.action_clear_list) { YouTubeSqlDb.getInstance().videos(YouTubeSqlDb.VIDEOS_TYPE.RECENTLY_WATCHED).deleteAll(); recentlyPlayedFragment.clearRecentlyPlayedList(); return true; } else if (id == R.id.action_search) { MenuItemCompat.expandActionView(item); return true; } else if (id == R.id.action_color_picker) { /* Show color picker dialog */ ColorPickerDialogBuilder.with(this).setTitle(getString(R.string.choose_colors)) .initialColor(initialColor).wheelType(ColorPickerView.WHEEL_TYPE.FLOWER).setPickerCount(2) .initialColors(initialColors).density(12) .setOnColorSelectedListener(new OnColorSelectedListener() { @Override public void onColorSelected(int selectedColor) { } }).setPositiveButton(getString(R.string.ok), new ColorPickerClickListener() { @Override public void onClick(DialogInterface dialog, int selectedColor, Integer[] allColors) { //changeBackgroundColor(selectedColor); if (allColors != null) { setColors(allColors[0], allColors[1]); } } }).setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }).showColorEdit(true).build().show(); } return super.onOptionsItemSelected(item); } /** * Loads app theme color saved in preferences */ private void loadColor() { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); int backgroundColor = sp.getInt(PREF_BACKGROUND_COLOR, -1); int textColor = sp.getInt(PREF_TEXT_COLOR, -1); if (backgroundColor != -1 && textColor != -1) { setColors(backgroundColor, textColor); } else { initialColors = new int[] { ContextCompat.getColor(this, R.color.colorPrimary), ContextCompat.getColor(this, R.color.textColorPrimary) }; } } /** * Save app theme color in preferences */ private void setColors(int backgroundColor, int textColor) { Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setBackgroundColor(backgroundColor); toolbar.setTitleTextColor(textColor); TabLayout tabs = (TabLayout) findViewById(R.id.tabs); tabs.setBackgroundColor(backgroundColor); tabs.setTabTextColors(textColor, textColor); setStatusBarColor(backgroundColor); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); sp.edit().putInt(PREF_BACKGROUND_COLOR, backgroundColor).apply(); sp.edit().putInt(PREF_TEXT_COLOR, textColor).apply(); initialColors[0] = backgroundColor; initialColors[1] = textColor; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void setStatusBarColor(int color) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Window window = getWindow(); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(color); } } }