我如何获得 Android MediaPlayer 运行 我的 http url?与其他 urls 它工作得很好
How I get the Android MediaPlayer running my http url? With other urls it works just fine
所以我想构建一个从我的后端服务器流式传输音乐的应用程序。为此,我用 MongoDB 创建了一个 Node JS Express API。然后我有一个像这样的 url:http://192.168.178.26:3000/stream?id=5dd5065f3b9a2a22149fdb09&format=mp3
当我在我的浏览器 (Opera) 中输入此 url 时,它将按预期播放音乐。也适用于 Postman。
然后我用 Android Studio 为 Android 编写了一个应用程序,它可以从给定的 url 流式传输音乐。当我尝试这个 url: https://www.ssaurel.com/tmp/mymusic.mp3
时效果很好,但我的不行。当我用我的 url 尝试这个时,MediaPlayer 在准备时失败了。错误如下:Prepare failed.: status=0x1
。我搜索了这个错误,发现它的意思是 unknown Error
.
我的后台代码:
const express = require('express');
const dbHandler = require('./src/dbHandler/dbHandler.js');
const fs = require('fs');
const app = express();
app.get('/stream', (req, res) => {
console.log(`Got stream request from ${req.ip}...`);
dbHandler.getFilePath(req.query.id, req.query.format).then((path) => {
let stat = fs.statSync(path);
res.set({
'Content-Type': 'audio/mpeg',
'Content-Length': stat.size,
'Accept-Ranges': 'bytes',
'Cache-Control': 'max-age=3600'
});
fs.createReadStream(path).pipe(res);
}).catch(err => {
res.status(400).send(err)
})
})
app.listen(3000, () => {
console.log(`Server is listening at 3000...`);
dbHandler.init();
})
如您所见,当服务器收到流请求时,它会将其打印出来。 dbHandler.getFilePath()
-方法只是 returns mp3 位置的完整路径,如下所示:D:/Music/song.mp3
。当我用邮递员尝试这个时,服务器收到一个请求并打印出来。然后 Postman 取回流,我就可以开始流式传输音乐了。
当我在智能手机上使用浏览器尝试此操作时,它也能正常工作。所以我可以通过智能手机的浏览器播放音乐,但不能使用我的应用程序。
请务必注意,当我尝试准备 MediaPlayer 时,服务器没有收到请求。所以它没有记录到控制台,提交了一个请求。
这是我应用程序的代码:
package sharemusic.truerushhunt3r.de.sharemusic.frontend;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;
import java.io.IOException;
import sharemusic.truerushhunt3r.de.sharemusic.R;
public class MainActivity extends AppCompatActivity {
//private GetHandler getHandler;
private boolean isPlaying = false;
private boolean initialStage = true;
private MediaPlayer player;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//getHandler = new GetHandler();
player = new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
ImageButton playButton = findViewById(R.id.playButton);
playButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isPlaying) {
Log.d("ShareMusic/Button", "Play pressed");
Toast.makeText(getApplicationContext(), "Play", Toast.LENGTH_SHORT).show();
if (initialStage) {
//new Player().execute("https://www.ssaurel.com/tmp/mymusic.mp3");
new Player().execute("http://192.168.178.26:3000/stream?id=5dd5065f3b9a2a22149fdb09&format=mp3");
} else {
if (!player.isPlaying()) {
player.start();
}
}
isPlaying = true;
} else {
Log.d("ShareMusic/Button", "Pause pressed");
Toast.makeText(getApplicationContext(), "Pause", Toast.LENGTH_SHORT).show();
if (player.isPlaying()) {
player.pause();
}
isPlaying = false;
}
}
});
}
@Override
protected void onPause() {
super.onPause();
if (player != null) {
player.reset();
player.release();
player = null;
}
}
class Player extends AsyncTask<String, Void, Boolean> {
@Override
protected Boolean doInBackground(String... strings) {
Boolean prepared = false;
try {
player.setDataSource(getApplicationContext(), Uri.parse(strings[0]));
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
initialStage = true;
isPlaying = false;
mp.stop();
mp.reset();
}
});
player.prepare();
prepared = true;
} catch(Exception e) {
Log.e("ShareMusic", e.getMessage());
}
return prepared;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if (aBoolean) {
player.start();
initialStage = false;
isPlaying = false;
} else {
Toast.makeText(getApplicationContext(), "Failed to prepare", Toast.LENGTH_SHORT).show();
initialStage = true;
isPlaying = false;
}
}
}
}
The Response Headers of my url: http://192.168.178.26:3000/stream?id=5dd5065f3b9a2a22149fdb09&format=mp3
The Response Headers of the working url: https://www.ssaurel.com/tmp/mymusic.mp3
我认为这与 http 和 https 协议无关。但我真的不知道现在该怎么办。 android (mp3) 支持我的音乐文件。是我的后端错误还是应用程序?我该如何解决这个问题?
有什么不明白的地方请追问。
Android API 等级:19 及以上
设备:华为P20 Lite
OS: 9.1.0
好的伙计们,我知道了!看看这个 website!基本上你必须写 cleartextTrafficPermitted="true"
而不是 cleartextTrafficPermitted="false"
来让魔法发生。
所以我的结论是,媒体播放器不喜欢 http 连接,但喜欢 https。但是我不明白为什么它不告诉我这个...
所以我想构建一个从我的后端服务器流式传输音乐的应用程序。为此,我用 MongoDB 创建了一个 Node JS Express API。然后我有一个像这样的 url:http://192.168.178.26:3000/stream?id=5dd5065f3b9a2a22149fdb09&format=mp3
当我在我的浏览器 (Opera) 中输入此 url 时,它将按预期播放音乐。也适用于 Postman。
然后我用 Android Studio 为 Android 编写了一个应用程序,它可以从给定的 url 流式传输音乐。当我尝试这个 url: https://www.ssaurel.com/tmp/mymusic.mp3
时效果很好,但我的不行。当我用我的 url 尝试这个时,MediaPlayer 在准备时失败了。错误如下:Prepare failed.: status=0x1
。我搜索了这个错误,发现它的意思是 unknown Error
.
我的后台代码:
const express = require('express');
const dbHandler = require('./src/dbHandler/dbHandler.js');
const fs = require('fs');
const app = express();
app.get('/stream', (req, res) => {
console.log(`Got stream request from ${req.ip}...`);
dbHandler.getFilePath(req.query.id, req.query.format).then((path) => {
let stat = fs.statSync(path);
res.set({
'Content-Type': 'audio/mpeg',
'Content-Length': stat.size,
'Accept-Ranges': 'bytes',
'Cache-Control': 'max-age=3600'
});
fs.createReadStream(path).pipe(res);
}).catch(err => {
res.status(400).send(err)
})
})
app.listen(3000, () => {
console.log(`Server is listening at 3000...`);
dbHandler.init();
})
如您所见,当服务器收到流请求时,它会将其打印出来。 dbHandler.getFilePath()
-方法只是 returns mp3 位置的完整路径,如下所示:D:/Music/song.mp3
。当我用邮递员尝试这个时,服务器收到一个请求并打印出来。然后 Postman 取回流,我就可以开始流式传输音乐了。
当我在智能手机上使用浏览器尝试此操作时,它也能正常工作。所以我可以通过智能手机的浏览器播放音乐,但不能使用我的应用程序。
请务必注意,当我尝试准备 MediaPlayer 时,服务器没有收到请求。所以它没有记录到控制台,提交了一个请求。
这是我应用程序的代码:
package sharemusic.truerushhunt3r.de.sharemusic.frontend;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;
import java.io.IOException;
import sharemusic.truerushhunt3r.de.sharemusic.R;
public class MainActivity extends AppCompatActivity {
//private GetHandler getHandler;
private boolean isPlaying = false;
private boolean initialStage = true;
private MediaPlayer player;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//getHandler = new GetHandler();
player = new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
ImageButton playButton = findViewById(R.id.playButton);
playButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isPlaying) {
Log.d("ShareMusic/Button", "Play pressed");
Toast.makeText(getApplicationContext(), "Play", Toast.LENGTH_SHORT).show();
if (initialStage) {
//new Player().execute("https://www.ssaurel.com/tmp/mymusic.mp3");
new Player().execute("http://192.168.178.26:3000/stream?id=5dd5065f3b9a2a22149fdb09&format=mp3");
} else {
if (!player.isPlaying()) {
player.start();
}
}
isPlaying = true;
} else {
Log.d("ShareMusic/Button", "Pause pressed");
Toast.makeText(getApplicationContext(), "Pause", Toast.LENGTH_SHORT).show();
if (player.isPlaying()) {
player.pause();
}
isPlaying = false;
}
}
});
}
@Override
protected void onPause() {
super.onPause();
if (player != null) {
player.reset();
player.release();
player = null;
}
}
class Player extends AsyncTask<String, Void, Boolean> {
@Override
protected Boolean doInBackground(String... strings) {
Boolean prepared = false;
try {
player.setDataSource(getApplicationContext(), Uri.parse(strings[0]));
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
initialStage = true;
isPlaying = false;
mp.stop();
mp.reset();
}
});
player.prepare();
prepared = true;
} catch(Exception e) {
Log.e("ShareMusic", e.getMessage());
}
return prepared;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if (aBoolean) {
player.start();
initialStage = false;
isPlaying = false;
} else {
Toast.makeText(getApplicationContext(), "Failed to prepare", Toast.LENGTH_SHORT).show();
initialStage = true;
isPlaying = false;
}
}
}
}
The Response Headers of my url: http://192.168.178.26:3000/stream?id=5dd5065f3b9a2a22149fdb09&format=mp3
The Response Headers of the working url: https://www.ssaurel.com/tmp/mymusic.mp3
我认为这与 http 和 https 协议无关。但我真的不知道现在该怎么办。 android (mp3) 支持我的音乐文件。是我的后端错误还是应用程序?我该如何解决这个问题?
有什么不明白的地方请追问。
Android API 等级:19 及以上
设备:华为P20 Lite
OS: 9.1.0
好的伙计们,我知道了!看看这个 website!基本上你必须写 cleartextTrafficPermitted="true"
而不是 cleartextTrafficPermitted="false"
来让魔法发生。
所以我的结论是,媒体播放器不喜欢 http 连接,但喜欢 https。但是我不明白为什么它不告诉我这个...