Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/226.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 来自SQLite db的流式音频_Android_Sqlite_Audio_Stream - Fatal编程技术网

Android 来自SQLite db的流式音频

Android 来自SQLite db的流式音频,android,sqlite,audio,stream,Android,Sqlite,Audio,Stream,我有一个SQLite数据库,其中有音频文件存储为blob 在android(或任何地方)中是否可以从db流媒体?如果您在数据库中以android音频系统可以本机解释的格式(即mp3、3gpp、ogg)存储实际音频数据,那么一种方法是在服务中实现web服务器,并让该服务打开SQLite数据库,通过使用ByteArrayInputStream包装字节数组,获取blob,然后通过web服务器将该blob发送到MediaPlayer实例。我见过这样的实现(在这些情况下,它来自文件,而不是数据库,但适用相

我有一个SQLite数据库,其中有音频文件存储为blob


在android(或任何地方)中是否可以从db流媒体?

如果您在数据库中以android音频系统可以本机解释的格式(即mp3、3gpp、ogg)存储实际音频数据,那么一种方法是在服务中实现web服务器,并让该服务打开SQLite数据库,通过使用ByteArrayInputStream包装字节数组,获取blob,然后通过web服务器将该blob发送到MediaPlayer实例。我见过这样的实现(在这些情况下,它来自文件,而不是数据库,但适用相同的原则)

或者,您可以使用AudioTrack,如果音频不是PCM格式,则转换音频,然后播放并自己处理音频管理:可能需要更多的工作,但效率更高


请注意,这将是非常内存密集型的,并且可能会表现不佳:对于5mb MP3,您基本上必须将整个内容保存在内存中,因为Android的SQLite界面似乎没有为您提供一个指向blob的流接口。如果您正在加载多个媒体文件,那么…会发生不好的事情。

我建议不要将音频数据存储在数据库中。前面提到的内存问题可能会导致大量GC抖动,这会使系统在几秒钟或更长时间内不响应

典型的方法包括几个步骤

  • 将音频存储在应用程序目录中的某个文件中

  • 在数据库中创建两列。一列(称为任意列)包含引用数据的“content://”URL。看到“content://”URL会触发系统查找同一行中“\u data”列的内容。该列的内容应该是文件的完整路径

  • 然后,系统透明地读取该文件,并将其呈现给实际请求内容的代码

  • 我有一些示例代码用于处理图像——显然,这不完全相同,但我可以在这里浏览一下,您应该可以了解要点

    我试图解决的具体问题是存储设备外存储的曲目的专辑插图。我希望能够在列表中显示相册插图,并将其本地缓存在设备上,以便重复滚动它是快速的,并且不涉及对相同数据的重复网络抓取

    我有一个相册数据库,其中包含从远程服务器惰性填充的各种列。我使用ContentProvider框架实现这个数据库。网站上有很多关于内容提供者的重要信息,你应该先阅读这些信息,这样剩下的内容才有意义

    涉及的文件有(注意:我已经链接到树中的特定点,因为这是一项正在进行的工作,我希望我提供给您的行号参考是稳定的):

    这个类定义了其他地方使用的各种常量,对于作为ContentProvider实现的任何东西来说都非常惯用

    在这个类中,COL_ARTWORK_PATH是将包含content://URL的列

    这是ContentProvider的实现。同样,对于包装SQLite数据库的ContentProviders来说,这是非常惯用的。一些关注点:

    429:albumListCallback()

    每当应用程序从远程服务器接收到有关相册的数据时(这是我的应用程序特有的,与您的问题无关),就会调用此代码。至此,数据已打包为一个压缩文件列表,因此此代码必须解压缩该数据并将其转入数据库中的行中

    456:在这里,我们称之为updateAlbumArt,它有足够的数据,可以远程获取专辑插图(我刚刚意识到,通过查看这些代码,我可以提高效率,因为它更新数据库的频率比应该的要高。但我离题了)

    475:updateAlbumArt()

    这必须获取远程映像,调整其大小,在文件系统中存储原始版本和调整大小的版本(为什么两者都存储?因为我还没有完成这项工作,稍后将有代码选择正确的缓存大小)

    这将根据需要创建缓存目录,下载远程映像,调整其大小,并将其保存到文件中

    这可能是你特别感兴趣的一点。这将创建一个content://URL(使用AlbumCache.java中的常量)来引用数据,并将其放入COL_ARTWORK_路径中。然后将文件的绝对路径放入_data列中

    571:openFile()

    你必须实现这一点。ContentProvider的用户要在数据库中打开文件时,将调用openFile()。此实现使用openFileHelper(),该代码在_data列中查找值,打开该文件,并向调用者返回ParcelFileDescriptor

    正如您可能刚刚意识到的,openFile()的开放实现不必这样做——您可以使用另一个列名,或者您可以直接从URL转到文件系统中的文件。不过,这似乎是一个非常常见的习语

    假设您已经完成了类似的操作,并且现在您的数据库有一个ContentProvider,要实际访问图像,您的应用程序将需要生成一个URI,该URI通过其ID引用给定的内容。应用程序中打开文件的代码如下所示:

    Inputstream f = this.getContentResolver().openInputStream(theUri);
    
    最终调用openFile()的实现,最终调用openFileHelper(),最终访问文件系统中的正确文件。这种方法的另一个优点是openFile()是在应用程序的安全域中调用的,因此它可以访问该文件,如果实现正确,则完全不同的应用程序可以调用ContentProvider