Need help creating Digest authentication for Android - android

I have this code so far:
private class DownloadWebPageTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... theParams)
{
String myUrl = theParams[0];
String myEmail = theParams[1];
String myPassword = theParams[2];
HttpPost post = new HttpPost(myUrl);
post.addHeader("Authorization","Basic "+ Base64.encodeToString((myEmail+":"+myPassword).getBytes(), 0 ));
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String response = null;
try
{
response = client.execute(post, responseHandler);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null)
{
response += s;
}
}
catch (Exception e)
{
e.printStackTrace();
}
return response;
}
#Override
protected void onPostExecute(String result)
{
}
}
This code does not compile because I am running into confusion at the point of:
response = client.execute(post, responseHandler);
InputStream content = execute.getEntity().getContent();
I got that code from tinkering with various examples, and not sure what Object the client is supposed to be, and whether the first line will just get me the server response, or I have to go the route of getting the InputStream and reading the server response in?
Please help me understand how to do this correctly.
Thank you!

I have managed to use Digest authentication using OkHttp. In this code sample I also use Dagger and Robospice-retrofit. What I did was creating an OkHttp Authenticator and assign it to my custom OkHttp client.
The authenticator class implements an authenticate method that will be called whenever the server encounters a 401 error and expects an Authorization header back (if it expects Proxy-Authorization you should implement the authenticateProxy method.
What it basically does is wrapping calls to the HttpClient DigestScheme and make it usable for OkHttp. Currently it does not increase the nc counter. This could cause problems with your server as it could be interpreted as a replay attack.
public class DigestAuthenticator implements com.squareup.okhttp.Authenticator {
#Inject DigestScheme mDigestScheme;
#Inject org.apache.http.auth.Credentials mCredentials;
#Override
public Request authenticate(Proxy proxy, Response response) throws IOException {
String authHeader = buildAuthorizationHeader(response);
if (authHeader == null) {
return null;
}
return response.request().newBuilder().addHeader("Authorization", authHeader).build();
}
#Override
public Request authenticateProxy(Proxy proxy, Response response) throws IOException {
return null;
}
private String buildAuthorizationHeader(Response response) throws IOException {
processChallenge("WWW-Authenticate", response.header("WWW-Authenticate"));
return generateDigestHeader(response);
}
private void processChallenge(String headerName, String headerValue) {
try {
mDigestScheme.processChallenge(new BasicHeader(headerName, headerValue));
} catch (MalformedChallengeException e) {
Timber.e(e, "Error processing header " + headerName + " for DIGEST authentication.");
}
}
private String generateDigestHeader(Response response) throws IOException {
org.apache.http.HttpRequest request = new BasicHttpRequest(
response.request().method(),
response.request().uri().toString()
);
try {
return mDigestScheme.authenticate(mCredentials, request).getValue();
} catch (AuthenticationException e) {
Timber.e(e, "Error generating DIGEST auth header.");
return null;
}
}
}
The authenticator will then be used in an OkHttpClient built with a provider:
public class CustomClientProvider implements Client.Provider {
#Inject DigestAuthenticator mDigestAuthenticator;
#Override
public Client get() {
OkHttpClient client = new OkHttpClient();
client.setAuthenticator(mDigestAuthenticator);
return new OkClient(client);
}
}
Finally the client is set to the RetrofitRobospice server in the function createRestAdapterBuilder:
public class ApiRetrofitSpiceService extends RetrofitJackson2SpiceService {
#Inject Client.Provider mClientProvider;
#Override
public void onCreate() {
App.get(this).inject(this);
super.onCreate();
addRetrofitInterface(NotificationRestInterface.class);
}
#Override
protected String getServerUrl() {
return Constants.Url.BASE;
}
#Override
protected RestAdapter.Builder createRestAdapterBuilder() {
return super.createRestAdapterBuilder()
.setClient(mClientProvider.get());
}
}

You might want to switch to HttpURLConnection. According to this article its API is simpler than HttpClient's and it's better supported on Android. If you do choose to go with HttpURLConnection, authenticating is pretty simple:
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("username", "password".toCharArray());
}
});
After that, continue using HttpURLConnection as usual. A simple example:
final URL url = new URL("http://example.com/");
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
final InputStream is = conn.getInputStream();
final byte[] buffer = new byte[8196];
int readCount;
final StringBuilder builder = new StringBuilder();
while ((readCount = is.read(buffer)) > -1) {
builder.append(new String(buffer, 0, readCount));
}
final String response = builder.toString();

The version of Apache's HttpClient shipped with Android is based on an old, pre-BETA version of HttpClient. Google has long recommended against using it and removed it in Android 6.0. Google's replacement HttpURLConnection does not support HTTP digest authentication, only basic.
This leaves you with a few options, including:
Migrate to HttpURLConnection (as Google recommends) and use a library, bare-bones-digest, for digest authentication. Example below.
Use the OkHttp library instead of HttpURLConnection or HttpClient. OkHttp does not support digest out of the box, but there's a library okhttp-digest that implements a digest authenticator. Example below.
Continue using the (deprecated) HttpClient by explicitly adding the 'org.apache.http.legacy' library to your build, as mentioned in the changelist for Android 6.0.
There is an Apache project for porting newer versions of HttpClient to Android, but the project has been discontinued. Read more on Apache's page on HttpClient for Android.
Implement HTTP digest yourself.
Here is a verbose example of how to authenticate a request using bare-bones-digest and HttpURLConnection (copied from the project's github page):
// Step 1. Create the connection
URL url = new URL("http://httpbin.org/digest-auth/auth/user/passwd");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Step 2. Make the request and check to see if the response contains
// an authorization challenge
if (connection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
// Step 3. Create a authentication object from the challenge...
DigestAuthentication auth = DigestAuthentication.fromResponse(connection);
// ...with correct credentials
auth.username("user").password("passwd");
// Step 4 (Optional). Check if the challenge was a digest
// challenge of a supported type
if (!auth.canRespond()) {
// No digest challenge or a challenge of an unsupported
// type - do something else or fail
return;
}
// Step 5. Create a new connection, identical to the original
// one..
connection = (HttpURLConnection) url.openConnection();
// ...and set the Authorization header on the request, with the
// challenge response
connection.setRequestProperty(
DigestChallengeResponse.HTTP_HEADER_AUTHORIZATION,
auth.getAuthorizationForRequest("GET", connection.getURL().getPath()));
}
Here is an example using OkHttp and okhttp-digest (copied from the okhttp-digest page):
client = new OkHttpClient();
final DigestAuthenticator authenticator = new DigestAuthenticator(new Credentials("username", "pass"));
final Map<String, CachingAuthenticator> authCache = new ConcurrentHashMap<>();
client.interceptors().add(new AuthenticationCacheInterceptor(authCache));
client.setAuthenticator(new CachingAuthenticatorDecorator(authenticator, authCache));
Request request = new Request.Builder()
.url(url);
.get()
.build();
Response response = client.newCall(request).execute();

Related

Log message to sumo logic from Android client

I've got a requirement to log message from the Android client. Is there any sumo logic API to log message from the Android application?
You can post your log message/ any message from your Android application to Summo Logic cloud-based log management.
Summo Logic provides Web Services/ REST to perform POST, GET Request.
You just need to post your data on the request body and mention your
Sumo collection endpoint as well as UniqueHTTPCollectorCode.
REST Service/ Web Service : https://[SumoEndpoint]/receiver/v1/http/[UniqueHTTPCollectorCode]
For Instance:
"https://endpoint1.collection.us2.sumologic.com/receiver/v1/http/SanTC12dhaV1oma90Vvb..."
You can use Retorfit / Volley library for REST Communication .
I have given a below pseudo code which conveys the basic REST Communication in background through Android Async Task.
I strictly recommend to use the above mentioned libraries.
public static String performPostRequest(String summoUrl, String payload,
Context context) throws IOException {
URL url = new URL(summoUrl);
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
String line;
StringBuffer jsonString = new StringBuffer();
uc.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
uc.setRequestMethod("POST");
uc.setDoInput(true);
uc.setInstanceFollowRedirects(false);
uc.connect();
OutputStreamWriter writer = new OutputStreamWriter(uc.getOutputStream(), "UTF-8");
writer.write(payload);
writer.close();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()));
while((line = br.readLine()) != null){
jsonString.append(line);
}
br.close();
} catch (Exception ex) {
ex.printStackTrace();
}
uc.disconnect();
return jsonString.toString();
}
Async task
new AsyncTask<String, String, String>() {
#Override
protected String doInBackground(String... params) {
try {
String response = makePostRequest(""https://endpoint1.collection.us2.sumologic.com/receiver/v1/http/ZaVnC4dhaV1oma90Vvb..."",
// Sample JSON Data "
{ \"organization": \"organization.name\",
\"environment": \"environment.name\",
\"apiProduct": \("apiproduct.name"),
\"proxyName": \("apiproxy.name"),
\"appName": \("developer.app.name"),
\"verb": \("request.verb"),
\"url": '' + \("client.scheme") + '://' + \("request.header.host") + \("request.uri"),
\"responseCode": \("message.status.code"),
\"responseReason": \("message.reason.phrase"),
\"clientLatency": total_client_time,
\"targetLatency": total_target_time,
\"totalLatency": total_request_time
}", getApplicationContext());
// Hard coded Success as response from Server, replace with this as per your need
return "Success";
} catch (IOException exception) {
exception.printStackTrace();
return exception.getMessage();
}
}
}.execute("");
For more information, Please refer the documentation from Official Sumo Webpage
https://help.sumologic.com/Send-Data/Sources/02Sources-for-Hosted-Collectors/HTTP-Source/Upload-Data-to-an-HTTP-Source

java.io.EOFException on Android Client (API 23) when POSTing Object to Jersey

I want to implement a basic authentication using an Android Client and a Glassfish 4.1.1 Server (communicating through REST-Service).
The Service is working quite well (proven by POSTMAN and another C#-Client) but on Android, it's driven me crazy by now.
It also appears that the object-to-send is received as 'null' on the server side, also an annoying "EOFException" is thrown on the Android Side.
Server side (works fine)
#POST
#Consumes({MediaType.APPLICATION_JSON})
#Produces({MediaType.APPLICATION_JSON})
public Account validate(Account acc)
{
Account a = null;
a = Database.getInstance().getAccountByUserPw(acc);
return a;
}
Android Client:
public Account postData(String JSONtoSend)
{
URL url;
Account get = new Account();
try {
url = new URL("http://192.xxx.xxx.x:18080/HolidayOutServer/webresources/validateacc");
HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();
urlCon.setRequestMethod("POST");
urlCon.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
urlCon.setRequestProperty("Accept", "application/json; charset=UTF-8");
urlCon.setDoOutput(true); // to be able to write.
urlCon.setDoInput(true); // to be able to read.
OutputStreamWriter out = new OutputStreamWriter(urlCon.getOutputStream());
out.write(JSONtoSend);
ObjectInputStream ois = new ObjectInputStream(urlCon.getInputStream());
get = (Account) ois.readObject();
return get;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return get;
}
which is called within this:
class help extends AsyncTask<String, Void, Account>
{
#Override
protected Account doInBackground(String... params) {
return postData(new Gson().toJson(new Account("aleqs", "lexx", -2)));
}
}
Problems in a nutshell:
Jersey Server receives null
Android throws this ridiculous EOFException.
Can somebody help ?
Thanks in advance,
John.
Ok, I managed to find a solution here after hours.
This code works for me:
try( DataOutputStream wr = new DataOutputStream( urlCon.getOutputStream())) {
wr.write(new Gson().toJson(new Account("aleqs", "lexx", -2)).getBytes());
}
Reader in = new BufferedReader(new InputStreamReader(urlCon.getInputStream(), "UTF-8"));
StringBuilder sb = new StringBuilder();
for (int c; (c = in.read()) >= 0;)
sb.append((char)c);
response = sb.toString();
return response;
} catch (IOException e) {
e.printStackTrace();
}
return response;
Change the return type of "donInBackGround" to String and let the helper class extend -String, Void, String-.
MOST IMPORTANT: CHECK IF YOUR ATTRIBUTES ON CLIENT SIDE (eg. id, name, ..) match with those from SERVER SIDE.
Consider cap locks and so on..
Cheers !

Connect Android App to Github API

I've been checking around for some time, but still can't find information on this how exactly to connect my android app to the Github API. I had it registered, had a token as well, read about the endpoints and everything, but cannot understand where the token to be used. May somebody give me a hint?
I've used below code to connect to GitHub Search Repo API in my android app.
//Method 1: To Authorize API access for all HTTP call
//Uncomment this part of code and input your username and password
// Authenticator.setDefault(new Authenticator() {
// #Override
// protected PasswordAuthentication getPasswordAuthentication() {
// return new PasswordAuthentication("username", "password".toCharArray());
// }
// });
HttpURLConnection urlConnection;
URL url;
InputStream inputStream;
try{
url = new URL("https://api.github.com/search/repositories?q="+"searchText");
urlConnection = (HttpURLConnection) url.openConnection();
//Method 2: To Authorize API access while making HTTP request
//Uncomment this part of code and input your username and password
// String basicAuth = "Basic "+Base64.encodeToString("username:password".getBytes(), Base64.NO_WRAP);
// urlConnection.setRequestProperty ("Authorization", basicAuth);
//set request type
urlConnection.setRequestMethod("GET");
//if you uncomment the following line GitHub API will not respond
// urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.connect();
//check for HTTP response
int httpStatus = urlConnection.getResponseCode();
//if HTTP response is 200 i.e. HTTP_OK read inputstream else read errorstream
if (httpStatus != HttpURLConnection.HTTP_OK) {
inputStream = urlConnection.getErrorStream();
//print GitHub api hearder data
Map<String, List<String>> map = urlConnection.getHeaderFields();
System.out.println("Printing Response Header...\n");
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
System.out.println(entry.getKey()
+ " : " + entry.getValue());
}
}
else {
inputStream = urlConnection.getInputStream();
}
//read inputstream
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String temp,response="";
while((temp = bufferedReader.readLine())!=null){
response+=temp;
}
//GitHub api has limit to access over http.
//Api rate limit is 10req/min for unauthenticated user and 30req/min is for authenticated user
boolean apiLimitExceeded = "false";
if(response.contains("API rate limit exceeded")){
apiLimitExceeded =true;
}else {
//convert data string into JSONObject
JSONObject obj = (JSONObject) new JSONTokener(response).nextValue();
JSONArray items = obj.getJSONArray("items");
//total result count and result status
total_count = obj.getString("total_count");
incomplete_results = obj.getString("incomplete_results");
}
urlConnection.disconnect();
} catch (MalformedURLException | ProtocolException | JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Check out my GitHub project to get a complete idea on how to use GitHub search repo API in Android App.
Link: https://github.com/kvipul/Search-GitHub-Repo
There are many filters that GitHub API provides. Check out the Documentation of GitHub search API for more details -https://developer.github.com/v3/search/

Android send https post request to the server without deprecated methods

In my app is used send request by https by following this source answer. Now some of them apache methods deprecated. Can anyone help me in order solve in a new approach?
To avoid using deprecated methods in API connectivity, think about using Retrofit. It's a third party library which makes HTTP communication much simpler.
When using Retrofit, you can create an interface of an API endpoint and the use it like a method. The rest of the HTTP request is managed by the library.
Here is the link to the Retrofit github homepage:
http://square.github.io/retrofit/
HttpURLConnection is part of SDK from API 1, you can use same http://developer.android.com/reference/java/net/HttpURLConnection.html.
// HTTP POST request
private void sendPost() throws Exception {
//Your server URL
String url = "https://selfsolve.apple.com/wcResults.do";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("POST");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
//Request Parameters you want to send
String urlParameters = "sn=C02G8416DRJM&cn=&locale=&caller=&num=12345";
// Send post request
con.setDoOutput(true);// Should be part of code only for .Net web-services else no need for PHP
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
}
More details you can get from
http://www.mkyong.com/java/how-to-send-http-request-getpost-in-java/
http://syntx.io/how-to-send-an-http-request-from-android-using-httpurlconnection/
Please check the below function:
public String makeServiceCall(String url1, MultipartEntity reqEntity) {
try {
// http client
URL url= new URL(url1);
HttpURLConnection httpClient = (HttpURLConnection) url.openConnection();
httpClient.setRequestMethod("POST");
httpClient.setUseCaches(false);
httpClient.setDoInput(true);
httpClient.setDoOutput(true);
httpClient.setRequestProperty("Connection", "Keep-Alive");
httpClient.addRequestProperty("Content-length", reqEntity.getContentLength()+"");
OutputStream os = httpClient.getOutputStream();
reqEntity.writeTo(httpClient.getOutputStream());
os.close();
httpClient.connect();
if (httpClient.getResponseCode() == HttpURLConnection.HTTP_OK) {
return readStream(httpClient.getInputStream());
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
In Android SDK 23
HttpClient is deprecated, you can migrate your code in HttpURLConnection
Something like this
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.connect();
if u want to continue using HttpClient for API level 22 and 23..
add org.apache.http.legacy.jar in ur project's Lib folder,
ull get .jar file in Android\sdk\platforms\android-23\optional..
if ur using android studio, after copy pasting jar file in lib folder,right click on jar file and click add as library
ur problem will be solved..comment if need any help.
thanx!
You can Use this Method for Get or Post Any purpose. Just use this method for Server request.
public void RequestToServer() {
// String User_id = "h";
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
// params.put("uid", User_id.toString());
client.post("http:// Your Url", params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String s) {
super.onSuccess(s);
Log.d("Server Response for success :", s);
tv.append("service_ReloadSqlDB" + " " + s);
}
#Override
public void onFailure(Throwable throwable) {
super.onFailure(throwable);
Log.d("Server Response for onFailure ", throwable.toString());
}
});
}
You also need a jar file = android-async-http-1.3.1.jar
download this jar and add your android project in libs folder
After that add this in your build.gradle
dependencies {
compile files('libs/<android-async-http-1.3.1.jar>')
}
Finally rebuild your project , run the application , Get your Server response.

How to parse a none standard HTTP response?

I'm having a real hard time figuring out how to parse a none standard HTTP response.
The none standard response contains ICY 200 OK instead of HTTP 200 OK. Here is a sample URL that sends the none standard HTTP response.
http://50.117.121.162:80
Since Android 4.4 HttpURLConnection will no longer work with these none standard responses. I have tried using the HttpClient by Apache but it doesn't work because of the none standard HTTP response. I have then tried following the guide for adding a custom response parser, but Android doesn't seem have all the classes needed to do it.
I'm really struggling to figure out a solution. Possibly modify the none standard response before it is parsed by the HttpClient or the HttpURLConnection could work but I'm not sure if that is even possible...
Any help would be greatly appreciated.
After a lot of research for a small/lite http client library, I ran into this port of the apache httpclient for android. The library provided a complete support for http connections. Then I simply modified the source code, particularly the BasicLineParser to replace ICY with HTTP/1.0.
I had similar problem with KitKat and had a success with using two classes found here for http post. They are incredibly easy to use and you can modify the protocol params easily too.
There is another solution to this issue in Android 4.4 but it requires using Apache HttpClient. This is based on possibility of providing custom response parser into Apache Http engine that can change ICY 200 OK to HTTP/1.0 200 OK. This is based on general idea presented in:
http://hc.apache.org/httpcomponents-client-4.2.x/tutorial/html/advanced.html
I have successfully used following code.
public class IcyClientConnection extends DefaultClientConnection{
#Override
protected HttpMessageParser createResponseParser(SessionInputBuffer buffer,
HttpResponseFactory responseFactory, HttpParams params) {
return new IcyHttpResponseParser(
buffer,
new BasicLineParser (),
responseFactory,
params);
}
}
public class IcyClientConnectionOperator extends DefaultClientConnectionOperator {
public IcyClientConnectionOperator(SchemeRegistry schemes) {
super(schemes);
}
#Override
public OperatedClientConnection createConnection() {
return new IcyClientConnection();
}
}
public class IcyClientConnManager extends SingleClientConnManager {
public IcyClientConnManager(HttpParams params, SchemeRegistry schreg) {
super(params, schreg);
}
#Override
protected ClientConnectionOperator createConnectionOperator(
SchemeRegistry schreg) {
return new IcyClientConnectionOperator(schreg);
}
}
Now you have to extend parser used by default and add code that will change wrong server replay to correct one. Normally code will block on hasProtocolVersion.
public class IcyHttpResponseParser extends DefaultResponseParser{
private CharArrayBuffer icyLineBuf;
private int icyMaxGarbageLines = 1000;
private final HttpResponseFactory icyResponseFactory;
public IcyHttpResponseParser(SessionInputBuffer buffer, LineParser parser,
HttpResponseFactory responseFactory, HttpParams params) {
super(buffer, parser, responseFactory, params);
this.icyLineBuf = new CharArrayBuffer(128);
icyResponseFactory = responseFactory;
}
#Override
protected HttpMessage parseHead(SessionInputBuffer sessionBuffer)
throws IOException, HttpException {
int count = 0;
ParserCursor cursor = null;
do {
// clear the buffer
this.icyLineBuf.clear();
final int i = sessionBuffer.readLine(this.icyLineBuf);
//look for ICY and change to HTTP to provide compatibility with non standard shoutcast servers
String tmp = icyLineBuf.substring(0, this.icyLineBuf.length());
if(tmp.contains("ICY ")){
tmp = tmp.replace("ICY", "HTTP/1.0");
}
//copy
this.icyLineBuf = new CharArrayBuffer(128);
System.arraycopy(tmp.toCharArray(), 0, icyLineBuf.buffer(), 0, tmp.length());
icyLineBuf.setLength( tmp.length());
if (i == -1 && count == 0) {
// The server just dropped connection on us
throw new NoHttpResponseException("The target server failed to respond");
}
cursor = new ParserCursor(0, this.icyLineBuf.length());
if (lineParser.hasProtocolVersion(this.icyLineBuf, cursor)) {
// Got one
break;
} else if (i == -1 || count >= this.icyMaxGarbageLines) {
// Giving up
throw new ProtocolException("The server failed to respond with a " +
"valid HTTP response");
}
//if (this.log.isDebugEnabled()) {
// this.log.debug("Garbage in response: " + this.lineBuf.toString());
// }
count++;
} while(true);
//create the status line from the status string
final StatusLine statusline = lineParser.parseStatusLine(this.icyLineBuf, cursor);
return this.icyResponseFactory.newHttpResponse(statusline, null);
}
}
Plug in HttpClient:
Scheme http = new Scheme("http", PlainSocketFactory.getSocketFactory(), 80);
Scheme ftp = new Scheme("ftp", PlainSocketFactory.getSocketFactory(), 21);
SchemeRegistry sr = new SchemeRegistry();
sr.register(http);
sr.register(ftp);
HttpClient httpClient = new DefaultHttpClient(new IcyClientConnManager(params, sr), params);
This is still being tested but initial results are promising.
Thanks #Michael M, you can even make it simpler by subclassing the BasicLineParser instead of subclassing the DefaultResponseParser.
I've uploaded the code into a gist
To use it:
IcyGetRequest request = new IcyGetRequest(urlStr);
HttpResponse response = request.get();
int responseCode = response.getStatusLine().getStatusCode();
Create an runnable that creates socket proxy then you will be able to response with HTTP/1.0 instead of ICY , then just connect to this local socket proxy with your player
Here a modification of the solution from Michal M in case you don't like to create lots of subclasses just to configure already available HttpClient classes.
final SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
HttpClient httpClient = new DefaultHttpClient() {
#Override
protected ClientConnectionManager createClientConnectionManager() {
return new SingleClientConnManager(getParams(), schemeRegistry) {
#Override
protected ClientConnectionOperator createConnectionOperator(SchemeRegistry schreg) {
return new DefaultClientConnectionOperator(schreg) {
#Override
public OperatedClientConnection createConnection() {
return new DefaultClientConnection() {
#Override
protected HttpMessageParser createResponseParser(SessionInputBuffer buffer, HttpResponseFactory responseFactory, HttpParams params) {
return new IcyHttpResponseParser(buffer, new BasicLineParser(), responseFactory, params);
}
};
}
};
}
};
}
};
Probably there is a way to get the SchemeRegistry obsoleted if one could get hold somehow from within the DefaultHttpClient class.

Categories

Resources