Send image as json entry android - android

I have a requirement where, i am sending a json file to the server and the parsing happens at the server side. I have created the entries to the json file, now i want to store an image stored in imageview as an entry to the json file. Searched several previous posts but could not find exactly what to do. Any pointers would be of great help for storing the image in json format for sending through server.

If you want to include Image in a JSON object which you will be sending in a request, convert Image into Base64 string and put this string into the JSON object.
For example:
String encodedImage = Base64.encodeToString(byteArrayImage, Base64.DEFAULT);
Check:
How to convert a image into Base64 string?
Convert png or jpg image to Base64 string in Android

Try base64-encoding the image (like below, where the Uri is your Image - but beware: ImageView has no Getter for the ImageUri, so you have to store it by yourself!):
Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM);
ContentResolver cr = getContentResolver();
InputStream is = cr.openInputStream(uri);
byte[] data = getBytesFromFile(is);
byte[] encoded_data = Base64.encodeBase64(data);
data_string = new String(encoded_data);
Now you have an base64-encoded String data_string that you can send with your JSON request. On the server-side you just have to decode the String and save the picture.

Well, it's kind of experimental, but you can create an array of bytes out of the bitmap, and then create a new string with that array of bytes, and then send it to the server.
However, why don't you just send a POST request to save the image directly, without any experimental processing or parsing?

you have an ImageView
<ImageView
android:layout_width = "300dp"
android:layout_height = "300dp"
android:id = "#+id/Plaatjeid"
android:scaleType = "centerCrop"
android:text = "#string/BerttxtPlaatje"
android:layout_alignParentEnd="true"
/>
and in the codebehind
String plaatje="";
ImageView iv1 = (ImageView)findViewById(R.id.Plaatjeid);
iv1.buildDrawingCache();
Bitmap bitmap = iv1.getDrawingCache();
ByteArrayOutputStream stream=new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
byte[] image=stream.toByteArray();
plaatje = Base64.encodeToString(image, 0);
then you create your Json string
String mailMessage;
mailMessage="<?xml version='1.0'?>";
mailMessage=mailMessage + "<RiscNotification xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'";
mailMessage=mailMessage + "xmlns:xsd='htp://www.w3.org/2001/XMLSchema'>";
mailMessage = mailMessage + " <mail To>" + Mailto() + "</mail To>" ;//server7
mailMessage = mailMessage + "</RiskNotification>";
I have a seperate Class in which I send it
Attach the variables to the Class
GetMethodDemo JsonConnect = new GetMethodDemo();
JsonConnect.MailTo= Mailto();
JsonConnect.Picture=plaatje;
JsonConnect.bertactivity=this;
JsonConnect.execute();//staat in AANHET BEGIN
and my Class
package nl.yentel.finekinney;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.view.Gravity;
import android.widget.Toast;
public class GetMethodDemo extends AsyncTask<String, Void, String> {
String MailTo;
String Picture;
Activity bertactivity;
Bitmap bm;
public void BitMapFoto(Bitmap bitmap) {
bm = bitmap;
}
//#Override
protected String doInBackground(String... strings) {
//http://geekonjava.blogspot.com/2014/03/upload-image-on-server-in-android-using.html
String dBresultaat = "start";
try {
URL url = new URL("http://10.0.2.2:64489/Risico/Risico.asmx/sendMail");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setDoOutput(true);
String jsonInputString = "";
jsonInputString = "{";
jsonInputString = jsonInputString + "\"MailTo\": \"" + MailTo.toString() + "\",";
jsonInputString = jsonInputString + "\"Picture\": \"" + Picture.toString() + "\"";
//if you take the Picture.toString in debug mode and put it in https://base64.guru/converter/decode/image you see the picture
jsonInputString = jsonInputString + "}";
try (OutputStream os = con.getOutputStream()) {
byte[] input = jsonInputString.getBytes("utf-8");
os.write(input, 0, input.length);
int code = con.getResponseCode();
System.out.println(code);
try (BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
System.out.println(response.toString());
return response.toString();
}
} catch (Exception e) {
e.printStackTrace();
return "catch twee";
}
} catch (Exception e) {
e.printStackTrace();
return "catch";
}
}
#Override
protected void onPreExecute() {
}
#Override
protected void onPostExecute(String s) {
// super.onPostExecute(s);
Activity activity = new Bert().activity;
Toast toast = Toast.makeText(bertactivity, s, Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0);
toast.show();
}
}
You should have your webservice in Framework 4.0. Framework 3.5 does not work
and the web.config shows
<configuration>
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="50000000"/>
</webServices>
</scripting>
</system.web.extensions>
<system.web>
My webmethod looks like this
[WebMethod()]
public string sendMail(sstring MailTo, string Picture)
{
string Resultstring = "";
int i;
MailMessage theMessage;
theMessage = new MailMessage();
// look if there is an attempt to hack the server
if ((MailBody.ToUpper()).IndexOf("SELECT") > 0 | (MailBody.ToUpper()).IndexOf("UPDATE") > 0)
{
Resultstring = "illegal string";
}
else
{
theMessage.From = new System.Net.Mail.MailAddress(ConfigurationManager.AppSettings["sender"]); // '"no-reply#taakmonitor.nl")
try
{
theMessage.To.Add(new MailAddress(MailFrom)); // also send a mail to the sender
}
catch (Exception ex)
{
Resultstring = "Mail address "+ MailFrom + " not ok "; //ex.Message; // als het formaat van het mail adres niet goed is
theMessage = null;
}
String FransGetsCopy = WebConfigurationManager.AppSettings["FransGetsCopy"];
String[] ToWhom = NullSafeString(MailTo).Split(',');
for (i = 0; i <= ToWhom.Length - 1; i++)
{
try
{
theMessage.To.Add(new MailAddress(ToWhom[i]));
}
catch (Exception ex)
{
Resultstring = Resultstring + " mail address " + ToWhom[i] + " not ok "; //ex.Message; // als het formaat van het mail adres niet goed is
theMessage = null;
}
}
// there should also be a stylesheet
string StyleText="";
try
{
StyleText = "";
var data = File.ReadAllText(Server.MapPath("~/App_Data/TextFile.txt"));
StyleText = data.ToString();
}
catch (Exception)
{
Resultstring = Resultstring + " No StyleText available. ";
}
theMessage.Subject = MailSubject;
theMessage.IsBodyHtml = true;
//the message is created in HTML with the style in the <head> and the MailBody in the body
theMessage.Body = "<html>" + StyleText + "<body>" + MailBody + "</body></html>";
// code copied from
// https://www.codeproject.com/Tips/569532/Submit-Images-to-Web-Service-and-Get-Them-Back
//in this piece of code I convert the Json picture data to a picture and attach it to the mail
try
{
byte[] data = Convert.FromBase64String(Picture);
var stream = new MemoryStream(data, 0, data.Length);
System.Drawing.Image img = System.Drawing.Image.FromStream(stream);
stream.Seek(0L, SeekOrigin.Begin);
theMessage.Attachments.Add(new Attachment(stream, "Picture.png"));
Resultstring = Resultstring + " image OK";
}
catch (Exception ex)
{
Resultstring = Resultstring + " image not OK";
}
SmtpClient MessageObject = new SmtpClient();
MessageObject.Host = ConfigurationManager.AppSettings["Host"];
MessageObject.Port = Int32.Parse(ConfigurationManager.AppSettings["Port"]);
MessageObject.EnableSsl = false;
MessageObject.Credentials = new System.Net.NetworkCredential(ConfigurationManager.AppSettings["Username"], ConfigurationManager.AppSettings["Password"]);
try
{
MessageObject.Send(theMessage);
Resultstring = Resultstring + " mail has been send.";
}
catch (Exception ex)
{
Resultstring = Resultstring + " mail has NOT been send.";
}
MessageObject = null;
theMessage = null;
}
return Resultstring;
}
at last I have a stylesheet TestFile.txt in the App_data folder attached
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-=1">
<meta content="text/html; charset=us-ascii">
<style>
h1{color:blue;}
.EditText{
background:#ff0000;/*rood*/
height:100;
font-size:10px;
color:#0000ff;/*blauw*/
}
.EditTextVervolg{
background:#00cc00;/*groen*/
font-size:20px;
color:#ffff00;/*geel*/
}
</style>
</head>
Have fun

Related

How to open epub files with Images and contents and when we click on contents then it move to particular part

i want to open ebub files either in webview or by something else but content click and images,videos should be there
-I have tried using webview but images cant display in that
textView.setText(Html.fromHtml(data, new Html.ImageGetter() {
#Override
public Drawable getDrawable(String source) {
String imageAsStr = source.substring(source.indexOf(";base64,") + 8);
byte[] imageAsBytes = Base64.decode(imageAsStr, Base64.DEFAULT);
Bitmap imageAsBitmap = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length);
int imageWidthStartPx = (pxScreenWidth - imageAsBitmap.getWidth()) / 2;
int imageWidthEndPx = pxScreenWidth - imageWidthStartPx;
Drawable imageAsDrawable = new BitmapDrawable(getResources(), imageAsBitmap);
imageAsDrawable.setBounds(imageWidthStartPx, 0, imageWidthEndPx, imageAsBitmap.getHeight());
return imageAsDrawable;
}
}, null));
-i tried this also but in this images are display but content click is no there
Use this code provided you have necessary libraries and sampleepubfile.epub in your assets...
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import nl.siegmann.epublib.domain.Book;
import nl.siegmann.epublib.domain.TOCReference;
import nl.siegmann.epublib.epub.EpubReader;
import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.webkit.WebView;
public class EPubDemo extends Activity {
WebView webview;
String line, line1 = "", finalstr = "";
int i = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webview = (WebView) findViewById(R.id.webview);
AssetManager assetManager = getAssets();
try {
// find InputStream for book
InputStream epubInputStream = assetManager
.open("sampleepubfile.epub");
// Load Book from inputStream
Book book = (new EpubReader()).readEpub(epubInputStream);
// Log the book's authors
Log.i("author", " : " + book.getMetadata().getAuthors());
// Log the book's title
Log.i("title", " : " + book.getTitle());
/* Log the book's coverimage property */
// Bitmap coverImage =
// BitmapFactory.decodeStream(book.getCoverImage()
// .getInputStream());
// Log.i("epublib", "Coverimage is " + coverImage.getWidth() +
// " by "
// + coverImage.getHeight() + " pixels");
// Log the tale of contents
logTableOfContents(book.getTableOfContents().getTocReferences(), 0);
} catch (IOException e) {
Log.e("epublib exception", e.getMessage());
}
String javascrips = "";
try {
// InputStream input = getResources().openRawResource(R.raw.lights);
InputStream input = this.getAssets().open(
"poe-fall-of-the-house-of-usher.epub");
int size;
size = input.available();
byte[] buffer = new byte[size];
input.read(buffer);
input.close();
// byte buffer into a string
javascrips = new String(buffer);
} catch (IOException e) {
e.printStackTrace();
}
// String html = readFile(is);
webview.loadDataWithBaseURL("file:///android_asset/", javascrips,
"application/epub+zip", "UTF-8", null);
}
#SuppressWarnings("unused")
private void logTableOfContents(List<TOCReference> tocReferences, int depth) {
if (tocReferences == null) {
return;
}
for (TOCReference tocReference : tocReferences) {
StringBuilder tocString = new StringBuilder();
for (int i = 0; i < depth; i++) {
tocString.append("\t");
}
tocString.append(tocReference.getTitle());
Log.i("TOC", tocString.toString());
try {
InputStream is = tocReference.getResource().getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(is));
while ((line = r.readLine()) != null) {
// line1 = Html.fromHtml(line).toString();
Log.v("line" + i, Html.fromHtml(line).toString());
// line1 = (tocString.append(Html.fromHtml(line).toString()+
// "\n")).toString();
line1 = line1.concat(Html.fromHtml(line).toString());
}
finalstr = finalstr.concat("\n").concat(line1);
// Log.v("Content " + i, finalstr);
i++;
} catch (IOException e) {
}
logTableOfContents(tocReference.getChildren(), depth + 1);
}
webview.loadDataWithBaseURL("", finalstr, "text/html", "UTF-8", "");
}
}
I have tried this and its working for me

Poor Performance of Android app

I had written a crawler program in C# which used to crawl on a given url or url postfixed with page number and download all the image files from it.It worked fine.
Now I am a newbie in android programming and thought to write the same thing for my android device so that I can also use it on my phone.
The algorithm I followed was...
1) Take the base url,start page no(in case the url is postfixed by page number in query string),end page no,and location to store the images on sdcard.
2) If end page no is less than start page no(means if i only want to crawl a single page) pass it to getHtml method. or else make a loop from start to end page and pass each url to getHtml method.
3) In getHtml method I download web page source and broke it in pieces to find link to image files in it.
4) for each image url found, download the image file to the given save location.
The algo seems easy but when I made the whole program I had some pretty big performance issues. It is so so heavy that while running it in emulator all i could see was gc clearing objects in logcat.Another very common issue is that the UI hangs.But as the program is only for personal use i can do with it because I doesnt know multithreading in android. But atleast the program should be fast. Is there any way I can decrease the number of objects or destroy them myself.
Is there anything I can do to improve this. I wonder how those GBs worth of games works flawlessly and my 20KB app is so so slow.
The whole code is.
package com.dwnldr;
import java.io.*;
import java.net.*;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import android.app.Activity;
import android.os.*;
import android.util.Log;
import android.view.View;
import android.widget.*;
public class IMGDwnldrActivity extends Activity {
EditText res;
String str;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.button1);
File SDCardRoot = Environment.getExternalStorageDirectory();
EditText saveat = (EditText) findViewById(R.id.editText4);
saveat.setText(SDCardRoot.getAbsolutePath());
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
//Getting URL,Start pageno,End pageno and the save location on sdcard
EditText baseurl = (EditText) findViewById(R.id.editText1);
String url = baseurl.getText().toString();
EditText startpage = (EditText) findViewById(R.id.editText2);
int start = Integer.parseInt(startpage.getText().toString());
EditText endpage = (EditText) findViewById(R.id.editText3);
int end = Integer.parseInt(endpage.getText().toString());
EditText saveat = (EditText) findViewById(R.id.editText4);
String save = saveat.getText().toString();
if (start <= end) {
for (int i = start; i <= end; i++) {
str = "\n--------------------";
str += "\nPage No" + String.valueOf(i);
writemsg(str);
getHtml(url + String.valueOf(i), save);
}
} else
getHtml(url, save);
writemsg("Done");
} catch (Exception ee) {
writemsg("\nException fired::" + ee.getMessage());
}
}
});
}
//method to get the source of a particular url
public void getHtml(String url, String save) throws ClientProtocolException, IOException {
try {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet(url);
HttpResponse response = httpClient.execute(httpGet, localContext);
String result = "";
str = "\nDownloading Page....";
writemsg(str);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().
getContent()));
String line = null;
while ((line = reader.readLine()) != null) {
result += line + "\n";
}
str = "\nPage Downloaded...";
writemsg(str);
String[] pieces;
if (result.contains(".jpg") || result.contains(".jpeg")) {
pieces = result.split("\"");
Log.d("Events", String.valueOf(pieces.length));
for (int i = 0; i < pieces.length; i++) {
if (pieces[i].contains(".jpg") || pieces[i].contains(".jpeg")) {
if (pieces[i].contains("http")) {
Log.d("Events", pieces[i]);
downloadme(pieces[i], save);
} else {
URL u = new URL(url);
if (pieces[i].startsWith("."));
pieces[i] = pieces[i].substring(pieces[i].indexOf("/"), pieces[i].length());
writemsg(u.getProtocol() + "://" + u.getHost() + pieces[i]);
if (pieces[i].startsWith("/"))
downloadme(u.getProtocol() + "://" + u.getHost() + pieces[i], save);
else
downloadme(u.getProtocol() + "://" + u.getHost() + "/" + pieces[i], save);
}
}
}
}
} catch (Exception ee) {
writemsg("\nException fired::" + ee.getMessage());
}
}
//download each image url given
private void downloadme(String url1, String save) {
try {
str = "\nDownloading Image " + url1;
writemsg(str);
URL url = new URL(url1);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
File f = new File(save);
if (f.isDirectory() && !f.exists())
f.mkdirs();
String fileName = url1.substring(url1.lastIndexOf('/') + 1, url1.length());
File file = new File(save, fileName);
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
int totalSize = urlConnection.getContentLength();
str = "\nImage Size " + String.valueOf(totalSize / 1024);
writemsg(str);
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
}
fileOutput.close();
str = "\nDownloaded Image " + url1;
writemsg(str);
catch some possible
errors // ...
} catch (MalformedURLException e) {
writemsg("\nException fired::" + e.getMessage());
} catch (IOException e) {
writemsg("\nException fired::" + e.getMessage());
} catch (Exception ee) {
writemsg("\nException fired::" + ee.getMessage());
}
}
//write certain text to the Result textbox
private void writemsg(String msg) {
res = (EditText) findViewById(R.id.result);
String str = res.getText().toString();
str += msg;
res.setText(str);
}
}

Read HTML file from assets

I have an html file in assets, aaa.html.
I want to read the contents of html file and replace it from another string.
Is this way is right or is there any other option.
my code:
File f = new File("file:///android_asset/aaa.html");
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
But its giving file not found, where as loading in web view loads the file.
InputStream is = getAssets().open("aaa.html");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
String str = new String(buffer);
str = str.replace("old string", "new string");
If you want to load file in webview then use this
mWebView.loadUrl("file:///android_asset/myfile.html");
you want to replace content inside Html file tags so the solution class code is here..
public class CardDetail {
public static String newHtmlString = "";
// private Context context;
#SuppressWarnings("rawtypes")
public String getNewHtmlString(String htmlString, HashMap hm) {
try {
StringTokenizer st = new StringTokenizer(htmlString, "##");
CardDetail.newHtmlString = "";
while (st.hasMoreTokens()) {
String token = st.nextToken();
CardDetail.newHtmlString += token;
if (st.hasMoreTokens()) {
String token2 = st.nextToken();
if (token2.equals("NAME") || token2.equals("POSITION") || token2.equals("COMPANY") || token2.equals("PHOTOURL"))
CardDetail.newHtmlString += hm.get(token2);
if (token2.equals("SKYPE_CONTAINER1")
|| token2.equals("TWITTER_CONTAINER1")
|| token2.equals("PHONENUMBER_CONTAINER1")
|| token2.equals("EMAIL_CONTAINER1")
|| token2.equals("ADDRESS_CONTAINER1")) {
String replaceString = st.nextToken();
String tokenMiddle = (String) hm.get(st.nextToken());
if (!tokenMiddle.equals("")) {
replaceString += tokenMiddle;
CardDetail.newHtmlString += replaceString + st.nextToken();
st.nextElement();
} else {
st.nextElement();
st.nextElement();
}
}
}
}
// Log.i("convertedHTMLString", newHtmlString);
return CardDetail.newHtmlString;
// htmlString = "<img src='" + hm.get("PHOTOURL") + "' width=80 height=80>";
// return htmlString;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return null;
}
#SuppressWarnings("unchecked")
public HashMap<?, ?> getProfileHashMap(JSONObject jsonObject) {
#SuppressWarnings("rawtypes")
HashMap hm = new HashMap();
jsonObject = (new JSONConverterClass()).convertJsonObjectToCardDetail(jsonObject);
try {
hm.put("EMAIL", jsonObject.getString("email"));
hm.put("NAME", jsonObject.getString("firstname") + " " + jsonObject.getString("lastname"));
hm.put("COMPANY", jsonObject.getString("company_name"));
hm.put("POSITION", jsonObject.getString("position"));
hm.put("WEBSITE", jsonObject.getString("website"));
hm.put("PHONENUMBER", jsonObject.getString("phonenumber"));
hm.put("PHOTOURL", jsonObject.getString("picture_url"));
hm.put("SKYPE", jsonObject.getString("skype_username"));
hm.put("TWITTER", jsonObject.getString("twitter_username"));
hm.put("ADDRESS", jsonObject.getString("generic_location"));
} catch (Exception e) {
e.printStackTrace();
}
return hm;
}
}
convertJsonObjectToCardDetail this class just replace string with values from Json
hope this solves your problem ....

Android: ProgressBar for HttpURLConnection String data

I am getting JSON data from a web service and would like to display a progress bar while the data is downloading. All the examples I have seen use a StringBuilder like so:
//Set up the initial connection
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setReadTimeout(10000);
connection.connect();
InputStream stream = connection.getInputStream();
//read the result from the server
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder builder = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
builder.append(line + '\n');
}
result = builder.toString();
I got the ProgressBar to work by downloading the data as a byte array, then converting the byte array to a String, but I'm wondering if there is a 'more correct' way to do this. Since I've found no other way of doing this, the following class can also serve as a working example, seems a bit of a hack, but it does work well.
package com.royaldigit.newsreader.services;
import android.os.AsyncTask;
import android.util.Log;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.royaldigit.newsreader.controller.commands.CommandInterface;
import com.royaldigit.newsreader.model.data.SearchResultDO;
import com.royaldigit.newsreader.model.data.SearchTermDO;
/**
* Gets news results from Feedzilla based on the search term currently stored in model.searchTermDO
*
* Sends progress update and returns results to the CommandInterface command reference:
* * command.onProgressUpdate(progress);
* * command.serviceComplete(results);
*
*
*/
public class FeedzillaSearchService {
private static final String TAG = "FeedzillaSearchService";
private static final String SERVICE_URI = "http://api.feedzilla.com/v1/categories/26/articles/search.json?q=";
private static final int STREAM_DIVISIONS = 10;
private CommandInterface command;
private SearchTermDO currentSearchTermDO;
private Integer maximumResults;
private DownloadTask task;
private ArrayList<SearchResultDO> results;
public Boolean isCanceled = false;
public void getData(CommandInterface cmd, SearchTermDO termDO, Integer maxResults){
command = cmd;
currentSearchTermDO = termDO;
//Feedzilla only allows count to be 100 or less, anything over throws an error
maximumResults = (maxResults > 100)? 100 : maxResults;
results = new ArrayList<SearchResultDO>();
task = new DownloadTask();
task.execute();
}
public void cancel() {
isCanceled = true;
if(task != null) task.cancel(true);
}
/**
* Handle GET request
*
*/
private class DownloadTask extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void...voids) {
String result = "";
if(currentSearchTermDO == null || currentSearchTermDO.term.equals("")) return result;
BufferedReader reader = null;
publishProgress(0);
try {
String path = SERVICE_URI + URLEncoder.encode(currentSearchTermDO.term, "UTF-8") + "&count=" + maximumResults;
Log.d(TAG, "path = "+path);
URL url = new URL(path);
//Set up the initial connection
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setReadTimeout(10000);
connection.connect();
int length = connection.getContentLength();
InputStream stream = connection.getInputStream();
byte[] data = new byte[length];
int bufferSize = (int) Math.ceil(length / STREAM_DIVISIONS);
int progress = 0;
for(int i = 1; i < STREAM_DIVISIONS; i++){
int read = stream.read(data, progress, bufferSize);
progress += read;
publishProgress(i);
}
stream.read(data, progress, length - progress);
publishProgress(STREAM_DIVISIONS);
result = new String(data);
} catch (Exception e) {
Log.e(TAG, "Exception "+e.toString());
} finally {
if(reader != null){
try {
reader.close();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
int currentProgress = progress[0] * 100/STREAM_DIVISIONS;
if(!this.isCancelled()) command.onProgressUpdate(currentProgress);
}
#Override
protected void onPostExecute(String result){
if(!this.isCancelled()) downloadTaskComplete(result);
}
}
/**
*
* #param data
*/
private void downloadTaskComplete(Object data){
if(!isCanceled){
try {
Log.d(TAG, data.toString());
JSONObject obj = new JSONObject(data.toString());
JSONArray array = obj.getJSONArray("articles");
for(int i = 0; i < array.length(); i++){
SearchResultDO dataObj = new SearchResultDO();
dataObj.title = array.getJSONObject(i).getString("title");
dataObj.url = array.getJSONObject(i).getString("url");
dataObj.snippet = array.getJSONObject(i).getString("summary");
dataObj.source = array.getJSONObject(i).getString("source");
dataObj.date = array.getJSONObject(i).getString("publish_date");
dataObj.termId = currentSearchTermDO.id;
//Reformat date
SimpleDateFormat format1 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
try {
Date date = format1.parse(dataObj.date);
SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dataObj.date = format2.format(date);
} catch(ParseException pe) {
Log.e(TAG, pe.getMessage());
}
results.add(dataObj);
}
command.serviceComplete(results);
} catch(JSONException e){
Log.e(TAG, e.toString());
command.serviceComplete(results);
}
}
}
}
UPDATE: Here is the finished version of the class using the suggestions from Nikolay. I ended up using the StringBuilder after all. The previous version would break because some times connection.getContentLength() returns -1. This version degrades gracefully for that case. Tested this implementation quite a bit and it seems bulletproof.
package com.royaldigit.newsreader.services;
import android.os.AsyncTask;
import android.util.Log;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.royaldigit.newsreader.controller.commands.CommandInterface;
import com.royaldigit.newsreader.model.data.SearchResultDO;
import com.royaldigit.newsreader.model.data.SearchTermDO;
/**
* Gets news results from Feedzilla based on the search term currently stored in model.searchTermDO
*
* Sends progress update and returns results to the CommandInterface command reference:
* * command.onProgressUpdate(progress);
* * command.serviceComplete(results);
*
*/
public class FeedzillaSearchService implements SearchServiceInterface {
private static final String TAG = "FeedzillaSearchService";
private static final String SERVICE_URI = "http://api.feedzilla.com/v1/categories/26/articles/search.json?q=";
private CommandInterface command;
private SearchTermDO currentSearchTermDO;
private Integer maximumResults;
private DownloadTask task;
private ArrayList<SearchResultDO> results;
private Boolean isCanceled = false;
public void getData(CommandInterface cmd, SearchTermDO termDO, Integer maxResults){
command = cmd;
currentSearchTermDO = termDO;
//Feedzilla only allows count to be 100 or less, anything over throws an error
maximumResults = (maxResults > 100)? 100 : maxResults;
results = new ArrayList<SearchResultDO>();
task = new DownloadTask();
task.execute();
}
public void cancel() {
isCanceled = true;
if(task != null) task.cancel(true);
}
/**
* Handle GET request
*
*/
private class DownloadTask extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void...voids) {
String result = "";
if(currentSearchTermDO == null || currentSearchTermDO.term.equals("")) return result;
BufferedReader reader = null;
publishProgress(0);
try {
String path = SERVICE_URI + URLEncoder.encode(currentSearchTermDO.term, "UTF-8") + "&count=" + maximumResults;
Log.d(TAG, "path = "+path);
URL url = new URL(path);
//Set up the initial connection
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setReadTimeout(20000);
connection.connect();
//connection.getContentType() should return something like "application/json; charset=utf-8"
String[] values = connection.getContentType().toString().split(";");
String charset = "";
for (String value : values) {
value = value.trim();
if (value.toLowerCase().startsWith("charset=")) {
charset = value.substring("charset=".length());
break;
}
}
//Set default value if charset not set
if(charset.equals("")) charset = "utf-8";
int contentLength = connection.getContentLength();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder builder = new StringBuilder();
/**
* connection.getContentLength() can return -1 on some connections.
* If we have the content length calculate progress, else just set progress to 100 and build the string all at once.
*
*/
if(contentLength>-1){
//Odd byte array sizes don't always work, tried 512, 1024, 2048; 1024 is the magic number because it seems to work best.
byte[] data = new byte[1024];
int totalRead = 0;
int bytesRead = 0;
while ((bytesRead = stream.read(data)) > 0) {
try {
builder.append(new String(data, 0, bytesRead, charset));
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Invalid charset: " + e.getMessage());
//Append without charset (uses system's default charset)
builder.append(new String(data, 0, bytesRead));
}
totalRead += bytesRead;
int progress = (int) (totalRead * (100/(double) contentLength));
//Log.d(TAG, "length = " + contentLength + " bytesRead = " + bytesRead + " totalRead = " + totalRead + " progress = " + progress);
publishProgress(progress);
}
} else {
String line = "";
while ((line = reader.readLine()) != null) {
builder.append(line + '\n');
publishProgress(100);
}
}
result = builder.toString();
} catch (Exception e) {
Log.e(TAG, "Exception "+e.toString());
} finally {
if(reader != null){
try {
reader.close();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
if(!this.isCancelled()) command.onProgressUpdate(progress[0]);
}
#Override
protected void onPostExecute(String result){
if(!this.isCancelled()) downloadTaskComplete(result);
}
}
/**
*
* #param data
*/
private void downloadTaskComplete(Object data){
if(!isCanceled){
try {
Log.d(TAG, data.toString());
JSONObject obj = new JSONObject(data.toString());
JSONArray array = obj.getJSONArray("articles");
for(int i = 0; i < array.length(); i++){
SearchResultDO dataObj = new SearchResultDO();
dataObj.title = array.getJSONObject(i).getString("title");
dataObj.url = array.getJSONObject(i).getString("url");
dataObj.snippet = array.getJSONObject(i).getString("summary");
dataObj.source = array.getJSONObject(i).getString("source");
dataObj.date = array.getJSONObject(i).getString("publish_date");
dataObj.termId = currentSearchTermDO.id;
//Reformat date
SimpleDateFormat format1 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
try {
Date date = format1.parse(dataObj.date);
SimpleDateFormat format2 = new SimpleDateFormat(SearchResultDO.DATE_FORMAT_STRING);
dataObj.date = format2.format(date);
} catch(ParseException pe) {
Log.e(TAG, pe.getMessage());
}
results.add(dataObj);
}
} catch(JSONException e){
Log.e(TAG, e.toString());
}
command.serviceComplete(results);
}
}
}
Well, since content length is reported in bytes, there is really no other way. If you want to use a StringReader you could take the length of each line you read and calculate the total bytes read to achieve the same thing. Also, the regular idiom is to check the return value of read() to check if you have reached the end of the stream. If, for some reason, the content length is wrong, your code may read more/less data then available. Finally, when converting a byte blob to a string, you should explicitly specify the encoding. When dealing with HTTP, you can get that from the 'charset' parameter of the 'Content-Type' header.
I had similar problem. I tried the solution of Jeremy C, but it was inaccurate, because value of "Content-Length" from header can be very different than real data.
My solution is:
Send HTTP header from server (PHP):
$string = json_encode($data, JSON_PRETTY_PRINT | JSON_FORCE_OBJECT);
header("X-Size: ".strlen($string)); //for example with name: "X-Size"
print($string);
Read correct value "X-size" for contentLength variable from HTTP header before read from stream:
protected String doInBackground(URL... urls) {
if (General.DEBUG) Log.i(TAG, "WebAsyncTask(doInBackground)");
String result = "";
BufferedReader reader = null;
try {
HttpURLConnection conn = (HttpURLConnection) urls[0].openConnection();
conn.setConnectTimeout(General.TIMEOUT_CONNECTION);
conn.setReadTimeout(General.TIMEOUT_SOCKET);
conn.setRequestMethod("GET");
conn.connect();
if (General.DEBUG) Log.i(TAG, "X-Size: "+conn.getHeaderField("X-Size"));
if (General.DEBUG) Log.i(TAG, "getHeaderField: "+conn.getHeaderFields());
if(conn.getResponseCode() != General.HTTP_STATUS_200)
return General.ERR_HTTP;
int contentLength = -1;
try {
contentLength = Integer.parseInt(conn.getHeaderField("X-Size"));
} catch (Exception e){
e.printStackTrace();
}
InputStream stream = conn.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder builder = new StringBuilder();
//Pokud delku zname:
if(contentLength > -1){
byte[] data = new byte[16]; //TODO
int totalRead = 0;
int bytesRead = 0;
while ((bytesRead = stream.read(data)) > 0){
Thread.sleep(100); //DEBUG TODO
try {
builder.append(new String(data, 0, bytesRead, "UTF-8"));
} catch (UnsupportedEncodingException e) {
Log.i(TAG, "Invalid charset: " + e.getMessage());
//Append without charset (uses system's default charset)
builder.append(new String(data, 0, bytesRead));
}
totalRead += bytesRead;
int progress = (int) (totalRead * (100/(double) contentLength));
Log.i(TAG, "length = " + contentLength + " bytesRead = " + bytesRead + " totalRead = " + totalRead + " progress = " + progress);
publishProgress(progress);
}
} else {
String line = "";
while ((line = reader.readLine()) != null) {
builder.append(line + '\n');
publishProgress(100);
}
}
result = builder.toString();
} catch (SocketException | SocketTimeoutException e){
if (General.DEBUG) Log.i(TAG, "SocketException or SocketTimeoutException");
e.printStackTrace();
return General.HTTP_TIMEOUT;
} catch (Exception e){
e.printStackTrace();
return General.ERR_HTTP;
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}

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

Categories

Resources