当前位置: 首页 > 知识库问答 >
问题:

原生android媒体播放器如何使数据持久化并反映变化

万高洁
2023-03-14

目前,我正在尝试构建一个成熟的android音乐播放器。每当应用程序加载且之前未出现在ram中时,我都会从mediastore加载所有歌曲、艺术家、播放列表等。不过,这种方法反映了应用程序加载之间的mediastore变化,大大增加了加载时间。我应该如何继续获得合适的加载时间并反映任何数据更改?提前谢谢。

共有2个答案

钱朝明
2023-03-14

我在我的应用程序New Playlist Manager中使用了一种viewpager方法,它适用于所有曲目、专辑和艺术家。对于其中的每一个,我都有一个片段,每个片段都有一个自定义游标适配器。我给你举一个所有曲目的例子:设置我的列:

        dataColumns= new String[]{
            MediaStore.Audio.Media.TRACK,
            MediaStore.Audio.Media._ID,
            MediaStore.Audio.Media.DATA,
            MediaStore.Audio.Media.ARTIST,
            MediaStore.Audio.Media.YEAR,
            MediaStore.Audio.Media.DURATION,
            MediaStore.Audio.Media.TITLE,
            MediaStore.Audio.Media.ALBUM,
            MediaStore.Audio.Media.ALBUM_ID
    };
    sort_order =  MediaStore.Audio.Media.TITLE +" ASC";

要填充我的listView,我在OnViewCreated中使用LoaderManager

 getLoaderManager().initLoader(GALLERY_LOADER, null, this);

       @Override
public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) {
    switch (loaderID) {
        case GALLERY_LOADER:
            return new CursorLoader(getActivity(),
                    MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                    dataColumns,
                    null, null,
                    sort_order);
        default:
            return null;
    }
}


@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    mAdapter.swapCursor(data);
    mAdapter.notifyDataSetChanged();
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
    mAdapter.swapCursor(null);

}

因此,创建视图后,LoaderManager将获取必要的游标,然后将其馈送给适配器。因此,对于每个片段,您只获取所需的数据。对于相册,我的光标加载器如下所示:

         public class showallAlbumsFragment extends Fragment implements
     OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor>

          dataColumns= new String[]{
                    BaseColumns._ID,
                    AlbumColumns.ALBUM,
                    AlbumColumns.NUMBER_OF_SONGS,
                    AlbumColumns.FIRST_YEAR,
                    AlbumColumns.ARTIST };
    sort_order =  AlbumColumns.ALBUM +" ASC";




    @Override
public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) {
    switch (loaderID) {
        case GALLERY_LOADER:
            return new CursorLoader(getActivity(),
                    MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
                    dataColumns,
                    null, null,
                    sort_order);

        default:
            return null;
    }
}

我希望这能让你振作起来

裴育
2023-03-14

要将光标传递给中的recyclerview适配器,片段实现LoaderManager

 public class LayoutFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> 

          getLoaderManager().initLoader(0, null, LayoutFragment.this);
    mAdapter = new LayoutAdapter(getActivity(),mRecyclerView,mLayoutId, mcursor);
    mRecyclerView.setAdapter(mAdapter);

此外,在适配器中,调整签名

      public LayoutAdapter(Context context, RecyclerView recyclerView, int layoutId, Cursor c) {
    mContext = context;
    mCursor = c;
    mRecyclerView = recyclerView;
    mLayoutId = layoutId;
}

并添加一些方法,因为您需要从片段中添加它们

       @Override
public int getItemCount() {
    if(mCursor!=null) {
        return mCursor.getCount();
    }else{
        return 0;
    }
}

public void swapCursor(Cursor newCursor) {
    if (newCursor == mCursor) {
        return;
    }

    if (newCursor != null) {
        mCursor = newCursor;
        mRowIDColumn = mCursor.getColumnIndexOrThrow("_id");
        mDataValid = true;
        // notify the observers about the new cursor
        notifyDataSetChanged();
    } else {
        notifyItemRangeRemoved(0, getItemCount());
        mCursor = null;
        mRowIDColumn = -1;
        mDataValid = false;
    }
}

碎片状

      @Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    switch (id) {
        case LOADER:
            Uri uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
            final String criteria = null;
            String[] columns = {
                    MediaStore.Audio.Playlists._ID,
                    MediaStore.Audio.Playlists.NAME,
            };
            return new CursorLoader(getActivity(), uri, columns, criteria, null, MediaStore.Audio.Playlists.NAME + " ASC");
        default:
            return null;
    }

}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    mAdapter.swapCursor(data);
    mcursor=data;
    mAdapter.notifyDataSetChanged();
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    mAdapter.swapCursor(null);
    mcursor=null;
    mAdapter.notifyDataSetChanged();
}
 类似资料:
  • 我正在寻找一个开源媒体播放器或Android应用编程接口,可以支持MPEG-DASH及其修正案,如平铺视频的空间关系描述(SRD)功能。有什么建议吗? 我以为Android的API支持DASH,但显然它不支持。他们提倡一种叫做ExoPlayer(http://google.github.io/ExoPlayer/)的播放器,它支持DASH、平滑流等等。我想知道它是否支持DASH的所有功能,如SRD

  • 问题内容: 我有两个按钮,它将播放声音以通知您正确的选择或错误的选择。这是我的方法: 同样,声音正确。在大多数情况下,它都可以正常工作,但是当我多次单击它时,随机出现此错误: 基本上说是行 playError.start(); 给我 NullPointerException (仅有时) 编辑: 行是148:playError.start(); 而falseAnswerPoints()是: 相同的是

  • 我想通过Android中的media player对象播放现场流媒体。 因此,我计划从源读取缓冲区数据,并将其写入媒体播放器的缓冲区,请注意,我不会使用任何URL为媒体播放器的流源,音频缓冲区数据将以字节形式通过输入流接收。 到目前为止,我可以使用音频跟踪对象,但该方法只适用于未压缩的PCM数据

  • 我正在一个在线广播流媒体项目中工作,在那里我正在使用来自 URL 的媒体播放器播放音频。音乐正在播放并且工作正常。但是我坚持播放,暂停有关玩家活动状态的功能。我希望当应用程序通过按主页按钮退出时,音乐将继续播放,但是当电话响起时,音乐将暂停,在语音通话后,音乐将恢复。此外,当用户打开另一个应用程序时,音乐将继续在后台播放。(作为Android的默认音乐播放器工作) 但我的所作所为几乎实现了我想要的

  • 当我使用MediaPlayer播放mp3文件时,系统会报告错误日志:。但是RealPlayer是正常的。 我发现它的错误只发生在更高的ROM版本。像4.0版本一样,它有错误。在2.3版中,它没有这个错误。 代码: 日志猫错误:

  • 我正在开发一个包含一些音频播放器的RecyclerView的应用程序。应用程序将下载。3gp文件(如果尚未下载)。 当我单击playAudio按钮时,音频未被播放。 这是我的适配器代码: 我怎样才能解决这个问题?