android 界面设计基本知识Ⅳ
Published on 2016-03-25 21:02 in 暂未分类 with 无涯Ⅱ

android 界面设计基本知识Ⅳ

    上一章讲述了Android界面开发中的Widget,Service,BroadcastReceiver基本知识点,本章以一个实际案例-后台音乐播放器解析各个知识点之间的关系。

    1.功能需求

    做一个Android音乐播放器

    •  用到Service、Broadcast Receiver、Widget
    •  使用后台服务播放音乐
    • 做一个音乐播放的Widget
    •  显示歌曲名
    • 显示上一首、下一首、播放、暂停

    2.软件实现

            

                        图1                              

                          图2                         

                              图3

    简易说明

    长按手机界面出现如图2所示信息,弹出小部件选项,点击进入小部件如图1。选择极客班-作业四,根据提示拖放界面到桌面,出现如图3所示音乐播放界面。点击按钮可实现音乐切换播放歌曲功能。

    3.实现流程

    后台音乐播放器主要是通过Widget的特性,用广播为通道,完成Widget与Service之间的交互。

    Widget:更新桌面信息,发送广播信息,接收用户操作事件。

    Service:注册服务,接收广播信息,发送广播信息。

    4.界面布局

    音乐播放器在界面布局和配置文件中主要包括以下方面:

    • appwidget-provider提供了桌面widget的初始化显示状态、默认图标、大小等功能,它放在res/xml文件夹下,参考项目中的music_app_widget_info.xml文件。
    • android:initialLayout="@layout/music_app_widget":这个就是指定初始化显示时,应该显示的布局,参考项目中的music_app_widget.xml文件。
    • 项目应用了服务,广播,须在AndroidManifest.xml中配置相应的标签。具体信息参考项目中的AndroidManifest.xml文件。

    5.核心代码分析

    (1)Widget函数-onUpdate()

    在用户添加Widget时,会调用OnUpdate()函数,在OnUpdate()中要实现绑定RemoteView和更新Widget的操作。在绑定控件时,主要应用了PendingIntent的方式。

    PendingIntent 是Intent的封装,在构造PendingIntent前,也要先构造一个Intent,并可以利用Intent 的属性传进去action,Extra等,同样,在接收时,对方依然是接收Intent的,而不是接收PaddingIntent。
    PendingIntent.getBroadcast(context, 0,intent, 0);指从系统中获取一个用于可以发送BroadcastReceiver广播的PendingIntent对象。PendingIntent这个类用于 处理即将发生的事情。比如在通知Notification中用于跳转页面,但不是马上跳转。所以可以将它理解成 一个封装成消息的intent的。即这个intent并不是立即start,而是像消息一样被发送出去,等接收方接到以后,再分析里面的内容。项目相关代 码摘抄如下:

    复制代码
     1 private PendingIntent getPendingIntent(Context context, int buttonId) {
     2         Intent intent = new Intent();
     3         intent.setClass(context, ExampleAppWidgetProvider.class);
     4         intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
     5         intent.setData(Uri.parse("harvic:" + buttonId));
     6         PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
     7         return pi;
     8     }
     9 
    10     // 更新所有的 widget
    11     private void pushUpdate(Context context,AppWidgetManager appWidgetManager,String songName,Boolean play_pause) {
    12 
    13         RemoteViews remoteView = new RemoteViews(context.getPackageName(),R.layout.music_app_widget);
    14         //将按钮与点击事件绑定
    15         remoteView.setOnClickPendingIntent(R.id.play_pause,getPendingIntent(context, R.id.play_pause));
    16         remoteView.setOnClickPendingIntent(R.id.prev_song, getPendingIntent(context, R.id.prev_song));
    17         remoteView.setOnClickPendingIntent(R.id.next_song, getPendingIntent(context, R.id.next_song));
    18 
    19         //设置内容
    20         if (!songName.equals("")) {
    21             remoteView.setTextViewText(R.id.song_name, songName);
    22         }
    23         //设定按钮图片
    24         if (play_pause) {
    25             remoteView.setImageViewResource(R.id.play_pause, R.drawable.button_stop);
    26         }else {
    27             remoteView.setImageViewResource(R.id.play_pause, R.drawable.button_on);
    28         }
    29         // 相当于获得所有本程序创建的appwidget
    30         ComponentName componentName = new ComponentName(context,ExampleAppWidgetProvider.class);
    31         appWidgetManager.updateAppWidget(componentName, remoteView);
    32     }
    33 
    34     @Override
    35     public void onUpdate(Context context, AppWidgetManager appWidgetManager,
    36                          int[] appWidgetIds) {
    37 
    38         pushUpdate(context,appWidgetManager,"",false);
    39     }
    Widget-onUpdate()
    复制代码

    (2)Widget函数-onReceive()

    接收用户操作,在接收时,首先根据当前用户点击的哪个按钮,然后给MusicManageService发送不同的广播(发送按钮id),让MusicManageService做出不同的响应,接收代码如下 :

    复制代码
     1 // 接收广播的回调函数
     2     @Override
     3     public void onReceive(Context context, Intent intent) {
     4         String action = intent.getAction();
     5         Log.d("harvic", "action:"+action);
     6         if (intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)) {
     7             Uri data = intent.getData();
     8             int buttonId = Integer.parseInt(data.getSchemeSpecificPart());
     9             switch (buttonId) {
    10                 case R.id.play_pause:
    11                     pushAction(context,MusicManageService.ACTION_PLAY_PAUSE);
    12                     if(mStop){
    13                         Intent startIntent = new Intent(context,MusicManageService.class);
    14                         context.startService(startIntent);
    15                         mStop = false;
    16                     }
    17                     break;
    18                 case R.id.prev_song:
    19                     pushAction(context, MusicManageService.ACTION_PRE);
    20                     break;
    21                 case R.id.next_song:
    22                     pushAction(context, MusicManageService.ACTION_NEXT);
    23                     break;
    24             }
    25         }else if (MAIN_UPDATE_UI.equals(action)){
    26             int play_pause =  intent.getIntExtra(KEY_MAIN_ACTIVITY_UI_BTN, -1);
    27             String songid = intent.getStringExtra(KEY_MAIN_ACTIVITY_UI_TEXT);
    28             if(songid==null) songid="歌曲";
    29             switch (play_pause) {
    30                 case VAL_UPDATE_UI_PLAY:
    31                     pushUpdate(context, AppWidgetManager.getInstance(context), songid,true);
    32                     break;
    33                 case VAL_UPDATE_UI_PAUSE:
    34                     pushUpdate(context, AppWidgetManager.getInstance(context), songid,false);
    35                     break;
    36                 default:
    37                     break;
    38             }
    39 
    40         }
    41 
    42         super.onReceive(context, intent);
    43     }
    Widget-onReceive()
    复制代码

    (3)Widget发送广播

    //发送按键广播
        private void pushAction(Context context, int ACTION) {
            //发送目的服务
            Intent actionIntent = new Intent(MusicManageService.ACTION);
            //发送参数
            actionIntent.putExtra(MusicManageService.KEY_USR_ACTION, ACTION);
            context.sendBroadcast(actionIntent);
        }

    (4)Service注册广播

    服 务要与按钮相交互,在Service中一般是通过BroadcastReceiver来实现,所以在 MusicManageService的OnCreate函数中(Service起来的时候调用OnCreate)应该包括下面几个步骤:注册 Receiver。对应的项目代码如下:

    复制代码
     1 private BroadcastReceiver receiver = new BroadcastReceiver() {
     2         @Override
     3         public void onReceive(Context context, Intent intent) {
     4             String action  = intent.getAction();
     5             if (ACTION.equals(action)) {
     6                 int widget_action = intent.getIntExtra(KEY_USR_ACTION, -1);
     7                 switch (widget_action){
     8                     case ACTION_PRE:
     9                         playPrev(context);Log.d("harvic","action_prev");break;
    10                     case ACTION_PLAY_PAUSE:
    11                         if (mPlayState) {
    12                             pause(context);Log.d("harvic","action_pause");
    13                         }else{
    14                             play(context);Log.d("harvic","action_play");
    15                         }
    16                         break;
    17                     case ACTION_NEXT:playNext(context);Log.d("harvic","action_next");break;
    18                     default:break;
    19                 }}
    20         }
    21     };
    22     @Override
    23     public void onCreate() {
    24         // TODO Auto-generated method stub
    25         super.onCreate();
    26         IntentFilter intentFilter = new IntentFilter();
    27         intentFilter.addAction(ACTION);
    28         //注册服务
    29         registerReceiver(receiver, intentFilter);
    30         //加载歌曲
    31         initList();
    32         //播放默认歌曲
    33         mediaPlayerStart();
    34     }
    复制代码

    (5)歌曲定义

    歌曲为本地歌曲文件,放在项目的raw目录下:

    复制代码
     1 //歌曲播放
     2     private void mediaPlayerStart(){
     3         mPlayer = new MediaPlayer();
     4         mPlayer = MediaPlayer.create(getApplicationContext(), mArrayList[mIndex]);
     5         mPlayer.start();
     6         mPlayState = true;
     7         //通过广播发送当前播放状态到Widget
     8         postState(getApplicationContext(), ExampleAppWidgetProvider.VAL_UPDATE_UI_PLAY,mIndex);
     9     }
    10     //歌曲初始化
    11     private void initList() {
    12         //歌曲路径
    13         mArrayList[0] = R.raw.night_two;
    14         mArrayList[1] = R.raw.night_four;
    15         mArrayList[2] = R.raw.night_five;
    16         mArrayList[3] = R.raw.night_six;
    17         //歌曲名称
    18         mArrayListName[0] ="石进-夜的钢琴曲二";
    19         mArrayListName[1] = "石进-夜的钢琴曲四";
    20         mArrayListName[2] ="石进-夜的钢琴曲五";
    21         mArrayListName[3] = "石进-夜的钢琴曲六";
    22     }
    复制代码

    (6)Service发送广播

    歌曲通过Widget不同按钮切换发送广播到Service,Service通过播放功能函数(参考项目源代码)做出相应的播放功能切换处理以后,就又一次发送一个广播信息回馈给Widget,Widget接收到广播信息后进行更新处理,项目代码如下:

    复制代码
     1 //回馈广播信息给Widget
     2     private void postState(Context context, int state,int songid) {
     3         //定义发送广播接收者
     4         Intent actionIntent = new Intent(ExampleAppWidgetProvider.MAIN_UPDATE_UI);
     5         //定义歌曲播放状态(播放/暂停)
     6         actionIntent.putExtra(ExampleAppWidgetProvider.KEY_MAIN_ACTIVITY_UI_BTN,state);
     7         //定义发送信息(歌曲名称)
     8         actionIntent.putExtra(ExampleAppWidgetProvider.KEY_MAIN_ACTIVITY_UI_TEXT, mArrayListName[songid]);
     9         context.sendBroadcast(actionIntent);
    10     }
    复制代码

    6.项目源代码下载

    本项目源代码在360云盘上,开发环境为 Android Studio 2.0 beta 7。

    https://yunpan.cn/cYamkZG3sq9jf  访问密码 f3d5

     

    posted @   无涯Ⅱ  阅读(824)  评论(3编辑  收藏  举报
    编辑推荐:
    · 如何编写易于单元测试的代码
    · 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
    · .NET Core 中如何实现缓存的预热?
    · 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
    · AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
    阅读排行:
    · 周边上新:园子的第一款马克杯温暖上架
    · Open-Sora 2.0 重磅开源!
    · 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
    · Ollama——大语言模型本地部署的极速利器
    · DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
    点击右上角即可分享
    微信分享提示