Add "plugins" menu option in full playback view (#559)
- refactor plugin querying in a way that now any library activity can utilize it - Make doc more thorough - Hopefully fix empty plugin list bug (flag was added to wrong intent)
This commit is contained in:
parent
2b07abdc8b
commit
2bc17ec2dd
@ -29,8 +29,6 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -40,13 +38,10 @@ import android.view.Menu;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.SeekBar;
|
|
||||||
import android.widget.TableLayout;
|
import android.widget.TableLayout;
|
||||||
import android.widget.TableRow;
|
import android.widget.TableRow;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
|
||||||
@ -308,6 +303,7 @@ public class FullPlaybackActivity extends SlidingPlaybackActivity
|
|||||||
menu.add(0, MENU_ENQUEUE_GENRE, 30, R.string.enqueue_current_genre);
|
menu.add(0, MENU_ENQUEUE_GENRE, 30, R.string.enqueue_current_genre);
|
||||||
menu.add(0, MENU_ADD_TO_PLAYLIST, 30, R.string.add_to_playlist);
|
menu.add(0, MENU_ADD_TO_PLAYLIST, 30, R.string.add_to_playlist);
|
||||||
menu.add(0, MENU_SHARE, 30, R.string.share);
|
menu.add(0, MENU_SHARE, 30, R.string.share);
|
||||||
|
menu.add(0, MENU_PLUGINS, 30, R.string.plugins);
|
||||||
mFavorites = menu.add(0, MENU_SONG_FAVORITE, 0, R.string.add_to_favorites).setIcon(R.drawable.btn_rating_star_off_mtrl_alpha).setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
mFavorites = menu.add(0, MENU_SONG_FAVORITE, 0, R.string.add_to_favorites).setIcon(R.drawable.btn_rating_star_off_mtrl_alpha).setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||||
|
|
||||||
// ensure that mFavorites is updated
|
// ensure that mFavorites is updated
|
||||||
@ -383,6 +379,11 @@ public class FullPlaybackActivity extends SlidingPlaybackActivity
|
|||||||
dialog.create().show();
|
dialog.create().show();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MENU_PLUGINS:
|
||||||
|
Intent songIntent = new Intent();
|
||||||
|
songIntent.putExtra("id", song.id);
|
||||||
|
queryPluginsForIntent(songIntent);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
@ -26,20 +26,14 @@ package ch.blinkenlights.android.vanilla;
|
|||||||
import ch.blinkenlights.android.medialibrary.MediaLibrary;
|
import ch.blinkenlights.android.medialibrary.MediaLibrary;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.ApplicationInfo;
|
|
||||||
import android.content.pm.ResolveInfo;
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.PaintDrawable;
|
import android.graphics.drawable.PaintDrawable;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
@ -60,10 +54,6 @@ import android.widget.TextView;
|
|||||||
import android.widget.SearchView;
|
import android.widget.SearchView;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
|
|
||||||
@ -143,19 +133,6 @@ public class LibraryActivity
|
|||||||
* The last used action from the menu. Used with ACTION_LAST_USED.
|
* The last used action from the menu. Used with ACTION_LAST_USED.
|
||||||
*/
|
*/
|
||||||
private int mLastAction = ACTION_PLAY;
|
private int mLastAction = ACTION_PLAY;
|
||||||
/**
|
|
||||||
* Holds last intent that was passed to the context menu
|
|
||||||
*/
|
|
||||||
private Intent mLastRequestedCtx;
|
|
||||||
/**
|
|
||||||
* Plugin descriptions and packages.
|
|
||||||
* Keys are plugin names, values are their packages
|
|
||||||
*/
|
|
||||||
private Map<String, ApplicationInfo> mPlugins = new HashMap<>();
|
|
||||||
/**
|
|
||||||
* Broadcast receiver for plugin collecting
|
|
||||||
*/
|
|
||||||
private BroadcastReceiver mPluginInfoReceiver;
|
|
||||||
/**
|
/**
|
||||||
* The pager adapter that manages each media ListView.
|
* The pager adapter that manages each media ListView.
|
||||||
*/
|
*/
|
||||||
@ -189,7 +166,6 @@ public class LibraryActivity
|
|||||||
mViewPager = pager;
|
mViewPager = pager;
|
||||||
|
|
||||||
SharedPreferences settings = PlaybackService.getSettings(this);
|
SharedPreferences settings = PlaybackService.getSettings(this);
|
||||||
mPluginInfoReceiver = new PluginBroadcastReceiver();
|
|
||||||
|
|
||||||
mBottomBarControls = (BottomBarControls)findViewById(R.id.bottombar_controls);
|
mBottomBarControls = (BottomBarControls)findViewById(R.id.bottombar_controls);
|
||||||
mBottomBarControls.setOnClickListener(this);
|
mBottomBarControls.setOnClickListener(this);
|
||||||
@ -213,43 +189,6 @@ public class LibraryActivity
|
|||||||
bindControlButtons();
|
bindControlButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows plugin selection dialog. Be sure that {@link #mLastRequestedCtx} is initialized
|
|
||||||
* and {@link #mPlugins} are populated before calling this.
|
|
||||||
*
|
|
||||||
* @see PluginBroadcastReceiver
|
|
||||||
*/
|
|
||||||
private void showPluginMenu() {
|
|
||||||
Set<String> pluginNames = mPlugins.keySet();
|
|
||||||
final String[] pNamesArr = pluginNames.toArray(new String[pluginNames.size()]);
|
|
||||||
new AlertDialog.Builder(this)
|
|
||||||
.setItems(pNamesArr, new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
long id = mLastRequestedCtx.getLongExtra("id", LibraryAdapter.INVALID_ID);
|
|
||||||
Song resolved = MediaUtils.getSongByTypeId(LibraryActivity.this, MediaUtils.TYPE_SONG, id);
|
|
||||||
if (resolved != null) {
|
|
||||||
ApplicationInfo selected = mPlugins.get(pNamesArr[which]);
|
|
||||||
Intent request = new Intent(PluginUtils.ACTION_LAUNCH_PLUGIN);
|
|
||||||
request.setPackage(selected.packageName);
|
|
||||||
request.putExtra(PluginUtils.EXTRA_PARAM_URI, Uri.fromFile(new File(resolved.path)));
|
|
||||||
request.putExtra(PluginUtils.EXTRA_PARAM_SONG_TITLE, resolved.title);
|
|
||||||
request.putExtra(PluginUtils.EXTRA_PARAM_SONG_ARTIST, resolved.artist);
|
|
||||||
request.putExtra(PluginUtils.EXTRA_PARAM_SONG_ALBUM, resolved.album);
|
|
||||||
startService(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
mLastRequestedCtx = null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
|
||||||
@Override
|
|
||||||
public void onCancel(DialogInterface dialog) {
|
|
||||||
mLastRequestedCtx = null;
|
|
||||||
}
|
|
||||||
}).create().show();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRestart()
|
public void onRestart()
|
||||||
{
|
{
|
||||||
@ -267,18 +206,6 @@ public class LibraryActivity
|
|||||||
updateHeaders();
|
updateHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
registerReceiver(mPluginInfoReceiver, new IntentFilter(PluginUtils.ACTION_HANDLE_PLUGIN_PARAMS));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
unregisterReceiver(mPluginInfoReceiver);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the tab order and update the tab bars if needed.
|
* Load the tab order and update the tab bars if needed.
|
||||||
*/
|
*/
|
||||||
@ -776,12 +703,7 @@ public class LibraryActivity
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CTX_MENU_PLUGINS: {
|
case CTX_MENU_PLUGINS: {
|
||||||
// obtain list of plugins anew - some plugins may be installed/deleted
|
queryPluginsForIntent(intent);
|
||||||
mPlugins.clear();
|
|
||||||
mLastRequestedCtx = intent;
|
|
||||||
Intent requestPlugins = new Intent(PluginUtils.ACTION_REQUEST_PLUGIN_PARAMS);
|
|
||||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
|
||||||
sendBroadcast(requestPlugins);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CTX_MENU_MORE_FROM_ARTIST: {
|
case CTX_MENU_MORE_FROM_ARTIST: {
|
||||||
@ -1004,21 +926,4 @@ public class LibraryActivity
|
|||||||
handler.sendMessage(mHandler.obtainMessage(MSG_SAVE_PAGE, position, 0));
|
handler.sendMessage(mHandler.obtainMessage(MSG_SAVE_PAGE, position, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PluginBroadcastReceiver extends BroadcastReceiver {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
List<ResolveInfo> resolved = getPackageManager().queryBroadcastReceivers(new Intent(PluginUtils.ACTION_REQUEST_PLUGIN_PARAMS), 0);
|
|
||||||
if (PluginUtils.ACTION_HANDLE_PLUGIN_PARAMS.equals(intent.getAction())) {
|
|
||||||
// plugin answered, store it in the map
|
|
||||||
String pluginName = intent.getStringExtra(PluginUtils.EXTRA_PARAM_PLUGIN_NAME);
|
|
||||||
ApplicationInfo info = intent.getParcelableExtra(PluginUtils.EXTRA_PARAM_PLUGIN_APP);
|
|
||||||
mPlugins.put(pluginName, info);
|
|
||||||
|
|
||||||
if (mPlugins.size() == resolved.size()) { // got all plugins
|
|
||||||
showPluginMenu();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -25,13 +25,24 @@ package ch.blinkenlights.android.vanilla;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
@ -75,6 +86,19 @@ public abstract class PlaybackActivity extends Activity
|
|||||||
* The looper for the worker thread.
|
* The looper for the worker thread.
|
||||||
*/
|
*/
|
||||||
protected Looper mLooper;
|
protected Looper mLooper;
|
||||||
|
/**
|
||||||
|
* Broadcast receiver for plugin collecting
|
||||||
|
*/
|
||||||
|
private BroadcastReceiver mPluginInfoReceiver;
|
||||||
|
/**
|
||||||
|
* Holds last intent that was passed to the context menu
|
||||||
|
*/
|
||||||
|
private Intent mLastRequestedCtx;
|
||||||
|
/**
|
||||||
|
* Plugin descriptions and packages.
|
||||||
|
* Keys are plugin names, values are their packages
|
||||||
|
*/
|
||||||
|
private Map<String, ApplicationInfo> mPlugins = new HashMap<>();
|
||||||
|
|
||||||
protected CoverView mCoverView;
|
protected CoverView mCoverView;
|
||||||
protected ImageButton mPlayPauseButton;
|
protected ImageButton mPlayPauseButton;
|
||||||
@ -92,6 +116,8 @@ public abstract class PlaybackActivity extends Activity
|
|||||||
|
|
||||||
PlaybackService.addTimelineCallback(this);
|
PlaybackService.addTimelineCallback(this);
|
||||||
|
|
||||||
|
mPluginInfoReceiver = new PluginBroadcastReceiver();
|
||||||
|
|
||||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||||
|
|
||||||
HandlerThread thread = new HandlerThread(getClass().getName(), Process.THREAD_PRIORITY_LOWEST);
|
HandlerThread thread = new HandlerThread(getClass().getName(), Process.THREAD_PRIORITY_LOWEST);
|
||||||
@ -138,6 +164,7 @@ public abstract class PlaybackActivity extends Activity
|
|||||||
public void onResume()
|
public void onResume()
|
||||||
{
|
{
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
registerReceiver(mPluginInfoReceiver, new IntentFilter(PluginUtils.ACTION_HANDLE_PLUGIN_PARAMS));
|
||||||
if (PlaybackService.hasInstance()) {
|
if (PlaybackService.hasInstance()) {
|
||||||
PlaybackService service = PlaybackService.get(this);
|
PlaybackService service = PlaybackService.get(this);
|
||||||
service.userActionTriggered();
|
service.userActionTriggered();
|
||||||
@ -145,6 +172,11 @@ public abstract class PlaybackActivity extends Activity
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
unregisterReceiver(mPluginInfoReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||||
@ -376,6 +408,7 @@ public abstract class PlaybackActivity extends Activity
|
|||||||
static final int MENU_ADD_TO_PLAYLIST = 17;
|
static final int MENU_ADD_TO_PLAYLIST = 17;
|
||||||
static final int MENU_SHARE = 18;
|
static final int MENU_SHARE = 18;
|
||||||
static final int MENU_GO_HOME = 19;
|
static final int MENU_GO_HOME = 19;
|
||||||
|
static final int MENU_PLUGINS = 20; // used in FullPlaybackActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu)
|
public boolean onCreateOptionsMenu(Menu menu)
|
||||||
@ -661,4 +694,80 @@ public abstract class PlaybackActivity extends Activity
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends broadcast query that wakes plugins are queries them for info.
|
||||||
|
* Answers are later processed in {@link PluginBroadcastReceiver}
|
||||||
|
*
|
||||||
|
* @param songIntent intent containing song id as {@link Long} in its "id" extra.
|
||||||
|
*/
|
||||||
|
protected void queryPluginsForIntent(Intent songIntent) {
|
||||||
|
// obtain list of plugins anew - some plugins may be installed/deleted
|
||||||
|
mPlugins.clear();
|
||||||
|
mLastRequestedCtx = songIntent;
|
||||||
|
Intent requestPlugins = new Intent(PluginUtils.ACTION_REQUEST_PLUGIN_PARAMS);
|
||||||
|
requestPlugins.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||||
|
sendBroadcast(requestPlugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcast receiver that handles return intents from queried plugins.
|
||||||
|
* Answered ones are stored in {@link #mPlugins}.
|
||||||
|
* Shows plugin menu once all queried plugins have answered.
|
||||||
|
*
|
||||||
|
* @see #showPluginMenu()
|
||||||
|
*/
|
||||||
|
private class PluginBroadcastReceiver extends BroadcastReceiver {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
List<ResolveInfo> resolved = getPackageManager().queryBroadcastReceivers(new Intent(PluginUtils.ACTION_REQUEST_PLUGIN_PARAMS), 0);
|
||||||
|
if (PluginUtils.ACTION_HANDLE_PLUGIN_PARAMS.equals(intent.getAction())) {
|
||||||
|
// plugin answered, store it in the map
|
||||||
|
String pluginName = intent.getStringExtra(PluginUtils.EXTRA_PARAM_PLUGIN_NAME);
|
||||||
|
ApplicationInfo info = intent.getParcelableExtra(PluginUtils.EXTRA_PARAM_PLUGIN_APP);
|
||||||
|
mPlugins.put(pluginName, info);
|
||||||
|
|
||||||
|
if (mPlugins.size() == resolved.size()) { // got all plugins
|
||||||
|
showPluginMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows plugin selection dialog. Be sure that {@link #mLastRequestedCtx} is initialized
|
||||||
|
* and {@link #mPlugins} are populated before calling this.
|
||||||
|
*
|
||||||
|
* @see PluginBroadcastReceiver
|
||||||
|
*/
|
||||||
|
private void showPluginMenu() {
|
||||||
|
Set<String> pluginNames = mPlugins.keySet();
|
||||||
|
final String[] pNamesArr = pluginNames.toArray(new String[pluginNames.size()]);
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setItems(pNamesArr, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
long id = mLastRequestedCtx.getLongExtra("id", LibraryAdapter.INVALID_ID);
|
||||||
|
Song resolved = MediaUtils.getSongByTypeId(PlaybackActivity.this, MediaUtils.TYPE_SONG, id);
|
||||||
|
if (resolved != null) {
|
||||||
|
ApplicationInfo selected = mPlugins.get(pNamesArr[which]);
|
||||||
|
Intent request = new Intent(PluginUtils.ACTION_LAUNCH_PLUGIN);
|
||||||
|
request.setPackage(selected.packageName);
|
||||||
|
request.putExtra(PluginUtils.EXTRA_PARAM_URI, Uri.fromFile(new File(resolved.path)));
|
||||||
|
request.putExtra(PluginUtils.EXTRA_PARAM_SONG_TITLE, resolved.title);
|
||||||
|
request.putExtra(PluginUtils.EXTRA_PARAM_SONG_ARTIST, resolved.artist);
|
||||||
|
request.putExtra(PluginUtils.EXTRA_PARAM_SONG_ALBUM, resolved.album);
|
||||||
|
startService(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
mLastRequestedCtx = null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||||
|
@Override
|
||||||
|
public void onCancel(DialogInterface dialog) {
|
||||||
|
mLastRequestedCtx = null;
|
||||||
|
}
|
||||||
|
}).create().show();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user