我有一个SQLite数据库,里面有存储为blobs的音频文件。
在android (或其他任何地方)可以从db中流式传输媒体吗?
发布于 2011-06-04 03:33:09
我建议不要将音频数据存储在数据库中。前面提到的内存问题可能会导致大量的GC颠簸,这可能会使系统在几秒钟或更长时间内无响应。
典型的方法包括几个步骤。
我有一些处理图像的示例代码--显然,它们并不完全相同,但我可以在这里一一介绍,您应该会明白要点。
我试图解决的具体问题是为存储在设备之外的曲目存储专辑插图。我希望能够在列表中显示专辑插图,并在设备上本地缓存它,以便重复滚动它是快速的,并且确实涉及到对相同数据的重复网络获取。
我有一个相册数据库,其中包含从远程服务器缓慢填充的各种列。我使用ContentProvider框架实现了这个数据库。在http://developer.android.com/guide/topics/providers/content-providers.html上有很多关于ContentProviders的很好的信息,你应该先读一读,这样才能理解剩下的内容。
涉及的文件是(注意:我已经链接到树中的特定点,因为这是一项正在进行的工作,我希望我给您的行号引用是稳定的):
这个类定义了在其他地方使用的各种常量,并且对于任何作为ContentProvider实现的常量来说都是非常惯用的。
在这个类中,COL_ARTWORK_PATH是将包含content:// URL的列。
这是ContentProvider的实现。同样,对于包装SQLite数据库的ContentProviders来说,这也是非常惯用的。一些有趣的地方:
429: albumListCallback()
每当应用程序从远程服务器接收到有关相册的数据时,都会调用此代码(这是我的应用程序特有的,与您的问题无关)。至此,数据已被包装为SqueezerAlbums列表,因此此代码必须解压缩该数据,并将其转换为数据库中的行。
456:这里我们使用足够的数据调用updateAlbumArt,它可以远程获取专辑插图(我刚刚意识到查看这段代码可以提高效率,因为它更新数据库的频率比正常情况下更高)。但我离题了)。
475: updateAlbumArt()
这必须获取远程映像,调整其大小,在文件系统中存储原始版本和调整大小的版本(为什么两者都是?因为我还没有完成这项工作,稍后会有代码来选择正确的缓存大小)。
这将根据需要创建一个缓存目录,下载远程映像,调整其大小,并将其保存到文件中。
535:这可能是你特别感兴趣的部分。这将创建一个引用数据的content:// URL (使用AlbumCache.java中的常量),并将其放入COL_ARTWORK_PATH中。然后,它将文件的绝对路径放在_data列中。
571: openFile()
您必须实现这一点。当ContentProvider的用户想要打开数据库中的文件时,他们将调用openFile()。此实现使用openFileHelper(),它是查找_data列中的值、打开该文件并向调用者返回ParcelFileDescriptor的代码。
正如您可能已经意识到的,openFile()的开放实现不必这样做--您可以使用另一个列名,或者您有一种方法可以直接从URL转到文件系统中的文件。不过,这似乎是一个非常常见的习惯用法。
假设你已经做了这样的事情,现在你的数据库有了一个ContentProvider,为了实际访问图像,你的应用程序需要生成一个URI,它通过ID引用给定的内容。应用程序中打开文件的代码如下:
Inputstream f = this.getContentResolver().openInputStream(theUri);
这最终调用了您的openFile()实现,最终调用了openFileHelper(),最终到达了文件系统中的正确文件。这种方法的另一个优点是,openFile()是在应用程序的安全域中调用的,因此它可以访问文件,并且如果正确实现,如果您将ContentProvider所响应的URL公知,则它可以由完全不同的应用程序调用。
发布于 2011-06-03 00:12:10
如果你将实际的音频数据以安卓音频系统可以原生解释的格式(即mp3、3gpp、ogg)存储在数据库中,那么你可以这样做的一种方式是在服务中实现一个web服务器,让该服务打开SQLite数据库,使用Cursor.getBlob获取blob,然后通过web服务器将该Blob提供给MediaPlayer实例,方法是使用ByteArrayInputStream包装字节数组。我见过这样的实现(在那些情况下,它来自文件,而不是db,但也适用相同的原则)。
或者,你可以使用AudioTrack,如果音频不是PCM格式,你可以翻译它,然后播放它,自己处理音频管理:可能会有更多的工作,但更有效率。
请注意,这将是内存密集型的,而且性能可能会很差:对于一个5mb的MP3,你基本上必须将所有东西都保存在内存中,因为看起来安卓的SQLite接口并没有为你提供一个到blob的流接口。如果你正在加载多个媒体文件,then...bad的事情就会发生。
https://stackoverflow.com/questions/6217008
复制相似问题