RemoteViews一 仿qq音乐自定义通知栏实现快捷切换歌曲
RemoteViews一 仿qq音乐自定义通知栏实现快捷切换歌曲
定义:RemoteViews表示一种view结构,它可以在其他进程中显示,由于它在其它进程中,为了能够更新它的界面,RemoteViews提供了一组基础的操作用于更新它的界面。
本文大概需要5分钟,从以下三方面讲解。文章底部有总结,急性子可以直接看总结,快速掌握知识点。
- 一、成果展示
- 二、代码讲解
- 三、总结
一、成果展示
仿照qq音乐通知栏切换歌曲(缺图,只能以文字代替)
点击下一曲后,执行相应的代码(以相应Toast代替)
后台启动相应的service执行切换歌曲和暂停等逻辑
二、代码讲解
package android.com.remoteviews; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.RemoteViews; import static android.R.string.no; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initRemoteViews(); } private void initRemoteViews () { Notification notification = new Notification(); notification.icon = R.mipmap.ic_launcher; notification.tickerText = "remoteviewTest"; notification.when = System.currentTimeMillis(); notification.flags = Notification.FLAG_AUTO_CANCEL; Intent intent = new Intent(this, SecondActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_remoteviews); remoteViews.setTextViewText(R.id.tv_remote, "暧昧"); remoteViews.setImageViewResource(R.id.iv_remote,R.mipmap.ic_launcher); Intent changeService = new Intent(this, ChangeService.class); changeService.putExtra("data","下一曲"); PendingIntent changeIntent = PendingIntent.getService(this, 1, changeService, PendingIntent.FLAG_UPDATE_CURRENT); changeService.putExtra("data","暂停"); PendingIntent pauseIntent = PendingIntent.getService(this, 2, changeService, PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.tv_pause,pauseIntent); remoteViews.setOnClickPendingIntent(R.id.tv_next,changeIntent); PendingIntent clickIntent = PendingIntent.getActivity(this, 1, new Intent(this, ThirdActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.iv_remote,clickIntent); notification.contentView = remoteViews; notification.contentIntent = pendingIntent; NotificationManager notifacationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notifacationManager.notify(2,notification); } }
上面是核心代码,以下会分块讲解:首先需要notification,设置参数,icon应该是每一首歌曲对应的图片
Notification notification = new Notification(); notification.icon = R.mipmap.ic_launcher; notification.tickerText = "remoteviewTest"; notification.when = System.currentTimeMillis(); notification.flags = Notification.FLAG_AUTO_CANCEL;
然后构造出PendingIntent
Intent intent = new Intent(this, SecondActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
再然后,构造出remoteviews,它有两个参数,一个是包名,另一个是布局的id,这里我写了一个简单的展示在通知栏的布局。注意了,remoteview设置文字和图片资源都没有findViewById,只能通过这种set方法,将对应的id和资源传进去。(这里先说用法,remoteview机制的原理在后面讲解)
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_remoteviews); remoteViews.setTextViewText(R.id.tv_remote, "暧昧"); remoteViews.setImageViewResource(R.id.iv_remote,R.mipmap.ic_launcher);
布局的代码如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:gravity="center_vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/iv_remote" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_launcher_round"/> <TextView android:id="@+id/tv_remote" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="i am a apple"/> <TextView android:id="@+id/tv_pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="暂停"/> <TextView android:id="@+id/tv_next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="下一曲"/> <TextView android:id="@+id/tv_close" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="关闭"/> </LinearLayout>
这里要澄清以下,不是非要用textview,而是我没有图,只能用文字代替,等以后又图了做个好看的哈哈。
下面说下remoteview上面点击事件,同理没有直接设置点击事件的方法(进它的源码瞅一眼就知道为啥了),还是只能传进去penddingIntent,由于qq音乐点击通知栏按钮直接切换歌曲,界面不发生变化所以,这块的penddingIntent用的PendingIntent.getService。当然,点击整个通知栏要跳到qq音乐主界面的话,就是底下PendingIntent.getActivity了。有一点,PendingIntent两个如果requescode一样,只是extras不一样会被认为是同一个peddingInetent。原因是,区分PenddingIntent是由内部intent和requescode,而内部intent区分是由componentName和intent-filter,ectras不参与Intent的匹配过程。如果notify方法的id是常量,那么不管PenddingIntent是否匹配,后面的通知会直接替换前面的通知。
Intent changeService = new Intent(this, ChangeService.class); changeService.putExtra("data","下一曲"); PendingIntent changeIntent = PendingIntent.getService(this, 1, changeService, PendingIntent.FLAG_UPDATE_CURRENT); changeService.putExtra("data","暂停"); PendingIntent pauseIntent = PendingIntent.getService(this, 2, changeService, PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.tv_pause,pauseIntent); remoteViews.setOnClickPendingIntent(R.id.tv_next,changeIntent); PendingIntent clickIntent = PendingIntent.getActivity(this, 1, new Intent(this, ThirdActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.iv_remote,clickIntent);
最后将自定义的remoteviews设置给notification的contentview并且获取系统NotificationManager,通过notifacationManager.notify方法将自定义的通知工具栏发出,展示在通知栏中国呢。
notification.contentView = remoteViews; notification.contentIntent = pendingIntent; NotificationManager notifacationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notifacationManager.notify(2,notification);
最后,本文只是仿照qq通知栏操作界面将remoteview的使用讲解一下,并不是一个播放器,再次强调,不是在做播放器。我这么想的,如果要做qq音乐的播放器通知更新,应该service里面去更新notinication的界面,比如,收到点击下一曲的penddingIntent,service去播放下一首歌曲,同时更新remoteview的界面(歌曲名字和歌曲对应的图片)对于qq音乐的其他操作,比如点击通知栏进入qq音乐主界面,就是notification的pendingIntent,它是由PenddingIntent.getActivity获取的。其他与qq音乐相关的先不管了,本文只提与remoteview有关的东西。
三、总结
- RemoteViews构造方法接受一个包名,一个layout的id;
- RemoteViews设置图片资源和文字资源接受id和资源;
- 没有直接方法设置点击事件,只能通过PenddingIntent相关方法实现;
- 将RemoteViews设置在notification中,通过NotificationManager的notify方法实现。
- 注意点:notify方法的id,penddingIntent的requestCode能用来区分PenddingIntent是不是同一个。
后记,RemoteViews还有一个最重要的使用就是桌面小部件(AppWidgetProvider),下一篇会写一个类似天气的桌面部件,并完成RemoteViews的原理讲解。
我的csdn博客欢迎关注我的微信公众号: