I have to stream an audio file from Android media player from an application. Initially the file to be streamed was coming from a Http:// url and for which I was Using code-
public void playSample() {
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
mediaPlayer = new MediaPlayer();
}
#Override
protected Void doInBackground(Void... arg0) {
try {
try {
mediaPlayer.setDataSource("http://an.http.url/");
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
Log.e("AudioFileError", "Could not open file for playback.", e);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
pd.dismiss();
}
};
task.execute((Void[]) null);
}
This code is working as desired with http based file, but now the URL for Audio file was changed to https:// one(i.e., https://an.https.url/) and the code fails with an exception in
mediaPlayer.prepare();
The exception is
Prepare failed.: status=0x1
Please suggest a solution for it.
Media player in android <4.x supports only HTTP and 4.x n above support for BOTH http and https , so while using https with older API level, please think over it use http instead of https.
After long struggle i found solution,
Add below code before setDataSource().
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
MySSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
sf.fixHttpsURLConnection();
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
} catch (Exception e) {
e.printStackTrace();
}
#update1
Those who are using this answer, Read this caution from developer.android.com. Caution: Many web sites describe a poor alternative solution which is to install a TrustManager that does nothing. If you do this you might as well not be encrypting your communication, because anyone can attack your users at a public Wi-Fi hotspot by using DNS tricks to send your users' traffic through a proxy of their own that pretends to be your server
Related
i am trying to download a hls file using the HLSDownloader, but i am not getting the best results yet. My code:
// Main download function
AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
downloadHls(VIDEO_URL);
return null;
}
};
asyncTask.execute();
...
// This is the main tool to download hls
private HlsDownloader hlsDownloader;
private void downloadHls(String masterHLS) {
hlsDownloader = getHlsDownloader(masterHLS);
try {
hlsDownloader.download(this);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private HlsDownloader getHlsDownloader(String mediaPlaylistUri) {
File downloadFolder = new File(getFilesDir(), "video_id_2");
SimpleCache cache = new SimpleCache(downloadFolder, new NoOpCacheEvictor());
DefaultHttpDataSourceFactory factory = new DefaultHttpDataSourceFactory("ExoPlayer", null);
CacheDataSource cacheDataSource =
new CacheDataSource(cache, factory.createDataSource(), CacheDataSource.FLAG_BLOCK_ON_CACHE);
// Create a downloader for the first variant in a master playlist.
return new HlsDownloader(
Uri.parse(mediaPlaylistUri), new DownloaderConstructorHelper(cache, factory));
}
It seems the download starts and i am getting the progress of the downloading, but i can not access the downloaded file (maybe not exists), so i do not know if i am coding well. Some help it would be appreciated.
EDITED:
Currently i've got the download in multiple chunks (i forgotten to add the write permission in the manifest) all named like *.ve.exo extension files, but i do not know how to play them, any idea?
I'm trying to play an rtsp stream using MediaPlayer in android and the application seems to always become stuck on MediaPlayer.prepare();
The url is valid as I tested it using VLC on my desktop.
Any ideas why the application is not preparing the stream.
class InitializeService extends Thread {
#Override
public void run() {
try {
player.prepare();
Log.d("Play", "Player prepared");
} catch (IOException e) {
e.printStackTrace();
fallback();
} catch (IllegalStateException e) {
e.printStackTrace();
fallback();
}
}
}
The log statement is never reached.
Update 1:
Sorry I forgot to mention that the stream will always be in 3gp format. Here is a url rtsp://r2---sn-p5qlsu76.c.youtube.com/CiILENy73wIaGQnTXOVs7Kwo8xMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp
Your stream might not be of a format supported by Android.
Check http://developer.android.com/guide/appendix/media-formats.html to see if Android supports it.
Turns out it was android l that wasn't able to play the streams.
I'm using gottox socket.io java client for an Android chat application. I could connect to both web-socket and Xhr transport in HTTP mode. But when i switch to HTTPS only Xhr mode is working. i used the default SSL Context as below
SocketIO.setDefaultSSLSocketFactory(SSLContext.getInstance("Default"));
This works fine in Xhr mode. But in websocket transport there are no responses or errors.
Update
It might be that with new versions IO.setDefaultSSLContext and IO. setDefaultHostnameVerifier methods are not available. Instead now we can create our own OkHttpClient and set the hostname verifier and ssl socket factory etc on it as mentioned on socket.io-client-java usage. Here is the sniplet from there:
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.hostnameVerifier(myHostnameVerifier)
.sslSocketFactory(mySSLContext.getSocketFactory(), myX509TrustManager)
.build(); // default settings for all sockets
IO.setDefaultOkHttpWebSocketFactory(okHttpClient);
IO.setDefaultOkHttpCallFactory(okHttpClient);
Initial Answer:
I had the same issue with io.socket:socket.io-client:0.7.0 version of socket.io library on Android for long. It used to work fine for http protocol, however for https protocol it had trouble establishing connection giving xhr poll errors.
Following solution works for me without modifying the library itself:
// Socket connection
private Socket mSocket;
// Configure options
IO.Options options = new IO.Options();
// ... add more options
// End point https
String yourEndpoint = "https://whatever.yoururl.com"
String yourHostName = "yoururl.com"
// If https, explicitly tell set the sslContext.
if (yourEndpoint.startsWith("https://")) {
try {
// Default settings for all sockets
// Set default ssl context
IO.setDefaultSSLContext(SSLContext.getDefault());
// Set default hostname
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
return hv.verify(yourHostName, session);
}
};
IO.setDefaultHostnameVerifier(hostnameVerifier);
// set as an option
options.sslContext = SSLContext.getDefault();
options.hostnameVerifier = hostnameVerifier;
options.secure = true;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
// Instantiate the socket
mSocket = IO.socket(mEndpoint, options);
Hope this helps.
It works but you have to do some modifications on io.socket library.
Instead of using the socketio.jar, import into src folder the io.socket library (You'll find inside socket.io-java-client package). There, you have to edit the WebsocketTransport class.
Here you have the solution
https://github.com/Gottox/socket.io-java-client/issues/60
public WebsocketTransport(URI uri, IOConnection connection) {
super(uri);
this.connection = connection;
SSLContext context = null;
try {
context = SSLContext.getInstance("TLS", "HarmonyJSSE");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
try {
context.init(null, null, null);
} catch (KeyManagementException e) {
e.printStackTrace();
}
if("wss".equals(uri.getScheme()) && context != null) {
this.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(context));
}
}
And remember to call the setDefaultSSLSocketFactory like this:
socket = new SocketIO();
socket.setDefaultSSLSocketFactory(SSLContext.getDefault());
socket.connect("https://www.myHttpsServer.com:443/");
Hope it helps someone ;)
Websocket with SSL working in AndroidAsync. Using that for now.
I created an Android project on 2.3.3 and tried it on mobile 2.3.3, everything works OK. It didn't work on mobile 4, so I re-built for Android 4, but I have the same problem.
This is the code:
public void FTP_Download(){
String server = "192.168.1.135";
int port = 21;
String user = "pc1";
String pass = "1551";
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
Toast.makeText(getBaseContext(), "download starting.",Toast.LENGTH_LONG).show();
// APPROACH #1: using retrieveFile(String, OutputStream)
String remoteFile1 = "i.xml";
File downloadFile1 = new File("sdcard/i.xml");
OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1));
boolean success = ftpClient.retrieveFile(remoteFile1, outputStream1);
outputStream1.close();
if (success) {
Toast.makeText(getBaseContext(), "File #1 has been downloaded successfully.",Toast.LENGTH_LONG).show();
}
} catch (IOException ex) {
System.out.println("Error: " + ex.getMessage());
ex.printStackTrace();
} finally {
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Note:
I use commons-net-3.1 to connect.
In android version 2.3 above you can not start internet connection from main UI thread. Instead you should use AsyncTask. I assumed you are not using AsyncTask. If you are, then post the code and log cat also. Some examples of other operations that ICS and HoneyComb won't allow you to perform on the UI thread are:( from link posted in comment below ) -
Opening a Socket connection (i.e. new Socket()).
HTTP requests (i.e. HTTPClient and HTTPUrlConnection).
Attempting to connect to a remote MySQL database.
Downloading a file (i.e. Downloader.downloadFile()).
You should not use the main UI Thread to start a network connection or read/write data from it as #phazorRise explained it. But I strongly disagree with using an AsyncTask to perform your download. AsyncTask have been designed for short living operations and downloading a file doesn't belong to that category.
The most relevant way to achieve your goal, if your files are big (and I assume it depends on users, so we can say they are big) is to use a service to download the files.
I invite you to have a look at RoboSpice, it will give your app robustness for networking and it's really the most interesting library for network requests on Android.
Here is an inforgraphics to get familiarized with alternatives and understand why using a service is better than any other technology.
When I use "internet conections" programming for andoid 4, I do an Async Task as follows:
You can put this Class code into the same file as principal file to intercatue with global variables or functions.
public class MyAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String url = urls[0]
try {
//Connection request code, in your case ftp
} catch (Exception e) {
//Catch code
}
}
#Override
protected void onPostExecute(String result) {
//Code to de After the connection is done
}
}
Then, in the Activity I call the Asyn Task
String url = "http://...";
new MyAsyncTask().execute(url);
Edit
Here it's explained how to use Async Task, with an example
http://developer.android.com/reference/android/os/AsyncTask.html
I added this code, and all thing OK
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Note: I taked the code from #user1169115 comment in another post.
This isn't the best soluation, but I don't know why asynctask isn't work, so I don't have another choice.
I have online radio (shout cast ) in web. I want to develop android app for listen this stream. so I want to know how to play online stream in android. using URL. In Android Im not going to Stream the audio. I want listen the web stream from android app.
How to do that..?
thanks
Something like
private void init() throws IOException {
try {
mediaPlayer = new MediaPlayer();
String streamPath = "";//enter path
mediaPlayer.setDataSource(streamPath);
mediaPlayer.prepare();
} catch (MalformedURLException ex) {
throw new RuntimeException("Wrong url for mediaplayer! " + ex);
} catch (IllegalStateException ex) {
} catch (IllegalArgumentException ex) {
throw new RuntimeException("Wrong url for mediaplayer! " + ex);
}
}
private void play() {
mediaPlayer.start();
}
Please refer the link it may help you a while, http://developer.android.com/guide/topics/media/index.html