Switch to appcompat notifications
I really liked our own notification styles, but on Android 11, it just starts to look very alien.
@ -27,6 +27,7 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
|
implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
|
||||||
|
implementation 'androidx.media:media:1.2.1'
|
||||||
implementation 'com.google.android.material:material:1.0.0'
|
implementation 'com.google.android.material:material:1.0.0'
|
||||||
implementation 'junit:junit:4.12'
|
implementation 'junit:junit:4.12'
|
||||||
compileOnly 'androidx.annotation:annotation:1.0.0'
|
compileOnly 'androidx.annotation:annotation:1.0.0'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 Adrian Ulrich <adrian@blinkenlights.ch>
|
* Copyright (C) 2017-2021 Adrian Ulrich <adrian@blinkenlights.ch>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -21,7 +21,10 @@ import android.app.Notification;
|
|||||||
import android.app.NotificationChannel;
|
import android.app.NotificationChannel;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
|
||||||
|
|
||||||
public class NotificationHelper {
|
public class NotificationHelper {
|
||||||
/**
|
/**
|
||||||
@ -51,27 +54,12 @@ public class NotificationHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new Notification.Builder.
|
* Returns a new NotificationCompat.Builder.
|
||||||
*
|
*
|
||||||
* @param context the context to use
|
* @param context the context to use
|
||||||
*/
|
*/
|
||||||
public Notification.Builder getNewBuilder(Context context) {
|
public NotificationCompat.Builder getNewBuilder(Context context) {
|
||||||
Notification.Builder builder;
|
return new NotificationCompat.Builder(context, mChannelId);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
builder = new Notification.Builder(context, mChannelId);
|
|
||||||
} else {
|
|
||||||
builder = new Notification.Builder(context);
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retruns a new Notification.
|
|
||||||
*
|
|
||||||
* @param context the context to use.
|
|
||||||
*/
|
|
||||||
public Notification getNewNotification(Context context) {
|
|
||||||
return getNewBuilder(context).getNotification(); // build() is API16.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,8 +57,8 @@ import android.os.Process;
|
|||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.RemoteViews;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
import java.lang.Math;
|
import java.lang.Math;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
@ -178,10 +178,6 @@ public final class PlaybackService extends Service
|
|||||||
* Change the repeat mode.
|
* Change the repeat mode.
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_CYCLE_REPEAT = "ch.blinkenlights.android.vanilla.CYCLE_REPEAT";
|
public static final String ACTION_CYCLE_REPEAT = "ch.blinkenlights.android.vanilla.CYCLE_REPEAT";
|
||||||
/**
|
|
||||||
* Pause music and hide the notification.
|
|
||||||
*/
|
|
||||||
public static final String ACTION_CLOSE_NOTIFICATION = "ch.blinkenlights.android.vanilla.CLOSE_NOTIFICATION";
|
|
||||||
/**
|
/**
|
||||||
* Whether we should create a foreground notification as early as possible.
|
* Whether we should create a foreground notification as early as possible.
|
||||||
*/
|
*/
|
||||||
@ -309,10 +305,6 @@ public final class PlaybackService extends Service
|
|||||||
* Behaviour of the notification
|
* Behaviour of the notification
|
||||||
*/
|
*/
|
||||||
private int mNotificationVisibility;
|
private int mNotificationVisibility;
|
||||||
/**
|
|
||||||
* If true, create a notification with ticker text or heads up display
|
|
||||||
*/
|
|
||||||
private boolean mNotificationNag;
|
|
||||||
/**
|
/**
|
||||||
* If true, audio will not be played through the speaker.
|
* If true, audio will not be played through the speaker.
|
||||||
*/
|
*/
|
||||||
@ -463,7 +455,6 @@ public final class PlaybackService extends Service
|
|||||||
SharedPreferences settings = SharedPrefHelper.getSettings(this);
|
SharedPreferences settings = SharedPrefHelper.getSettings(this);
|
||||||
settings.registerOnSharedPreferenceChangeListener(this);
|
settings.registerOnSharedPreferenceChangeListener(this);
|
||||||
mNotificationVisibility = Integer.parseInt(settings.getString(PrefKeys.NOTIFICATION_VISIBILITY, PrefDefaults.NOTIFICATION_VISIBILITY));
|
mNotificationVisibility = Integer.parseInt(settings.getString(PrefKeys.NOTIFICATION_VISIBILITY, PrefDefaults.NOTIFICATION_VISIBILITY));
|
||||||
mNotificationNag = settings.getBoolean(PrefKeys.NOTIFICATION_NAG, PrefDefaults.NOTIFICATION_NAG);
|
|
||||||
mScrobble = settings.getBoolean(PrefKeys.SCROBBLE, PrefDefaults.SCROBBLE);
|
mScrobble = settings.getBoolean(PrefKeys.SCROBBLE, PrefDefaults.SCROBBLE);
|
||||||
mIdleTimeout = settings.getBoolean(PrefKeys.USE_IDLE_TIMEOUT, PrefDefaults.USE_IDLE_TIMEOUT) ? settings.getInt(PrefKeys.IDLE_TIMEOUT, PrefDefaults.IDLE_TIMEOUT) : 0;
|
mIdleTimeout = settings.getBoolean(PrefKeys.USE_IDLE_TIMEOUT, PrefDefaults.USE_IDLE_TIMEOUT) ? settings.getInt(PrefKeys.IDLE_TIMEOUT, PrefDefaults.IDLE_TIMEOUT) : 0;
|
||||||
|
|
||||||
@ -607,11 +598,6 @@ public final class PlaybackService extends Service
|
|||||||
// Flush the queue and start playing:
|
// Flush the queue and start playing:
|
||||||
query.mode = SongTimeline.MODE_PLAY;
|
query.mode = SongTimeline.MODE_PLAY;
|
||||||
addSongs(query);
|
addSongs(query);
|
||||||
} else if (ACTION_CLOSE_NOTIFICATION.equals(action)) {
|
|
||||||
mForceNotificationVisible = false;
|
|
||||||
pause();
|
|
||||||
stopForeground(true); // sometimes required to clear notification
|
|
||||||
updateNotification();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -890,9 +876,6 @@ public final class PlaybackService extends Service
|
|||||||
// mode.
|
// mode.
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
updateNotification();
|
updateNotification();
|
||||||
} else if (PrefKeys.NOTIFICATION_NAG.equals(key)) {
|
|
||||||
mNotificationNag = settings.getBoolean(PrefKeys.NOTIFICATION_NAG, PrefDefaults.NOTIFICATION_NAG);
|
|
||||||
// no need to update notification: happens on next event
|
|
||||||
} else if (PrefKeys.SCROBBLE.equals(key)) {
|
} else if (PrefKeys.SCROBBLE.equals(key)) {
|
||||||
mScrobble = settings.getBoolean(PrefKeys.SCROBBLE, PrefDefaults.SCROBBLE);
|
mScrobble = settings.getBoolean(PrefKeys.SCROBBLE, PrefDefaults.SCROBBLE);
|
||||||
} else if (PrefKeys.MEDIA_BUTTON.equals(key) || PrefKeys.MEDIA_BUTTON_BEEP.equals(key)) {
|
} else if (PrefKeys.MEDIA_BUTTON.equals(key) || PrefKeys.MEDIA_BUTTON_BEEP.equals(key)) {
|
||||||
@ -2143,81 +2126,38 @@ public final class PlaybackService extends Service
|
|||||||
*/
|
*/
|
||||||
public Notification createNotification(Song song, int state, int mode)
|
public Notification createNotification(Song song, int state, int mode)
|
||||||
{
|
{
|
||||||
boolean playing = (state & FLAG_PLAYING) != 0;
|
final boolean playing = (state & FLAG_PLAYING) != 0;
|
||||||
|
final Bitmap cover = song.getCover(this);
|
||||||
RemoteViews views = new RemoteViews(getPackageName(), R.layout.notification);
|
|
||||||
RemoteViews expanded = new RemoteViews(getPackageName(), R.layout.notification_expanded);
|
|
||||||
|
|
||||||
Bitmap cover = song.getCover(this);
|
|
||||||
if (cover == null) {
|
|
||||||
views.setImageViewResource(R.id.cover, R.drawable.fallback_cover);
|
|
||||||
expanded.setImageViewResource(R.id.cover, R.drawable.fallback_cover_large);
|
|
||||||
} else {
|
|
||||||
views.setImageViewBitmap(R.id.cover, cover);
|
|
||||||
expanded.setImageViewBitmap(R.id.cover, cover);
|
|
||||||
}
|
|
||||||
|
|
||||||
int playButton = ThemeHelper.getPlayButtonResource(playing);
|
|
||||||
|
|
||||||
views.setImageViewResource(R.id.play_pause, playButton);
|
|
||||||
expanded.setImageViewResource(R.id.play_pause, playButton);
|
|
||||||
|
|
||||||
ComponentName service = new ComponentName(this, PlaybackService.class);
|
ComponentName service = new ComponentName(this, PlaybackService.class);
|
||||||
|
|
||||||
Intent previous = new Intent(PlaybackService.ACTION_PREVIOUS_SONG);
|
int playButton = ThemeHelper.getPlayButtonResource(playing);
|
||||||
previous.setComponent(service);
|
|
||||||
views.setOnClickPendingIntent(R.id.previous, PendingIntent.getService(this, 0, previous, 0));
|
|
||||||
expanded.setOnClickPendingIntent(R.id.previous, PendingIntent.getService(this, 0, previous, 0));
|
|
||||||
|
|
||||||
Intent playPause = new Intent(PlaybackService.ACTION_TOGGLE_PLAYBACK_NOTIFICATION);
|
Intent playPause = new Intent(PlaybackService.ACTION_TOGGLE_PLAYBACK_NOTIFICATION);
|
||||||
playPause.setComponent(service);
|
playPause.setComponent(service);
|
||||||
views.setOnClickPendingIntent(R.id.play_pause, PendingIntent.getService(this, 0, playPause, 0));
|
|
||||||
expanded.setOnClickPendingIntent(R.id.play_pause, PendingIntent.getService(this, 0, playPause, 0));
|
|
||||||
|
|
||||||
Intent next = new Intent(PlaybackService.ACTION_NEXT_SONG);
|
Intent next = new Intent(PlaybackService.ACTION_NEXT_SONG);
|
||||||
next.setComponent(service);
|
next.setComponent(service);
|
||||||
views.setOnClickPendingIntent(R.id.next, PendingIntent.getService(this, 0, next, 0));
|
|
||||||
expanded.setOnClickPendingIntent(R.id.next, PendingIntent.getService(this, 0, next, 0));
|
|
||||||
|
|
||||||
int closeButtonVisibility = (mode == VISIBILITY_WHEN_PLAYING) ? View.VISIBLE : View.INVISIBLE;
|
Intent previous = new Intent(PlaybackService.ACTION_PREVIOUS_SONG);
|
||||||
Intent close = new Intent(PlaybackService.ACTION_CLOSE_NOTIFICATION);
|
previous.setComponent(service);
|
||||||
close.setComponent(service);
|
|
||||||
views.setOnClickPendingIntent(R.id.close, PendingIntent.getService(this, 0, close, 0));
|
|
||||||
views.setViewVisibility(R.id.close, closeButtonVisibility);
|
|
||||||
expanded.setOnClickPendingIntent(R.id.close, PendingIntent.getService(this, 0, close, 0));
|
|
||||||
expanded.setViewVisibility(R.id.close, closeButtonVisibility);
|
|
||||||
|
|
||||||
views.setTextViewText(R.id.title, song.title);
|
Notification n = mNotificationHelper.getNewBuilder(getApplicationContext())
|
||||||
views.setTextViewText(R.id.artist, song.artist);
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
expanded.setTextViewText(R.id.title, song.title);
|
.setSmallIcon(R.drawable.status_icon)
|
||||||
expanded.setTextViewText(R.id.album, song.album);
|
.setLargeIcon(cover)
|
||||||
expanded.setTextViewText(R.id.artist, song.artist);
|
.setContentTitle(song.title)
|
||||||
|
.setContentText(song.album)
|
||||||
Notification notification = mNotificationHelper.getNewNotification(getApplicationContext());
|
.setSubText(song.artist)
|
||||||
notification.contentView = views;
|
.setContentIntent(mNotificationAction)
|
||||||
notification.icon = R.drawable.status_icon;
|
.addAction(new NotificationCompat.Action(R.drawable.previous,
|
||||||
notification.flags |= Notification.FLAG_ONGOING_EVENT;
|
getString(R.string.previous_song), PendingIntent.getService(this, 0, previous, 0)))
|
||||||
notification.contentIntent = mNotificationAction;
|
.addAction(new NotificationCompat.Action(playButton,
|
||||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
getString(R.string.play_pause), PendingIntent.getService(this, 0, playPause, 0)))
|
||||||
// expanded view is available since 4.1
|
.addAction(new NotificationCompat.Action(R.drawable.next,
|
||||||
notification.bigContentView = expanded;
|
getString(R.string.next_song), PendingIntent.getService(this, 0, next, 0)))
|
||||||
// 4.1 also knows about notification priorities
|
.setStyle(new androidx.media.app.NotificationCompat.MediaStyle())
|
||||||
// HIGH is one higher than the default.
|
.build();
|
||||||
notification.priority = Notification.PRIORITY_HIGH;
|
return n;
|
||||||
}
|
|
||||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
notification.visibility = Notification.VISIBILITY_PUBLIC;
|
|
||||||
}
|
|
||||||
if(mNotificationNag) {
|
|
||||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
notification.priority = Notification.PRIORITY_MAX;
|
|
||||||
notification.vibrate = new long[0]; // needed to get headsup
|
|
||||||
} else {
|
|
||||||
notification.tickerText = song.title + " - " + song.artist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return notification;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onAudioFocusChange(int type)
|
public void onAudioFocusChange(int type)
|
||||||
|
@ -52,7 +52,6 @@ public class PrefKeys {
|
|||||||
public static final String MEDIA_BUTTON_BEEP = "media_button_beep";
|
public static final String MEDIA_BUTTON_BEEP = "media_button_beep";
|
||||||
public static final String NOTIFICATION_ACTION = "notification_action";
|
public static final String NOTIFICATION_ACTION = "notification_action";
|
||||||
public static final String NOTIFICATION_VISIBILITY = "notification_visibility";
|
public static final String NOTIFICATION_VISIBILITY = "notification_visibility";
|
||||||
public static final String NOTIFICATION_NAG = "notification_nag";
|
|
||||||
public static final String PLAYBACK_ON_STARTUP = "playback_on_startup";
|
public static final String PLAYBACK_ON_STARTUP = "playback_on_startup";
|
||||||
public static final String SCROBBLE = "scrobble";
|
public static final String SCROBBLE = "scrobble";
|
||||||
public static final String SHAKE_ACTION = "shake_action";
|
public static final String SHAKE_ACTION = "shake_action";
|
||||||
|
Before Width: | Height: | Size: 251 B |
Before Width: | Height: | Size: 500 B |
Before Width: | Height: | Size: 166 B |
Before Width: | Height: | Size: 369 B |
Before Width: | Height: | Size: 305 B |
Before Width: | Height: | Size: 687 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 883 B |
@ -1,99 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright (C) 2012 Christopher Eby <kreed@kreed.org>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
-->
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="64dp"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
>
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/cover"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:layout_width="64dp"
|
|
||||||
android:layout_height="64dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:contentDescription="@string/cover_art" />
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="0px"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:orientation="vertical">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="marquee" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/artist"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.Material.Notification.Line2"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="marquee" />
|
|
||||||
</LinearLayout>
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/previous"
|
|
||||||
android:paddingTop="5dp"
|
|
||||||
android:paddingBottom="5dp"
|
|
||||||
android:layout_height="42dp"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/widget_previous"
|
|
||||||
android:contentDescription="@string/previous_song" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/play_pause"
|
|
||||||
android:paddingTop="5dp"
|
|
||||||
android:paddingBottom="5dp"
|
|
||||||
android:layout_height="42dp"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/widget_play"
|
|
||||||
android:contentDescription="@string/play_pause" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/next"
|
|
||||||
android:paddingTop="5dp"
|
|
||||||
android:paddingBottom="5dp"
|
|
||||||
android:layout_height="42dp"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/widget_next"
|
|
||||||
android:contentDescription="@string/next_song" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/close"
|
|
||||||
android:padding="5dp"
|
|
||||||
android:layout_height="42dp"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/notification_close_dark"
|
|
||||||
android:contentDescription="@string/close_notification" />
|
|
||||||
</LinearLayout>
|
|
@ -1,130 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright (C) 2014 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/>.
|
|
||||||
-->
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/cover"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:layout_width="128dp"
|
|
||||||
android:layout_height="128dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:contentDescription="@string/cover_art" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:layout_width="0px"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:orientation="vertical">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="marquee" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/artist"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.Material.Notification.Line2"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="marquee" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/album"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.Material.Notification.Line2"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="marquee" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/close"
|
|
||||||
android:padding="5dp"
|
|
||||||
android:layout_width="32dp"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:src="@drawable/notification_close_dark"
|
|
||||||
android:contentDescription="@string/close_notification" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!-- start controll buttons -->
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/previous"
|
|
||||||
android:paddingTop="5dp"
|
|
||||||
android:paddingBottom="5dp"
|
|
||||||
android:layout_height="42dp"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/widget_previous"
|
|
||||||
android:contentDescription="@string/next_song" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/play_pause"
|
|
||||||
android:paddingTop="5dp"
|
|
||||||
android:paddingBottom="5dp"
|
|
||||||
android:layout_height="42dp"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/widget_play"
|
|
||||||
android:contentDescription="@string/play_pause" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/next"
|
|
||||||
android:paddingTop="5dp"
|
|
||||||
android:paddingBottom="5dp"
|
|
||||||
android:layout_height="42dp"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/widget_next"
|
|
||||||
android:contentDescription="@string/next_song" />
|
|
||||||
</LinearLayout>
|
|
||||||
<!-- end controll buttons -->
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,99 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright (C) 2012 Christopher Eby <kreed@kreed.org>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
-->
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/cover"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:layout_width="64dip"
|
|
||||||
android:layout_height="64dip"
|
|
||||||
android:layout_marginRight="8dip"
|
|
||||||
android:contentDescription="@string/cover_art" />
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="0px"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:orientation="vertical">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent.Title"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="marquee" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/artist"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="marquee" />
|
|
||||||
</LinearLayout>
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/previous"
|
|
||||||
android:paddingTop="5dip"
|
|
||||||
android:paddingBottom="5dip"
|
|
||||||
android:layout_height="42dip"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/widget_previous"
|
|
||||||
android:contentDescription="@string/previous_song" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/play_pause"
|
|
||||||
android:paddingTop="5dip"
|
|
||||||
android:paddingBottom="5dip"
|
|
||||||
android:layout_height="42dip"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/widget_play"
|
|
||||||
android:contentDescription="@string/play_pause" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/next"
|
|
||||||
android:paddingTop="5dip"
|
|
||||||
android:paddingBottom="5dip"
|
|
||||||
android:layout_height="42dip"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/widget_next"
|
|
||||||
android:contentDescription="@string/next_song" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/close"
|
|
||||||
android:padding="5dip"
|
|
||||||
android:layout_height="42dip"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/notification_close"
|
|
||||||
android:contentDescription="@string/close_notification" />
|
|
||||||
</LinearLayout>
|
|
@ -1,130 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright (C) 2014 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/>.
|
|
||||||
-->
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/cover"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:layout_width="128dip"
|
|
||||||
android:layout_height="128dip"
|
|
||||||
android:layout_marginRight="8dip"
|
|
||||||
android:contentDescription="@string/cover_art" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_marginTop="4dip"
|
|
||||||
android:layout_width="0px"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:orientation="vertical">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent.Title"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="marquee" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/artist"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="marquee" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/album"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="marquee" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/close"
|
|
||||||
android:padding="5dip"
|
|
||||||
android:layout_width="32dp"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:src="@drawable/notification_close"
|
|
||||||
android:contentDescription="@string/close_notification" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!-- start controll buttons -->
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/previous"
|
|
||||||
android:paddingTop="5dip"
|
|
||||||
android:paddingBottom="5dip"
|
|
||||||
android:layout_height="42dip"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/previous"
|
|
||||||
android:contentDescription="@string/next_song" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/play_pause"
|
|
||||||
android:paddingTop="5dip"
|
|
||||||
android:paddingBottom="5dip"
|
|
||||||
android:layout_height="42dip"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/play"
|
|
||||||
android:contentDescription="@string/play_pause" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/next"
|
|
||||||
android:paddingTop="5dip"
|
|
||||||
android:paddingBottom="5dip"
|
|
||||||
android:layout_height="42dip"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/next"
|
|
||||||
android:contentDescription="@string/next_song" />
|
|
||||||
</LinearLayout>
|
|
||||||
<!-- end controll buttons -->
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -219,9 +219,6 @@ THE SOFTWARE.
|
|||||||
<string name="notification_visibility_title">Notification visibility</string>
|
<string name="notification_visibility_title">Notification visibility</string>
|
||||||
<string name="notification_action_title">Notification action</string>
|
<string name="notification_action_title">Notification action</string>
|
||||||
|
|
||||||
<string name="notification_nag">Very verbose notification</string>
|
|
||||||
<string name="notification_nag_summary">Announce track changes using a \'Heads-Up-Notification\'</string>
|
|
||||||
|
|
||||||
<string name="playback_screen">Playback screen</string>
|
<string name="playback_screen">Playback screen</string>
|
||||||
<string name="playback_on_startup_title">Open on startup</string>
|
<string name="playback_on_startup_title">Open on startup</string>
|
||||||
<string name="playback_on_startup_summary">Open playback view on startup</string>
|
<string name="playback_on_startup_summary">Open playback view on startup</string>
|
||||||
|
@ -35,9 +35,4 @@ THE SOFTWARE.
|
|||||||
android:entries="@array/notification_action_entries"
|
android:entries="@array/notification_action_entries"
|
||||||
android:entryValues="@array/entry_values"
|
android:entryValues="@array/entry_values"
|
||||||
android:defaultValue="0" />
|
android:defaultValue="0" />
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="notification_nag"
|
|
||||||
android:title="@string/notification_nag"
|
|
||||||
android:defaultValue="false"
|
|
||||||
android:summary="@string/notification_nag_summary" />
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|