我需要在手机(任何位置)的某个地方获取文件的完整路径并使用MediaPlayer播放。
我听说过使用Android的文件选择器(通过启动意图)。
在测试代码中,我只是将一个资源复制到另一个文件,得到了路径并将其传递给AudioVideoEntry(正如我稍后展示的,一个围绕MediaPlayer的非常简单和薄的包装器)
这是我写的测试代码:
private String ave_path;
private String ave_file_name = "my_media_content";
private InputStream ave_fis;
private OutputStream ave_fos;
public void testAudioVideoEntry()
{
//get the Activity
Module_JournalEntry journalentryactivity = getActivity();
//open an InputStream to a resource file (in this case strokes.mp3)
ave_fis = journalentryactivity.getResources().openRawResource(module.jakway.JournalEntry.R.raw.strokes);
//open an OutputStream to a new file
try {
ave_fos = journalentryactivity.openFileOutput(ave_file_name,
Context.MODE_PRIVATE);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
assertTrue(false);
}
catch(Exception e)
{
assertTrue(false);
}
//copy the data from the resource into
//the OutputStream
int data;
try {
while((data = ave_fis.read()) != -1)
{
ave_fos.write(data);
}
assertTrue(true);
}
catch(Exception e)
{
assertTrue(false);
}
//get the full path of the file we wrote to
ave_path = journalentryactivity.getFileStreamPath(ave_file_name).toString();
//and construct a new object of AudioVideoEntry with that path
AudioVideoEntry ave = new AudioVideoEntry(ave_path);
//register an error listener via MediaPlayer's setOnErrorListener
ave.setOnErrorListener(new OnErrorListener()
{
@Override
public boolean onError(MediaPlayer mp,
int what, int extra) {
Log.e("MEDIAPLAYER ERRORS",
"what: " + what + " extra: " + extra);
assertTrue(false);
// TODO Auto-generated method stub
return false;
}
});
ave.prepareMedia();
ave.playMedia();
try {
ave_fis.close();
ave_fos.close();
}
catch(Exception e)
{
assertTrue(false);
e.printStackTrace();
}
AudioVideoEntry基本上是一个围绕MediaPlayer的瘦包装器,它可以保存自己的路径:
public class AudioVideoEntry
{
private String path_to_audio_file;
private MediaPlayer mediaplayer;
/**
* Initialize the internal MediaPlayer
* from the String parameter
* @param set_path_to_audio_file
*/
public AudioVideoEntry(String set_path_to_audio_file)
{
path_to_audio_file = set_path_to_audio_file;
mediaplayer = new MediaPlayer();
try {
mediaplayer.setDataSource(path_to_audio_file);
mediaplayer.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public AudioVideoEntry(FileDescriptor fd)
{
mediaplayer = new MediaPlayer();
try {
mediaplayer.setDataSource(fd);
mediaplayer.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Begin playing media
*/
public void prepareMedia()
{
try {
mediaplayer.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* play media
* don't forget to prepare() if necessary
*/
public void playMedia()
{
mediaplayer.start();
}
/**
* pause the media
* can be played later
*/
public void pauseMedia()
{
mediaplayer.pause();
}
/**
* stop media
*/
public void stopMedia()
{
mediaplayer.stop();
}
public void setOnErrorListener(OnErrorListener listener)
{
mediaplayer.setOnErrorListener(listener);
}
}
这里是JUnit测试的logcat输出(测试成功,实际结果 - 如logat所示 - 不是)
02-07 09:40:23.129: ERROR/MediaPlayer(1209): error (1, -2147483648)
02-07 09:40:23.139: WARN/System.err(1209): java.io.IOException: Prepare failed.: status=0x1
02-07 09:40:23.149: WARN/System.err(1209): at android.media.MediaPlayer.prepare(Native Method)
02-07 09:40:23.149: WARN/System.err(1209): at module.jakway.JournalEntry.AudioVideoEntry.<init>(AudioVideoEntry.java:39)
02-07 09:40:23.149: WARN/System.err(1209): at module.jakway.JournalEntry.test.Module_JournalEntryTest.testAudioVideoEntry(Module_JournalEntryTest.java:182)
02-07 09:40:23.149: WARN/System.err(1209): at java.lang.reflect.Method.invokeNative(Native Method)
02-07 09:40:23.149: WARN/System.err(1209): at java.lang.reflect.Method.invoke(Method.java:507)
02-07 09:40:23.159: WARN/System.err(1209): at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:204)
02-07 09:40:23.159: WARN/System.err(1209): at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:194)
02-07 09:40:23.159: WARN/System.err(1209): at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:186)
02-07 09:40:23.159: WARN/System.err(1209): at junit.framework.TestCase.runBare(TestCase.java:127)
02-07 09:40:23.169: WARN/System.err(1209): at junit.framework.TestResult$1.protect(TestResult.java:106)
02-07 09:40:23.169: WARN/System.err(1209): at junit.framework.TestResult.runProtected(TestResult.java:124)
02-07 09:40:23.169: WARN/System.err(1209): at junit.framework.TestResult.run(TestResult.java:109)
02-07 09:40:23.179: WARN/System.err(1209): at junit.framework.TestCase.run(TestCase.java:118)
02-07 09:40:23.179: WARN/System.err(1209): at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
02-07 09:40:23.179: WARN/System.err(1209): at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
02-07 09:40:23.179: WARN/System.err(1209): at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:529)
02-07 09:40:23.189: WARN/System.err(1209): at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
02-07 09:40:23.189: ERROR/MediaPlayer(1209): prepareAsync called in state 0
02-07 09:40:23.189: WARN/System.err(1209): java.lang.IllegalStateException
02-07 09:40:23.189: WARN/System.err(1209): at android.media.MediaPlayer.prepare(Native Method)
02-07 09:40:23.189: WARN/System.err(1209): at module.jakway.JournalEntry.AudioVideoEntry.prepareMedia(AudioVideoEntry.java:79)
02-07 09:40:23.199: WARN/System.err(1209): at module.jakway.JournalEntry.test.Module_JournalEntryTest.testAudioVideoEntry(Module_JournalEntryTest.java:197)
02-07 09:40:23.199: WARN/System.err(1209): at java.lang.reflect.Method.invokeNative(Native Method)
02-07 09:40:23.199: WARN/System.err(1209): at java.lang.reflect.Method.invoke(Method.java:507)
02-07 09:40:23.199: WARN/System.err(1209): at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:204)
02-07 09:40:23.199: WARN/System.err(1209): at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:194)
02-07 09:40:23.199: WARN/System.err(1209): at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:186)
02-07 09:40:23.199: WARN/System.err(1209): at junit.framework.TestCase.runBare(TestCase.java:127)
02-07 09:40:23.199: WARN/System.err(1209): at junit.framework.TestResult$1.protect(TestResult.java:106)
02-07 09:40:23.199: WARN/System.err(1209): at junit.framework.TestResult.runProtected(TestResult.java:124)
02-07 09:40:23.199: WARN/System.err(1209): at junit.framework.TestResult.run(TestResult.java:109)
02-07 09:40:23.199: WARN/System.err(1209): at junit.framework.TestCase.run(TestCase.java:118)
02-07 09:40:23.199: WARN/System.err(1209): at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
02-07 09:40:23.199: WARN/System.err(1209): at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
02-07 09:40:23.199: WARN/System.err(1209): at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:529)
02-07 09:40:23.199: WARN/System.err(1209): at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
02-07 09:40:23.199: ERROR/MediaPlayer(1209): start called in state 0
02-07 09:40:23.199: ERROR/MediaPlayer(1209): error (-38, 0)
编辑:为什么MediaPlayer失败?
谢谢! dragonwrenn
答案 0 :(得分:11)
在AudioVideoEntry.prepareMedia()方法中第二次调用MediaPlayer.prepare()(已经在AudioVideoEntry ctor中调用过一次)很容易被发现,就像其他人注意到的那样。
找到更难的错误是第一个错误。
我使用了一个Ogg文件进行测试。
第一个线索来自android-platform - Ogg on G1
中的davidsparks回复(最后一个)只要文件具有.ogg扩展名,就应该使用 内置音乐播放器。我们依赖文件扩展名,因为有 没有媒体扫描仪的集中文件识别器。
第二条线索来自[android-developers] Re: File permission about MediaPlayer
由于Android安全模型,MediaPlayer没有root 访问权限。它可以访问SD卡,但无法访问私有 app目录。
您的应用可以明确授予MediaPlayer临时访问权限 打开文件并将文件描述符传递给的文件 MediaPlayer使用setDataSource(FileDescriptor fd)方法。
如果查看输出流的绝对路径,您会看到它位于应用程序包名称目录下的/data/data
目录中。
请原谅时间戳 - 我向后工作以获取要在OS2.1update1(API7)模拟器上显示的数据。
您的代码有:
String ave_file_name = "my_media_content";
ave_fos = activity.openFileOutput(ave_file_name, Context.MODE_PRIVATE);
DDMS显示:
02-10 05:10:28.253: WARN/MediaPlayer(1992): info/warning (1, 26)
02-10 05:10:28.253: ERROR/PlayerDriver(31): Command PLAYER_SET_DATA_SOURCE completed with an error or info PVMFErrNotSupported
02-10 05:10:28.253: ERROR/MediaPlayer(1992): error (1, -4)
02-10 05:10:28.274: WARN/PlayerDriver(31): PVMFInfoErrorHandlingComplete
如果我们将 JUST 文件更改为MODE_WORLD_READABLE:
String ave_file_name = "my_media_content";
ave_fos = activity.openFileOutput(ave_file_name, Context.MODE_WORLD_READABLE);
DDMS没有改善:
02-10 05:08:28.543: WARN/MediaPlayer(1900): info/warning (1, 26)
02-10 05:08:28.553: ERROR/PlayerDriver(31): Command PLAYER_SET_DATA_SOURCE completed with an error or info PVMFErrNotSupported
02-10 05:08:28.553: ERROR/MediaPlayer(1900): error (1, -4)
02-10 05:08:28.563: WARN/PlayerDriver(31): PVMFInfoErrorHandlingComplete
如果我们将 JUST 的文件扩展名更改为ogg
:
String ave_file_name = "my_media_content.ogg";
ave_fos = activity.openFileOutput(ave_file_name, Context.MODE_PRIVATE);
我们对DDMS输出进行了更改:
02-10 04:59:30.153: ERROR/MediaPlayerService(31): error: -2
02-10 04:59:30.163: ERROR/MediaPlayer(1603): Unable to to create media player
但是当我们合并两个时:
String ave_file_name = "my_media_content.ogg";
ave_fos = activity.openFileOutput(ave_file_name, Context.MODE_WORLD_READABLE);
DDMS没有显示错误。
答案 1 :(得分:3)
有些观点:
prepare()
(一次在构造函数中,另一次显式调用)。这可能是抛出IllegalStateException
的原因之一。 此外,您尝试在应用程序中播放的文件是?如果是这样,你为什么要创建一个流?如果该文件已经在应用程序中(并且在/res/raw
内,您可以尝试通过创建媒体播放器对象来节省使用prepare()
的麻烦:
mediaplayer = new MediaPlayer.create(this,R.raw.resource-name here);
create函数调用prepare()
3.如果MediaPlayer中的任何一个阶段失败,您也可以尝试使用reset()
函数,从而导致MediaPlayer对象进入错误状态。使用reset()
会将其恢复为空闲状态
4.我最后一次收到该错误status=0x1
消息,结果发现我没有为文件(Manifest中的外部存储等)设置正确的权限,而且有些文件放在不正确的文件夹中。您可能还想看一下。
如果不起作用,请告诉我,
我们可以尝试其他的东西
斯利拉姆。
答案 2 :(得分:0)
您似乎正在调用prepare()
两次,首先是AudioVideoEntry
的构造函数,第二个是方法prepareMedia()
,这就是为什么它会给IllegalStateException
。
如果您仔细阅读documentation,您可以理解状态图以及为什么会出现此类例外情况。