initial shortcut support

This commit is contained in:
Adrian Ulrich 2018-10-26 20:20:15 +02:00
parent e37225bb91
commit 62e498a1a9
6 changed files with 137 additions and 2 deletions

View File

@ -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"

View File

@ -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);
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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>