Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.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
Java Android MediaPlayer通过有线耳机播放时会出现口吃,而不是通过蓝牙_Java_Android_Bluetooth - Fatal编程技术网

Java Android MediaPlayer通过有线耳机播放时会出现口吃,而不是通过蓝牙

Java Android MediaPlayer通过有线耳机播放时会出现口吃,而不是通过蓝牙,java,android,bluetooth,Java,Android,Bluetooth,我有一个简单的音乐播放器应用程序(),当使用耳机时,它在棒棒糖中出现播放问题。音乐将正常播放30秒至5分钟,然后暂停约2-4秒,然后继续播放 这种行为似乎通常发生在屏幕关闭时,但获取CPU唤醒锁没有帮助 停顿的频率似乎随着时间的推移而加快。一开始是每小时一次,但是每次暂停之间的时间减少一半,直到几乎每分钟暂停一次 我在iTunes编码的aac文件中观察到了这种行为,其他人在MP3中也观察到了这种行为 这仅在通过有线耳机播放时观察到。我从未在蓝牙耳机上体验过这种行为 这可能是什么原因造成的?这似乎

我有一个简单的音乐播放器应用程序(),当使用耳机时,它在棒棒糖中出现播放问题。音乐将正常播放30秒至5分钟,然后暂停约2-4秒,然后继续播放

这种行为似乎通常发生在屏幕关闭时,但获取CPU唤醒锁没有帮助

停顿的频率似乎随着时间的推移而加快。一开始是每小时一次,但是每次暂停之间的时间减少一半,直到几乎每分钟暂停一次

我在iTunes编码的aac文件中观察到了这种行为,其他人在MP3中也观察到了这种行为

这仅在通过有线耳机播放时观察到。我从未在蓝牙耳机上体验过这种行为

这可能是什么原因造成的?这似乎是一个过程优先级问题,但我不知道如何解决这类问题

我还没有在安卓4.x上体验过这种情况

这是这个问题的答案

以下是一些相关的源代码:

清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.smithdtyler.prettygoodmusicplayer"
    android:versionCode="65"
    android:versionName="3.2.14" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="19" />

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_pgmp_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppBaseTheme" >

        <!-- Set the artist list to launch mode single task to prevent multiple instances -->
        <!-- This fixes an error where exiting the application just brings up another instance -->
        <!-- See https://developer.android.com/guide/topics/manifest/activity-element.html#lmode -->
        <activity
            android:name="com.smithdtyler.prettygoodmusicplayer.ArtistList"
            android:label="@string/app_name"
            android:launchMode="singleTask" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="android.intent.category.CATEGORY_APP_MUSIC " />
            </intent-filter>
        </activity>
        <activity
            android:name="com.smithdtyler.prettygoodmusicplayer.SettingsActivity"
            android:label="@string/title_activity_settings" >
        </activity>
        <activity
            android:name="com.smithdtyler.prettygoodmusicplayer.AlbumList"
            android:label="@string/title_activity_album_list" >
        </activity>
        <activity
            android:name="com.smithdtyler.prettygoodmusicplayer.SongList"
            android:label="@string/title_activity_song_list" >
        </activity>
        <activity
            android:name="com.smithdtyler.prettygoodmusicplayer.NowPlaying"
            android:exported="true"
            android:label="@string/title_activity_now_playing" >
        </activity>
        <!--
        The service has android:exported="true" because that's needed for
        control from the notification. Not sure why it causes a warning...
        -->
        <service
            android:name="com.smithdtyler.prettygoodmusicplayer.MusicPlaybackService"
            android:exported="true"
            android:icon="@drawable/ic_pgmp_launcher" >
        </service>

        <receiver
            android:name="com.smithdtyler.prettygoodmusicplayer.MusicBroadcastReceiver"
            android:enabled="true" >
            <intent-filter android:priority="2147483647" >
                <action android:name="android.intent.action.MEDIA_BUTTON" />
            </intent-filter>
        </receiver>
    </application>

</manifest>
MusicPlaybackService.startPlayingFile()

MusicLaybackService计时器任务

private void onTimerTick() {
    long currentTime = System.currentTimeMillis();
    if (pauseTime < currentTime) {
        pause();
    }
    updateResumePosition();
    sendUpdateToClients();
}

private void updateResumePosition(){
    long currentTime = System.currentTimeMillis();
    if(currentTime - 10000 > lastResumeUpdateTime){
        if(mp != null && songFile != null && mp.isPlaying()){
            int pos = mp.getCurrentPosition();
            SharedPreferences prefs = getSharedPreferences("PrettyGoodMusicPlayer", MODE_PRIVATE);
            Log.i(TAG,
                    "Preferences update success: "
                            + prefs.edit()
                            .putString(songFile.getParentFile().getAbsolutePath(),songFile.getName() + "~" + pos)
                            .commit());
        }
        lastResumeUpdateTime = currentTime;
    }
}


private void sendUpdateToClients() {
    List<Messenger> toRemove = new ArrayList<Messenger>();
    synchronized (mClients) {
        for (Messenger client : mClients) {
            Message msg = Message.obtain(null, MSG_SERVICE_STATUS);
            Bundle b = new Bundle();
            if (songFile != null) {
                b.putString(PRETTY_SONG_NAME,
                        Utils.getPrettySongName(songFile));
                b.putString(PRETTY_ALBUM_NAME, songFile.getParentFile()
                        .getName());
                b.putString(PRETTY_ARTIST_NAME, songFile.getParentFile()
                        .getParentFile().getName());
            } else {
                // songFile can be null while we're shutting down.
                b.putString(PRETTY_SONG_NAME, " ");
                b.putString(PRETTY_ALBUM_NAME, " ");
                b.putString(PRETTY_ARTIST_NAME, " ");
            }

            b.putBoolean(IS_SHUFFLING, this._shuffle);

            if (mp.isPlaying()) {
                b.putInt(PLAYBACK_STATE, PlaybackState.PLAYING.ordinal());
            } else {
                b.putInt(PLAYBACK_STATE, PlaybackState.PAUSED.ordinal());
            }
            // We might not be able to send the position right away if mp is
            // still being created
            // so instead let's send the last position we knew about.
            if (mp.isPlaying()) {
                lastDuration = mp.getDuration();
                lastPosition = mp.getCurrentPosition();
            }
            b.putInt(TRACK_DURATION, lastDuration);
            b.putInt(TRACK_POSITION, lastPosition);
            msg.setData(b);
            try {
                client.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
                toRemove.add(client);
            }
        }

        for (Messenger remove : toRemove) {
            mClients.remove(remove);
        }
    }
}
private void onTimerTick(){
长currentTime=System.currentTimeMillis();
如果(暂停时间<当前时间){
暂停();
}
updateResumePosition();
sendUpdateToClient();
}
私有void updateResumePosition(){
长currentTime=System.currentTimeMillis();
如果(currentTime-10000>lastResumeUpdateTime){
if(mp!=null&&songFile!=null&&mp.isPlaying()){
int pos=mp.getCurrentPosition();
SharedReferences prefs=GetSharedReferences(“PrettyGoodMusicLayer”,模式\私人);
Log.i(标签,
“首选项更新成功:”
+prefs.edit()
.putString(songFile.getParentFile().getAbsolutePath(),songFile.getName()+“~”+pos)
.commit());
}
lastResumeUpdateTime=currentTime;
}
}
私有void sendUpdateToClient(){
List toRemove=new ArrayList();
已同步(McClient){
用于(Messenger客户端:mClients){
Message msg=Message.get(空,消息服务状态);
Bundle b=新Bundle();
if(songFile!=null){
b、 putString(漂亮的歌名,
getPrettySongName(songFile));
b、 putString(PRETTY_相册_名称,songFile.getParentFile()
.getName());
b、 putString(PRETTY\u ARTIST\u NAME,songFile.getParentFile()
.getParentFile().getName());
}否则{
//关闭时,songFile可以为null。
b、 putString(PRETTY_SONG_NAME,”);
b、 putString(PRETTY_相册_NAME,”);
b、 putString(PRETTY_ARTIST_NAME,”);
}
b、 putBoolean(是SHUFFLING,this.\ushuffle);
if(mp.isPlaying()){
b、 putInt(PLAYBACK_STATE,PlaybackState.PLAYING.ordinal());
}否则{
b、 putInt(播放状态,PlaybackState.PAUSED.ordinal());
}
//如果议员不同意,我们可能无法立即发送该职位
//仍在创建中
//因此,让我们发送我们知道的最后一个位置。
if(mp.isPlaying()){
lastDuration=mp.getDuration();
lastPosition=mp.getCurrentPosition();
}
b、 putInt(轨道持续时间,最后持续时间);
b、 putInt(轨道位置,最后位置);
msg.setData(b);
试一试{
client.send(msg);
}捕获(远程异常){
e、 printStackTrace();
删除。添加(客户端);
}
}
对于(通讯器移除:toRemove){
mClients.remove(移除);
}
}
}
我从开发人员那里得到了一个:

我们使用一个单独的线程提前读取当前正在播放的文件:

->线程以大约256kb/s的速度读取文件,因此它读取文件的速度比mediaserver快 ->这使文件有很好的机会留在页面/磁盘缓存中 ->..这将因时髦的sd卡或其他IO暂停而“退出”的机会降至最低

代码位于此处: 代码不依赖于香草音乐的任何部分:如果您想尝试一下,只需将其放入您的项目中,然后执行以下操作:

onCreate {
 ...
 mReadaheadThread = new ReadaheadThread()
 ...
}
...
mMediaPlayer.setDataSource(path);
mReadaheadThread.setDataSource(path);
...

自从实施此更改以来,我没有遇到过这个问题。

我想指出,我也遇到过类似的问题。这些问题发生在摩托罗拉Moto G上,其CyanogenMod build 11-20141206-NIGHTLY-falcon(4.4.4)版本。我没有在其他设备上测试。我怀疑有音频聚焦问题。您是否正在打印音频焦点丢失和丢失日志?尝试在该区域进行调试。我有一个类似的问题,这是“意外”解决了当我搞砸了我的音频焦点听众
private void onTimerTick() {
    long currentTime = System.currentTimeMillis();
    if (pauseTime < currentTime) {
        pause();
    }
    updateResumePosition();
    sendUpdateToClients();
}

private void updateResumePosition(){
    long currentTime = System.currentTimeMillis();
    if(currentTime - 10000 > lastResumeUpdateTime){
        if(mp != null && songFile != null && mp.isPlaying()){
            int pos = mp.getCurrentPosition();
            SharedPreferences prefs = getSharedPreferences("PrettyGoodMusicPlayer", MODE_PRIVATE);
            Log.i(TAG,
                    "Preferences update success: "
                            + prefs.edit()
                            .putString(songFile.getParentFile().getAbsolutePath(),songFile.getName() + "~" + pos)
                            .commit());
        }
        lastResumeUpdateTime = currentTime;
    }
}


private void sendUpdateToClients() {
    List<Messenger> toRemove = new ArrayList<Messenger>();
    synchronized (mClients) {
        for (Messenger client : mClients) {
            Message msg = Message.obtain(null, MSG_SERVICE_STATUS);
            Bundle b = new Bundle();
            if (songFile != null) {
                b.putString(PRETTY_SONG_NAME,
                        Utils.getPrettySongName(songFile));
                b.putString(PRETTY_ALBUM_NAME, songFile.getParentFile()
                        .getName());
                b.putString(PRETTY_ARTIST_NAME, songFile.getParentFile()
                        .getParentFile().getName());
            } else {
                // songFile can be null while we're shutting down.
                b.putString(PRETTY_SONG_NAME, " ");
                b.putString(PRETTY_ALBUM_NAME, " ");
                b.putString(PRETTY_ARTIST_NAME, " ");
            }

            b.putBoolean(IS_SHUFFLING, this._shuffle);

            if (mp.isPlaying()) {
                b.putInt(PLAYBACK_STATE, PlaybackState.PLAYING.ordinal());
            } else {
                b.putInt(PLAYBACK_STATE, PlaybackState.PAUSED.ordinal());
            }
            // We might not be able to send the position right away if mp is
            // still being created
            // so instead let's send the last position we knew about.
            if (mp.isPlaying()) {
                lastDuration = mp.getDuration();
                lastPosition = mp.getCurrentPosition();
            }
            b.putInt(TRACK_DURATION, lastDuration);
            b.putInt(TRACK_POSITION, lastPosition);
            msg.setData(b);
            try {
                client.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
                toRemove.add(client);
            }
        }

        for (Messenger remove : toRemove) {
            mClients.remove(remove);
        }
    }
}
onCreate {
 ...
 mReadaheadThread = new ReadaheadThread()
 ...
}
...
mMediaPlayer.setDataSource(path);
mReadaheadThread.setDataSource(path);
...