系统应用篇(五)--Music篇

目录

一、Music应用的作用和重要性

二、Music应用的类型和分类

三、Music应用的架构和组件

四、Music应用的定制和扩展


一、Music应用的作用和重要性

音乐应用的作用和重要性如下表所示:

作用/重要性 描述
1. 音乐播放 音乐应用的主要作用是提供音乐播放功能,让用户能够享受各种音乐内容。它能够播放本地存储的音乐文件,或者通过网络连接来播放在线音乐流。音乐播放是音乐应用的核心功能之一。
2. 音乐库管理 音乐应用负责管理用户的音乐库,包括扫描和索引本地音乐文件,建立音乐标签和分类等。它允许用户轻松浏览和搜索音乐内容,并提供歌曲信息和艺术家信息等。音乐库管理有助于组织和管理用户的音乐收藏。
3. 播放列表 音乐应用允许用户创建和管理播放列表,将不同的音乐曲目组合在一起以满足用户的不同需求。播放列表可以按照用户的喜好、心情或主题来创建,提供更加个性化的音乐播放体验。
4. 音乐控制 音乐应用提供音乐控制功能,包括播放、暂停、上一曲、下一曲等操作。用户可以通过界面上的控制按钮或者快捷键来控制音乐的播放和操作。音乐控制是用户与音乐应用进行交互的重要方式。
5. 音效调节 音乐应用提供音效调节功能,用户可以根据个人喜好调整音乐的音量、均衡器设置、重低音效果等。这些音效调节可以增强音乐的音质和听觉体验,满足用户对音乐效果的个性化需求。
6. 在线音乐服务 音乐应用可以集成在线音乐服务,提供更广泛的音乐内容和服务。用户可以通过音乐应用访问和播放来自各种在线音乐平台的音乐,享受更丰富多样的音乐体验。在线音乐服务扩展了音乐应用的功能和内容范围。

        音乐应用的作用和重要性,包括音乐播放、音乐库管理、播放列表、音乐控制、音效调节和在线音乐服务等。这些功能使音乐应用成为用户在移动设备上欣赏和管理


二、Music应用的类型和分类

音乐应用的类型和分类如下表所示:

类型/分类 描述
1. 本地音乐播放器 本地音乐播放器是指可以播放存储在设备本地的音乐文件的应用。它们通过扫描设备存储上的音乐文件,建立音乐库并提供播放功能。用户可以浏览本地音乐文件夹、创建播放列表和调整音效设置等。
2. 在线音乐播放器 在线音乐播放器是指通过网络连接,提供在线音乐流媒体服务的应用。它们允许用户浏览和播放来自各种在线音乐平台的音乐内容,如流行音乐、专辑、歌手等。用户可以根据自己的喜好搜索和收藏音乐,享受在线音乐服务。
3. 个性化音乐推荐 个性化音乐推荐应用利用算法和用户的偏好信息,推荐适合用户口味的音乐。它们分析用户的听歌历史、喜好标签等数据,为用户提供个性化的音乐推荐列表。这些应用通常提供歌曲推荐、每日推荐、热门歌曲等功能。
4. 歌词显示应用 歌词显示应用提供歌曲的歌词文本显示功能。当用户播放音乐时,这些应用会自动匹配并显示相应歌曲的歌词,让用户可以跟随歌词唱歌或阅读歌曲的歌词内容。歌词显示应用可以提供不同样式和字体的歌词显示。
5. 音乐编辑和创作工具 音乐编辑和创作工具是一类专注于音乐创作和编辑的应用。它们提供音频剪辑、混音、音效处理等功能,让用户能够创建、编辑和定制自己的音乐作品。这些工具通常包括多轨道编辑、效果处理和音乐导出等功能。

        音乐应用的类型和分类,包括本地音乐播放器、在线音乐播放器、个性化音乐推荐、歌词显示应用和音乐编辑和创作工具。这些类型和分类展示了音乐应用在功能和用途上的多样性。用户可以根据自己的需求和兴趣选择适合的音乐应用。


三、Music应用的架构和组件

音乐应用的架构和组件如下表所示:

架构/组件 描述
1. 用户界面 (UI) 音乐应用的用户界面负责展示音乐库、播放控制、搜索功能和歌曲信息等。它包括主界面、播放界面、歌曲列表和设置等模块。用户可以通过界面操作播放音乐、调整音量和切换播放模式等。
2. 音乐播放引擎 音乐播放引擎是音乐应用的核心组件,负责音乐文件的解码和播放。它能够处理各种音频格式,并提供播放控制功能,如暂停、停止、快进和快退等。播放引擎通常支持音效处理、播放队列管理和循环模式等特性。
3. 音乐库管理 音乐库管理组件用于管理设备上的音乐文件。它负责扫描设备存储上的音乐文件,并建立索引以供用户浏览和搜索。音乐库管理还包括歌曲标签的解析和存储,以及歌手、专辑和播放列表等元数据的管理。
4. 数据库存储 数据库存储组件用于持久化存储音乐应用的配置和用户数据。它存储音乐库索引、播放记录、用户喜好设置和收藏的歌曲等信息。数据库存储提供数据的增删改查功能,以支持用户的个性化设置和数据的持久化。
5. 音乐推荐算法 音乐推荐算法组件分析用户的音乐偏好和听歌历史,为用户提供个性化的音乐推荐。它根据用户的喜好标签、歌曲评分和相似性等算法,推荐符合用户口味的音乐内容。推荐算法组件不仅提供歌曲推荐功能,还可以生成每日推荐和热门歌曲等特色推荐。

        音乐应用的架构和组件,包括用户界面 (UI)、音乐播放引擎、音乐库管理、数据库存储和音乐推荐算法。这些组件共同构成了音乐应用的功能和特性,用户通过界面操作与音乐播放引擎交互,同时利用音乐库管理和数据库存储来管理音乐文件和用户数据,最终通过音乐推荐算法获取个性化的音乐推荐。


四、Music应用的定制和扩展

以高通平台的骁龙音乐为例:

  1. 修改按下音量键可以调整播放的音量
  2. 调整item的位置大小和修改播放详细界面item触屏点击一次就能响应事件
  3. 调整歌曲listView的item可以切换顺畅
  4. 解决音乐中DrawerLayout布局的焦点问题

解决方案:

1.在AudioPreview.java中的onKeyDown中添加处理音量上下按键逻辑的代码:

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // Null pointer check here is to avoid monkey test failure.
        // Key down event will be received even when acitivity is
        // about to finish.
        if (mPlayer == null) {
            return true;
        }

        switch (keyCode) {
			//add begin
            case KeyEvent.KEYCODE_VOLUME_UP:
                mAudioManager.adjustVolume(AudioManager.ADJUST_RAISE,0);
                return true;
            case KeyEvent.KEYCODE_VOLUME_DOWN:
                mAudioManager.adjustVolume(AudioManager.ADJUST_LOWER,0);
                return true;
            //add end
            case KeyEvent.KEYCODE_HEADSETHOOK:
            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                if (mPlayer.isPlaying()) {
                    mPlayer.pause();
                } else {
                    start();
                }
                updatePlayPause();
                return true;
            case KeyEvent.KEYCODE_MEDIA_PLAY:
                start();
                updatePlayPause();
                return true;
            case KeyEvent.KEYCODE_MEDIA_PAUSE:
                if (mPlayer.isPlaying()) {
                    mPlayer.pause();
                }
                updatePlayPause();
                return true;
            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
            case KeyEvent.KEYCODE_MEDIA_NEXT:
            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
            case KeyEvent.KEYCODE_MEDIA_REWIND:
                return true;
            case KeyEvent.KEYCODE_MEDIA_STOP:
            case KeyEvent.KEYCODE_BACK:
                stopPlayback();
                if (MusicUtils.sService == null) {
                    System.exit(0);
                }
                finish();
                return true;
        }
        return super.onKeyDown(keyCode, event);
    }

2.在MediaPlaybackActivity.java中的init()方法中设置Clickable属性为true:

    public void init() {
        mToolbar = (Toolbar) findViewById(R.id.music_tool_bar);
        mNowPlayingView = findViewById(R.id.dragLayout);
        mSlidingPanelLayout = (MusicPanelLayout) findViewById(R.id.sliding_layout);
        mNowPlayingIcon = (ImageView) findViewById(R.id.nowplay_icon);
        mNowPlayingIcon.setOnClickListener(mPauseListener);
		//add begin
		//mSlidingPanelLayout.setClickable(true);
		mToolbar.setClickable(false);
		mNowPlayingIcon.setFocusable(true);
        mNowPlayingIcon.requestFocus();
        setTouchDelegate(mNowPlayingIcon);
        mAlbum = (ImageView) findViewById(R.id.album);
        mArtistName = (TextView) findViewById(R.id.artist_name);
        mTrackName = (TextView) findViewById(R.id.song_name);
        mCurrentPlaylist = (ImageButton) findViewById(R.id.animViewcurrPlaylist);
        mCurrentPlaylist.setOnClickListener(mQueueListener);		
		//add begin
        //mCurrentPlaylist.setFocusable(true);
        //mCurrentPlaylist.requestFocus();
		mCurrentPlaylist.setVisibility(View.INVISIBLE);
        setTouchDelegate(mCurrentPlaylist);
        seekmethod = 1;

        mDeviceHasDpad
                = (getResources().getConfiguration().navigation == Configuration.NAVIGATION_DPAD);

        mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
        mMenuOverFlow = (ImageButton) findViewById(R.id.menu_overflow_audio_header);
        mMenuOverFlow.setOnClickListener(mActiveButtonPopUpMenuListener);		
        setTouchDelegate(mMenuOverFlow);
		//add begin
        mMenuOverFlow.setFocusable(true);
		mMenuOverFlow.setFocusableInTouchMode(false);
		mMenuOverFlow.setClickable(true);
        //add end
        SysApplication.getInstance().addActivity(this);
        mLyricAdapter = new LyricAdapter(this);
        mAudioPlayerBody = (LinearLayout)findViewById(R.id.audio_player_body);
        initAudioPlayerBodyView();
    }

3.在TrackBrowserFragment.java中的onCreateView()方法中设置TrackList.setItemsCanFocus(true):

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.media_picker_fragment,
                container, false);
        mShuffleLayout = (RelativeLayout) rootView
                .findViewById(R.id.shuffleLayout);
        mSdErrorMessageView = (TextView) rootView.findViewById(R.id.sd_message);
        mSdErrorMessageIcon = rootView.findViewById(R.id.sd_icon);
        mTrackList = (ListView) rootView.findViewById(R.id.list);
        mTrackList.setCacheColorHint(0);
        mTrackList.setDividerHeight(0);
		//add begin
        //mTrackList.setFocusable(false);
        //add end
        if (mEditMode) {
            mShuffleLayout.setVisibility(View.GONE);
            ((TouchInterceptor) mTrackList).setDropListener(mDropListener);
            ((TouchInterceptor) mTrackList).setRemoveListener(mRemoveListener);
            ((TouchInterceptor) mTrackList)
                    .registerContentObserver(mParentActivity
                            .getApplicationContext());
            mTrackList.setDivider(null);
        } else {
            mTrackList.setTextFilterEnabled(true);
        }
        if ("podcasts".equals(mPlaylist) || "recentlyadded".equals(mPlaylist)
                || mParent != -1) {
            mShuffleLayout.setVisibility(View.GONE);
        }
        if (mAdapter != null) {
            mAdapter.setActivity(this);
            mTrackList.setAdapter(mAdapter);
        }
        mToken = MusicUtils.bindToService(mParentActivity, this);

        // don't set the album art until after the view has been layed out
        mTrackList.post(new Runnable() {

            public void run() {
                setAlbumArtBackground();
            }
        });
        mTrackList.setOnItemClickListener(this);
        mTrackList.setOnScrollListener(this);
		//add begin
		mTrackList.setItemsCanFocus(true);
        //add end
        ImageButton shuffleAll = (ImageButton) rootView
                .findViewById(R.id.shuffleAll);
        shuffleAll.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Cursor cursor = MusicUtils.query(mParentActivity,
                        MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                        new String[] { MediaStore.Audio.Media._ID },
                        MediaStore.Audio.Media.IS_MUSIC + "=1", null,
                        MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
                if (cursor != null) {
                    MusicUtils.shuffleAll(mParentActivity, cursor);
                    cursor.close();
                }
            }
        });

        rootView.setOnKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                int curpos = mTrackList.getSelectedItemPosition();
                if (mPlaylist != null && !mPlaylist.equals("recentlyadded")
                        && curpos >= 0 && event.getMetaState() != 0
                        && event.getAction() == KeyEvent.ACTION_DOWN) {
                    switch (event.getKeyCode()) {
                    case KeyEvent.KEYCODE_DPAD_UP:
                        moveItem(true);
                        return true;
                    case KeyEvent.KEYCODE_DPAD_DOWN:
                        moveItem(false);
                        return true;
                    case KeyEvent.KEYCODE_DEL:
                        removeItem();
                        return true;
                    }
                } else if (event.getAction() == KeyEvent.ACTION_UP
                        && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                    mParentActivity.finish();
                    return true;
                }
                return false;
            }
        });
        return rootView;
    }

4.在MusicBrowserActivity.java的initview()方法中设置对DrawerListener的监听,并在其中的onDrawerOpened()中设置焦点:

    public void initView() {
        mNowPlayingIcon = (ImageView) findViewById(R.id.nowplay_icon);
        mNowPlayingIcon.setOnClickListener(mPauseListener);
        mDrawerListView = (ListView) findViewById(R.id.navList);
        int height = MusicUtils.isGroupByFolder() ? LIST_HEIGHT_CMCC_MODE
                     : LIST_HEIGHT_NON_CMCC_MODE;
        height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height,
                      getResources().getDisplayMetrics());
        mDrawerListView.getLayoutParams().height = height;
        RelativeLayout equalizerLayout = (RelativeLayout) findViewById(R.id.equalizer_btn_view);
        RelativeLayout exitLayout = (RelativeLayout) findViewById(R.id.exit_btn_view);
        if (getApplicationContext().getResources().getBoolean(R.bool.exit_in_drawer)) {
            exitLayout.setVisibility(View.VISIBLE);
        } else {
            exitLayout.setVisibility(View.GONE);
        }
        mNavigationAdapter = new NavigationDrawerListAdapter(this);
        mDrawerListView.setAdapter(mNavigationAdapter);
        activeTab = MusicUtils.getIntPref(this, "activetab", 0);
        mDrawerListView
                .setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView parent, View view,
                            int position, long id) {
                        if (mIsPanelExpanded) {
                            getSlidingPanelLayout().setHookState(
                                    BoardState.COLLAPSED);

                        }
                        activeTab = MusicUtils.getIntPref(
                                MusicBrowserActivity.this, "activetab", 0);
                        mNavigationAdapter.setClickPosition(position);
                        mDrawerLayout.closeDrawer(Gravity.START);
                        final int toShowPosition = position;
                        mDrawerLayout.setDrawerListener(new DrawerLayout.DrawerListener() {
                            @Override
                            public void onDrawerSlide(View drawerView, float slideOffset) {
                            }
                            @Override
                            public void onDrawerOpened(View drawerView) {
                            }
                            @Override
                            public void onDrawerClosed(View drawerView) {
                                showScreen(toShowPosition);
                            }
                            @Override
                            public void onDrawerStateChanged(int newState) {
                            }
                        });
                    }
                });
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
		//add begin
		mDrawerLayout.setDrawerListener(new DrawerLayout.SimpleDrawerListener() {
            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
                super.onDrawerSlide(drawerView, slideOffset);
            }

            @Override
            public void onDrawerOpened(View drawerView) {
				mDrawerLayout.clearFocus();
				mDrawerLayout.setFocusable(false); 
				mDrawerListView.setClickable(true);
				mDrawerListView.setFocusable(true);
				mDrawerListView.requestFocus();
                mDrawerListView.setFocusableInTouchMode(false);    			           
            }

            @Override
            public void onDrawerClosed(View drawerView) {
                //mDrawerLayout.clearFocus();
				//mDrawerLayout.requestFocus();
            }

            @Override
            public void onDrawerStateChanged(int newState) {
                super.onDrawerStateChanged(newState);
            }
        });

        equalizerLayout.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                MusicUtils.startSoundEffectActivity(MusicBrowserActivity.this);
                mDrawerLayout.closeDrawer(Gravity.START);
            }
        });

        exitLayout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    MusicUtils.sService.stop();
                    SysApplication.getInstance().exit();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });

        if (mToolbar.getMenu() != null) {
            mToolbar.getMenu().clear();
        }

        mToolbar.inflateMenu(R.menu.main);
        MenuItem menuItem = mToolbar.getMenu().findItem(R.id.action_search);
        menuItem.setVisible(false);
        mToolbar.setOnMenuItemClickListener(new OnMenuItemClickListener() {

            @Override
            public boolean onMenuItemClick(MenuItem item) {
                // TODO Auto-generated method stub
                mIsparentActivityFInishing = true;
                Intent intent = new Intent(MusicBrowserActivity.this,
                        QueryBrowserActivity.class);
                startActivity(intent);
                return false;
            }
        });
        mToolbar.setNavigationContentDescription("drawer");
		//add begin
		mToolbar.setFocusable(false);
        mToolbar.setNavigationOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (mToolbar.getNavigationContentDescription().equals("drawer")) {
                    mDrawerLayout.openDrawer(Gravity.START);
                }else {
                    showScreen(MusicUtils.navigatingTabPosition);
                    mToolbar.setNavigationContentDescription("drawer");
                    mToolbar
                    .setNavigationIcon(R.drawable.ic_material_light_navigation_drawer);
                }
            }
        });

        showScreen(activeTab);
    }

本文仅代表个人观点和经验,难免存在不足之处。如果有任何错误或改进的建议,欢迎指正和交流,共同进步。

你可能感兴趣的:(android基础,Java基础,android,java,智能手机)