I have asked variations of this question over the past couple of days. I am not understanding or making the proper connections etc. so I am getting really frustrated not understanding which path I should be on.
I have developed a XAMLX WCF workflow service and my windows clients interact with it just fine. I am new to android and java and thus basically a NOOB. My service uses BasicHttpBinding and expects a couple of string values (uid & pwd) in the request. The response is simply a string.
Now on the android I am totally lost. I have read to use the AsyncTask, I've heard it has major issues and to use RoboSpice. Looking at RoboSpice it looks very solid but very stiff learning curve. I've heard for the stiff learning curve to use LoopJ as it will be easier when starting out. Throw in there the people who want you to use JSON and yeah. I'm definitely lost.
So I have been pulled in a lot of different directions. I know that I need it to be Async so it doesn't lock the ui thread and I would like to get to a solid robust solution but for now a baby step of just interacting with the service even synchronously would be encouraging.
Here are my basics:
Send a request to the service.
Have the application pause/loop etc. A progress bar would be wonderful but a simple loop that doesn't hang would be just fine for now.
RX the response and continue processing.
This is so simple for me in .NET I thought it would be simple. Just goes to show that pride cometh before the fall.
TIA
JB
Direct Question
As has been commented there are several implied questions in my OP. That is because I don't know what to ask. So let's go with AsynchTask for now. Let's call that my baby step.
Here are my questions:
HOW do I associate values to populate the request? In .NET I would create an object that matches what the request expects. So my object would have a UserName property and Password property. I would assign them their values like obj.UserName = "Joe"; I would then call the service operation and pass it obj.
HOW do I ensure I am using the proper libraries? I have read that AsyncTask uses the Apache Http Client library. OK I google that to get the jar's and apparently it's end of life. But still available so I download the latest and put it in my lib folder....but I didn't have to because I can import org.apache.http.HttpResponse without it so which version am I using then and should I use an older one or the latest.
**Finally how do I get the app to pause because this code does something (although it never shows in the logs of my service machine) and while it is off doing something my code continues to execute and crashes when it reaches the point where it needs the data from the service.....but it's not there. A progress bar would be the bees knees.
Here is my code for the implementation:
public class AsyncHttpRequestManager extends AsyncTask<String, Boolean, String>
{
private static final String serviceUrl = "http://www.serviceurl.com/service.xamlx";
#Override
protected String doInBackground(String... params)
{
try
{
DefaultHttpClient client = new DefaultHttpClient();
HttpPut putRequest = new HttpPut(serviceUrl);
putRequest.setHeader("Content-type", "text/plain");
putRequest.setHeader("Accept", "text/plain");
putRequest.setEntity(new StringEntity(params[0])); //This one is connected to my first question. How do I get the proper associations for the operations contract.
HttpResponse response = client.execute(putRequest);
InputStream content = response.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String result = "";
String s = "";
while ((s = buffer.readLine()) != null)
{
result += s;
}
return result;
}
catch (UnsupportedEncodingException e)
{
Log.e("AsyncOperationFailed", e.getMessage());
e.printStackTrace();
} catch (ClientProtocolException e)
{
Log.e("AsyncOperationFailed", e.getMessage());
e.printStackTrace();
} catch (IOException e)
{
Log.e("AsyncOperationFailed", e.getMessage());
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result)
{
Log.d("MESSAGE", result);
}
}
I call this like this:
new AsyncHttpRequestManager().execute("joe","asdf");
If more info is needed I will gladly post.
You should ask one question at a time, it's how SO is designed, and curated, to work.
For HTTP authentication
http://developer.android.com/reference/org/apache/http/auth/UsernamePasswordCredentials.html
E.g.
HttpClient client = new HttpClient();
client.getParams().setAuthenticationPreemptive(true);
Credentials defaultcreds = new UsernamePasswordCredentials("username", "password");
client.getState().setCredentials(new AuthScope("myhost", 80, AuthScope.ANY_REALM), defaultcreds);
Asynctask does not require any external libraries it's part of the Android platform. Don't get confused about HTTPClient and Asynctask. Asyntask is a generic class intended to call background processing on a separate thread from the main UI thread to avoid blocking. It just so happens that you are considering using an Asynctask to process your web request but they are not linked in any way.
Your question about "how to return data to my app" is best posed separately but, in essence, you're thinking sequentially. Your app should not pause. There are many methods, progress dialogs being one, to properly handle this.
Related
I will try to make this a simple as possible (which is more than I can say for the Java HTTP setups I have seen).
I have a decision tree (pseudo) within my Activity:
private void okOnClick(View v){
if(HttpService.isCredentialValid()){
//wait to do something
} else {
//wait to do something else
}
}
Then I have an HttpService:
public class HttpService {
public static boolean isCredentialValid(){
//GET `http://my_server:8080/is-valid?someParam=123`
//the endpoint will return a 200 or 500
}
}
I don't want isCredentialValid to do any actions to the UI, I just want it to tell me, true or false.
I don't want to tightly couple it to a button.setText() or any of that, I just want a simple contract response.code == 200
In nearly every language this is not that difficult. Can someone please set me straight here.
...Sorry for any sounds of hostility. This is one of the most elementary mechanics of nearly every codebase I have ever worked with. And I am only finding Asynchronous patterns that have no way to return something substantial to the method caller. Or I am finding methods that endanger the main thread with no way to catch errors (when there is no connection for instance).
So far I have tried something like below (adjusted the code for simplification). I have allowed this to operate on the main thread, because I do want it to synchronously block. However there is no way to catch on the scenario for bad internet connection or when the remote server does not respond:
public static boolean isCredentialValid(){
String url = "http://my_server:8080?param=123";
StrictMode.ThreadPolicy policy = new
StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
try {
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(1, TimeUnit.SECONDS)
.writeTimeout(1, TimeUnit.SECONDS)
.readTimeout(1, TimeUnit.SECONDS)
.build();
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.code() == 200;
} catch(Exception e){
//
//THIS DOES NOT GET HIT WHEN THERE
//IS A BAD CONNECTION OR REMOTE SERVER FAILS TO RESPOND
//the app just hangs then quits
//
Log.d("ERROR:", e.toString());
return false;
}
}
First, you shouldn't execute your request on the main thread. Also, on Android HTTP requests are meant to be executed asynchronously, it's an extremely bad practice and a code smell if you need to execute them synchronously as a return for a method. The proper way of doing what you are trying to achieve is through the usage of the callback pattern. Your method shouldn't return anything, but invoke a callback which should be received as one of its parameters. If you still have the extreme necessity of doing things synchronously because either you don't know how to handle asynchronous calls or your architecture doesn't allow it, how about using a CountDownLatch? Excuse my Kotlin, but basically it works like this:
val countDownLatch = CountDownLatch(1)
// Execute your request
countDownLatch.countDown()
try {
countDownLatch.await(30, TimeUnit.SECONDS) // Give it a 30 seconds timeout
// return the response code here.
} catch (ex: InterruptedException) {
// Catch the timeout exception
}
Anyway, you should probably re-think about the necessity of actually returning from that method in particular instead of using callbacks, what I proposed isn't exactly the best practice.
PS: This code below is REALLY a bad idea. Basically what you are doing is forcing Android to allow HTTP requests on the main thread, which will completely block the UI of your application.
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
I developed my application using java GWT and I deployed my application on google app engine. my access url is sample.myappid.appspot.com I want to call this url through code so i did like this :-
URL url;
try {
url = new URL("http://sample.myappid.appspot.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
// OK
logger.log(Level.SEVERE,"Done okkkkkk");
} else {
// Server returned HTTP error code.
logger.log(Level.SEVERE,"Erorrrrrrr");
}
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
This is not calling my url. so any other solution how can i call my url using code.
Any help?
You need to pay attention if/when making requests to your app right from inside your apps' request handlers as you can cause infinite recursive loops, making GAE attempt to spawn a new app instance in an attempt to serve each such request. Possibly related to your other question: while user inactivity of 2mins getting info "This request caused a new process to be started for your application".
There are several methods to access your app programatically from itself, internally, basically making requests to paths in your app's serving namespace (like /index.html, for example):
task queues
deferred tasks
cron/scheduled tasks
Requests initiated by these internal methods are internally generated, independent of external requests, and can be safely used to implement your app's logic (loops are still possible if misused, but only creating a great deal of activity, they're not infinite recusions/deadlocking in the sense of forcing GAE to spawn a new instance for every request).
You can also use generic URL access from your app (applicable to any URL, not only those of your app), just as an external user would access your app. These can be useful for automated testing of your app, but note that they can be more costly than the internal access methods, I wouldn't recommend them for actually implementing your app's logic:
using URL Fetch API
using java.net
These external access methods are also subject to infinite recursion problem, so use them with care.
I have an android app and a C# web service
I am hosting my web service on IIS Express - nothing fancy just set up the directories.
My android app go to the web service gets the data and then displays it on the screen and repeats this as fast as it can go.
After a while my android app will throw the following exception:
"SoapFault - faultcode: 'soap:Server' faultstring: 'Server was unable to process request. ---> No ports available in the range 10101 to 11100' faultactor: 'null' detail: org.kxml2.kdom.Node#41bdf340"
I have Googled around a bit and have not found anything that will help me.
I ran CurrPorts to watch the ports and it looks like every time the app calls the web service it is using a different port.
They all use port 80 but different remote ports.
The exception is being thrown on the following line of code
"SoapPrimitive response = (SoapPrimitive) _envelope.getResponse();"
If I run IISReset the app will go back to getting data again until sometime thereafter to get the exception mentioned above.
Here is the code for my web service which is just returning a comma separated string (it will do something more interesting just trying to get this working)
Web service code
[WebMethod]
public string GetDefaultResults()
{
return "100,1,0,125.987,124.993,117.904,116.038";
}
Here is the code that my android app uses to call the web service.
I create a new thread and have it call this method then get the string value split it on ',' then put it in a few different TextViews
public class WebService implements Runnable{
private static String NAMESPACE = "http://tempuri.org/";
private static String URL = "http://mymachine/mywebservice/service.asmx";
private static String SOAP_ACTION = "http://tempuri.org/";
private String _soapAndMethod;
private HttpTransportSE _androidHttpTransport;
private SoapSerializationEnvelope _envelope;
private String _methodName;
public WebService(String methodName) {
_methodName = methodName;
_soapAndMethod = SOAP_ACTION + _methodName;
SoapObject request = new SoapObject(NAMESPACE, methodName);
_envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
_envelope.dotNet = true;
_envelope.setOutputSoapObject(request);
_androidHttpTransport = new HttpTransportSE(URL);
}
#Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
}
public String InvokeWebService() {
String resTxt = null;
try {
_androidHttpTransport.call(_soapAndMethod, _envelope);
SoapPrimitive response = (SoapPrimitive) _envelope.getResponse();
resTxt = response.toString();
} catch (Exception e){
e.printStackTrace();
}
return resTxt;
}
}
Any help would be great. Thank you to those who do respond. Is there some setting in IIS I need to change? Is there something I missed in my code?
Additional information:
When the server is responding the webservice request IIS creates a process called w3wp.exe and it this process that is running out of ports.
Doing in a little digging and experimentation the Webservice gets newed up each call to "GetDefaultResults". Which leaves w3wp.exe in a Listening state and they never go away until the iisreset is run.
Some time later it uses the remaining ports available and starts throwing that exception.
Why is it not reusing the same webservice instead of creating a new one each time.
If that is not possible what code do I write in the Webservice to close the connection after it is finished. I put in a hack to cause it close after 5 seconds to see if that would work at least.
It does clean up w3wp.exe but after a short time I start getting this exception on the client.
"expected: START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope (position:START_TAG #2:7 in java.io.InputStreamReader#41beb098) "
so this is not a work around but it helped me understand what the problem is a little better.
protected override void Dispose(bool disposing)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 5000;
timer.Elapsed += timer_Elapsed;
timer.Start();
base.Dispose(disposing);
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Environment.Exit(1);
}
Thanks for your help.
If you failed your first request, you might need to enable IIS Express to allow external connections. In your case, it looks like it only failed after running for a while.
In your question, I see that you
"go to the web service gets the data and then displays it on the screen and repeats this as fast as it can go.
did not call "close" on HttpTransportSE
You might be running out of local ports. Are you reusing the connection on all your requests? If not, try to close it when you are done.
My Webservice was referencing an api to get the values from then pass them over a webservice to the android app.
The problem was that every time the webservice was being called a new reference would be created to the api and after the request was sent it would never close out the port. As soon as I stopped referencing the api everything worked.
A cludge to get this to work is I had the webservice monitor a folder and send the data in the file that was last created. Then created another program to attach to the api and output the data to that folder. Not the most elegant solution but it works as a proof of concept for what I am doing.
Still not entirely sure why the Webservice was never closing the port and I am suspect that the Webservice could not dispose of the reference to the api but I am not really sure.
I have made a method to make http request using LWUIT IO library and also tried with J2me library. Everything is working fine on simulator but when i tired on two different Nokia phones then i have received exception. Both are showing different exceptions.
Exceptions-
411 length required
java.io.IOException: Error in HTTP operation:Error in HTTP operation
Here is my code-
private void startReq(String url) {
NetworkManager.getInstance().start();
ConnectionRequest myRequest = new ConnectionRequest() {
protected void readResponse(InputStream input) throws IOException {
StringBuffer stringBuffer = new StringBuffer();
int ch;
while ((ch = input.read()) != -1) {
stringBuffer.append((char) ch);
}
System.out.println("Response:"+stringBuffer.toString());
}
};
progress = new Progress("Please Wait ", myRequest,true);
progress.setDisposeOnCompletion(true);
myRequest.setUrl(url);
myRequest.setPost(true);
NetworkManager.getInstance().addToQueue(myRequest);
progress.show();
}
I have found the solution , it was problem related to Mobile Access Point. I could not recognize the problem because internet was working in browser very fine. so i could not guess that the reason can be Access Point. The problem was solved but still i am not satisfied and also surprised that how all applications were able to access internet service instead my Midlet.
Check this link to change access point settings
and if somebody knows the reason of this behavior kindly clear my doubt.
In my app i'm using code like the following to download several images.
Is it High-Performance to do it like that or can I reuse the connection somehow?
for(int i = 0; i < 100; i++){
URL url = new URL("http://www.android.com/image" + i + ".jpg");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally {
urlConnection.disconnect();
}
}
}
You won't really get any benefit from reuse of the HttpURLConnection.
One thing that will greatly benefit your application is if you spend some time looking into Async Tasks, which will allow you to harness the power of multi threaded HTTP requests with callbacks to your main code.
See:
http://www.vogella.com/articles/AndroidPerformance/article.html
for a good example of how Async Tasks can be utilised.
A good starting point though is of course the Android Developers Blog, where they have an example for downloading an image from a server asynchronously, which will match your requirements nicely. With some adaptation you can have your application sending multiple asynchronous requests at once for good performance.
The Google article can be found at:
http://android-developers.blogspot.co.uk/2009/05/painless-threading.html
The key area to look at is:
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
The loadImageFromNetwork method is where the downloading takes place, and will be completely asynchronous away from your main UI thread.
As a basic example, you could modify your application to call this like so:
for(int i = 0; i < 100; i++){
new DownloadImageTask().execute("http://www.android.com/image" + i + ".jpg");
}
Though for an optimisation, I wouldn't throw 100 requests out at once, maybe creating a Threaded queue system which will allow maybe 4 or 5 concurrent connections and then keep the rest coming through when another finishes by maintaining an ArrayList of pending requests to read off.
No matter how you do it, you are going to end up opening multiple connections, one to get each image. This is how any image is received. And there's no way to change the HttpURLConnection anyways. So this could looks fine from that sense.
However, you could attempt to load multiple images at the same time through threading. It would be somewhat complex to implement such a scheme, but entirely possible. It would speed up the process by requesting multiple images at the same time.