initial shortcut support
This commit is contained in:
parent
e37225bb91
commit
62e498a1a9
@ -31,6 +31,8 @@ THE SOFTWARE.
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<!-- This is needed for isWiredHeadsetOn() to work in some cases. (bug?) -->
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<!-- Playlist shortcuts -->
|
||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:resizeableActivity="true"
|
||||
|
@ -616,6 +616,7 @@ public class LibraryActivity
|
||||
private static final int CTX_MENU_OPEN_EXTERNAL = 10;
|
||||
private static final int CTX_MENU_PLUGINS = 11;
|
||||
private static final int CTX_MENU_SHOW_DETAILS = 12;
|
||||
private static final int CTX_MENU_ADD_TO_HOMESCREEN = 13;
|
||||
|
||||
/**
|
||||
* Creates a context menu for an adapter row.
|
||||
@ -651,6 +652,8 @@ public class LibraryActivity
|
||||
if (type == MediaUtils.TYPE_SONG) {
|
||||
menu.add(0, CTX_MENU_SHOW_DETAILS, 0, R.string.details).setIntent(rowData);
|
||||
}
|
||||
if (type >= MediaUtils.TYPE_ARTIST && type <= MediaUtils.TYPE_COMPOSER && type != MediaUtils.TYPE_SONG)
|
||||
menu.add(0, CTX_MENU_ADD_TO_HOMESCREEN, 0, R.string.add_to_homescreen).setIntent(rowData);
|
||||
if (type == MediaUtils.TYPE_ALBUM || type == MediaUtils.TYPE_SONG)
|
||||
menu.add(0, CTX_MENU_MORE_FROM_ARTIST, 0, R.string.more_from_artist).setIntent(rowData);
|
||||
if (type == MediaUtils.TYPE_SONG) {
|
||||
@ -762,11 +765,19 @@ public class LibraryActivity
|
||||
setLimiter(MediaUtils.TYPE_ALBUM, "_id=" + intent.getLongExtra(LibraryAdapter.DATA_ID, LibraryAdapter.INVALID_ID));
|
||||
updateLimiterViews();
|
||||
break;
|
||||
case CTX_MENU_ADD_TO_PLAYLIST:
|
||||
case CTX_MENU_ADD_TO_PLAYLIST: {
|
||||
long id = intent.getLongExtra("id", LibraryAdapter.INVALID_ID);
|
||||
PlaylistDialog plDialog = PlaylistDialog.newInstance(this, intent, (id == LibraryAdapter.HEADER_ID ? mCurrentAdapter : null));
|
||||
plDialog.show(getFragmentManager(), "PlaylistDialog");
|
||||
break;
|
||||
}
|
||||
case CTX_MENU_ADD_TO_HOMESCREEN: {
|
||||
int type = intent.getIntExtra(LibraryAdapter.DATA_TYPE, MediaUtils.TYPE_INVALID);
|
||||
long id = intent.getLongExtra(LibraryAdapter.DATA_ID, LibraryAdapter.INVALID_ID);
|
||||
String label = intent.getStringExtra(LibraryAdapter.DATA_TITLE);
|
||||
SystemUtils.installLauncherShortcut(this, label, type, id);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
@ -167,6 +167,10 @@ public final class PlaybackService extends Service
|
||||
* Flushes the queue, switches to random mode and starts playing.
|
||||
*/
|
||||
public static final String ACTION_RANDOM_MIX_AUTOPLAY = "ch.blinkenlights.android.vanilla.action.RANDOM_MIX_AUTOPLAY";
|
||||
/**
|
||||
* Flushes the queue and plays everything of the passed type/id combination.
|
||||
*/
|
||||
public static final String ACTION_FROM_TYPE_ID_AUTOPLAY = "ch.blinkenlights.android.vanilla.action.FROM_TYPE_ID_AUTOPLAY";
|
||||
/**
|
||||
* Change the shuffle mode.
|
||||
*/
|
||||
@ -600,6 +604,13 @@ public final class PlaybackService extends Service
|
||||
// We therefore send a GO message to the same queue, so it will get handled as
|
||||
// soon as the queue is ready.
|
||||
mHandler.sendEmptyMessage(MSG_CALL_GO);
|
||||
} else if (ACTION_FROM_TYPE_ID_AUTOPLAY.equals(action)) {
|
||||
int type = intent.getIntExtra(LibraryAdapter.DATA_TYPE, MediaUtils.TYPE_INVALID);
|
||||
long id = intent.getLongExtra(LibraryAdapter.DATA_ID, LibraryAdapter.INVALID_ID);
|
||||
QueryTask query = MediaUtils.buildQuery(type, id, Song.FILLED_PROJECTION, null);
|
||||
// Flush the queue and start playing:
|
||||
query.mode = SongTimeline.MODE_PLAY;
|
||||
addSongs(query);
|
||||
} else if (ACTION_CLOSE_NOTIFICATION.equals(action)) {
|
||||
mForceNotificationVisible = false;
|
||||
pause();
|
||||
|
@ -57,11 +57,22 @@ public class ShortcutPseudoActivity extends Activity {
|
||||
case PlaybackService.ACTION_PREVIOUS_SONG:
|
||||
case PlaybackService.ACTION_PREVIOUS_SONG_AUTOPLAY:
|
||||
case PlaybackService.ACTION_CYCLE_SHUFFLE:
|
||||
case PlaybackService.ACTION_CYCLE_REPEAT:
|
||||
case PlaybackService.ACTION_CYCLE_REPEAT: {
|
||||
Intent intent = new Intent(this, PlaybackService.class);
|
||||
intent.setAction(action);
|
||||
startService(intent);
|
||||
break;
|
||||
}
|
||||
case PlaybackService.ACTION_FROM_TYPE_ID_AUTOPLAY: {
|
||||
// From pinned shortcuts: Same as other actions, but this
|
||||
// includes some extras.
|
||||
Intent intent = new Intent(this, PlaybackService.class);
|
||||
intent.setAction(action);
|
||||
intent.putExtra(LibraryAdapter.DATA_TYPE, getIntent().getIntExtra(LibraryAdapter.DATA_TYPE, MediaUtils.TYPE_INVALID));
|
||||
intent.putExtra(LibraryAdapter.DATA_ID, getIntent().getLongExtra(LibraryAdapter.DATA_ID, LibraryAdapter.INVALID_ID));
|
||||
startService(intent);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new IllegalArgumentException("No such action: " + action);
|
||||
}
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Adrian Ulrich <adrian@blinkenlights.ch>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ch.blinkenlights.android.vanilla;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ShortcutManager;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Icon;
|
||||
|
||||
|
||||
/**
|
||||
* Provides some static System-related utility functions.
|
||||
*/
|
||||
public class SystemUtils {
|
||||
|
||||
/**
|
||||
* Installs (or prompts user to install) a shortcut launcher pointing to the given type and id
|
||||
* combination. Launching the shortcut will cause vanilla to play the type / id combination.
|
||||
*
|
||||
* @param context the context to use.
|
||||
* @param label the label of the shortcut.
|
||||
* @param type the media type of the passed in id.
|
||||
* @param id an id of a media type
|
||||
*/
|
||||
public static void installLauncherShortcut(Context context, String label, int type, long id) {
|
||||
Intent shortcut = new Intent(context, ShortcutPseudoActivity.class);
|
||||
shortcut.setAction(PlaybackService.ACTION_FROM_TYPE_ID_AUTOPLAY);
|
||||
shortcut.putExtra(LibraryAdapter.DATA_TYPE, type);
|
||||
shortcut.putExtra(LibraryAdapter.DATA_ID, id);
|
||||
|
||||
Bitmap cover = null;
|
||||
Song song = MediaUtils.getSongByTypeId(context, type, id);
|
||||
if (song != null) {
|
||||
cover = song.getSmallCover(context);
|
||||
}
|
||||
if (cover == null) {
|
||||
cover = BitmapFactory.decodeResource(context.getResources(), R.drawable.fallback_cover);
|
||||
}
|
||||
|
||||
// TODO: Support pre api 26.
|
||||
installShortcut(context, label, cover, shortcut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to install a shortcut. This is only available on API >= 26.
|
||||
*
|
||||
* @param context the context to use.
|
||||
* @param label the label to use for this shortcut.
|
||||
* @param cover the icon to use for this shortcut.
|
||||
* @param intent intent launched by the shortcut.
|
||||
*
|
||||
* @return true if the shortcut MAY have been created.
|
||||
*/
|
||||
private static boolean installShortcut(Context context, String label, Bitmap cover, Intent intent) {
|
||||
ShortcutManager manager = context.getSystemService(ShortcutManager.class);
|
||||
if (manager == null || !manager.isRequestPinShortcutSupported())
|
||||
return false;
|
||||
|
||||
String uniqueId = "vanilla:shortcut:" + System.currentTimeMillis();
|
||||
ShortcutInfo pin = new ShortcutInfo.Builder(context, uniqueId)
|
||||
.setIntent(intent)
|
||||
.setShortLabel(label)
|
||||
.setIcon(Icon.createWithBitmap(cover))
|
||||
.build();
|
||||
|
||||
manager.requestPinShortcut(pin, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Test this on kitkat.
|
||||
private static boolean installShortcutLegacy(Context context, String label, Intent intent) {
|
||||
Intent add = new Intent();
|
||||
add.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
|
||||
add.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
|
||||
add.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
|
||||
Intent.ShortcutIconResource.fromContext(context, R.drawable.repeat_active));
|
||||
add.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
|
||||
context.sendBroadcast(add);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -68,6 +68,7 @@ THE SOFTWARE.
|
||||
<string name="rename">Rename</string>
|
||||
<string name="save_as_playlist">Save as playlist…</string>
|
||||
<string name="add_to_playlist">Add to playlist…</string>
|
||||
<string name="add_to_homescreen">Add to homescreen…</string>
|
||||
<string name="add_to_favorites">Add to favorites</string>
|
||||
<string name="remove_from_favorites">Remove from favorites</string>
|
||||
<string name="playlist_favorites">Favorites</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user