- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在使用以下代码时遇到问题。我在我的 MediaController 上调用了 setPrevNextListener 并为 Prev 和 Next 定义了两个 onClickListeners。当我单击下一个按钮而不是前进一首轨道时,我前进了两首轨道。这似乎是由于以某种方式调用了 onCompletion。 MediaPlayer.reset() 是否调用 onCompletion?我包含了 logcat 输出和我的代码。如果我做错了什么,请告诉我。提前致谢。
日志:
02-24 00:36:34.826: D/MP(6675): Next Button Clicked, index was: 0
02-24 00:36:34.837: D/MP(6675): About to call Reset()
02-24 00:36:34.906: D/MP(6675): Inside setUpPlayer
02-24 00:36:34.917: D/MP(6675): Called setDataSource with index: 1
02-24 00:36:34.917: D/MP(6675): Leaving setUpPlayer
02-24 00:36:34.917: D/MP(6675): About to call prepareAsync()
02-24 00:36:34.937: D/MP(6675): Leaving next button
02-24 00:36:35.226: E/MediaPlayer(6675): Attempt to call getDuration without a valid mediaplayer
02-24 00:36:35.226: E/MediaPlayer(6675): error (-38, 0)
02-24 00:36:35.276: E/MediaPlayer(6675): Error (-38,0)
02-24 00:36:35.287: D/MP(6675): Inside onCompletion
02-24 00:36:35.337: D/MP(6675): About to call Reset()
02-24 00:36:35.347: D/MP(6675): Inside setUpPlayer
02-24 00:36:35.356: D/MP(6675): Called setDataSource with index: 2
02-24 00:36:35.356: D/MP(6675): Leaving setUpPlayer
02-24 00:36:35.356: D/MP(6675): About to call prepareAsync()
02-24 00:36:35.377: D/MP(6675): Leaving onCompletion
02-24 00:36:36.517: D/MP(6675): Inside onPrepared, index is: 2
02-24 00:36:36.577: D/MP(6675): Leaving onPrepared
代码:
public class MusicPlayerActivity extends Activity implements OnPreparedListener, OnCompletionListener, MediaController.MediaPlayerControl {
private MediaPlayer mp;
private MediaController mc;
private SonarDatabase db;
private SubsonicAPIConnector sonic;
ArrayList<String> songs;
int index = 0;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.music_player);
// Get params from intent
Intent i = getIntent();
String albumId = i.getStringExtra("albumId");
String artistId = i.getStringExtra("artistId");
String albumName = i.getStringExtra("albumName");
String songName = i.getStringExtra("songName");
String songId = i.getStringExtra("songId");
String coverArt = "al-"+albumId+".jpeg";
String duration = i.getStringExtra("duration");
Log.d("MP", "results: albumName:" + albumName + ", songName: " + songName + ", songId: "
+ songId + ", duration: " + duration + ", coverArt: " + coverArt + ", artistId: "
+ artistId + ", albumId: " + albumId);
db = new SonarDatabase(getApplicationContext());
sonic = new SubsonicAPIConnector(db.getURL(), db.getUsername(), db.getPassword());
String artistName = db.getArtistNameById(artistId);
setTitle("Now Playing");
songs = db.getSongListForAlbum(albumId);
index = songs.indexOf(songId);
Log.d("MP", "songid: " + songId + ", index: " + index);
// Update text views with song information
TextView txtArtist = (TextView) findViewById(R.id.txtArtistName);
txtArtist.setText(artistName);
TextView txtAlbum = (TextView) findViewById(R.id.txtAlbumName);
txtAlbum.setText(albumName);
TextView txtSong = (TextView) findViewById(R.id.txtSongName);
txtSong.setText(songName);
// Show the album art
File img = new File(this.getFilesDir()+"/covers/"+coverArt);
if(img.exists()) {
Log.d("MP", "Found image at: " + img.toString());
ImageView imgView = (ImageView) findViewById(R.id.cover_art);
imgView.setImageBitmap(BitmapFactory.decodeFile(img.getPath()));
} else {
Log.d("MP", "Couldn't find image: " + img.toString());
}
// Create the media player and controller
mp = new MediaPlayer();
mp.setOnPreparedListener(this);
mp.setOnCompletionListener(this);
mc = new NonHidingMediaController(this);
mc.setPrevNextListeners(new View.OnClickListener() {
@Override
public void onClick(View v) {
// next button clicked
Log.d("MP", "Next Button Clicked, index was: " + index);
playNextTrack();
Log.d("MP", "Leaving next button");
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
// previous button clicked
Log.d("MP", "Previous button clicked, index was: " + index);
if(mp.isPlaying() && mp.getCurrentPosition() < 2000 && index != 0) {
Log.d("MP", "Start the prior song.");
playPreviousTrack();
} else {
Log.d("MP", "Restart this song.");
restartCurrentTrack();
}
Log.d("MP", "Leaving previous button");
}
});
mc.setMediaPlayer(this);
setUpPlayer();
Log.d("MP", "About to call prepareAsync()");
mp.prepareAsync();
}
@Override
public void onCompletion(MediaPlayer mp) {
Log.d("MP", "Inside onCompletion");
//TODO add code for scrobbling here.
playNextTrack();
Log.d("MP", "Leaving onCompletion");
}
private void playNextTrack() {
index++;
TextView txtSong = (TextView) findViewById(R.id.txtSongName);
txtSong.setText(db.getSongNameById(songs.get(index)));
Log.d("MP", "About to call Reset()");
mp.reset();
setUpPlayer();
Log.d("MP", "About to call prepareAsync()");
mp.prepareAsync();
}
private void playPreviousTrack() {
index--;
TextView txtSong = (TextView) findViewById(R.id.txtSongName);
txtSong.setText(db.getSongNameById(songs.get(index)));
Log.d("MP", "About to call Reset()");
mp.reset();
setUpPlayer();
Log.d("MP", "About to call prepareAsync()");
mp.prepareAsync();
}
private void restartCurrentTrack() {
mp.seekTo(0);
}
public void onPrepared(MediaPlayer mp) {
Log.d("MP", "Inside onPrepared, index is: " + index);
mc.setMediaPlayer(this);
mc.setAnchorView(findViewById(R.id.music_player_view));
mp.start();
handler.post(new Runnable() {
public void run() {
mc.setEnabled(true);
mc.show();
}
});
Log.d("MP", "Leaving onPrepared");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_music_player, menu);
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("MP", "OnTouchEvent called");
mc.show();
return false;
}
private void setUpPlayer() {
Log.d("MP", "Inside setUpPlayer");
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mp.setDataSource(sonic.streamString("&id=" + songs.get(index)));
Log.d("MP", "Called setDataSource with index: " + index);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException 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();
}
Log.d("MP", "Leaving setUpPlayer");
}
@Override
protected void onStop() {
super.onStop();
mc.hide();
mp.stop();
mp.release();
}
public void start() {
mp.start();
}
public void pause() {
mp.pause();
}
public int getDuration() {
return mp.getDuration();
}
public int getCurrentPosition() {
return mp.getCurrentPosition();
}
public void seekTo(int i) {
mp.seekTo(i);
}
public boolean isPlaying() {
return mp.isPlaying();
}
public int getBufferPercentage() {
return 0;
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
public class NonHidingMediaController extends MediaController {
public NonHidingMediaController(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NonHidingMediaController(Context context, boolean useFastForward) {
super(context, useFastForward);
}
public NonHidingMediaController(Context context) {
super(context);
}
@Override
public void show(int timeout) {
super.show(0);
}
}
}
最佳答案
我深入研究了 android 源代码,发现任何未处理的错误都会导致 MediaPlayer 调用 onCompletion 处理程序。在这种情况下,您似乎是在空闲、已初始化或错误状态下调用 getDuration。可能从媒体 Controller 内部。我建议在任何调用 getDuration 的地方之前添加一些 Log.d() 以查看导致问题的调用位置。
关于Android MediaPlayer.reset() 正在调用 onCompletion,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15049097/
我有一个加号/减号按钮,希望用户不能选择超过 20 个但不知道如何让它工作。我尝试使用 min="1"max="5 属性,但它们不起作用。这是我的代码和一个 fiddle 链接。https://jsf
我正在尝试复制顶部底部图,如示例 here但它没有正确渲染(紫色系列有 +ve 和 -ve 值,绿色为负值)留下杂乱的人工制品。我也在努力创建一个玩具示例来复制这个问题,所以我希望尽管我缺乏数据,但有
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 已关闭 6 年前。 社区去年审查了是
这个问题在这里已经有了答案: Adding two positive integers gives negative answer.Why? (4 个答案) 关闭 5 年前。 我遇到了一个奇怪的问题
有谁知道如何将字符串值类型 -4,5 或 5,4 转换为 double -4.5 或 5.4? 最佳答案 只需使用 Double.parseDouble(Locale, String); 糟糕,我很困
我正在尝试根据 TextBlob 分类插入一个仅包含“正”或“负”字符串的新数据框列:对于我的 df 的第一行,结果是 ( pos , 0.75, 0.2499999999999997)我想要' 正
我对 VBA 非常陌生,无法理解如何在一个循环中完成 2 个任务。我非常感谢您的帮助。 我已经能够根据第 3 列中的数据更改第 2 列中的数值,但我不明白如何将负值的字体更改为红色。 表格的大小每月都
欢迎, 我正在使用 jquery 通过 POST 发送表单。 这就是我获得值(value)的方式。 var mytext = $("#textareaid").val(); var dataStrin
double d = 0; // random decimal value with it's integral part within the range of Int32 and always p
我有这个字符串: var a='abc123#xyz123'; 我想构建 2 个正则表达式替换函数: 1) 用 '*' 替换所有确实有 future '#'的字符(不包括'#') 所以结果应该是这样的
我正在使用 DialogFragment。当用户从 Gmail 平板电脑应用程序的屏幕与下面示例图片中的编辑文本进行交互时,我希望正面和负面按钮保持在键盘上方。 在我的尝试中不起作用,这是我的 Dia
从组装艺术一书中,我复制了这句话: In the two’s complement system, the H.O. bit of a number is a sign bit. If the H.O
是否有更好更优雅的方法来实现下面的简单代码(diffYear、A 和 B 是数字): diffYear = yearA - yearB; if (diffYear == 0) { A = B
我正在设计一种语言,并尝试确定 true 应该是 0x01 还是 0xFF。显然,所有非零值都将转换为 true,但我正在尝试确定确切的内部表示。 每种选择的优点和缺点是什么? 最佳答案 没关系,只要
在我的 dialogfragment 类的 OnCreateDialog 中,我正在这样做: AlertDialog.Builder builder = new AlertDialog.Builder
这个问题在这里已经有了答案: Resolving ambiguous overload on function pointer and std::function for a lambda usin
我偶然发现了一个奇怪的 NSDecimalNumber 行为:对于某些值,调用 integerValue、longValue、longLongValue 等,返回意想不到的值(value)。示例: l
这个问题在这里已经有了答案: Resolving ambiguous overload on function pointer and std::function for a lambda using
我有这个正则表达式来测试用户输入是否有效: value.length === 0 || value === '-' || (!isNaN(parseFloat(value)) && /^-?\d+\.
我想用高斯混合模型拟合数据集,数据集包含大约 120k 个样本,每个样本有大约 130 个维度。当我使用 matlab 执行此操作时,我运行脚本(簇号为 1000): gm = fitgmdist(d
我是一名优秀的程序员,十分优秀!