android mms download mms content through mms url - android

I am trying to download the MMS picture content through the MMS url, but it returns with a 403 (Forbidden) server response with an invalid MSISDN number. I have pasted my code below for reference. Thanks in advance!
private static boolean downloadThroughGateway(Context context, String host,
String port, String urlMms) throws Exception {
URL url = new URL(urlMms);
// Set-up proxy
if (host != null && port != null && host.equals("") && !port.equals("")) {
Log.d(TAG, "[MMS Receiver] Setting up proxy (" + host + ":" + port
+ ")");
Properties systemProperties = System.getProperties();
systemProperties.setProperty("http.proxyHost", host);
systemProperties.setProperty("http.proxyPort", port);
systemProperties.setProperty("http.keepAlive", "false");
}
// Open connection
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Disable cache
connection.setUseCaches(false);
// Set the timeouts
connection.setConnectTimeout(TIMEOUT);
connection.setReadTimeout(TIMEOUT);
// Connect to the MMSC
Log.d(TAG, "[MMS Receiver] Connecting to MMS Url " + urlMms);
connection.connect();
try {
Log.d(TAG,
"[MMS Receiver] Response code is "
+ connection.getResponseCode());
if (connection.getContentLength() >= 0) {
Log.d(TAG, "[MMS Receiver] Download MMS data (Size: "
+ connection.getContentLength() + ")");
byte[] responseArray = new byte[connection.getContentLength()];
DataInputStream i = new DataInputStream(
connection.getInputStream());
int b = 0;
int index = 0;
while ((b = i.read()) != -1) {
responseArray[index] = (byte) b;
index++;
}
i.close();
// Parse the response
MmsDecoder parser = new MmsDecoder(responseArray);
parser.parse();
byte[][] imageBytes = new byte[parser.getParts().size()][];
for (int j = 0; j < parser.getParts().size(); j++) {
imageBytes[j] = parser.getParts().get(j).getContent();
}
// Insert into db
// Uri msgUri = MmsHelper.insert(context, parser.getFrom(),
// parser.getSubject(), imageBytes);
// ContentValues updateValues = new ContentValues();
// updateValues.put("read", 0);
// context.getContentResolver().update(msgUri, updateValues,
// null,
// null);
// Close the connection
Log.d(TAG, "[MMS Receiver] Disconnecting ...");
connection.disconnect();
System.gc();
// Callback
// if (bi != null)
// bi.onReceiveMms(context, msgUri);
return true;
}
// Close the connection
Log.d(TAG, "[MMS Receiver] Disconnecting ...");
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}

Now I am able to find out the solution but I find that sometime the download code doesn't work but when you try again it works although what I was missing first establishing the connectivity to the server. I have mention below the connectivity method and after this call the method name downloadThroughGateway(parameters) which is mention on this question code.
private void startConnectivity() throws Exception {
ConnectivityManager mConnMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (!mConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS)
.isAvailable()) {
throw new Exception("Not available yet");
}
int count = 0;
int result = beginMmsConnectivity(mConnMgr);
if (result != PhoneEx.APN_ALREADY_ACTIVE) {
NetworkInfo info = mConnMgr
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS);
while (!info.isConnected()) {
Thread.sleep(1500);
info = mConnMgr
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS);
Log.d(">>>", "Waiting for CONNECTED: state=" + info.getState());
if (count++ > 5)
throw new Exception("Failed to connect");
}
}
Thread.sleep(1500);
}

Related

android image not appearing when getting bytes from socket and using bitmap creation

I have a program in which I'm trying to download the content of an image file from a server. I'm using java socket to download it. After downloading, I use BitmapFactory.decodeByteArray() to create a bitmap.
At the server side, the file is a .jpg file and it's only about 180 KBytes, so I don't need to try scaling it. I can see through logs that the exact number of bytes in the file is received by my image download code. I store all the bytes in a byte[] array and then convert it into a bitmap.
The imageView is initially hidden and then supposed to be made visible after populating the image. But using BitmapFactory.decodeByteArray() is returning null always. I did see some other posts about null bitmap, but nothing seems to have an answer for this problem.
I don't want to use any external library just for this, so please do not give me suggestions to try out some other libraries. Can someone spot any problem with the code? The server side program is also mine and I know that part is correct because using that, browsers are able to download the same image file. I have copy-pasted it below.
public class ImageDownloader {
private Socket sockToSrvr;
private PrintWriter strmToSrvr;
private BufferedInputStream strmFromSrvr;
private String srvrAddr;
private int port;
private String remoteFile;
private Context ctxt;
private Bitmap imgBmap;
private View parkSpotImgVwHldr;
private View mngAndFndVwHldr;
private View parkSpotImgVw;
public ImageDownloader(Context c) {
srvrAddr = KloudSrvr.srvrIp();
port = KloudSrvr.port();
sockToSrvr = null;
strmFromSrvr = null;
strmToSrvr = null;
remoteFile = null;
ctxt = c;
imgBmap = null;
parkSpotImgVwHldr = null;
mngAndFndVwHldr = null;
parkSpotImgVw = null;
}
public void downloadFile(String remf, View parkSpotImgVwHldrVal,
View mngAndFndVwHldrVal, View parkSpotImgVwVal) {
remoteFile = remf;
parkSpotImgVwHldr = parkSpotImgVwHldrVal;
mngAndFndVwHldr = mngAndFndVwHldrVal;
parkSpotImgVw = parkSpotImgVwVal;
Thread dwnThrd = new Thread() {
#Override
public void run() {
imgBmap = null;
openServerConnection(); sendReq(); doDownload(); closeServerConnection();
((Activity)ctxt).runOnUiThread(new Runnable() {
public void run() {
((Activity)ctxt).runOnUiThread(new Runnable() {
public void run() {
mngAndFndVwHldr.setVisibility(View.GONE);
parkSpotImgVwHldr.setVisibility(View.VISIBLE);
Toast.makeText(ctxt, "completed", Toast.LENGTH_LONG).show();
}
});
}
});
}
};
dwnThrd.start();
}
private void sendReq() {
if(strmToSrvr == null) return;
String req = "GET /downloadFile " + remoteFile + " HTTP/1.1\r\n\r\n";
Log.d("IMG-DWNL-LOG: ", "writing req msg to socket " + req);
strmToSrvr.write(req); strmToSrvr.flush();
}
private void doDownload() {
boolean gotContLen = false;
int contLen = 0;
while(true) {
String inLine = getLine(strmFromSrvr); if(inLine == null) break;
if((gotContLen == true) &&
(inLine.replace("\r", "").replace("\n", "").isEmpty() == true)) break;
if(inLine.trim().startsWith("Content-Length:") == true) {
// an empty line after this signifies start of content
String s = inLine.replace("Content-Length:", "").trim();
try {contLen = Integer.valueOf(s); gotContLen = true; continue;}
catch(NumberFormatException nfe) {contLen = 0;}
}
}
if((gotContLen == false) || (contLen <= 0)) return;
byte[] imgByts = new byte[contLen];
int totRdByts = 0, rdByts, chnk = 1024, avlByts;
while(true) {
try {
avlByts = strmFromSrvr.available(); if(avlByts < 0) break;
if(avlByts == 0) {try {Thread.sleep(1000);} catch(InterruptedException ie) {} continue;}
rdByts = (avlByts < chnk) ? avlByts : chnk;
rdByts = strmFromSrvr.read(imgByts, totRdByts, rdByts); if(rdByts < 0) break;
if(rdByts == 0) {try {Thread.sleep(1000);} catch(InterruptedException ie) {} continue;}
totRdByts += rdByts;
if(totRdByts >= contLen) break;
} catch(IOException ioe) {return;}
}
if(totRdByts < contLen) {
Log.d("IMG-DWNL-LOG: ", "error - bytes read " + totRdByts
+ " less than content length " + contLen);
return;
}
if(totRdByts <= 0) return;
Log.d("IMG-DWNL-LOG: ", "read all image bytes successfully, setting image into view");
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeByteArray(imgByts, 0, contLen, options);
if(bitmap == null) {Log.d("IMG-DWNL-LOG: ", "got a null bitmap");}
((ImageView)parkSpotImgVw).setImageBitmap(bitmap);
}
private void closeServerConnection() {
if(sockToSrvr == null) return;
if(strmFromSrvr != null) {
try {strmFromSrvr.close();}
catch(IOException e) {Log.d("IMG-DWNL-LOG: ", "Inp strm close exception");}
}
if(strmToSrvr != null) strmToSrvr.close();
try {sockToSrvr.close();}
catch(IOException e) {Log.d("IMG-DWNL-LOG: ", "Conn close exception");}
strmFromSrvr = null; strmToSrvr = null; sockToSrvr = null;
}
private void openServerConnection() {
try {sockToSrvr = new Socket(InetAddress.getByName(srvrAddr), port);}
catch(UnknownHostException e) {
Log.d("IMG-DWNL-LOG: ", "Unknown host exception"); sockToSrvr = null; return;
} catch(IOException e) {
Log.d("IMG-DWNL-LOG: ", "Server connect exception"); sockToSrvr = null; return;
}
Log.d("IMG-DWNL-LOG: ", "Connected to server");
try {
strmFromSrvr = new BufferedInputStream(sockToSrvr.getInputStream());
strmToSrvr = new PrintWriter(new BufferedWriter(new OutputStreamWriter
(sockToSrvr.getOutputStream())), true);
} catch(IOException e) {
closeServerConnection();
Log.d("IMG-DWNL-LOG: ", "Failed to open reader / writer. Closed the connection."); return;
}
}
private String getLine(BufferedInputStream dis) {
String outLine = "";
while(true) {
try {
int c = dis.read(); if((c == -1) && (outLine.length() <= 0)) return(null);
outLine += Character.toString((char)c);
if(c == '\n') return(outLine);
} catch(IOException e) {if(outLine.length() <= 0) return(null); return(outLine);}
}
}
}
I was making a mistake, assuming that a .jpg file's bytes can be directly decode with the android bitmap decoder. Apparently this is not the case. So, I wrote the received bytes into a temporary file in the phone storage and then called BitmapFactory.decodeFile() which is able to return a good bitmap and ends up showing the image.
So, have a working solution now.
Still - if anyone has a better suggestion how to decode directly from the received bytes (which are from a .jpg file), I would be very interested to try it out since that would be more efficient. Thanks.

how to upload a video to YouTube using my android app

How to upload a video to a particular YouTube account from my android app i have followed https://github.com/youtube/yt-direct-lite-android but its not very documented.
I have tried
public class YoutubeUploader {
private static final String TAG = "YoutubeUploader";
// After creating project at http://www.appspot.com DEFAULT_YTD_DOMAIN == <Developers Console Project ID>.appspot.com [ You can find from Project -> Administration -> Application settings]
//public static final String DEFAULT_YTD_DOMAIN = "developerconsolid.appspot.com";
// I used Google APIs Console Project Title as Domain name:
//public static final String DEFAULT_YTD_DOMAIN_NAME = "Domain Name";
//From Google Developer Console from same project (Created by SHA1; project package)
//Example https://console.developers.google.com/project/apps~gtl-android-youtube-test/apiui/credential
public static final String DEVELOPER_KEY = "<MY_DEVELOPER_KEY>";
// CLIENT_ID == Google APIs Console Project Number:
public static final String CLIENT_ID = "157613";
public static final String YOUTUBE_AUTH_TOKEN_TYPE = "youtube";
private static final String AUTH_URL = "https://www.google.com/accounts/ClientLogin";
// Uploader's user-name and password
private static final String USER_NAME = "my#gmail.com";
private static final String PASSWORD = "mypassword";
private static final String INITIAL_UPLOAD_URL = "https://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads";
private static String getClientAuthToken() {
try {
URL url = new URL(AUTH_URL);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String template = "Email=%s&Passwd=%s&service=%s&source=%s";
String userName = USER_NAME; // TODO
String password = PASSWORD; // TODO
String service = YOUTUBE_AUTH_TOKEN_TYPE;
String source = CLIENT_ID;
userName = URLEncoder.encode(userName, "UTF-8");
password = URLEncoder.encode(password, "UTF-8");
String loginData = String.format(template, userName, password, service, source);
OutputStreamWriter outStreamWriter = new OutputStreamWriter(urlConnection.getOutputStream());
outStreamWriter.write(loginData);
outStreamWriter.close();
int responseCode = urlConnection.getResponseCode();
if (responseCode != 200) {
Log.d(TAG, "Got an error response : " + responseCode + " " + urlConnection.getResponseMessage());
throw new IOException(urlConnection.getResponseMessage());
} else {
InputStream is = urlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
if (line.startsWith("Auth=")) {
String split[] = line.split("=");
String token = split[1];
Log.d(TAG, "Auth Token : " + token);
return token;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String upload(YoutubeUploadRequest uploadRequest, ProgressListner listner, Activity activity) {
totalBytesUploaded = 0;
String authToken = getClientAuthToken();
if(authToken != null) {
String uploadUrl = uploadMetaData(uploadRequest, authToken, activity, true);
File file = getFileFromUri(uploadRequest.getUri(), activity);
long currentFileSize = file.length();
int uploadChunk = 1024 * 1024 * 3; // 3MB
int start = 0;
int end = -1;
String videoId = null;
double fileSize = currentFileSize;
while (fileSize > 0) {
if (fileSize - uploadChunk > 0) {
end = start + uploadChunk - 1;
} else {
end = start + (int) fileSize - 1;
}
Log.d(TAG, String.format("start=%s end=%s total=%s", start, end, file.length()));
try {
videoId = gdataUpload(file, uploadUrl, start, end, authToken, listner);
fileSize -= uploadChunk;
start = end + 1;
} catch (IOException e) {
Log.d(TAG,"Error during upload : " + e.getMessage());
}
}
if (videoId != null) {
return videoId;
}
}
return null;
}
public static int totalBytesUploaded = 0;
#SuppressLint("DefaultLocale")
#SuppressWarnings("resource")
private static String gdataUpload(File file, String uploadUrl, int start, int end, String clientLoginToken, ProgressListner listner) throws IOException {
int chunk = end - start + 1;
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
FileInputStream fileStream = new FileInputStream(file);
URL url = new URL(uploadUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestProperty("Authorization", String.format("GoogleLogin auth=\"%s\"", clientLoginToken));
urlConnection.setRequestProperty("GData-Version", "2");
urlConnection.setRequestProperty("X-GData-Client", CLIENT_ID);
urlConnection.setRequestProperty("X-GData-Key", String.format("key=%s", DEVELOPER_KEY));
// some mobile proxies do not support PUT, using X-HTTP-Method-Override to get around this problem
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("X-HTTP-Method-Override", "PUT");
urlConnection.setDoOutput(true);
urlConnection.setFixedLengthStreamingMode(chunk);
urlConnection.setRequestProperty("Content-Type", "video/3gpp");
urlConnection.setRequestProperty("Content-Range", String.format("bytes %d-%d/%d", start, end,
file.length()));
Log.d(TAG, urlConnection.getRequestProperty("Content-Range"));
OutputStream outStreamWriter = urlConnection.getOutputStream();
fileStream.skip(start);
double currentFileSize = file.length();
int bytesRead;
int totalRead = 0;
while ((bytesRead = fileStream.read(buffer, 0, bufferSize)) != -1) {
outStreamWriter.write(buffer, 0, bytesRead);
totalRead += bytesRead;
totalBytesUploaded += bytesRead;
double percent = (totalBytesUploaded / currentFileSize) * 100;
if(listner != null){
listner.onUploadProgressUpdate((int) percent);
}
System.out.println("GTL You tube upload progress: " + percent + "%");
/*
Log.d(LOG_TAG, String.format(
"fileSize=%f totalBytesUploaded=%f percent=%f", currentFileSize,
totalBytesUploaded, percent));
*/
//dialog.setProgress((int) percent);
// TODO My settings
if (totalRead == (end - start + 1)) {
break;
}
}
outStreamWriter.close();
int responseCode = urlConnection.getResponseCode();
Log.d(TAG, "responseCode=" + responseCode);
Log.d(TAG, "responseMessage=" + urlConnection.getResponseMessage());
try {
if (responseCode == 201) {
String videoId = parseVideoId(urlConnection.getInputStream());
return videoId;
} else if (responseCode == 200) {
Set<String> keySet = urlConnection.getHeaderFields().keySet();
String keys = urlConnection.getHeaderFields().keySet().toString();
Log.d(TAG, String.format("Headers keys %s.", keys));
for (String key : keySet) {
Log.d(TAG, String.format("Header key %s value %s.", key, urlConnection.getHeaderField(key)));
}
Log.w(TAG, "Received 200 response during resumable uploading");
throw new IOException(String.format("Unexpected response code : responseCode=%d responseMessage=%s", responseCode,
urlConnection.getResponseMessage()));
} else {
if ((responseCode + "").startsWith("5")) {
String error = String.format("responseCode=%d responseMessage=%s", responseCode,
urlConnection.getResponseMessage());
Log.w(TAG, error);
// TODO - this exception will trigger retry mechanism to kick in
// TODO - even though it should not, consider introducing a new type so
// TODO - resume does not kick in upon 5xx
throw new IOException(error);
} else if (responseCode == 308) {
// OK, the chunk completed succesfully
Log.d(TAG, String.format("responseCode=%d responseMessage=%s", responseCode,
urlConnection.getResponseMessage()));
} else {
// TODO - this case is not handled properly yet
Log.w(TAG, String.format("Unexpected return code : %d %s while uploading :%s", responseCode,
urlConnection.getResponseMessage(), uploadUrl));
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
return null;
}
private static String parseVideoId(InputStream atomDataStream) throws ParserConfigurationException,
SAXException, IOException {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.parse(atomDataStream);
NodeList nodes = doc.getElementsByTagNameNS("*", "*");
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
String nodeName = node.getNodeName();
if (nodeName != null && nodeName.equals("yt:videoid")) {
return node.getFirstChild().getNodeValue();
}
}
return null;
}
private static File getFileFromUri(Uri uri, Activity activity) {
try {
String filePath = null;
String[] proj = { Video.VideoColumns.DATA };
Cursor cursor = activity.getContentResolver().query(uri, proj, null, null, null);
if(cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(Video.VideoColumns.DATA);
filePath = cursor.getString(column_index);
}
cursor.close();
//String filePath = cursor.getString(cursor.getColumnIndex(Video.VideoColumns.DATA));
File file = new File(filePath);
cursor.close();
return file;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String uploadMetaData(YoutubeUploadRequest uploadRequest, String clientLoginToken, Activity activity, boolean retry) {
try {
File file = getFileFromUri(uploadRequest.getUri(), activity);
if(file != null) {
String uploadUrl = INITIAL_UPLOAD_URL;
URL url = new URL(uploadUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization", String.format("GoogleLogin auth=\"%s\"", clientLoginToken));
connection.setRequestProperty("GData-Version", "2");
connection.setRequestProperty("X-GData-Client", CLIENT_ID);
connection.setRequestProperty("X-GData-Key", String.format("key=%s", DEVELOPER_KEY));
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/atom+xml");
connection.setRequestProperty("Slug", file.getAbsolutePath());
String title = uploadRequest.getTitle();
String description = uploadRequest.getDescription();
String category = uploadRequest.getCategory();
String tags = uploadRequest.getTags();
String template = readFile(activity, R.raw.gdata).toString();
String atomData = String.format(template, title, description, category, tags);
/*String template = readFile(activity, R.raw.gdata_geo).toString();
atomData = String.format(template, title, description, category, tags,
videoLocation.getLatitude(), videoLocation.getLongitude());*/
OutputStreamWriter outStreamWriter = new OutputStreamWriter(connection.getOutputStream());
outStreamWriter.write(atomData);
outStreamWriter.close();
int responseCode = connection.getResponseCode();
if (responseCode < 200 || responseCode >= 300) {
// The response code is 40X
if ((responseCode + "").startsWith("4") && retry) {
Log.d(TAG, "retrying to fetch auth token for ");
clientLoginToken = getClientAuthToken();
// Try again with fresh token
return uploadMetaData(uploadRequest, clientLoginToken, activity, false);
} else {
return null;
}
}
return connection.getHeaderField("Location");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static CharSequence readFile(Activity activity, int id) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(activity.getResources().openRawResource(id)));
String line;
StringBuilder buffer = new StringBuilder();
while ((line = in.readLine()) != null) {
buffer.append(line).append('\n');
}
// Chomp the last newline
buffer.deleteCharAt(buffer.length() - 1);
return buffer;
} catch (IOException e) {
return "";
} finally {
closeStream(in);
}
}
/**
* Closes the specified stream.
*
* #param stream The stream to close.
*/
private static void closeStream(Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
// Ignore
}
}
}
public static interface ProgressListner {
void onUploadProgressUpdate(int progress);
}
I am getting 404 error in getClientAuthToken() method.I think "https://www.google.com/accounts/ClientLogin";deprecated by google any alternative to this

Apache HTTP Client Android Exception on Execute only for LG G3 6.0

I've taken over an android app that takes pictures and attaches them to jobs for a larger software system at a company's home base- it has worked fine until recently.
It seems that only on LG G3 phones that have upgraded to Android 6.0 there is an exception in this prodecure:
public static String frapiGetRequest(String transaction, ArrayList<Content> parameters) {
StringBuilder builder = new StringBuilder();
DefaultHttpClient client = new DefaultHttpClient();
HttpHost targetHost = new HttpHost(HOST,PORT,SCHEME);
String url = SCHEME + "://" + HOST + "/" + transaction;
if (parameters != null && parameters.size() > 0) {
url += "?" + buildParameterString(parameters);
}
Utilities.bLog(TAG, "Making FrapiRequest -- " + url);
try {
HttpGet getRequest = new HttpGet(url);
client.getCredentialsProvider().setCredentials(
new AuthScope(targetHost.getHostName(), targetHost.getPort()),
new UsernamePasswordCredentials(USERNAME, PASSWORD));
/**Exception Occurs Here**/
HttpResponse response = client.execute(getRequest);
StatusLine statusLine = response.getStatusLine();
int statusCode = -1;
statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
Utilities.bLog(TAG,"Frapi Request Succeeded");
}
else {
Utilities.bLog(TAG, "Frapi Request Failed: " + url);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
Utilities.eLog(e);
} catch (IOException e) {
e.printStackTrace();
Utilities.eLog(e);
} catch (Exception e) {
e.printStackTrace();
Utilities.eLog(e);
}
return builder.toString();
}
The stack trace
java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
at org.apache.http.impl.auth.DigestScheme.isGbaScheme(DigestScheme.java:210)
at org.apache.http.impl.auth.DigestScheme.processChallenge(DigestScheme.java:176)
at org.apache.http.impl.client.DefaultRequestDirector.processChallenges(DefaultRequestDirector.java:1097)
at org.apache.http.impl.client.DefaultRequestDirector.handleResponse(DefaultRequestDirector.java:980)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:490)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:560)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:492)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:470)
at com.rossware.sd_quickpics.Utilities.frapiGetRequest(Utilities.java:111)
at com.rossware.sd_quickpics.Business.authenticate(Business.java:83)
at com.rossware.sd_quickpics.MainActivity$AuthenticateAsyncTask.doInBackground(MainActivity.java:320)
at com.rossware.sd_quickpics.MainActivity$AuthenticateAsyncTask.doInBackground(MainActivity.java:307)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
This hasn't been reported on any other phone.. I would use HttpURLConnection But it doesn't support Digest Authentication (which is currently what our frapi server is using)
I'm just not sure if there's any way to continue using the authentication mechanism we have or if I have to implement a different protocol in frapi (hopefully without breaking all of our existing applications..) or if there is another way to bypass this issue for the folks with these phones? This issue is pretty restricted (one client who has about 10 phones, not the end of the world, but definitely a major issue for them)
Is there anything in android that I can do to resolve this kind of problem for the affected users? Does it seem like the code is incorrect?
It is possible to use DigestAuth with HttpUrlConnection:
private InputStream connect(String urlStr, String username, String password) throws Exception {
URL url = new URL(urlStr);
HttpURLConnection connection = (HttpURLConnection) new URL(urlStr).openConnection();
connection.setDoInput(true);
connection.setRequestMethod("GET");
try {
return connection.getInputStream();
} catch(Exception e) {
if (connection.getResponseCode() == 401) {
String header = connection.getHeaderField("WWW-Authenticate");
String uri = new URL(urlStr).getFile();
String nonce = Tools.match(header, "nonce=\"([A-F0-9]+)\"");
String realm = match(header, "realm=\"(.*?)\"");
String qop = match(header, "qop=\"(.*?)\"");
String algorithm = match(header, "algorithm=(.*?),");
String cnonce = generateCNonce();
String ha1 = username + ":" + realm + ":" + password;
String ha1String = md5digestHex(ha1);
String ha2 = "GET" + ":" + uri;
String ha2String = md5digestHex(ha2);
int nc = 1;
String response = ha1String + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2String;
String responseString = md5digestHex(response);
String authorization =
"Digest username=\"" + username + "\"" +
", realm=\"" + realm + "\"" +
", nonce=\"" + nonce + "\"" +
", uri=\"" + uri + "\"" +
", qop=\"" + qop + "\"" +
", nc=\"" + nc + "\"" +
", cnonce=\"" + cnonce + "\"" +
", response=\"" + responseString + "\"" +
", algorithm=\"" + algorithm + "\"";
HttpURLConnection digestAuthConnection = prepareConnection(urlStr);
digestAuthConnection.setRequestMethod("GET");
digestAuthConnection.setRequestProperty("Authorization", authorization);
return processResponse(digestAuthConnection);
} else throw e;
}
}
public static String match(String s, String patternString, boolean strict) {
if (!isEmpty(s) && !isEmpty(patternString)) {
Pattern pattern = Pattern.compile(patternString);
if (pattern != null) {
Matcher matcher = pattern.matcher(s);
if (matcher != null && matcher.find() && (matcher.groupCount() == 1 || !strict)) {
return matcher.group(1);
}
}
}
return null;
}
public static String match(String s, String patternString) {
return match(s, patternString, true);
}
public static byte[] md5Digist(String s) {
try {
MessageDigest md5 = MessageDigest.getInstance("md5");
md5.update(s.getBytes());
return md5.digest();
} catch (NoSuchAlgorithmException e) {
return null;
}
}
public static String digest2HexString(byte[] digest) {
String digestString="";
int low, hi;
for (int i = 0; i < digest.length; i++) {
low = (digest[i] & 0x0f ) ;
hi = ((digest[i] & 0xf0) >> 4);
digestString += Integer.toHexString(hi);
digestString += Integer.toHexString(low);
}
return digestString;
}
public static String md5digestHex(String s) {
return digest2HexString(md5Digist(s));
}
public static String generateCNonce() {
String s = "";
for (int i = 0; i < 8; i++) {
s += Integer.toHexString(new Random().nextInt(16));
}
return s;
}
I ran into a similar issue today and just started using HttpClient for Android
Added dependency compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1' to build.gradle.
Replace new DefaultHttpClient() with HttpClientBuilder.create().build()
There are probably some other minor refactors you might need to make in other portions of the code, but that should be pretty straight forward.

Android retrieve return value from WCF

I have an Android app that posts to a web service via the code below and it all works fine. But the myContract method in the service returns a Boolean, true or false. How do I retrieve that value so I can tell my app to move on or not if false?
HttpPost request = new HttpPost(SERVICE_URI + "/myContract/someString");
request.setHeader("Accept", "application/json");
request.setHeader("Content-type", "application/json");
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
Edit
Sorry about the edit, but using HttpResponse, and then logging or toasting response.toString() returns a string I don’t understand!
Update
Thanks Shereef,
But that seems like a bit too much information and code to do what I was trying to do. I have added some code below that works but I’m not sure if it’s right. The service will return a Boolean true or false as to whether or not the POST was successful, but I seem to be retrieving it as a string!
HttpEntity responseEntity = response.getEntity();
char[] buffer = new char[(int)responseEntity.getContentLength()];
InputStream stream = responseEntity.getContent();
InputStreamReader reader = new InputStreamReader(stream);
reader.read(buffer);
stream.close();
JSONObject jsonResponse = new JSONObject(new String(buffer));
String ServiceResponse = jsonResponse.getString("putCommuniqueResult");
Log.d("WebInvoke", "Saving : " + ServiceResponse);
Is this ok? It works but I’m not sure if its right!
Cheers,
Mike.
private static String getDataFromXML(final String text) {
final String temp = new String(text).split("<")[2].split(">")[1];
final String temp2 = temp.replace("<", "<").replace(">", ">")
.replace("&", "&");
return temp2;
}
/**
* Connects to the web service and returns the pure string returned, NOTE:
* if the generated url is more than 1024 it automatically delegates to
* connectPOST
*
* #param hostName
* : the host name ex: google.com or IP ex:
* 127.0.0.1
* #param webService
* : web service name ex: TestWS
* #param classOrEndPoint
* : file or end point ex: CTest
* #param method
* : method being called ex: TestMethod
* #param parameters
* : Array of {String Key, String Value} ex: { { "Username",
* "admin" }, { "Password", "313233" } }
* #return the trimmed String received from the web service
*
* #author Shereef Marzouk - http://shereef.net
*
*
*/
public static String connectGET(final String hostNameOrIP,
final String webService, final String classOrEndPoint,
final String method, final String[][] parameters) {
String url = "http://" + hostNameOrIP + "/" + webService + "/"
+ classOrEndPoint + "/" + method;
String params = "";
if (null != parameters) {
for (final String[] strings : parameters) {
if (strings.length == 2) {
if (params.length() != 0) {
params += "&";
}
params += strings[0] + "=" + strings[1];
} else {
Log.e(Standards.TAG,
"The array 'parameters' has the wrong dimensions("
+ strings.length + ") in " + method + "("
+ parameters.toString() + ")");
}
}
}
url += "?" + params;
if (url.length() >= 1024) { // The URL will be truncated if it is more
// than 1024
return Communications.connectPOST(hostNameOrIP, webService,
classOrEndPoint, method, parameters);
}
final StringBuffer text = new StringBuffer();
HttpURLConnection conn = null;
InputStreamReader in = null;
BufferedReader buff = null;
try {
final URL page = new URL(url);
conn = (HttpURLConnection) page.openConnection();
conn.connect();
in = new InputStreamReader((InputStream) conn.getContent());
buff = new BufferedReader(in);
String line;
while (null != (line = buff.readLine()) && !"null".equals(line)) {
text.append(line + "\n");
}
} catch (final Exception e) {
Log.e(Standards.TAG,
"Exception while getting " + method + " from " + webService
+ "/" + classOrEndPoint + " with parameters: "
+ params + ", exception: " + e.toString()
+ ", cause: " + e.getCause() + ", message: "
+ e.getMessage());
Standards.stackTracePrint(e.getStackTrace(), method);
return null;
} finally {
if (null != buff) {
try {
buff.close();
} catch (final IOException e1) {
}
buff = null;
}
if (null != in) {
try {
in.close();
} catch (final IOException e1) {
}
in = null;
}
if (null != conn) {
conn.disconnect();
conn = null;
}
}
if (text.length() > 0 && Communications.checkText(text.toString())) {
final String temp = Communications.getDataFromXML(text.toString());
Log.i(Standards.TAG, "Success in " + method + "(" + params
+ ") = " + temp);
return temp;
}
Log.w(Standards.TAG, "Warning: " + method + "(" + params + "), text = "
+ text.toString());
return null;
}
let's say this url makes your service shows it's output
http://google.com/wcfsvc/service.svc/showuserdata/11949
public boolean isWSTrue() {
String data = connectGET("google.com",
"wcfsvc", "service.svc",
"showuserdata/11949", null);
if(null != data && data.length() >0)
return data.toLowerCase().contains("true");
throw new Exception("failed to get webservice data");
}
Note: that within this case you do not actually need to parse the JSON or XML if only checking for boolean then you know if you found true it's true if found anything else it's false.
if you need to get data using XML or JSON you can refer to this answer https://stackoverflow.com/a/3812146/435706

Every second HttpsUrlConnection request of my static method fails on Android

I'm having a big issue with a static HTTPS connection method. Every second request fails and HttpsUrlConnection.getResponseCode() returns -1. So every second call works well, returning data as expected.
It's the method of a static class I'm using in different corners of my application. I would guess there is anything I don't clean up correctly when the method returns the first time and that whatever causes a problem might get destroyed through a second call of the method. But I'm having a hard time finding any clues.
I'm currently using this class to talk to hosts with invalid SSL certificates. Not going to use this in the final version of the app, but right now I need to save money. ;)
public static String makeInvalidHTTPSRequest(String url, String[] postVars, String userName, String userPass, Context ctx) throws MalformedURLException, IOException, NoSuchAlgorithmException, KeyManagementException {
StringBuffer sb = new StringBuffer();
String serverAuth = null;
String serverAuthBase64 = null;
StringBuffer urlParameters = new StringBuffer();
InputStream rcvdInputStream = null;
if (checkNetworkAvailability(ctx) == false) {
GeneralMethods.writeLog("Network unavailable", 1, GeneralMethods.class);
return null;
}
SSLContext sc = null;
sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[] { new KTPTrustManager() }, new SecureRandom());
GeneralMethods.writeLog("makeInvalidHTTPSRequest-> " + url + ", " + userName + ", " + userPass, 0, GeneralMethods.class);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new KTPHostnameVerifier());
HttpsURLConnection con = null;
con = (HttpsURLConnection) new URL(url).openConnection();
if (userName != null) {
serverAuth = userName + ":" + userPass;
serverAuthBase64 = KTPBase64.encode(serverAuth.getBytes());
}
try {
String[] tmpPair = null;
con.setRequestMethod("POST");
if (serverAuthBase64 != null)
con.setRequestProperty("Authorization", "Basic " + serverAuthBase64);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
if (postVars != null) {
for (int i = 0; i < postVars.length; i++) {
tmpPair = postVars[i].toString().split("=");
if (i > 0)
urlParameters.append("&" + tmpPair[0] + "=" + URLEncoder.encode(tmpPair[1], "UTF-8"));
else
urlParameters.append(tmpPair[0] + "=" + URLEncoder.encode(tmpPair[1], "UTF-8"));
}
con.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.toString().getBytes().length));
}
con.setUseCaches(false);
con.setDoOutput(true);
con.setDoInput(true);
DataOutputStream wr = new DataOutputStream (con.getOutputStream());
if (postVars != null)
wr.writeBytes (urlParameters.toString());
wr.flush();
wr.close();
if (con.getResponseCode() == 200) {
globalRetries = 0;
rcvdInputStream = con.getInputStream();
}
else if (con.getResponseCode() == 401) {
con.disconnect();
GeneralMethods.writeLog("error 401", 2, GeneralMethods.class);
con = null;
// SEND CONNECTION PROBLEM-INTENT
return null;
}
else {
GeneralMethods.writeLog("error - connection response code " + con.getResponseCode() + ": " + con.getResponseMessage() + " (length: "+ con.getContentLength() +")\n\n", 1, GeneralMethods.class);
con.disconnect();
con = null;
// SEND CONNECTION PROBLEM-INTENT
return null;
}
BufferedReader br = new BufferedReader(new InputStreamReader(rcvdInputStream), 8192 );
String line;
while ( ( line = br.readLine() ) != null ) {
sb.append(line);
}
con.disconnect();
con = null;
}
catch(Exception e) {
handleException(e, 2, GeneralMethods.class);
}
GeneralMethods.writeLog("makeInvalidHTTPSRequest: Response is \"" + sb.toString() + "\"\n\n", 0, GeneralMethods.class);
if(con != null) {
con.disconnect();
con = null;
}
if (sb.toString().trim() == "")
return null;
else
return sb.toString();
}
Thanks a lot for your help!
Best regards
S.
This might be of help: HttpsURLConnection and intermittent connections

Categories

Resources