I know Java but unfortunately chosen Basic4Android for Android Development. After working over an year I realized I should move in native solution. So my question might be silly but I need your advice to solve it.
My goal is to retrieve data from a GET request. I've tried tons of android http client tutorials over internet but failed with each tutorial. I'm just going to share one here so that you can help me to fix. When I'm clicking on the button, nothing is happening without tons of error message in logcat window.
Main Class is here for a quick review:
public class MainActivity extends Activity implements OnClickListener {
private Button Test;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Test = (Button) findViewById(R.id.Test);
Test.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.Test){
try {
HttpClient client = new DefaultHttpClient();
String getURL = "http://www.google.com";
HttpGet get = new HttpGet(getURL);
HttpResponse responseGet = client.execute(get);
HttpEntity resEntityGet = responseGet.getEntity();
if (resEntityGet != null) {
// do something with the response
String response = EntityUtils.toString(resEntityGet);
Log.i("GET RESPONSE", response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
And the whole project is here: https://dl.dropboxusercontent.com/u/15625012/TestHttp.zip
I'll really appreciate any sort of help/advice.
you are currently doing a network access in your main UI thread (Button click function). Android does not allow long operations such as network access in the main thread UI thread of the app. You need to do this asynchronously in a separate thread. You can use built in Async Class for this purpose.
Here is a sample code i wrote
public class Sample extends Activity
{
private ProgressDialog progress_dialog;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
progress_dialog = new ProgressDialog(this);
}
public void MyButtonClick(View view)
{
EditText usernameEditText = (EditText)findViewById(R.id.sample_username);
String username = usernameEditText.getText();
String URL = "http://SOME_WEBSITE?Username=" + username;
progress_dialog.setMessage("Loading. Please wait...");
progress_dialog.setCancelable(false);
progress_dialog.show();
new SampleAsynThread().execute(URL);
}
private class SampleAsynThreadextends AsyncTask <String, Void, String>
{
protected String doInBackground(String... urls)
{
// make your request here
return "Response";
}
protected void onPostExecute(String result)
{
// show response on ui
progress_dialog.dismiss();
}
}
protected void onDestroy()
{
progress_dialog.dismiss();
super.onDestroy();
}
#Override
protected void onPause()
{
progress_dialog.dismiss();
super.onPause();
}
}
First- always post the errors in logcat here, we almost always need them to fix the problem.
But here it's easy- you can't do network IO on the main thread. You need to run it on an AsyncTask or a Thread instead.
try {
URL url = new URL(urlstr);
HttpsURLConnection connection =
(HttpsURLConnection)url.openConnection();
connection.setReadTimeout(6000);
connection.setRequestMethod("GET");
connection.setRequestProperty("User_agent", "android");
OutputStream os = connection.getOutputStream();
//os.write(buffer);
InputStream is = connection.getInputStream();
} catch (MalformedURLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}catch (Exception e) {
// TODO: handle exception
}
Related
Very new at Android development. Trying to call a webservice in Android Studio and getting this: java.net.SocketTimeoutException: SSL handshake timed out. I dont see traffic with wireshark and am not sure at what point its failing. Does not seem to leave the emulator.
EDIT: The webservice contains three methods, for lack of better term. I am not sure how to call the proper method in android. In powershell I call like this:
Powershell:
$myname = New-WebServiceProxy -Uri $URI -Namespace myname-class ssl
$myname.webservicemethod($qualifications,0,30)
Android:
public class MainActivity extends AppCompatActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button2);
final TextView textview = findViewById(R.id.textView);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
AsyncTask asyncTask = new AsyncTask()
{
#Override
protected Object doInBackground(Object[] objects)
{
OkHttpClient client = new OkHttpClient();
HttpUrl.Builder urlBuilder = HttpUrl.parse("https://ip of webservice/pathvalue/WSDL/public/hostname/name").newBuilder();
urlBuilder.addQueryParameter("username", "someuser");
urlBuilder.addQueryParameter("password", "somepass");
urlBuilder.addQueryParameter("qualification", "Assigned Group=Admin Group");
String url = urlBuilder.build().toString();
Request request = new Request.Builder().url(url).build();
Response response = null;
try
{
response = client.newCall(request).execute();
return response.body().string();
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Object o)
{
textview.setText(o.toString());
}
}.execute();
}
});
}
}
I suspect preventing SocketTimeoutException is beyond our limit. One way to effectively handle it is to define a connection timeout and later handle it by using a try catch block. Hope this will helps
HttpUrlConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(7000); //set the timeout in milliseconds
The Problem
I have an AsyncTask task called from an Activity's OnCreate method. This task makes an http request. The HTTP request hangs. Once the "CODE HANGS HERE" code in the code below is executed, I observe in the debugger that the Async threads are perpetually 'running' and never return anything.
The Code
Here's the OnCreate method of the activity:
protected void onCreate(Bundle savedInstanceState) {
asyncRequest.delegate = this;
super.onCreate(savedInstanceState);
setContentView(R.layout.activty_attach);
Button retakeButton = (Button) (findViewById(R.id.retake_button));
retakeButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(AttachActivity.this, MainActivity.class);
startActivity(intent);
}
});
try {
URL url;
url = new URL("http://btl-cromwell:9000/api/engine/v1/version");
asyncRequest.execute(url);
} catch (Exception e) {
Log.e(logtag, e.toString());
}
}
Note the URL that is passed to he async task should just return JSON containing the version number of the service receiving the request.
The async task (asyncRequest) code is below:
public class AsyncRequest extends AsyncTask<URL, Void, List<String>> {
private String logtag = "AsyncRequestTask";
public AsyncResponse delegate;
List<String> projects = new ArrayList<String>();
#Override
protected void onPreExecute(){
super.onPreExecute();
}
#Override
protected List<String> doInBackground(URL... urls) {
try {
// Creating & connection Connection with url and required Header.
HttpURLConnection urlConnection = (HttpURLConnection) urls[0].openConnection();
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestMethod("GET"); //POST or GET
urlConnection.setRequestProperty("User-Agent", "Test");
// CODE HANGS HERE
int responseCode = urlConnection.getResponseCode();
String responseMessage = urlConnection.getResponseMessage();
projects.add(responseMessage);
} catch (Exception e) {
Log.e(logtag, e.toString());
}
return projects;
}
#Override
protected void onPostExecute(List<String> result){
delegate.processFinish(result);
}
}
Once I have the request working I will populate the projects variable with what I actually want to return but for now I just have it set to responseMessage. I'm sure this is just something to do with my unfamiliarity in making requests in Java, but I have spent days on this and can't figure it out. Any help is greatly appreciated.
asyncRequest.execute(url);
asyncRequest.getStatus();
String[] projects = asyncRequest.get();
It is not possible to do both an .execute and a .get().
As you should never use .get(), you better remove that statement.
Remove all code after asyncRequest.execute(url); and put that code in the onPostExecute of your AsyncTask.
I want to make a simple HTTP Head Request to URL which is fetched from a text box. Everytime I enter the URL and Click to get the HTTP response, the App Become Irrespnosive. Here is the code :
public void MakeRequest(View v)
{
EditText mEdit;
TextView txtresponse;
txtresponse = (TextView)findViewById(R.id.textView1);
mEdit = (EditText)findViewById(R.id.editText1);
HttpClient httpClient = new DefaultHttpClient();
HttpHead httphead = new HttpHead(mEdit.getText().toString());
try {
HttpResponse response = httpClient.execute(httphead);
txtresponse.setText(response.toString());
} catch (ClientProtocolException e) {
// writing exception to log
e.printStackTrace();
} catch (IOException e) {
// writing exception to log
e.printStackTrace();
}
}
Never perform long running tasks on the UI Thread (and HTTP Request / Response can take very long due to server latency).
Run the HTTP handling in a background thread.
There are several examples on Stackoverflow - like Make an HTTP request with android and of course read up on Android site - http://developer.android.com/training/articles/perf-anr.html
You are probably doing the request in the UI thread. This is bad practice, as it is in charge of all work done for the UI. You can read more about this here.
A better way would be to do this in another thread. This can be done with e.g.
a custom worker thread or
an AsyncTask.
Example with an AsyncTask (this goes inside your class):
public void MakeRequest(View v)
{
EditText mEdit;
mEdit = (EditText)findViewById(R.id.editText1);
new RequestTask().execute(mEdit.getText().toString());
}
private class RequestTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
HttpClient httpClient = new DefaultHttpClient();
HttpHead httphead = new HttpHead(params[0]);
try {
HttpResponse response = httpClient.execute(httphead);
return response.toString();
} catch (ClientProtocolException e) {
// writing exception to log
e.printStackTrace();
} catch (IOException e) {
// writing exception to log
e.printStackTrace();
}
return "";
}
#Override
protected void onPostExecute(String result) {
TextView txtresponse;
txtresponse = (TextView)findViewById(R.id.textView1);
txtresponse.setText(result);
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
I am new to android development. I have a AsyncTask function in my application. Calling http request from all activities. Now in each activity I am using the following class to connect to server, in some activities I even called twice !!.
Basically I am a web developer and in such cases we use a single class which can be accessed from entire application(web) and use the common function to do the same activity. The only difference is input and out put will be changed.
My doubt is in this case can I use ( convert) this to such a function or class ?
My assume is
Create an android class ( which can be accessed from all the activities )
Just make the JSON string we need with specific server ( for process in server )
Just pass the created json to the created class and then made the http connect )
Process the returned data from server
Pass that to the corresponding activity
So that I can use the same function for all the activities and I can avoid duplicate query
Can I convert this code to such a manner ?
My Code
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_main);
LogIN loginUser = new LogIN();
LoginUser.execute("");
}
private class LogIN extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... sUrl) {
try {
String path = "http://www.domain_name.com/app/checkSession.php";
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
HttpResponse response;
JSONObject json = new JSONObject();
try {
HttpPost post = new HttpPost(path);
json.put("access_token", "123456");
post.setHeader("json", json.toString());
StringEntity se = new StringEntity(json.toString());
se.setContentEncoding((Header) new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
/* Checking response */
if (response != null) {
InputStream in = response.getEntity().getContent();
String a = convertStreamToString(in);
JSONObject jsono = stringToJsonobj(a);
String passedStringValue = jsono.getString("result");
if(passedStringValue.equals("1")){
flags=1;
//Log.v("TAGG", "Success");
}
else {
flags=0;
//Log.v("TAGG", "Failed !");
}
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialogue("Login Processing", "Loading");
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
}
#Override
protected void onPostExecute(String result) {
if(flags.equals(1)){
Itent homepage = new Intent(MainActivity.this, RegisterDevice.class);
startActivity(homepage);
finish();
}
else {
Intent homepage = new Intent(MainActivity.this, LoginActivity.class);
startActivity(homepage);
finish();
}
super.onPostExecute(result);
}
}
}
Please any one help/advise
Thanks in advance
Extract your class to a different file and make it public
public class LogIN extends AsyncTask<Object, Integer, String> {
private ILoginListener listener;
#Override
protected String doInBackground(Object... arg0) {
try {
this.listener = (ILoginListener) arg0[0];
//You can also send the url in the obj array
String theUrl = (String) arg0[1];
String path = "http://www.domain_name.com/app/checkSession.php";
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
HttpResponse response;
JSONObject json = new JSONObject();
try {
HttpPost post = new HttpPost(path);
json.put("access_token", "123456");
post.setHeader("json", json.toString());
StringEntity se = new StringEntity(json.toString());
se.setContentEncoding((Header) new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
/* Checking response */
if (response != null) {
InputStream in = response.getEntity().getContent();
String a = convertStreamToString(in);
JSONObject jsono = stringToJsonobj(a);
String passedStringValue = jsono.getString("result");
if(passedStringValue.equals("1")){
flags=1;
//Log.v("TAGG", "Success");
}
else {
flags=0;
//Log.v("TAGG", "Failed !");
}
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialogue("Login Processing", "Loading");
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
}
#Override
protected void onPostExecute(String result) {
listener.logInSessionCheckListener(flag.equals(1));
super.onPostExecute(result);
}
}
Regarding your other question, I normally have an interface for that, something like this:
public interface ILoginListener {
public void logInSessionCheckListener(SomeNeeded Value);
}
I implement the interface in the class where i need the postExecute result and in the overriden method you can to what you want with the result of your task.
Your class where you user it will look something like this:
public class SomeClass implements ILoginListener {
//Call it like this from any class:
LogIN loginTask = new LogIn();
Object[] someParams = new Object[2];
//add the listener
someParams[0] = SomeClass.this
//add the url
someParams[1] = someUrlString;
loginTask.execute(someParams);
#Override
public void logInSessionCheckListener(SomeNeeded Value){
//do Stuff with your results
}
}
You can do it like make separate class for everything inside doInBackground() method and called it in all activity with passing parameter to
LogIN loginUser = new LogIN(yourparameter);
LoginUser.execute("");
and check parameter in AsyncTask Class constructor like
public LogIN(Myparameter){
// Your data
}
On the other hand you can use this great framework for android : android-query and the async API.
It allows you to perform asynchroneous network tasks from activities and easily work with the results of your requests.
You should use interfaces to implement a callback to your ui activity.
Have a look at this thread, it might be useful:
android asynctask sending callbacks to ui
And your asyntask class should be in a seperate java file with public acces.
And to pass the parametres you simply have to call a new LogIN async Task like this:
new LogIN().execute(urls);
Hope it helped :)
Remember that you can never know when AsyncTask is going to finish. So if you're using this to authenticate users and then perform task X, task Y, or task Z,
then maybe it's better to create a Login helper class
public class LoginHelper {
public boolean login(params){
// Authenticate user and return true if successfull
}
}
and then have in your Activity classes
private class X extends AsyncTask {
#Override
protected String doInBackground(String... sUrl) {
...
boolean authenticated = LoginHelper.login(params...);
if(authenticated == true) {
// Perform task X here...
} else {
// Inform the user that the login failed...
}
}
First of all
You have to pass the context in which you are calling your async task
Sample Code
Login loginTask = new Long(getContext());
loginTask.execute();
You class Login should have a constructor that accepts the Context
Sample Code
public class Login extends AsyncTask<String, Integer, String> {
private Context mContext ;
private ProgressDialog pd;
private Handler handler = new Handler { };
public Login (Context context){
mContext = context ;
}
.....
Then make sure to create the method showDialog inside Login class to show the progress dialog
Note
You can add what ever Constructors you need to customize the behaviour of your Login task
for example : pass boolean parameter to tell that the Login Task is cancelable....
Hope that help you :)
I am getting the exception android.os.NetworkOnMainThreadException when I tried to use the following codes:
public class CheckServer extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Runnable runn = null;
HttpTask.execute(runn);
}
private class HttpTask extends AsyncTask<String, String, String>
{
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
HttpURLConnection urlConnection = null;
URL theURL = null;
try {
theURL = new URL("http://192.168.2.8/parkme/Client/clientquery.php?ticket=66t");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
urlConnection = (HttpURLConnection) theURL.openConnection();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String response = null;
try {
response = readInputStream(urlConnection.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return response;
}
private String readInputStream(InputStream is) {
// TODO Auto-generated method stub
String line = "";
StringBuilder total = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((line = rd.readLine()) != null) {
total.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
return total.toString();
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();
}
}}
If possible can someone tell me how to use it inside an Async Task and get the output? I tried but can't seem to get anywhere.
NetworkOnMainThread Exception occurs because you are running a network related operation on the main UI Thread.This is only thrown for applications targeting the Honeycomb SDK or higher
You should be using asynctask.
http://developer.android.com/reference/android/os/AsyncTask.html
In onCreate()
new TheTask().execute();
You can also pass parameters like url to the constructor of AsyncTask and use the same in doInBackground()
class TheTask extends AsyncTask<Void,Void,Void>
{
protected void onPreExecute()
{ super.onPreExecute();
//display progressdialog.
}
protected void doInBackground(Void ...params)//return result here
{
//http request. do not update ui here
return null;
}
protected void onPostExecute(Void result)//result of doInBackground is passed a parameter
{
super.onPostExecute(result);
//dismiss progressdialog.
//update ui using the result returned form doInbackground()
}
}
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
Ok, lets do it step by step ...
1) create private class extending AsyncTask
private class HttpUrlConnectionTask extends AsyncTask {
2) Override the doInBackground() method, this will do the heavy load
#Override
protected Object doInBackground(Object... params) {
// your HttpUrlConnection code goes here
return response;
3) Once the job is done and returns, the onPostExecute() method will be called. The result parameter contains the return value of doInBackground() - so response.
#Override
protected void onPostExecute(Object result) {
Within this method you can update your UI.
4) Finally lets have a look onto the HttpUrlConnection code
HttpURLConnection urlConnection = null;
URL theURL = new URL(url);
urlConnection = (HttpURLConnection) theURL.openConnection();
String response = readInputStream(urlConnection.getInputStream());
return response;
Hope this helps. Happy coding!
#Raghunandan comes with a really good explanation of how AsyncTask works
Here you go:
public static class InitializeTask extends MyAsyncTask<String, String, String> {
private Activity activity;
private ProgressDialog dialog;
public InitializeTask(Activity activity) {
this.activity = activity;
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(activity, result, Toast.LENGTH_SHORT).show();
}
#Override
protected String doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://192.168.2.8/localhost/parkme/Client/clientquery.php?ticket=");
try {
HttpResponse response = httpclient.execute(httpget);
if(response != null) {
String line = "";
InputStream inputstream = response.getEntity().getContent();
return convertStreamToString(inputstream);
} else {
return "Unable to complete your request";
}
} catch (ClientProtocolException e) {
return "Caught ClientProtocolException";
} catch (IOException e) {
return "Caught IOException";
}
}
private String convertStreamToString(InputStream is) {
String line = "";
StringBuilder total = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((line = rd.readLine()) != null) {
total.append(line);
}
} catch (Exception e) {
return "Stream Exception";
}
return total.toString();
}
}
A little side note, it is generally considered bad code to catch just Exception, since this will catch anything, and you are not accounting for what it is.
To use the AsyncTask in the Activity do this:
InitializeTask task = new InitializeTask(this)
task.execute()
Exactly as it says, network activity isn't allowed on the thread the activity ran in. Moving your code to an Asynctask is the way to do it properly. Though if you're just trying to get your concept working still you can do this...
//lazy workaround with newer than gingerbread
//normally UI thread can't get Internet.
if(Build.VERSION.SDK_INT >= 9){
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
And then the UI thread actually can. I wouldn't release anything like this however, I haven't even tried infact. It's just my lazy debugging move I use a lot.