Android MediaPlayer 无法在 API 26+ 上播放音乐
Android MediaPlayer won't play music on API 26+
我有一个为用户流式传输音乐的应用程序,当我在设备 运行 API 26 或更高版本音乐无法播放,也不会显示错误消息,附件是我使用 API 28 设备时的日志。
我尝试过的:
- MediaPlayer.setAudioStreamType(int streamtype) 已弃用所以我为 26
以上的 API 实现了 AudioAttributes
- 不同类型的 mp3 文件,但它们在 api 25 及以下播放相同,当我尝试使用 API 26 的设备或模拟器时没有任何反应
在文档和示例中搜索,但看起来都一样,我看不出我的代码有什么不同
private void playMusic() {
try {
mMediaPlayer.reset();
// For Android API 26 (Android 8 Oreo) and newer, specify AudioAttributes.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Log.d("Record", "setAudioAttributes()");
AudioAttributes.Builder builder = new AudioAttributes.Builder();
builder.setUsage(AudioAttributes.USAGE_MEDIA);
builder.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC);
AudioAttributes attributes = builder.build();
mMediaPlayer.setAudioAttributes(attributes);
} else {
Log.d("Record", "setAudioStreamType()");
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
mMediaPlayer.setDataSource(String.format("http://www.server.com/mp3/%s.mp3", mp3File));
mMediaPlayer.prepareAsync();
mMediaPlayer.start();
} catch (IOException e) {
Log.d("Record", "error playing mp3");
e.printStackTrace();
}
}
日志
2019-04-04 17:51:38.911 2947-24864/com.roneskinder.karaoke
V/MediaPlayer: resetDrmState: mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false
2019-04-04 17:51:38.911 2947-24864/com.roneskinder.karaoke V/MediaPlayer: cleanDrmObj: mDrmObj=null mDrmSessionId=null
2019-04-04 17:51:38.913 2947-3054/com.roneskinder.karaoke D/EGL_emulation: eglMakeCurrent: 0xe830ce20: ver 3 0 (tinfo 0xe8315bd0)
2019-04-04 17:51:38.915 2947-24864/com.roneskinder.karaoke V/MediaHTTPService: MediaHTTPService(android.media.MediaHTTPService@aa03fa3): Cookies: null
2019-04-04 17:51:38.920 2947-4147/com.roneskinder.karaoke V/MediaHTTPService: makeHTTPConnection: CookieHandler (java.net.CookieManager@ead45b3) exists.
2019-04-04 17:51:38.920 2947-4147/com.roneskinder.karaoke V/MediaHTTPService: makeHTTPConnection(android.media.MediaHTTPService@aa03fa3): cookieHandler: java.net.CookieManager@ead45b3 Cookies: null
请使用此代码。
MediaPlayer player = new MediaPlayer();
player.setDataSource("http://www.server.com/mp3/%s.mp3");
player.setLooping(false);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.prepareAsync();
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer player) {
player.start();
}
});
您需要为该主机定义 res/xml/network_security_config.xml
并允许 HTTP
:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">server.com</domain>
</domain-config>
</network-security-config>
那个network_security_config.xml
也需要在Manifest.xml
中引用:
<?xml version="1.0" encoding="utf-8"?>
<manifest
...>
<application
android:networkSecurityConfig="@xml/network_security_config"
...>
...
</application>
</manifest>
SDK documentation 对此进行了详细解释 - 这适用于应用创建的所有网络流量。
与其降低安全标准,不如将连接升级到 HTTPS
。
关于那个已弃用的方法 .setAudioStreamType()
,请改用 .setAudioAttributes() - 正如您的代码已经做的那样。这里好像不是"main problem";验证了。
只需在 application
标签中添加一行
<application
.......
android:usesCleartextTraffic="true"
.......>
.......
</application>
我有一个为用户流式传输音乐的应用程序,当我在设备 运行 API 26 或更高版本音乐无法播放,也不会显示错误消息,附件是我使用 API 28 设备时的日志。
我尝试过的:
- MediaPlayer.setAudioStreamType(int streamtype) 已弃用所以我为 26 以上的 API 实现了 AudioAttributes
- 不同类型的 mp3 文件,但它们在 api 25 及以下播放相同,当我尝试使用 API 26 的设备或模拟器时没有任何反应
在文档和示例中搜索,但看起来都一样,我看不出我的代码有什么不同
private void playMusic() { try { mMediaPlayer.reset(); // For Android API 26 (Android 8 Oreo) and newer, specify AudioAttributes. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { Log.d("Record", "setAudioAttributes()"); AudioAttributes.Builder builder = new AudioAttributes.Builder(); builder.setUsage(AudioAttributes.USAGE_MEDIA); builder.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC); AudioAttributes attributes = builder.build(); mMediaPlayer.setAudioAttributes(attributes); } else { Log.d("Record", "setAudioStreamType()"); mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); } mMediaPlayer.setDataSource(String.format("http://www.server.com/mp3/%s.mp3", mp3File)); mMediaPlayer.prepareAsync(); mMediaPlayer.start(); } catch (IOException e) { Log.d("Record", "error playing mp3"); e.printStackTrace(); } }
日志
2019-04-04 17:51:38.911 2947-24864/com.roneskinder.karaoke
V/MediaPlayer: resetDrmState: mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false
2019-04-04 17:51:38.911 2947-24864/com.roneskinder.karaoke V/MediaPlayer: cleanDrmObj: mDrmObj=null mDrmSessionId=null
2019-04-04 17:51:38.913 2947-3054/com.roneskinder.karaoke D/EGL_emulation: eglMakeCurrent: 0xe830ce20: ver 3 0 (tinfo 0xe8315bd0)
2019-04-04 17:51:38.915 2947-24864/com.roneskinder.karaoke V/MediaHTTPService: MediaHTTPService(android.media.MediaHTTPService@aa03fa3): Cookies: null
2019-04-04 17:51:38.920 2947-4147/com.roneskinder.karaoke V/MediaHTTPService: makeHTTPConnection: CookieHandler (java.net.CookieManager@ead45b3) exists.
2019-04-04 17:51:38.920 2947-4147/com.roneskinder.karaoke V/MediaHTTPService: makeHTTPConnection(android.media.MediaHTTPService@aa03fa3): cookieHandler: java.net.CookieManager@ead45b3 Cookies: null
请使用此代码。
MediaPlayer player = new MediaPlayer();
player.setDataSource("http://www.server.com/mp3/%s.mp3");
player.setLooping(false);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.prepareAsync();
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer player) {
player.start();
}
});
您需要为该主机定义 res/xml/network_security_config.xml
并允许 HTTP
:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">server.com</domain>
</domain-config>
</network-security-config>
那个network_security_config.xml
也需要在Manifest.xml
中引用:
<?xml version="1.0" encoding="utf-8"?>
<manifest
...>
<application
android:networkSecurityConfig="@xml/network_security_config"
...>
...
</application>
</manifest>
SDK documentation 对此进行了详细解释 - 这适用于应用创建的所有网络流量。
与其降低安全标准,不如将连接升级到 HTTPS
。
关于那个已弃用的方法 .setAudioStreamType()
,请改用 .setAudioAttributes() - 正如您的代码已经做的那样。这里好像不是"main problem";验证了。
只需在 application
标签中添加一行
<application
.......
android:usesCleartextTraffic="true"
.......>
.......
</application>