更新媒体播放期间 RemoteView 的视图

huangapple go评论60阅读模式
英文:

updating the views of a RemoteView during media playback

问题

以下是代码的翻译部分:

package com.app1.notificationtemplate;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.widget.RemoteViews;

import androidx.core.app.NotificationCompat;

public class NotificationGenerator {
    public static final int NOTIFICATION_ID_OPEN_ACTIVITY = 9;

    public static final String NOTIFY_PREVIOUS = "com.a.b.previous";
    public static final String NOTIFY_DELETE = "com.a.b.delete";
    public static final String NOTIFY_PAUSE = "com.a.b.pause";
    public static final String NOTIFY_PLAY = "com.a.b.play";
    public static final String NOTIFY_NEXT = "com.a.b.next";

    public static void openActivityNotificaton(Context context) {
        NotificationCompat.Builder nc = new NotificationCompat.Builder(context,
            MainActivity.channelID);
        NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        Intent notifyIntent = new Intent(context, MainActivity.class);
        notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        nc.setContentIntent(pendingIntent);
        nc.setSmallIcon(R.mipmap.ic_launcher);
        nc.setAutoCancel(true);
        nc.setContentTitle("Notification Demo");
        nc.setContentText("Click please");

        nm.notify(NOTIFICATION_ID_OPEN_ACTIVITY, nc.build());
    }

    public static void customBigNotification(Context context) {
        final RemoteViews expandedView = new RemoteViews(context.getPackageName(), R.layout.big_notification);
        NotificationCompat.Builder nc = new NotificationCompat.Builder(context, MainActivity.channelID);
        NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        Intent notifyIntent = new Intent(context, MainActivity.class);
        notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        nc.setContentIntent(pendingIntent);
        nc.setSmallIcon(R.drawable.play);
        nc.setAutoCancel(true);
        nc.setCustomBigContentView(expandedView);
        nc.setContentTitle("MusicPlayer");
        nc.setPriority(NotificationCompat.PRIORITY_MAX);
        nc.setContentText("Control AUdio");
        setListeners(expandedView, context);
        Notification notification = nc.build();
        notification.flags = NotificationCompat.FLAG_ONGOING_EVENT | NotificationCompat.FLAG_FOREGROUND_SERVICE
                | NotificationCompat.FLAG_NO_CLEAR | NotificationCompat.FLAG_BUBBLE;
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        nm.notify("newNotif", 1, nc.build());
    }

    public static void setListeners(RemoteViews view, Context context) {
        Intent previous = new Intent(NOTIFY_PREVIOUS);
        Intent delete = new Intent(NOTIFY_DELETE);
        Intent pause = new Intent(NOTIFY_PAUSE);
        Intent next = new Intent(NOTIFY_NEXT);
        Intent play = new Intent(NOTIFY_PLAY);

        PendingIntent pPrevious = PendingIntent.getBroadcast(context, 0,
            previous, PendingIntent.FLAG_UPDATE_CURRENT);
        view.setOnClickPendingIntent(R.id.btnPrevious, pPrevious);

        PendingIntent pDelete = PendingIntent.getBroadcast(context, 0,
            delete, PendingIntent.FLAG_UPDATE_CURRENT);
        view.setOnClickPendingIntent(R.id.btnDelete, pDelete);

        PendingIntent pPause = PendingIntent.getBroadcast(context, 0,
            pause, PendingIntent.FLAG_UPDATE_CURRENT);
        view.setOnClickPendingIntent(R.id.btnPause, pPause);

        PendingIntent pPlay = PendingIntent.getBroadcast(context, 0,
            play, PendingIntent.FLAG_UPDATE_CURRENT);
        view.setOnClickPendingIntent(R.id.btnPlay, pPlay);

        PendingIntent pNext = PendingIntent.getBroadcast(context, 0,
            next, PendingIntent.FLAG_UPDATE_CURRENT);
        view.setOnClickPendingIntent(R.id.btnNext, pNext);
    }
}

关于你的问题,以下是关于如何根据用户交互更新RemoteViews中的视图的建议:

  • 你可以使用RemoteViewssetImageViewResource()方法来更改按钮图像。例如,当用户从播放切换到暂停时,你可以调用setImageViewResource(R.id.btnPlay, R.drawable.pause)来设置暂停按钮的图像。
  • 要更新RemoteView中的文本,可以使用setTextViewText()方法。例如,你可以通过setTextViewText(R.id.text_song_name, "新歌曲名")来更新歌曲名称。

关于通知与服务之间的通信,除了使用广播(Broadcasts),还有其他选项,例如使用PendingIntentEventBus等。但广播在Android中是一种常见的方法,特别是用于在不同组件之间传递简单消息。

英文:

I'm using the following code to generate a mediaPlayer notification:

package com.app1.notificationtemplate;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.widget.RemoteViews;
import androidx.core.app.NotificationCompat;
public class NotificationGenerator {
public static final int  NOTIFICATION_ID_OPEN_ACTIVITY = 9;
public static final String NOTIFY_PREVIOUS = "com.a.b.previous";
public static final String NOTIFY_DELETE = "com.a.b.delete";
public static final String NOTIFY_PAUSE = "com.a.b.pause";
public static final String NOTIFY_PLAY = "com.a.b.play";
public static final String NOTIFY_NEXT = "com.a.b.next";
public static void openActivityNotificaton(Context context) {
NotificationCompat.Builder nc = new NotificationCompat.Builder(context,
MainActivity.channelID);
NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notifyIntent = new Intent(context, MainActivity.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
nc.setContentIntent(pendingIntent);
nc.setSmallIcon(R.mipmap.ic_launcher);
nc.setAutoCancel(true);
nc.setContentTitle("Notification Demo");
nc.setContentText("Click please");
nm.notify(NOTIFICATION_ID_OPEN_ACTIVITY, nc.build());
}
public static void customBigNotification(Context context){
final RemoteViews expandedView = new RemoteViews(context.getPackageName(), R.layout.big_notification);
NotificationCompat.Builder nc = new NotificationCompat.Builder(context, MainActivity.channelID);
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notifyIntent = new Intent(context, MainActivity.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
nc.setContentIntent(pendingIntent);
nc.setSmallIcon(R.drawable.play);
nc.setAutoCancel(true);
nc.setCustomBigContentView(expandedView);
nc.setContentTitle("MusicPlayer");
nc.setPriority(NotificationCompat.PRIORITY_MAX);
nc.setContentText("Control AUdio");
//expandedView.setTextViewText(R.id.text_song_name,"Adele");
setListeners(expandedView, context);
Notification notification = nc.build();
notification.flags = NotificationCompat.FLAG_ONGOING_EVENT|NotificationCompat.FLAG_FOREGROUND_SERVICE
| NotificationCompat.FLAG_NO_CLEAR|NotificationCompat.FLAG_BUBBLE ;
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
nm.notify("newNotif", 1, nc.build());
}
public  static void setListeners(RemoteViews view, Context context){
Intent previous = new Intent(NOTIFY_PREVIOUS);
Intent delete = new Intent(NOTIFY_DELETE);
Intent pause = new Intent(NOTIFY_PAUSE);
Intent next = new Intent(NOTIFY_NEXT);
Intent play = new Intent(NOTIFY_PLAY);
PendingIntent pPrevious = PendingIntent.getBroadcast(context, 0,
previous, PendingIntent.FLAG_UPDATE_CURRENT);
view.setOnClickPendingIntent(R.id.btnPrevious, pPrevious);
PendingIntent pDelete = PendingIntent.getBroadcast(context, 0,
delete, PendingIntent.FLAG_UPDATE_CURRENT);
view.setOnClickPendingIntent(R.id.btnDelete, pDelete);
PendingIntent pPause = PendingIntent.getBroadcast(context, 0,
pause, PendingIntent.FLAG_UPDATE_CURRENT);
view.setOnClickPendingIntent(R.id.btnPause, pPause);
PendingIntent pPlay = PendingIntent.getBroadcast(context, 0,
play, PendingIntent.FLAG_UPDATE_CURRENT);
view.setOnClickPendingIntent(R.id.btnPlay, pPlay);
PendingIntent pNext = PendingIntent.getBroadcast(context, 0,
next, PendingIntent.FLAG_UPDATE_CURRENT);
view.setOnClickPendingIntent(R.id.btnNext, pNext);
}
}    

I have custom notification views (RemoteViews) setup for the notification as well.

but, when I click play, I'm not sure how to update the play view to a pause view. Currently, I'm just setting the visibility of the play button to gone. But, is turning on and off the visibility turnwise the only option? And how do I do that anyways(the tutorial I've followed doesn't really show this). But, I think it'd be better if we could replace the image in the button which would avoid possible blinking or flickering. I've also gotta update the Remote view's artist and song Title name, but have no idea to do so. Please tell me how to update views in the RemoteView according to user interaction

Also, to communicate from the notification to the Service is using Broadcasts the only option? What other options do I have?

答案1

得分: 1

你需要使用更新后的数据创建一个新的通知,并使用 NotificationManager 进行更新。无需再次启动服务。你已经有一个正在运行的前台服务,你只需通过 notify 更新用户界面。

因此,在你的广播接收器中,根据通知内部点击的视图调用 openActivityNotificaton() 函数并提供更新后的数据。你可以为每个视图点击设置一个唯一的操作,然后相应地更新通知。我已经测试过,这不会导致闪烁,通知会平稳地更新。

你的接收器的代码应该类似于这样:

const val NOTIFICATION_TITLE_INTENT_ACTION = "notification_title_intent_action"
const val NOTIFICATION_ARROW_INTENT_ACTION = "notification_arrow_intent_action"

class NotificationInteractionReceiver : BroadcastReceiver() {

    private lateinit var notificationsFactory: NotificationFactory

    override fun onReceive(context: Context, intent: Intent) {
        notificationsFactory = NotificationFactory(context)

        // 根据点击的按钮更新标题
        val newTitle = when (intent.action) {
            NOTIFICATION_TITLE_INTENT_ACTION -> "标题被点击"
            else -> "箭头被点击"
        }

        // 将新标题传递给负责显示通知的类
        notificationsFactory.showNotification(context, newTitle)
    }

    companion object {
        fun getIntent(context: Context, action: String): Intent {
            val intent = Intent(context, NotificationInteractionReceiver::class.java).apply {
                flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
            }

            intent.action = action

            return intent
        }
    }
}

请注意,上述代码是针对你提供的 Kotlin 代码进行的翻译和调整。

英文:

You need to create a new notification with the updated data and use NotificationManager to update it. No need to start service again. You have a running foreground service, all you have to do is update your UI via notify.

So in your Broadcast Receiver call your openActivityNotificaton() function with updated data, according to what view was clicked inside the notification. You can have one Receiver with a unique action for each view click, and update notification accordingly. I tested and it does not cause a blink, the notification is updated smoothly.

The code for your Receiver would be something like this:

const val NOTIFICATION_TITLE_INTENT_ACTION = "notification_title_intent_action"
const val NOTIFICATION_ARROW_INTENT_ACTION = "notification_arrow_intent_action"
class NotificationInteractionReceiver : BroadcastReceiver() {
private lateinit var notificationsFactory: NotificationFactory
override fun onReceive(context: Context, intent: Intent) {
notificationsFactory = NotificationFactory(context)
// Update title according to what button was clicked
val newTitle = when (intent.action) {
NOTIFICATION_TITLE_INTENT_ACTION -> "title clicked"
else -> "arrow clicked"
}
// Pass new title to class responsible for showing notification
notificationsFactory.showNotification(context, s)
}
companion object {
fun getIntent(context: Context, action: String): Intent {
val intent = Intent(context, NotificationInteractionReceiver::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
intent.action = action
return intent
}
}
}

huangapple
  • 本文由 发表于 2020年9月13日 17:30:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/63869193.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定